aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/addrconf.c35
-rw-r--r--net/ipv6/af_inet6.c1
-rw-r--r--net/ipv6/ah6.c2
-rw-r--r--net/ipv6/datagram.c8
-rw-r--r--net/ipv6/exthdrs.c16
-rw-r--r--net/ipv6/ip6_fib.c9
-rw-r--r--net/ipv6/ip6_input.c2
-rw-r--r--net/ipv6/ip6_output.c13
-rw-r--r--net/ipv6/netfilter/Kconfig2
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c70
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c96
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c52
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c3
-rw-r--r--net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c3
-rw-r--r--net/ipv6/raw.c8
-rw-r--r--net/ipv6/route.c63
-rw-r--r--net/ipv6/tcp_ipv6.c8
-rw-r--r--net/ipv6/udp.c29
-rw-r--r--net/ipv6/udp_impl.h2
-rw-r--r--net/ipv6/udplite.c2
-rw-r--r--net/ipv6/xfrm6_input.c6
-rw-r--r--net/ipv6/xfrm6_mode_tunnel.c1
22 files changed, 220 insertions, 211 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d02685c6bc69..329de679ac38 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2154,15 +2154,6 @@ static void addrconf_dev_config(struct net_device *dev)
2154 2154
2155 ASSERT_RTNL(); 2155 ASSERT_RTNL();
2156 2156
2157 if ((dev->type != ARPHRD_ETHER) &&
2158 (dev->type != ARPHRD_FDDI) &&
2159 (dev->type != ARPHRD_IEEE802_TR) &&
2160 (dev->type != ARPHRD_ARCNET) &&
2161 (dev->type != ARPHRD_INFINIBAND)) {
2162 /* Alas, we support only Ethernet autoconfiguration. */
2163 return;
2164 }
2165
2166 idev = addrconf_add_dev(dev); 2157 idev = addrconf_add_dev(dev);
2167 if (idev == NULL) 2158 if (idev == NULL)
2168 return; 2159 return;
@@ -2250,13 +2241,33 @@ static void addrconf_ip6_tnl_config(struct net_device *dev)
2250 ip6_tnl_add_linklocal(idev); 2241 ip6_tnl_add_linklocal(idev);
2251} 2242}
2252 2243
2244static int ipv6_hwtype(struct net_device *dev)
2245{
2246 if ((dev->type == ARPHRD_ETHER) ||
2247 (dev->type == ARPHRD_LOOPBACK) ||
2248 (dev->type == ARPHRD_SIT) ||
2249 (dev->type == ARPHRD_TUNNEL6) ||
2250 (dev->type == ARPHRD_FDDI) ||
2251 (dev->type == ARPHRD_IEEE802_TR) ||
2252 (dev->type == ARPHRD_ARCNET) ||
2253 (dev->type == ARPHRD_INFINIBAND))
2254 return 1;
2255
2256 return 0;
2257}
2258
2253static int addrconf_notify(struct notifier_block *this, unsigned long event, 2259static int addrconf_notify(struct notifier_block *this, unsigned long event,
2254 void * data) 2260 void * data)
2255{ 2261{
2256 struct net_device *dev = (struct net_device *) data; 2262 struct net_device *dev = (struct net_device *) data;
2257 struct inet6_dev *idev = __in6_dev_get(dev); 2263 struct inet6_dev *idev;
2258 int run_pending = 0; 2264 int run_pending = 0;
2259 2265
2266 if (!ipv6_hwtype(dev))
2267 return NOTIFY_OK;
2268
2269 idev = __in6_dev_get(dev);
2270
2260 switch(event) { 2271 switch(event) {
2261 case NETDEV_REGISTER: 2272 case NETDEV_REGISTER:
2262 if (!idev) { 2273 if (!idev) {
@@ -4204,6 +4215,10 @@ int __init addrconf_init(void)
4204 return err; 4215 return err;
4205 4216
4206 ip6_null_entry.rt6i_idev = in6_dev_get(&loopback_dev); 4217 ip6_null_entry.rt6i_idev = in6_dev_get(&loopback_dev);
4218#ifdef CONFIG_IPV6_MULTIPLE_TABLES
4219 ip6_prohibit_entry.rt6i_idev = in6_dev_get(&loopback_dev);
4220 ip6_blk_hole_entry.rt6i_idev = in6_dev_get(&loopback_dev);
4221#endif
4207 4222
4208 register_netdevice_notifier(&ipv6_dev_notf); 4223 register_netdevice_notifier(&ipv6_dev_notf);
4209 4224
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 18cb928c8d92..6dd377253cf7 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -42,7 +42,6 @@
42#include <linux/inet.h> 42#include <linux/inet.h>
43#include <linux/netdevice.h> 43#include <linux/netdevice.h>
44#include <linux/icmpv6.h> 44#include <linux/icmpv6.h>
45#include <linux/smp_lock.h>
46#include <linux/netfilter_ipv6.h> 45#include <linux/netfilter_ipv6.h>
47 46
48#include <net/ip.h> 47#include <net/ip.h>
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index b696c8401200..128f94c79c64 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -247,7 +247,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
247 memcpy(tmp_base, top_iph, sizeof(tmp_base)); 247 memcpy(tmp_base, top_iph, sizeof(tmp_base));
248 248
249 tmp_ext = NULL; 249 tmp_ext = NULL;
250 extlen = skb_transport_offset(skb) + sizeof(struct ipv6hdr); 250 extlen = skb_transport_offset(skb) - sizeof(struct ipv6hdr);
251 if (extlen) { 251 if (extlen) {
252 extlen += sizeof(*tmp_ext); 252 extlen += sizeof(*tmp_ext);
253 tmp_ext = kmalloc(extlen, GFP_ATOMIC); 253 tmp_ext = kmalloc(extlen, GFP_ATOMIC);
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 403eee66b9c5..b1fe7ac5dc90 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -177,8 +177,12 @@ ipv4_connected:
177 if (final_p) 177 if (final_p)
178 ipv6_addr_copy(&fl.fl6_dst, final_p); 178 ipv6_addr_copy(&fl.fl6_dst, final_p);
179 179
180 if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0) 180 if ((err = __xfrm_lookup(&dst, &fl, sk, 1)) < 0) {
181 goto out; 181 if (err == -EREMOTE)
182 err = ip6_dst_blackhole(sk, &dst, &fl);
183 if (err < 0)
184 goto out;
185 }
182 186
183 /* source address lookup done in ip6_dst_lookup */ 187 /* source address lookup done in ip6_dst_lookup */
184 188
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 6d8e4ac7bdad..14be0b9b77a5 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -660,6 +660,14 @@ EXPORT_SYMBOL_GPL(ipv6_invert_rthdr);
660 Hop-by-hop options. 660 Hop-by-hop options.
661 **********************************/ 661 **********************************/
662 662
663/*
664 * Note: we cannot rely on skb->dst before we assign it in ip6_route_input().
665 */
666static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb)
667{
668 return skb->dst ? ip6_dst_idev(skb->dst) : __in6_dev_get(skb->dev);
669}
670
663/* Router Alert as of RFC 2711 */ 671/* Router Alert as of RFC 2711 */
664 672
665static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) 673static int ipv6_hop_ra(struct sk_buff **skbp, int optoff)
@@ -688,25 +696,25 @@ static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff)
688 if (nh[optoff + 1] != 4 || (optoff & 3) != 2) { 696 if (nh[optoff + 1] != 4 || (optoff & 3) != 2) {
689 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", 697 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
690 nh[optoff+1]); 698 nh[optoff+1]);
691 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 699 IP6_INC_STATS_BH(ipv6_skb_idev(skb),
692 IPSTATS_MIB_INHDRERRORS); 700 IPSTATS_MIB_INHDRERRORS);
693 goto drop; 701 goto drop;
694 } 702 }
695 703
696 pkt_len = ntohl(*(__be32 *)(nh + optoff + 2)); 704 pkt_len = ntohl(*(__be32 *)(nh + optoff + 2));
697 if (pkt_len <= IPV6_MAXPLEN) { 705 if (pkt_len <= IPV6_MAXPLEN) {
698 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); 706 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS);
699 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); 707 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
700 return 0; 708 return 0;
701 } 709 }
702 if (ipv6_hdr(skb)->payload_len) { 710 if (ipv6_hdr(skb)->payload_len) {
703 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); 711 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS);
704 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff); 712 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
705 return 0; 713 return 0;
706 } 714 }
707 715
708 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) { 716 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
709 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INTRUNCATEDPKTS); 717 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INTRUNCATEDPKTS);
710 goto drop; 718 goto drop;
711 } 719 }
712 720
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index ca08ee88d07f..662a7d9681fd 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -619,14 +619,6 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
619 619
620 ins = &fn->leaf; 620 ins = &fn->leaf;
621 621
622 if (fn->fn_flags&RTN_TL_ROOT &&
623 fn->leaf == &ip6_null_entry &&
624 !(rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ){
625 fn->leaf = rt;
626 rt->u.dst.rt6_next = NULL;
627 goto out;
628 }
629
630 for (iter = fn->leaf; iter; iter=iter->u.dst.rt6_next) { 622 for (iter = fn->leaf; iter; iter=iter->u.dst.rt6_next) {
631 /* 623 /*
632 * Search for duplicates 624 * Search for duplicates
@@ -666,7 +658,6 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
666 * insert node 658 * insert node
667 */ 659 */
668 660
669out:
670 rt->u.dst.rt6_next = iter; 661 rt->u.dst.rt6_next = iter;
671 *ins = rt; 662 *ins = rt;
672 rt->rt6i_node = fn; 663 rt->rt6i_node = fn;
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index be0ee8a34f9b..30a5cb1b203e 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -235,7 +235,7 @@ int ip6_mc_input(struct sk_buff *skb)
235 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS); 235 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS);
236 236
237 hdr = ipv6_hdr(skb); 237 hdr = ipv6_hdr(skb);
238 deliver = likely(!(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI))) || 238 deliver = unlikely(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) ||
239 ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL); 239 ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL);
240 240
241 /* 241 /*
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index f508171bab73..4704b5fc3085 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -463,10 +463,17 @@ int ip6_forward(struct sk_buff *skb)
463 */ 463 */
464 if (xrlim_allow(dst, 1*HZ)) 464 if (xrlim_allow(dst, 1*HZ))
465 ndisc_send_redirect(skb, n, target); 465 ndisc_send_redirect(skb, n, target);
466 } else if (ipv6_addr_type(&hdr->saddr)&(IPV6_ADDR_MULTICAST|IPV6_ADDR_LOOPBACK 466 } else {
467 |IPV6_ADDR_LINKLOCAL)) { 467 int addrtype = ipv6_addr_type(&hdr->saddr);
468
468 /* This check is security critical. */ 469 /* This check is security critical. */
469 goto error; 470 if (addrtype & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LOOPBACK))
471 goto error;
472 if (addrtype & IPV6_ADDR_LINKLOCAL) {
473 icmpv6_send(skb, ICMPV6_DEST_UNREACH,
474 ICMPV6_NOT_NEIGHBOUR, 0, skb->dev);
475 goto error;
476 }
470 } 477 }
471 478
472 if (skb->len > dst_mtu(dst)) { 479 if (skb->len > dst_mtu(dst)) {
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index bbe99f842f9f..838b8ddee8c0 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -28,7 +28,7 @@ config IP6_NF_QUEUE
28 packets which enables users to receive the filtered packets 28 packets which enables users to receive the filtered packets
29 with QUEUE target using libipq. 29 with QUEUE target using libipq.
30 30
31 THis option enables the old IPv6-only "ip6_queue" implementation 31 This option enables the old IPv6-only "ip6_queue" implementation
32 which has been obsoleted by the new "nfnetlink_queue" code (see 32 which has been obsoleted by the new "nfnetlink_queue" code (see
33 CONFIG_NETFILTER_NETLINK_QUEUE). 33 CONFIG_NETFILTER_NETLINK_QUEUE).
34 34
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index 76f0cf66f95c..7e32e2aaf7f7 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -24,53 +24,29 @@ static struct
24 struct ip6t_replace repl; 24 struct ip6t_replace repl;
25 struct ip6t_standard entries[3]; 25 struct ip6t_standard entries[3];
26 struct ip6t_error term; 26 struct ip6t_error term;
27} initial_table __initdata 27} initial_table __initdata = {
28= { { "filter", FILTER_VALID_HOOKS, 4, 28 .repl = {
29 sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error), 29 .name = "filter",
30 { [NF_IP6_LOCAL_IN] = 0, 30 .valid_hooks = FILTER_VALID_HOOKS,
31 [NF_IP6_FORWARD] = sizeof(struct ip6t_standard), 31 .num_entries = 4,
32 [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 }, 32 .size = sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error),
33 { [NF_IP6_LOCAL_IN] = 0, 33 .hook_entry = {
34 [NF_IP6_FORWARD] = sizeof(struct ip6t_standard), 34 [NF_IP6_LOCAL_IN] = 0,
35 [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 }, 35 [NF_IP6_FORWARD] = sizeof(struct ip6t_standard),
36 0, NULL, { } }, 36 [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2
37 { 37 },
38 /* LOCAL_IN */ 38 .underflow = {
39 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 39 [NF_IP6_LOCAL_IN] = 0,
40 0, 40 [NF_IP6_FORWARD] = sizeof(struct ip6t_standard),
41 sizeof(struct ip6t_entry), 41 [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2
42 sizeof(struct ip6t_standard), 42 },
43 0, { 0, 0 }, { } }, 43 },
44 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } }, 44 .entries = {
45 -NF_ACCEPT - 1 } }, 45 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
46 /* FORWARD */ 46 IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
47 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 47 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
48 0, 48 },
49 sizeof(struct ip6t_entry), 49 .term = IP6T_ERROR_INIT, /* ERROR */
50 sizeof(struct ip6t_standard),
51 0, { 0, 0 }, { } },
52 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
53 -NF_ACCEPT - 1 } },
54 /* LOCAL_OUT */
55 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
56 0,
57 sizeof(struct ip6t_entry),
58 sizeof(struct ip6t_standard),
59 0, { 0, 0 }, { } },
60 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
61 -NF_ACCEPT - 1 } }
62 },
63 /* ERROR */
64 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
65 0,
66 sizeof(struct ip6t_entry),
67 sizeof(struct ip6t_error),
68 0, { 0, 0 }, { } },
69 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
70 { } },
71 "ERROR"
72 }
73 }
74}; 50};
75 51
76static struct xt_table packet_filter = { 52static struct xt_table packet_filter = {
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index a9f10e32c163..f2d26495f413 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -32,73 +32,35 @@ static struct
32 struct ip6t_replace repl; 32 struct ip6t_replace repl;
33 struct ip6t_standard entries[5]; 33 struct ip6t_standard entries[5];
34 struct ip6t_error term; 34 struct ip6t_error term;
35} initial_table __initdata 35} initial_table __initdata = {
36= { { "mangle", MANGLE_VALID_HOOKS, 6, 36 .repl = {
37 sizeof(struct ip6t_standard) * 5 + sizeof(struct ip6t_error), 37 .name = "mangle",
38 { [NF_IP6_PRE_ROUTING] = 0, 38 .valid_hooks = MANGLE_VALID_HOOKS,
39 [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard), 39 .num_entries = 6,
40 [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2, 40 .size = sizeof(struct ip6t_standard) * 5 + sizeof(struct ip6t_error),
41 [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3, 41 .hook_entry = {
42 [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4}, 42 [NF_IP6_PRE_ROUTING] = 0,
43 { [NF_IP6_PRE_ROUTING] = 0, 43 [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard),
44 [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard), 44 [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2,
45 [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2, 45 [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3,
46 [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3, 46 [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4,
47 [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4}, 47 },
48 0, NULL, { } }, 48 .underflow = {
49 { 49 [NF_IP6_PRE_ROUTING] = 0,
50 /* PRE_ROUTING */ 50 [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard),
51 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 51 [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2,
52 0, 52 [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3,
53 sizeof(struct ip6t_entry), 53 [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4,
54 sizeof(struct ip6t_standard), 54 },
55 0, { 0, 0 }, { } }, 55 },
56 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } }, 56 .entries = {
57 -NF_ACCEPT - 1 } }, 57 IP6T_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
58 /* LOCAL_IN */ 58 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
59 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 59 IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
60 0, 60 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
61 sizeof(struct ip6t_entry), 61 IP6T_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
62 sizeof(struct ip6t_standard), 62 },
63 0, { 0, 0 }, { } }, 63 .term = IP6T_ERROR_INIT, /* ERROR */
64 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
65 -NF_ACCEPT - 1 } },
66 /* FORWARD */
67 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
68 0,
69 sizeof(struct ip6t_entry),
70 sizeof(struct ip6t_standard),
71 0, { 0, 0 }, { } },
72 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
73 -NF_ACCEPT - 1 } },
74 /* LOCAL_OUT */
75 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
76 0,
77 sizeof(struct ip6t_entry),
78 sizeof(struct ip6t_standard),
79 0, { 0, 0 }, { } },
80 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
81 -NF_ACCEPT - 1 } },
82 /* POST_ROUTING */
83 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
84 0,
85 sizeof(struct ip6t_entry),
86 sizeof(struct ip6t_standard),
87 0, { 0, 0 }, { } },
88 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
89 -NF_ACCEPT - 1 } }
90 },
91 /* ERROR */
92 { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
93 0,
94 sizeof(struct ip6t_entry),
95 sizeof(struct ip6t_error),
96 0, { 0, 0 }, { } },
97 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
98 { } },
99 "ERROR"
100 }
101 }
102}; 64};
103 65
104static struct xt_table packet_mangler = { 66static struct xt_table packet_mangler = {
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index a3eb5b8ce18d..0acda45d455d 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -35,56 +35,10 @@ static struct
35 }, 35 },
36 }, 36 },
37 .entries = { 37 .entries = {
38 /* PRE_ROUTING */ 38 IP6T_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
39 { 39 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
40 .entry = {
41 .target_offset = sizeof(struct ip6t_entry),
42 .next_offset = sizeof(struct ip6t_standard),
43 },
44 .target = {
45 .target = {
46 .u = {
47 .target_size = IP6T_ALIGN(sizeof(struct ip6t_standard_target)),
48 },
49 },
50 .verdict = -NF_ACCEPT - 1,
51 },
52 },
53
54 /* LOCAL_OUT */
55 {
56 .entry = {
57 .target_offset = sizeof(struct ip6t_entry),
58 .next_offset = sizeof(struct ip6t_standard),
59 },
60 .target = {
61 .target = {
62 .u = {
63 .target_size = IP6T_ALIGN(sizeof(struct ip6t_standard_target)),
64 },
65 },
66 .verdict = -NF_ACCEPT - 1,
67 },
68 },
69 }, 40 },
70 /* ERROR */ 41 .term = IP6T_ERROR_INIT, /* ERROR */
71 .term = {
72 .entry = {
73 .target_offset = sizeof(struct ip6t_entry),
74 .next_offset = sizeof(struct ip6t_error),
75 },
76 .target = {
77 .target = {
78 .u = {
79 .user = {
80 .target_size = IP6T_ALIGN(sizeof(struct ip6t_error_target)),
81 .name = IP6T_ERROR_TARGET,
82 },
83 },
84 },
85 .errorname = "ERROR",
86 },
87 }
88}; 42};
89 43
90static struct xt_table packet_raw = { 44static struct xt_table packet_raw = {
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 6d2a08205111..dc442fb791b0 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -177,8 +177,7 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
177 177
178 protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum, 178 protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum,
179 (*pskb)->len - extoff); 179 (*pskb)->len - extoff);
180 if (protoff < 0 || protoff > (*pskb)->len || 180 if (protoff > (*pskb)->len || pnum == NEXTHDR_FRAGMENT) {
181 pnum == NEXTHDR_FRAGMENT) {
182 DEBUGP("proto header not found\n"); 181 DEBUGP("proto header not found\n");
183 return NF_ACCEPT; 182 return NF_ACCEPT;
184 } 183 }
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 0be790d250f9..8814b95b2326 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -168,8 +168,7 @@ icmpv6_error_message(struct sk_buff *skb,
168 skb->len - inip6off 168 skb->len - inip6off
169 - sizeof(struct ipv6hdr)); 169 - sizeof(struct ipv6hdr));
170 170
171 if ((inprotoff < 0) || (inprotoff > skb->len) || 171 if ((inprotoff > skb->len) || (inprotonum == NEXTHDR_FRAGMENT)) {
172 (inprotonum == NEXTHDR_FRAGMENT)) {
173 DEBUGP("icmpv6_error: Can't get protocol header in ICMPv6 payload.\n"); 172 DEBUGP("icmpv6_error: Can't get protocol header in ICMPv6 payload.\n");
174 return -NF_ACCEPT; 173 return -NF_ACCEPT;
175 } 174 }
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 009a1047fc3f..a58459a76684 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -818,8 +818,12 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
818 if (final_p) 818 if (final_p)
819 ipv6_addr_copy(&fl.fl6_dst, final_p); 819 ipv6_addr_copy(&fl.fl6_dst, final_p);
820 820
821 if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0) 821 if ((err = __xfrm_lookup(&dst, &fl, sk, 1)) < 0) {
822 goto out; 822 if (err == -EREMOTE)
823 err = ip6_dst_blackhole(sk, &dst, &fl);
824 if (err < 0)
825 goto out;
826 }
823 827
824 if (hlimit < 0) { 828 if (hlimit < 0) {
825 if (ipv6_addr_is_multicast(&fl.fl6_dst)) 829 if (ipv6_addr_is_multicast(&fl.fl6_dst))
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index b46ad53044ba..1324b06796c0 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -119,6 +119,19 @@ static struct dst_ops ip6_dst_ops = {
119 .entry_size = sizeof(struct rt6_info), 119 .entry_size = sizeof(struct rt6_info),
120}; 120};
121 121
122static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
123{
124}
125
126static struct dst_ops ip6_dst_blackhole_ops = {
127 .family = AF_INET6,
128 .protocol = __constant_htons(ETH_P_IPV6),
129 .destroy = ip6_dst_destroy,
130 .check = ip6_dst_check,
131 .update_pmtu = ip6_rt_blackhole_update_pmtu,
132 .entry_size = sizeof(struct rt6_info),
133};
134
122struct rt6_info ip6_null_entry = { 135struct rt6_info ip6_null_entry = {
123 .u = { 136 .u = {
124 .dst = { 137 .dst = {
@@ -833,6 +846,54 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
833 846
834EXPORT_SYMBOL(ip6_route_output); 847EXPORT_SYMBOL(ip6_route_output);
835 848
849static int ip6_blackhole_output(struct sk_buff *skb)
850{
851 kfree_skb(skb);
852 return 0;
853}
854
855int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl)
856{
857 struct rt6_info *ort = (struct rt6_info *) *dstp;
858 struct rt6_info *rt = (struct rt6_info *)
859 dst_alloc(&ip6_dst_blackhole_ops);
860 struct dst_entry *new = NULL;
861
862 if (rt) {
863 new = &rt->u.dst;
864
865 atomic_set(&new->__refcnt, 1);
866 new->__use = 1;
867 new->input = ip6_blackhole_output;
868 new->output = ip6_blackhole_output;
869
870 memcpy(new->metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32));
871 new->dev = ort->u.dst.dev;
872 if (new->dev)
873 dev_hold(new->dev);
874 rt->rt6i_idev = ort->rt6i_idev;
875 if (rt->rt6i_idev)
876 in6_dev_hold(rt->rt6i_idev);
877 rt->rt6i_expires = 0;
878
879 ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway);
880 rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES;
881 rt->rt6i_metric = 0;
882
883 memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key));
884#ifdef CONFIG_IPV6_SUBTREES
885 memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key));
886#endif
887
888 dst_free(new);
889 }
890
891 dst_release(*dstp);
892 *dstp = new;
893 return (new ? 0 : -ENOMEM);
894}
895EXPORT_SYMBOL_GPL(ip6_dst_blackhole);
896
836/* 897/*
837 * Destination cache support functions 898 * Destination cache support functions
838 */ 899 */
@@ -2495,6 +2556,8 @@ void __init ip6_route_init(void)
2495 ip6_dst_ops.kmem_cachep = 2556 ip6_dst_ops.kmem_cachep =
2496 kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0, 2557 kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0,
2497 SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); 2558 SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
2559 ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep;
2560
2498 fib6_init(); 2561 fib6_init();
2499#ifdef CONFIG_PROC_FS 2562#ifdef CONFIG_PROC_FS
2500 p = proc_net_create("ipv6_route", 0, rt6_proc_info); 2563 p = proc_net_create("ipv6_route", 0, rt6_proc_info);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index e2f25ea43b68..4f06a51ad4fd 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -265,8 +265,12 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
265 if (final_p) 265 if (final_p)
266 ipv6_addr_copy(&fl.fl6_dst, final_p); 266 ipv6_addr_copy(&fl.fl6_dst, final_p);
267 267
268 if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0) 268 if ((err = __xfrm_lookup(&dst, &fl, sk, 1)) < 0) {
269 goto failure; 269 if (err == -EREMOTE)
270 err = ip6_dst_blackhole(sk, &dst, &fl);
271 if (err < 0)
272 goto failure;
273 }
270 274
271 if (saddr == NULL) { 275 if (saddr == NULL) {
272 saddr = &fl.fl6_src; 276 saddr = &fl.fl6_src;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index b083c09e3d2d..d1fbddd172e7 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -52,9 +52,28 @@
52 52
53DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly; 53DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly;
54 54
55static int ipv6_rcv_saddr_any(const struct sock *sk)
56{
57 struct ipv6_pinfo *np = inet6_sk(sk);
58
59 return ipv6_addr_any(&np->rcv_saddr);
60}
61
62static unsigned int ipv6_hash_port_and_rcv_saddr(__u16 port,
63 const struct sock *sk)
64{
65 return port;
66}
67
68const struct udp_get_port_ops udp_ipv6_ops = {
69 .saddr_cmp = ipv6_rcv_saddr_equal,
70 .saddr_any = ipv6_rcv_saddr_any,
71 .hash_port_and_rcv_saddr = ipv6_hash_port_and_rcv_saddr,
72};
73
55static inline int udp_v6_get_port(struct sock *sk, unsigned short snum) 74static inline int udp_v6_get_port(struct sock *sk, unsigned short snum)
56{ 75{
57 return udp_get_port(sk, snum, ipv6_rcv_saddr_equal); 76 return udp_get_port(sk, snum, &udp_ipv6_ops);
58} 77}
59 78
60static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport, 79static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport,
@@ -748,8 +767,12 @@ do_udp_sendmsg:
748 if (final_p) 767 if (final_p)
749 ipv6_addr_copy(&fl.fl6_dst, final_p); 768 ipv6_addr_copy(&fl.fl6_dst, final_p);
750 769
751 if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0) 770 if ((err = __xfrm_lookup(&dst, &fl, sk, 1)) < 0) {
752 goto out; 771 if (err == -EREMOTE)
772 err = ip6_dst_blackhole(sk, &dst, &fl);
773 if (err < 0)
774 goto out;
775 }
753 776
754 if (hlimit < 0) { 777 if (hlimit < 0) {
755 if (ipv6_addr_is_multicast(&fl.fl6_dst)) 778 if (ipv6_addr_is_multicast(&fl.fl6_dst))
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h
index 6e252f318f7c..36b0c11a28a3 100644
--- a/net/ipv6/udp_impl.h
+++ b/net/ipv6/udp_impl.h
@@ -6,6 +6,8 @@
6#include <net/addrconf.h> 6#include <net/addrconf.h>
7#include <net/inet_common.h> 7#include <net/inet_common.h>
8 8
9extern const struct udp_get_port_ops udp_ipv6_ops;
10
9extern int __udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int ); 11extern int __udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int );
10extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, 12extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *,
11 int , int , int , __be32 , struct hlist_head []); 13 int , int , int , __be32 , struct hlist_head []);
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c
index f54016a55004..c40a51362f89 100644
--- a/net/ipv6/udplite.c
+++ b/net/ipv6/udplite.c
@@ -37,7 +37,7 @@ static struct inet6_protocol udplitev6_protocol = {
37 37
38static int udplite_v6_get_port(struct sock *sk, unsigned short snum) 38static int udplite_v6_get_port(struct sock *sk, unsigned short snum)
39{ 39{
40 return udplite_get_port(sk, snum, ipv6_rcv_saddr_equal); 40 return udplite_get_port(sk, snum, &udp_ipv6_ops);
41} 41}
42 42
43struct proto udplitev6_prot = { 43struct proto udplitev6_prot = {
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index d7ed8aa56ec1..c858537cec4b 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -104,10 +104,8 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi)
104 nf_reset(skb); 104 nf_reset(skb);
105 105
106 if (decaps) { 106 if (decaps) {
107 if (!(skb->dev->flags&IFF_LOOPBACK)) { 107 dst_release(skb->dst);
108 dst_release(skb->dst); 108 skb->dst = NULL;
109 skb->dst = NULL;
110 }
111 netif_rx(skb); 109 netif_rx(skb);
112 return -1; 110 return -1;
113 } else { 111 } else {
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index a6c0cdf46ad6..9fc95bc6509f 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -80,6 +80,7 @@ static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
80 top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT); 80 top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT);
81 ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); 81 ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
82 ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); 82 ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
83 skb->protocol = htons(ETH_P_IPV6);
83 return 0; 84 return 0;
84} 85}
85 86