1 #include <linux/mutex.h>
2 #include <linux/socket.h>
3 #include <linux/skbuff.h>
4 #include <net/netlink.h>
5 #include <net/net_namespace.h>
6 #include <linux/module.h>
9 #include <linux/inet_diag.h>
10 #include <linux/sock_diag.h>
12 static const struct sock_diag_handler
*sock_diag_handlers
[AF_MAX
];
13 static int (*inet_rcv_compat
)(struct sk_buff
*skb
, struct nlmsghdr
*nlh
);
14 static DEFINE_MUTEX(sock_diag_table_mutex
);
16 static u64
sock_gen_cookie(struct sock
*sk
)
19 u64 res
= atomic64_read(&sk
->sk_cookie
);
23 res
= atomic64_inc_return(&sock_net(sk
)->cookie_gen
);
24 atomic64_cmpxchg(&sk
->sk_cookie
, 0, res
);
28 int sock_diag_check_cookie(struct sock
*sk
, const __u32
*cookie
)
32 if (cookie
[0] == INET_DIAG_NOCOOKIE
&& cookie
[1] == INET_DIAG_NOCOOKIE
)
35 res
= sock_gen_cookie(sk
);
36 if ((u32
)res
!= cookie
[0] || (u32
)(res
>> 32) != cookie
[1])
41 EXPORT_SYMBOL_GPL(sock_diag_check_cookie
);
43 void sock_diag_save_cookie(struct sock
*sk
, __u32
*cookie
)
45 u64 res
= sock_gen_cookie(sk
);
48 cookie
[1] = (u32
)(res
>> 32);
50 EXPORT_SYMBOL_GPL(sock_diag_save_cookie
);
52 int sock_diag_put_meminfo(struct sock
*sk
, struct sk_buff
*skb
, int attrtype
)
54 u32 mem
[SK_MEMINFO_VARS
];
56 mem
[SK_MEMINFO_RMEM_ALLOC
] = sk_rmem_alloc_get(sk
);
57 mem
[SK_MEMINFO_RCVBUF
] = sk
->sk_rcvbuf
;
58 mem
[SK_MEMINFO_WMEM_ALLOC
] = sk_wmem_alloc_get(sk
);
59 mem
[SK_MEMINFO_SNDBUF
] = sk
->sk_sndbuf
;
60 mem
[SK_MEMINFO_FWD_ALLOC
] = sk
->sk_forward_alloc
;
61 mem
[SK_MEMINFO_WMEM_QUEUED
] = sk
->sk_wmem_queued
;
62 mem
[SK_MEMINFO_OPTMEM
] = atomic_read(&sk
->sk_omem_alloc
);
63 mem
[SK_MEMINFO_BACKLOG
] = sk
->sk_backlog
.len
;
65 return nla_put(skb
, attrtype
, sizeof(mem
), &mem
);
67 EXPORT_SYMBOL_GPL(sock_diag_put_meminfo
);
69 int sock_diag_put_filterinfo(bool may_report_filterinfo
, struct sock
*sk
,
70 struct sk_buff
*skb
, int attrtype
)
72 struct sock_fprog_kern
*fprog
;
73 struct sk_filter
*filter
;
78 if (!may_report_filterinfo
) {
79 nla_reserve(skb
, attrtype
, 0);
84 filter
= rcu_dereference(sk
->sk_filter
);
88 fprog
= filter
->prog
->orig_prog
;
92 flen
= bpf_classic_proglen(fprog
);
94 attr
= nla_reserve(skb
, attrtype
, flen
);
100 memcpy(nla_data(attr
), fprog
->filter
, flen
);
105 EXPORT_SYMBOL(sock_diag_put_filterinfo
);
107 void sock_diag_register_inet_compat(int (*fn
)(struct sk_buff
*skb
, struct nlmsghdr
*nlh
))
109 mutex_lock(&sock_diag_table_mutex
);
110 inet_rcv_compat
= fn
;
111 mutex_unlock(&sock_diag_table_mutex
);
113 EXPORT_SYMBOL_GPL(sock_diag_register_inet_compat
);
115 void sock_diag_unregister_inet_compat(int (*fn
)(struct sk_buff
*skb
, struct nlmsghdr
*nlh
))
117 mutex_lock(&sock_diag_table_mutex
);
118 inet_rcv_compat
= NULL
;
119 mutex_unlock(&sock_diag_table_mutex
);
121 EXPORT_SYMBOL_GPL(sock_diag_unregister_inet_compat
);
123 int sock_diag_register(const struct sock_diag_handler
*hndl
)
127 if (hndl
->family
>= AF_MAX
)
130 mutex_lock(&sock_diag_table_mutex
);
131 if (sock_diag_handlers
[hndl
->family
])
134 sock_diag_handlers
[hndl
->family
] = hndl
;
135 mutex_unlock(&sock_diag_table_mutex
);
139 EXPORT_SYMBOL_GPL(sock_diag_register
);
141 void sock_diag_unregister(const struct sock_diag_handler
*hnld
)
143 int family
= hnld
->family
;
145 if (family
>= AF_MAX
)
148 mutex_lock(&sock_diag_table_mutex
);
149 BUG_ON(sock_diag_handlers
[family
] != hnld
);
150 sock_diag_handlers
[family
] = NULL
;
151 mutex_unlock(&sock_diag_table_mutex
);
153 EXPORT_SYMBOL_GPL(sock_diag_unregister
);
155 static int __sock_diag_rcv_msg(struct sk_buff
*skb
, struct nlmsghdr
*nlh
)
158 struct sock_diag_req
*req
= nlmsg_data(nlh
);
159 const struct sock_diag_handler
*hndl
;
161 if (nlmsg_len(nlh
) < sizeof(*req
))
164 if (req
->sdiag_family
>= AF_MAX
)
167 if (sock_diag_handlers
[req
->sdiag_family
] == NULL
)
168 request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK
,
169 NETLINK_SOCK_DIAG
, req
->sdiag_family
);
171 mutex_lock(&sock_diag_table_mutex
);
172 hndl
= sock_diag_handlers
[req
->sdiag_family
];
176 err
= hndl
->dump(skb
, nlh
);
177 mutex_unlock(&sock_diag_table_mutex
);
182 static int sock_diag_rcv_msg(struct sk_buff
*skb
, struct nlmsghdr
*nlh
)
186 switch (nlh
->nlmsg_type
) {
187 case TCPDIAG_GETSOCK
:
188 case DCCPDIAG_GETSOCK
:
189 if (inet_rcv_compat
== NULL
)
190 request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK
,
191 NETLINK_SOCK_DIAG
, AF_INET
);
193 mutex_lock(&sock_diag_table_mutex
);
194 if (inet_rcv_compat
!= NULL
)
195 ret
= inet_rcv_compat(skb
, nlh
);
198 mutex_unlock(&sock_diag_table_mutex
);
201 case SOCK_DIAG_BY_FAMILY
:
202 return __sock_diag_rcv_msg(skb
, nlh
);
208 static DEFINE_MUTEX(sock_diag_mutex
);
210 static void sock_diag_rcv(struct sk_buff
*skb
)
212 mutex_lock(&sock_diag_mutex
);
213 netlink_rcv_skb(skb
, &sock_diag_rcv_msg
);
214 mutex_unlock(&sock_diag_mutex
);
217 static int __net_init
diag_net_init(struct net
*net
)
219 struct netlink_kernel_cfg cfg
= {
220 .input
= sock_diag_rcv
,
223 net
->diag_nlsk
= netlink_kernel_create(net
, NETLINK_SOCK_DIAG
, &cfg
);
224 return net
->diag_nlsk
== NULL
? -ENOMEM
: 0;
227 static void __net_exit
diag_net_exit(struct net
*net
)
229 netlink_kernel_release(net
->diag_nlsk
);
230 net
->diag_nlsk
= NULL
;
233 static struct pernet_operations diag_net_ops
= {
234 .init
= diag_net_init
,
235 .exit
= diag_net_exit
,
238 static int __init
sock_diag_init(void)
240 return register_pernet_subsys(&diag_net_ops
);
243 static void __exit
sock_diag_exit(void)
245 unregister_pernet_subsys(&diag_net_ops
);
248 module_init(sock_diag_init
);
249 module_exit(sock_diag_exit
);
250 MODULE_LICENSE("GPL");
251 MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK
, NETLINK_SOCK_DIAG
);