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
)
55 struct sock_fprog_kern
*fprog
;
56 struct sk_filter
*filter
;
61 if (!may_report_filterinfo
) {
62 nla_reserve(skb
, attrtype
, 0);
67 filter
= rcu_dereference(sk
->sk_filter
);
71 fprog
= filter
->prog
->orig_prog
;
72 flen
= bpf_classic_proglen(fprog
);
74 attr
= nla_reserve(skb
, attrtype
, flen
);
80 memcpy(nla_data(attr
), fprog
->filter
, flen
);
85 EXPORT_SYMBOL(sock_diag_put_filterinfo
);
87 void sock_diag_register_inet_compat(int (*fn
)(struct sk_buff
*skb
, struct nlmsghdr
*nlh
))
89 mutex_lock(&sock_diag_table_mutex
);
91 mutex_unlock(&sock_diag_table_mutex
);
93 EXPORT_SYMBOL_GPL(sock_diag_register_inet_compat
);
95 void sock_diag_unregister_inet_compat(int (*fn
)(struct sk_buff
*skb
, struct nlmsghdr
*nlh
))
97 mutex_lock(&sock_diag_table_mutex
);
98 inet_rcv_compat
= NULL
;
99 mutex_unlock(&sock_diag_table_mutex
);
101 EXPORT_SYMBOL_GPL(sock_diag_unregister_inet_compat
);
103 int sock_diag_register(const struct sock_diag_handler
*hndl
)
107 if (hndl
->family
>= AF_MAX
)
110 mutex_lock(&sock_diag_table_mutex
);
111 if (sock_diag_handlers
[hndl
->family
])
114 sock_diag_handlers
[hndl
->family
] = hndl
;
115 mutex_unlock(&sock_diag_table_mutex
);
119 EXPORT_SYMBOL_GPL(sock_diag_register
);
121 void sock_diag_unregister(const struct sock_diag_handler
*hnld
)
123 int family
= hnld
->family
;
125 if (family
>= AF_MAX
)
128 mutex_lock(&sock_diag_table_mutex
);
129 BUG_ON(sock_diag_handlers
[family
] != hnld
);
130 sock_diag_handlers
[family
] = NULL
;
131 mutex_unlock(&sock_diag_table_mutex
);
133 EXPORT_SYMBOL_GPL(sock_diag_unregister
);
135 static int __sock_diag_rcv_msg(struct sk_buff
*skb
, struct nlmsghdr
*nlh
)
138 struct sock_diag_req
*req
= nlmsg_data(nlh
);
139 const struct sock_diag_handler
*hndl
;
141 if (nlmsg_len(nlh
) < sizeof(*req
))
144 if (req
->sdiag_family
>= AF_MAX
)
147 if (sock_diag_handlers
[req
->sdiag_family
] == NULL
)
148 request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK
,
149 NETLINK_SOCK_DIAG
, req
->sdiag_family
);
151 mutex_lock(&sock_diag_table_mutex
);
152 hndl
= sock_diag_handlers
[req
->sdiag_family
];
156 err
= hndl
->dump(skb
, nlh
);
157 mutex_unlock(&sock_diag_table_mutex
);
162 static int sock_diag_rcv_msg(struct sk_buff
*skb
, struct nlmsghdr
*nlh
)
166 switch (nlh
->nlmsg_type
) {
167 case TCPDIAG_GETSOCK
:
168 case DCCPDIAG_GETSOCK
:
169 if (inet_rcv_compat
== NULL
)
170 request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK
,
171 NETLINK_SOCK_DIAG
, AF_INET
);
173 mutex_lock(&sock_diag_table_mutex
);
174 if (inet_rcv_compat
!= NULL
)
175 ret
= inet_rcv_compat(skb
, nlh
);
178 mutex_unlock(&sock_diag_table_mutex
);
181 case SOCK_DIAG_BY_FAMILY
:
182 return __sock_diag_rcv_msg(skb
, nlh
);
188 static DEFINE_MUTEX(sock_diag_mutex
);
190 static void sock_diag_rcv(struct sk_buff
*skb
)
192 mutex_lock(&sock_diag_mutex
);
193 netlink_rcv_skb(skb
, &sock_diag_rcv_msg
);
194 mutex_unlock(&sock_diag_mutex
);
197 static int __net_init
diag_net_init(struct net
*net
)
199 struct netlink_kernel_cfg cfg
= {
200 .input
= sock_diag_rcv
,
203 net
->diag_nlsk
= netlink_kernel_create(net
, NETLINK_SOCK_DIAG
, &cfg
);
204 return net
->diag_nlsk
== NULL
? -ENOMEM
: 0;
207 static void __net_exit
diag_net_exit(struct net
*net
)
209 netlink_kernel_release(net
->diag_nlsk
);
210 net
->diag_nlsk
= NULL
;
213 static struct pernet_operations diag_net_ops
= {
214 .init
= diag_net_init
,
215 .exit
= diag_net_exit
,
218 static int __init
sock_diag_init(void)
220 return register_pernet_subsys(&diag_net_ops
);
223 static void __exit
sock_diag_exit(void)
225 unregister_pernet_subsys(&diag_net_ops
);
228 module_init(sock_diag_init
);
229 module_exit(sock_diag_exit
);
230 MODULE_LICENSE("GPL");
231 MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK
, NETLINK_SOCK_DIAG
);