hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/net/ipv4/tcp_diag.c
....@@ -1,12 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * tcp_diag.c Module for monitoring TCP transport protocols sockets.
34 *
45 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
5
- *
6
- * This program is free software; you can redistribute it and/or
7
- * modify it under the terms of the GNU General Public License
8
- * as published by the Free Software Foundation; either version
9
- * 2 of the License, or (at your option) any later version.
106 */
117
128 #include <linux/module.h>
....@@ -25,8 +21,8 @@
2521 struct tcp_info *info = _info;
2622
2723 if (inet_sk_state_load(sk) == TCP_LISTEN) {
28
- r->idiag_rqueue = sk->sk_ack_backlog;
29
- r->idiag_wqueue = sk->sk_max_ack_backlog;
24
+ r->idiag_rqueue = READ_ONCE(sk->sk_ack_backlog);
25
+ r->idiag_wqueue = READ_ONCE(sk->sk_max_ack_backlog);
3026 } else if (sk->sk_type == SOCK_STREAM) {
3127 const struct tcp_sock *tp = tcp_sk(sk);
3228
....@@ -86,13 +82,42 @@
8682 }
8783 #endif
8884
85
+static int tcp_diag_put_ulp(struct sk_buff *skb, struct sock *sk,
86
+ const struct tcp_ulp_ops *ulp_ops)
87
+{
88
+ struct nlattr *nest;
89
+ int err;
90
+
91
+ nest = nla_nest_start_noflag(skb, INET_DIAG_ULP_INFO);
92
+ if (!nest)
93
+ return -EMSGSIZE;
94
+
95
+ err = nla_put_string(skb, INET_ULP_INFO_NAME, ulp_ops->name);
96
+ if (err)
97
+ goto nla_failure;
98
+
99
+ if (ulp_ops->get_info)
100
+ err = ulp_ops->get_info(sk, skb);
101
+ if (err)
102
+ goto nla_failure;
103
+
104
+ nla_nest_end(skb, nest);
105
+ return 0;
106
+
107
+nla_failure:
108
+ nla_nest_cancel(skb, nest);
109
+ return err;
110
+}
111
+
89112 static int tcp_diag_get_aux(struct sock *sk, bool net_admin,
90113 struct sk_buff *skb)
91114 {
115
+ struct inet_connection_sock *icsk = inet_csk(sk);
116
+ int err = 0;
117
+
92118 #ifdef CONFIG_TCP_MD5SIG
93119 if (net_admin) {
94120 struct tcp_md5sig_info *md5sig;
95
- int err = 0;
96121
97122 rcu_read_lock();
98123 md5sig = rcu_dereference(tcp_sk(sk)->md5sig_info);
....@@ -104,11 +129,21 @@
104129 }
105130 #endif
106131
132
+ if (net_admin) {
133
+ const struct tcp_ulp_ops *ulp_ops;
134
+
135
+ ulp_ops = icsk->icsk_ulp_ops;
136
+ if (ulp_ops)
137
+ err = tcp_diag_put_ulp(skb, sk, ulp_ops);
138
+ if (err)
139
+ return err;
140
+ }
107141 return 0;
108142 }
109143
110144 static size_t tcp_diag_get_aux_size(struct sock *sk, bool net_admin)
111145 {
146
+ struct inet_connection_sock *icsk = inet_csk(sk);
112147 size_t size = 0;
113148
114149 #ifdef CONFIG_TCP_MD5SIG
....@@ -129,19 +164,30 @@
129164 }
130165 #endif
131166
167
+ if (net_admin && sk_fullsock(sk)) {
168
+ const struct tcp_ulp_ops *ulp_ops;
169
+
170
+ ulp_ops = icsk->icsk_ulp_ops;
171
+ if (ulp_ops) {
172
+ size += nla_total_size(0) +
173
+ nla_total_size(TCP_ULP_NAME_MAX);
174
+ if (ulp_ops->get_info_size)
175
+ size += ulp_ops->get_info_size(sk);
176
+ }
177
+ }
132178 return size;
133179 }
134180
135181 static void tcp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
136
- const struct inet_diag_req_v2 *r, struct nlattr *bc)
182
+ const struct inet_diag_req_v2 *r)
137183 {
138
- inet_diag_dump_icsk(&tcp_hashinfo, skb, cb, r, bc);
184
+ inet_diag_dump_icsk(&tcp_hashinfo, skb, cb, r);
139185 }
140186
141
-static int tcp_diag_dump_one(struct sk_buff *in_skb, const struct nlmsghdr *nlh,
187
+static int tcp_diag_dump_one(struct netlink_callback *cb,
142188 const struct inet_diag_req_v2 *req)
143189 {
144
- return inet_diag_dump_one_icsk(&tcp_hashinfo, in_skb, nlh, req);
190
+ return inet_diag_dump_one_icsk(&tcp_hashinfo, cb, req);
145191 }
146192
147193 #ifdef CONFIG_INET_DIAG_DESTROY