1 // SPDX-License-Identifier: GPL-2.0-only
2 #include <linux/module.h>
4 #include <linux/inet_diag.h>
5 #include <linux/sock_diag.h>
7 #include <net/inet_sock.h>
15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17 static struct raw_hashinfo
*
18 raw_get_hashinfo(const struct inet_diag_req_v2
*r
)
20 if (r
->sdiag_family
== AF_INET
) {
21 return &raw_v4_hashinfo
;
22 #if IS_ENABLED(CONFIG_IPV6)
23 } else if (r
->sdiag_family
== AF_INET6
) {
24 return &raw_v6_hashinfo
;
27 return ERR_PTR(-EINVAL
);
32 * Due to requirement of not breaking user API we can't simply
33 * rename @pad field in inet_diag_req_v2 structure, instead
34 * use helper to figure it out.
37 static struct sock
*raw_lookup(struct net
*net
, struct sock
*from
,
38 const struct inet_diag_req_v2
*req
)
40 struct inet_diag_req_raw
*r
= (void *)req
;
41 struct sock
*sk
= NULL
;
43 if (r
->sdiag_family
== AF_INET
)
44 sk
= __raw_v4_lookup(net
, from
, r
->sdiag_raw_protocol
,
48 #if IS_ENABLED(CONFIG_IPV6)
50 sk
= __raw_v6_lookup(net
, from
, r
->sdiag_raw_protocol
,
51 (const struct in6_addr
*)r
->id
.idiag_src
,
52 (const struct in6_addr
*)r
->id
.idiag_dst
,
58 static struct sock
*raw_sock_get(struct net
*net
, const struct inet_diag_req_v2
*r
)
60 struct raw_hashinfo
*hashinfo
= raw_get_hashinfo(r
);
61 struct sock
*sk
= NULL
, *s
;
65 return ERR_CAST(hashinfo
);
67 read_lock(&hashinfo
->lock
);
68 for (slot
= 0; slot
< RAW_HTABLE_SIZE
; slot
++) {
69 sk_for_each(s
, &hashinfo
->ht
[slot
]) {
70 sk
= raw_lookup(net
, s
, r
);
73 * Grab it and keep until we fill
74 * diag meaage to be reported, so
75 * caller should call sock_put then.
76 * We can do that because we're keeping
77 * hashinfo->lock here.
85 read_unlock(&hashinfo
->lock
);
87 return sk
? sk
: ERR_PTR(-ENOENT
);
90 static int raw_diag_dump_one(struct netlink_callback
*cb
,
91 const struct inet_diag_req_v2
*r
)
93 struct sk_buff
*in_skb
= cb
->skb
;
99 net
= sock_net(in_skb
->sk
);
100 sk
= raw_sock_get(net
, r
);
104 rep
= nlmsg_new(nla_total_size(sizeof(struct inet_diag_msg
)) +
105 inet_diag_msg_attrs_size() +
106 nla_total_size(sizeof(struct inet_diag_meminfo
)) + 64,
113 err
= inet_sk_diag_fill(sk
, NULL
, rep
, cb
, r
, 0,
114 netlink_net_capable(in_skb
, CAP_NET_ADMIN
));
122 err
= netlink_unicast(net
->diag_nlsk
, rep
,
123 NETLINK_CB(in_skb
).portid
,
130 static int sk_diag_dump(struct sock
*sk
, struct sk_buff
*skb
,
131 struct netlink_callback
*cb
,
132 const struct inet_diag_req_v2
*r
,
133 struct nlattr
*bc
, bool net_admin
)
135 if (!inet_diag_bc_sk(bc
, sk
))
138 return inet_sk_diag_fill(sk
, NULL
, skb
, cb
, r
, NLM_F_MULTI
, net_admin
);
141 static void raw_diag_dump(struct sk_buff
*skb
, struct netlink_callback
*cb
,
142 const struct inet_diag_req_v2
*r
)
144 bool net_admin
= netlink_net_capable(cb
->skb
, CAP_NET_ADMIN
);
145 struct raw_hashinfo
*hashinfo
= raw_get_hashinfo(r
);
146 struct net
*net
= sock_net(skb
->sk
);
147 struct inet_diag_dump_data
*cb_data
;
148 int num
, s_num
, slot
, s_slot
;
149 struct sock
*sk
= NULL
;
152 if (IS_ERR(hashinfo
))
156 bc
= cb_data
->inet_diag_nla_bc
;
157 s_slot
= cb
->args
[0];
158 num
= s_num
= cb
->args
[1];
160 read_lock(&hashinfo
->lock
);
161 for (slot
= s_slot
; slot
< RAW_HTABLE_SIZE
; s_num
= 0, slot
++) {
164 sk_for_each(sk
, &hashinfo
->ht
[slot
]) {
165 struct inet_sock
*inet
= inet_sk(sk
);
167 if (!net_eq(sock_net(sk
), net
))
171 if (sk
->sk_family
!= r
->sdiag_family
)
173 if (r
->id
.idiag_sport
!= inet
->inet_sport
&&
176 if (r
->id
.idiag_dport
!= inet
->inet_dport
&&
179 if (sk_diag_dump(sk
, skb
, cb
, r
, bc
, net_admin
) < 0)
187 read_unlock(&hashinfo
->lock
);
193 static void raw_diag_get_info(struct sock
*sk
, struct inet_diag_msg
*r
,
196 r
->idiag_rqueue
= sk_rmem_alloc_get(sk
);
197 r
->idiag_wqueue
= sk_wmem_alloc_get(sk
);
200 #ifdef CONFIG_INET_DIAG_DESTROY
201 static int raw_diag_destroy(struct sk_buff
*in_skb
,
202 const struct inet_diag_req_v2
*r
)
204 struct net
*net
= sock_net(in_skb
->sk
);
208 sk
= raw_sock_get(net
, r
);
211 err
= sock_diag_destroy(sk
, ECONNABORTED
);
217 static const struct inet_diag_handler raw_diag_handler
= {
218 .dump
= raw_diag_dump
,
219 .dump_one
= raw_diag_dump_one
,
220 .idiag_get_info
= raw_diag_get_info
,
221 .idiag_type
= IPPROTO_RAW
,
222 .idiag_info_size
= 0,
223 #ifdef CONFIG_INET_DIAG_DESTROY
224 .destroy
= raw_diag_destroy
,
228 static void __always_unused
__check_inet_diag_req_raw(void)
231 * Make sure the two structures are identical,
232 * except the @pad field.
234 #define __offset_mismatch(m1, m2) \
235 (offsetof(struct inet_diag_req_v2, m1) != \
236 offsetof(struct inet_diag_req_raw, m2))
238 BUILD_BUG_ON(sizeof(struct inet_diag_req_v2
) !=
239 sizeof(struct inet_diag_req_raw
));
240 BUILD_BUG_ON(__offset_mismatch(sdiag_family
, sdiag_family
));
241 BUILD_BUG_ON(__offset_mismatch(sdiag_protocol
, sdiag_protocol
));
242 BUILD_BUG_ON(__offset_mismatch(idiag_ext
, idiag_ext
));
243 BUILD_BUG_ON(__offset_mismatch(pad
, sdiag_raw_protocol
));
244 BUILD_BUG_ON(__offset_mismatch(idiag_states
, idiag_states
));
245 BUILD_BUG_ON(__offset_mismatch(id
, id
));
246 #undef __offset_mismatch
249 static int __init
raw_diag_init(void)
251 return inet_diag_register(&raw_diag_handler
);
254 static void __exit
raw_diag_exit(void)
256 inet_diag_unregister(&raw_diag_handler
);
259 module_init(raw_diag_init
);
260 module_exit(raw_diag_exit
);
261 MODULE_LICENSE("GPL");
262 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK
, NETLINK_SOCK_DIAG
, 2-255 /* AF_INET - IPPROTO_RAW */);
263 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK
, NETLINK_SOCK_DIAG
, 10-255 /* AF_INET6 - IPPROTO_RAW */);