-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sock_diag: Move the sock_ code to net/core/
This patch moves the sock_ code from inet_diag.c to generic sock_diag.c file and provides necessary request_module-s calls and a pointer on inet_diag_compat dumping routine. Signed-off-by: Pavel Emelyanov <xemul@parallels.com> Signed-off-by: David S. Miller <davem@davemloft.net>
- Loading branch information
Pavel Emelyanov
authored and
David S. Miller
committed
Dec 6, 2011
1 parent
a029fe2
commit 8ef874b
Showing
3 changed files
with
158 additions
and
100 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
#include <linux/mutex.h> | ||
#include <linux/socket.h> | ||
#include <linux/skbuff.h> | ||
#include <net/netlink.h> | ||
#include <net/net_namespace.h> | ||
#include <linux/module.h> | ||
|
||
#include <linux/inet_diag.h> | ||
#include <linux/sock_diag.h> | ||
|
||
static struct sock_diag_handler *sock_diag_handlers[AF_MAX]; | ||
static int (*inet_rcv_compat)(struct sk_buff *skb, struct nlmsghdr *nlh); | ||
static DEFINE_MUTEX(sock_diag_table_mutex); | ||
|
||
void sock_diag_register_inet_compat(int (*fn)(struct sk_buff *skb, struct nlmsghdr *nlh)) | ||
{ | ||
mutex_lock(&sock_diag_table_mutex); | ||
inet_rcv_compat = fn; | ||
mutex_unlock(&sock_diag_table_mutex); | ||
} | ||
EXPORT_SYMBOL_GPL(sock_diag_register_inet_compat); | ||
|
||
void sock_diag_unregister_inet_compat(int (*fn)(struct sk_buff *skb, struct nlmsghdr *nlh)) | ||
{ | ||
mutex_lock(&sock_diag_table_mutex); | ||
inet_rcv_compat = NULL; | ||
mutex_unlock(&sock_diag_table_mutex); | ||
} | ||
EXPORT_SYMBOL_GPL(sock_diag_unregister_inet_compat); | ||
|
||
int sock_diag_register(struct sock_diag_handler *hndl) | ||
{ | ||
int err = 0; | ||
|
||
if (hndl->family > AF_MAX) | ||
return -EINVAL; | ||
|
||
mutex_lock(&sock_diag_table_mutex); | ||
if (sock_diag_handlers[hndl->family]) | ||
err = -EBUSY; | ||
else | ||
sock_diag_handlers[hndl->family] = hndl; | ||
mutex_unlock(&sock_diag_table_mutex); | ||
|
||
return err; | ||
} | ||
EXPORT_SYMBOL_GPL(sock_diag_register); | ||
|
||
void sock_diag_unregister(struct sock_diag_handler *hnld) | ||
{ | ||
int family = hnld->family; | ||
|
||
if (family > AF_MAX) | ||
return; | ||
|
||
mutex_lock(&sock_diag_table_mutex); | ||
BUG_ON(sock_diag_handlers[family] != hnld); | ||
sock_diag_handlers[family] = NULL; | ||
mutex_unlock(&sock_diag_table_mutex); | ||
} | ||
EXPORT_SYMBOL_GPL(sock_diag_unregister); | ||
|
||
static inline struct sock_diag_handler *sock_diag_lock_handler(int family) | ||
{ | ||
if (sock_diag_handlers[family] == NULL) | ||
request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK, | ||
NETLINK_SOCK_DIAG, IPPROTO_IP); | ||
|
||
mutex_lock(&sock_diag_table_mutex); | ||
return sock_diag_handlers[family]; | ||
} | ||
|
||
static inline void sock_diag_unlock_handler(struct sock_diag_handler *h) | ||
{ | ||
mutex_unlock(&sock_diag_table_mutex); | ||
} | ||
|
||
static int __sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | ||
{ | ||
int err; | ||
struct sock_diag_req *req = NLMSG_DATA(nlh); | ||
struct sock_diag_handler *hndl; | ||
|
||
if (nlmsg_len(nlh) < sizeof(*req)) | ||
return -EINVAL; | ||
|
||
hndl = sock_diag_lock_handler(req->sdiag_family); | ||
if (hndl == NULL) | ||
err = -ENOENT; | ||
else | ||
err = hndl->dump(skb, nlh); | ||
sock_diag_unlock_handler(hndl); | ||
|
||
return err; | ||
} | ||
|
||
static int sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | ||
{ | ||
int ret; | ||
|
||
switch (nlh->nlmsg_type) { | ||
case TCPDIAG_GETSOCK: | ||
case DCCPDIAG_GETSOCK: | ||
if (inet_rcv_compat == NULL) | ||
request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK, | ||
NETLINK_SOCK_DIAG, IPPROTO_IP); | ||
|
||
mutex_lock(&sock_diag_table_mutex); | ||
if (inet_rcv_compat != NULL) | ||
ret = inet_rcv_compat(skb, nlh); | ||
else | ||
ret = -EOPNOTSUPP; | ||
mutex_unlock(&sock_diag_table_mutex); | ||
|
||
return ret; | ||
case SOCK_DIAG_BY_FAMILY: | ||
return __sock_diag_rcv_msg(skb, nlh); | ||
default: | ||
return -EINVAL; | ||
} | ||
} | ||
|
||
static DEFINE_MUTEX(sock_diag_mutex); | ||
|
||
static void sock_diag_rcv(struct sk_buff *skb) | ||
{ | ||
mutex_lock(&sock_diag_mutex); | ||
netlink_rcv_skb(skb, &sock_diag_rcv_msg); | ||
mutex_unlock(&sock_diag_mutex); | ||
} | ||
|
||
struct sock *sock_diag_nlsk; | ||
EXPORT_SYMBOL_GPL(sock_diag_nlsk); | ||
|
||
static int __init sock_diag_init(void) | ||
{ | ||
sock_diag_nlsk = netlink_kernel_create(&init_net, NETLINK_SOCK_DIAG, 0, | ||
sock_diag_rcv, NULL, THIS_MODULE); | ||
return sock_diag_nlsk == NULL ? -ENOMEM : 0; | ||
} | ||
|
||
static void __exit sock_diag_exit(void) | ||
{ | ||
netlink_kernel_release(sock_diag_nlsk); | ||
} | ||
|
||
module_init(sock_diag_init); | ||
module_exit(sock_diag_exit); | ||
MODULE_LICENSE("GPL"); | ||
MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_SOCK_DIAG); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters