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 sk_buff
*in_skb
,
91 const struct nlmsghdr
*nlh
,
92 const struct inet_diag_req_v2
*r
)
94 struct net
*net
= sock_net(in_skb
->sk
);
99 sk
= raw_sock_get(net
, r
);
103 rep
= nlmsg_new(sizeof(struct inet_diag_msg
) +
104 sizeof(struct inet_diag_meminfo
) + 64,
111 err
= inet_sk_diag_fill(sk
, NULL
, rep
, r
,
112 sk_user_ns(NETLINK_CB(in_skb
).sk
),
113 NETLINK_CB(in_skb
).portid
,
114 nlh
->nlmsg_seq
, 0, nlh
,
115 netlink_net_capable(in_skb
, CAP_NET_ADMIN
));
123 err
= netlink_unicast(net
->diag_nlsk
, rep
,
124 NETLINK_CB(in_skb
).portid
,
131 static int sk_diag_dump(struct sock
*sk
, struct sk_buff
*skb
,
132 struct netlink_callback
*cb
,
133 const struct inet_diag_req_v2
*r
,
134 struct nlattr
*bc
, bool net_admin
)
136 if (!inet_diag_bc_sk(bc
, sk
))
139 return inet_sk_diag_fill(sk
, NULL
, skb
, r
,
140 sk_user_ns(NETLINK_CB(cb
->skb
).sk
),
141 NETLINK_CB(cb
->skb
).portid
,
142 cb
->nlh
->nlmsg_seq
, NLM_F_MULTI
,
146 static void raw_diag_dump(struct sk_buff
*skb
, struct netlink_callback
*cb
,
147 const struct inet_diag_req_v2
*r
, struct nlattr
*bc
)
149 bool net_admin
= netlink_net_capable(cb
->skb
, CAP_NET_ADMIN
);
150 struct raw_hashinfo
*hashinfo
= raw_get_hashinfo(r
);
151 struct net
*net
= sock_net(skb
->sk
);
152 int num
, s_num
, slot
, s_slot
;
153 struct sock
*sk
= NULL
;
155 if (IS_ERR(hashinfo
))
158 s_slot
= cb
->args
[0];
159 num
= s_num
= cb
->args
[1];
161 read_lock(&hashinfo
->lock
);
162 for (slot
= s_slot
; slot
< RAW_HTABLE_SIZE
; s_num
= 0, slot
++) {
165 sk_for_each(sk
, &hashinfo
->ht
[slot
]) {
166 struct inet_sock
*inet
= inet_sk(sk
);
168 if (!net_eq(sock_net(sk
), net
))
172 if (sk
->sk_family
!= r
->sdiag_family
)
174 if (r
->id
.idiag_sport
!= inet
->inet_sport
&&
177 if (r
->id
.idiag_dport
!= inet
->inet_dport
&&
180 if (sk_diag_dump(sk
, skb
, cb
, r
, bc
, net_admin
) < 0)
188 read_unlock(&hashinfo
->lock
);
194 static void raw_diag_get_info(struct sock
*sk
, struct inet_diag_msg
*r
,
197 r
->idiag_rqueue
= sk_rmem_alloc_get(sk
);
198 r
->idiag_wqueue
= sk_wmem_alloc_get(sk
);
201 #ifdef CONFIG_INET_DIAG_DESTROY
202 static int raw_diag_destroy(struct sk_buff
*in_skb
,
203 const struct inet_diag_req_v2
*r
)
205 struct net
*net
= sock_net(in_skb
->sk
);
209 sk
= raw_sock_get(net
, r
);
212 err
= sock_diag_destroy(sk
, ECONNABORTED
);
218 static const struct inet_diag_handler raw_diag_handler
= {
219 .dump
= raw_diag_dump
,
220 .dump_one
= raw_diag_dump_one
,
221 .idiag_get_info
= raw_diag_get_info
,
222 .idiag_type
= IPPROTO_RAW
,
223 .idiag_info_size
= 0,
224 #ifdef CONFIG_INET_DIAG_DESTROY
225 .destroy
= raw_diag_destroy
,
229 static void __always_unused
__check_inet_diag_req_raw(void)
232 * Make sure the two structures are identical,
233 * except the @pad field.
235 #define __offset_mismatch(m1, m2) \
236 (offsetof(struct inet_diag_req_v2, m1) != \
237 offsetof(struct inet_diag_req_raw, m2))
239 BUILD_BUG_ON(sizeof(struct inet_diag_req_v2
) !=
240 sizeof(struct inet_diag_req_raw
));
241 BUILD_BUG_ON(__offset_mismatch(sdiag_family
, sdiag_family
));
242 BUILD_BUG_ON(__offset_mismatch(sdiag_protocol
, sdiag_protocol
));
243 BUILD_BUG_ON(__offset_mismatch(idiag_ext
, idiag_ext
));
244 BUILD_BUG_ON(__offset_mismatch(pad
, sdiag_raw_protocol
));
245 BUILD_BUG_ON(__offset_mismatch(idiag_states
, idiag_states
));
246 BUILD_BUG_ON(__offset_mismatch(id
, id
));
247 #undef __offset_mismatch
250 static int __init
raw_diag_init(void)
252 return inet_diag_register(&raw_diag_handler
);
255 static void __exit
raw_diag_exit(void)
257 inet_diag_unregister(&raw_diag_handler
);
260 module_init(raw_diag_init
);
261 module_exit(raw_diag_exit
);
262 MODULE_LICENSE("GPL");
263 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK
, NETLINK_SOCK_DIAG
, 2-255 /* AF_INET - IPPROTO_RAW */);
264 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK
, NETLINK_SOCK_DIAG
, 10-255 /* AF_INET6 - IPPROTO_RAW */);