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 int sock_diag_check_cookie(void *sk
, __u32
*cookie
)
18 if ((cookie
[0] != INET_DIAG_NOCOOKIE
||
19 cookie
[1] != INET_DIAG_NOCOOKIE
) &&
20 ((u32
)(unsigned long)sk
!= cookie
[0] ||
21 (u32
)((((unsigned long)sk
) >> 31) >> 1) != cookie
[1]))
26 EXPORT_SYMBOL_GPL(sock_diag_check_cookie
);
28 void sock_diag_save_cookie(void *sk
, __u32
*cookie
)
30 cookie
[0] = (u32
)(unsigned long)sk
;
31 cookie
[1] = (u32
)(((unsigned long)sk
>> 31) >> 1);
33 EXPORT_SYMBOL_GPL(sock_diag_save_cookie
);
35 int sock_diag_put_meminfo(struct sock
*sk
, struct sk_buff
*skb
, int attrtype
)
37 u32 mem
[SK_MEMINFO_VARS
];
39 mem
[SK_MEMINFO_RMEM_ALLOC
] = sk_rmem_alloc_get(sk
);
40 mem
[SK_MEMINFO_RCVBUF
] = sk
->sk_rcvbuf
;
41 mem
[SK_MEMINFO_WMEM_ALLOC
] = sk_wmem_alloc_get(sk
);
42 mem
[SK_MEMINFO_SNDBUF
] = sk
->sk_sndbuf
;
43 mem
[SK_MEMINFO_FWD_ALLOC
] = sk
->sk_forward_alloc
;
44 mem
[SK_MEMINFO_WMEM_QUEUED
] = sk
->sk_wmem_queued
;
45 mem
[SK_MEMINFO_OPTMEM
] = atomic_read(&sk
->sk_omem_alloc
);
46 mem
[SK_MEMINFO_BACKLOG
] = sk
->sk_backlog
.len
;
48 return nla_put(skb
, attrtype
, sizeof(mem
), &mem
);
50 EXPORT_SYMBOL_GPL(sock_diag_put_meminfo
);
52 int sock_diag_put_filterinfo(bool may_report_filterinfo
, struct sock
*sk
,
53 struct sk_buff
*skb
, int attrtype
)
56 struct sk_filter
*filter
;
60 if (!may_report_filterinfo
) {
61 nla_reserve(skb
, attrtype
, 0);
67 filter
= rcu_dereference(sk
->sk_filter
);
68 len
= filter
? filter
->len
* sizeof(struct sock_filter
) : 0;
70 attr
= nla_reserve(skb
, attrtype
, len
);
77 struct sock_filter
*fb
= (struct sock_filter
*)nla_data(attr
);
80 for (i
= 0; i
< filter
->len
; i
++, fb
++)
81 sk_decode_filter(&filter
->insns
[i
], fb
);
88 EXPORT_SYMBOL(sock_diag_put_filterinfo
);
90 void sock_diag_register_inet_compat(int (*fn
)(struct sk_buff
*skb
, struct nlmsghdr
*nlh
))
92 mutex_lock(&sock_diag_table_mutex
);
94 mutex_unlock(&sock_diag_table_mutex
);
96 EXPORT_SYMBOL_GPL(sock_diag_register_inet_compat
);
98 void sock_diag_unregister_inet_compat(int (*fn
)(struct sk_buff
*skb
, struct nlmsghdr
*nlh
))
100 mutex_lock(&sock_diag_table_mutex
);
101 inet_rcv_compat
= NULL
;
102 mutex_unlock(&sock_diag_table_mutex
);
104 EXPORT_SYMBOL_GPL(sock_diag_unregister_inet_compat
);
106 int sock_diag_register(const struct sock_diag_handler
*hndl
)
110 if (hndl
->family
>= AF_MAX
)
113 mutex_lock(&sock_diag_table_mutex
);
114 if (sock_diag_handlers
[hndl
->family
])
117 sock_diag_handlers
[hndl
->family
] = hndl
;
118 mutex_unlock(&sock_diag_table_mutex
);
122 EXPORT_SYMBOL_GPL(sock_diag_register
);
124 void sock_diag_unregister(const struct sock_diag_handler
*hnld
)
126 int family
= hnld
->family
;
128 if (family
>= AF_MAX
)
131 mutex_lock(&sock_diag_table_mutex
);
132 BUG_ON(sock_diag_handlers
[family
] != hnld
);
133 sock_diag_handlers
[family
] = NULL
;
134 mutex_unlock(&sock_diag_table_mutex
);
136 EXPORT_SYMBOL_GPL(sock_diag_unregister
);
138 static int __sock_diag_rcv_msg(struct sk_buff
*skb
, struct nlmsghdr
*nlh
)
141 struct sock_diag_req
*req
= nlmsg_data(nlh
);
142 const struct sock_diag_handler
*hndl
;
144 if (nlmsg_len(nlh
) < sizeof(*req
))
147 if (req
->sdiag_family
>= AF_MAX
)
150 if (sock_diag_handlers
[req
->sdiag_family
] == NULL
)
151 request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK
,
152 NETLINK_SOCK_DIAG
, req
->sdiag_family
);
154 mutex_lock(&sock_diag_table_mutex
);
155 hndl
= sock_diag_handlers
[req
->sdiag_family
];
159 err
= hndl
->dump(skb
, nlh
);
160 mutex_unlock(&sock_diag_table_mutex
);
165 static int sock_diag_rcv_msg(struct sk_buff
*skb
, struct nlmsghdr
*nlh
)
169 switch (nlh
->nlmsg_type
) {
170 case TCPDIAG_GETSOCK
:
171 case DCCPDIAG_GETSOCK
:
172 if (inet_rcv_compat
== NULL
)
173 request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK
,
174 NETLINK_SOCK_DIAG
, AF_INET
);
176 mutex_lock(&sock_diag_table_mutex
);
177 if (inet_rcv_compat
!= NULL
)
178 ret
= inet_rcv_compat(skb
, nlh
);
181 mutex_unlock(&sock_diag_table_mutex
);
184 case SOCK_DIAG_BY_FAMILY
:
185 return __sock_diag_rcv_msg(skb
, nlh
);
191 static DEFINE_MUTEX(sock_diag_mutex
);
193 static void sock_diag_rcv(struct sk_buff
*skb
)
195 mutex_lock(&sock_diag_mutex
);
196 netlink_rcv_skb(skb
, &sock_diag_rcv_msg
);
197 mutex_unlock(&sock_diag_mutex
);
200 static int __net_init
diag_net_init(struct net
*net
)
202 struct netlink_kernel_cfg cfg
= {
203 .input
= sock_diag_rcv
,
206 net
->diag_nlsk
= netlink_kernel_create(net
, NETLINK_SOCK_DIAG
, &cfg
);
207 return net
->diag_nlsk
== NULL
? -ENOMEM
: 0;
210 static void __net_exit
diag_net_exit(struct net
*net
)
212 netlink_kernel_release(net
->diag_nlsk
);
213 net
->diag_nlsk
= NULL
;
216 static struct pernet_operations diag_net_ops
= {
217 .init
= diag_net_init
,
218 .exit
= diag_net_exit
,
221 static int __init
sock_diag_init(void)
223 return register_pernet_subsys(&diag_net_ops
);
226 static void __exit
sock_diag_exit(void)
228 unregister_pernet_subsys(&diag_net_ops
);
231 module_init(sock_diag_init
);
232 module_exit(sock_diag_exit
);
233 MODULE_LICENSE("GPL");
234 MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK
, NETLINK_SOCK_DIAG
);