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
;
89 flen
= bpf_classic_proglen(fprog
);
91 attr
= nla_reserve(skb
, attrtype
, flen
);
97 memcpy(nla_data(attr
), fprog
->filter
, flen
);
102 EXPORT_SYMBOL(sock_diag_put_filterinfo
);
104 void sock_diag_register_inet_compat(int (*fn
)(struct sk_buff
*skb
, struct nlmsghdr
*nlh
))
106 mutex_lock(&sock_diag_table_mutex
);
107 inet_rcv_compat
= fn
;
108 mutex_unlock(&sock_diag_table_mutex
);
110 EXPORT_SYMBOL_GPL(sock_diag_register_inet_compat
);
112 void sock_diag_unregister_inet_compat(int (*fn
)(struct sk_buff
*skb
, struct nlmsghdr
*nlh
))
114 mutex_lock(&sock_diag_table_mutex
);
115 inet_rcv_compat
= NULL
;
116 mutex_unlock(&sock_diag_table_mutex
);
118 EXPORT_SYMBOL_GPL(sock_diag_unregister_inet_compat
);
120 int sock_diag_register(const struct sock_diag_handler
*hndl
)
124 if (hndl
->family
>= AF_MAX
)
127 mutex_lock(&sock_diag_table_mutex
);
128 if (sock_diag_handlers
[hndl
->family
])
131 sock_diag_handlers
[hndl
->family
] = hndl
;
132 mutex_unlock(&sock_diag_table_mutex
);
136 EXPORT_SYMBOL_GPL(sock_diag_register
);
138 void sock_diag_unregister(const struct sock_diag_handler
*hnld
)
140 int family
= hnld
->family
;
142 if (family
>= AF_MAX
)
145 mutex_lock(&sock_diag_table_mutex
);
146 BUG_ON(sock_diag_handlers
[family
] != hnld
);
147 sock_diag_handlers
[family
] = NULL
;
148 mutex_unlock(&sock_diag_table_mutex
);
150 EXPORT_SYMBOL_GPL(sock_diag_unregister
);
152 static int __sock_diag_rcv_msg(struct sk_buff
*skb
, struct nlmsghdr
*nlh
)
155 struct sock_diag_req
*req
= nlmsg_data(nlh
);
156 const struct sock_diag_handler
*hndl
;
158 if (nlmsg_len(nlh
) < sizeof(*req
))
161 if (req
->sdiag_family
>= AF_MAX
)
164 if (sock_diag_handlers
[req
->sdiag_family
] == NULL
)
165 request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK
,
166 NETLINK_SOCK_DIAG
, req
->sdiag_family
);
168 mutex_lock(&sock_diag_table_mutex
);
169 hndl
= sock_diag_handlers
[req
->sdiag_family
];
173 err
= hndl
->dump(skb
, nlh
);
174 mutex_unlock(&sock_diag_table_mutex
);
179 static int sock_diag_rcv_msg(struct sk_buff
*skb
, struct nlmsghdr
*nlh
)
183 switch (nlh
->nlmsg_type
) {
184 case TCPDIAG_GETSOCK
:
185 case DCCPDIAG_GETSOCK
:
186 if (inet_rcv_compat
== NULL
)
187 request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK
,
188 NETLINK_SOCK_DIAG
, AF_INET
);
190 mutex_lock(&sock_diag_table_mutex
);
191 if (inet_rcv_compat
!= NULL
)
192 ret
= inet_rcv_compat(skb
, nlh
);
195 mutex_unlock(&sock_diag_table_mutex
);
198 case SOCK_DIAG_BY_FAMILY
:
199 return __sock_diag_rcv_msg(skb
, nlh
);
205 static DEFINE_MUTEX(sock_diag_mutex
);
207 static void sock_diag_rcv(struct sk_buff
*skb
)
209 mutex_lock(&sock_diag_mutex
);
210 netlink_rcv_skb(skb
, &sock_diag_rcv_msg
);
211 mutex_unlock(&sock_diag_mutex
);
214 static int __net_init
diag_net_init(struct net
*net
)
216 struct netlink_kernel_cfg cfg
= {
217 .input
= sock_diag_rcv
,
220 net
->diag_nlsk
= netlink_kernel_create(net
, NETLINK_SOCK_DIAG
, &cfg
);
221 return net
->diag_nlsk
== NULL
? -ENOMEM
: 0;
224 static void __net_exit
diag_net_exit(struct net
*net
)
226 netlink_kernel_release(net
->diag_nlsk
);
227 net
->diag_nlsk
= NULL
;
230 static struct pernet_operations diag_net_ops
= {
231 .init
= diag_net_init
,
232 .exit
= diag_net_exit
,
235 static int __init
sock_diag_init(void)
237 return register_pernet_subsys(&diag_net_ops
);
240 static void __exit
sock_diag_exit(void)
242 unregister_pernet_subsys(&diag_net_ops
);
245 module_init(sock_diag_init
);
246 module_exit(sock_diag_exit
);
247 MODULE_LICENSE("GPL");
248 MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK
, NETLINK_SOCK_DIAG
);