aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/ah6.c3
-rw-r--r--net/ipv6/esp6.c3
-rw-r--r--net/ipv6/inet6_hashtables.c2
-rw-r--r--net/ipv6/ip6_gre.c6
-rw-r--r--net/ipv6/ip6_output.c29
-rw-r--r--net/ipv6/ip6_tunnel.c12
-rw-r--r--net/ipv6/ipcomp6.c3
-rw-r--r--net/ipv6/route.c46
-rw-r--r--net/ipv6/udp.c5
-rw-r--r--net/ipv6/xfrm6_policy.c1
10 files changed, 72 insertions, 38 deletions
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 73784c3d4642..82e1da3a40b9 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -618,8 +618,7 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
618 struct ip_auth_hdr *ah = (struct ip_auth_hdr*)(skb->data+offset); 618 struct ip_auth_hdr *ah = (struct ip_auth_hdr*)(skb->data+offset);
619 struct xfrm_state *x; 619 struct xfrm_state *x;
620 620
621 if (type != ICMPV6_DEST_UNREACH && 621 if (type != ICMPV6_PKT_TOOBIG &&
622 type != ICMPV6_PKT_TOOBIG &&
623 type != NDISC_REDIRECT) 622 type != NDISC_REDIRECT)
624 return; 623 return;
625 624
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index d3618a78fcac..e67e63f9858d 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -436,8 +436,7 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
436 struct ip_esp_hdr *esph = (struct ip_esp_hdr *)(skb->data + offset); 436 struct ip_esp_hdr *esph = (struct ip_esp_hdr *)(skb->data + offset);
437 struct xfrm_state *x; 437 struct xfrm_state *x;
438 438
439 if (type != ICMPV6_DEST_UNREACH && 439 if (type != ICMPV6_PKT_TOOBIG &&
440 type != ICMPV6_PKT_TOOBIG &&
441 type != NDISC_REDIRECT) 440 type != NDISC_REDIRECT)
442 return; 441 return;
443 442
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 32b4a1675d82..066640e0ba8e 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -116,7 +116,7 @@ begintw:
116 } 116 }
117 if (unlikely(!INET6_TW_MATCH(sk, net, saddr, daddr, 117 if (unlikely(!INET6_TW_MATCH(sk, net, saddr, daddr,
118 ports, dif))) { 118 ports, dif))) {
119 sock_put(sk); 119 inet_twsk_put(inet_twsk(sk));
120 goto begintw; 120 goto begintw;
121 } 121 }
122 goto out; 122 goto out;
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 7bb5446b9d73..bf4a9a084de5 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -976,6 +976,7 @@ static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu)
976 if (t->parms.o_flags&GRE_SEQ) 976 if (t->parms.o_flags&GRE_SEQ)
977 addend += 4; 977 addend += 4;
978 } 978 }
979 t->hlen = addend;
979 980
980 if (p->flags & IP6_TNL_F_CAP_XMIT) { 981 if (p->flags & IP6_TNL_F_CAP_XMIT) {
981 int strict = (ipv6_addr_type(&p->raddr) & 982 int strict = (ipv6_addr_type(&p->raddr) &
@@ -1002,8 +1003,6 @@ static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu)
1002 } 1003 }
1003 ip6_rt_put(rt); 1004 ip6_rt_put(rt);
1004 } 1005 }
1005
1006 t->hlen = addend;
1007} 1006}
1008 1007
1009static int ip6gre_tnl_change(struct ip6_tnl *t, 1008static int ip6gre_tnl_change(struct ip6_tnl *t,
@@ -1173,9 +1172,8 @@ done:
1173 1172
1174static int ip6gre_tunnel_change_mtu(struct net_device *dev, int new_mtu) 1173static int ip6gre_tunnel_change_mtu(struct net_device *dev, int new_mtu)
1175{ 1174{
1176 struct ip6_tnl *tunnel = netdev_priv(dev);
1177 if (new_mtu < 68 || 1175 if (new_mtu < 68 ||
1178 new_mtu > 0xFFF8 - dev->hard_header_len - tunnel->hlen) 1176 new_mtu > 0xFFF8 - dev->hard_header_len)
1179 return -EINVAL; 1177 return -EINVAL;
1180 dev->mtu = new_mtu; 1178 dev->mtu = new_mtu;
1181 return 0; 1179 return 0;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index a54c45ce4a48..91fb4e8212f5 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -105,7 +105,7 @@ static int ip6_finish_output2(struct sk_buff *skb)
105 } 105 }
106 106
107 rcu_read_lock_bh(); 107 rcu_read_lock_bh();
108 nexthop = rt6_nexthop((struct rt6_info *)dst, &ipv6_hdr(skb)->daddr); 108 nexthop = rt6_nexthop((struct rt6_info *)dst);
109 neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop); 109 neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop);
110 if (unlikely(!neigh)) 110 if (unlikely(!neigh))
111 neigh = __neigh_create(&nd_tbl, nexthop, dst->dev, false); 111 neigh = __neigh_create(&nd_tbl, nexthop, dst->dev, false);
@@ -874,7 +874,7 @@ static int ip6_dst_lookup_tail(struct sock *sk,
874 */ 874 */
875 rt = (struct rt6_info *) *dst; 875 rt = (struct rt6_info *) *dst;
876 rcu_read_lock_bh(); 876 rcu_read_lock_bh();
877 n = __ipv6_neigh_lookup_noref(rt->dst.dev, rt6_nexthop(rt, &fl6->daddr)); 877 n = __ipv6_neigh_lookup_noref(rt->dst.dev, rt6_nexthop(rt));
878 err = n && !(n->nud_state & NUD_VALID) ? -EINVAL : 0; 878 err = n && !(n->nud_state & NUD_VALID) ? -EINVAL : 0;
879 rcu_read_unlock_bh(); 879 rcu_read_unlock_bh();
880 880
@@ -1008,6 +1008,7 @@ static inline int ip6_ufo_append_data(struct sock *sk,
1008 1008
1009{ 1009{
1010 struct sk_buff *skb; 1010 struct sk_buff *skb;
1011 struct frag_hdr fhdr;
1011 int err; 1012 int err;
1012 1013
1013 /* There is support for UDP large send offload by network 1014 /* There is support for UDP large send offload by network
@@ -1015,8 +1016,6 @@ static inline int ip6_ufo_append_data(struct sock *sk,
1015 * udp datagram 1016 * udp datagram
1016 */ 1017 */
1017 if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) { 1018 if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) {
1018 struct frag_hdr fhdr;
1019
1020 skb = sock_alloc_send_skb(sk, 1019 skb = sock_alloc_send_skb(sk,
1021 hh_len + fragheaderlen + transhdrlen + 20, 1020 hh_len + fragheaderlen + transhdrlen + 20,
1022 (flags & MSG_DONTWAIT), &err); 1021 (flags & MSG_DONTWAIT), &err);
@@ -1036,20 +1035,24 @@ static inline int ip6_ufo_append_data(struct sock *sk,
1036 skb->transport_header = skb->network_header + fragheaderlen; 1035 skb->transport_header = skb->network_header + fragheaderlen;
1037 1036
1038 skb->protocol = htons(ETH_P_IPV6); 1037 skb->protocol = htons(ETH_P_IPV6);
1039 skb->ip_summed = CHECKSUM_PARTIAL;
1040 skb->csum = 0; 1038 skb->csum = 0;
1041 1039
1042 /* Specify the length of each IPv6 datagram fragment.
1043 * It has to be a multiple of 8.
1044 */
1045 skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
1046 sizeof(struct frag_hdr)) & ~7;
1047 skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
1048 ipv6_select_ident(&fhdr, rt);
1049 skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
1050 __skb_queue_tail(&sk->sk_write_queue, skb); 1040 __skb_queue_tail(&sk->sk_write_queue, skb);
1041 } else if (skb_is_gso(skb)) {
1042 goto append;
1051 } 1043 }
1052 1044
1045 skb->ip_summed = CHECKSUM_PARTIAL;
1046 /* Specify the length of each IPv6 datagram fragment.
1047 * It has to be a multiple of 8.
1048 */
1049 skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
1050 sizeof(struct frag_hdr)) & ~7;
1051 skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
1052 ipv6_select_ident(&fhdr, rt);
1053 skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
1054
1055append:
1053 return skb_append_datato_frags(sk, skb, getfrag, from, 1056 return skb_append_datato_frags(sk, skb, getfrag, from,
1054 (length - transhdrlen)); 1057 (length - transhdrlen));
1055} 1058}
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index a791552e0422..583b77e2f69b 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1430,9 +1430,17 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1430static int 1430static int
1431ip6_tnl_change_mtu(struct net_device *dev, int new_mtu) 1431ip6_tnl_change_mtu(struct net_device *dev, int new_mtu)
1432{ 1432{
1433 if (new_mtu < IPV6_MIN_MTU) { 1433 struct ip6_tnl *tnl = netdev_priv(dev);
1434 return -EINVAL; 1434
1435 if (tnl->parms.proto == IPPROTO_IPIP) {
1436 if (new_mtu < 68)
1437 return -EINVAL;
1438 } else {
1439 if (new_mtu < IPV6_MIN_MTU)
1440 return -EINVAL;
1435 } 1441 }
1442 if (new_mtu > 0xFFF8 - dev->hard_header_len)
1443 return -EINVAL;
1436 dev->mtu = new_mtu; 1444 dev->mtu = new_mtu;
1437 return 0; 1445 return 0;
1438} 1446}
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 5636a912074a..ce507d9e1c90 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -64,8 +64,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
64 (struct ip_comp_hdr *)(skb->data + offset); 64 (struct ip_comp_hdr *)(skb->data + offset);
65 struct xfrm_state *x; 65 struct xfrm_state *x;
66 66
67 if (type != ICMPV6_DEST_UNREACH && 67 if (type != ICMPV6_PKT_TOOBIG &&
68 type != ICMPV6_PKT_TOOBIG &&
69 type != NDISC_REDIRECT) 68 type != NDISC_REDIRECT)
70 return; 69 return;
71 70
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index c979dd96d82a..f54e3a101098 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -476,6 +476,24 @@ out:
476} 476}
477 477
478#ifdef CONFIG_IPV6_ROUTER_PREF 478#ifdef CONFIG_IPV6_ROUTER_PREF
479struct __rt6_probe_work {
480 struct work_struct work;
481 struct in6_addr target;
482 struct net_device *dev;
483};
484
485static void rt6_probe_deferred(struct work_struct *w)
486{
487 struct in6_addr mcaddr;
488 struct __rt6_probe_work *work =
489 container_of(w, struct __rt6_probe_work, work);
490
491 addrconf_addr_solict_mult(&work->target, &mcaddr);
492 ndisc_send_ns(work->dev, NULL, &work->target, &mcaddr, NULL);
493 dev_put(work->dev);
494 kfree(w);
495}
496
479static void rt6_probe(struct rt6_info *rt) 497static void rt6_probe(struct rt6_info *rt)
480{ 498{
481 struct neighbour *neigh; 499 struct neighbour *neigh;
@@ -499,17 +517,23 @@ static void rt6_probe(struct rt6_info *rt)
499 517
500 if (!neigh || 518 if (!neigh ||
501 time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) { 519 time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) {
502 struct in6_addr mcaddr; 520 struct __rt6_probe_work *work;
503 struct in6_addr *target;
504 521
505 if (neigh) { 522 work = kmalloc(sizeof(*work), GFP_ATOMIC);
523
524 if (neigh && work)
506 neigh->updated = jiffies; 525 neigh->updated = jiffies;
526
527 if (neigh)
507 write_unlock(&neigh->lock); 528 write_unlock(&neigh->lock);
508 }
509 529
510 target = (struct in6_addr *)&rt->rt6i_gateway; 530 if (work) {
511 addrconf_addr_solict_mult(target, &mcaddr); 531 INIT_WORK(&work->work, rt6_probe_deferred);
512 ndisc_send_ns(rt->dst.dev, NULL, target, &mcaddr, NULL); 532 work->target = rt->rt6i_gateway;
533 dev_hold(rt->dst.dev);
534 work->dev = rt->dst.dev;
535 schedule_work(&work->work);
536 }
513 } else { 537 } else {
514out: 538out:
515 write_unlock(&neigh->lock); 539 write_unlock(&neigh->lock);
@@ -851,7 +875,6 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort,
851 if (ort->rt6i_dst.plen != 128 && 875 if (ort->rt6i_dst.plen != 128 &&
852 ipv6_addr_equal(&ort->rt6i_dst.addr, daddr)) 876 ipv6_addr_equal(&ort->rt6i_dst.addr, daddr))
853 rt->rt6i_flags |= RTF_ANYCAST; 877 rt->rt6i_flags |= RTF_ANYCAST;
854 rt->rt6i_gateway = *daddr;
855 } 878 }
856 879
857 rt->rt6i_flags |= RTF_CACHE; 880 rt->rt6i_flags |= RTF_CACHE;
@@ -1338,6 +1361,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
1338 rt->dst.flags |= DST_HOST; 1361 rt->dst.flags |= DST_HOST;
1339 rt->dst.output = ip6_output; 1362 rt->dst.output = ip6_output;
1340 atomic_set(&rt->dst.__refcnt, 1); 1363 atomic_set(&rt->dst.__refcnt, 1);
1364 rt->rt6i_gateway = fl6->daddr;
1341 rt->rt6i_dst.addr = fl6->daddr; 1365 rt->rt6i_dst.addr = fl6->daddr;
1342 rt->rt6i_dst.plen = 128; 1366 rt->rt6i_dst.plen = 128;
1343 rt->rt6i_idev = idev; 1367 rt->rt6i_idev = idev;
@@ -1873,7 +1897,10 @@ static struct rt6_info *ip6_rt_copy(struct rt6_info *ort,
1873 in6_dev_hold(rt->rt6i_idev); 1897 in6_dev_hold(rt->rt6i_idev);
1874 rt->dst.lastuse = jiffies; 1898 rt->dst.lastuse = jiffies;
1875 1899
1876 rt->rt6i_gateway = ort->rt6i_gateway; 1900 if (ort->rt6i_flags & RTF_GATEWAY)
1901 rt->rt6i_gateway = ort->rt6i_gateway;
1902 else
1903 rt->rt6i_gateway = *dest;
1877 rt->rt6i_flags = ort->rt6i_flags; 1904 rt->rt6i_flags = ort->rt6i_flags;
1878 if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) == 1905 if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ==
1879 (RTF_DEFAULT | RTF_ADDRCONF)) 1906 (RTF_DEFAULT | RTF_ADDRCONF))
@@ -2160,6 +2187,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
2160 else 2187 else
2161 rt->rt6i_flags |= RTF_LOCAL; 2188 rt->rt6i_flags |= RTF_LOCAL;
2162 2189
2190 rt->rt6i_gateway = *addr;
2163 rt->rt6i_dst.addr = *addr; 2191 rt->rt6i_dst.addr = *addr;
2164 rt->rt6i_dst.plen = 128; 2192 rt->rt6i_dst.plen = 128;
2165 rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); 2193 rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL);
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 72b7eaaf3ca0..18786098fd41 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1225,9 +1225,6 @@ do_udp_sendmsg:
1225 if (tclass < 0) 1225 if (tclass < 0)
1226 tclass = np->tclass; 1226 tclass = np->tclass;
1227 1227
1228 if (dontfrag < 0)
1229 dontfrag = np->dontfrag;
1230
1231 if (msg->msg_flags&MSG_CONFIRM) 1228 if (msg->msg_flags&MSG_CONFIRM)
1232 goto do_confirm; 1229 goto do_confirm;
1233back_from_confirm: 1230back_from_confirm:
@@ -1246,6 +1243,8 @@ back_from_confirm:
1246 up->pending = AF_INET6; 1243 up->pending = AF_INET6;
1247 1244
1248do_append_data: 1245do_append_data:
1246 if (dontfrag < 0)
1247 dontfrag = np->dontfrag;
1249 up->len += ulen; 1248 up->len += ulen;
1250 getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; 1249 getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
1251 err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen, 1250 err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen,
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 23ed03d786c8..08ed2772b7aa 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -138,6 +138,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
138 138
139 memset(fl6, 0, sizeof(struct flowi6)); 139 memset(fl6, 0, sizeof(struct flowi6));
140 fl6->flowi6_mark = skb->mark; 140 fl6->flowi6_mark = skb->mark;
141 fl6->flowi6_oif = skb_dst(skb)->dev->ifindex;
141 142
142 fl6->daddr = reverse ? hdr->saddr : hdr->daddr; 143 fl6->daddr = reverse ? hdr->saddr : hdr->daddr;
143 fl6->saddr = reverse ? hdr->daddr : hdr->saddr; 144 fl6->saddr = reverse ? hdr->daddr : hdr->saddr;