diff options
-rw-r--r-- | net/netlink/af_netlink.c | 81 |
1 files changed, 43 insertions, 38 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 1518244ffad9..2e02b19e4552 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -156,7 +156,7 @@ static void netlink_sock_destruct(struct sock *sk) | |||
156 | skb_queue_purge(&sk->sk_receive_queue); | 156 | skb_queue_purge(&sk->sk_receive_queue); |
157 | 157 | ||
158 | if (!sock_flag(sk, SOCK_DEAD)) { | 158 | if (!sock_flag(sk, SOCK_DEAD)) { |
159 | printk("Freeing alive netlink socket %p\n", sk); | 159 | printk(KERN_ERR "Freeing alive netlink socket %p\n", sk); |
160 | return; | 160 | return; |
161 | } | 161 | } |
162 | BUG_TRAP(!atomic_read(&sk->sk_rmem_alloc)); | 162 | BUG_TRAP(!atomic_read(&sk->sk_rmem_alloc)); |
@@ -164,8 +164,8 @@ static void netlink_sock_destruct(struct sock *sk) | |||
164 | BUG_TRAP(!nlk_sk(sk)->groups); | 164 | BUG_TRAP(!nlk_sk(sk)->groups); |
165 | } | 165 | } |
166 | 166 | ||
167 | /* This lock without WQ_FLAG_EXCLUSIVE is good on UP and it is _very_ bad on SMP. | 167 | /* This lock without WQ_FLAG_EXCLUSIVE is good on UP and it is _very_ bad on |
168 | * Look, when several writers sleep and reader wakes them up, all but one | 168 | * SMP. Look, when several writers sleep and reader wakes them up, all but one |
169 | * immediately hit write lock and grab all the cpus. Exclusive sleep solves | 169 | * immediately hit write lock and grab all the cpus. Exclusive sleep solves |
170 | * this, _but_ remember, it adds useless work on UP machines. | 170 | * this, _but_ remember, it adds useless work on UP machines. |
171 | */ | 171 | */ |
@@ -178,7 +178,7 @@ static void netlink_table_grab(void) | |||
178 | DECLARE_WAITQUEUE(wait, current); | 178 | DECLARE_WAITQUEUE(wait, current); |
179 | 179 | ||
180 | add_wait_queue_exclusive(&nl_table_wait, &wait); | 180 | add_wait_queue_exclusive(&nl_table_wait, &wait); |
181 | for(;;) { | 181 | for (;;) { |
182 | set_current_state(TASK_UNINTERRUPTIBLE); | 182 | set_current_state(TASK_UNINTERRUPTIBLE); |
183 | if (atomic_read(&nl_table_users) == 0) | 183 | if (atomic_read(&nl_table_users) == 0) |
184 | break; | 184 | break; |
@@ -192,13 +192,13 @@ static void netlink_table_grab(void) | |||
192 | } | 192 | } |
193 | } | 193 | } |
194 | 194 | ||
195 | static __inline__ void netlink_table_ungrab(void) | 195 | static inline void netlink_table_ungrab(void) |
196 | { | 196 | { |
197 | write_unlock_irq(&nl_table_lock); | 197 | write_unlock_irq(&nl_table_lock); |
198 | wake_up(&nl_table_wait); | 198 | wake_up(&nl_table_wait); |
199 | } | 199 | } |
200 | 200 | ||
201 | static __inline__ void | 201 | static inline void |
202 | netlink_lock_table(void) | 202 | netlink_lock_table(void) |
203 | { | 203 | { |
204 | /* read_lock() synchronizes us to netlink_table_grab */ | 204 | /* read_lock() synchronizes us to netlink_table_grab */ |
@@ -208,14 +208,15 @@ netlink_lock_table(void) | |||
208 | read_unlock(&nl_table_lock); | 208 | read_unlock(&nl_table_lock); |
209 | } | 209 | } |
210 | 210 | ||
211 | static __inline__ void | 211 | static inline void |
212 | netlink_unlock_table(void) | 212 | netlink_unlock_table(void) |
213 | { | 213 | { |
214 | if (atomic_dec_and_test(&nl_table_users)) | 214 | if (atomic_dec_and_test(&nl_table_users)) |
215 | wake_up(&nl_table_wait); | 215 | wake_up(&nl_table_wait); |
216 | } | 216 | } |
217 | 217 | ||
218 | static __inline__ struct sock *netlink_lookup(struct net *net, int protocol, u32 pid) | 218 | static inline struct sock *netlink_lookup(struct net *net, int protocol, |
219 | u32 pid) | ||
219 | { | 220 | { |
220 | struct nl_pid_hash *hash = &nl_table[protocol].hash; | 221 | struct nl_pid_hash *hash = &nl_table[protocol].hash; |
221 | struct hlist_head *head; | 222 | struct hlist_head *head; |
@@ -428,7 +429,7 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol) | |||
428 | if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM) | 429 | if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM) |
429 | return -ESOCKTNOSUPPORT; | 430 | return -ESOCKTNOSUPPORT; |
430 | 431 | ||
431 | if (protocol<0 || protocol >= MAX_LINKS) | 432 | if (protocol < 0 || protocol >= MAX_LINKS) |
432 | return -EPROTONOSUPPORT; | 433 | return -EPROTONOSUPPORT; |
433 | 434 | ||
434 | netlink_lock_table(); | 435 | netlink_lock_table(); |
@@ -445,7 +446,8 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol) | |||
445 | cb_mutex = nl_table[protocol].cb_mutex; | 446 | cb_mutex = nl_table[protocol].cb_mutex; |
446 | netlink_unlock_table(); | 447 | netlink_unlock_table(); |
447 | 448 | ||
448 | if ((err = __netlink_create(net, sock, cb_mutex, protocol)) < 0) | 449 | err = __netlink_create(net, sock, cb_mutex, protocol); |
450 | if (err < 0) | ||
449 | goto out_module; | 451 | goto out_module; |
450 | 452 | ||
451 | nlk = nlk_sk(sock->sk); | 453 | nlk = nlk_sk(sock->sk); |
@@ -590,7 +592,7 @@ static int netlink_realloc_groups(struct sock *sk) | |||
590 | err = -ENOMEM; | 592 | err = -ENOMEM; |
591 | goto out_unlock; | 593 | goto out_unlock; |
592 | } | 594 | } |
593 | memset((char*)new_groups + NLGRPSZ(nlk->ngroups), 0, | 595 | memset((char *)new_groups + NLGRPSZ(nlk->ngroups), 0, |
594 | NLGRPSZ(groups) - NLGRPSZ(nlk->ngroups)); | 596 | NLGRPSZ(groups) - NLGRPSZ(nlk->ngroups)); |
595 | 597 | ||
596 | nlk->groups = new_groups; | 598 | nlk->groups = new_groups; |
@@ -600,7 +602,8 @@ static int netlink_realloc_groups(struct sock *sk) | |||
600 | return err; | 602 | return err; |
601 | } | 603 | } |
602 | 604 | ||
603 | static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len) | 605 | static int netlink_bind(struct socket *sock, struct sockaddr *addr, |
606 | int addr_len) | ||
604 | { | 607 | { |
605 | struct sock *sk = sock->sk; | 608 | struct sock *sk = sock->sk; |
606 | struct net *net = sk->sk_net; | 609 | struct net *net = sk->sk_net; |
@@ -651,7 +654,7 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr, | |||
651 | int err = 0; | 654 | int err = 0; |
652 | struct sock *sk = sock->sk; | 655 | struct sock *sk = sock->sk; |
653 | struct netlink_sock *nlk = nlk_sk(sk); | 656 | struct netlink_sock *nlk = nlk_sk(sk); |
654 | struct sockaddr_nl *nladdr=(struct sockaddr_nl*)addr; | 657 | struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr; |
655 | 658 | ||
656 | if (addr->sa_family == AF_UNSPEC) { | 659 | if (addr->sa_family == AF_UNSPEC) { |
657 | sk->sk_state = NETLINK_UNCONNECTED; | 660 | sk->sk_state = NETLINK_UNCONNECTED; |
@@ -678,11 +681,12 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr, | |||
678 | return err; | 681 | return err; |
679 | } | 682 | } |
680 | 683 | ||
681 | static int netlink_getname(struct socket *sock, struct sockaddr *addr, int *addr_len, int peer) | 684 | static int netlink_getname(struct socket *sock, struct sockaddr *addr, |
685 | int *addr_len, int peer) | ||
682 | { | 686 | { |
683 | struct sock *sk = sock->sk; | 687 | struct sock *sk = sock->sk; |
684 | struct netlink_sock *nlk = nlk_sk(sk); | 688 | struct netlink_sock *nlk = nlk_sk(sk); |
685 | struct sockaddr_nl *nladdr=(struct sockaddr_nl *)addr; | 689 | struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr; |
686 | 690 | ||
687 | nladdr->nl_family = AF_NETLINK; | 691 | nladdr->nl_family = AF_NETLINK; |
688 | nladdr->nl_pad = 0; | 692 | nladdr->nl_pad = 0; |
@@ -885,6 +889,7 @@ retry: | |||
885 | 889 | ||
886 | return netlink_sendskb(sk, skb); | 890 | return netlink_sendskb(sk, skb); |
887 | } | 891 | } |
892 | EXPORT_SYMBOL(netlink_unicast); | ||
888 | 893 | ||
889 | int netlink_has_listeners(struct sock *sk, unsigned int group) | 894 | int netlink_has_listeners(struct sock *sk, unsigned int group) |
890 | { | 895 | { |
@@ -905,7 +910,8 @@ int netlink_has_listeners(struct sock *sk, unsigned int group) | |||
905 | } | 910 | } |
906 | EXPORT_SYMBOL_GPL(netlink_has_listeners); | 911 | EXPORT_SYMBOL_GPL(netlink_has_listeners); |
907 | 912 | ||
908 | static __inline__ int netlink_broadcast_deliver(struct sock *sk, struct sk_buff *skb) | 913 | static inline int netlink_broadcast_deliver(struct sock *sk, |
914 | struct sk_buff *skb) | ||
909 | { | 915 | { |
910 | struct netlink_sock *nlk = nlk_sk(sk); | 916 | struct netlink_sock *nlk = nlk_sk(sk); |
911 | 917 | ||
@@ -1026,6 +1032,7 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, | |||
1026 | return -ENOBUFS; | 1032 | return -ENOBUFS; |
1027 | return -ESRCH; | 1033 | return -ESRCH; |
1028 | } | 1034 | } |
1035 | EXPORT_SYMBOL(netlink_broadcast); | ||
1029 | 1036 | ||
1030 | struct netlink_set_err_data { | 1037 | struct netlink_set_err_data { |
1031 | struct sock *exclude_sk; | 1038 | struct sock *exclude_sk; |
@@ -1182,7 +1189,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1182 | struct sock_iocb *siocb = kiocb_to_siocb(kiocb); | 1189 | struct sock_iocb *siocb = kiocb_to_siocb(kiocb); |
1183 | struct sock *sk = sock->sk; | 1190 | struct sock *sk = sock->sk; |
1184 | struct netlink_sock *nlk = nlk_sk(sk); | 1191 | struct netlink_sock *nlk = nlk_sk(sk); |
1185 | struct sockaddr_nl *addr=msg->msg_name; | 1192 | struct sockaddr_nl *addr = msg->msg_name; |
1186 | u32 dst_pid; | 1193 | u32 dst_pid; |
1187 | u32 dst_group; | 1194 | u32 dst_group; |
1188 | struct sk_buff *skb; | 1195 | struct sk_buff *skb; |
@@ -1221,7 +1228,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1221 | goto out; | 1228 | goto out; |
1222 | err = -ENOBUFS; | 1229 | err = -ENOBUFS; |
1223 | skb = alloc_skb(len, GFP_KERNEL); | 1230 | skb = alloc_skb(len, GFP_KERNEL); |
1224 | if (skb==NULL) | 1231 | if (skb == NULL) |
1225 | goto out; | 1232 | goto out; |
1226 | 1233 | ||
1227 | NETLINK_CB(skb).pid = nlk->pid; | 1234 | NETLINK_CB(skb).pid = nlk->pid; |
@@ -1237,7 +1244,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1237 | */ | 1244 | */ |
1238 | 1245 | ||
1239 | err = -EFAULT; | 1246 | err = -EFAULT; |
1240 | if (memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len)) { | 1247 | if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { |
1241 | kfree_skb(skb); | 1248 | kfree_skb(skb); |
1242 | goto out; | 1249 | goto out; |
1243 | } | 1250 | } |
@@ -1276,8 +1283,8 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, | |||
1276 | 1283 | ||
1277 | copied = 0; | 1284 | copied = 0; |
1278 | 1285 | ||
1279 | skb = skb_recv_datagram(sk,flags,noblock,&err); | 1286 | skb = skb_recv_datagram(sk, flags, noblock, &err); |
1280 | if (skb==NULL) | 1287 | if (skb == NULL) |
1281 | goto out; | 1288 | goto out; |
1282 | 1289 | ||
1283 | msg->msg_namelen = 0; | 1290 | msg->msg_namelen = 0; |
@@ -1292,7 +1299,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, | |||
1292 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); | 1299 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); |
1293 | 1300 | ||
1294 | if (msg->msg_name) { | 1301 | if (msg->msg_name) { |
1295 | struct sockaddr_nl *addr = (struct sockaddr_nl*)msg->msg_name; | 1302 | struct sockaddr_nl *addr = (struct sockaddr_nl *)msg->msg_name; |
1296 | addr->nl_family = AF_NETLINK; | 1303 | addr->nl_family = AF_NETLINK; |
1297 | addr->nl_pad = 0; | 1304 | addr->nl_pad = 0; |
1298 | addr->nl_pid = NETLINK_CB(skb).pid; | 1305 | addr->nl_pid = NETLINK_CB(skb).pid; |
@@ -1344,7 +1351,7 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups, | |||
1344 | 1351 | ||
1345 | BUG_ON(!nl_table); | 1352 | BUG_ON(!nl_table); |
1346 | 1353 | ||
1347 | if (unit<0 || unit>=MAX_LINKS) | 1354 | if (unit < 0 || unit >= MAX_LINKS) |
1348 | return NULL; | 1355 | return NULL; |
1349 | 1356 | ||
1350 | if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock)) | 1357 | if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock)) |
@@ -1390,6 +1397,7 @@ out_sock_release: | |||
1390 | sock_release(sock); | 1397 | sock_release(sock); |
1391 | return NULL; | 1398 | return NULL; |
1392 | } | 1399 | } |
1400 | EXPORT_SYMBOL(netlink_kernel_create); | ||
1393 | 1401 | ||
1394 | /** | 1402 | /** |
1395 | * netlink_change_ngroups - change number of multicast groups | 1403 | * netlink_change_ngroups - change number of multicast groups |
@@ -1461,6 +1469,7 @@ void netlink_set_nonroot(int protocol, unsigned int flags) | |||
1461 | if ((unsigned int)protocol < MAX_LINKS) | 1469 | if ((unsigned int)protocol < MAX_LINKS) |
1462 | nl_table[protocol].nl_nonroot = flags; | 1470 | nl_table[protocol].nl_nonroot = flags; |
1463 | } | 1471 | } |
1472 | EXPORT_SYMBOL(netlink_set_nonroot); | ||
1464 | 1473 | ||
1465 | static void netlink_destroy_callback(struct netlink_callback *cb) | 1474 | static void netlink_destroy_callback(struct netlink_callback *cb) |
1466 | { | 1475 | { |
@@ -1529,8 +1538,9 @@ errout: | |||
1529 | 1538 | ||
1530 | int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, | 1539 | int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, |
1531 | struct nlmsghdr *nlh, | 1540 | struct nlmsghdr *nlh, |
1532 | int (*dump)(struct sk_buff *skb, struct netlink_callback*), | 1541 | int (*dump)(struct sk_buff *skb, |
1533 | int (*done)(struct netlink_callback*)) | 1542 | struct netlink_callback *), |
1543 | int (*done)(struct netlink_callback *)) | ||
1534 | { | 1544 | { |
1535 | struct netlink_callback *cb; | 1545 | struct netlink_callback *cb; |
1536 | struct sock *sk; | 1546 | struct sock *sk; |
@@ -1571,6 +1581,7 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, | |||
1571 | */ | 1581 | */ |
1572 | return -EINTR; | 1582 | return -EINTR; |
1573 | } | 1583 | } |
1584 | EXPORT_SYMBOL(netlink_dump_start); | ||
1574 | 1585 | ||
1575 | void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err) | 1586 | void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err) |
1576 | { | 1587 | { |
@@ -1605,6 +1616,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err) | |||
1605 | memcpy(&errmsg->msg, nlh, err ? nlh->nlmsg_len : sizeof(*nlh)); | 1616 | memcpy(&errmsg->msg, nlh, err ? nlh->nlmsg_len : sizeof(*nlh)); |
1606 | netlink_unicast(in_skb->sk, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); | 1617 | netlink_unicast(in_skb->sk, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); |
1607 | } | 1618 | } |
1619 | EXPORT_SYMBOL(netlink_ack); | ||
1608 | 1620 | ||
1609 | int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, | 1621 | int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, |
1610 | struct nlmsghdr *)) | 1622 | struct nlmsghdr *)) |
@@ -1638,7 +1650,7 @@ ack: | |||
1638 | netlink_ack(skb, nlh, err); | 1650 | netlink_ack(skb, nlh, err); |
1639 | 1651 | ||
1640 | skip: | 1652 | skip: |
1641 | msglen = NLMSG_ALIGN(nlh->nlmsg_len); | 1653 | msglen = NLMSG_ALIGN(nlh->nlmsg_len); |
1642 | if (msglen > skb->len) | 1654 | if (msglen > skb->len) |
1643 | msglen = skb->len; | 1655 | msglen = skb->len; |
1644 | skb_pull(skb, msglen); | 1656 | skb_pull(skb, msglen); |
@@ -1646,6 +1658,7 @@ skip: | |||
1646 | 1658 | ||
1647 | return 0; | 1659 | return 0; |
1648 | } | 1660 | } |
1661 | EXPORT_SYMBOL(netlink_rcv_skb); | ||
1649 | 1662 | ||
1650 | /** | 1663 | /** |
1651 | * nlmsg_notify - send a notification netlink message | 1664 | * nlmsg_notify - send a notification netlink message |
@@ -1678,6 +1691,7 @@ int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 pid, | |||
1678 | 1691 | ||
1679 | return err; | 1692 | return err; |
1680 | } | 1693 | } |
1694 | EXPORT_SYMBOL(nlmsg_notify); | ||
1681 | 1695 | ||
1682 | #ifdef CONFIG_PROC_FS | 1696 | #ifdef CONFIG_PROC_FS |
1683 | struct nl_seq_iter { | 1697 | struct nl_seq_iter { |
@@ -1694,7 +1708,7 @@ static struct sock *netlink_seq_socket_idx(struct seq_file *seq, loff_t pos) | |||
1694 | struct hlist_node *node; | 1708 | struct hlist_node *node; |
1695 | loff_t off = 0; | 1709 | loff_t off = 0; |
1696 | 1710 | ||
1697 | for (i=0; i<MAX_LINKS; i++) { | 1711 | for (i = 0; i < MAX_LINKS; i++) { |
1698 | struct nl_pid_hash *hash = &nl_table[i].hash; | 1712 | struct nl_pid_hash *hash = &nl_table[i].hash; |
1699 | 1713 | ||
1700 | for (j = 0; j <= hash->mask; j++) { | 1714 | for (j = 0; j <= hash->mask; j++) { |
@@ -1820,11 +1834,13 @@ int netlink_register_notifier(struct notifier_block *nb) | |||
1820 | { | 1834 | { |
1821 | return atomic_notifier_chain_register(&netlink_chain, nb); | 1835 | return atomic_notifier_chain_register(&netlink_chain, nb); |
1822 | } | 1836 | } |
1837 | EXPORT_SYMBOL(netlink_register_notifier); | ||
1823 | 1838 | ||
1824 | int netlink_unregister_notifier(struct notifier_block *nb) | 1839 | int netlink_unregister_notifier(struct notifier_block *nb) |
1825 | { | 1840 | { |
1826 | return atomic_notifier_chain_unregister(&netlink_chain, nb); | 1841 | return atomic_notifier_chain_unregister(&netlink_chain, nb); |
1827 | } | 1842 | } |
1843 | EXPORT_SYMBOL(netlink_unregister_notifier); | ||
1828 | 1844 | ||
1829 | static const struct proto_ops netlink_ops = { | 1845 | static const struct proto_ops netlink_ops = { |
1830 | .family = PF_NETLINK, | 1846 | .family = PF_NETLINK, |
@@ -1929,14 +1945,3 @@ panic: | |||
1929 | } | 1945 | } |
1930 | 1946 | ||
1931 | core_initcall(netlink_proto_init); | 1947 | core_initcall(netlink_proto_init); |
1932 | |||
1933 | EXPORT_SYMBOL(netlink_ack); | ||
1934 | EXPORT_SYMBOL(netlink_rcv_skb); | ||
1935 | EXPORT_SYMBOL(netlink_broadcast); | ||
1936 | EXPORT_SYMBOL(netlink_dump_start); | ||
1937 | EXPORT_SYMBOL(netlink_kernel_create); | ||
1938 | EXPORT_SYMBOL(netlink_register_notifier); | ||
1939 | EXPORT_SYMBOL(netlink_set_nonroot); | ||
1940 | EXPORT_SYMBOL(netlink_unicast); | ||
1941 | EXPORT_SYMBOL(netlink_unregister_notifier); | ||
1942 | EXPORT_SYMBOL(nlmsg_notify); | ||