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 const 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
);
49 mem
[SK_MEMINFO_BACKLOG
] = sk
->sk_backlog
.len
;
56 EXPORT_SYMBOL_GPL(sock_diag_put_meminfo
);
58 void sock_diag_register_inet_compat(int (*fn
)(struct sk_buff
*skb
, struct nlmsghdr
*nlh
))
60 mutex_lock(&sock_diag_table_mutex
);
62 mutex_unlock(&sock_diag_table_mutex
);
64 EXPORT_SYMBOL_GPL(sock_diag_register_inet_compat
);
66 void sock_diag_unregister_inet_compat(int (*fn
)(struct sk_buff
*skb
, struct nlmsghdr
*nlh
))
68 mutex_lock(&sock_diag_table_mutex
);
69 inet_rcv_compat
= NULL
;
70 mutex_unlock(&sock_diag_table_mutex
);
72 EXPORT_SYMBOL_GPL(sock_diag_unregister_inet_compat
);
74 int sock_diag_register(const struct sock_diag_handler
*hndl
)
78 if (hndl
->family
>= AF_MAX
)
81 mutex_lock(&sock_diag_table_mutex
);
82 if (sock_diag_handlers
[hndl
->family
])
85 sock_diag_handlers
[hndl
->family
] = hndl
;
86 mutex_unlock(&sock_diag_table_mutex
);
90 EXPORT_SYMBOL_GPL(sock_diag_register
);
92 void sock_diag_unregister(const struct sock_diag_handler
*hnld
)
94 int family
= hnld
->family
;
99 mutex_lock(&sock_diag_table_mutex
);
100 BUG_ON(sock_diag_handlers
[family
] != hnld
);
101 sock_diag_handlers
[family
] = NULL
;
102 mutex_unlock(&sock_diag_table_mutex
);
104 EXPORT_SYMBOL_GPL(sock_diag_unregister
);
106 static const inline struct sock_diag_handler
*sock_diag_lock_handler(int family
)
108 if (sock_diag_handlers
[family
] == NULL
)
109 request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK
,
110 NETLINK_SOCK_DIAG
, family
);
112 mutex_lock(&sock_diag_table_mutex
);
113 return sock_diag_handlers
[family
];
116 static inline void sock_diag_unlock_handler(const struct sock_diag_handler
*h
)
118 mutex_unlock(&sock_diag_table_mutex
);
121 static int __sock_diag_rcv_msg(struct sk_buff
*skb
, struct nlmsghdr
*nlh
)
124 struct sock_diag_req
*req
= NLMSG_DATA(nlh
);
125 const struct sock_diag_handler
*hndl
;
127 if (nlmsg_len(nlh
) < sizeof(*req
))
130 hndl
= sock_diag_lock_handler(req
->sdiag_family
);
134 err
= hndl
->dump(skb
, nlh
);
135 sock_diag_unlock_handler(hndl
);
140 static int sock_diag_rcv_msg(struct sk_buff
*skb
, struct nlmsghdr
*nlh
)
144 switch (nlh
->nlmsg_type
) {
145 case TCPDIAG_GETSOCK
:
146 case DCCPDIAG_GETSOCK
:
147 if (inet_rcv_compat
== NULL
)
148 request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK
,
149 NETLINK_SOCK_DIAG
, AF_INET
);
151 mutex_lock(&sock_diag_table_mutex
);
152 if (inet_rcv_compat
!= NULL
)
153 ret
= inet_rcv_compat(skb
, nlh
);
156 mutex_unlock(&sock_diag_table_mutex
);
159 case SOCK_DIAG_BY_FAMILY
:
160 return __sock_diag_rcv_msg(skb
, nlh
);
166 static DEFINE_MUTEX(sock_diag_mutex
);
168 static void sock_diag_rcv(struct sk_buff
*skb
)
170 mutex_lock(&sock_diag_mutex
);
171 netlink_rcv_skb(skb
, &sock_diag_rcv_msg
);
172 mutex_unlock(&sock_diag_mutex
);
175 struct sock
*sock_diag_nlsk
;
176 EXPORT_SYMBOL_GPL(sock_diag_nlsk
);
178 static int __init
sock_diag_init(void)
180 sock_diag_nlsk
= netlink_kernel_create(&init_net
, NETLINK_SOCK_DIAG
, 0,
181 sock_diag_rcv
, NULL
, THIS_MODULE
);
182 return sock_diag_nlsk
== NULL
? -ENOMEM
: 0;
185 static void __exit
sock_diag_exit(void)
187 netlink_kernel_release(sock_diag_nlsk
);
190 module_init(sock_diag_init
);
191 module_exit(sock_diag_exit
);
192 MODULE_LICENSE("GPL");
193 MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK
, NETLINK_SOCK_DIAG
);