diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/Kconfig | 29 | ||||
-rw-r--r-- | net/ipv6/Makefile | 3 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 18 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 2 | ||||
-rw-r--r-- | net/ipv6/fib6_rules.c | 11 | ||||
-rw-r--r-- | net/ipv6/ip6_fib.c | 9 | ||||
-rw-r--r-- | net/ipv6/ip6_flowlabel.c | 24 | ||||
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 19 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 3 | ||||
-rw-r--r-- | net/ipv6/netfilter/Kconfig | 2 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_queue.c | 7 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 47 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_ah.c | 7 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_frag.c | 7 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_hbh.c | 7 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_rt.c | 7 | ||||
-rw-r--r-- | net/ipv6/raw.c | 17 | ||||
-rw-r--r-- | net/ipv6/route.c | 81 | ||||
-rw-r--r-- | net/ipv6/sit.c | 5 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 13 | ||||
-rw-r--r-- | net/ipv6/udp.c | 7 | ||||
-rw-r--r-- | net/ipv6/xfrm6_policy.c | 14 | ||||
-rw-r--r-- | net/ipv6/xfrm6_tunnel.c | 4 |
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 | ||
156 | config 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 | |||
156 | config IPV6_TUNNEL | 169 | config 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 | ||
178 | config 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 | |||
165 | config IPV6_SUBTREES | 185 | config 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 | ||
179 | config 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 | |||
186 | config IPV6_ROUTE_FWMARK | 199 | config 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 | ||
5 | obj-$(CONFIG_IPV6) += ipv6.o | 5 | obj-$(CONFIG_IPV6) += ipv6.o |
6 | 6 | ||
7 | ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o sit.o \ | 7 | ipv6-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 | |||
29 | obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o | 29 | obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o |
30 | obj-$(CONFIG_NETFILTER) += netfilter/ | 30 | obj-$(CONFIG_NETFILTER) += netfilter/ |
31 | 31 | ||
32 | obj-$(CONFIG_IPV6_SIT) += sit.o | ||
32 | obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o | 33 | obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o |
33 | 34 | ||
34 | obj-y += exthdrs_core.o | 35 | obj-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) | ||
1572 | static void sit_route_add(struct net_device *dev) | 1577 | static 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 | ||
1586 | static void addrconf_add_lroute(struct net_device *dev) | 1592 | static 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 | ||
1885 | err_exit: | 1893 | err_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) | ||
2013 | static void sit_add_v4_addrs(struct inet6_dev *idev) | 2022 | static 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 | ||
2082 | static void init_loopback(struct net_device *dev) | 2092 | static 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) | ||
2144 | static void addrconf_sit_config(struct net_device *dev) | 2155 | static 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 | ||
2170 | static inline int | 2182 | static inline int |
2171 | ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev) | 2183 | ipv6_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 | ||
170 | static struct fib6_table fib6_main_tbl = { | 170 | static 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 |
200 | static struct fib6_table fib6_local_tbl = { | 205 | static 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 | ||
626 | static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl) | 630 | static 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 | |||
643 | static 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 | ||
1153 | static 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 | ||
1164 | module_init(ip6_tunnel_init); | 1181 | module_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 | ||
1745 | void ndisc_cleanup(void) | 1743 | void 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 | ||
42 | config IP6_NF_IPTABLES | 42 | config 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; | ||
780 | cleanup: | ||
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 | ||
607 | static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) | 607 | static 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 | ||
669 | static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | 672 | static 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 | ||
144 | static int ip6_pkt_prohibit(struct sk_buff *skb); | ||
145 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); | ||
146 | static int ip6_pkt_blk_hole(struct sk_buff *skb); | ||
147 | |||
144 | struct rt6_info ip6_prohibit_entry = { | 148 | struct 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, | |||
484 | do { \ | 489 | do { \ |
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: | |||
697 | void ip6_route_input(struct sk_buff *skb) | 704 | void 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 | ||
1733 | static int ip6_pkt_discard(struct sk_buff *skb) | 1750 | static 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 | ||
1762 | static int ip6_pkt_discard(struct sk_buff *skb) | ||
1763 | { | ||
1764 | return ip6_pkt_drop(skb, ICMPV6_NOROUTE); | ||
1765 | } | ||
1766 | |||
1745 | static int ip6_pkt_discard_out(struct sk_buff *skb) | 1767 | static 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 | |||
1775 | static int ip6_pkt_prohibit(struct sk_buff *skb) | ||
1776 | { | ||
1777 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED); | ||
1778 | } | ||
1779 | |||
1780 | static int ip6_pkt_prohibit_out(struct sk_buff *skb) | ||
1781 | { | ||
1782 | skb->dev = skb->dst->dev; | ||
1783 | return ip6_pkt_prohibit(skb); | ||
1784 | } | ||
1785 | |||
1786 | static 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 | |||
854 | module_init(sit_init); | ||
855 | module_exit(sit_cleanup); | ||
856 | MODULE_LICENSE("GPL"); | ||
857 | MODULE_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 | ||
1284 | do_time_wait: | 1284 | do_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 @@ | |||
25 | static struct dst_ops xfrm6_dst_ops; | 25 | static struct dst_ops xfrm6_dst_ops; |
26 | static struct xfrm_policy_afinfo xfrm6_policy_afinfo; | 26 | static struct xfrm_policy_afinfo xfrm6_policy_afinfo; |
27 | 27 | ||
28 | static int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl) | 28 | static 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 | ||
141 | EXPORT_SYMBOL(xfrm6_tunnel_spi_lookup); | 141 | EXPORT_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 | ||
216 | EXPORT_SYMBOL(xfrm6_tunnel_alloc_spi); | 216 | EXPORT_SYMBOL(xfrm6_tunnel_alloc_spi); |