aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/net.h1
-rw-r--r--include/net/sock.h1
-rw-r--r--net/core/sock.c21
-rw-r--r--net/core/sock_diag.c12
-rw-r--r--net/ipv4/inet_diag.c3
-rw-r--r--net/socket.c5
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 {
222int sock_wake_async(struct socket_wq *sk_wq, int how, int band); 222int sock_wake_async(struct socket_wq *sk_wq, int how, int band);
223int sock_register(const struct net_proto_family *fam); 223int sock_register(const struct net_proto_family *fam);
224void sock_unregister(int family); 224void sock_unregister(int family);
225bool sock_is_registered(int family);
225int __sock_create(struct net *net, int family, int type, int proto, 226int __sock_create(struct net *net, int family, int type, int proto,
226 struct socket **res, int kern); 227 struct socket **res, int kern);
227int sock_create(int family, int type, int proto, struct socket **res); 228int 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
1138int proto_register(struct proto *prot, int alloc_slab); 1138int proto_register(struct proto *prot, int alloc_slab);
1139void proto_unregister(struct proto *prot); 1139void proto_unregister(struct proto *prot);
1140int sock_load_diag_module(int family, int protocol);
1140 1141
1141#ifdef SOCK_REFCNT_DEBUG 1142#ifdef SOCK_REFCNT_DEBUG
1142static inline void sk_refcnt_debug_inc(struct sock *sk) 1143static 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}
3262EXPORT_SYMBOL(proto_unregister); 3262EXPORT_SYMBOL(proto_unregister);
3263 3263
3264int 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}
3283EXPORT_SYMBOL(sock_load_diag_module);
3284
3264#ifdef CONFIG_PROC_FS 3285#ifdef CONFIG_PROC_FS
3265static void *proto_seq_start(struct seq_file *seq, loff_t *pos) 3286static 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);
53static const struct inet_diag_handler *inet_diag_lock_handler(int proto) 53static 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}
2588EXPORT_SYMBOL(sock_unregister); 2588EXPORT_SYMBOL(sock_unregister);
2589 2589
2590bool sock_is_registered(int family)
2591{
2592 return family < NPROTO && rcu_access_pointer(net_families[family]);
2593}
2594
2590static int __init sock_init(void) 2595static int __init sock_init(void)
2591{ 2596{
2592 int err; 2597 int err;