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>
7 #include <linux/rtnetlink.h>
10 #include <linux/inet_diag.h>
11 #include <linux/sock_diag.h>
13 static struct sock_diag_handler
*sock_diag_handlers
[AF_MAX
];
14 static int (*inet_rcv_compat
)(struct sk_buff
*skb
, struct nlmsghdr
*nlh
);
15 static DEFINE_MUTEX(sock_diag_table_mutex
);
17 int sock_diag_check_cookie(void *sk
, __u32
*cookie
)
19 if ((cookie
[0] != INET_DIAG_NOCOOKIE
||
20 cookie
[1] != INET_DIAG_NOCOOKIE
) &&
21 ((u32
)(unsigned long)sk
!= cookie
[0] ||
22 (u32
)((((unsigned long)sk
) >> 31) >> 1) != cookie
[1]))
27 EXPORT_SYMBOL_GPL(sock_diag_check_cookie
);
29 void sock_diag_save_cookie(void *sk
, __u32
*cookie
)
31 cookie
[0] = (u32
)(unsigned long)sk
;
32 cookie
[1] = (u32
)(((unsigned long)sk
>> 31) >> 1);
34 EXPORT_SYMBOL_GPL(sock_diag_save_cookie
);
36 int sock_diag_put_meminfo(struct sock
*sk
, struct sk_buff
*skb
, int attrtype
)
40 mem
= RTA_DATA(__RTA_PUT(skb
, attrtype
, SK_MEMINFO_VARS
* sizeof(__u32
)));
42 mem
[SK_MEMINFO_RMEM_ALLOC
] = sk_rmem_alloc_get(sk
);
43 mem
[SK_MEMINFO_RCVBUF
] = sk
->sk_rcvbuf
;
44 mem
[SK_MEMINFO_WMEM_ALLOC
] = sk_wmem_alloc_get(sk
);
45 mem
[SK_MEMINFO_SNDBUF
] = sk
->sk_sndbuf
;
46 mem
[SK_MEMINFO_FWD_ALLOC
] = sk
->sk_forward_alloc
;
47 mem
[SK_MEMINFO_WMEM_QUEUED
] = sk
->sk_wmem_queued
;
48 mem
[SK_MEMINFO_OPTMEM
] = atomic_read(&sk
->sk_omem_alloc
);
55 EXPORT_SYMBOL_GPL(sock_diag_put_meminfo
);
57 void sock_diag_register_inet_compat(int (*fn
)(struct sk_buff
*skb
, struct nlmsghdr
*nlh
))
59 mutex_lock(&sock_diag_table_mutex
);
61 mutex_unlock(&sock_diag_table_mutex
);
63 EXPORT_SYMBOL_GPL(sock_diag_register_inet_compat
);
65 void sock_diag_unregister_inet_compat(int (*fn
)(struct sk_buff
*skb
, struct nlmsghdr
*nlh
))
67 mutex_lock(&sock_diag_table_mutex
);
68 inet_rcv_compat
= NULL
;
69 mutex_unlock(&sock_diag_table_mutex
);
71 EXPORT_SYMBOL_GPL(sock_diag_unregister_inet_compat
);
73 int sock_diag_register(struct sock_diag_handler
*hndl
)
77 if (hndl
->family
>= AF_MAX
)
80 mutex_lock(&sock_diag_table_mutex
);
81 if (sock_diag_handlers
[hndl
->family
])
84 sock_diag_handlers
[hndl
->family
] = hndl
;
85 mutex_unlock(&sock_diag_table_mutex
);
89 EXPORT_SYMBOL_GPL(sock_diag_register
);
91 void sock_diag_unregister(struct sock_diag_handler
*hnld
)
93 int family
= hnld
->family
;
98 mutex_lock(&sock_diag_table_mutex
);
99 BUG_ON(sock_diag_handlers
[family
] != hnld
);
100 sock_diag_handlers
[family
] = NULL
;
101 mutex_unlock(&sock_diag_table_mutex
);
103 EXPORT_SYMBOL_GPL(sock_diag_unregister
);
105 static inline struct sock_diag_handler
*sock_diag_lock_handler(int family
)
107 if (sock_diag_handlers
[family
] == NULL
)
108 request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK
,
109 NETLINK_SOCK_DIAG
, family
);
111 mutex_lock(&sock_diag_table_mutex
);
112 return sock_diag_handlers
[family
];
115 static inline void sock_diag_unlock_handler(struct sock_diag_handler
*h
)
117 mutex_unlock(&sock_diag_table_mutex
);
120 static int __sock_diag_rcv_msg(struct sk_buff
*skb
, struct nlmsghdr
*nlh
)
123 struct sock_diag_req
*req
= NLMSG_DATA(nlh
);
124 struct sock_diag_handler
*hndl
;
126 if (nlmsg_len(nlh
) < sizeof(*req
))
129 hndl
= sock_diag_lock_handler(req
->sdiag_family
);
133 err
= hndl
->dump(skb
, nlh
);
134 sock_diag_unlock_handler(hndl
);
139 static int sock_diag_rcv_msg(struct sk_buff
*skb
, struct nlmsghdr
*nlh
)
143 switch (nlh
->nlmsg_type
) {
144 case TCPDIAG_GETSOCK
:
145 case DCCPDIAG_GETSOCK
:
146 if (inet_rcv_compat
== NULL
)
147 request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK
,
148 NETLINK_SOCK_DIAG
, AF_INET
);
150 mutex_lock(&sock_diag_table_mutex
);
151 if (inet_rcv_compat
!= NULL
)
152 ret
= inet_rcv_compat(skb
, nlh
);
155 mutex_unlock(&sock_diag_table_mutex
);
158 case SOCK_DIAG_BY_FAMILY
:
159 return __sock_diag_rcv_msg(skb
, nlh
);
165 static DEFINE_MUTEX(sock_diag_mutex
);
167 static void sock_diag_rcv(struct sk_buff
*skb
)
169 mutex_lock(&sock_diag_mutex
);
170 netlink_rcv_skb(skb
, &sock_diag_rcv_msg
);
171 mutex_unlock(&sock_diag_mutex
);
174 struct sock
*sock_diag_nlsk
;
175 EXPORT_SYMBOL_GPL(sock_diag_nlsk
);
177 static int __init
sock_diag_init(void)
179 sock_diag_nlsk
= netlink_kernel_create(&init_net
, NETLINK_SOCK_DIAG
, 0,
180 sock_diag_rcv
, NULL
, THIS_MODULE
);
181 return sock_diag_nlsk
== NULL
? -ENOMEM
: 0;
184 static void __exit
sock_diag_exit(void)
186 netlink_kernel_release(sock_diag_nlsk
);
189 module_init(sock_diag_init
);
190 module_exit(sock_diag_exit
);
191 MODULE_LICENSE("GPL");
192 MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK
, NETLINK_SOCK_DIAG
);