aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/af_inet6.c3
-rw-r--r--net/ipv6/datagram.c19
-rw-r--r--net/ipv6/ipv6_sockglue.c23
-rw-r--r--net/ipv6/netfilter/Makefile5
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c78
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c14
-rw-r--r--net/ipv6/netfilter/nf_defrag_ipv6_hooks.c131
-rw-r--r--net/ipv6/tcp_ipv6.c12
-rw-r--r--net/ipv6/udp.c16
9 files changed, 214 insertions, 87 deletions
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 56b9bf2516f4..4869797c1afa 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -343,7 +343,8 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
343 */ 343 */
344 v4addr = LOOPBACK4_IPV6; 344 v4addr = LOOPBACK4_IPV6;
345 if (!(addr_type & IPV6_ADDR_MULTICAST)) { 345 if (!(addr_type & IPV6_ADDR_MULTICAST)) {
346 if (!ipv6_chk_addr(net, &addr->sin6_addr, 346 if (!inet->transparent &&
347 !ipv6_chk_addr(net, &addr->sin6_addr,
347 dev, 0)) { 348 dev, 0)) {
348 err = -EADDRNOTAVAIL; 349 err = -EADDRNOTAVAIL;
349 goto out_unlock; 350 goto out_unlock;
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index ef371aa01ac5..320bdb877eed 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -577,6 +577,25 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
577 u8 *ptr = nh + opt->dst1; 577 u8 *ptr = nh + opt->dst1;
578 put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr); 578 put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr);
579 } 579 }
580 if (np->rxopt.bits.rxorigdstaddr) {
581 struct sockaddr_in6 sin6;
582 u16 *ports = (u16 *) skb_transport_header(skb);
583
584 if (skb_transport_offset(skb) + 4 <= skb->len) {
585 /* All current transport protocols have the port numbers in the
586 * first four bytes of the transport header and this function is
587 * written with this assumption in mind.
588 */
589
590 sin6.sin6_family = AF_INET6;
591 ipv6_addr_copy(&sin6.sin6_addr, &ipv6_hdr(skb)->daddr);
592 sin6.sin6_port = ports[1];
593 sin6.sin6_flowinfo = 0;
594 sin6.sin6_scope_id = 0;
595
596 put_cmsg(msg, SOL_IPV6, IPV6_ORIGDSTADDR, sizeof(sin6), &sin6);
597 }
598 }
580 return 0; 599 return 0;
581} 600}
582 601
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index a7f66bc8f0b0..0553867a317f 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -342,6 +342,21 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
342 retv = 0; 342 retv = 0;
343 break; 343 break;
344 344
345 case IPV6_TRANSPARENT:
346 if (optlen < sizeof(int))
347 goto e_inval;
348 /* we don't have a separate transparent bit for IPV6 we use the one in the IPv4 socket */
349 inet_sk(sk)->transparent = valbool;
350 retv = 0;
351 break;
352
353 case IPV6_RECVORIGDSTADDR:
354 if (optlen < sizeof(int))
355 goto e_inval;
356 np->rxopt.bits.rxorigdstaddr = valbool;
357 retv = 0;
358 break;
359
345 case IPV6_HOPOPTS: 360 case IPV6_HOPOPTS:
346 case IPV6_RTHDRDSTOPTS: 361 case IPV6_RTHDRDSTOPTS:
347 case IPV6_RTHDR: 362 case IPV6_RTHDR:
@@ -1104,6 +1119,14 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
1104 break; 1119 break;
1105 } 1120 }
1106 1121
1122 case IPV6_TRANSPARENT:
1123 val = inet_sk(sk)->transparent;
1124 break;
1125
1126 case IPV6_RECVORIGDSTADDR:
1127 val = np->rxopt.bits.rxorigdstaddr;
1128 break;
1129
1107 case IPV6_UNICAST_HOPS: 1130 case IPV6_UNICAST_HOPS:
1108 case IPV6_MULTICAST_HOPS: 1131 case IPV6_MULTICAST_HOPS:
1109 { 1132 {
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index aafbba30c899..3f8e4a3d83ce 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -11,10 +11,11 @@ obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
11obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o 11obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o
12 12
13# objects for l3 independent conntrack 13# objects for l3 independent conntrack
14nf_conntrack_ipv6-objs := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o nf_conntrack_reasm.o 14nf_conntrack_ipv6-objs := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o
15nf_defrag_ipv6-objs := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o
15 16
16# l3 independent conntrack 17# l3 independent conntrack
17obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o 18obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o nf_defrag_ipv6.o
18 19
19# matches 20# matches
20obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o 21obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index ff43461704be..c8af58b22562 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -16,7 +16,6 @@
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/skbuff.h> 17#include <linux/skbuff.h>
18#include <linux/icmp.h> 18#include <linux/icmp.h>
19#include <linux/sysctl.h>
20#include <net/ipv6.h> 19#include <net/ipv6.h>
21#include <net/inet_frag.h> 20#include <net/inet_frag.h>
22 21
@@ -29,6 +28,7 @@
29#include <net/netfilter/nf_conntrack_core.h> 28#include <net/netfilter/nf_conntrack_core.h>
30#include <net/netfilter/nf_conntrack_zones.h> 29#include <net/netfilter/nf_conntrack_zones.h>
31#include <net/netfilter/ipv6/nf_conntrack_ipv6.h> 30#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
31#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
32#include <net/netfilter/nf_log.h> 32#include <net/netfilter/nf_log.h>
33 33
34static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, 34static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
@@ -189,53 +189,6 @@ out:
189 return nf_conntrack_confirm(skb); 189 return nf_conntrack_confirm(skb);
190} 190}
191 191
192static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
193 struct sk_buff *skb)
194{
195 u16 zone = NF_CT_DEFAULT_ZONE;
196
197 if (skb->nfct)
198 zone = nf_ct_zone((struct nf_conn *)skb->nfct);
199
200#ifdef CONFIG_BRIDGE_NETFILTER
201 if (skb->nf_bridge &&
202 skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
203 return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
204#endif
205 if (hooknum == NF_INET_PRE_ROUTING)
206 return IP6_DEFRAG_CONNTRACK_IN + zone;
207 else
208 return IP6_DEFRAG_CONNTRACK_OUT + zone;
209
210}
211
212static unsigned int ipv6_defrag(unsigned int hooknum,
213 struct sk_buff *skb,
214 const struct net_device *in,
215 const struct net_device *out,
216 int (*okfn)(struct sk_buff *))
217{
218 struct sk_buff *reasm;
219
220 /* Previously seen (loopback)? */
221 if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
222 return NF_ACCEPT;
223
224 reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb));
225 /* queued */
226 if (reasm == NULL)
227 return NF_STOLEN;
228
229 /* error occured or not fragmented */
230 if (reasm == skb)
231 return NF_ACCEPT;
232
233 nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in,
234 (struct net_device *)out, okfn);
235
236 return NF_STOLEN;
237}
238
239static unsigned int __ipv6_conntrack_in(struct net *net, 192static unsigned int __ipv6_conntrack_in(struct net *net,
240 unsigned int hooknum, 193 unsigned int hooknum,
241 struct sk_buff *skb, 194 struct sk_buff *skb,
@@ -288,13 +241,6 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum,
288 241
289static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = { 242static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = {
290 { 243 {
291 .hook = ipv6_defrag,
292 .owner = THIS_MODULE,
293 .pf = NFPROTO_IPV6,
294 .hooknum = NF_INET_PRE_ROUTING,
295 .priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
296 },
297 {
298 .hook = ipv6_conntrack_in, 244 .hook = ipv6_conntrack_in,
299 .owner = THIS_MODULE, 245 .owner = THIS_MODULE,
300 .pf = NFPROTO_IPV6, 246 .pf = NFPROTO_IPV6,
@@ -309,13 +255,6 @@ static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = {
309 .priority = NF_IP6_PRI_CONNTRACK, 255 .priority = NF_IP6_PRI_CONNTRACK,
310 }, 256 },
311 { 257 {
312 .hook = ipv6_defrag,
313 .owner = THIS_MODULE,
314 .pf = NFPROTO_IPV6,
315 .hooknum = NF_INET_LOCAL_OUT,
316 .priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
317 },
318 {
319 .hook = ipv6_confirm, 258 .hook = ipv6_confirm,
320 .owner = THIS_MODULE, 259 .owner = THIS_MODULE,
321 .pf = NFPROTO_IPV6, 260 .pf = NFPROTO_IPV6,
@@ -387,10 +326,6 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = {
387 .nlattr_to_tuple = ipv6_nlattr_to_tuple, 326 .nlattr_to_tuple = ipv6_nlattr_to_tuple,
388 .nla_policy = ipv6_nla_policy, 327 .nla_policy = ipv6_nla_policy,
389#endif 328#endif
390#ifdef CONFIG_SYSCTL
391 .ctl_table_path = nf_net_netfilter_sysctl_path,
392 .ctl_table = nf_ct_ipv6_sysctl_table,
393#endif
394 .me = THIS_MODULE, 329 .me = THIS_MODULE,
395}; 330};
396 331
@@ -403,16 +338,12 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
403 int ret = 0; 338 int ret = 0;
404 339
405 need_conntrack(); 340 need_conntrack();
341 nf_defrag_ipv6_enable();
406 342
407 ret = nf_ct_frag6_init();
408 if (ret < 0) {
409 pr_err("nf_conntrack_ipv6: can't initialize frag6.\n");
410 return ret;
411 }
412 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp6); 343 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp6);
413 if (ret < 0) { 344 if (ret < 0) {
414 pr_err("nf_conntrack_ipv6: can't register tcp.\n"); 345 pr_err("nf_conntrack_ipv6: can't register tcp.\n");
415 goto cleanup_frag6; 346 return ret;
416 } 347 }
417 348
418 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp6); 349 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp6);
@@ -450,8 +381,6 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
450 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6); 381 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
451 cleanup_tcp: 382 cleanup_tcp:
452 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6); 383 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
453 cleanup_frag6:
454 nf_ct_frag6_cleanup();
455 return ret; 384 return ret;
456} 385}
457 386
@@ -463,7 +392,6 @@ static void __exit nf_conntrack_l3proto_ipv6_fini(void)
463 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6); 392 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
464 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6); 393 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
465 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6); 394 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
466 nf_ct_frag6_cleanup();
467} 395}
468 396
469module_init(nf_conntrack_l3proto_ipv6_init); 397module_init(nf_conntrack_l3proto_ipv6_init);
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 138a8b362706..489d71b844ac 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -73,7 +73,7 @@ static struct inet_frags nf_frags;
73static struct netns_frags nf_init_frags; 73static struct netns_frags nf_init_frags;
74 74
75#ifdef CONFIG_SYSCTL 75#ifdef CONFIG_SYSCTL
76struct ctl_table nf_ct_ipv6_sysctl_table[] = { 76struct ctl_table nf_ct_frag6_sysctl_table[] = {
77 { 77 {
78 .procname = "nf_conntrack_frag6_timeout", 78 .procname = "nf_conntrack_frag6_timeout",
79 .data = &nf_init_frags.timeout, 79 .data = &nf_init_frags.timeout,
@@ -97,6 +97,8 @@ struct ctl_table nf_ct_ipv6_sysctl_table[] = {
97 }, 97 },
98 { } 98 { }
99}; 99};
100
101static struct ctl_table_header *nf_ct_frag6_sysctl_header;
100#endif 102#endif
101 103
102static unsigned int nf_hashfn(struct inet_frag_queue *q) 104static unsigned int nf_hashfn(struct inet_frag_queue *q)
@@ -623,11 +625,21 @@ int nf_ct_frag6_init(void)
623 inet_frags_init_net(&nf_init_frags); 625 inet_frags_init_net(&nf_init_frags);
624 inet_frags_init(&nf_frags); 626 inet_frags_init(&nf_frags);
625 627
628 nf_ct_frag6_sysctl_header = register_sysctl_paths(nf_net_netfilter_sysctl_path,
629 nf_ct_frag6_sysctl_table);
630 if (!nf_ct_frag6_sysctl_header) {
631 inet_frags_fini(&nf_frags);
632 return -ENOMEM;
633 }
634
626 return 0; 635 return 0;
627} 636}
628 637
629void nf_ct_frag6_cleanup(void) 638void nf_ct_frag6_cleanup(void)
630{ 639{
640 unregister_sysctl_table(nf_ct_frag6_sysctl_header);
641 nf_ct_frag6_sysctl_header = NULL;
642
631 inet_frags_fini(&nf_frags); 643 inet_frags_fini(&nf_frags);
632 644
633 nf_init_frags.low_thresh = 0; 645 nf_init_frags.low_thresh = 0;
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
new file mode 100644
index 000000000000..99abfb53bab9
--- /dev/null
+++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
@@ -0,0 +1,131 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/types.h>
10#include <linux/ipv6.h>
11#include <linux/in6.h>
12#include <linux/netfilter.h>
13#include <linux/module.h>
14#include <linux/skbuff.h>
15#include <linux/icmp.h>
16#include <linux/sysctl.h>
17#include <net/ipv6.h>
18#include <net/inet_frag.h>
19
20#include <linux/netfilter_ipv6.h>
21#include <linux/netfilter_bridge.h>
22#include <net/netfilter/nf_conntrack.h>
23#include <net/netfilter/nf_conntrack_helper.h>
24#include <net/netfilter/nf_conntrack_l4proto.h>
25#include <net/netfilter/nf_conntrack_l3proto.h>
26#include <net/netfilter/nf_conntrack_core.h>
27#include <net/netfilter/nf_conntrack_zones.h>
28#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
29#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
30
31static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
32 struct sk_buff *skb)
33{
34 u16 zone = NF_CT_DEFAULT_ZONE;
35
36 if (skb->nfct)
37 zone = nf_ct_zone((struct nf_conn *)skb->nfct);
38
39#ifdef CONFIG_BRIDGE_NETFILTER
40 if (skb->nf_bridge &&
41 skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
42 return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
43#endif
44 if (hooknum == NF_INET_PRE_ROUTING)
45 return IP6_DEFRAG_CONNTRACK_IN + zone;
46 else
47 return IP6_DEFRAG_CONNTRACK_OUT + zone;
48
49}
50
51static unsigned int ipv6_defrag(unsigned int hooknum,
52 struct sk_buff *skb,
53 const struct net_device *in,
54 const struct net_device *out,
55 int (*okfn)(struct sk_buff *))
56{
57 struct sk_buff *reasm;
58
59 /* Previously seen (loopback)? */
60 if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
61 return NF_ACCEPT;
62
63 reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb));
64 /* queued */
65 if (reasm == NULL)
66 return NF_STOLEN;
67
68 /* error occured or not fragmented */
69 if (reasm == skb)
70 return NF_ACCEPT;
71
72 nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in,
73 (struct net_device *)out, okfn);
74
75 return NF_STOLEN;
76}
77
78static struct nf_hook_ops ipv6_defrag_ops[] = {
79 {
80 .hook = ipv6_defrag,
81 .owner = THIS_MODULE,
82 .pf = NFPROTO_IPV6,
83 .hooknum = NF_INET_PRE_ROUTING,
84 .priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
85 },
86 {
87 .hook = ipv6_defrag,
88 .owner = THIS_MODULE,
89 .pf = NFPROTO_IPV6,
90 .hooknum = NF_INET_LOCAL_OUT,
91 .priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
92 },
93};
94
95static int __init nf_defrag_init(void)
96{
97 int ret = 0;
98
99 ret = nf_ct_frag6_init();
100 if (ret < 0) {
101 pr_err("nf_defrag_ipv6: can't initialize frag6.\n");
102 return ret;
103 }
104 ret = nf_register_hooks(ipv6_defrag_ops, ARRAY_SIZE(ipv6_defrag_ops));
105 if (ret < 0) {
106 pr_err("nf_defrag_ipv6: can't register hooks\n");
107 goto cleanup_frag6;
108 }
109 return ret;
110
111cleanup_frag6:
112 nf_ct_frag6_cleanup();
113 return ret;
114
115}
116
117static void __exit nf_defrag_fini(void)
118{
119 nf_unregister_hooks(ipv6_defrag_ops, ARRAY_SIZE(ipv6_defrag_ops));
120 nf_ct_frag6_cleanup();
121}
122
123void nf_defrag_ipv6_enable(void)
124{
125}
126EXPORT_SYMBOL_GPL(nf_defrag_ipv6_enable);
127
128module_init(nf_defrag_init);
129module_exit(nf_defrag_fini);
130
131MODULE_LICENSE("GPL");
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index fe6d40418c0b..ba5258ef1c57 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1409,7 +1409,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
1409 1409
1410 newsk = tcp_create_openreq_child(sk, req, skb); 1410 newsk = tcp_create_openreq_child(sk, req, skb);
1411 if (newsk == NULL) 1411 if (newsk == NULL)
1412 goto out; 1412 goto out_nonewsk;
1413 1413
1414 /* 1414 /*
1415 * No need to charge this sock to the relevant IPv6 refcnt debug socks 1415 * No need to charge this sock to the relevant IPv6 refcnt debug socks
@@ -1497,18 +1497,22 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
1497 } 1497 }
1498#endif 1498#endif
1499 1499
1500 if (__inet_inherit_port(sk, newsk) < 0) {
1501 sock_put(newsk);
1502 goto out;
1503 }
1500 __inet6_hash(newsk, NULL); 1504 __inet6_hash(newsk, NULL);
1501 __inet_inherit_port(sk, newsk);
1502 1505
1503 return newsk; 1506 return newsk;
1504 1507
1505out_overflow: 1508out_overflow:
1506 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); 1509 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
1507out: 1510out_nonewsk:
1508 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
1509 if (opt && opt != np->opt) 1511 if (opt && opt != np->opt)
1510 sock_kfree_s(sk, opt, opt->tot_len); 1512 sock_kfree_s(sk, opt, opt->tot_len);
1511 dst_release(dst); 1513 dst_release(dst);
1514out:
1515 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
1512 return NULL; 1516 return NULL;
1513} 1517}
1514 1518
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 5acb3560ff15..c84dad432114 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -122,8 +122,8 @@ static void udp_v6_rehash(struct sock *sk)
122 122
123static inline int compute_score(struct sock *sk, struct net *net, 123static inline int compute_score(struct sock *sk, struct net *net,
124 unsigned short hnum, 124 unsigned short hnum,
125 struct in6_addr *saddr, __be16 sport, 125 const struct in6_addr *saddr, __be16 sport,
126 struct in6_addr *daddr, __be16 dport, 126 const struct in6_addr *daddr, __be16 dport,
127 int dif) 127 int dif)
128{ 128{
129 int score = -1; 129 int score = -1;
@@ -239,8 +239,8 @@ exact_match:
239} 239}
240 240
241static struct sock *__udp6_lib_lookup(struct net *net, 241static struct sock *__udp6_lib_lookup(struct net *net,
242 struct in6_addr *saddr, __be16 sport, 242 const struct in6_addr *saddr, __be16 sport,
243 struct in6_addr *daddr, __be16 dport, 243 const struct in6_addr *daddr, __be16 dport,
244 int dif, struct udp_table *udptable) 244 int dif, struct udp_table *udptable)
245{ 245{
246 struct sock *sk, *result; 246 struct sock *sk, *result;
@@ -320,6 +320,14 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb,
320 udptable); 320 udptable);
321} 321}
322 322
323struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport,
324 const struct in6_addr *daddr, __be16 dport, int dif)
325{
326 return __udp6_lib_lookup(net, saddr, sport, daddr, dport, dif, &udp_table);
327}
328EXPORT_SYMBOL_GPL(udp6_lib_lookup);
329
330
323/* 331/*
324 * This should be easy, if there is something there we 332 * This should be easy, if there is something there we
325 * return it, otherwise we block. 333 * return it, otherwise we block.