Blame view
net/ipv4/tcp_diag.c
5.45 KB
2874c5fd2 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
17b085eac [INET_DIAG]: Move... |
2 3 4 |
/* * tcp_diag.c Module for monitoring TCP transport protocols sockets. * |
17b085eac [INET_DIAG]: Move... |
5 |
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
17b085eac [INET_DIAG]: Move... |
6 |
*/ |
17b085eac [INET_DIAG]: Move... |
7 |
#include <linux/module.h> |
c1e64e298 net: diag: Suppor... |
8 9 |
#include <linux/net.h> #include <linux/sock_diag.h> |
17b085eac [INET_DIAG]: Move... |
10 11 12 |
#include <linux/inet_diag.h> #include <linux/tcp.h> |
c03fa9bca tcp_diag: report ... |
13 |
#include <net/netlink.h> |
17b085eac [INET_DIAG]: Move... |
14 15 16 17 18 |
#include <net/tcp.h> static void tcp_diag_get_info(struct sock *sk, struct inet_diag_msg *r, void *_info) { |
17b085eac [INET_DIAG]: Move... |
19 |
struct tcp_info *info = _info; |
986ffdfd0 net: sock: replac... |
20 |
if (inet_sk_state_load(sk) == TCP_LISTEN) { |
288efe860 net: annotate loc... |
21 |
r->idiag_rqueue = READ_ONCE(sk->sk_ack_backlog); |
099ecf59f net: annotate loc... |
22 |
r->idiag_wqueue = READ_ONCE(sk->sk_max_ack_backlog); |
35ac838a9 sock_diag: implem... |
23 24 |
} else if (sk->sk_type == SOCK_STREAM) { const struct tcp_sock *tp = tcp_sk(sk); |
7db48e983 tcp: annotate tp-... |
25 26 |
r->idiag_rqueue = max_t(int, READ_ONCE(tp->rcv_nxt) - READ_ONCE(tp->copied_seq), 0); |
0f3174645 tcp: annotate tp-... |
27 |
r->idiag_wqueue = READ_ONCE(tp->write_seq) - tp->snd_una; |
5ee3afba8 [TCP]: Return use... |
28 |
} |
00db41243 ipv4: coding styl... |
29 |
if (info) |
17b085eac [INET_DIAG]: Move... |
30 31 |
tcp_get_info(sk, info); } |
c03fa9bca tcp_diag: report ... |
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
#ifdef CONFIG_TCP_MD5SIG static void tcp_diag_md5sig_fill(struct tcp_diag_md5sig *info, const struct tcp_md5sig_key *key) { info->tcpm_family = key->family; info->tcpm_prefixlen = key->prefixlen; info->tcpm_keylen = key->keylen; memcpy(info->tcpm_key, key->key, key->keylen); if (key->family == AF_INET) info->tcpm_addr[0] = key->addr.a4.s_addr; #if IS_ENABLED(CONFIG_IPV6) else if (key->family == AF_INET6) memcpy(&info->tcpm_addr, &key->addr.a6, sizeof(info->tcpm_addr)); #endif } static int tcp_diag_put_md5sig(struct sk_buff *skb, const struct tcp_md5sig_info *md5sig) { const struct tcp_md5sig_key *key; struct tcp_diag_md5sig *info; struct nlattr *attr; int md5sig_count = 0; hlist_for_each_entry_rcu(key, &md5sig->head, node) md5sig_count++; if (md5sig_count == 0) return 0; attr = nla_reserve(skb, INET_DIAG_MD5SIG, md5sig_count * sizeof(struct tcp_diag_md5sig)); if (!attr) return -EMSGSIZE; info = nla_data(attr); memset(info, 0, md5sig_count * sizeof(struct tcp_diag_md5sig)); hlist_for_each_entry_rcu(key, &md5sig->head, node) { tcp_diag_md5sig_fill(info++, key); if (--md5sig_count == 0) break; } return 0; } #endif |
61723b393 tcp: ulp: add fun... |
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
static int tcp_diag_put_ulp(struct sk_buff *skb, struct sock *sk, const struct tcp_ulp_ops *ulp_ops) { struct nlattr *nest; int err; nest = nla_nest_start_noflag(skb, INET_DIAG_ULP_INFO); if (!nest) return -EMSGSIZE; err = nla_put_string(skb, INET_ULP_INFO_NAME, ulp_ops->name); if (err) goto nla_failure; if (ulp_ops->get_info) err = ulp_ops->get_info(sk, skb); if (err) goto nla_failure; nla_nest_end(skb, nest); return 0; nla_failure: nla_nest_cancel(skb, nest); return err; } |
c03fa9bca tcp_diag: report ... |
105 106 107 |
static int tcp_diag_get_aux(struct sock *sk, bool net_admin, struct sk_buff *skb) { |
61723b393 tcp: ulp: add fun... |
108 109 |
struct inet_connection_sock *icsk = inet_csk(sk); int err = 0; |
c03fa9bca tcp_diag: report ... |
110 111 112 |
#ifdef CONFIG_TCP_MD5SIG if (net_admin) { struct tcp_md5sig_info *md5sig; |
c03fa9bca tcp_diag: report ... |
113 114 115 116 117 118 119 120 121 122 |
rcu_read_lock(); md5sig = rcu_dereference(tcp_sk(sk)->md5sig_info); if (md5sig) err = tcp_diag_put_md5sig(skb, md5sig); rcu_read_unlock(); if (err < 0) return err; } #endif |
61723b393 tcp: ulp: add fun... |
123 124 125 126 127 128 129 130 131 |
if (net_admin) { const struct tcp_ulp_ops *ulp_ops; ulp_ops = icsk->icsk_ulp_ops; if (ulp_ops) err = tcp_diag_put_ulp(skb, sk, ulp_ops); if (err) return err; } |
c03fa9bca tcp_diag: report ... |
132 133 134 135 136 |
return 0; } static size_t tcp_diag_get_aux_size(struct sock *sk, bool net_admin) { |
61723b393 tcp: ulp: add fun... |
137 |
struct inet_connection_sock *icsk = inet_csk(sk); |
c03fa9bca tcp_diag: report ... |
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
size_t size = 0; #ifdef CONFIG_TCP_MD5SIG if (net_admin && sk_fullsock(sk)) { const struct tcp_md5sig_info *md5sig; const struct tcp_md5sig_key *key; size_t md5sig_count = 0; rcu_read_lock(); md5sig = rcu_dereference(tcp_sk(sk)->md5sig_info); if (md5sig) { hlist_for_each_entry_rcu(key, &md5sig->head, node) md5sig_count++; } rcu_read_unlock(); size += nla_total_size(md5sig_count * sizeof(struct tcp_diag_md5sig)); } #endif |
b58662a5f tcp: ulp: fix pos... |
157 |
if (net_admin && sk_fullsock(sk)) { |
61723b393 tcp: ulp: add fun... |
158 159 160 161 162 163 164 165 166 167 |
const struct tcp_ulp_ops *ulp_ops; ulp_ops = icsk->icsk_ulp_ops; if (ulp_ops) { size += nla_total_size(0) + nla_total_size(TCP_ULP_NAME_MAX); if (ulp_ops->get_info_size) size += ulp_ops->get_info_size(sk); } } |
c03fa9bca tcp_diag: report ... |
168 169 |
return size; } |
1942c518c inet_diag: Genera... |
170 |
static void tcp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, |
0df6d3284 inet_diag: Move t... |
171 |
const struct inet_diag_req_v2 *r) |
1942c518c inet_diag: Genera... |
172 |
{ |
0df6d3284 inet_diag: Move t... |
173 |
inet_diag_dump_icsk(&tcp_hashinfo, skb, cb, r); |
1942c518c inet_diag: Genera... |
174 |
} |
5682d393b inet_diag: Refact... |
175 |
static int tcp_diag_dump_one(struct netlink_callback *cb, |
34160ea3f inet_diag: add co... |
176 |
const struct inet_diag_req_v2 *req) |
1942c518c inet_diag: Genera... |
177 |
{ |
5682d393b inet_diag: Refact... |
178 |
return inet_diag_dump_one_icsk(&tcp_hashinfo, cb, req); |
1942c518c inet_diag: Genera... |
179 |
} |
c1e64e298 net: diag: Suppor... |
180 181 182 183 184 185 |
#ifdef CONFIG_INET_DIAG_DESTROY static int tcp_diag_destroy(struct sk_buff *in_skb, const struct inet_diag_req_v2 *req) { struct net *net = sock_net(in_skb->sk); struct sock *sk = inet_diag_find_one_icsk(net, &tcp_hashinfo, req); |
d7226c7a4 net: diag: Fix re... |
186 |
int err; |
c1e64e298 net: diag: Suppor... |
187 188 189 |
if (IS_ERR(sk)) return PTR_ERR(sk); |
d7226c7a4 net: diag: Fix re... |
190 191 192 193 194 |
err = sock_diag_destroy(sk, ECONNABORTED); sock_gen_put(sk); return err; |
c1e64e298 net: diag: Suppor... |
195 196 |
} #endif |
a7a0d6a87 net: inet_diag_ha... |
197 |
static const struct inet_diag_handler tcp_diag_handler = { |
c03fa9bca tcp_diag: report ... |
198 199 200 201 202 203 204 |
.dump = tcp_diag_dump, .dump_one = tcp_diag_dump_one, .idiag_get_info = tcp_diag_get_info, .idiag_get_aux = tcp_diag_get_aux, .idiag_get_aux_size = tcp_diag_get_aux_size, .idiag_type = IPPROTO_TCP, .idiag_info_size = sizeof(struct tcp_info), |
c1e64e298 net: diag: Suppor... |
205 |
#ifdef CONFIG_INET_DIAG_DESTROY |
c03fa9bca tcp_diag: report ... |
206 |
.destroy = tcp_diag_destroy, |
c1e64e298 net: diag: Suppor... |
207 |
#endif |
17b085eac [INET_DIAG]: Move... |
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
}; static int __init tcp_diag_init(void) { return inet_diag_register(&tcp_diag_handler); } static void __exit tcp_diag_exit(void) { inet_diag_unregister(&tcp_diag_handler); } module_init(tcp_diag_init); module_exit(tcp_diag_exit); MODULE_LICENSE("GPL"); |
aec8dc62f sock_diag: Fix mo... |
223 |
MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-6 /* AF_INET - IPPROTO_TCP */); |