diff options
-rw-r--r-- | include/linux/net.h | 1 | ||||
-rw-r--r-- | include/net/sock.h | 1 | ||||
-rw-r--r-- | net/core/sock.c | 21 | ||||
-rw-r--r-- | net/core/sock_diag.c | 12 | ||||
-rw-r--r-- | net/ipv4/inet_diag.c | 3 | ||||
-rw-r--r-- | net/socket.c | 5 |
6 files changed, 33 insertions, 10 deletions
diff --git a/include/linux/net.h b/include/linux/net.h index 91216b16feb7..2a0391eea05c 100644 --- a/include/linux/net.h +++ b/include/linux/net.h | |||
@@ -222,6 +222,7 @@ enum { | |||
222 | int sock_wake_async(struct socket_wq *sk_wq, int how, int band); | 222 | int sock_wake_async(struct socket_wq *sk_wq, int how, int band); |
223 | int sock_register(const struct net_proto_family *fam); | 223 | int sock_register(const struct net_proto_family *fam); |
224 | void sock_unregister(int family); | 224 | void sock_unregister(int family); |
225 | bool sock_is_registered(int family); | ||
225 | int __sock_create(struct net *net, int family, int type, int proto, | 226 | int __sock_create(struct net *net, int family, int type, int proto, |
226 | struct socket **res, int kern); | 227 | struct socket **res, int kern); |
227 | int sock_create(int family, int type, int proto, struct socket **res); | 228 | int sock_create(int family, int type, int proto, struct socket **res); |
diff --git a/include/net/sock.h b/include/net/sock.h index 169c92afcafa..ae23f3b389ca 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -1137,6 +1137,7 @@ struct proto { | |||
1137 | 1137 | ||
1138 | int proto_register(struct proto *prot, int alloc_slab); | 1138 | int proto_register(struct proto *prot, int alloc_slab); |
1139 | void proto_unregister(struct proto *prot); | 1139 | void proto_unregister(struct proto *prot); |
1140 | int sock_load_diag_module(int family, int protocol); | ||
1140 | 1141 | ||
1141 | #ifdef SOCK_REFCNT_DEBUG | 1142 | #ifdef SOCK_REFCNT_DEBUG |
1142 | static inline void sk_refcnt_debug_inc(struct sock *sk) | 1143 | static inline void sk_refcnt_debug_inc(struct sock *sk) |
diff --git a/net/core/sock.c b/net/core/sock.c index c501499a04fe..85b0b64e7f9d 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -3261,6 +3261,27 @@ void proto_unregister(struct proto *prot) | |||
3261 | } | 3261 | } |
3262 | EXPORT_SYMBOL(proto_unregister); | 3262 | EXPORT_SYMBOL(proto_unregister); |
3263 | 3263 | ||
3264 | int sock_load_diag_module(int family, int protocol) | ||
3265 | { | ||
3266 | if (!protocol) { | ||
3267 | if (!sock_is_registered(family)) | ||
3268 | return -ENOENT; | ||
3269 | |||
3270 | return request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK, | ||
3271 | NETLINK_SOCK_DIAG, family); | ||
3272 | } | ||
3273 | |||
3274 | #ifdef CONFIG_INET | ||
3275 | if (family == AF_INET && | ||
3276 | !rcu_access_pointer(inet_protos[protocol])) | ||
3277 | return -ENOENT; | ||
3278 | #endif | ||
3279 | |||
3280 | return request_module("net-pf-%d-proto-%d-type-%d-%d", PF_NETLINK, | ||
3281 | NETLINK_SOCK_DIAG, family, protocol); | ||
3282 | } | ||
3283 | EXPORT_SYMBOL(sock_load_diag_module); | ||
3284 | |||
3264 | #ifdef CONFIG_PROC_FS | 3285 | #ifdef CONFIG_PROC_FS |
3265 | static void *proto_seq_start(struct seq_file *seq, loff_t *pos) | 3286 | static void *proto_seq_start(struct seq_file *seq, loff_t *pos) |
3266 | __acquires(proto_list_mutex) | 3287 | __acquires(proto_list_mutex) |
diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c index 146b50e30659..c37b5be7c5e4 100644 --- a/net/core/sock_diag.c +++ b/net/core/sock_diag.c | |||
@@ -220,8 +220,7 @@ static int __sock_diag_cmd(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
220 | return -EINVAL; | 220 | return -EINVAL; |
221 | 221 | ||
222 | if (sock_diag_handlers[req->sdiag_family] == NULL) | 222 | if (sock_diag_handlers[req->sdiag_family] == NULL) |
223 | request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK, | 223 | sock_load_diag_module(req->sdiag_family, 0); |
224 | NETLINK_SOCK_DIAG, req->sdiag_family); | ||
225 | 224 | ||
226 | mutex_lock(&sock_diag_table_mutex); | 225 | mutex_lock(&sock_diag_table_mutex); |
227 | hndl = sock_diag_handlers[req->sdiag_family]; | 226 | hndl = sock_diag_handlers[req->sdiag_family]; |
@@ -247,8 +246,7 @@ static int sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
247 | case TCPDIAG_GETSOCK: | 246 | case TCPDIAG_GETSOCK: |
248 | case DCCPDIAG_GETSOCK: | 247 | case DCCPDIAG_GETSOCK: |
249 | if (inet_rcv_compat == NULL) | 248 | if (inet_rcv_compat == NULL) |
250 | request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK, | 249 | sock_load_diag_module(AF_INET, 0); |
251 | NETLINK_SOCK_DIAG, AF_INET); | ||
252 | 250 | ||
253 | mutex_lock(&sock_diag_table_mutex); | 251 | mutex_lock(&sock_diag_table_mutex); |
254 | if (inet_rcv_compat != NULL) | 252 | if (inet_rcv_compat != NULL) |
@@ -281,14 +279,12 @@ static int sock_diag_bind(struct net *net, int group) | |||
281 | case SKNLGRP_INET_TCP_DESTROY: | 279 | case SKNLGRP_INET_TCP_DESTROY: |
282 | case SKNLGRP_INET_UDP_DESTROY: | 280 | case SKNLGRP_INET_UDP_DESTROY: |
283 | if (!sock_diag_handlers[AF_INET]) | 281 | if (!sock_diag_handlers[AF_INET]) |
284 | request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK, | 282 | sock_load_diag_module(AF_INET, 0); |
285 | NETLINK_SOCK_DIAG, AF_INET); | ||
286 | break; | 283 | break; |
287 | case SKNLGRP_INET6_TCP_DESTROY: | 284 | case SKNLGRP_INET6_TCP_DESTROY: |
288 | case SKNLGRP_INET6_UDP_DESTROY: | 285 | case SKNLGRP_INET6_UDP_DESTROY: |
289 | if (!sock_diag_handlers[AF_INET6]) | 286 | if (!sock_diag_handlers[AF_INET6]) |
290 | request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK, | 287 | sock_load_diag_module(AF_INET6, 0); |
291 | NETLINK_SOCK_DIAG, AF_INET6); | ||
292 | break; | 288 | break; |
293 | } | 289 | } |
294 | return 0; | 290 | return 0; |
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index a383f299ce24..4e5bc4b2f14e 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
@@ -53,8 +53,7 @@ static DEFINE_MUTEX(inet_diag_table_mutex); | |||
53 | static const struct inet_diag_handler *inet_diag_lock_handler(int proto) | 53 | static const struct inet_diag_handler *inet_diag_lock_handler(int proto) |
54 | { | 54 | { |
55 | if (!inet_diag_table[proto]) | 55 | if (!inet_diag_table[proto]) |
56 | request_module("net-pf-%d-proto-%d-type-%d-%d", PF_NETLINK, | 56 | sock_load_diag_module(AF_INET, proto); |
57 | NETLINK_SOCK_DIAG, AF_INET, proto); | ||
58 | 57 | ||
59 | mutex_lock(&inet_diag_table_mutex); | 58 | mutex_lock(&inet_diag_table_mutex); |
60 | if (!inet_diag_table[proto]) | 59 | if (!inet_diag_table[proto]) |
diff --git a/net/socket.c b/net/socket.c index a93c99b518ca..08847c3b8c39 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -2587,6 +2587,11 @@ void sock_unregister(int family) | |||
2587 | } | 2587 | } |
2588 | EXPORT_SYMBOL(sock_unregister); | 2588 | EXPORT_SYMBOL(sock_unregister); |
2589 | 2589 | ||
2590 | bool sock_is_registered(int family) | ||
2591 | { | ||
2592 | return family < NPROTO && rcu_access_pointer(net_families[family]); | ||
2593 | } | ||
2594 | |||
2590 | static int __init sock_init(void) | 2595 | static int __init sock_init(void) |
2591 | { | 2596 | { |
2592 | int err; | 2597 | int err; |