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.c138
1 files changed, 68 insertions, 70 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 1704c1474ea1..b053ac795275 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) &&
@@ -232,7 +231,7 @@ gotit:
232 if (sk_unhashed(sk)) { 231 if (sk_unhashed(sk)) {
233 head = &udptable[snum & (UDP_HTABLE_SIZE - 1)]; 232 head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
234 sk_add_node(sk, head); 233 sk_add_node(sk, head);
235 sock_prot_inuse_add(sk->sk_prot, 1); 234 sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
236 } 235 }
237 error = 0; 236 error = 0;
238fail: 237fail:
@@ -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) {
@@ -1228,7 +1221,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
1228 return 0; 1221 return 0;
1229 1222
1230short_packet: 1223short_packet:
1231 LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n", 1224 LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: short packet: From " NIPQUAD_FMT ":%u %d/%d to " NIPQUAD_FMT ":%u\n",
1232 proto == IPPROTO_UDPLITE ? "-Lite" : "", 1225 proto == IPPROTO_UDPLITE ? "-Lite" : "",
1233 NIPQUAD(saddr), 1226 NIPQUAD(saddr),
1234 ntohs(uh->source), 1227 ntohs(uh->source),
@@ -1243,7 +1236,7 @@ csum_error:
1243 * RFC1122: OK. Discards the bad packet silently (as far as 1236 * RFC1122: OK. Discards the bad packet silently (as far as
1244 * the network is concerned, anyway) as per 4.1.3.4 (MUST). 1237 * the network is concerned, anyway) as per 4.1.3.4 (MUST).
1245 */ 1238 */
1246 LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n", 1239 LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: bad checksum. From " NIPQUAD_FMT ":%u to " NIPQUAD_FMT ":%u ulen %d\n",
1247 proto == IPPROTO_UDPLITE ? "-Lite" : "", 1240 proto == IPPROTO_UDPLITE ? "-Lite" : "",
1248 NIPQUAD(saddr), 1241 NIPQUAD(saddr),
1249 ntohs(uh->source), 1242 ntohs(uh->source),
@@ -1474,8 +1467,6 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
1474 1467
1475} 1468}
1476 1469
1477DEFINE_PROTO_INUSE(udp)
1478
1479struct proto udp_prot = { 1470struct proto udp_prot = {
1480 .name = "UDP", 1471 .name = "UDP",
1481 .owner = THIS_MODULE, 1472 .owner = THIS_MODULE,
@@ -1498,11 +1489,11 @@ struct proto udp_prot = {
1498 .sysctl_wmem = &sysctl_udp_wmem_min, 1489 .sysctl_wmem = &sysctl_udp_wmem_min,
1499 .sysctl_rmem = &sysctl_udp_rmem_min, 1490 .sysctl_rmem = &sysctl_udp_rmem_min,
1500 .obj_size = sizeof(struct udp_sock), 1491 .obj_size = sizeof(struct udp_sock),
1492 .h.udp_hash = udp_hash,
1501#ifdef CONFIG_COMPAT 1493#ifdef CONFIG_COMPAT
1502 .compat_setsockopt = compat_udp_setsockopt, 1494 .compat_setsockopt = compat_udp_setsockopt,
1503 .compat_getsockopt = compat_udp_getsockopt, 1495 .compat_getsockopt = compat_udp_getsockopt,
1504#endif 1496#endif
1505 REF_PROTO_INUSE(udp)
1506}; 1497};
1507 1498
1508/* ------------------------------------------------------------------------ */ 1499/* ------------------------------------------------------------------------ */
@@ -1512,10 +1503,13 @@ static struct sock *udp_get_first(struct seq_file *seq)
1512{ 1503{
1513 struct sock *sk; 1504 struct sock *sk;
1514 struct udp_iter_state *state = seq->private; 1505 struct udp_iter_state *state = seq->private;
1506 struct net *net = seq_file_net(seq);
1515 1507
1516 for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) { 1508 for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) {
1517 struct hlist_node *node; 1509 struct hlist_node *node;
1518 sk_for_each(sk, node, state->hashtable + state->bucket) { 1510 sk_for_each(sk, node, state->hashtable + state->bucket) {
1511 if (!net_eq(sock_net(sk), net))
1512 continue;
1519 if (sk->sk_family == state->family) 1513 if (sk->sk_family == state->family)
1520 goto found; 1514 goto found;
1521 } 1515 }
@@ -1528,12 +1522,13 @@ found:
1528static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk) 1522static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk)
1529{ 1523{
1530 struct udp_iter_state *state = seq->private; 1524 struct udp_iter_state *state = seq->private;
1525 struct net *net = seq_file_net(seq);
1531 1526
1532 do { 1527 do {
1533 sk = sk_next(sk); 1528 sk = sk_next(sk);
1534try_again: 1529try_again:
1535 ; 1530 ;
1536 } while (sk && sk->sk_family != state->family); 1531 } while (sk && (!net_eq(sock_net(sk), net) || sk->sk_family != state->family));
1537 1532
1538 if (!sk && ++state->bucket < UDP_HTABLE_SIZE) { 1533 if (!sk && ++state->bucket < UDP_HTABLE_SIZE) {
1539 sk = sk_head(state->hashtable + state->bucket); 1534 sk = sk_head(state->hashtable + state->bucket);
@@ -1581,47 +1576,36 @@ static void udp_seq_stop(struct seq_file *seq, void *v)
1581static int udp_seq_open(struct inode *inode, struct file *file) 1576static int udp_seq_open(struct inode *inode, struct file *file)
1582{ 1577{
1583 struct udp_seq_afinfo *afinfo = PDE(inode)->data; 1578 struct udp_seq_afinfo *afinfo = PDE(inode)->data;
1584 struct seq_file *seq; 1579 struct udp_iter_state *s;
1585 int rc = -ENOMEM; 1580 int err;
1586 struct udp_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
1587 1581
1588 if (!s) 1582 err = seq_open_net(inode, file, &afinfo->seq_ops,
1589 goto out; 1583 sizeof(struct udp_iter_state));
1584 if (err < 0)
1585 return err;
1586
1587 s = ((struct seq_file *)file->private_data)->private;
1590 s->family = afinfo->family; 1588 s->family = afinfo->family;
1591 s->hashtable = afinfo->hashtable; 1589 s->hashtable = afinfo->hashtable;
1592 s->seq_ops.start = udp_seq_start; 1590 return err;
1593 s->seq_ops.next = udp_seq_next;
1594 s->seq_ops.show = afinfo->seq_show;
1595 s->seq_ops.stop = udp_seq_stop;
1596
1597 rc = seq_open(file, &s->seq_ops);
1598 if (rc)
1599 goto out_kfree;
1600
1601 seq = file->private_data;
1602 seq->private = s;
1603out:
1604 return rc;
1605out_kfree:
1606 kfree(s);
1607 goto out;
1608} 1591}
1609 1592
1610/* ------------------------------------------------------------------------ */ 1593/* ------------------------------------------------------------------------ */
1611int udp_proc_register(struct udp_seq_afinfo *afinfo) 1594int udp_proc_register(struct net *net, struct udp_seq_afinfo *afinfo)
1612{ 1595{
1613 struct proc_dir_entry *p; 1596 struct proc_dir_entry *p;
1614 int rc = 0; 1597 int rc = 0;
1615 1598
1616 if (!afinfo) 1599 afinfo->seq_fops.open = udp_seq_open;
1617 return -EINVAL; 1600 afinfo->seq_fops.read = seq_read;
1618 afinfo->seq_fops->owner = afinfo->owner; 1601 afinfo->seq_fops.llseek = seq_lseek;
1619 afinfo->seq_fops->open = udp_seq_open; 1602 afinfo->seq_fops.release = seq_release_net;
1620 afinfo->seq_fops->read = seq_read; 1603
1621 afinfo->seq_fops->llseek = seq_lseek; 1604 afinfo->seq_ops.start = udp_seq_start;
1622 afinfo->seq_fops->release = seq_release_private; 1605 afinfo->seq_ops.next = udp_seq_next;
1606 afinfo->seq_ops.stop = udp_seq_stop;
1623 1607
1624 p = proc_net_fops_create(&init_net, afinfo->name, S_IRUGO, afinfo->seq_fops); 1608 p = proc_net_fops_create(net, afinfo->name, S_IRUGO, &afinfo->seq_fops);
1625 if (p) 1609 if (p)
1626 p->data = afinfo; 1610 p->data = afinfo;
1627 else 1611 else
@@ -1629,12 +1613,9 @@ int udp_proc_register(struct udp_seq_afinfo *afinfo)
1629 return rc; 1613 return rc;
1630} 1614}
1631 1615
1632void udp_proc_unregister(struct udp_seq_afinfo *afinfo) 1616void udp_proc_unregister(struct net *net, struct udp_seq_afinfo *afinfo)
1633{ 1617{
1634 if (!afinfo) 1618 proc_net_remove(net, afinfo->name);
1635 return;
1636 proc_net_remove(&init_net, afinfo->name);
1637 memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
1638} 1619}
1639 1620
1640/* ------------------------------------------------------------------------ */ 1621/* ------------------------------------------------------------------------ */
@@ -1673,24 +1654,41 @@ int udp4_seq_show(struct seq_file *seq, void *v)
1673} 1654}
1674 1655
1675/* ------------------------------------------------------------------------ */ 1656/* ------------------------------------------------------------------------ */
1676static struct file_operations udp4_seq_fops;
1677static struct udp_seq_afinfo udp4_seq_afinfo = { 1657static struct udp_seq_afinfo udp4_seq_afinfo = {
1678 .owner = THIS_MODULE,
1679 .name = "udp", 1658 .name = "udp",
1680 .family = AF_INET, 1659 .family = AF_INET,
1681 .hashtable = udp_hash, 1660 .hashtable = udp_hash,
1682 .seq_show = udp4_seq_show, 1661 .seq_fops = {
1683 .seq_fops = &udp4_seq_fops, 1662 .owner = THIS_MODULE,
1663 },
1664 .seq_ops = {
1665 .show = udp4_seq_show,
1666 },
1667};
1668
1669static int udp4_proc_init_net(struct net *net)
1670{
1671 return udp_proc_register(net, &udp4_seq_afinfo);
1672}
1673
1674static void udp4_proc_exit_net(struct net *net)
1675{
1676 udp_proc_unregister(net, &udp4_seq_afinfo);
1677}
1678
1679static struct pernet_operations udp4_net_ops = {
1680 .init = udp4_proc_init_net,
1681 .exit = udp4_proc_exit_net,
1684}; 1682};
1685 1683
1686int __init udp4_proc_init(void) 1684int __init udp4_proc_init(void)
1687{ 1685{
1688 return udp_proc_register(&udp4_seq_afinfo); 1686 return register_pernet_subsys(&udp4_net_ops);
1689} 1687}
1690 1688
1691void udp4_proc_exit(void) 1689void udp4_proc_exit(void)
1692{ 1690{
1693 udp_proc_unregister(&udp4_seq_afinfo); 1691 unregister_pernet_subsys(&udp4_net_ops);
1694} 1692}
1695#endif /* CONFIG_PROC_FS */ 1693#endif /* CONFIG_PROC_FS */
1696 1694
@@ -1717,12 +1715,12 @@ EXPORT_SYMBOL(udp_disconnect);
1717EXPORT_SYMBOL(udp_hash); 1715EXPORT_SYMBOL(udp_hash);
1718EXPORT_SYMBOL(udp_hash_lock); 1716EXPORT_SYMBOL(udp_hash_lock);
1719EXPORT_SYMBOL(udp_ioctl); 1717EXPORT_SYMBOL(udp_ioctl);
1720EXPORT_SYMBOL(udp_get_port);
1721EXPORT_SYMBOL(udp_prot); 1718EXPORT_SYMBOL(udp_prot);
1722EXPORT_SYMBOL(udp_sendmsg); 1719EXPORT_SYMBOL(udp_sendmsg);
1723EXPORT_SYMBOL(udp_lib_getsockopt); 1720EXPORT_SYMBOL(udp_lib_getsockopt);
1724EXPORT_SYMBOL(udp_lib_setsockopt); 1721EXPORT_SYMBOL(udp_lib_setsockopt);
1725EXPORT_SYMBOL(udp_poll); 1722EXPORT_SYMBOL(udp_poll);
1723EXPORT_SYMBOL(udp_lib_get_port);
1726 1724
1727#ifdef CONFIG_PROC_FS 1725#ifdef CONFIG_PROC_FS
1728EXPORT_SYMBOL(udp_proc_register); 1726EXPORT_SYMBOL(udp_proc_register);