diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 79 | ||||
-rw-r--r-- | net/ipv6/ah6.c | 3 | ||||
-rw-r--r-- | net/ipv6/esp6.c | 3 | ||||
-rw-r--r-- | net/ipv6/inet6_hashtables.c | 2 | ||||
-rw-r--r-- | net/ipv6/ip6_gre.c | 10 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 78 | ||||
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 19 | ||||
-rw-r--r-- | net/ipv6/ipcomp6.c | 3 | ||||
-rw-r--r-- | net/ipv6/mcast.c | 6 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_SYNPROXY.c | 10 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_nat_proto_icmpv6.c | 4 | ||||
-rw-r--r-- | net/ipv6/raw.c | 4 | ||||
-rw-r--r-- | net/ipv6/route.c | 46 | ||||
-rw-r--r-- | net/ipv6/sit.c | 86 | ||||
-rw-r--r-- | net/ipv6/udp.c | 9 | ||||
-rw-r--r-- | net/ipv6/xfrm6_policy.c | 1 |
16 files changed, 227 insertions, 136 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index d6ff12617f36..cd3fb301da38 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -1499,6 +1499,33 @@ static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, | |||
1499 | return false; | 1499 | return false; |
1500 | } | 1500 | } |
1501 | 1501 | ||
1502 | /* Compares an address/prefix_len with addresses on device @dev. | ||
1503 | * If one is found it returns true. | ||
1504 | */ | ||
1505 | bool ipv6_chk_custom_prefix(const struct in6_addr *addr, | ||
1506 | const unsigned int prefix_len, struct net_device *dev) | ||
1507 | { | ||
1508 | struct inet6_dev *idev; | ||
1509 | struct inet6_ifaddr *ifa; | ||
1510 | bool ret = false; | ||
1511 | |||
1512 | rcu_read_lock(); | ||
1513 | idev = __in6_dev_get(dev); | ||
1514 | if (idev) { | ||
1515 | read_lock_bh(&idev->lock); | ||
1516 | list_for_each_entry(ifa, &idev->addr_list, if_list) { | ||
1517 | ret = ipv6_prefix_equal(addr, &ifa->addr, prefix_len); | ||
1518 | if (ret) | ||
1519 | break; | ||
1520 | } | ||
1521 | read_unlock_bh(&idev->lock); | ||
1522 | } | ||
1523 | rcu_read_unlock(); | ||
1524 | |||
1525 | return ret; | ||
1526 | } | ||
1527 | EXPORT_SYMBOL(ipv6_chk_custom_prefix); | ||
1528 | |||
1502 | int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev) | 1529 | int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev) |
1503 | { | 1530 | { |
1504 | struct inet6_dev *idev; | 1531 | struct inet6_dev *idev; |
@@ -2193,43 +2220,21 @@ ok: | |||
2193 | else | 2220 | else |
2194 | stored_lft = 0; | 2221 | stored_lft = 0; |
2195 | if (!update_lft && !create && stored_lft) { | 2222 | if (!update_lft && !create && stored_lft) { |
2196 | if (valid_lft > MIN_VALID_LIFETIME || | 2223 | const u32 minimum_lft = min( |
2197 | valid_lft > stored_lft) | 2224 | stored_lft, (u32)MIN_VALID_LIFETIME); |
2198 | update_lft = 1; | 2225 | valid_lft = max(valid_lft, minimum_lft); |
2199 | else if (stored_lft <= MIN_VALID_LIFETIME) { | 2226 | |
2200 | /* valid_lft <= stored_lft is always true */ | 2227 | /* RFC4862 Section 5.5.3e: |
2201 | /* | 2228 | * "Note that the preferred lifetime of the |
2202 | * RFC 4862 Section 5.5.3e: | 2229 | * corresponding address is always reset to |
2203 | * "Note that the preferred lifetime of | 2230 | * the Preferred Lifetime in the received |
2204 | * the corresponding address is always | 2231 | * Prefix Information option, regardless of |
2205 | * reset to the Preferred Lifetime in | 2232 | * whether the valid lifetime is also reset or |
2206 | * the received Prefix Information | 2233 | * ignored." |
2207 | * option, regardless of whether the | 2234 | * |
2208 | * valid lifetime is also reset or | 2235 | * So we should always update prefered_lft here. |
2209 | * ignored." | 2236 | */ |
2210 | * | 2237 | update_lft = 1; |
2211 | * So if the preferred lifetime in | ||
2212 | * this advertisement is different | ||
2213 | * than what we have stored, but the | ||
2214 | * valid lifetime is invalid, just | ||
2215 | * reset prefered_lft. | ||
2216 | * | ||
2217 | * We must set the valid lifetime | ||
2218 | * to the stored lifetime since we'll | ||
2219 | * be updating the timestamp below, | ||
2220 | * else we'll set it back to the | ||
2221 | * minimum. | ||
2222 | */ | ||
2223 | if (prefered_lft != ifp->prefered_lft) { | ||
2224 | valid_lft = stored_lft; | ||
2225 | update_lft = 1; | ||
2226 | } | ||
2227 | } else { | ||
2228 | valid_lft = MIN_VALID_LIFETIME; | ||
2229 | if (valid_lft < prefered_lft) | ||
2230 | prefered_lft = valid_lft; | ||
2231 | update_lft = 1; | ||
2232 | } | ||
2233 | } | 2238 | } |
2234 | 2239 | ||
2235 | if (update_lft) { | 2240 | if (update_lft) { |
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 6b26e9feafb9..bf4a9a084de5 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c | |||
@@ -618,7 +618,7 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb, | |||
618 | struct ip6_tnl *tunnel = netdev_priv(dev); | 618 | struct ip6_tnl *tunnel = netdev_priv(dev); |
619 | struct net_device *tdev; /* Device to other host */ | 619 | struct net_device *tdev; /* Device to other host */ |
620 | struct ipv6hdr *ipv6h; /* Our new IP header */ | 620 | struct ipv6hdr *ipv6h; /* Our new IP header */ |
621 | unsigned int max_headroom; /* The extra header space needed */ | 621 | unsigned int max_headroom = 0; /* The extra header space needed */ |
622 | int gre_hlen; | 622 | int gre_hlen; |
623 | struct ipv6_tel_txoption opt; | 623 | struct ipv6_tel_txoption opt; |
624 | int mtu; | 624 | int mtu; |
@@ -693,7 +693,7 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb, | |||
693 | 693 | ||
694 | skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(dev))); | 694 | skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(dev))); |
695 | 695 | ||
696 | max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen + dst->header_len; | 696 | max_headroom += LL_RESERVED_SPACE(tdev) + gre_hlen + dst->header_len; |
697 | 697 | ||
698 | if (skb_headroom(skb) < max_headroom || skb_shared(skb) || | 698 | if (skb_headroom(skb) < max_headroom || skb_shared(skb) || |
699 | (skb_cloned(skb) && !skb_clone_writable(skb, 0))) { | 699 | (skb_cloned(skb) && !skb_clone_writable(skb, 0))) { |
@@ -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 | ||
1009 | static int ip6gre_tnl_change(struct ip6_tnl *t, | 1008 | static int ip6gre_tnl_change(struct ip6_tnl *t, |
@@ -1173,9 +1172,8 @@ done: | |||
1173 | 1172 | ||
1174 | static int ip6gre_tunnel_change_mtu(struct net_device *dev, int new_mtu) | 1173 | static 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 3a692d529163..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 |
@@ -1034,33 +1035,26 @@ static inline int ip6_ufo_append_data(struct sock *sk, | |||
1034 | skb->transport_header = skb->network_header + fragheaderlen; | 1035 | skb->transport_header = skb->network_header + fragheaderlen; |
1035 | 1036 | ||
1036 | skb->protocol = htons(ETH_P_IPV6); | 1037 | skb->protocol = htons(ETH_P_IPV6); |
1037 | skb->ip_summed = CHECKSUM_PARTIAL; | ||
1038 | skb->csum = 0; | 1038 | skb->csum = 0; |
1039 | } | ||
1040 | |||
1041 | err = skb_append_datato_frags(sk,skb, getfrag, from, | ||
1042 | (length - transhdrlen)); | ||
1043 | if (!err) { | ||
1044 | struct frag_hdr fhdr; | ||
1045 | 1039 | ||
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 | __skb_queue_tail(&sk->sk_write_queue, skb); | 1040 | __skb_queue_tail(&sk->sk_write_queue, skb); |
1055 | 1041 | } else if (skb_is_gso(skb)) { | |
1056 | return 0; | 1042 | goto append; |
1057 | } | 1043 | } |
1058 | /* There is not enough support do UPD LSO, | ||
1059 | * so follow normal path | ||
1060 | */ | ||
1061 | kfree_skb(skb); | ||
1062 | 1044 | ||
1063 | return err; | 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 | |||
1055 | append: | ||
1056 | return skb_append_datato_frags(sk, skb, getfrag, from, | ||
1057 | (length - transhdrlen)); | ||
1064 | } | 1058 | } |
1065 | 1059 | ||
1066 | static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src, | 1060 | static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src, |
@@ -1227,27 +1221,27 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1227 | * --yoshfuji | 1221 | * --yoshfuji |
1228 | */ | 1222 | */ |
1229 | 1223 | ||
1230 | cork->length += length; | 1224 | if ((length > mtu) && dontfrag && (sk->sk_protocol == IPPROTO_UDP || |
1231 | if (length > mtu) { | 1225 | sk->sk_protocol == IPPROTO_RAW)) { |
1232 | int proto = sk->sk_protocol; | 1226 | ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen); |
1233 | if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){ | 1227 | return -EMSGSIZE; |
1234 | ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen); | 1228 | } |
1235 | return -EMSGSIZE; | ||
1236 | } | ||
1237 | |||
1238 | if (proto == IPPROTO_UDP && | ||
1239 | (rt->dst.dev->features & NETIF_F_UFO)) { | ||
1240 | 1229 | ||
1241 | err = ip6_ufo_append_data(sk, getfrag, from, length, | 1230 | skb = skb_peek_tail(&sk->sk_write_queue); |
1242 | hh_len, fragheaderlen, | 1231 | cork->length += length; |
1243 | transhdrlen, mtu, flags, rt); | 1232 | if (((length > mtu) || |
1244 | if (err) | 1233 | (skb && skb_is_gso(skb))) && |
1245 | goto error; | 1234 | (sk->sk_protocol == IPPROTO_UDP) && |
1246 | return 0; | 1235 | (rt->dst.dev->features & NETIF_F_UFO)) { |
1247 | } | 1236 | err = ip6_ufo_append_data(sk, getfrag, from, length, |
1237 | hh_len, fragheaderlen, | ||
1238 | transhdrlen, mtu, flags, rt); | ||
1239 | if (err) | ||
1240 | goto error; | ||
1241 | return 0; | ||
1248 | } | 1242 | } |
1249 | 1243 | ||
1250 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) | 1244 | if (!skb) |
1251 | goto alloc_new_skb; | 1245 | goto alloc_new_skb; |
1252 | 1246 | ||
1253 | while (length > 0) { | 1247 | while (length > 0) { |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 61355f7f4da5..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) | |||
1430 | static int | 1430 | static int |
1431 | ip6_tnl_change_mtu(struct net_device *dev, int new_mtu) | 1431 | ip6_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 | } |
@@ -1656,9 +1664,9 @@ static int ip6_tnl_fill_info(struct sk_buff *skb, const struct net_device *dev) | |||
1656 | 1664 | ||
1657 | if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) || | 1665 | if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) || |
1658 | nla_put(skb, IFLA_IPTUN_LOCAL, sizeof(struct in6_addr), | 1666 | nla_put(skb, IFLA_IPTUN_LOCAL, sizeof(struct in6_addr), |
1659 | &parm->raddr) || | ||
1660 | nla_put(skb, IFLA_IPTUN_REMOTE, sizeof(struct in6_addr), | ||
1661 | &parm->laddr) || | 1667 | &parm->laddr) || |
1668 | nla_put(skb, IFLA_IPTUN_REMOTE, sizeof(struct in6_addr), | ||
1669 | &parm->raddr) || | ||
1662 | nla_put_u8(skb, IFLA_IPTUN_TTL, parm->hop_limit) || | 1670 | nla_put_u8(skb, IFLA_IPTUN_TTL, parm->hop_limit) || |
1663 | nla_put_u8(skb, IFLA_IPTUN_ENCAP_LIMIT, parm->encap_limit) || | 1671 | nla_put_u8(skb, IFLA_IPTUN_ENCAP_LIMIT, parm->encap_limit) || |
1664 | nla_put_be32(skb, IFLA_IPTUN_FLOWINFO, parm->flowinfo) || | 1672 | nla_put_be32(skb, IFLA_IPTUN_FLOWINFO, parm->flowinfo) || |
@@ -1731,8 +1739,6 @@ static void __net_exit ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n) | |||
1731 | } | 1739 | } |
1732 | } | 1740 | } |
1733 | 1741 | ||
1734 | t = rtnl_dereference(ip6n->tnls_wc[0]); | ||
1735 | unregister_netdevice_queue(t->dev, &list); | ||
1736 | unregister_netdevice_many(&list); | 1742 | unregister_netdevice_many(&list); |
1737 | } | 1743 | } |
1738 | 1744 | ||
@@ -1752,6 +1758,7 @@ static int __net_init ip6_tnl_init_net(struct net *net) | |||
1752 | if (!ip6n->fb_tnl_dev) | 1758 | if (!ip6n->fb_tnl_dev) |
1753 | goto err_alloc_dev; | 1759 | goto err_alloc_dev; |
1754 | dev_net_set(ip6n->fb_tnl_dev, net); | 1760 | dev_net_set(ip6n->fb_tnl_dev, net); |
1761 | ip6n->fb_tnl_dev->rtnl_link_ops = &ip6_link_ops; | ||
1755 | /* FB netdevice is special: we have one, and only one per netns. | 1762 | /* FB netdevice is special: we have one, and only one per netns. |
1756 | * Allowing to move it to another netns is clearly unsafe. | 1763 | * Allowing to move it to another netns is clearly unsafe. |
1757 | */ | 1764 | */ |
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/mcast.c b/net/ipv6/mcast.c index 096cd67b737c..d18f9f903db6 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -2034,7 +2034,7 @@ static void mld_dad_timer_expire(unsigned long data) | |||
2034 | if (idev->mc_dad_count) | 2034 | if (idev->mc_dad_count) |
2035 | mld_dad_start_timer(idev, idev->mc_maxdelay); | 2035 | mld_dad_start_timer(idev, idev->mc_maxdelay); |
2036 | } | 2036 | } |
2037 | __in6_dev_put(idev); | 2037 | in6_dev_put(idev); |
2038 | } | 2038 | } |
2039 | 2039 | ||
2040 | static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode, | 2040 | static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode, |
@@ -2379,7 +2379,7 @@ static void mld_gq_timer_expire(unsigned long data) | |||
2379 | 2379 | ||
2380 | idev->mc_gq_running = 0; | 2380 | idev->mc_gq_running = 0; |
2381 | mld_send_report(idev, NULL); | 2381 | mld_send_report(idev, NULL); |
2382 | __in6_dev_put(idev); | 2382 | in6_dev_put(idev); |
2383 | } | 2383 | } |
2384 | 2384 | ||
2385 | static void mld_ifc_timer_expire(unsigned long data) | 2385 | static void mld_ifc_timer_expire(unsigned long data) |
@@ -2392,7 +2392,7 @@ static void mld_ifc_timer_expire(unsigned long data) | |||
2392 | if (idev->mc_ifc_count) | 2392 | if (idev->mc_ifc_count) |
2393 | mld_ifc_start_timer(idev, idev->mc_maxdelay); | 2393 | mld_ifc_start_timer(idev, idev->mc_maxdelay); |
2394 | } | 2394 | } |
2395 | __in6_dev_put(idev); | 2395 | in6_dev_put(idev); |
2396 | } | 2396 | } |
2397 | 2397 | ||
2398 | static void mld_ifc_event(struct inet6_dev *idev) | 2398 | static void mld_ifc_event(struct inet6_dev *idev) |
diff --git a/net/ipv6/netfilter/ip6t_SYNPROXY.c b/net/ipv6/netfilter/ip6t_SYNPROXY.c index 19cfea8dbcaa..2748b042da72 100644 --- a/net/ipv6/netfilter/ip6t_SYNPROXY.c +++ b/net/ipv6/netfilter/ip6t_SYNPROXY.c | |||
@@ -282,7 +282,8 @@ synproxy_tg6(struct sk_buff *skb, const struct xt_action_param *par) | |||
282 | if (th == NULL) | 282 | if (th == NULL) |
283 | return NF_DROP; | 283 | return NF_DROP; |
284 | 284 | ||
285 | synproxy_parse_options(skb, par->thoff, th, &opts); | 285 | if (!synproxy_parse_options(skb, par->thoff, th, &opts)) |
286 | return NF_DROP; | ||
286 | 287 | ||
287 | if (th->syn && !(th->ack || th->fin || th->rst)) { | 288 | if (th->syn && !(th->ack || th->fin || th->rst)) { |
288 | /* Initial SYN from client */ | 289 | /* Initial SYN from client */ |
@@ -372,7 +373,8 @@ static unsigned int ipv6_synproxy_hook(unsigned int hooknum, | |||
372 | 373 | ||
373 | /* fall through */ | 374 | /* fall through */ |
374 | case TCP_CONNTRACK_SYN_SENT: | 375 | case TCP_CONNTRACK_SYN_SENT: |
375 | synproxy_parse_options(skb, thoff, th, &opts); | 376 | if (!synproxy_parse_options(skb, thoff, th, &opts)) |
377 | return NF_DROP; | ||
376 | 378 | ||
377 | if (!th->syn && th->ack && | 379 | if (!th->syn && th->ack && |
378 | CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) { | 380 | CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) { |
@@ -395,7 +397,9 @@ static unsigned int ipv6_synproxy_hook(unsigned int hooknum, | |||
395 | if (!th->syn || !th->ack) | 397 | if (!th->syn || !th->ack) |
396 | break; | 398 | break; |
397 | 399 | ||
398 | synproxy_parse_options(skb, thoff, th, &opts); | 400 | if (!synproxy_parse_options(skb, thoff, th, &opts)) |
401 | return NF_DROP; | ||
402 | |||
399 | if (opts.options & XT_SYNPROXY_OPT_TIMESTAMP) | 403 | if (opts.options & XT_SYNPROXY_OPT_TIMESTAMP) |
400 | synproxy->tsoff = opts.tsval - synproxy->its; | 404 | synproxy->tsoff = opts.tsval - synproxy->its; |
401 | 405 | ||
diff --git a/net/ipv6/netfilter/nf_nat_proto_icmpv6.c b/net/ipv6/netfilter/nf_nat_proto_icmpv6.c index 61aaf70f376e..2205e8eeeacf 100644 --- a/net/ipv6/netfilter/nf_nat_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_nat_proto_icmpv6.c | |||
@@ -69,8 +69,8 @@ icmpv6_manip_pkt(struct sk_buff *skb, | |||
69 | hdr = (struct icmp6hdr *)(skb->data + hdroff); | 69 | hdr = (struct icmp6hdr *)(skb->data + hdroff); |
70 | l3proto->csum_update(skb, iphdroff, &hdr->icmp6_cksum, | 70 | l3proto->csum_update(skb, iphdroff, &hdr->icmp6_cksum, |
71 | tuple, maniptype); | 71 | tuple, maniptype); |
72 | if (hdr->icmp6_code == ICMPV6_ECHO_REQUEST || | 72 | if (hdr->icmp6_type == ICMPV6_ECHO_REQUEST || |
73 | hdr->icmp6_code == ICMPV6_ECHO_REPLY) { | 73 | hdr->icmp6_type == ICMPV6_ECHO_REPLY) { |
74 | inet_proto_csum_replace2(&hdr->icmp6_cksum, skb, | 74 | inet_proto_csum_replace2(&hdr->icmp6_cksum, skb, |
75 | hdr->icmp6_identifier, | 75 | hdr->icmp6_identifier, |
76 | tuple->src.u.icmp.id, 0); | 76 | tuple->src.u.icmp.id, 0); |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 58916bbb1728..a4ed2416399e 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -335,8 +335,10 @@ static void rawv6_err(struct sock *sk, struct sk_buff *skb, | |||
335 | ip6_sk_update_pmtu(skb, sk, info); | 335 | ip6_sk_update_pmtu(skb, sk, info); |
336 | harderr = (np->pmtudisc == IPV6_PMTUDISC_DO); | 336 | harderr = (np->pmtudisc == IPV6_PMTUDISC_DO); |
337 | } | 337 | } |
338 | if (type == NDISC_REDIRECT) | 338 | if (type == NDISC_REDIRECT) { |
339 | ip6_sk_redirect(skb, sk); | 339 | ip6_sk_redirect(skb, sk); |
340 | return; | ||
341 | } | ||
340 | if (np->recverr) { | 342 | if (np->recverr) { |
341 | u8 *payload = skb->data; | 343 | u8 *payload = skb->data; |
342 | if (!inet->hdrincl) | 344 | if (!inet->hdrincl) |
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 |
479 | struct __rt6_probe_work { | ||
480 | struct work_struct work; | ||
481 | struct in6_addr target; | ||
482 | struct net_device *dev; | ||
483 | }; | ||
484 | |||
485 | static 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 | |||
479 | static void rt6_probe(struct rt6_info *rt) | 497 | static 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 { |
514 | out: | 538 | out: |
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/sit.c b/net/ipv6/sit.c index 7ee5cb96db34..19269453a8ea 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -566,6 +566,70 @@ static inline bool is_spoofed_6rd(struct ip_tunnel *tunnel, const __be32 v4addr, | |||
566 | return false; | 566 | return false; |
567 | } | 567 | } |
568 | 568 | ||
569 | /* Checks if an address matches an address on the tunnel interface. | ||
570 | * Used to detect the NAT of proto 41 packets and let them pass spoofing test. | ||
571 | * Long story: | ||
572 | * This function is called after we considered the packet as spoofed | ||
573 | * in is_spoofed_6rd. | ||
574 | * We may have a router that is doing NAT for proto 41 packets | ||
575 | * for an internal station. Destination a.a.a.a/PREFIX:bbbb:bbbb | ||
576 | * will be translated to n.n.n.n/PREFIX:bbbb:bbbb. And is_spoofed_6rd | ||
577 | * function will return true, dropping the packet. | ||
578 | * But, we can still check if is spoofed against the IP | ||
579 | * addresses associated with the interface. | ||
580 | */ | ||
581 | static bool only_dnatted(const struct ip_tunnel *tunnel, | ||
582 | const struct in6_addr *v6dst) | ||
583 | { | ||
584 | int prefix_len; | ||
585 | |||
586 | #ifdef CONFIG_IPV6_SIT_6RD | ||
587 | prefix_len = tunnel->ip6rd.prefixlen + 32 | ||
588 | - tunnel->ip6rd.relay_prefixlen; | ||
589 | #else | ||
590 | prefix_len = 48; | ||
591 | #endif | ||
592 | return ipv6_chk_custom_prefix(v6dst, prefix_len, tunnel->dev); | ||
593 | } | ||
594 | |||
595 | /* Returns true if a packet is spoofed */ | ||
596 | static bool packet_is_spoofed(struct sk_buff *skb, | ||
597 | const struct iphdr *iph, | ||
598 | struct ip_tunnel *tunnel) | ||
599 | { | ||
600 | const struct ipv6hdr *ipv6h; | ||
601 | |||
602 | if (tunnel->dev->priv_flags & IFF_ISATAP) { | ||
603 | if (!isatap_chksrc(skb, iph, tunnel)) | ||
604 | return true; | ||
605 | |||
606 | return false; | ||
607 | } | ||
608 | |||
609 | if (tunnel->dev->flags & IFF_POINTOPOINT) | ||
610 | return false; | ||
611 | |||
612 | ipv6h = ipv6_hdr(skb); | ||
613 | |||
614 | if (unlikely(is_spoofed_6rd(tunnel, iph->saddr, &ipv6h->saddr))) { | ||
615 | net_warn_ratelimited("Src spoofed %pI4/%pI6c -> %pI4/%pI6c\n", | ||
616 | &iph->saddr, &ipv6h->saddr, | ||
617 | &iph->daddr, &ipv6h->daddr); | ||
618 | return true; | ||
619 | } | ||
620 | |||
621 | if (likely(!is_spoofed_6rd(tunnel, iph->daddr, &ipv6h->daddr))) | ||
622 | return false; | ||
623 | |||
624 | if (only_dnatted(tunnel, &ipv6h->daddr)) | ||
625 | return false; | ||
626 | |||
627 | net_warn_ratelimited("Dst spoofed %pI4/%pI6c -> %pI4/%pI6c\n", | ||
628 | &iph->saddr, &ipv6h->saddr, | ||
629 | &iph->daddr, &ipv6h->daddr); | ||
630 | return true; | ||
631 | } | ||
632 | |||
569 | static int ipip6_rcv(struct sk_buff *skb) | 633 | static int ipip6_rcv(struct sk_buff *skb) |
570 | { | 634 | { |
571 | const struct iphdr *iph = ip_hdr(skb); | 635 | const struct iphdr *iph = ip_hdr(skb); |
@@ -586,19 +650,9 @@ static int ipip6_rcv(struct sk_buff *skb) | |||
586 | IPCB(skb)->flags = 0; | 650 | IPCB(skb)->flags = 0; |
587 | skb->protocol = htons(ETH_P_IPV6); | 651 | skb->protocol = htons(ETH_P_IPV6); |
588 | 652 | ||
589 | if (tunnel->dev->priv_flags & IFF_ISATAP) { | 653 | if (packet_is_spoofed(skb, iph, tunnel)) { |
590 | if (!isatap_chksrc(skb, iph, tunnel)) { | 654 | tunnel->dev->stats.rx_errors++; |
591 | tunnel->dev->stats.rx_errors++; | 655 | goto out; |
592 | goto out; | ||
593 | } | ||
594 | } else if (!(tunnel->dev->flags&IFF_POINTOPOINT)) { | ||
595 | if (is_spoofed_6rd(tunnel, iph->saddr, | ||
596 | &ipv6_hdr(skb)->saddr) || | ||
597 | is_spoofed_6rd(tunnel, iph->daddr, | ||
598 | &ipv6_hdr(skb)->daddr)) { | ||
599 | tunnel->dev->stats.rx_errors++; | ||
600 | goto out; | ||
601 | } | ||
602 | } | 656 | } |
603 | 657 | ||
604 | __skb_tunnel_rx(skb, tunnel->dev, tunnel->net); | 658 | __skb_tunnel_rx(skb, tunnel->dev, tunnel->net); |
@@ -748,7 +802,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
748 | neigh = dst_neigh_lookup(skb_dst(skb), &iph6->daddr); | 802 | neigh = dst_neigh_lookup(skb_dst(skb), &iph6->daddr); |
749 | 803 | ||
750 | if (neigh == NULL) { | 804 | if (neigh == NULL) { |
751 | net_dbg_ratelimited("sit: nexthop == NULL\n"); | 805 | net_dbg_ratelimited("nexthop == NULL\n"); |
752 | goto tx_error; | 806 | goto tx_error; |
753 | } | 807 | } |
754 | 808 | ||
@@ -777,7 +831,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
777 | neigh = dst_neigh_lookup(skb_dst(skb), &iph6->daddr); | 831 | neigh = dst_neigh_lookup(skb_dst(skb), &iph6->daddr); |
778 | 832 | ||
779 | if (neigh == NULL) { | 833 | if (neigh == NULL) { |
780 | net_dbg_ratelimited("sit: nexthop == NULL\n"); | 834 | net_dbg_ratelimited("nexthop == NULL\n"); |
781 | goto tx_error; | 835 | goto tx_error; |
782 | } | 836 | } |
783 | 837 | ||
@@ -1612,6 +1666,7 @@ static int __net_init sit_init_net(struct net *net) | |||
1612 | goto err_alloc_dev; | 1666 | goto err_alloc_dev; |
1613 | } | 1667 | } |
1614 | dev_net_set(sitn->fb_tunnel_dev, net); | 1668 | dev_net_set(sitn->fb_tunnel_dev, net); |
1669 | sitn->fb_tunnel_dev->rtnl_link_ops = &sit_link_ops; | ||
1615 | /* FB netdevice is special: we have one, and only one per netns. | 1670 | /* FB netdevice is special: we have one, and only one per netns. |
1616 | * Allowing to move it to another netns is clearly unsafe. | 1671 | * Allowing to move it to another netns is clearly unsafe. |
1617 | */ | 1672 | */ |
@@ -1646,7 +1701,6 @@ static void __net_exit sit_exit_net(struct net *net) | |||
1646 | 1701 | ||
1647 | rtnl_lock(); | 1702 | rtnl_lock(); |
1648 | sit_destroy_tunnels(sitn, &list); | 1703 | sit_destroy_tunnels(sitn, &list); |
1649 | unregister_netdevice_queue(sitn->fb_tunnel_dev, &list); | ||
1650 | unregister_netdevice_many(&list); | 1704 | unregister_netdevice_many(&list); |
1651 | rtnl_unlock(); | 1705 | rtnl_unlock(); |
1652 | } | 1706 | } |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index f4058150262b..18786098fd41 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -525,8 +525,10 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
525 | 525 | ||
526 | if (type == ICMPV6_PKT_TOOBIG) | 526 | if (type == ICMPV6_PKT_TOOBIG) |
527 | ip6_sk_update_pmtu(skb, sk, info); | 527 | ip6_sk_update_pmtu(skb, sk, info); |
528 | if (type == NDISC_REDIRECT) | 528 | if (type == NDISC_REDIRECT) { |
529 | ip6_sk_redirect(skb, sk); | 529 | ip6_sk_redirect(skb, sk); |
530 | goto out; | ||
531 | } | ||
530 | 532 | ||
531 | np = inet6_sk(sk); | 533 | np = inet6_sk(sk); |
532 | 534 | ||
@@ -1223,9 +1225,6 @@ do_udp_sendmsg: | |||
1223 | if (tclass < 0) | 1225 | if (tclass < 0) |
1224 | tclass = np->tclass; | 1226 | tclass = np->tclass; |
1225 | 1227 | ||
1226 | if (dontfrag < 0) | ||
1227 | dontfrag = np->dontfrag; | ||
1228 | |||
1229 | if (msg->msg_flags&MSG_CONFIRM) | 1228 | if (msg->msg_flags&MSG_CONFIRM) |
1230 | goto do_confirm; | 1229 | goto do_confirm; |
1231 | back_from_confirm: | 1230 | back_from_confirm: |
@@ -1244,6 +1243,8 @@ back_from_confirm: | |||
1244 | up->pending = AF_INET6; | 1243 | up->pending = AF_INET6; |
1245 | 1244 | ||
1246 | do_append_data: | 1245 | do_append_data: |
1246 | if (dontfrag < 0) | ||
1247 | dontfrag = np->dontfrag; | ||
1247 | up->len += ulen; | 1248 | up->len += ulen; |
1248 | getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; | 1249 | getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; |
1249 | 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; |