aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/addrconf.c4
-rw-r--r--net/ipv6/af_inet6.c13
-rw-r--r--net/ipv6/fib6_rules.c4
-rw-r--r--net/ipv6/ip6_tunnel.c4
-rw-r--r--net/ipv6/ndisc.c1
-rw-r--r--net/ipv6/netfilter/ip6t_ipv6header.c6
-rw-r--r--net/ipv6/route.c3
-rw-r--r--net/ipv6/sit.c97
-rw-r--r--net/ipv6/tcp_ipv6.c7
9 files changed, 113 insertions, 26 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index a8218bc1806a..31938e5fb220 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -503,7 +503,7 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
503 return 0; 503 return 0;
504 504
505 if (!rtnl_trylock()) 505 if (!rtnl_trylock())
506 return -ERESTARTSYS; 506 return restart_syscall();
507 507
508 if (p == &net->ipv6.devconf_all->forwarding) { 508 if (p == &net->ipv6.devconf_all->forwarding) {
509 __s32 newf = net->ipv6.devconf_all->forwarding; 509 __s32 newf = net->ipv6.devconf_all->forwarding;
@@ -1520,6 +1520,8 @@ static int addrconf_ifid_infiniband(u8 *eui, struct net_device *dev)
1520 1520
1521int __ipv6_isatap_ifid(u8 *eui, __be32 addr) 1521int __ipv6_isatap_ifid(u8 *eui, __be32 addr)
1522{ 1522{
1523 if (addr == 0)
1524 return -1;
1523 eui[0] = (ipv4_is_zeronet(addr) || ipv4_is_private_10(addr) || 1525 eui[0] = (ipv4_is_zeronet(addr) || ipv4_is_private_10(addr) ||
1524 ipv4_is_loopback(addr) || ipv4_is_linklocal_169(addr) || 1526 ipv4_is_loopback(addr) || ipv4_is_linklocal_169(addr) ||
1525 ipv4_is_private_172(addr) || ipv4_is_test_192(addr) || 1527 ipv4_is_private_172(addr) || ipv4_is_test_192(addr) ||
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 61f55386a236..b6215be0963f 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -817,13 +817,20 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
817 struct sk_buff *p; 817 struct sk_buff *p;
818 struct ipv6hdr *iph; 818 struct ipv6hdr *iph;
819 unsigned int nlen; 819 unsigned int nlen;
820 unsigned int hlen;
821 unsigned int off;
820 int flush = 1; 822 int flush = 1;
821 int proto; 823 int proto;
822 __wsum csum; 824 __wsum csum;
823 825
824 iph = skb_gro_header(skb, sizeof(*iph)); 826 off = skb_gro_offset(skb);
825 if (unlikely(!iph)) 827 hlen = off + sizeof(*iph);
826 goto out; 828 iph = skb_gro_header_fast(skb, off);
829 if (skb_gro_header_hard(skb, hlen)) {
830 iph = skb_gro_header_slow(skb, hlen, off);
831 if (unlikely(!iph))
832 goto out;
833 }
827 834
828 skb_gro_pull(skb, sizeof(*iph)); 835 skb_gro_pull(skb, sizeof(*iph));
829 skb_set_transport_header(skb, skb_gro_offset(skb)); 836 skb_set_transport_header(skb, skb_gro_offset(skb));
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index f5de3f9dc692..00a7a5e4ac97 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -151,7 +151,7 @@ static const struct nla_policy fib6_rule_policy[FRA_MAX+1] = {
151}; 151};
152 152
153static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, 153static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
154 struct nlmsghdr *nlh, struct fib_rule_hdr *frh, 154 struct fib_rule_hdr *frh,
155 struct nlattr **tb) 155 struct nlattr **tb)
156{ 156{
157 int err = -EINVAL; 157 int err = -EINVAL;
@@ -211,7 +211,7 @@ static int fib6_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
211} 211}
212 212
213static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb, 213static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
214 struct nlmsghdr *nlh, struct fib_rule_hdr *frh) 214 struct fib_rule_hdr *frh)
215{ 215{
216 struct fib6_rule *rule6 = (struct fib6_rule *) rule; 216 struct fib6_rule *rule6 = (struct fib6_rule *) rule;
217 217
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index d994c55a5b16..af256d47fd35 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1100,8 +1100,8 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
1100 struct ip6_tnl_parm *p = &t->parms; 1100 struct ip6_tnl_parm *p = &t->parms;
1101 struct flowi *fl = &t->fl; 1101 struct flowi *fl = &t->fl;
1102 1102
1103 memcpy(&dev->dev_addr, &p->laddr, sizeof(struct in6_addr)); 1103 memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr));
1104 memcpy(&dev->broadcast, &p->raddr, sizeof(struct in6_addr)); 1104 memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr));
1105 1105
1106 /* Set up flowi template */ 1106 /* Set up flowi template */
1107 ipv6_addr_copy(&fl->fl6_src, &p->laddr); 1107 ipv6_addr_copy(&fl->fl6_src, &p->laddr);
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index ab65cc51b00e..e09f12ee57cf 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -658,6 +658,7 @@ void ndisc_send_rs(struct net_device *dev, const struct in6_addr *saddr,
658 &icmp6h, NULL, 658 &icmp6h, NULL,
659 send_sllao ? ND_OPT_SOURCE_LL_ADDR : 0); 659 send_sllao ? ND_OPT_SOURCE_LL_ADDR : 0);
660} 660}
661EXPORT_SYMBOL(ndisc_send_rs);
661 662
662 663
663static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb) 664static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb)
diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c
index 14e6724d5672..91490ad9302c 100644
--- a/net/ipv6/netfilter/ip6t_ipv6header.c
+++ b/net/ipv6/netfilter/ip6t_ipv6header.c
@@ -50,14 +50,14 @@ ipv6header_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
50 struct ipv6_opt_hdr _hdr; 50 struct ipv6_opt_hdr _hdr;
51 int hdrlen; 51 int hdrlen;
52 52
53 /* Is there enough space for the next ext header? */
54 if (len < (int)sizeof(struct ipv6_opt_hdr))
55 return false;
56 /* No more exthdr -> evaluate */ 53 /* No more exthdr -> evaluate */
57 if (nexthdr == NEXTHDR_NONE) { 54 if (nexthdr == NEXTHDR_NONE) {
58 temp |= MASK_NONE; 55 temp |= MASK_NONE;
59 break; 56 break;
60 } 57 }
58 /* Is there enough space for the next ext header? */
59 if (len < (int)sizeof(struct ipv6_opt_hdr))
60 return false;
61 /* ESP -> evaluate */ 61 /* ESP -> evaluate */
62 if (nexthdr == NEXTHDR_ESP) { 62 if (nexthdr == NEXTHDR_ESP) {
63 temp |= MASK_ESP; 63 temp |= MASK_ESP;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 1394ddb6e35c..032a5ec391c5 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -137,6 +137,7 @@ static struct rt6_info ip6_null_entry_template = {
137 } 137 }
138 }, 138 },
139 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), 139 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
140 .rt6i_protocol = RTPROT_KERNEL,
140 .rt6i_metric = ~(u32) 0, 141 .rt6i_metric = ~(u32) 0,
141 .rt6i_ref = ATOMIC_INIT(1), 142 .rt6i_ref = ATOMIC_INIT(1),
142}; 143};
@@ -159,6 +160,7 @@ static struct rt6_info ip6_prohibit_entry_template = {
159 } 160 }
160 }, 161 },
161 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), 162 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
163 .rt6i_protocol = RTPROT_KERNEL,
162 .rt6i_metric = ~(u32) 0, 164 .rt6i_metric = ~(u32) 0,
163 .rt6i_ref = ATOMIC_INIT(1), 165 .rt6i_ref = ATOMIC_INIT(1),
164}; 166};
@@ -176,6 +178,7 @@ static struct rt6_info ip6_blk_hole_entry_template = {
176 } 178 }
177 }, 179 },
178 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), 180 .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
181 .rt6i_protocol = RTPROT_KERNEL,
179 .rt6i_metric = ~(u32) 0, 182 .rt6i_metric = ~(u32) 0,
180 .rt6i_ref = ATOMIC_INIT(1), 183 .rt6i_ref = ATOMIC_INIT(1),
181}; 184};
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 664ab82e03b2..b3a59bd40f01 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -15,6 +15,7 @@
15 * Roger Venning <r.venning@telstra.com>: 6to4 support 15 * Roger Venning <r.venning@telstra.com>: 6to4 support
16 * Nate Thompson <nate@thebog.net>: 6to4 support 16 * Nate Thompson <nate@thebog.net>: 6to4 support
17 * Fred Templin <fred.l.templin@boeing.com>: isatap support 17 * Fred Templin <fred.l.templin@boeing.com>: isatap support
18 * Sascha Hlusiak <mail@saschahlusiak.de>: stateless autoconf for isatap
18 */ 19 */
19 20
20#include <linux/module.h> 21#include <linux/module.h>
@@ -80,7 +81,7 @@ struct sit_net {
80static DEFINE_RWLOCK(ipip6_lock); 81static DEFINE_RWLOCK(ipip6_lock);
81 82
82static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net, 83static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net,
83 __be32 remote, __be32 local) 84 struct net_device *dev, __be32 remote, __be32 local)
84{ 85{
85 unsigned h0 = HASH(remote); 86 unsigned h0 = HASH(remote);
86 unsigned h1 = HASH(local); 87 unsigned h1 = HASH(local);
@@ -89,18 +90,25 @@ static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net,
89 90
90 for (t = sitn->tunnels_r_l[h0^h1]; t; t = t->next) { 91 for (t = sitn->tunnels_r_l[h0^h1]; t; t = t->next) {
91 if (local == t->parms.iph.saddr && 92 if (local == t->parms.iph.saddr &&
92 remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) 93 remote == t->parms.iph.daddr &&
94 (!dev || !t->parms.link || dev->iflink == t->parms.link) &&
95 (t->dev->flags & IFF_UP))
93 return t; 96 return t;
94 } 97 }
95 for (t = sitn->tunnels_r[h0]; t; t = t->next) { 98 for (t = sitn->tunnels_r[h0]; t; t = t->next) {
96 if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) 99 if (remote == t->parms.iph.daddr &&
100 (!dev || !t->parms.link || dev->iflink == t->parms.link) &&
101 (t->dev->flags & IFF_UP))
97 return t; 102 return t;
98 } 103 }
99 for (t = sitn->tunnels_l[h1]; t; t = t->next) { 104 for (t = sitn->tunnels_l[h1]; t; t = t->next) {
100 if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP)) 105 if (local == t->parms.iph.saddr &&
106 (!dev || !t->parms.link || dev->iflink == t->parms.link) &&
107 (t->dev->flags & IFF_UP))
101 return t; 108 return t;
102 } 109 }
103 if ((t = sitn->tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP)) 110 t = sitn->tunnels_wc[0];
111 if ((t != NULL) && (t->dev->flags & IFF_UP))
104 return t; 112 return t;
105 return NULL; 113 return NULL;
106} 114}
@@ -165,8 +173,14 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct net *net,
165 struct sit_net *sitn = net_generic(net, sit_net_id); 173 struct sit_net *sitn = net_generic(net, sit_net_id);
166 174
167 for (tp = __ipip6_bucket(sitn, parms); (t = *tp) != NULL; tp = &t->next) { 175 for (tp = __ipip6_bucket(sitn, parms); (t = *tp) != NULL; tp = &t->next) {
168 if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) 176 if (local == t->parms.iph.saddr &&
169 return t; 177 remote == t->parms.iph.daddr &&
178 parms->link == t->parms.link) {
179 if (create)
180 return NULL;
181 else
182 return t;
183 }
170 } 184 }
171 if (!create) 185 if (!create)
172 goto failed; 186 goto failed;
@@ -209,6 +223,44 @@ failed:
209 return NULL; 223 return NULL;
210} 224}
211 225
226static void ipip6_tunnel_rs_timer(unsigned long data)
227{
228 struct ip_tunnel_prl_entry *p = (struct ip_tunnel_prl_entry *) data;
229 struct inet6_dev *ifp;
230 struct inet6_ifaddr *addr;
231
232 spin_lock(&p->lock);
233 ifp = __in6_dev_get(p->tunnel->dev);
234
235 read_lock_bh(&ifp->lock);
236 for (addr = ifp->addr_list; addr; addr = addr->if_next) {
237 struct in6_addr rtr;
238
239 if (!(ipv6_addr_type(&addr->addr) & IPV6_ADDR_LINKLOCAL))
240 continue;
241
242 /* Send RS to guessed linklocal address of router
243 *
244 * Better: send to ff02::2 encapsuled in unicast directly
245 * to router-v4 instead of guessing the v6 address.
246 *
247 * Cisco/Windows seem to not set the u/l bit correctly,
248 * so we won't guess right.
249 */
250 ipv6_addr_set(&rtr, htonl(0xFE800000), 0, 0, 0);
251 if (!__ipv6_isatap_ifid(rtr.s6_addr + 8,
252 p->addr)) {
253 ndisc_send_rs(p->tunnel->dev, &addr->addr, &rtr);
254 }
255 }
256 read_unlock_bh(&ifp->lock);
257
258 mod_timer(&p->rs_timer, jiffies + HZ * p->rs_delay);
259 spin_unlock(&p->lock);
260
261 return;
262}
263
212static struct ip_tunnel_prl_entry * 264static struct ip_tunnel_prl_entry *
213__ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr) 265__ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr)
214{ 266{
@@ -267,6 +319,7 @@ static int ipip6_tunnel_get_prl(struct ip_tunnel *t,
267 continue; 319 continue;
268 kp[c].addr = prl->addr; 320 kp[c].addr = prl->addr;
269 kp[c].flags = prl->flags; 321 kp[c].flags = prl->flags;
322 kp[c].rs_delay = prl->rs_delay;
270 c++; 323 c++;
271 if (kprl.addr != htonl(INADDR_ANY)) 324 if (kprl.addr != htonl(INADDR_ANY))
272 break; 325 break;
@@ -316,11 +369,23 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg)
316 } 369 }
317 370
318 p->next = t->prl; 371 p->next = t->prl;
372 p->tunnel = t;
319 t->prl = p; 373 t->prl = p;
320 t->prl_count++; 374 t->prl_count++;
375
376 spin_lock_init(&p->lock);
377 setup_timer(&p->rs_timer, ipip6_tunnel_rs_timer, (unsigned long) p);
321update: 378update:
322 p->addr = a->addr; 379 p->addr = a->addr;
323 p->flags = a->flags; 380 p->flags = a->flags;
381 p->rs_delay = a->rs_delay;
382 if (p->rs_delay == 0)
383 p->rs_delay = IPTUNNEL_RS_DEFAULT_DELAY;
384 spin_lock(&p->lock);
385 del_timer(&p->rs_timer);
386 if (p->flags & PRL_DEFAULT)
387 mod_timer(&p->rs_timer, jiffies + 1);
388 spin_unlock(&p->lock);
324out: 389out:
325 write_unlock(&ipip6_lock); 390 write_unlock(&ipip6_lock);
326 return err; 391 return err;
@@ -339,6 +404,9 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a)
339 if ((*p)->addr == a->addr) { 404 if ((*p)->addr == a->addr) {
340 x = *p; 405 x = *p;
341 *p = x->next; 406 *p = x->next;
407 spin_lock(&x->lock);
408 del_timer(&x->rs_timer);
409 spin_unlock(&x->lock);
342 kfree(x); 410 kfree(x);
343 t->prl_count--; 411 t->prl_count--;
344 goto out; 412 goto out;
@@ -349,13 +417,16 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a)
349 while (t->prl) { 417 while (t->prl) {
350 x = t->prl; 418 x = t->prl;
351 t->prl = t->prl->next; 419 t->prl = t->prl->next;
420 spin_lock(&x->lock);
421 del_timer(&x->rs_timer);
422 spin_unlock(&x->lock);
352 kfree(x); 423 kfree(x);
353 t->prl_count--; 424 t->prl_count--;
354 } 425 }
355 } 426 }
356out: 427out:
357 write_unlock(&ipip6_lock); 428 write_unlock(&ipip6_lock);
358 return 0; 429 return err;
359} 430}
360 431
361static int 432static int
@@ -446,7 +517,10 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
446 err = -ENOENT; 517 err = -ENOENT;
447 518
448 read_lock(&ipip6_lock); 519 read_lock(&ipip6_lock);
449 t = ipip6_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr); 520 t = ipip6_tunnel_lookup(dev_net(skb->dev),
521 skb->dev,
522 iph->daddr,
523 iph->saddr);
450 if (t == NULL || t->parms.iph.daddr == 0) 524 if (t == NULL || t->parms.iph.daddr == 0)
451 goto out; 525 goto out;
452 526
@@ -481,8 +555,9 @@ static int ipip6_rcv(struct sk_buff *skb)
481 iph = ip_hdr(skb); 555 iph = ip_hdr(skb);
482 556
483 read_lock(&ipip6_lock); 557 read_lock(&ipip6_lock);
484 if ((tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), 558 tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev,
485 iph->saddr, iph->daddr)) != NULL) { 559 iph->saddr, iph->daddr);
560 if (tunnel != NULL) {
486 secpath_reset(skb); 561 secpath_reset(skb);
487 skb->mac_header = skb->network_header; 562 skb->mac_header = skb->network_header;
488 skb_reset_network_header(skb); 563 skb_reset_network_header(skb);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index d9dd94b6bf66..ea37741062a9 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -941,7 +941,8 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb)
941 return 0; 941 return 0;
942} 942}
943 943
944struct sk_buff **tcp6_gro_receive(struct sk_buff **head, struct sk_buff *skb) 944static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
945 struct sk_buff *skb)
945{ 946{
946 struct ipv6hdr *iph = skb_gro_network_header(skb); 947 struct ipv6hdr *iph = skb_gro_network_header(skb);
947 948
@@ -961,9 +962,8 @@ struct sk_buff **tcp6_gro_receive(struct sk_buff **head, struct sk_buff *skb)
961 962
962 return tcp_gro_receive(head, skb); 963 return tcp_gro_receive(head, skb);
963} 964}
964EXPORT_SYMBOL(tcp6_gro_receive);
965 965
966int tcp6_gro_complete(struct sk_buff *skb) 966static int tcp6_gro_complete(struct sk_buff *skb)
967{ 967{
968 struct ipv6hdr *iph = ipv6_hdr(skb); 968 struct ipv6hdr *iph = ipv6_hdr(skb);
969 struct tcphdr *th = tcp_hdr(skb); 969 struct tcphdr *th = tcp_hdr(skb);
@@ -974,7 +974,6 @@ int tcp6_gro_complete(struct sk_buff *skb)
974 974
975 return tcp_gro_complete(skb); 975 return tcp_gro_complete(skb);
976} 976}
977EXPORT_SYMBOL(tcp6_gro_complete);
978 977
979static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, 978static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
980 u32 ts, struct tcp_md5sig_key *key, int rst) 979 u32 ts, struct tcp_md5sig_key *key, int rst)