aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/udp.c')
-rw-r--r--net/ipv4/udp.c97
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 */
153int __udp_lib_get_port(struct sock *sk, unsigned short snum, 152int 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
243int udp_get_port(struct sock *sk, unsigned short snum, 242static 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
249int 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
258static inline int udp_v4_get_port(struct sock *sk, unsigned short snum) 251int 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:
1528static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk) 1525static 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);
1534try_again: 1532try_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;
1603out: 1609out:
1604 return rc; 1610 return rc;
1611out_put_net:
1612 put_net(net);
1605out_kfree: 1613out_kfree:
1606 kfree(s); 1614 kfree(s);
1607 goto out; 1615 goto out;
1608} 1616}
1609 1617
1618static 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/* ------------------------------------------------------------------------ */
1611int udp_proc_register(struct udp_seq_afinfo *afinfo) 1629int 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
1632void udp_proc_unregister(struct udp_seq_afinfo *afinfo) 1650void 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
1704static int udp4_proc_init_net(struct net *net)
1705{
1706 return udp_proc_register(net, &udp4_seq_afinfo);
1707}
1708
1709static void udp4_proc_exit_net(struct net *net)
1710{
1711 udp_proc_unregister(net, &udp4_seq_afinfo);
1712}
1713
1714static struct pernet_operations udp4_net_ops = {
1715 .init = udp4_proc_init_net,
1716 .exit = udp4_proc_exit_net,
1717};
1718
1686int __init udp4_proc_init(void) 1719int __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
1691void udp4_proc_exit(void) 1724void 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);
1717EXPORT_SYMBOL(udp_hash); 1750EXPORT_SYMBOL(udp_hash);
1718EXPORT_SYMBOL(udp_hash_lock); 1751EXPORT_SYMBOL(udp_hash_lock);
1719EXPORT_SYMBOL(udp_ioctl); 1752EXPORT_SYMBOL(udp_ioctl);
1720EXPORT_SYMBOL(udp_get_port);
1721EXPORT_SYMBOL(udp_prot); 1753EXPORT_SYMBOL(udp_prot);
1722EXPORT_SYMBOL(udp_sendmsg); 1754EXPORT_SYMBOL(udp_sendmsg);
1723EXPORT_SYMBOL(udp_lib_getsockopt); 1755EXPORT_SYMBOL(udp_lib_getsockopt);
1724EXPORT_SYMBOL(udp_lib_setsockopt); 1756EXPORT_SYMBOL(udp_lib_setsockopt);
1725EXPORT_SYMBOL(udp_poll); 1757EXPORT_SYMBOL(udp_poll);
1758EXPORT_SYMBOL(udp_lib_get_port);
1726 1759
1727#ifdef CONFIG_PROC_FS 1760#ifdef CONFIG_PROC_FS
1728EXPORT_SYMBOL(udp_proc_register); 1761EXPORT_SYMBOL(udp_proc_register);