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 void sock_diag_register_inet_compat(int (*fn
)(struct sk_buff
*skb
, struct nlmsghdr
*nlh
))
54 mutex_lock(&sock_diag_table_mutex
);
56 mutex_unlock(&sock_diag_table_mutex
);
58 EXPORT_SYMBOL_GPL(sock_diag_register_inet_compat
);
60 void sock_diag_unregister_inet_compat(int (*fn
)(struct sk_buff
*skb
, struct nlmsghdr
*nlh
))
62 mutex_lock(&sock_diag_table_mutex
);
63 inet_rcv_compat
= NULL
;
64 mutex_unlock(&sock_diag_table_mutex
);
66 EXPORT_SYMBOL_GPL(sock_diag_unregister_inet_compat
);
68 int sock_diag_register(const struct sock_diag_handler
*hndl
)
72 if (hndl
->family
>= AF_MAX
)
75 mutex_lock(&sock_diag_table_mutex
);
76 if (sock_diag_handlers
[hndl
->family
])
79 sock_diag_handlers
[hndl
->family
] = hndl
;
80 mutex_unlock(&sock_diag_table_mutex
);
84 EXPORT_SYMBOL_GPL(sock_diag_register
);
86 void sock_diag_unregister(const struct sock_diag_handler
*hnld
)
88 int family
= hnld
->family
;
93 mutex_lock(&sock_diag_table_mutex
);
94 BUG_ON(sock_diag_handlers
[family
] != hnld
);
95 sock_diag_handlers
[family
] = NULL
;
96 mutex_unlock(&sock_diag_table_mutex
);
98 EXPORT_SYMBOL_GPL(sock_diag_unregister
);
100 static const inline struct sock_diag_handler
*sock_diag_lock_handler(int family
)
102 if (sock_diag_handlers
[family
] == NULL
)
103 request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK
,
104 NETLINK_SOCK_DIAG
, family
);
106 mutex_lock(&sock_diag_table_mutex
);
107 return sock_diag_handlers
[family
];
110 static inline void sock_diag_unlock_handler(const struct sock_diag_handler
*h
)
112 mutex_unlock(&sock_diag_table_mutex
);
115 static int __sock_diag_rcv_msg(struct sk_buff
*skb
, struct nlmsghdr
*nlh
)
118 struct sock_diag_req
*req
= nlmsg_data(nlh
);
119 const struct sock_diag_handler
*hndl
;
121 if (nlmsg_len(nlh
) < sizeof(*req
))
124 hndl
= sock_diag_lock_handler(req
->sdiag_family
);
128 err
= hndl
->dump(skb
, nlh
);
129 sock_diag_unlock_handler(hndl
);
134 static int sock_diag_rcv_msg(struct sk_buff
*skb
, struct nlmsghdr
*nlh
)
138 switch (nlh
->nlmsg_type
) {
139 case TCPDIAG_GETSOCK
:
140 case DCCPDIAG_GETSOCK
:
141 if (inet_rcv_compat
== NULL
)
142 request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK
,
143 NETLINK_SOCK_DIAG
, AF_INET
);
145 mutex_lock(&sock_diag_table_mutex
);
146 if (inet_rcv_compat
!= NULL
)
147 ret
= inet_rcv_compat(skb
, nlh
);
150 mutex_unlock(&sock_diag_table_mutex
);
153 case SOCK_DIAG_BY_FAMILY
:
154 return __sock_diag_rcv_msg(skb
, nlh
);
160 static DEFINE_MUTEX(sock_diag_mutex
);
162 static void sock_diag_rcv(struct sk_buff
*skb
)
164 mutex_lock(&sock_diag_mutex
);
165 netlink_rcv_skb(skb
, &sock_diag_rcv_msg
);
166 mutex_unlock(&sock_diag_mutex
);
169 static int __net_init
diag_net_init(struct net
*net
)
171 struct netlink_kernel_cfg cfg
= {
172 .input
= sock_diag_rcv
,
175 net
->diag_nlsk
= netlink_kernel_create(net
, NETLINK_SOCK_DIAG
, &cfg
);
176 return net
->diag_nlsk
== NULL
? -ENOMEM
: 0;
179 static void __net_exit
diag_net_exit(struct net
*net
)
181 netlink_kernel_release(net
->diag_nlsk
);
182 net
->diag_nlsk
= NULL
;
185 static struct pernet_operations diag_net_ops
= {
186 .init
= diag_net_init
,
187 .exit
= diag_net_exit
,
190 static int __init
sock_diag_init(void)
192 return register_pernet_subsys(&diag_net_ops
);
195 static void __exit
sock_diag_exit(void)
197 unregister_pernet_subsys(&diag_net_ops
);
200 module_init(sock_diag_init
);
201 module_exit(sock_diag_exit
);
202 MODULE_LICENSE("GPL");
203 MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK
, NETLINK_SOCK_DIAG
);