aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/Kconfig29
-rw-r--r--net/ipv6/Makefile3
-rw-r--r--net/ipv6/addrconf.c18
-rw-r--r--net/ipv6/af_inet6.c2
-rw-r--r--net/ipv6/fib6_rules.c11
-rw-r--r--net/ipv6/ip6_fib.c9
-rw-r--r--net/ipv6/ip6_flowlabel.c24
-rw-r--r--net/ipv6/ip6_tunnel.c19
-rw-r--r--net/ipv6/ndisc.c3
-rw-r--r--net/ipv6/netfilter/Kconfig2
-rw-r--r--net/ipv6/netfilter/ip6_queue.c7
-rw-r--r--net/ipv6/netfilter/ip6_tables.c47
-rw-r--r--net/ipv6/netfilter/ip6t_ah.c7
-rw-r--r--net/ipv6/netfilter/ip6t_frag.c7
-rw-r--r--net/ipv6/netfilter/ip6t_hbh.c7
-rw-r--r--net/ipv6/netfilter/ip6t_rt.c7
-rw-r--r--net/ipv6/raw.c17
-rw-r--r--net/ipv6/route.c81
-rw-r--r--net/ipv6/sit.c5
-rw-r--r--net/ipv6/tcp_ipv6.c13
-rw-r--r--net/ipv6/udp.c7
-rw-r--r--net/ipv6/xfrm6_policy.c14
-rw-r--r--net/ipv6/xfrm6_tunnel.c4
23 files changed, 238 insertions, 105 deletions
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index a460e8132b4d..6e48f52e197c 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -153,6 +153,19 @@ config INET6_XFRM_MODE_ROUTEOPTIMIZATION
153 ---help--- 153 ---help---
154 Support for MIPv6 route optimization mode. 154 Support for MIPv6 route optimization mode.
155 155
156config IPV6_SIT
157 tristate "IPv6: IPv6-in-IPv4 tunnel (SIT driver)"
158 depends on IPV6
159 default y
160 ---help---
161 Tunneling means encapsulating data of one protocol type within
162 another protocol and sending it over a channel that understands the
163 encapsulating protocol. This driver implements encapsulation of IPv6
164 into IPv4 packets. This is useful if you want to connect two IPv6
165 networks over an IPv4-only path.
166
167 Saying M here will produce a module called sit.ko. If unsure, say Y.
168
156config IPV6_TUNNEL 169config IPV6_TUNNEL
157 tristate "IPv6: IPv6-in-IPv6 tunnel" 170 tristate "IPv6: IPv6-in-IPv6 tunnel"
158 select INET6_TUNNEL 171 select INET6_TUNNEL
@@ -162,9 +175,16 @@ config IPV6_TUNNEL
162 175
163 If unsure, say N. 176 If unsure, say N.
164 177
178config IPV6_MULTIPLE_TABLES
179 bool "IPv6: Multiple Routing Tables"
180 depends on IPV6 && EXPERIMENTAL
181 select FIB_RULES
182 ---help---
183 Support multiple routing tables.
184
165config IPV6_SUBTREES 185config IPV6_SUBTREES
166 bool "IPv6: source address based routing" 186 bool "IPv6: source address based routing"
167 depends on IPV6 && EXPERIMENTAL 187 depends on IPV6_MULTIPLE_TABLES
168 ---help--- 188 ---help---
169 Enable routing by source address or prefix. 189 Enable routing by source address or prefix.
170 190
@@ -176,13 +196,6 @@ config IPV6_SUBTREES
176 196
177 If unsure, say N. 197 If unsure, say N.
178 198
179config IPV6_MULTIPLE_TABLES
180 bool "IPv6: Multiple Routing Tables"
181 depends on IPV6 && EXPERIMENTAL
182 select FIB_RULES
183 ---help---
184 Support multiple routing tables.
185
186config IPV6_ROUTE_FWMARK 199config IPV6_ROUTE_FWMARK
187 bool "IPv6: use netfilter MARK value as routing key" 200 bool "IPv6: use netfilter MARK value as routing key"
188 depends on IPV6_MULTIPLE_TABLES && NETFILTER 201 depends on IPV6_MULTIPLE_TABLES && NETFILTER
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index 87274e47fe32..addcc011bc01 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -4,7 +4,7 @@
4 4
5obj-$(CONFIG_IPV6) += ipv6.o 5obj-$(CONFIG_IPV6) += ipv6.o
6 6
7ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o sit.o \ 7ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \
8 route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o raw.o \ 8 route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o raw.o \
9 protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ 9 protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
10 exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \ 10 exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \
@@ -29,6 +29,7 @@ obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o
29obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o 29obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o
30obj-$(CONFIG_NETFILTER) += netfilter/ 30obj-$(CONFIG_NETFILTER) += netfilter/
31 31
32obj-$(CONFIG_IPV6_SIT) += sit.o
32obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o 33obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
33 34
34obj-y += exthdrs_core.o 35obj-y += exthdrs_core.o
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index e03c33b2465b..b312a5f7a759 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -396,8 +396,10 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
396 ndev->regen_timer.data = (unsigned long) ndev; 396 ndev->regen_timer.data = (unsigned long) ndev;
397 if ((dev->flags&IFF_LOOPBACK) || 397 if ((dev->flags&IFF_LOOPBACK) ||
398 dev->type == ARPHRD_TUNNEL || 398 dev->type == ARPHRD_TUNNEL ||
399 dev->type == ARPHRD_NONE || 399#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
400 dev->type == ARPHRD_SIT) { 400 dev->type == ARPHRD_SIT ||
401#endif
402 dev->type == ARPHRD_NONE) {
401 printk(KERN_INFO 403 printk(KERN_INFO
402 "%s: Disabled Privacy Extensions\n", 404 "%s: Disabled Privacy Extensions\n",
403 dev->name); 405 dev->name);
@@ -1546,8 +1548,10 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
1546 This thing is done here expecting that the whole 1548 This thing is done here expecting that the whole
1547 class of non-broadcast devices need not cloning. 1549 class of non-broadcast devices need not cloning.
1548 */ 1550 */
1551#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
1549 if (dev->type == ARPHRD_SIT && (dev->flags & IFF_POINTOPOINT)) 1552 if (dev->type == ARPHRD_SIT && (dev->flags & IFF_POINTOPOINT))
1550 cfg.fc_flags |= RTF_NONEXTHOP; 1553 cfg.fc_flags |= RTF_NONEXTHOP;
1554#endif
1551 1555
1552 ip6_route_add(&cfg); 1556 ip6_route_add(&cfg);
1553} 1557}
@@ -1569,6 +1573,7 @@ static void addrconf_add_mroute(struct net_device *dev)
1569 ip6_route_add(&cfg); 1573 ip6_route_add(&cfg);
1570} 1574}
1571 1575
1576#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
1572static void sit_route_add(struct net_device *dev) 1577static void sit_route_add(struct net_device *dev)
1573{ 1578{
1574 struct fib6_config cfg = { 1579 struct fib6_config cfg = {
@@ -1582,6 +1587,7 @@ static void sit_route_add(struct net_device *dev)
1582 /* prefix length - 96 bits "::d.d.d.d" */ 1587 /* prefix length - 96 bits "::d.d.d.d" */
1583 ip6_route_add(&cfg); 1588 ip6_route_add(&cfg);
1584} 1589}
1590#endif
1585 1591
1586static void addrconf_add_lroute(struct net_device *dev) 1592static void addrconf_add_lroute(struct net_device *dev)
1587{ 1593{
@@ -1852,6 +1858,7 @@ int addrconf_set_dstaddr(void __user *arg)
1852 if (dev == NULL) 1858 if (dev == NULL)
1853 goto err_exit; 1859 goto err_exit;
1854 1860
1861#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
1855 if (dev->type == ARPHRD_SIT) { 1862 if (dev->type == ARPHRD_SIT) {
1856 struct ifreq ifr; 1863 struct ifreq ifr;
1857 mm_segment_t oldfs; 1864 mm_segment_t oldfs;
@@ -1881,6 +1888,7 @@ int addrconf_set_dstaddr(void __user *arg)
1881 err = dev_open(dev); 1888 err = dev_open(dev);
1882 } 1889 }
1883 } 1890 }
1891#endif
1884 1892
1885err_exit: 1893err_exit:
1886 rtnl_unlock(); 1894 rtnl_unlock();
@@ -2010,6 +2018,7 @@ int addrconf_del_ifaddr(void __user *arg)
2010 return err; 2018 return err;
2011} 2019}
2012 2020
2021#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
2013static void sit_add_v4_addrs(struct inet6_dev *idev) 2022static void sit_add_v4_addrs(struct inet6_dev *idev)
2014{ 2023{
2015 struct inet6_ifaddr * ifp; 2024 struct inet6_ifaddr * ifp;
@@ -2078,6 +2087,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev)
2078 } 2087 }
2079 } 2088 }
2080} 2089}
2090#endif
2081 2091
2082static void init_loopback(struct net_device *dev) 2092static void init_loopback(struct net_device *dev)
2083{ 2093{
@@ -2141,6 +2151,7 @@ static void addrconf_dev_config(struct net_device *dev)
2141 addrconf_add_linklocal(idev, &addr); 2151 addrconf_add_linklocal(idev, &addr);
2142} 2152}
2143 2153
2154#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
2144static void addrconf_sit_config(struct net_device *dev) 2155static void addrconf_sit_config(struct net_device *dev)
2145{ 2156{
2146 struct inet6_dev *idev; 2157 struct inet6_dev *idev;
@@ -2166,6 +2177,7 @@ static void addrconf_sit_config(struct net_device *dev)
2166 } else 2177 } else
2167 sit_route_add(dev); 2178 sit_route_add(dev);
2168} 2179}
2180#endif
2169 2181
2170static inline int 2182static inline int
2171ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev) 2183ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev)
@@ -2260,9 +2272,11 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
2260 } 2272 }
2261 2273
2262 switch(dev->type) { 2274 switch(dev->type) {
2275#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
2263 case ARPHRD_SIT: 2276 case ARPHRD_SIT:
2264 addrconf_sit_config(dev); 2277 addrconf_sit_config(dev);
2265 break; 2278 break;
2279#endif
2266 case ARPHRD_TUNNEL6: 2280 case ARPHRD_TUNNEL6:
2267 addrconf_ip6_tnl_config(dev); 2281 addrconf_ip6_tnl_config(dev);
2268 break; 2282 break;
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index e94eccb99707..858cae29581c 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -850,7 +850,6 @@ static int __init inet6_init(void)
850 err = addrconf_init(); 850 err = addrconf_init();
851 if (err) 851 if (err)
852 goto addrconf_fail; 852 goto addrconf_fail;
853 sit_init();
854 853
855 /* Init v6 extension headers. */ 854 /* Init v6 extension headers. */
856 ipv6_rthdr_init(); 855 ipv6_rthdr_init();
@@ -927,7 +926,6 @@ static void __exit inet6_exit(void)
927 mip6_fini(); 926 mip6_fini();
928#endif 927#endif
929 /* Cleanup code parts. */ 928 /* Cleanup code parts. */
930 sit_cleanup();
931 ip6_flowlabel_cleanup(); 929 ip6_flowlabel_cleanup();
932 addrconf_cleanup(); 930 addrconf_cleanup();
933 ip6_route_cleanup(); 931 ip6_route_cleanup();
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index d8c1057e8b00..1896ecb52899 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -117,12 +117,15 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
117{ 117{
118 struct fib6_rule *r = (struct fib6_rule *) rule; 118 struct fib6_rule *r = (struct fib6_rule *) rule;
119 119
120 if (!ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen)) 120 if (r->dst.plen &&
121 !ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen))
121 return 0; 122 return 0;
122 123
123 if ((flags & RT6_LOOKUP_F_HAS_SADDR) && 124 if (r->src.plen) {
124 !ipv6_prefix_equal(&fl->fl6_src, &r->src.addr, r->src.plen)) 125 if (!(flags & RT6_LOOKUP_F_HAS_SADDR) ||
125 return 0; 126 !ipv6_prefix_equal(&fl->fl6_src, &r->src.addr, r->src.plen))
127 return 0;
128 }
126 129
127 if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff)) 130 if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff))
128 return 0; 131 return 0;
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 8fcae7a6510b..f98ca30d7c1f 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -169,7 +169,6 @@ static __inline__ void rt6_release(struct rt6_info *rt)
169 169
170static struct fib6_table fib6_main_tbl = { 170static struct fib6_table fib6_main_tbl = {
171 .tb6_id = RT6_TABLE_MAIN, 171 .tb6_id = RT6_TABLE_MAIN,
172 .tb6_lock = RW_LOCK_UNLOCKED,
173 .tb6_root = { 172 .tb6_root = {
174 .leaf = &ip6_null_entry, 173 .leaf = &ip6_null_entry,
175 .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO, 174 .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
@@ -187,6 +186,12 @@ static void fib6_link_table(struct fib6_table *tb)
187{ 186{
188 unsigned int h; 187 unsigned int h;
189 188
189 /*
190 * Initialize table lock at a single place to give lockdep a key,
191 * tables aren't visible prior to being linked to the list.
192 */
193 rwlock_init(&tb->tb6_lock);
194
190 h = tb->tb6_id & (FIB_TABLE_HASHSZ - 1); 195 h = tb->tb6_id & (FIB_TABLE_HASHSZ - 1);
191 196
192 /* 197 /*
@@ -199,7 +204,6 @@ static void fib6_link_table(struct fib6_table *tb)
199#ifdef CONFIG_IPV6_MULTIPLE_TABLES 204#ifdef CONFIG_IPV6_MULTIPLE_TABLES
200static struct fib6_table fib6_local_tbl = { 205static struct fib6_table fib6_local_tbl = {
201 .tb6_id = RT6_TABLE_LOCAL, 206 .tb6_id = RT6_TABLE_LOCAL,
202 .tb6_lock = RW_LOCK_UNLOCKED,
203 .tb6_root = { 207 .tb6_root = {
204 .leaf = &ip6_null_entry, 208 .leaf = &ip6_null_entry,
205 .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO, 209 .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
@@ -213,7 +217,6 @@ static struct fib6_table *fib6_alloc_table(u32 id)
213 table = kzalloc(sizeof(*table), GFP_ATOMIC); 217 table = kzalloc(sizeof(*table), GFP_ATOMIC);
214 if (table != NULL) { 218 if (table != NULL) {
215 table->tb6_id = id; 219 table->tb6_id = id;
216 table->tb6_lock = RW_LOCK_UNLOCKED;
217 table->tb6_root.leaf = &ip6_null_entry; 220 table->tb6_root.leaf = &ip6_null_entry;
218 table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; 221 table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
219 } 222 }
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 1d672b0547f2..6d4533b58dca 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -330,8 +330,10 @@ fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int *
330 fl->share = freq->flr_share; 330 fl->share = freq->flr_share;
331 addr_type = ipv6_addr_type(&freq->flr_dst); 331 addr_type = ipv6_addr_type(&freq->flr_dst);
332 if ((addr_type&IPV6_ADDR_MAPPED) 332 if ((addr_type&IPV6_ADDR_MAPPED)
333 || addr_type == IPV6_ADDR_ANY) 333 || addr_type == IPV6_ADDR_ANY) {
334 err = -EINVAL;
334 goto done; 335 goto done;
336 }
335 ipv6_addr_copy(&fl->dst, &freq->flr_dst); 337 ipv6_addr_copy(&fl->dst, &freq->flr_dst);
336 atomic_set(&fl->users, 1); 338 atomic_set(&fl->users, 1);
337 switch (fl->share) { 339 switch (fl->share) {
@@ -587,6 +589,8 @@ static struct ip6_flowlabel *ip6fl_get_next(struct seq_file *seq, struct ip6_flo
587 while (!fl) { 589 while (!fl) {
588 if (++state->bucket <= FL_HASH_MASK) 590 if (++state->bucket <= FL_HASH_MASK)
589 fl = fl_ht[state->bucket]; 591 fl = fl_ht[state->bucket];
592 else
593 break;
590 } 594 }
591 return fl; 595 return fl;
592} 596}
@@ -623,9 +627,13 @@ static void ip6fl_seq_stop(struct seq_file *seq, void *v)
623 read_unlock_bh(&ip6_fl_lock); 627 read_unlock_bh(&ip6_fl_lock);
624} 628}
625 629
626static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl) 630static int ip6fl_seq_show(struct seq_file *seq, void *v)
627{ 631{
628 while(fl) { 632 if (v == SEQ_START_TOKEN)
633 seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n",
634 "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt");
635 else {
636 struct ip6_flowlabel *fl = v;
629 seq_printf(seq, 637 seq_printf(seq,
630 "%05X %-1d %-6d %-6d %-6ld %-8ld " NIP6_SEQFMT " %-4d\n", 638 "%05X %-1d %-6d %-6d %-6ld %-8ld " NIP6_SEQFMT " %-4d\n",
631 (unsigned)ntohl(fl->label), 639 (unsigned)ntohl(fl->label),
@@ -636,17 +644,7 @@ static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl)
636 (long)(fl->expires - jiffies)/HZ, 644 (long)(fl->expires - jiffies)/HZ,
637 NIP6(fl->dst), 645 NIP6(fl->dst),
638 fl->opt ? fl->opt->opt_nflen : 0); 646 fl->opt ? fl->opt->opt_nflen : 0);
639 fl = fl->next;
640 } 647 }
641}
642
643static int ip6fl_seq_show(struct seq_file *seq, void *v)
644{
645 if (v == SEQ_START_TOKEN)
646 seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n",
647 "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt");
648 else
649 ip6fl_fl_seq_show(seq, v);
650 return 0; 648 return 0;
651} 649}
652 650
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 84d7ebdb9d21..b9f40290d12a 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -542,6 +542,7 @@ ip6ip6_rcv(struct sk_buff *skb)
542 skb->dev = t->dev; 542 skb->dev = t->dev;
543 dst_release(skb->dst); 543 dst_release(skb->dst);
544 skb->dst = NULL; 544 skb->dst = NULL;
545 nf_reset(skb);
545 if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) 546 if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY)
546 ipv6_copy_dscp(ipv6h, skb->nh.ipv6h); 547 ipv6_copy_dscp(ipv6h, skb->nh.ipv6h);
547 ip6ip6_ecn_decapsulate(ipv6h, skb); 548 ip6ip6_ecn_decapsulate(ipv6h, skb);
@@ -1149,6 +1150,20 @@ fail:
1149 return err; 1150 return err;
1150} 1151}
1151 1152
1153static void __exit ip6ip6_destroy_tunnels(void)
1154{
1155 int h;
1156 struct ip6_tnl *t;
1157
1158 for (h = 0; h < HASH_SIZE; h++) {
1159 while ((t = tnls_r_l[h]) != NULL)
1160 unregister_netdevice(t->dev);
1161 }
1162
1163 t = tnls_wc[0];
1164 unregister_netdevice(t->dev);
1165}
1166
1152/** 1167/**
1153 * ip6_tunnel_cleanup - free resources and unregister protocol 1168 * ip6_tunnel_cleanup - free resources and unregister protocol
1154 **/ 1169 **/
@@ -1158,7 +1173,9 @@ static void __exit ip6_tunnel_cleanup(void)
1158 if (xfrm6_tunnel_deregister(&ip6ip6_handler)) 1173 if (xfrm6_tunnel_deregister(&ip6ip6_handler))
1159 printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n"); 1174 printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n");
1160 1175
1161 unregister_netdev(ip6ip6_fb_tnl_dev); 1176 rtnl_lock();
1177 ip6ip6_destroy_tunnels();
1178 rtnl_unlock();
1162} 1179}
1163 1180
1164module_init(ip6_tunnel_init); 1181module_init(ip6_tunnel_init);
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 0304b5fe8d6a..73eb8c33e9f0 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -967,8 +967,6 @@ static void ndisc_recv_na(struct sk_buff *skb)
967 ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp && 967 ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp &&
968 pneigh_lookup(&nd_tbl, &msg->target, dev, 0)) { 968 pneigh_lookup(&nd_tbl, &msg->target, dev, 0)) {
969 /* XXX: idev->cnf.prixy_ndp */ 969 /* XXX: idev->cnf.prixy_ndp */
970 WARN_ON(skb->dst != NULL &&
971 ((struct rt6_info *)skb->dst)->rt6i_idev);
972 goto out; 970 goto out;
973 } 971 }
974 972
@@ -1744,6 +1742,7 @@ int __init ndisc_init(struct net_proto_family *ops)
1744 1742
1745void ndisc_cleanup(void) 1743void ndisc_cleanup(void)
1746{ 1744{
1745 unregister_netdevice_notifier(&ndisc_netdev_notifier);
1747#ifdef CONFIG_SYSCTL 1746#ifdef CONFIG_SYSCTL
1748 neigh_sysctl_unregister(&nd_tbl.parms); 1747 neigh_sysctl_unregister(&nd_tbl.parms);
1749#endif 1748#endif
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 4bc4e5b33794..d7c45a9c15fe 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -40,7 +40,7 @@ config IP6_NF_QUEUE
40 To compile it as a module, choose M here. If unsure, say N. 40 To compile it as a module, choose M here. If unsure, say N.
41 41
42config IP6_NF_IPTABLES 42config IP6_NF_IPTABLES
43 tristate "IP6 tables support (required for filtering/masq/NAT)" 43 tristate "IP6 tables support (required for filtering)"
44 depends on NETFILTER_XTABLES 44 depends on NETFILTER_XTABLES
45 help 45 help
46 ip6tables is a general, extensible packet identification framework. 46 ip6tables is a general, extensible packet identification framework.
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index 9510c24ca8d2..9fec832ee08b 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -349,9 +349,10 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
349 if (v->data_len < sizeof(*user_iph)) 349 if (v->data_len < sizeof(*user_iph))
350 return 0; 350 return 0;
351 diff = v->data_len - e->skb->len; 351 diff = v->data_len - e->skb->len;
352 if (diff < 0) 352 if (diff < 0) {
353 skb_trim(e->skb, v->data_len); 353 if (pskb_trim(e->skb, v->data_len))
354 else if (diff > 0) { 354 return -ENOMEM;
355 } else if (diff > 0) {
355 if (v->data_len > 0xFFFF) 356 if (v->data_len > 0xFFFF)
356 return -EINVAL; 357 return -EINVAL;
357 if (diff > skb_tailroom(e->skb)) { 358 if (diff > skb_tailroom(e->skb)) {
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 4ab368fa0b8f..204e02162d49 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -111,7 +111,7 @@ ip6_packet_match(const struct sk_buff *skb,
111 const char *outdev, 111 const char *outdev,
112 const struct ip6t_ip6 *ip6info, 112 const struct ip6t_ip6 *ip6info,
113 unsigned int *protoff, 113 unsigned int *protoff,
114 int *fragoff) 114 int *fragoff, int *hotdrop)
115{ 115{
116 size_t i; 116 size_t i;
117 unsigned long ret; 117 unsigned long ret;
@@ -169,9 +169,11 @@ ip6_packet_match(const struct sk_buff *skb,
169 unsigned short _frag_off; 169 unsigned short _frag_off;
170 170
171 protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off); 171 protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off);
172 if (protohdr < 0) 172 if (protohdr < 0) {
173 if (_frag_off == 0)
174 *hotdrop = 1;
173 return 0; 175 return 0;
174 176 }
175 *fragoff = _frag_off; 177 *fragoff = _frag_off;
176 178
177 dprintf("Packet protocol %hi ?= %s%hi.\n", 179 dprintf("Packet protocol %hi ?= %s%hi.\n",
@@ -290,7 +292,7 @@ ip6t_do_table(struct sk_buff **pskb,
290 IP_NF_ASSERT(e); 292 IP_NF_ASSERT(e);
291 IP_NF_ASSERT(back); 293 IP_NF_ASSERT(back);
292 if (ip6_packet_match(*pskb, indev, outdev, &e->ipv6, 294 if (ip6_packet_match(*pskb, indev, outdev, &e->ipv6,
293 &protoff, &offset)) { 295 &protoff, &offset, &hotdrop)) {
294 struct ip6t_entry_target *t; 296 struct ip6t_entry_target *t;
295 297
296 if (IP6T_MATCH_ITERATE(e, do_match, 298 if (IP6T_MATCH_ITERATE(e, do_match,
@@ -584,12 +586,19 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
584 return -EINVAL; 586 return -EINVAL;
585 } 587 }
586 588
589 if (e->target_offset + sizeof(struct ip6t_entry_target) >
590 e->next_offset)
591 return -EINVAL;
592
587 j = 0; 593 j = 0;
588 ret = IP6T_MATCH_ITERATE(e, check_match, name, &e->ipv6, e->comefrom, &j); 594 ret = IP6T_MATCH_ITERATE(e, check_match, name, &e->ipv6, e->comefrom, &j);
589 if (ret != 0) 595 if (ret != 0)
590 goto cleanup_matches; 596 goto cleanup_matches;
591 597
592 t = ip6t_get_target(e); 598 t = ip6t_get_target(e);
599 ret = -EINVAL;
600 if (e->target_offset + t->u.target_size > e->next_offset)
601 goto cleanup_matches;
593 target = try_then_request_module(xt_find_target(AF_INET6, 602 target = try_then_request_module(xt_find_target(AF_INET6,
594 t->u.user.name, 603 t->u.user.name,
595 t->u.user.revision), 604 t->u.user.revision),
@@ -749,19 +758,17 @@ translate_table(const char *name,
749 } 758 }
750 } 759 }
751 760
752 if (!mark_source_chains(newinfo, valid_hooks, entry0))
753 return -ELOOP;
754
755 /* Finally, each sanity check must pass */ 761 /* Finally, each sanity check must pass */
756 i = 0; 762 i = 0;
757 ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size, 763 ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size,
758 check_entry, name, size, &i); 764 check_entry, name, size, &i);
759 765
760 if (ret != 0) { 766 if (ret != 0)
761 IP6T_ENTRY_ITERATE(entry0, newinfo->size, 767 goto cleanup;
762 cleanup_entry, &i); 768
763 return ret; 769 ret = -ELOOP;
764 } 770 if (!mark_source_chains(newinfo, valid_hooks, entry0))
771 goto cleanup;
765 772
766 /* And one copy for every other CPU */ 773 /* And one copy for every other CPU */
767 for_each_possible_cpu(i) { 774 for_each_possible_cpu(i) {
@@ -769,6 +776,9 @@ translate_table(const char *name,
769 memcpy(newinfo->entries[i], entry0, newinfo->size); 776 memcpy(newinfo->entries[i], entry0, newinfo->size);
770 } 777 }
771 778
779 return 0;
780cleanup:
781 IP6T_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
772 return ret; 782 return ret;
773} 783}
774 784
@@ -1438,6 +1448,9 @@ static void __exit ip6_tables_fini(void)
1438 * If target header is found, its offset is set in *offset and return protocol 1448 * If target header is found, its offset is set in *offset and return protocol
1439 * number. Otherwise, return -1. 1449 * number. Otherwise, return -1.
1440 * 1450 *
1451 * If the first fragment doesn't contain the final protocol header or
1452 * NEXTHDR_NONE it is considered invalid.
1453 *
1441 * Note that non-1st fragment is special case that "the protocol number 1454 * Note that non-1st fragment is special case that "the protocol number
1442 * of last header" is "next header" field in Fragment header. In this case, 1455 * of last header" is "next header" field in Fragment header. In this case,
1443 * *offset is meaningless and fragment offset is stored in *fragoff if fragoff 1456 * *offset is meaningless and fragment offset is stored in *fragoff if fragoff
@@ -1461,12 +1474,12 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
1461 if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) { 1474 if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) {
1462 if (target < 0) 1475 if (target < 0)
1463 break; 1476 break;
1464 return -1; 1477 return -ENOENT;
1465 } 1478 }
1466 1479
1467 hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr); 1480 hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
1468 if (hp == NULL) 1481 if (hp == NULL)
1469 return -1; 1482 return -EBADMSG;
1470 if (nexthdr == NEXTHDR_FRAGMENT) { 1483 if (nexthdr == NEXTHDR_FRAGMENT) {
1471 unsigned short _frag_off, *fp; 1484 unsigned short _frag_off, *fp;
1472 fp = skb_header_pointer(skb, 1485 fp = skb_header_pointer(skb,
@@ -1475,18 +1488,18 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
1475 sizeof(_frag_off), 1488 sizeof(_frag_off),
1476 &_frag_off); 1489 &_frag_off);
1477 if (fp == NULL) 1490 if (fp == NULL)
1478 return -1; 1491 return -EBADMSG;
1479 1492
1480 _frag_off = ntohs(*fp) & ~0x7; 1493 _frag_off = ntohs(*fp) & ~0x7;
1481 if (_frag_off) { 1494 if (_frag_off) {
1482 if (target < 0 && 1495 if (target < 0 &&
1483 ((!ipv6_ext_hdr(hp->nexthdr)) || 1496 ((!ipv6_ext_hdr(hp->nexthdr)) ||
1484 nexthdr == NEXTHDR_NONE)) { 1497 hp->nexthdr == NEXTHDR_NONE)) {
1485 if (fragoff) 1498 if (fragoff)
1486 *fragoff = _frag_off; 1499 *fragoff = _frag_off;
1487 return hp->nexthdr; 1500 return hp->nexthdr;
1488 } 1501 }
1489 return -1; 1502 return -ENOENT;
1490 } 1503 }
1491 hdrlen = 8; 1504 hdrlen = 8;
1492 } else if (nexthdr == NEXTHDR_AUTH) 1505 } else if (nexthdr == NEXTHDR_AUTH)
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index ec1b1608156c..46486645eb75 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -54,9 +54,14 @@ match(const struct sk_buff *skb,
54 const struct ip6t_ah *ahinfo = matchinfo; 54 const struct ip6t_ah *ahinfo = matchinfo;
55 unsigned int ptr; 55 unsigned int ptr;
56 unsigned int hdrlen = 0; 56 unsigned int hdrlen = 0;
57 int err;
57 58
58 if (ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL) < 0) 59 err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL);
60 if (err < 0) {
61 if (err != -ENOENT)
62 *hotdrop = 1;
59 return 0; 63 return 0;
64 }
60 65
61 ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah); 66 ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah);
62 if (ah == NULL) { 67 if (ah == NULL) {
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index 78d9c8b9e28a..cd22eaaccdca 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -52,9 +52,14 @@ match(const struct sk_buff *skb,
52 struct frag_hdr _frag, *fh; 52 struct frag_hdr _frag, *fh;
53 const struct ip6t_frag *fraginfo = matchinfo; 53 const struct ip6t_frag *fraginfo = matchinfo;
54 unsigned int ptr; 54 unsigned int ptr;
55 int err;
55 56
56 if (ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL) < 0) 57 err = ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL);
58 if (err < 0) {
59 if (err != -ENOENT)
60 *hotdrop = 1;
57 return 0; 61 return 0;
62 }
58 63
59 fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag); 64 fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag);
60 if (fh == NULL) { 65 if (fh == NULL) {
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index d32a205e3af2..3f25babe0440 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -65,9 +65,14 @@ match(const struct sk_buff *skb,
65 u8 _opttype, *tp = NULL; 65 u8 _opttype, *tp = NULL;
66 u8 _optlen, *lp = NULL; 66 u8 _optlen, *lp = NULL;
67 unsigned int optlen; 67 unsigned int optlen;
68 int err;
68 69
69 if (ipv6_find_hdr(skb, &ptr, match->data, NULL) < 0) 70 err = ipv6_find_hdr(skb, &ptr, match->data, NULL);
71 if (err < 0) {
72 if (err != -ENOENT)
73 *hotdrop = 1;
70 return 0; 74 return 0;
75 }
71 76
72 oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); 77 oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
73 if (oh == NULL) { 78 if (oh == NULL) {
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index bcb2e168a5bc..54d7d14134fd 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -58,9 +58,14 @@ match(const struct sk_buff *skb,
58 unsigned int hdrlen = 0; 58 unsigned int hdrlen = 0;
59 unsigned int ret = 0; 59 unsigned int ret = 0;
60 struct in6_addr *ap, _addr; 60 struct in6_addr *ap, _addr;
61 int err;
61 62
62 if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL) < 0) 63 err = ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL);
64 if (err < 0) {
65 if (err != -ENOENT)
66 *hotdrop = 1;
63 return 0; 67 return 0;
68 }
64 69
65 rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); 70 rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route);
66 if (rh == NULL) { 71 if (rh == NULL) {
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index d09329ca3267..d6dedc4aec77 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -604,7 +604,7 @@ error:
604 return err; 604 return err;
605} 605}
606 606
607static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) 607static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
608{ 608{
609 struct iovec *iov; 609 struct iovec *iov;
610 u8 __user *type = NULL; 610 u8 __user *type = NULL;
@@ -616,7 +616,7 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
616 int i; 616 int i;
617 617
618 if (!msg->msg_iov) 618 if (!msg->msg_iov)
619 return; 619 return 0;
620 620
621 for (i = 0; i < msg->msg_iovlen; i++) { 621 for (i = 0; i < msg->msg_iovlen; i++) {
622 iov = &msg->msg_iov[i]; 622 iov = &msg->msg_iov[i];
@@ -638,8 +638,9 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
638 code = iov->iov_base; 638 code = iov->iov_base;
639 639
640 if (type && code) { 640 if (type && code) {
641 get_user(fl->fl_icmp_type, type); 641 if (get_user(fl->fl_icmp_type, type) ||
642 get_user(fl->fl_icmp_code, code); 642 get_user(fl->fl_icmp_code, code))
643 return -EFAULT;
643 probed = 1; 644 probed = 1;
644 } 645 }
645 break; 646 break;
@@ -650,7 +651,8 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
650 /* check if type field is readable or not. */ 651 /* check if type field is readable or not. */
651 if (iov->iov_len > 2 - len) { 652 if (iov->iov_len > 2 - len) {
652 u8 __user *p = iov->iov_base; 653 u8 __user *p = iov->iov_base;
653 get_user(fl->fl_mh_type, &p[2 - len]); 654 if (get_user(fl->fl_mh_type, &p[2 - len]))
655 return -EFAULT;
654 probed = 1; 656 probed = 1;
655 } else 657 } else
656 len += iov->iov_len; 658 len += iov->iov_len;
@@ -664,6 +666,7 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
664 if (probed) 666 if (probed)
665 break; 667 break;
666 } 668 }
669 return 0;
667} 670}
668 671
669static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, 672static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
@@ -787,7 +790,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
787 opt = ipv6_fixup_options(&opt_space, opt); 790 opt = ipv6_fixup_options(&opt_space, opt);
788 791
789 fl.proto = proto; 792 fl.proto = proto;
790 rawv6_probe_proto_opt(&fl, msg); 793 err = rawv6_probe_proto_opt(&fl, msg);
794 if (err)
795 goto out;
791 796
792 ipv6_addr_copy(&fl.fl6_dst, daddr); 797 ipv6_addr_copy(&fl.fl6_dst, daddr);
793 if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) 798 if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index d6b4b4f48d18..b39ae99122d5 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -141,6 +141,10 @@ struct rt6_info ip6_null_entry = {
141 141
142#ifdef CONFIG_IPV6_MULTIPLE_TABLES 142#ifdef CONFIG_IPV6_MULTIPLE_TABLES
143 143
144static int ip6_pkt_prohibit(struct sk_buff *skb);
145static int ip6_pkt_prohibit_out(struct sk_buff *skb);
146static int ip6_pkt_blk_hole(struct sk_buff *skb);
147
144struct rt6_info ip6_prohibit_entry = { 148struct rt6_info ip6_prohibit_entry = {
145 .u = { 149 .u = {
146 .dst = { 150 .dst = {
@@ -150,8 +154,8 @@ struct rt6_info ip6_prohibit_entry = {
150 .obsolete = -1, 154 .obsolete = -1,
151 .error = -EACCES, 155 .error = -EACCES,
152 .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, 156 .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
153 .input = ip6_pkt_discard, 157 .input = ip6_pkt_prohibit,
154 .output = ip6_pkt_discard_out, 158 .output = ip6_pkt_prohibit_out,
155 .ops = &ip6_dst_ops, 159 .ops = &ip6_dst_ops,
156 .path = (struct dst_entry*)&ip6_prohibit_entry, 160 .path = (struct dst_entry*)&ip6_prohibit_entry,
157 } 161 }
@@ -170,8 +174,8 @@ struct rt6_info ip6_blk_hole_entry = {
170 .obsolete = -1, 174 .obsolete = -1,
171 .error = -EINVAL, 175 .error = -EINVAL,
172 .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, 176 .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
173 .input = ip6_pkt_discard, 177 .input = ip6_pkt_blk_hole,
174 .output = ip6_pkt_discard_out, 178 .output = ip6_pkt_blk_hole,
175 .ops = &ip6_dst_ops, 179 .ops = &ip6_dst_ops,
176 .path = (struct dst_entry*)&ip6_blk_hole_entry, 180 .path = (struct dst_entry*)&ip6_blk_hole_entry,
177 } 181 }
@@ -326,6 +330,8 @@ static int inline rt6_check_neigh(struct rt6_info *rt)
326 read_lock_bh(&neigh->lock); 330 read_lock_bh(&neigh->lock);
327 if (neigh->nud_state & NUD_VALID) 331 if (neigh->nud_state & NUD_VALID)
328 m = 2; 332 m = 2;
333 else if (!(neigh->nud_state & NUD_FAILED))
334 m = 1;
329 read_unlock_bh(&neigh->lock); 335 read_unlock_bh(&neigh->lock);
330 } 336 }
331 return m; 337 return m;
@@ -343,9 +349,7 @@ static int rt6_score_route(struct rt6_info *rt, int oif,
343 m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2; 349 m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2;
344#endif 350#endif
345 n = rt6_check_neigh(rt); 351 n = rt6_check_neigh(rt);
346 if (n > 1) 352 if (!n && (strict & RT6_LOOKUP_F_REACHABLE))
347 m |= 16;
348 else if (!n && strict & RT6_LOOKUP_F_REACHABLE)
349 return -1; 353 return -1;
350 return m; 354 return m;
351} 355}
@@ -376,10 +380,11 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif,
376 continue; 380 continue;
377 381
378 if (m > mpri) { 382 if (m > mpri) {
379 rt6_probe(match); 383 if (strict & RT6_LOOKUP_F_REACHABLE)
384 rt6_probe(match);
380 match = rt; 385 match = rt;
381 mpri = m; 386 mpri = m;
382 } else { 387 } else if (strict & RT6_LOOKUP_F_REACHABLE) {
383 rt6_probe(rt); 388 rt6_probe(rt);
384 } 389 }
385 } 390 }
@@ -484,7 +489,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
484do { \ 489do { \
485 if (rt == &ip6_null_entry) { \ 490 if (rt == &ip6_null_entry) { \
486 struct fib6_node *pn; \ 491 struct fib6_node *pn; \
487 while (fn) { \ 492 while (1) { \
488 if (fn->fn_flags & RTN_TL_ROOT) \ 493 if (fn->fn_flags & RTN_TL_ROOT) \
489 goto out; \ 494 goto out; \
490 pn = fn->parent; \ 495 pn = fn->parent; \
@@ -529,13 +534,17 @@ struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr,
529 .nl_u = { 534 .nl_u = {
530 .ip6_u = { 535 .ip6_u = {
531 .daddr = *daddr, 536 .daddr = *daddr,
532 /* TODO: saddr */
533 }, 537 },
534 }, 538 },
535 }; 539 };
536 struct dst_entry *dst; 540 struct dst_entry *dst;
537 int flags = strict ? RT6_LOOKUP_F_IFACE : 0; 541 int flags = strict ? RT6_LOOKUP_F_IFACE : 0;
538 542
543 if (saddr) {
544 memcpy(&fl.fl6_src, saddr, sizeof(*saddr));
545 flags |= RT6_LOOKUP_F_HAS_SADDR;
546 }
547
539 dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_lookup); 548 dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_lookup);
540 if (dst->error == 0) 549 if (dst->error == 0)
541 return (struct rt6_info *) dst; 550 return (struct rt6_info *) dst;
@@ -614,8 +623,6 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d
614 ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); 623 ipv6_addr_copy(&rt->rt6i_dst.addr, daddr);
615 rt->rt6i_dst.plen = 128; 624 rt->rt6i_dst.plen = 128;
616 rt->rt6i_flags |= RTF_CACHE; 625 rt->rt6i_flags |= RTF_CACHE;
617 if (rt->rt6i_flags & RTF_REJECT)
618 rt->u.dst.error = ort->u.dst.error;
619 rt->u.dst.flags |= DST_HOST; 626 rt->u.dst.flags |= DST_HOST;
620 rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop); 627 rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop);
621 } 628 }
@@ -630,7 +637,7 @@ static struct rt6_info *ip6_pol_route_input(struct fib6_table *table,
630 int strict = 0; 637 int strict = 0;
631 int attempts = 3; 638 int attempts = 3;
632 int err; 639 int err;
633 int reachable = RT6_LOOKUP_F_REACHABLE; 640 int reachable = ipv6_devconf.forwarding ? 0 : RT6_LOOKUP_F_REACHABLE;
634 641
635 strict |= flags & RT6_LOOKUP_F_IFACE; 642 strict |= flags & RT6_LOOKUP_F_IFACE;
636 643
@@ -697,6 +704,7 @@ out2:
697void ip6_route_input(struct sk_buff *skb) 704void ip6_route_input(struct sk_buff *skb)
698{ 705{
699 struct ipv6hdr *iph = skb->nh.ipv6h; 706 struct ipv6hdr *iph = skb->nh.ipv6h;
707 int flags = RT6_LOOKUP_F_HAS_SADDR;
700 struct flowi fl = { 708 struct flowi fl = {
701 .iif = skb->dev->ifindex, 709 .iif = skb->dev->ifindex,
702 .nl_u = { 710 .nl_u = {
@@ -711,7 +719,9 @@ void ip6_route_input(struct sk_buff *skb)
711 }, 719 },
712 .proto = iph->nexthdr, 720 .proto = iph->nexthdr,
713 }; 721 };
714 int flags = rt6_need_strict(&iph->daddr) ? RT6_LOOKUP_F_IFACE : 0; 722
723 if (rt6_need_strict(&iph->daddr))
724 flags |= RT6_LOOKUP_F_IFACE;
715 725
716 skb->dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_input); 726 skb->dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_input);
717} 727}
@@ -724,7 +734,7 @@ static struct rt6_info *ip6_pol_route_output(struct fib6_table *table,
724 int strict = 0; 734 int strict = 0;
725 int attempts = 3; 735 int attempts = 3;
726 int err; 736 int err;
727 int reachable = RT6_LOOKUP_F_REACHABLE; 737 int reachable = ipv6_devconf.forwarding ? 0 : RT6_LOOKUP_F_REACHABLE;
728 738
729 strict |= flags & RT6_LOOKUP_F_IFACE; 739 strict |= flags & RT6_LOOKUP_F_IFACE;
730 740
@@ -794,6 +804,9 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
794 if (rt6_need_strict(&fl->fl6_dst)) 804 if (rt6_need_strict(&fl->fl6_dst))
795 flags |= RT6_LOOKUP_F_IFACE; 805 flags |= RT6_LOOKUP_F_IFACE;
796 806
807 if (!ipv6_addr_any(&fl->fl6_src))
808 flags |= RT6_LOOKUP_F_HAS_SADDR;
809
797 return fib6_rule_lookup(fl, flags, ip6_pol_route_output); 810 return fib6_rule_lookup(fl, flags, ip6_pol_route_output);
798} 811}
799 812
@@ -1345,6 +1358,7 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest,
1345 struct in6_addr *gateway, 1358 struct in6_addr *gateway,
1346 struct net_device *dev) 1359 struct net_device *dev)
1347{ 1360{
1361 int flags = RT6_LOOKUP_F_HAS_SADDR;
1348 struct ip6rd_flowi rdfl = { 1362 struct ip6rd_flowi rdfl = {
1349 .fl = { 1363 .fl = {
1350 .oif = dev->ifindex, 1364 .oif = dev->ifindex,
@@ -1357,7 +1371,9 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest,
1357 }, 1371 },
1358 .gateway = *gateway, 1372 .gateway = *gateway,
1359 }; 1373 };
1360 int flags = rt6_need_strict(dest) ? RT6_LOOKUP_F_IFACE : 0; 1374
1375 if (rt6_need_strict(dest))
1376 flags |= RT6_LOOKUP_F_IFACE;
1361 1377
1362 return (struct rt6_info *)fib6_rule_lookup((struct flowi *)&rdfl, flags, __ip6_route_redirect); 1378 return (struct rt6_info *)fib6_rule_lookup((struct flowi *)&rdfl, flags, __ip6_route_redirect);
1363} 1379}
@@ -1527,6 +1543,7 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
1527 rt->u.dst.output = ort->u.dst.output; 1543 rt->u.dst.output = ort->u.dst.output;
1528 1544
1529 memcpy(rt->u.dst.metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32)); 1545 memcpy(rt->u.dst.metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32));
1546 rt->u.dst.error = ort->u.dst.error;
1530 rt->u.dst.dev = ort->u.dst.dev; 1547 rt->u.dst.dev = ort->u.dst.dev;
1531 if (rt->u.dst.dev) 1548 if (rt->u.dst.dev)
1532 dev_hold(rt->u.dst.dev); 1549 dev_hold(rt->u.dst.dev);
@@ -1730,24 +1747,50 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg)
1730 * Drop the packet on the floor 1747 * Drop the packet on the floor
1731 */ 1748 */
1732 1749
1733static int ip6_pkt_discard(struct sk_buff *skb) 1750static inline int ip6_pkt_drop(struct sk_buff *skb, int code)
1734{ 1751{
1735 int type = ipv6_addr_type(&skb->nh.ipv6h->daddr); 1752 int type = ipv6_addr_type(&skb->nh.ipv6h->daddr);
1736 if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) 1753 if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED)
1737 IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS); 1754 IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS);
1738 1755
1739 IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); 1756 IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES);
1740 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev); 1757 icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev);
1741 kfree_skb(skb); 1758 kfree_skb(skb);
1742 return 0; 1759 return 0;
1743} 1760}
1744 1761
1762static int ip6_pkt_discard(struct sk_buff *skb)
1763{
1764 return ip6_pkt_drop(skb, ICMPV6_NOROUTE);
1765}
1766
1745static int ip6_pkt_discard_out(struct sk_buff *skb) 1767static int ip6_pkt_discard_out(struct sk_buff *skb)
1746{ 1768{
1747 skb->dev = skb->dst->dev; 1769 skb->dev = skb->dst->dev;
1748 return ip6_pkt_discard(skb); 1770 return ip6_pkt_discard(skb);
1749} 1771}
1750 1772
1773#ifdef CONFIG_IPV6_MULTIPLE_TABLES
1774
1775static int ip6_pkt_prohibit(struct sk_buff *skb)
1776{
1777 return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED);
1778}
1779
1780static int ip6_pkt_prohibit_out(struct sk_buff *skb)
1781{
1782 skb->dev = skb->dst->dev;
1783 return ip6_pkt_prohibit(skb);
1784}
1785
1786static int ip6_pkt_blk_hole(struct sk_buff *skb)
1787{
1788 kfree_skb(skb);
1789 return 0;
1790}
1791
1792#endif
1793
1751/* 1794/*
1752 * Allocate a dst for local (unicast / anycast) address. 1795 * Allocate a dst for local (unicast / anycast) address.
1753 */ 1796 */
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 836eecd7e62b..be699f85b2c7 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -850,3 +850,8 @@ int __init sit_init(void)
850 inet_del_protocol(&sit_protocol, IPPROTO_IPV6); 850 inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
851 goto out; 851 goto out;
852} 852}
853
854module_init(sit_init);
855module_exit(sit_cleanup);
856MODULE_LICENSE("GPL");
857MODULE_ALIAS("sit0");
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 3b6575478fcc..4c2a7c0cafef 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -329,7 +329,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
329 } 329 }
330 330
331 if (sk->sk_state == TCP_TIME_WAIT) { 331 if (sk->sk_state == TCP_TIME_WAIT) {
332 inet_twsk_put((struct inet_timewait_sock *)sk); 332 inet_twsk_put(inet_twsk(sk));
333 return; 333 return;
334 } 334 }
335 335
@@ -653,7 +653,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
653 int tot_len = sizeof(struct tcphdr); 653 int tot_len = sizeof(struct tcphdr);
654 654
655 if (ts) 655 if (ts)
656 tot_len += 3*4; 656 tot_len += TCPOLEN_TSTAMP_ALIGNED;
657 657
658 buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len, 658 buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len,
659 GFP_ATOMIC); 659 GFP_ATOMIC);
@@ -749,7 +749,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
749 bh_lock_sock(nsk); 749 bh_lock_sock(nsk);
750 return nsk; 750 return nsk;
751 } 751 }
752 inet_twsk_put((struct inet_timewait_sock *)nsk); 752 inet_twsk_put(inet_twsk(nsk));
753 return NULL; 753 return NULL;
754 } 754 }
755 755
@@ -1283,18 +1283,17 @@ discard_and_relse:
1283 1283
1284do_time_wait: 1284do_time_wait:
1285 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { 1285 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
1286 inet_twsk_put((struct inet_timewait_sock *)sk); 1286 inet_twsk_put(inet_twsk(sk));
1287 goto discard_it; 1287 goto discard_it;
1288 } 1288 }
1289 1289
1290 if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { 1290 if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
1291 TCP_INC_STATS_BH(TCP_MIB_INERRS); 1291 TCP_INC_STATS_BH(TCP_MIB_INERRS);
1292 inet_twsk_put((struct inet_timewait_sock *)sk); 1292 inet_twsk_put(inet_twsk(sk));
1293 goto discard_it; 1293 goto discard_it;
1294 } 1294 }
1295 1295
1296 switch (tcp_timewait_state_process((struct inet_timewait_sock *)sk, 1296 switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
1297 skb, th)) {
1298 case TCP_TW_SYN: 1297 case TCP_TW_SYN:
1299 { 1298 {
1300 struct sock *sk2; 1299 struct sock *sk2;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index e0c3934a7e4b..c83f23e51c46 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -242,14 +242,13 @@ static void udpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
242{ 242{
243 struct ipv6_pinfo *np; 243 struct ipv6_pinfo *np;
244 struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; 244 struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data;
245 struct net_device *dev = skb->dev;
246 struct in6_addr *saddr = &hdr->saddr; 245 struct in6_addr *saddr = &hdr->saddr;
247 struct in6_addr *daddr = &hdr->daddr; 246 struct in6_addr *daddr = &hdr->daddr;
248 struct udphdr *uh = (struct udphdr*)(skb->data+offset); 247 struct udphdr *uh = (struct udphdr*)(skb->data+offset);
249 struct sock *sk; 248 struct sock *sk;
250 int err; 249 int err;
251 250
252 sk = udp_v6_lookup(daddr, uh->dest, saddr, uh->source, dev->ifindex); 251 sk = udp_v6_lookup(daddr, uh->dest, saddr, uh->source, inet6_iif(skb));
253 252
254 if (sk == NULL) 253 if (sk == NULL)
255 return; 254 return;
@@ -348,7 +347,7 @@ static void udpv6_mcast_deliver(struct udphdr *uh,
348 347
349 read_lock(&udp_hash_lock); 348 read_lock(&udp_hash_lock);
350 sk = sk_head(&udp_hash[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]); 349 sk = sk_head(&udp_hash[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]);
351 dif = skb->dev->ifindex; 350 dif = inet6_iif(skb);
352 sk = udp_v6_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif); 351 sk = udp_v6_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif);
353 if (!sk) { 352 if (!sk) {
354 kfree_skb(skb); 353 kfree_skb(skb);
@@ -429,7 +428,7 @@ static int udpv6_rcv(struct sk_buff **pskb)
429 * check socket cache ... must talk to Alan about his plans 428 * check socket cache ... must talk to Alan about his plans
430 * for sock caches... i'll skip this for now. 429 * for sock caches... i'll skip this for now.
431 */ 430 */
432 sk = udp_v6_lookup(saddr, uh->source, daddr, uh->dest, dev->ifindex); 431 sk = udp_v6_lookup(saddr, uh->source, daddr, uh->dest, inet6_iif(skb));
433 432
434 if (sk == NULL) { 433 if (sk == NULL) {
435 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) 434 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 6a252e2134d1..d400f8fae129 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -25,12 +25,14 @@
25static struct dst_ops xfrm6_dst_ops; 25static struct dst_ops xfrm6_dst_ops;
26static struct xfrm_policy_afinfo xfrm6_policy_afinfo; 26static struct xfrm_policy_afinfo xfrm6_policy_afinfo;
27 27
28static int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl) 28static int xfrm6_dst_lookup(struct xfrm_dst **xdst, struct flowi *fl)
29{ 29{
30 int err = 0; 30 struct dst_entry *dst = ip6_route_output(NULL, fl);
31 *dst = (struct xfrm_dst*)ip6_route_output(NULL, fl); 31 int err = dst->error;
32 if (!*dst) 32 if (!err)
33 err = -ENETUNREACH; 33 *xdst = (struct xfrm_dst *) dst;
34 else
35 dst_release(dst);
34 return err; 36 return err;
35} 37}
36 38
@@ -73,7 +75,7 @@ __xfrm6_find_bundle(struct flowi *fl, struct xfrm_policy *policy)
73 xdst->u.rt6.rt6i_src.plen); 75 xdst->u.rt6.rt6i_src.plen);
74 if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) && 76 if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) &&
75 ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) && 77 ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) &&
76 xfrm_bundle_ok(xdst, fl, AF_INET6, 78 xfrm_bundle_ok(policy, xdst, fl, AF_INET6,
77 (xdst->u.rt6.rt6i_dst.plen != 128 || 79 (xdst->u.rt6.rt6i_dst.plen != 128 ||
78 xdst->u.rt6.rt6i_src.plen != 128))) { 80 xdst->u.rt6.rt6i_src.plen != 128))) {
79 dst_clone(dst); 81 dst_clone(dst);
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 7af227bb1551..7931e4f898d4 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -135,7 +135,7 @@ u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr)
135 x6spi = __xfrm6_tunnel_spi_lookup(saddr); 135 x6spi = __xfrm6_tunnel_spi_lookup(saddr);
136 spi = x6spi ? x6spi->spi : 0; 136 spi = x6spi ? x6spi->spi : 0;
137 read_unlock_bh(&xfrm6_tunnel_spi_lock); 137 read_unlock_bh(&xfrm6_tunnel_spi_lock);
138 return spi; 138 return htonl(spi);
139} 139}
140 140
141EXPORT_SYMBOL(xfrm6_tunnel_spi_lookup); 141EXPORT_SYMBOL(xfrm6_tunnel_spi_lookup);
@@ -210,7 +210,7 @@ u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr)
210 spi = __xfrm6_tunnel_alloc_spi(saddr); 210 spi = __xfrm6_tunnel_alloc_spi(saddr);
211 write_unlock_bh(&xfrm6_tunnel_spi_lock); 211 write_unlock_bh(&xfrm6_tunnel_spi_lock);
212 212
213 return spi; 213 return htonl(spi);
214} 214}
215 215
216EXPORT_SYMBOL(xfrm6_tunnel_alloc_spi); 216EXPORT_SYMBOL(xfrm6_tunnel_alloc_spi);