1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * udp_diag.c Module for monitoring UDP transport protocols sockets.
5 * Authors: Pavel Emelyanov, <xemul@parallels.com>
9 #include <linux/module.h>
10 #include <linux/inet_diag.h>
11 #include <linux/udp.h>
13 #include <net/udplite.h>
14 #include <linux/sock_diag.h>
16 static int sk_diag_dump(struct sock
*sk
, struct sk_buff
*skb
,
17 struct netlink_callback
*cb
,
18 const struct inet_diag_req_v2
*req
,
19 struct nlattr
*bc
, bool net_admin
)
21 if (!inet_diag_bc_sk(bc
, sk
))
24 return inet_sk_diag_fill(sk
, NULL
, skb
, cb
, req
, NLM_F_MULTI
,
28 static int udp_dump_one(struct udp_table
*tbl
,
29 struct netlink_callback
*cb
,
30 const struct inet_diag_req_v2
*req
)
32 struct sk_buff
*in_skb
= cb
->skb
;
34 struct sock
*sk
= NULL
;
36 struct net
*net
= sock_net(in_skb
->sk
);
39 if (req
->sdiag_family
== AF_INET
)
40 /* src and dst are swapped for historical reasons */
41 sk
= __udp4_lib_lookup(net
,
42 req
->id
.idiag_src
[0], req
->id
.idiag_sport
,
43 req
->id
.idiag_dst
[0], req
->id
.idiag_dport
,
44 req
->id
.idiag_if
, 0, tbl
, NULL
);
45 #if IS_ENABLED(CONFIG_IPV6)
46 else if (req
->sdiag_family
== AF_INET6
)
47 sk
= __udp6_lib_lookup(net
,
48 (struct in6_addr
*)req
->id
.idiag_src
,
50 (struct in6_addr
*)req
->id
.idiag_dst
,
52 req
->id
.idiag_if
, 0, tbl
, NULL
);
54 if (sk
&& !refcount_inc_not_zero(&sk
->sk_refcnt
))
61 err
= sock_diag_check_cookie(sk
, req
->id
.idiag_cookie
);
66 rep
= nlmsg_new(nla_total_size(sizeof(struct inet_diag_msg
)) +
67 inet_diag_msg_attrs_size() +
68 nla_total_size(sizeof(struct inet_diag_meminfo
)) + 64,
73 err
= inet_sk_diag_fill(sk
, NULL
, rep
, cb
, req
, 0,
74 netlink_net_capable(in_skb
, CAP_NET_ADMIN
));
76 WARN_ON(err
== -EMSGSIZE
);
80 err
= nlmsg_unicast(net
->diag_nlsk
, rep
, NETLINK_CB(in_skb
).portid
);
89 static void udp_dump(struct udp_table
*table
, struct sk_buff
*skb
,
90 struct netlink_callback
*cb
,
91 const struct inet_diag_req_v2
*r
)
93 bool net_admin
= netlink_net_capable(cb
->skb
, CAP_NET_ADMIN
);
94 struct net
*net
= sock_net(skb
->sk
);
95 struct inet_diag_dump_data
*cb_data
;
96 int num
, s_num
, slot
, s_slot
;
100 bc
= cb_data
->inet_diag_nla_bc
;
101 s_slot
= cb
->args
[0];
102 num
= s_num
= cb
->args
[1];
104 for (slot
= s_slot
; slot
<= table
->mask
; s_num
= 0, slot
++) {
105 struct udp_hslot
*hslot
= &table
->hash
[slot
];
110 if (hlist_empty(&hslot
->head
))
113 spin_lock_bh(&hslot
->lock
);
114 sk_for_each(sk
, &hslot
->head
) {
115 struct inet_sock
*inet
= inet_sk(sk
);
117 if (!net_eq(sock_net(sk
), net
))
121 if (!(r
->idiag_states
& (1 << sk
->sk_state
)))
123 if (r
->sdiag_family
!= AF_UNSPEC
&&
124 sk
->sk_family
!= r
->sdiag_family
)
126 if (r
->id
.idiag_sport
!= inet
->inet_sport
&&
129 if (r
->id
.idiag_dport
!= inet
->inet_dport
&&
133 if (sk_diag_dump(sk
, skb
, cb
, r
, bc
, net_admin
) < 0) {
134 spin_unlock_bh(&hslot
->lock
);
140 spin_unlock_bh(&hslot
->lock
);
147 static void udp_diag_dump(struct sk_buff
*skb
, struct netlink_callback
*cb
,
148 const struct inet_diag_req_v2
*r
)
150 udp_dump(sock_net(cb
->skb
->sk
)->ipv4
.udp_table
, skb
, cb
, r
);
153 static int udp_diag_dump_one(struct netlink_callback
*cb
,
154 const struct inet_diag_req_v2
*req
)
156 return udp_dump_one(sock_net(cb
->skb
->sk
)->ipv4
.udp_table
, cb
, req
);
159 static void udp_diag_get_info(struct sock
*sk
, struct inet_diag_msg
*r
,
162 r
->idiag_rqueue
= udp_rqueue_get(sk
);
163 r
->idiag_wqueue
= sk_wmem_alloc_get(sk
);
166 #ifdef CONFIG_INET_DIAG_DESTROY
167 static int __udp_diag_destroy(struct sk_buff
*in_skb
,
168 const struct inet_diag_req_v2
*req
,
169 struct udp_table
*tbl
)
171 struct net
*net
= sock_net(in_skb
->sk
);
177 if (req
->sdiag_family
== AF_INET
)
178 sk
= __udp4_lib_lookup(net
,
179 req
->id
.idiag_dst
[0], req
->id
.idiag_dport
,
180 req
->id
.idiag_src
[0], req
->id
.idiag_sport
,
181 req
->id
.idiag_if
, 0, tbl
, NULL
);
182 #if IS_ENABLED(CONFIG_IPV6)
183 else if (req
->sdiag_family
== AF_INET6
) {
184 if (ipv6_addr_v4mapped((struct in6_addr
*)req
->id
.idiag_dst
) &&
185 ipv6_addr_v4mapped((struct in6_addr
*)req
->id
.idiag_src
))
186 sk
= __udp4_lib_lookup(net
,
187 req
->id
.idiag_dst
[3], req
->id
.idiag_dport
,
188 req
->id
.idiag_src
[3], req
->id
.idiag_sport
,
189 req
->id
.idiag_if
, 0, tbl
, NULL
);
192 sk
= __udp6_lib_lookup(net
,
193 (struct in6_addr
*)req
->id
.idiag_dst
,
195 (struct in6_addr
*)req
->id
.idiag_src
,
197 req
->id
.idiag_if
, 0, tbl
, NULL
);
205 if (sk
&& !refcount_inc_not_zero(&sk
->sk_refcnt
))
213 if (sock_diag_check_cookie(sk
, req
->id
.idiag_cookie
)) {
218 err
= sock_diag_destroy(sk
, ECONNABORTED
);
225 static int udp_diag_destroy(struct sk_buff
*in_skb
,
226 const struct inet_diag_req_v2
*req
)
228 return __udp_diag_destroy(in_skb
, req
, sock_net(in_skb
->sk
)->ipv4
.udp_table
);
231 static int udplite_diag_destroy(struct sk_buff
*in_skb
,
232 const struct inet_diag_req_v2
*req
)
234 return __udp_diag_destroy(in_skb
, req
, &udplite_table
);
239 static const struct inet_diag_handler udp_diag_handler
= {
240 .owner
= THIS_MODULE
,
241 .dump
= udp_diag_dump
,
242 .dump_one
= udp_diag_dump_one
,
243 .idiag_get_info
= udp_diag_get_info
,
244 .idiag_type
= IPPROTO_UDP
,
245 .idiag_info_size
= 0,
246 #ifdef CONFIG_INET_DIAG_DESTROY
247 .destroy
= udp_diag_destroy
,
251 static void udplite_diag_dump(struct sk_buff
*skb
, struct netlink_callback
*cb
,
252 const struct inet_diag_req_v2
*r
)
254 udp_dump(&udplite_table
, skb
, cb
, r
);
257 static int udplite_diag_dump_one(struct netlink_callback
*cb
,
258 const struct inet_diag_req_v2
*req
)
260 return udp_dump_one(&udplite_table
, cb
, req
);
263 static const struct inet_diag_handler udplite_diag_handler
= {
264 .owner
= THIS_MODULE
,
265 .dump
= udplite_diag_dump
,
266 .dump_one
= udplite_diag_dump_one
,
267 .idiag_get_info
= udp_diag_get_info
,
268 .idiag_type
= IPPROTO_UDPLITE
,
269 .idiag_info_size
= 0,
270 #ifdef CONFIG_INET_DIAG_DESTROY
271 .destroy
= udplite_diag_destroy
,
275 static int __init
udp_diag_init(void)
279 err
= inet_diag_register(&udp_diag_handler
);
282 err
= inet_diag_register(&udplite_diag_handler
);
288 inet_diag_unregister(&udp_diag_handler
);
292 static void __exit
udp_diag_exit(void)
294 inet_diag_unregister(&udplite_diag_handler
);
295 inet_diag_unregister(&udp_diag_handler
);
298 module_init(udp_diag_init
);
299 module_exit(udp_diag_exit
);
300 MODULE_LICENSE("GPL");
301 MODULE_DESCRIPTION("UDP socket monitoring via SOCK_DIAG");
302 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK
, NETLINK_SOCK_DIAG
, 2-17 /* AF_INET - IPPROTO_UDP */);
303 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK
, NETLINK_SOCK_DIAG
, 2-136 /* AF_INET - IPPROTO_UDPLITE */);