diff options
Diffstat (limited to 'net/ipv4/udp.c')
-rw-r--r-- | net/ipv4/udp.c | 97 |
1 files changed, 65 insertions, 32 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 7ea1b67b6de1..80007c79f12f 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -137,29 +137,28 @@ static inline int __udp_lib_lport_inuse(struct net *net, __u16 num, | |||
137 | struct hlist_node *node; | 137 | struct hlist_node *node; |
138 | 138 | ||
139 | sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)]) | 139 | sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)]) |
140 | if (sk->sk_net == net && sk->sk_hash == num) | 140 | if (net_eq(sock_net(sk), net) && sk->sk_hash == num) |
141 | return 1; | 141 | return 1; |
142 | return 0; | 142 | return 0; |
143 | } | 143 | } |
144 | 144 | ||
145 | /** | 145 | /** |
146 | * __udp_lib_get_port - UDP/-Lite port lookup for IPv4 and IPv6 | 146 | * udp_lib_get_port - UDP/-Lite port lookup for IPv4 and IPv6 |
147 | * | 147 | * |
148 | * @sk: socket struct in question | 148 | * @sk: socket struct in question |
149 | * @snum: port number to look up | 149 | * @snum: port number to look up |
150 | * @udptable: hash list table, must be of UDP_HTABLE_SIZE | ||
151 | * @saddr_comp: AF-dependent comparison of bound local IP addresses | 150 | * @saddr_comp: AF-dependent comparison of bound local IP addresses |
152 | */ | 151 | */ |
153 | int __udp_lib_get_port(struct sock *sk, unsigned short snum, | 152 | int udp_lib_get_port(struct sock *sk, unsigned short snum, |
154 | struct hlist_head udptable[], | ||
155 | int (*saddr_comp)(const struct sock *sk1, | 153 | int (*saddr_comp)(const struct sock *sk1, |
156 | const struct sock *sk2 ) ) | 154 | const struct sock *sk2 ) ) |
157 | { | 155 | { |
156 | struct hlist_head *udptable = sk->sk_prot->h.udp_hash; | ||
158 | struct hlist_node *node; | 157 | struct hlist_node *node; |
159 | struct hlist_head *head; | 158 | struct hlist_head *head; |
160 | struct sock *sk2; | 159 | struct sock *sk2; |
161 | int error = 1; | 160 | int error = 1; |
162 | struct net *net = sk->sk_net; | 161 | struct net *net = sock_net(sk); |
163 | 162 | ||
164 | write_lock_bh(&udp_hash_lock); | 163 | write_lock_bh(&udp_hash_lock); |
165 | 164 | ||
@@ -219,7 +218,7 @@ gotit: | |||
219 | sk_for_each(sk2, node, head) | 218 | sk_for_each(sk2, node, head) |
220 | if (sk2->sk_hash == snum && | 219 | if (sk2->sk_hash == snum && |
221 | sk2 != sk && | 220 | sk2 != sk && |
222 | sk2->sk_net == net && | 221 | net_eq(sock_net(sk2), net) && |
223 | (!sk2->sk_reuse || !sk->sk_reuse) && | 222 | (!sk2->sk_reuse || !sk->sk_reuse) && |
224 | (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if | 223 | (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if |
225 | || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && | 224 | || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && |
@@ -240,13 +239,7 @@ fail: | |||
240 | return error; | 239 | return error; |
241 | } | 240 | } |
242 | 241 | ||
243 | int udp_get_port(struct sock *sk, unsigned short snum, | 242 | static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) |
244 | int (*scmp)(const struct sock *, const struct sock *)) | ||
245 | { | ||
246 | return __udp_lib_get_port(sk, snum, udp_hash, scmp); | ||
247 | } | ||
248 | |||
249 | int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) | ||
250 | { | 243 | { |
251 | struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2); | 244 | struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2); |
252 | 245 | ||
@@ -255,9 +248,9 @@ int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) | |||
255 | inet1->rcv_saddr == inet2->rcv_saddr )); | 248 | inet1->rcv_saddr == inet2->rcv_saddr )); |
256 | } | 249 | } |
257 | 250 | ||
258 | static inline int udp_v4_get_port(struct sock *sk, unsigned short snum) | 251 | int udp_v4_get_port(struct sock *sk, unsigned short snum) |
259 | { | 252 | { |
260 | return udp_get_port(sk, snum, ipv4_rcv_saddr_equal); | 253 | return udp_lib_get_port(sk, snum, ipv4_rcv_saddr_equal); |
261 | } | 254 | } |
262 | 255 | ||
263 | /* UDP is nearly always wildcards out the wazoo, it makes no sense to try | 256 | /* UDP is nearly always wildcards out the wazoo, it makes no sense to try |
@@ -276,7 +269,7 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, | |||
276 | sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) { | 269 | sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) { |
277 | struct inet_sock *inet = inet_sk(sk); | 270 | struct inet_sock *inet = inet_sk(sk); |
278 | 271 | ||
279 | if (sk->sk_net == net && sk->sk_hash == hnum && | 272 | if (net_eq(sock_net(sk), net) && sk->sk_hash == hnum && |
280 | !ipv6_only_sock(sk)) { | 273 | !ipv6_only_sock(sk)) { |
281 | int score = (sk->sk_family == PF_INET ? 1 : 0); | 274 | int score = (sk->sk_family == PF_INET ? 1 : 0); |
282 | if (inet->rcv_saddr) { | 275 | if (inet->rcv_saddr) { |
@@ -364,7 +357,7 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct hlist_head udptable[]) | |||
364 | int harderr; | 357 | int harderr; |
365 | int err; | 358 | int err; |
366 | 359 | ||
367 | sk = __udp4_lib_lookup(skb->dev->nd_net, iph->daddr, uh->dest, | 360 | sk = __udp4_lib_lookup(dev_net(skb->dev), iph->daddr, uh->dest, |
368 | iph->saddr, uh->source, skb->dev->ifindex, udptable); | 361 | iph->saddr, uh->source, skb->dev->ifindex, udptable); |
369 | if (sk == NULL) { | 362 | if (sk == NULL) { |
370 | ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); | 363 | ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); |
@@ -614,7 +607,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
614 | 607 | ||
615 | ipc.oif = sk->sk_bound_dev_if; | 608 | ipc.oif = sk->sk_bound_dev_if; |
616 | if (msg->msg_controllen) { | 609 | if (msg->msg_controllen) { |
617 | err = ip_cmsg_send(msg, &ipc); | 610 | err = ip_cmsg_send(sock_net(sk), msg, &ipc); |
618 | if (err) | 611 | if (err) |
619 | return err; | 612 | return err; |
620 | if (ipc.opt) | 613 | if (ipc.opt) |
@@ -663,7 +656,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
663 | { .sport = inet->sport, | 656 | { .sport = inet->sport, |
664 | .dport = dport } } }; | 657 | .dport = dport } } }; |
665 | security_sk_classify_flow(sk, &fl); | 658 | security_sk_classify_flow(sk, &fl); |
666 | err = ip_route_output_flow(&init_net, &rt, &fl, sk, 1); | 659 | err = ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 1); |
667 | if (err) { | 660 | if (err) { |
668 | if (err == -ENETUNREACH) | 661 | if (err == -ENETUNREACH) |
669 | IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); | 662 | IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); |
@@ -1188,7 +1181,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[], | |||
1188 | if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST)) | 1181 | if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST)) |
1189 | return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable); | 1182 | return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable); |
1190 | 1183 | ||
1191 | sk = __udp4_lib_lookup(skb->dev->nd_net, saddr, uh->source, daddr, | 1184 | sk = __udp4_lib_lookup(dev_net(skb->dev), saddr, uh->source, daddr, |
1192 | uh->dest, inet_iif(skb), udptable); | 1185 | uh->dest, inet_iif(skb), udptable); |
1193 | 1186 | ||
1194 | if (sk != NULL) { | 1187 | if (sk != NULL) { |
@@ -1498,6 +1491,7 @@ struct proto udp_prot = { | |||
1498 | .sysctl_wmem = &sysctl_udp_wmem_min, | 1491 | .sysctl_wmem = &sysctl_udp_wmem_min, |
1499 | .sysctl_rmem = &sysctl_udp_rmem_min, | 1492 | .sysctl_rmem = &sysctl_udp_rmem_min, |
1500 | .obj_size = sizeof(struct udp_sock), | 1493 | .obj_size = sizeof(struct udp_sock), |
1494 | .h.udp_hash = udp_hash, | ||
1501 | #ifdef CONFIG_COMPAT | 1495 | #ifdef CONFIG_COMPAT |
1502 | .compat_setsockopt = compat_udp_setsockopt, | 1496 | .compat_setsockopt = compat_udp_setsockopt, |
1503 | .compat_getsockopt = compat_udp_getsockopt, | 1497 | .compat_getsockopt = compat_udp_getsockopt, |
@@ -1512,10 +1506,13 @@ static struct sock *udp_get_first(struct seq_file *seq) | |||
1512 | { | 1506 | { |
1513 | struct sock *sk; | 1507 | struct sock *sk; |
1514 | struct udp_iter_state *state = seq->private; | 1508 | struct udp_iter_state *state = seq->private; |
1509 | struct net *net = state->net; | ||
1515 | 1510 | ||
1516 | for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) { | 1511 | for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) { |
1517 | struct hlist_node *node; | 1512 | struct hlist_node *node; |
1518 | sk_for_each(sk, node, state->hashtable + state->bucket) { | 1513 | sk_for_each(sk, node, state->hashtable + state->bucket) { |
1514 | if (!net_eq(sock_net(sk), net)) | ||
1515 | continue; | ||
1519 | if (sk->sk_family == state->family) | 1516 | if (sk->sk_family == state->family) |
1520 | goto found; | 1517 | goto found; |
1521 | } | 1518 | } |
@@ -1528,12 +1525,13 @@ found: | |||
1528 | static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk) | 1525 | static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk) |
1529 | { | 1526 | { |
1530 | struct udp_iter_state *state = seq->private; | 1527 | struct udp_iter_state *state = seq->private; |
1528 | struct net *net = state->net; | ||
1531 | 1529 | ||
1532 | do { | 1530 | do { |
1533 | sk = sk_next(sk); | 1531 | sk = sk_next(sk); |
1534 | try_again: | 1532 | try_again: |
1535 | ; | 1533 | ; |
1536 | } while (sk && sk->sk_family != state->family); | 1534 | } while (sk && (!net_eq(sock_net(sk), net) || sk->sk_family != state->family)); |
1537 | 1535 | ||
1538 | if (!sk && ++state->bucket < UDP_HTABLE_SIZE) { | 1536 | if (!sk && ++state->bucket < UDP_HTABLE_SIZE) { |
1539 | sk = sk_head(state->hashtable + state->bucket); | 1537 | sk = sk_head(state->hashtable + state->bucket); |
@@ -1582,33 +1580,53 @@ static int udp_seq_open(struct inode *inode, struct file *file) | |||
1582 | { | 1580 | { |
1583 | struct udp_seq_afinfo *afinfo = PDE(inode)->data; | 1581 | struct udp_seq_afinfo *afinfo = PDE(inode)->data; |
1584 | struct seq_file *seq; | 1582 | struct seq_file *seq; |
1583 | struct net *net; | ||
1585 | int rc = -ENOMEM; | 1584 | int rc = -ENOMEM; |
1586 | struct udp_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL); | 1585 | struct udp_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL); |
1587 | 1586 | ||
1588 | if (!s) | 1587 | if (!s) |
1589 | goto out; | 1588 | goto out; |
1589 | |||
1590 | rc = -ENXIO; | ||
1591 | net = get_proc_net(inode); | ||
1592 | if (!net) | ||
1593 | goto out_kfree; | ||
1594 | |||
1590 | s->family = afinfo->family; | 1595 | s->family = afinfo->family; |
1591 | s->hashtable = afinfo->hashtable; | 1596 | s->hashtable = afinfo->hashtable; |
1592 | s->seq_ops.start = udp_seq_start; | 1597 | s->seq_ops.start = udp_seq_start; |
1593 | s->seq_ops.next = udp_seq_next; | 1598 | s->seq_ops.next = udp_seq_next; |
1594 | s->seq_ops.show = afinfo->seq_show; | 1599 | s->seq_ops.show = afinfo->seq_show; |
1595 | s->seq_ops.stop = udp_seq_stop; | 1600 | s->seq_ops.stop = udp_seq_stop; |
1601 | s->net = net; | ||
1596 | 1602 | ||
1597 | rc = seq_open(file, &s->seq_ops); | 1603 | rc = seq_open(file, &s->seq_ops); |
1598 | if (rc) | 1604 | if (rc) |
1599 | goto out_kfree; | 1605 | goto out_put_net; |
1600 | 1606 | ||
1601 | seq = file->private_data; | 1607 | seq = file->private_data; |
1602 | seq->private = s; | 1608 | seq->private = s; |
1603 | out: | 1609 | out: |
1604 | return rc; | 1610 | return rc; |
1611 | out_put_net: | ||
1612 | put_net(net); | ||
1605 | out_kfree: | 1613 | out_kfree: |
1606 | kfree(s); | 1614 | kfree(s); |
1607 | goto out; | 1615 | goto out; |
1608 | } | 1616 | } |
1609 | 1617 | ||
1618 | static int udp_seq_release(struct inode *inode, struct file *file) | ||
1619 | { | ||
1620 | struct seq_file *seq = file->private_data; | ||
1621 | struct udp_iter_state *s = seq->private; | ||
1622 | |||
1623 | put_net(s->net); | ||
1624 | seq_release_private(inode, file); | ||
1625 | return 0; | ||
1626 | } | ||
1627 | |||
1610 | /* ------------------------------------------------------------------------ */ | 1628 | /* ------------------------------------------------------------------------ */ |
1611 | int udp_proc_register(struct udp_seq_afinfo *afinfo) | 1629 | int udp_proc_register(struct net *net, struct udp_seq_afinfo *afinfo) |
1612 | { | 1630 | { |
1613 | struct proc_dir_entry *p; | 1631 | struct proc_dir_entry *p; |
1614 | int rc = 0; | 1632 | int rc = 0; |
@@ -1619,9 +1637,9 @@ int udp_proc_register(struct udp_seq_afinfo *afinfo) | |||
1619 | afinfo->seq_fops->open = udp_seq_open; | 1637 | afinfo->seq_fops->open = udp_seq_open; |
1620 | afinfo->seq_fops->read = seq_read; | 1638 | afinfo->seq_fops->read = seq_read; |
1621 | afinfo->seq_fops->llseek = seq_lseek; | 1639 | afinfo->seq_fops->llseek = seq_lseek; |
1622 | afinfo->seq_fops->release = seq_release_private; | 1640 | afinfo->seq_fops->release = udp_seq_release; |
1623 | 1641 | ||
1624 | p = proc_net_fops_create(&init_net, afinfo->name, S_IRUGO, afinfo->seq_fops); | 1642 | p = proc_net_fops_create(net, afinfo->name, S_IRUGO, afinfo->seq_fops); |
1625 | if (p) | 1643 | if (p) |
1626 | p->data = afinfo; | 1644 | p->data = afinfo; |
1627 | else | 1645 | else |
@@ -1629,11 +1647,11 @@ int udp_proc_register(struct udp_seq_afinfo *afinfo) | |||
1629 | return rc; | 1647 | return rc; |
1630 | } | 1648 | } |
1631 | 1649 | ||
1632 | void udp_proc_unregister(struct udp_seq_afinfo *afinfo) | 1650 | void udp_proc_unregister(struct net *net, struct udp_seq_afinfo *afinfo) |
1633 | { | 1651 | { |
1634 | if (!afinfo) | 1652 | if (!afinfo) |
1635 | return; | 1653 | return; |
1636 | proc_net_remove(&init_net, afinfo->name); | 1654 | proc_net_remove(net, afinfo->name); |
1637 | memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops)); | 1655 | memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops)); |
1638 | } | 1656 | } |
1639 | 1657 | ||
@@ -1683,14 +1701,29 @@ static struct udp_seq_afinfo udp4_seq_afinfo = { | |||
1683 | .seq_fops = &udp4_seq_fops, | 1701 | .seq_fops = &udp4_seq_fops, |
1684 | }; | 1702 | }; |
1685 | 1703 | ||
1704 | static int udp4_proc_init_net(struct net *net) | ||
1705 | { | ||
1706 | return udp_proc_register(net, &udp4_seq_afinfo); | ||
1707 | } | ||
1708 | |||
1709 | static void udp4_proc_exit_net(struct net *net) | ||
1710 | { | ||
1711 | udp_proc_unregister(net, &udp4_seq_afinfo); | ||
1712 | } | ||
1713 | |||
1714 | static struct pernet_operations udp4_net_ops = { | ||
1715 | .init = udp4_proc_init_net, | ||
1716 | .exit = udp4_proc_exit_net, | ||
1717 | }; | ||
1718 | |||
1686 | int __init udp4_proc_init(void) | 1719 | int __init udp4_proc_init(void) |
1687 | { | 1720 | { |
1688 | return udp_proc_register(&udp4_seq_afinfo); | 1721 | return register_pernet_subsys(&udp4_net_ops); |
1689 | } | 1722 | } |
1690 | 1723 | ||
1691 | void udp4_proc_exit(void) | 1724 | void udp4_proc_exit(void) |
1692 | { | 1725 | { |
1693 | udp_proc_unregister(&udp4_seq_afinfo); | 1726 | unregister_pernet_subsys(&udp4_net_ops); |
1694 | } | 1727 | } |
1695 | #endif /* CONFIG_PROC_FS */ | 1728 | #endif /* CONFIG_PROC_FS */ |
1696 | 1729 | ||
@@ -1717,12 +1750,12 @@ EXPORT_SYMBOL(udp_disconnect); | |||
1717 | EXPORT_SYMBOL(udp_hash); | 1750 | EXPORT_SYMBOL(udp_hash); |
1718 | EXPORT_SYMBOL(udp_hash_lock); | 1751 | EXPORT_SYMBOL(udp_hash_lock); |
1719 | EXPORT_SYMBOL(udp_ioctl); | 1752 | EXPORT_SYMBOL(udp_ioctl); |
1720 | EXPORT_SYMBOL(udp_get_port); | ||
1721 | EXPORT_SYMBOL(udp_prot); | 1753 | EXPORT_SYMBOL(udp_prot); |
1722 | EXPORT_SYMBOL(udp_sendmsg); | 1754 | EXPORT_SYMBOL(udp_sendmsg); |
1723 | EXPORT_SYMBOL(udp_lib_getsockopt); | 1755 | EXPORT_SYMBOL(udp_lib_getsockopt); |
1724 | EXPORT_SYMBOL(udp_lib_setsockopt); | 1756 | EXPORT_SYMBOL(udp_lib_setsockopt); |
1725 | EXPORT_SYMBOL(udp_poll); | 1757 | EXPORT_SYMBOL(udp_poll); |
1758 | EXPORT_SYMBOL(udp_lib_get_port); | ||
1726 | 1759 | ||
1727 | #ifdef CONFIG_PROC_FS | 1760 | #ifdef CONFIG_PROC_FS |
1728 | EXPORT_SYMBOL(udp_proc_register); | 1761 | EXPORT_SYMBOL(udp_proc_register); |