diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/core/rtnetlink.c | 12 | ||||
-rw-r--r-- | net/decnet/netfilter/dn_rtmsg.c | 14 | ||||
-rw-r--r-- | net/ipv4/fib_frontend.c | 9 | ||||
-rw-r--r-- | net/ipv4/inet_diag.c | 12 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_queue.c | 17 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_queue.c | 19 | ||||
-rw-r--r-- | net/netfilter/nfnetlink.c | 12 | ||||
-rw-r--r-- | net/netlink/af_netlink.c | 152 | ||||
-rw-r--r-- | net/netlink/genetlink.c | 12 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 13 |
10 files changed, 84 insertions, 188 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 471d2d9f8eae..1072d16696c3 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -1312,15 +1312,11 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
1312 | return doit(skb, nlh, (void *)&rta_buf[0]); | 1312 | return doit(skb, nlh, (void *)&rta_buf[0]); |
1313 | } | 1313 | } |
1314 | 1314 | ||
1315 | static void rtnetlink_rcv(struct sock *sk, int len) | 1315 | static void rtnetlink_rcv(struct sk_buff *skb) |
1316 | { | 1316 | { |
1317 | unsigned int qlen = 0; | 1317 | rtnl_lock(); |
1318 | 1318 | netlink_rcv_skb(skb, &rtnetlink_rcv_msg); | |
1319 | do { | 1319 | rtnl_unlock(); |
1320 | rtnl_lock(); | ||
1321 | qlen = netlink_run_queue(sk, qlen, &rtnetlink_rcv_msg); | ||
1322 | rtnl_unlock(); | ||
1323 | } while (qlen); | ||
1324 | } | 1320 | } |
1325 | 1321 | ||
1326 | static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr) | 1322 | static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr) |
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c index ebb38feb4df3..f7fba7721e63 100644 --- a/net/decnet/netfilter/dn_rtmsg.c +++ b/net/decnet/netfilter/dn_rtmsg.c | |||
@@ -115,17 +115,6 @@ static inline void dnrmg_receive_user_skb(struct sk_buff *skb) | |||
115 | RCV_SKB_FAIL(-EINVAL); | 115 | RCV_SKB_FAIL(-EINVAL); |
116 | } | 116 | } |
117 | 117 | ||
118 | static void dnrmg_receive_user_sk(struct sock *sk, int len) | ||
119 | { | ||
120 | struct sk_buff *skb; | ||
121 | unsigned int qlen = skb_queue_len(&sk->sk_receive_queue); | ||
122 | |||
123 | for (; qlen && (skb = skb_dequeue(&sk->sk_receive_queue)); qlen--) { | ||
124 | dnrmg_receive_user_skb(skb); | ||
125 | kfree_skb(skb); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | static struct nf_hook_ops dnrmg_ops = { | 118 | static struct nf_hook_ops dnrmg_ops = { |
130 | .hook = dnrmg_hook, | 119 | .hook = dnrmg_hook, |
131 | .pf = PF_DECnet, | 120 | .pf = PF_DECnet, |
@@ -139,7 +128,8 @@ static int __init dn_rtmsg_init(void) | |||
139 | 128 | ||
140 | dnrmg = netlink_kernel_create(&init_net, | 129 | dnrmg = netlink_kernel_create(&init_net, |
141 | NETLINK_DNRTMSG, DNRNG_NLGRP_MAX, | 130 | NETLINK_DNRTMSG, DNRNG_NLGRP_MAX, |
142 | dnrmg_receive_user_sk, NULL, THIS_MODULE); | 131 | dnrmg_receive_user_skb, |
132 | NULL, THIS_MODULE); | ||
143 | if (dnrmg == NULL) { | 133 | if (dnrmg == NULL) { |
144 | printk(KERN_ERR "dn_rtmsg: Cannot create netlink socket"); | 134 | printk(KERN_ERR "dn_rtmsg: Cannot create netlink socket"); |
145 | return -ENOMEM; | 135 | return -ENOMEM; |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index f823ca34cb12..a5cba2349605 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -62,6 +62,9 @@ static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ]; | |||
62 | #define FIB_TABLE_HASHSZ 256 | 62 | #define FIB_TABLE_HASHSZ 256 |
63 | static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ]; | 63 | static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ]; |
64 | 64 | ||
65 | static struct sock *fibnl = NULL; | ||
66 | |||
67 | |||
65 | struct fib_table *fib_new_table(u32 id) | 68 | struct fib_table *fib_new_table(u32 id) |
66 | { | 69 | { |
67 | struct fib_table *tb; | 70 | struct fib_table *tb; |
@@ -811,13 +814,13 @@ static void nl_fib_input(struct sock *sk, int len) | |||
811 | pid = NETLINK_CB(skb).pid; /* pid of sending process */ | 814 | pid = NETLINK_CB(skb).pid; /* pid of sending process */ |
812 | NETLINK_CB(skb).pid = 0; /* from kernel */ | 815 | NETLINK_CB(skb).pid = 0; /* from kernel */ |
813 | NETLINK_CB(skb).dst_group = 0; /* unicast */ | 816 | NETLINK_CB(skb).dst_group = 0; /* unicast */ |
814 | netlink_unicast(sk, skb, pid, MSG_DONTWAIT); | 817 | netlink_unicast(fibnl, skb, pid, MSG_DONTWAIT); |
815 | } | 818 | } |
816 | 819 | ||
817 | static void nl_fib_lookup_init(void) | 820 | static void nl_fib_lookup_init(void) |
818 | { | 821 | { |
819 | netlink_kernel_create(&init_net, NETLINK_FIB_LOOKUP, 0, nl_fib_input, | 822 | fibnl = netlink_kernel_create(&init_net, NETLINK_FIB_LOOKUP, 0, |
820 | NULL, THIS_MODULE); | 823 | nl_fib_input, NULL, THIS_MODULE); |
821 | } | 824 | } |
822 | 825 | ||
823 | static void fib_disable_ip(struct net_device *dev, int force) | 826 | static void fib_disable_ip(struct net_device *dev, int force) |
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index b04a6ee5a9a1..7eb83ebed2ec 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
@@ -839,15 +839,11 @@ static int inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
839 | 839 | ||
840 | static DEFINE_MUTEX(inet_diag_mutex); | 840 | static DEFINE_MUTEX(inet_diag_mutex); |
841 | 841 | ||
842 | static void inet_diag_rcv(struct sock *sk, int len) | 842 | static void inet_diag_rcv(struct sk_buff *skb) |
843 | { | 843 | { |
844 | unsigned int qlen = 0; | 844 | mutex_lock(&inet_diag_mutex); |
845 | 845 | netlink_rcv_skb(skb, &inet_diag_rcv_msg); | |
846 | do { | 846 | mutex_unlock(&inet_diag_mutex); |
847 | mutex_lock(&inet_diag_mutex); | ||
848 | qlen = netlink_run_queue(sk, qlen, &inet_diag_rcv_msg); | ||
849 | mutex_unlock(&inet_diag_mutex); | ||
850 | } while (qlen); | ||
851 | } | 847 | } |
852 | 848 | ||
853 | static DEFINE_SPINLOCK(inet_diag_register_lock); | 849 | static DEFINE_SPINLOCK(inet_diag_register_lock); |
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index aaa3f5c56761..23cbfc7c80fd 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c | |||
@@ -475,7 +475,7 @@ ipq_dev_drop(int ifindex) | |||
475 | #define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0) | 475 | #define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0) |
476 | 476 | ||
477 | static inline void | 477 | static inline void |
478 | ipq_rcv_skb(struct sk_buff *skb) | 478 | __ipq_rcv_skb(struct sk_buff *skb) |
479 | { | 479 | { |
480 | int status, type, pid, flags, nlmsglen, skblen; | 480 | int status, type, pid, flags, nlmsglen, skblen; |
481 | struct nlmsghdr *nlh; | 481 | struct nlmsghdr *nlh; |
@@ -533,19 +533,10 @@ ipq_rcv_skb(struct sk_buff *skb) | |||
533 | } | 533 | } |
534 | 534 | ||
535 | static void | 535 | static void |
536 | ipq_rcv_sk(struct sock *sk, int len) | 536 | ipq_rcv_skb(struct sk_buff *skb) |
537 | { | 537 | { |
538 | struct sk_buff *skb; | ||
539 | unsigned int qlen; | ||
540 | |||
541 | mutex_lock(&ipqnl_mutex); | 538 | mutex_lock(&ipqnl_mutex); |
542 | 539 | __ipq_rcv_skb(skb); | |
543 | for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) { | ||
544 | skb = skb_dequeue(&sk->sk_receive_queue); | ||
545 | ipq_rcv_skb(skb); | ||
546 | kfree_skb(skb); | ||
547 | } | ||
548 | |||
549 | mutex_unlock(&ipqnl_mutex); | 540 | mutex_unlock(&ipqnl_mutex); |
550 | } | 541 | } |
551 | 542 | ||
@@ -670,7 +661,7 @@ static int __init ip_queue_init(void) | |||
670 | 661 | ||
671 | netlink_register_notifier(&ipq_nl_notifier); | 662 | netlink_register_notifier(&ipq_nl_notifier); |
672 | ipqnl = netlink_kernel_create(&init_net, NETLINK_FIREWALL, 0, | 663 | ipqnl = netlink_kernel_create(&init_net, NETLINK_FIREWALL, 0, |
673 | ipq_rcv_sk, NULL, THIS_MODULE); | 664 | ipq_rcv_skb, NULL, THIS_MODULE); |
674 | if (ipqnl == NULL) { | 665 | if (ipqnl == NULL) { |
675 | printk(KERN_ERR "ip_queue: failed to create netlink socket\n"); | 666 | printk(KERN_ERR "ip_queue: failed to create netlink socket\n"); |
676 | goto cleanup_netlink_notifier; | 667 | goto cleanup_netlink_notifier; |
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index c75f467a8f51..0473145ac534 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -464,7 +464,7 @@ ipq_dev_drop(int ifindex) | |||
464 | #define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0) | 464 | #define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0) |
465 | 465 | ||
466 | static inline void | 466 | static inline void |
467 | ipq_rcv_skb(struct sk_buff *skb) | 467 | __ipq_rcv_skb(struct sk_buff *skb) |
468 | { | 468 | { |
469 | int status, type, pid, flags, nlmsglen, skblen; | 469 | int status, type, pid, flags, nlmsglen, skblen; |
470 | struct nlmsghdr *nlh; | 470 | struct nlmsghdr *nlh; |
@@ -522,19 +522,10 @@ ipq_rcv_skb(struct sk_buff *skb) | |||
522 | } | 522 | } |
523 | 523 | ||
524 | static void | 524 | static void |
525 | ipq_rcv_sk(struct sock *sk, int len) | 525 | ipq_rcv_skb(struct sk_buff *skb) |
526 | { | 526 | { |
527 | struct sk_buff *skb; | ||
528 | unsigned int qlen; | ||
529 | |||
530 | mutex_lock(&ipqnl_mutex); | 527 | mutex_lock(&ipqnl_mutex); |
531 | 528 | __ipq_rcv_skb(skb); | |
532 | for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) { | ||
533 | skb = skb_dequeue(&sk->sk_receive_queue); | ||
534 | ipq_rcv_skb(skb); | ||
535 | kfree_skb(skb); | ||
536 | } | ||
537 | |||
538 | mutex_unlock(&ipqnl_mutex); | 529 | mutex_unlock(&ipqnl_mutex); |
539 | } | 530 | } |
540 | 531 | ||
@@ -658,8 +649,8 @@ static int __init ip6_queue_init(void) | |||
658 | struct proc_dir_entry *proc; | 649 | struct proc_dir_entry *proc; |
659 | 650 | ||
660 | netlink_register_notifier(&ipq_nl_notifier); | 651 | netlink_register_notifier(&ipq_nl_notifier); |
661 | ipqnl = netlink_kernel_create(&init_net, NETLINK_IP6_FW, 0, ipq_rcv_sk, | 652 | ipqnl = netlink_kernel_create(&init_net, NETLINK_IP6_FW, 0, |
662 | NULL, THIS_MODULE); | 653 | ipq_rcv_skb, NULL, THIS_MODULE); |
663 | if (ipqnl == NULL) { | 654 | if (ipqnl == NULL) { |
664 | printk(KERN_ERR "ip6_queue: failed to create netlink socket\n"); | 655 | printk(KERN_ERR "ip6_queue: failed to create netlink socket\n"); |
665 | goto cleanup_netlink_notifier; | 656 | goto cleanup_netlink_notifier; |
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 99775af19ff4..2128542995f7 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c | |||
@@ -169,15 +169,11 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
169 | } | 169 | } |
170 | } | 170 | } |
171 | 171 | ||
172 | static void nfnetlink_rcv(struct sock *sk, int len) | 172 | static void nfnetlink_rcv(struct sk_buff *skb) |
173 | { | 173 | { |
174 | unsigned int qlen = 0; | 174 | nfnl_lock(); |
175 | 175 | netlink_rcv_skb(skb, &nfnetlink_rcv_msg); | |
176 | do { | 176 | nfnl_unlock(); |
177 | nfnl_lock(); | ||
178 | qlen = netlink_run_queue(sk, qlen, nfnetlink_rcv_msg); | ||
179 | nfnl_unlock(); | ||
180 | } while (qlen); | ||
181 | } | 177 | } |
182 | 178 | ||
183 | static void __exit nfnetlink_exit(void) | 179 | static void __exit nfnetlink_exit(void) |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 4ce7dcbcb6ef..c776bcd9f825 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -80,7 +80,7 @@ struct netlink_sock { | |||
80 | struct netlink_callback *cb; | 80 | struct netlink_callback *cb; |
81 | struct mutex *cb_mutex; | 81 | struct mutex *cb_mutex; |
82 | struct mutex cb_def_mutex; | 82 | struct mutex cb_def_mutex; |
83 | void (*data_ready)(struct sock *sk, int bytes); | 83 | void (*netlink_rcv)(struct sk_buff *skb); |
84 | struct module *module; | 84 | struct module *module; |
85 | }; | 85 | }; |
86 | 86 | ||
@@ -127,7 +127,6 @@ static DECLARE_WAIT_QUEUE_HEAD(nl_table_wait); | |||
127 | 127 | ||
128 | static int netlink_dump(struct sock *sk); | 128 | static int netlink_dump(struct sock *sk); |
129 | static void netlink_destroy_callback(struct netlink_callback *cb); | 129 | static void netlink_destroy_callback(struct netlink_callback *cb); |
130 | static void netlink_queue_skip(struct nlmsghdr *nlh, struct sk_buff *skb); | ||
131 | 130 | ||
132 | static DEFINE_RWLOCK(nl_table_lock); | 131 | static DEFINE_RWLOCK(nl_table_lock); |
133 | static atomic_t nl_table_users = ATOMIC_INIT(0); | 132 | static atomic_t nl_table_users = ATOMIC_INIT(0); |
@@ -709,21 +708,17 @@ static void netlink_overrun(struct sock *sk) | |||
709 | 708 | ||
710 | static struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid) | 709 | static struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid) |
711 | { | 710 | { |
712 | int protocol = ssk->sk_protocol; | ||
713 | struct net *net; | ||
714 | struct sock *sock; | 711 | struct sock *sock; |
715 | struct netlink_sock *nlk; | 712 | struct netlink_sock *nlk; |
716 | 713 | ||
717 | net = ssk->sk_net; | 714 | sock = netlink_lookup(ssk->sk_net, ssk->sk_protocol, pid); |
718 | sock = netlink_lookup(net, protocol, pid); | ||
719 | if (!sock) | 715 | if (!sock) |
720 | return ERR_PTR(-ECONNREFUSED); | 716 | return ERR_PTR(-ECONNREFUSED); |
721 | 717 | ||
722 | /* Don't bother queuing skb if kernel socket has no input function */ | 718 | /* Don't bother queuing skb if kernel socket has no input function */ |
723 | nlk = nlk_sk(sock); | 719 | nlk = nlk_sk(sock); |
724 | if ((netlink_is_kernel(sock) && !nlk->data_ready) || | 720 | if (sock->sk_state == NETLINK_CONNECTED && |
725 | (sock->sk_state == NETLINK_CONNECTED && | 721 | nlk->dst_pid != nlk_sk(ssk)->pid) { |
726 | nlk->dst_pid != nlk_sk(ssk)->pid)) { | ||
727 | sock_put(sock); | 722 | sock_put(sock); |
728 | return ERR_PTR(-ECONNREFUSED); | 723 | return ERR_PTR(-ECONNREFUSED); |
729 | } | 724 | } |
@@ -837,7 +832,34 @@ static inline struct sk_buff *netlink_trim(struct sk_buff *skb, | |||
837 | return skb; | 832 | return skb; |
838 | } | 833 | } |
839 | 834 | ||
840 | int netlink_unicast(struct sock *ssk, struct sk_buff *skb, u32 pid, int nonblock) | 835 | static inline void netlink_rcv_wake(struct sock *sk) |
836 | { | ||
837 | struct netlink_sock *nlk = nlk_sk(sk); | ||
838 | |||
839 | if (skb_queue_empty(&sk->sk_receive_queue)) | ||
840 | clear_bit(0, &nlk->state); | ||
841 | if (!test_bit(0, &nlk->state)) | ||
842 | wake_up_interruptible(&nlk->wait); | ||
843 | } | ||
844 | |||
845 | static inline int netlink_unicast_kernel(struct sock *sk, struct sk_buff *skb) | ||
846 | { | ||
847 | int ret; | ||
848 | struct netlink_sock *nlk = nlk_sk(sk); | ||
849 | |||
850 | ret = -ECONNREFUSED; | ||
851 | if (nlk->netlink_rcv != NULL) { | ||
852 | ret = skb->len; | ||
853 | skb_set_owner_r(skb, sk); | ||
854 | nlk->netlink_rcv(skb); | ||
855 | } | ||
856 | kfree_skb(skb); | ||
857 | sock_put(sk); | ||
858 | return ret; | ||
859 | } | ||
860 | |||
861 | int netlink_unicast(struct sock *ssk, struct sk_buff *skb, | ||
862 | u32 pid, int nonblock) | ||
841 | { | 863 | { |
842 | struct sock *sk; | 864 | struct sock *sk; |
843 | int err; | 865 | int err; |
@@ -852,6 +874,9 @@ retry: | |||
852 | kfree_skb(skb); | 874 | kfree_skb(skb); |
853 | return PTR_ERR(sk); | 875 | return PTR_ERR(sk); |
854 | } | 876 | } |
877 | if (netlink_is_kernel(sk)) | ||
878 | return netlink_unicast_kernel(sk, skb); | ||
879 | |||
855 | err = netlink_attachskb(sk, skb, nonblock, timeo, ssk); | 880 | err = netlink_attachskb(sk, skb, nonblock, timeo, ssk); |
856 | if (err == 1) | 881 | if (err == 1) |
857 | goto retry; | 882 | goto retry; |
@@ -1151,16 +1176,6 @@ static void netlink_cmsg_recv_pktinfo(struct msghdr *msg, struct sk_buff *skb) | |||
1151 | put_cmsg(msg, SOL_NETLINK, NETLINK_PKTINFO, sizeof(info), &info); | 1176 | put_cmsg(msg, SOL_NETLINK, NETLINK_PKTINFO, sizeof(info), &info); |
1152 | } | 1177 | } |
1153 | 1178 | ||
1154 | static inline void netlink_rcv_wake(struct sock *sk) | ||
1155 | { | ||
1156 | struct netlink_sock *nlk = nlk_sk(sk); | ||
1157 | |||
1158 | if (skb_queue_empty(&sk->sk_receive_queue)) | ||
1159 | clear_bit(0, &nlk->state); | ||
1160 | if (!test_bit(0, &nlk->state)) | ||
1161 | wake_up_interruptible(&nlk->wait); | ||
1162 | } | ||
1163 | |||
1164 | static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, | 1179 | static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, |
1165 | struct msghdr *msg, size_t len) | 1180 | struct msghdr *msg, size_t len) |
1166 | { | 1181 | { |
@@ -1308,11 +1323,7 @@ out: | |||
1308 | 1323 | ||
1309 | static void netlink_data_ready(struct sock *sk, int len) | 1324 | static void netlink_data_ready(struct sock *sk, int len) |
1310 | { | 1325 | { |
1311 | struct netlink_sock *nlk = nlk_sk(sk); | 1326 | BUG(); |
1312 | |||
1313 | if (nlk->data_ready) | ||
1314 | nlk->data_ready(sk, len); | ||
1315 | netlink_rcv_wake(sk); | ||
1316 | } | 1327 | } |
1317 | 1328 | ||
1318 | /* | 1329 | /* |
@@ -1323,7 +1334,7 @@ static void netlink_data_ready(struct sock *sk, int len) | |||
1323 | 1334 | ||
1324 | struct sock * | 1335 | struct sock * |
1325 | netlink_kernel_create(struct net *net, int unit, unsigned int groups, | 1336 | netlink_kernel_create(struct net *net, int unit, unsigned int groups, |
1326 | void (*input)(struct sock *sk, int len), | 1337 | void (*input)(struct sk_buff *skb), |
1327 | struct mutex *cb_mutex, struct module *module) | 1338 | struct mutex *cb_mutex, struct module *module) |
1328 | { | 1339 | { |
1329 | struct socket *sock; | 1340 | struct socket *sock; |
@@ -1352,7 +1363,7 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups, | |||
1352 | sk = sock->sk; | 1363 | sk = sock->sk; |
1353 | sk->sk_data_ready = netlink_data_ready; | 1364 | sk->sk_data_ready = netlink_data_ready; |
1354 | if (input) | 1365 | if (input) |
1355 | nlk_sk(sk)->data_ready = input; | 1366 | nlk_sk(sk)->netlink_rcv = input; |
1356 | 1367 | ||
1357 | if (netlink_insert(sk, net, 0)) | 1368 | if (netlink_insert(sk, net, 0)) |
1358 | goto out_sock_release; | 1369 | goto out_sock_release; |
@@ -1552,12 +1563,7 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, | |||
1552 | 1563 | ||
1553 | netlink_dump(sk); | 1564 | netlink_dump(sk); |
1554 | sock_put(sk); | 1565 | sock_put(sk); |
1555 | 1566 | return 0; | |
1556 | /* We successfully started a dump, by returning -EINTR we | ||
1557 | * signal the queue mangement to interrupt processing of | ||
1558 | * any netlink messages so userspace gets a chance to read | ||
1559 | * the results. */ | ||
1560 | return -EINTR; | ||
1561 | } | 1567 | } |
1562 | 1568 | ||
1563 | void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err) | 1569 | void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err) |
@@ -1594,13 +1600,15 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err) | |||
1594 | netlink_unicast(in_skb->sk, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); | 1600 | netlink_unicast(in_skb->sk, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); |
1595 | } | 1601 | } |
1596 | 1602 | ||
1597 | static int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, | 1603 | int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, |
1598 | struct nlmsghdr *)) | 1604 | struct nlmsghdr *)) |
1599 | { | 1605 | { |
1600 | struct nlmsghdr *nlh; | 1606 | struct nlmsghdr *nlh; |
1601 | int err; | 1607 | int err; |
1602 | 1608 | ||
1603 | while (skb->len >= nlmsg_total_size(0)) { | 1609 | while (skb->len >= nlmsg_total_size(0)) { |
1610 | int msglen; | ||
1611 | |||
1604 | nlh = nlmsg_hdr(skb); | 1612 | nlh = nlmsg_hdr(skb); |
1605 | err = 0; | 1613 | err = 0; |
1606 | 1614 | ||
@@ -1616,86 +1624,20 @@ static int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, | |||
1616 | goto skip; | 1624 | goto skip; |
1617 | 1625 | ||
1618 | err = cb(skb, nlh); | 1626 | err = cb(skb, nlh); |
1619 | if (err == -EINTR) { | ||
1620 | /* Not an error, but we interrupt processing */ | ||
1621 | netlink_queue_skip(nlh, skb); | ||
1622 | return err; | ||
1623 | } | ||
1624 | skip: | 1627 | skip: |
1625 | if (nlh->nlmsg_flags & NLM_F_ACK || err) | 1628 | if (nlh->nlmsg_flags & NLM_F_ACK || err) |
1626 | netlink_ack(skb, nlh, err); | 1629 | netlink_ack(skb, nlh, err); |
1627 | 1630 | ||
1628 | netlink_queue_skip(nlh, skb); | 1631 | msglen = NLMSG_ALIGN(nlh->nlmsg_len); |
1632 | if (msglen > skb->len) | ||
1633 | msglen = skb->len; | ||
1634 | skb_pull(skb, msglen); | ||
1629 | } | 1635 | } |
1630 | 1636 | ||
1631 | return 0; | 1637 | return 0; |
1632 | } | 1638 | } |
1633 | 1639 | ||
1634 | /** | 1640 | /** |
1635 | * nelink_run_queue - Process netlink receive queue. | ||
1636 | * @sk: Netlink socket containing the queue | ||
1637 | * @qlen: Initial queue length | ||
1638 | * @cb: Callback function invoked for each netlink message found | ||
1639 | * | ||
1640 | * Processes as much as there was in the queue upon entry and invokes | ||
1641 | * a callback function for each netlink message found. The callback | ||
1642 | * function may refuse a message by returning a negative error code | ||
1643 | * but setting the error pointer to 0 in which case this function | ||
1644 | * returns with a qlen != 0. | ||
1645 | * | ||
1646 | * qlen must be initialized to 0 before the initial entry, afterwards | ||
1647 | * the function may be called repeatedly until the returned qlen is 0. | ||
1648 | * | ||
1649 | * The callback function may return -EINTR to signal that processing | ||
1650 | * of netlink messages shall be interrupted. In this case the message | ||
1651 | * currently being processed will NOT be requeued onto the receive | ||
1652 | * queue. | ||
1653 | */ | ||
1654 | unsigned int netlink_run_queue(struct sock *sk, unsigned int qlen, | ||
1655 | int (*cb)(struct sk_buff *, struct nlmsghdr *)) | ||
1656 | { | ||
1657 | struct sk_buff *skb; | ||
1658 | |||
1659 | if (!qlen || qlen > skb_queue_len(&sk->sk_receive_queue)) | ||
1660 | qlen = skb_queue_len(&sk->sk_receive_queue); | ||
1661 | |||
1662 | for (; qlen; qlen--) { | ||
1663 | skb = skb_dequeue(&sk->sk_receive_queue); | ||
1664 | if (netlink_rcv_skb(skb, cb)) { | ||
1665 | if (skb->len) | ||
1666 | skb_queue_head(&sk->sk_receive_queue, skb); | ||
1667 | else { | ||
1668 | kfree_skb(skb); | ||
1669 | qlen--; | ||
1670 | } | ||
1671 | break; | ||
1672 | } | ||
1673 | |||
1674 | kfree_skb(skb); | ||
1675 | } | ||
1676 | |||
1677 | return qlen; | ||
1678 | } | ||
1679 | |||
1680 | /** | ||
1681 | * netlink_queue_skip - Skip netlink message while processing queue. | ||
1682 | * @nlh: Netlink message to be skipped | ||
1683 | * @skb: Socket buffer containing the netlink messages. | ||
1684 | * | ||
1685 | * Pulls the given netlink message off the socket buffer so the next | ||
1686 | * call to netlink_queue_run() will not reconsider the message. | ||
1687 | */ | ||
1688 | static void netlink_queue_skip(struct nlmsghdr *nlh, struct sk_buff *skb) | ||
1689 | { | ||
1690 | int msglen = NLMSG_ALIGN(nlh->nlmsg_len); | ||
1691 | |||
1692 | if (msglen > skb->len) | ||
1693 | msglen = skb->len; | ||
1694 | |||
1695 | skb_pull(skb, msglen); | ||
1696 | } | ||
1697 | |||
1698 | /** | ||
1699 | * nlmsg_notify - send a notification netlink message | 1641 | * nlmsg_notify - send a notification netlink message |
1700 | * @sk: netlink socket to use | 1642 | * @sk: netlink socket to use |
1701 | * @skb: notification message | 1643 | * @skb: notification message |
@@ -1998,7 +1940,7 @@ panic: | |||
1998 | core_initcall(netlink_proto_init); | 1940 | core_initcall(netlink_proto_init); |
1999 | 1941 | ||
2000 | EXPORT_SYMBOL(netlink_ack); | 1942 | EXPORT_SYMBOL(netlink_ack); |
2001 | EXPORT_SYMBOL(netlink_run_queue); | 1943 | EXPORT_SYMBOL(netlink_rcv_skb); |
2002 | EXPORT_SYMBOL(netlink_broadcast); | 1944 | EXPORT_SYMBOL(netlink_broadcast); |
2003 | EXPORT_SYMBOL(netlink_dump_start); | 1945 | EXPORT_SYMBOL(netlink_dump_start); |
2004 | EXPORT_SYMBOL(netlink_kernel_create); | 1946 | EXPORT_SYMBOL(netlink_kernel_create); |
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 3f1104dc128b..150579a21469 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
@@ -470,15 +470,11 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
470 | return ops->doit(skb, &info); | 470 | return ops->doit(skb, &info); |
471 | } | 471 | } |
472 | 472 | ||
473 | static void genl_rcv(struct sock *sk, int len) | 473 | static void genl_rcv(struct sk_buff *skb) |
474 | { | 474 | { |
475 | unsigned int qlen = 0; | 475 | genl_lock(); |
476 | 476 | netlink_rcv_skb(skb, &genl_rcv_msg); | |
477 | do { | 477 | genl_unlock(); |
478 | genl_lock(); | ||
479 | qlen = netlink_run_queue(sk, qlen, genl_rcv_msg); | ||
480 | genl_unlock(); | ||
481 | } while (qlen && genl_sock && genl_sock->sk_receive_queue.qlen); | ||
482 | } | 478 | } |
483 | 479 | ||
484 | /************************************************************************** | 480 | /************************************************************************** |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 5238f6a8dfad..d41588d101d0 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -1895,16 +1895,11 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
1895 | return link->doit(skb, nlh, attrs); | 1895 | return link->doit(skb, nlh, attrs); |
1896 | } | 1896 | } |
1897 | 1897 | ||
1898 | static void xfrm_netlink_rcv(struct sock *sk, int len) | 1898 | static void xfrm_netlink_rcv(struct sk_buff *skb) |
1899 | { | 1899 | { |
1900 | unsigned int qlen = 0; | 1900 | mutex_lock(&xfrm_cfg_mutex); |
1901 | 1901 | netlink_rcv_skb(skb, &xfrm_user_rcv_msg); | |
1902 | do { | 1902 | mutex_unlock(&xfrm_cfg_mutex); |
1903 | mutex_lock(&xfrm_cfg_mutex); | ||
1904 | qlen = netlink_run_queue(sk, qlen, &xfrm_user_rcv_msg); | ||
1905 | mutex_unlock(&xfrm_cfg_mutex); | ||
1906 | |||
1907 | } while (qlen); | ||
1908 | } | 1903 | } |
1909 | 1904 | ||
1910 | static inline size_t xfrm_expire_msgsize(void) | 1905 | static inline size_t xfrm_expire_msgsize(void) |