diff options
author | Pavel Emelyanov <xemul@parallels.com> | 2011-12-06 02:59:52 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-12-06 13:58:02 -0500 |
commit | 8ef874bfc7296fa206eea2ad1e8a426f576bf6f6 (patch) | |
tree | 1746f3acd306c55bff845a56e783ec6f1bd6fc6e /net | |
parent | a029fe26b67f815eddd432d9e702b9f2edbc2535 (diff) |
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>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/Makefile | 3 | ||||
-rw-r--r-- | net/core/sock_diag.c | 150 | ||||
-rw-r--r-- | net/ipv4/inet_diag.c | 105 |
3 files changed, 158 insertions, 100 deletions
diff --git a/net/core/Makefile b/net/core/Makefile index c4ecc864020..674641b13ae 100644 --- a/net/core/Makefile +++ b/net/core/Makefile | |||
@@ -8,7 +8,8 @@ obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \ | |||
8 | obj-$(CONFIG_SYSCTL) += sysctl_net_core.o | 8 | obj-$(CONFIG_SYSCTL) += sysctl_net_core.o |
9 | 9 | ||
10 | obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \ | 10 | obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \ |
11 | neighbour.o rtnetlink.o utils.o link_watch.o filter.o | 11 | neighbour.o rtnetlink.o utils.o link_watch.o filter.o \ |
12 | sock_diag.o | ||
12 | 13 | ||
13 | obj-$(CONFIG_XFRM) += flow.o | 14 | obj-$(CONFIG_XFRM) += flow.o |
14 | obj-y += net-sysfs.o | 15 | obj-y += net-sysfs.o |
diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c new file mode 100644 index 00000000000..fbaf01ce12f --- /dev/null +++ b/net/core/sock_diag.c | |||
@@ -0,0 +1,150 @@ | |||
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 | |||
8 | #include <linux/inet_diag.h> | ||
9 | #include <linux/sock_diag.h> | ||
10 | |||
11 | static struct sock_diag_handler *sock_diag_handlers[AF_MAX]; | ||
12 | static int (*inet_rcv_compat)(struct sk_buff *skb, struct nlmsghdr *nlh); | ||
13 | static DEFINE_MUTEX(sock_diag_table_mutex); | ||
14 | |||
15 | void sock_diag_register_inet_compat(int (*fn)(struct sk_buff *skb, struct nlmsghdr *nlh)) | ||
16 | { | ||
17 | mutex_lock(&sock_diag_table_mutex); | ||
18 | inet_rcv_compat = fn; | ||
19 | mutex_unlock(&sock_diag_table_mutex); | ||
20 | } | ||
21 | EXPORT_SYMBOL_GPL(sock_diag_register_inet_compat); | ||
22 | |||
23 | void sock_diag_unregister_inet_compat(int (*fn)(struct sk_buff *skb, struct nlmsghdr *nlh)) | ||
24 | { | ||
25 | mutex_lock(&sock_diag_table_mutex); | ||
26 | inet_rcv_compat = NULL; | ||
27 | mutex_unlock(&sock_diag_table_mutex); | ||
28 | } | ||
29 | EXPORT_SYMBOL_GPL(sock_diag_unregister_inet_compat); | ||
30 | |||
31 | int sock_diag_register(struct sock_diag_handler *hndl) | ||
32 | { | ||
33 | int err = 0; | ||
34 | |||
35 | if (hndl->family > AF_MAX) | ||
36 | return -EINVAL; | ||
37 | |||
38 | mutex_lock(&sock_diag_table_mutex); | ||
39 | if (sock_diag_handlers[hndl->family]) | ||
40 | err = -EBUSY; | ||
41 | else | ||
42 | sock_diag_handlers[hndl->family] = hndl; | ||
43 | mutex_unlock(&sock_diag_table_mutex); | ||
44 | |||
45 | return err; | ||
46 | } | ||
47 | EXPORT_SYMBOL_GPL(sock_diag_register); | ||
48 | |||
49 | void sock_diag_unregister(struct sock_diag_handler *hnld) | ||
50 | { | ||
51 | int family = hnld->family; | ||
52 | |||
53 | if (family > AF_MAX) | ||
54 | return; | ||
55 | |||
56 | mutex_lock(&sock_diag_table_mutex); | ||
57 | BUG_ON(sock_diag_handlers[family] != hnld); | ||
58 | sock_diag_handlers[family] = NULL; | ||
59 | mutex_unlock(&sock_diag_table_mutex); | ||
60 | } | ||
61 | EXPORT_SYMBOL_GPL(sock_diag_unregister); | ||
62 | |||
63 | static inline struct sock_diag_handler *sock_diag_lock_handler(int family) | ||
64 | { | ||
65 | if (sock_diag_handlers[family] == NULL) | ||
66 | request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK, | ||
67 | NETLINK_SOCK_DIAG, IPPROTO_IP); | ||
68 | |||
69 | mutex_lock(&sock_diag_table_mutex); | ||
70 | return sock_diag_handlers[family]; | ||
71 | } | ||
72 | |||
73 | static inline void sock_diag_unlock_handler(struct sock_diag_handler *h) | ||
74 | { | ||
75 | mutex_unlock(&sock_diag_table_mutex); | ||
76 | } | ||
77 | |||
78 | static int __sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | ||
79 | { | ||
80 | int err; | ||
81 | struct sock_diag_req *req = NLMSG_DATA(nlh); | ||
82 | struct sock_diag_handler *hndl; | ||
83 | |||
84 | if (nlmsg_len(nlh) < sizeof(*req)) | ||
85 | return -EINVAL; | ||
86 | |||
87 | hndl = sock_diag_lock_handler(req->sdiag_family); | ||
88 | if (hndl == NULL) | ||
89 | err = -ENOENT; | ||
90 | else | ||
91 | err = hndl->dump(skb, nlh); | ||
92 | sock_diag_unlock_handler(hndl); | ||
93 | |||
94 | return err; | ||
95 | } | ||
96 | |||
97 | static int sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | ||
98 | { | ||
99 | int ret; | ||
100 | |||
101 | switch (nlh->nlmsg_type) { | ||
102 | case TCPDIAG_GETSOCK: | ||
103 | case DCCPDIAG_GETSOCK: | ||
104 | if (inet_rcv_compat == NULL) | ||
105 | request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK, | ||
106 | NETLINK_SOCK_DIAG, IPPROTO_IP); | ||
107 | |||
108 | mutex_lock(&sock_diag_table_mutex); | ||
109 | if (inet_rcv_compat != NULL) | ||
110 | ret = inet_rcv_compat(skb, nlh); | ||
111 | else | ||
112 | ret = -EOPNOTSUPP; | ||
113 | mutex_unlock(&sock_diag_table_mutex); | ||
114 | |||
115 | return ret; | ||
116 | case SOCK_DIAG_BY_FAMILY: | ||
117 | return __sock_diag_rcv_msg(skb, nlh); | ||
118 | default: | ||
119 | return -EINVAL; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | static DEFINE_MUTEX(sock_diag_mutex); | ||
124 | |||
125 | static void sock_diag_rcv(struct sk_buff *skb) | ||
126 | { | ||
127 | mutex_lock(&sock_diag_mutex); | ||
128 | netlink_rcv_skb(skb, &sock_diag_rcv_msg); | ||
129 | mutex_unlock(&sock_diag_mutex); | ||
130 | } | ||
131 | |||
132 | struct sock *sock_diag_nlsk; | ||
133 | EXPORT_SYMBOL_GPL(sock_diag_nlsk); | ||
134 | |||
135 | static int __init sock_diag_init(void) | ||
136 | { | ||
137 | sock_diag_nlsk = netlink_kernel_create(&init_net, NETLINK_SOCK_DIAG, 0, | ||
138 | sock_diag_rcv, NULL, THIS_MODULE); | ||
139 | return sock_diag_nlsk == NULL ? -ENOMEM : 0; | ||
140 | } | ||
141 | |||
142 | static void __exit sock_diag_exit(void) | ||
143 | { | ||
144 | netlink_kernel_release(sock_diag_nlsk); | ||
145 | } | ||
146 | |||
147 | module_init(sock_diag_init); | ||
148 | module_exit(sock_diag_exit); | ||
149 | MODULE_LICENSE("GPL"); | ||
150 | MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_SOCK_DIAG); | ||
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 515dc7b6dae..b56b7ba8bee 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
@@ -46,8 +46,6 @@ struct inet_diag_entry { | |||
46 | u16 userlocks; | 46 | u16 userlocks; |
47 | }; | 47 | }; |
48 | 48 | ||
49 | static struct sock *sdiagnl; | ||
50 | |||
51 | #define INET_DIAG_PUT(skb, attrtype, attrlen) \ | 49 | #define INET_DIAG_PUT(skb, attrtype, attrlen) \ |
52 | RTA_DATA(__RTA_PUT(skb, attrtype, attrlen)) | 50 | RTA_DATA(__RTA_PUT(skb, attrtype, attrlen)) |
53 | 51 | ||
@@ -314,7 +312,7 @@ static int inet_diag_get_exact(struct sk_buff *in_skb, | |||
314 | kfree_skb(rep); | 312 | kfree_skb(rep); |
315 | goto out; | 313 | goto out; |
316 | } | 314 | } |
317 | err = netlink_unicast(sdiagnl, rep, NETLINK_CB(in_skb).pid, | 315 | err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid, |
318 | MSG_DONTWAIT); | 316 | MSG_DONTWAIT); |
319 | if (err > 0) | 317 | if (err > 0) |
320 | err = 0; | 318 | err = 0; |
@@ -931,7 +929,7 @@ static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
931 | return -EINVAL; | 929 | return -EINVAL; |
932 | } | 930 | } |
933 | 931 | ||
934 | return netlink_dump_start(sdiagnl, skb, nlh, | 932 | return netlink_dump_start(sock_diag_nlsk, skb, nlh, |
935 | inet_diag_dump_compat, NULL, 0); | 933 | inet_diag_dump_compat, NULL, 0); |
936 | } | 934 | } |
937 | 935 | ||
@@ -956,7 +954,7 @@ static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) | |||
956 | return -EINVAL; | 954 | return -EINVAL; |
957 | } | 955 | } |
958 | 956 | ||
959 | return netlink_dump_start(sdiagnl, skb, h, | 957 | return netlink_dump_start(sock_diag_nlsk, skb, h, |
960 | inet_diag_dump, NULL, 0); | 958 | inet_diag_dump, NULL, 0); |
961 | } | 959 | } |
962 | 960 | ||
@@ -973,91 +971,6 @@ static struct sock_diag_handler inet6_diag_handler = { | |||
973 | .dump = inet_diag_handler_dump, | 971 | .dump = inet_diag_handler_dump, |
974 | }; | 972 | }; |
975 | 973 | ||
976 | static struct sock_diag_handler *sock_diag_handlers[AF_MAX]; | ||
977 | static DEFINE_MUTEX(sock_diag_table_mutex); | ||
978 | |||
979 | int sock_diag_register(struct sock_diag_handler *hndl) | ||
980 | { | ||
981 | int err = 0; | ||
982 | |||
983 | if (hndl->family > AF_MAX) | ||
984 | return -EINVAL; | ||
985 | |||
986 | mutex_lock(&sock_diag_table_mutex); | ||
987 | if (sock_diag_handlers[hndl->family]) | ||
988 | err = -EBUSY; | ||
989 | else | ||
990 | sock_diag_handlers[hndl->family] = hndl; | ||
991 | mutex_unlock(&sock_diag_table_mutex); | ||
992 | |||
993 | return err; | ||
994 | } | ||
995 | |||
996 | void sock_diag_unregister(struct sock_diag_handler *hnld) | ||
997 | { | ||
998 | int family = hnld->family; | ||
999 | |||
1000 | if (family > AF_MAX) | ||
1001 | return; | ||
1002 | |||
1003 | mutex_lock(&sock_diag_table_mutex); | ||
1004 | BUG_ON(sock_diag_handlers[family] != hnld); | ||
1005 | sock_diag_handlers[family] = NULL; | ||
1006 | mutex_unlock(&sock_diag_table_mutex); | ||
1007 | } | ||
1008 | |||
1009 | static inline struct sock_diag_handler *sock_diag_lock_handler(int family) | ||
1010 | { | ||
1011 | mutex_lock(&sock_diag_table_mutex); | ||
1012 | return sock_diag_handlers[family]; | ||
1013 | } | ||
1014 | |||
1015 | static inline void sock_diag_unlock_handler(struct sock_diag_handler *h) | ||
1016 | { | ||
1017 | mutex_unlock(&sock_diag_table_mutex); | ||
1018 | } | ||
1019 | |||
1020 | static int __sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | ||
1021 | { | ||
1022 | int err; | ||
1023 | struct sock_diag_req *req = NLMSG_DATA(nlh); | ||
1024 | struct sock_diag_handler *hndl; | ||
1025 | |||
1026 | if (nlmsg_len(nlh) < sizeof(*req)) | ||
1027 | return -EINVAL; | ||
1028 | |||
1029 | hndl = sock_diag_lock_handler(req->sdiag_family); | ||
1030 | if (hndl == NULL) | ||
1031 | err = -ENOENT; | ||
1032 | else | ||
1033 | err = hndl->dump(skb, nlh); | ||
1034 | sock_diag_unlock_handler(hndl); | ||
1035 | |||
1036 | return err; | ||
1037 | } | ||
1038 | |||
1039 | static int sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | ||
1040 | { | ||
1041 | switch (nlh->nlmsg_type) { | ||
1042 | case TCPDIAG_GETSOCK: | ||
1043 | case DCCPDIAG_GETSOCK: | ||
1044 | return inet_diag_rcv_msg_compat(skb, nlh); | ||
1045 | case SOCK_DIAG_BY_FAMILY: | ||
1046 | return __sock_diag_rcv_msg(skb, nlh); | ||
1047 | default: | ||
1048 | return -EINVAL; | ||
1049 | } | ||
1050 | } | ||
1051 | |||
1052 | static DEFINE_MUTEX(sock_diag_mutex); | ||
1053 | |||
1054 | static void sock_diag_rcv(struct sk_buff *skb) | ||
1055 | { | ||
1056 | mutex_lock(&sock_diag_mutex); | ||
1057 | netlink_rcv_skb(skb, &sock_diag_rcv_msg); | ||
1058 | mutex_unlock(&sock_diag_mutex); | ||
1059 | } | ||
1060 | |||
1061 | int inet_diag_register(const struct inet_diag_handler *h) | 974 | int inet_diag_register(const struct inet_diag_handler *h) |
1062 | { | 975 | { |
1063 | const __u16 type = h->idiag_type; | 976 | const __u16 type = h->idiag_type; |
@@ -1101,11 +1014,6 @@ static int __init inet_diag_init(void) | |||
1101 | if (!inet_diag_table) | 1014 | if (!inet_diag_table) |
1102 | goto out; | 1015 | goto out; |
1103 | 1016 | ||
1104 | sdiagnl = netlink_kernel_create(&init_net, NETLINK_SOCK_DIAG, 0, | ||
1105 | sock_diag_rcv, NULL, THIS_MODULE); | ||
1106 | if (sdiagnl == NULL) | ||
1107 | goto out_free_table; | ||
1108 | |||
1109 | err = sock_diag_register(&inet_diag_handler); | 1017 | err = sock_diag_register(&inet_diag_handler); |
1110 | if (err) | 1018 | if (err) |
1111 | goto out_free_nl; | 1019 | goto out_free_nl; |
@@ -1114,14 +1022,13 @@ static int __init inet_diag_init(void) | |||
1114 | if (err) | 1022 | if (err) |
1115 | goto out_free_inet; | 1023 | goto out_free_inet; |
1116 | 1024 | ||
1025 | sock_diag_register_inet_compat(inet_diag_rcv_msg_compat); | ||
1117 | out: | 1026 | out: |
1118 | return err; | 1027 | return err; |
1119 | 1028 | ||
1120 | out_free_inet: | 1029 | out_free_inet: |
1121 | sock_diag_unregister(&inet_diag_handler); | 1030 | sock_diag_unregister(&inet_diag_handler); |
1122 | out_free_nl: | 1031 | out_free_nl: |
1123 | netlink_kernel_release(sdiagnl); | ||
1124 | out_free_table: | ||
1125 | kfree(inet_diag_table); | 1032 | kfree(inet_diag_table); |
1126 | goto out; | 1033 | goto out; |
1127 | } | 1034 | } |
@@ -1130,11 +1037,11 @@ static void __exit inet_diag_exit(void) | |||
1130 | { | 1037 | { |
1131 | sock_diag_unregister(&inet6_diag_handler); | 1038 | sock_diag_unregister(&inet6_diag_handler); |
1132 | sock_diag_unregister(&inet_diag_handler); | 1039 | sock_diag_unregister(&inet_diag_handler); |
1133 | netlink_kernel_release(sdiagnl); | 1040 | sock_diag_unregister_inet_compat(inet_diag_rcv_msg_compat); |
1134 | kfree(inet_diag_table); | 1041 | kfree(inet_diag_table); |
1135 | } | 1042 | } |
1136 | 1043 | ||
1137 | module_init(inet_diag_init); | 1044 | module_init(inet_diag_init); |
1138 | module_exit(inet_diag_exit); | 1045 | module_exit(inet_diag_exit); |
1139 | MODULE_LICENSE("GPL"); | 1046 | MODULE_LICENSE("GPL"); |
1140 | MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_SOCK_DIAG); | 1047 | MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 0); |