diff options
Diffstat (limited to 'net/ipv6')
| -rw-r--r-- | net/ipv6/Kconfig | 1 | ||||
| -rw-r--r-- | net/ipv6/addrconf.c | 2 | ||||
| -rw-r--r-- | net/ipv6/exthdrs_core.c | 2 | ||||
| -rw-r--r-- | net/ipv6/icmp.c | 2 | ||||
| -rw-r--r-- | net/ipv6/ip6_offload.c | 20 | ||||
| -rw-r--r-- | net/ipv6/ip6_output.c | 20 | ||||
| -rw-r--r-- | net/ipv6/netfilter/Kconfig | 5 | ||||
| -rw-r--r-- | net/ipv6/netfilter/Makefile | 1 | ||||
| -rw-r--r-- | net/ipv6/netfilter/nft_reject_ipv6.c | 76 | ||||
| -rw-r--r-- | net/ipv6/ping.c | 1 | ||||
| -rw-r--r-- | net/ipv6/sit.c | 19 | ||||
| -rw-r--r-- | net/ipv6/udp_offload.c | 2 |
12 files changed, 135 insertions, 16 deletions
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index d92e5586783e..438a73aa777c 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
| @@ -138,6 +138,7 @@ config INET6_XFRM_MODE_ROUTEOPTIMIZATION | |||
| 138 | config IPV6_VTI | 138 | config IPV6_VTI |
| 139 | tristate "Virtual (secure) IPv6: tunneling" | 139 | tristate "Virtual (secure) IPv6: tunneling" |
| 140 | select IPV6_TUNNEL | 140 | select IPV6_TUNNEL |
| 141 | select NET_IP_TUNNEL | ||
| 141 | depends on INET6_XFRM_MODE_TUNNEL | 142 | depends on INET6_XFRM_MODE_TUNNEL |
| 142 | ---help--- | 143 | ---help--- |
| 143 | Tunneling means encapsulating data of one protocol type within | 144 | Tunneling means encapsulating data of one protocol type within |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index ad235690684c..fdbfeca36d63 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -2783,6 +2783,8 @@ static void addrconf_gre_config(struct net_device *dev) | |||
| 2783 | ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); | 2783 | ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); |
| 2784 | if (!ipv6_generate_eui64(addr.s6_addr + 8, dev)) | 2784 | if (!ipv6_generate_eui64(addr.s6_addr + 8, dev)) |
| 2785 | addrconf_add_linklocal(idev, &addr); | 2785 | addrconf_add_linklocal(idev, &addr); |
| 2786 | else | ||
| 2787 | addrconf_prefix_route(&addr, 64, dev, 0, 0); | ||
| 2786 | } | 2788 | } |
| 2787 | #endif | 2789 | #endif |
| 2788 | 2790 | ||
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c index 140748debc4a..8af3eb57f438 100644 --- a/net/ipv6/exthdrs_core.c +++ b/net/ipv6/exthdrs_core.c | |||
| @@ -212,7 +212,7 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, | |||
| 212 | found = (nexthdr == target); | 212 | found = (nexthdr == target); |
| 213 | 213 | ||
| 214 | if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) { | 214 | if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) { |
| 215 | if (target < 0) | 215 | if (target < 0 || found) |
| 216 | break; | 216 | break; |
| 217 | return -ENOENT; | 217 | return -ENOENT; |
| 218 | } | 218 | } |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index f81f59686f21..f2610e157660 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
| @@ -414,7 +414,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) | |||
| 414 | addr_type = ipv6_addr_type(&hdr->daddr); | 414 | addr_type = ipv6_addr_type(&hdr->daddr); |
| 415 | 415 | ||
| 416 | if (ipv6_chk_addr(net, &hdr->daddr, skb->dev, 0) || | 416 | if (ipv6_chk_addr(net, &hdr->daddr, skb->dev, 0) || |
| 417 | ipv6_anycast_destination(skb)) | 417 | ipv6_chk_acast_addr_src(net, skb->dev, &hdr->daddr)) |
| 418 | saddr = &hdr->daddr; | 418 | saddr = &hdr->daddr; |
| 419 | 419 | ||
| 420 | /* | 420 | /* |
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index 1e8683b135bb..59f95affceb0 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c | |||
| @@ -89,7 +89,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
| 89 | unsigned int unfrag_ip6hlen; | 89 | unsigned int unfrag_ip6hlen; |
| 90 | u8 *prevhdr; | 90 | u8 *prevhdr; |
| 91 | int offset = 0; | 91 | int offset = 0; |
| 92 | bool tunnel; | 92 | bool encap, udpfrag; |
| 93 | int nhoff; | 93 | int nhoff; |
| 94 | 94 | ||
| 95 | if (unlikely(skb_shinfo(skb)->gso_type & | 95 | if (unlikely(skb_shinfo(skb)->gso_type & |
| @@ -110,8 +110,8 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
| 110 | if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) | 110 | if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) |
| 111 | goto out; | 111 | goto out; |
| 112 | 112 | ||
| 113 | tunnel = SKB_GSO_CB(skb)->encap_level > 0; | 113 | encap = SKB_GSO_CB(skb)->encap_level > 0; |
| 114 | if (tunnel) | 114 | if (encap) |
| 115 | features = skb->dev->hw_enc_features & netif_skb_features(skb); | 115 | features = skb->dev->hw_enc_features & netif_skb_features(skb); |
| 116 | SKB_GSO_CB(skb)->encap_level += sizeof(*ipv6h); | 116 | SKB_GSO_CB(skb)->encap_level += sizeof(*ipv6h); |
| 117 | 117 | ||
| @@ -121,6 +121,12 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
| 121 | 121 | ||
| 122 | proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); | 122 | proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); |
| 123 | 123 | ||
| 124 | if (skb->encapsulation && | ||
| 125 | skb_shinfo(skb)->gso_type & (SKB_GSO_SIT|SKB_GSO_IPIP)) | ||
| 126 | udpfrag = proto == IPPROTO_UDP && encap; | ||
| 127 | else | ||
| 128 | udpfrag = proto == IPPROTO_UDP && !skb->encapsulation; | ||
| 129 | |||
| 124 | ops = rcu_dereference(inet6_offloads[proto]); | 130 | ops = rcu_dereference(inet6_offloads[proto]); |
| 125 | if (likely(ops && ops->callbacks.gso_segment)) { | 131 | if (likely(ops && ops->callbacks.gso_segment)) { |
| 126 | skb_reset_transport_header(skb); | 132 | skb_reset_transport_header(skb); |
| @@ -133,13 +139,9 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
| 133 | for (skb = segs; skb; skb = skb->next) { | 139 | for (skb = segs; skb; skb = skb->next) { |
| 134 | ipv6h = (struct ipv6hdr *)(skb_mac_header(skb) + nhoff); | 140 | ipv6h = (struct ipv6hdr *)(skb_mac_header(skb) + nhoff); |
| 135 | ipv6h->payload_len = htons(skb->len - nhoff - sizeof(*ipv6h)); | 141 | ipv6h->payload_len = htons(skb->len - nhoff - sizeof(*ipv6h)); |
| 136 | if (tunnel) { | ||
| 137 | skb_reset_inner_headers(skb); | ||
| 138 | skb->encapsulation = 1; | ||
| 139 | } | ||
| 140 | skb->network_header = (u8 *)ipv6h - skb->head; | 142 | skb->network_header = (u8 *)ipv6h - skb->head; |
| 141 | 143 | ||
| 142 | if (!tunnel && proto == IPPROTO_UDP) { | 144 | if (udpfrag) { |
| 143 | unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr); | 145 | unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr); |
| 144 | fptr = (struct frag_hdr *)((u8 *)ipv6h + unfrag_ip6hlen); | 146 | fptr = (struct frag_hdr *)((u8 *)ipv6h + unfrag_ip6hlen); |
| 145 | fptr->frag_off = htons(offset); | 147 | fptr->frag_off = htons(offset); |
| @@ -148,6 +150,8 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
| 148 | offset += (ntohs(ipv6h->payload_len) - | 150 | offset += (ntohs(ipv6h->payload_len) - |
| 149 | sizeof(struct frag_hdr)); | 151 | sizeof(struct frag_hdr)); |
| 150 | } | 152 | } |
| 153 | if (encap) | ||
| 154 | skb_reset_inner_headers(skb); | ||
| 151 | } | 155 | } |
| 152 | 156 | ||
| 153 | out: | 157 | out: |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index ef02b26ccf81..16f91a2e7888 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
| @@ -342,6 +342,20 @@ static unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst) | |||
| 342 | return mtu; | 342 | return mtu; |
| 343 | } | 343 | } |
| 344 | 344 | ||
| 345 | static bool ip6_pkt_too_big(const struct sk_buff *skb, unsigned int mtu) | ||
| 346 | { | ||
| 347 | if (skb->len <= mtu || skb->local_df) | ||
| 348 | return false; | ||
| 349 | |||
| 350 | if (IP6CB(skb)->frag_max_size && IP6CB(skb)->frag_max_size > mtu) | ||
| 351 | return true; | ||
| 352 | |||
| 353 | if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu) | ||
| 354 | return false; | ||
| 355 | |||
| 356 | return true; | ||
| 357 | } | ||
| 358 | |||
| 345 | int ip6_forward(struct sk_buff *skb) | 359 | int ip6_forward(struct sk_buff *skb) |
| 346 | { | 360 | { |
| 347 | struct dst_entry *dst = skb_dst(skb); | 361 | struct dst_entry *dst = skb_dst(skb); |
| @@ -466,8 +480,7 @@ int ip6_forward(struct sk_buff *skb) | |||
| 466 | if (mtu < IPV6_MIN_MTU) | 480 | if (mtu < IPV6_MIN_MTU) |
| 467 | mtu = IPV6_MIN_MTU; | 481 | mtu = IPV6_MIN_MTU; |
| 468 | 482 | ||
| 469 | if ((!skb->local_df && skb->len > mtu && !skb_is_gso(skb)) || | 483 | if (ip6_pkt_too_big(skb, mtu)) { |
| 470 | (IP6CB(skb)->frag_max_size && IP6CB(skb)->frag_max_size > mtu)) { | ||
| 471 | /* Again, force OUTPUT device used as source address */ | 484 | /* Again, force OUTPUT device used as source address */ |
| 472 | skb->dev = dst->dev; | 485 | skb->dev = dst->dev; |
| 473 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); | 486 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
| @@ -517,9 +530,6 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) | |||
| 517 | to->tc_index = from->tc_index; | 530 | to->tc_index = from->tc_index; |
| 518 | #endif | 531 | #endif |
| 519 | nf_copy(to, from); | 532 | nf_copy(to, from); |
| 520 | #if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) | ||
| 521 | to->nf_trace = from->nf_trace; | ||
| 522 | #endif | ||
| 523 | skb_copy_secmark(to, from); | 533 | skb_copy_secmark(to, from); |
| 524 | } | 534 | } |
| 525 | 535 | ||
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 35750df744dc..4bff1f297e39 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
| @@ -50,6 +50,11 @@ config NFT_CHAIN_NAT_IPV6 | |||
| 50 | packet transformations such as the source, destination address and | 50 | packet transformations such as the source, destination address and |
| 51 | source and destination ports. | 51 | source and destination ports. |
| 52 | 52 | ||
| 53 | config NFT_REJECT_IPV6 | ||
| 54 | depends on NF_TABLES_IPV6 | ||
| 55 | default NFT_REJECT | ||
| 56 | tristate | ||
| 57 | |||
| 53 | config IP6_NF_IPTABLES | 58 | config IP6_NF_IPTABLES |
| 54 | tristate "IP6 tables support (required for filtering)" | 59 | tristate "IP6 tables support (required for filtering)" |
| 55 | depends on INET && IPV6 | 60 | depends on INET && IPV6 |
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index d1b4928f34f7..70d3dd66f2cd 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
| @@ -27,6 +27,7 @@ obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o | |||
| 27 | obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o | 27 | obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o |
| 28 | obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o | 28 | obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o |
| 29 | obj-$(CONFIG_NFT_CHAIN_NAT_IPV6) += nft_chain_nat_ipv6.o | 29 | obj-$(CONFIG_NFT_CHAIN_NAT_IPV6) += nft_chain_nat_ipv6.o |
| 30 | obj-$(CONFIG_NFT_REJECT_IPV6) += nft_reject_ipv6.o | ||
| 30 | 31 | ||
| 31 | # matches | 32 | # matches |
| 32 | obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o | 33 | obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o |
diff --git a/net/ipv6/netfilter/nft_reject_ipv6.c b/net/ipv6/netfilter/nft_reject_ipv6.c new file mode 100644 index 000000000000..0bc19fa87821 --- /dev/null +++ b/net/ipv6/netfilter/nft_reject_ipv6.c | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> | ||
| 3 | * Copyright (c) 2013 Eric Leblond <eric@regit.org> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License version 2 as | ||
| 7 | * published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * Development of this code funded by Astaro AG (http://www.astaro.com/) | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/netlink.h> | ||
| 16 | #include <linux/netfilter.h> | ||
| 17 | #include <linux/netfilter/nf_tables.h> | ||
| 18 | #include <net/netfilter/nf_tables.h> | ||
| 19 | #include <net/netfilter/nft_reject.h> | ||
| 20 | #include <net/netfilter/ipv6/nf_reject.h> | ||
| 21 | |||
| 22 | void nft_reject_ipv6_eval(const struct nft_expr *expr, | ||
| 23 | struct nft_data data[NFT_REG_MAX + 1], | ||
| 24 | const struct nft_pktinfo *pkt) | ||
| 25 | { | ||
| 26 | struct nft_reject *priv = nft_expr_priv(expr); | ||
| 27 | struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); | ||
| 28 | |||
| 29 | switch (priv->type) { | ||
| 30 | case NFT_REJECT_ICMP_UNREACH: | ||
| 31 | nf_send_unreach6(net, pkt->skb, priv->icmp_code, | ||
| 32 | pkt->ops->hooknum); | ||
| 33 | break; | ||
| 34 | case NFT_REJECT_TCP_RST: | ||
| 35 | nf_send_reset6(net, pkt->skb, pkt->ops->hooknum); | ||
| 36 | break; | ||
| 37 | } | ||
| 38 | |||
| 39 | data[NFT_REG_VERDICT].verdict = NF_DROP; | ||
| 40 | } | ||
| 41 | EXPORT_SYMBOL_GPL(nft_reject_ipv6_eval); | ||
| 42 | |||
| 43 | static struct nft_expr_type nft_reject_ipv6_type; | ||
| 44 | static const struct nft_expr_ops nft_reject_ipv6_ops = { | ||
| 45 | .type = &nft_reject_ipv6_type, | ||
| 46 | .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), | ||
| 47 | .eval = nft_reject_ipv6_eval, | ||
| 48 | .init = nft_reject_init, | ||
| 49 | .dump = nft_reject_dump, | ||
| 50 | }; | ||
| 51 | |||
| 52 | static struct nft_expr_type nft_reject_ipv6_type __read_mostly = { | ||
| 53 | .family = NFPROTO_IPV6, | ||
| 54 | .name = "reject", | ||
| 55 | .ops = &nft_reject_ipv6_ops, | ||
| 56 | .policy = nft_reject_policy, | ||
| 57 | .maxattr = NFTA_REJECT_MAX, | ||
| 58 | .owner = THIS_MODULE, | ||
| 59 | }; | ||
| 60 | |||
| 61 | static int __init nft_reject_ipv6_module_init(void) | ||
| 62 | { | ||
| 63 | return nft_register_expr(&nft_reject_ipv6_type); | ||
| 64 | } | ||
| 65 | |||
| 66 | static void __exit nft_reject_ipv6_module_exit(void) | ||
| 67 | { | ||
| 68 | nft_unregister_expr(&nft_reject_ipv6_type); | ||
| 69 | } | ||
| 70 | |||
| 71 | module_init(nft_reject_ipv6_module_init); | ||
| 72 | module_exit(nft_reject_ipv6_module_exit); | ||
| 73 | |||
| 74 | MODULE_LICENSE("GPL"); | ||
| 75 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
| 76 | MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "reject"); | ||
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index fb9beb78f00b..587bbdcb22b4 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c | |||
| @@ -135,6 +135,7 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
| 135 | fl6.flowi6_proto = IPPROTO_ICMPV6; | 135 | fl6.flowi6_proto = IPPROTO_ICMPV6; |
| 136 | fl6.saddr = np->saddr; | 136 | fl6.saddr = np->saddr; |
| 137 | fl6.daddr = *daddr; | 137 | fl6.daddr = *daddr; |
| 138 | fl6.flowi6_mark = sk->sk_mark; | ||
| 138 | fl6.fl6_icmp_type = user_icmph.icmp6_type; | 139 | fl6.fl6_icmp_type = user_icmph.icmp6_type; |
| 139 | fl6.fl6_icmp_code = user_icmph.icmp6_code; | 140 | fl6.fl6_icmp_code = user_icmph.icmp6_code; |
| 140 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); | 141 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 3dfbcf1dcb1c..b4d74c86586c 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
| @@ -475,6 +475,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev) | |||
| 475 | ipip6_tunnel_unlink(sitn, tunnel); | 475 | ipip6_tunnel_unlink(sitn, tunnel); |
| 476 | ipip6_tunnel_del_prl(tunnel, NULL); | 476 | ipip6_tunnel_del_prl(tunnel, NULL); |
| 477 | } | 477 | } |
| 478 | ip_tunnel_dst_reset_all(tunnel); | ||
| 478 | dev_put(dev); | 479 | dev_put(dev); |
| 479 | } | 480 | } |
| 480 | 481 | ||
| @@ -1082,6 +1083,7 @@ static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p) | |||
| 1082 | t->parms.link = p->link; | 1083 | t->parms.link = p->link; |
| 1083 | ipip6_tunnel_bind_dev(t->dev); | 1084 | ipip6_tunnel_bind_dev(t->dev); |
| 1084 | } | 1085 | } |
| 1086 | ip_tunnel_dst_reset_all(t); | ||
| 1085 | netdev_state_change(t->dev); | 1087 | netdev_state_change(t->dev); |
| 1086 | } | 1088 | } |
| 1087 | 1089 | ||
| @@ -1112,6 +1114,7 @@ static int ipip6_tunnel_update_6rd(struct ip_tunnel *t, | |||
| 1112 | t->ip6rd.relay_prefix = relay_prefix; | 1114 | t->ip6rd.relay_prefix = relay_prefix; |
| 1113 | t->ip6rd.prefixlen = ip6rd->prefixlen; | 1115 | t->ip6rd.prefixlen = ip6rd->prefixlen; |
| 1114 | t->ip6rd.relay_prefixlen = ip6rd->relay_prefixlen; | 1116 | t->ip6rd.relay_prefixlen = ip6rd->relay_prefixlen; |
| 1117 | ip_tunnel_dst_reset_all(t); | ||
| 1115 | netdev_state_change(t->dev); | 1118 | netdev_state_change(t->dev); |
| 1116 | return 0; | 1119 | return 0; |
| 1117 | } | 1120 | } |
| @@ -1271,6 +1274,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 1271 | err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); | 1274 | err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); |
| 1272 | break; | 1275 | break; |
| 1273 | } | 1276 | } |
| 1277 | ip_tunnel_dst_reset_all(t); | ||
| 1274 | netdev_state_change(dev); | 1278 | netdev_state_change(dev); |
| 1275 | break; | 1279 | break; |
| 1276 | 1280 | ||
| @@ -1326,6 +1330,9 @@ static const struct net_device_ops ipip6_netdev_ops = { | |||
| 1326 | 1330 | ||
| 1327 | static void ipip6_dev_free(struct net_device *dev) | 1331 | static void ipip6_dev_free(struct net_device *dev) |
| 1328 | { | 1332 | { |
| 1333 | struct ip_tunnel *tunnel = netdev_priv(dev); | ||
| 1334 | |||
| 1335 | free_percpu(tunnel->dst_cache); | ||
| 1329 | free_percpu(dev->tstats); | 1336 | free_percpu(dev->tstats); |
| 1330 | free_netdev(dev); | 1337 | free_netdev(dev); |
| 1331 | } | 1338 | } |
| @@ -1375,6 +1382,12 @@ static int ipip6_tunnel_init(struct net_device *dev) | |||
| 1375 | u64_stats_init(&ipip6_tunnel_stats->syncp); | 1382 | u64_stats_init(&ipip6_tunnel_stats->syncp); |
| 1376 | } | 1383 | } |
| 1377 | 1384 | ||
| 1385 | tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); | ||
| 1386 | if (!tunnel->dst_cache) { | ||
| 1387 | free_percpu(dev->tstats); | ||
| 1388 | return -ENOMEM; | ||
| 1389 | } | ||
| 1390 | |||
| 1378 | return 0; | 1391 | return 0; |
| 1379 | } | 1392 | } |
| 1380 | 1393 | ||
| @@ -1405,6 +1418,12 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) | |||
| 1405 | u64_stats_init(&ipip6_fb_stats->syncp); | 1418 | u64_stats_init(&ipip6_fb_stats->syncp); |
| 1406 | } | 1419 | } |
| 1407 | 1420 | ||
| 1421 | tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); | ||
| 1422 | if (!tunnel->dst_cache) { | ||
| 1423 | free_percpu(dev->tstats); | ||
| 1424 | return -ENOMEM; | ||
| 1425 | } | ||
| 1426 | |||
| 1408 | dev_hold(dev); | 1427 | dev_hold(dev); |
| 1409 | rcu_assign_pointer(sitn->tunnels_wc[0], tunnel); | 1428 | rcu_assign_pointer(sitn->tunnels_wc[0], tunnel); |
| 1410 | return 0; | 1429 | return 0; |
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index e7359f9eaa8d..b261ee8b83fc 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c | |||
| @@ -113,7 +113,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, | |||
| 113 | fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen); | 113 | fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen); |
| 114 | fptr->nexthdr = nexthdr; | 114 | fptr->nexthdr = nexthdr; |
| 115 | fptr->reserved = 0; | 115 | fptr->reserved = 0; |
| 116 | ipv6_select_ident(fptr, (struct rt6_info *)skb_dst(skb)); | 116 | fptr->identification = skb_shinfo(skb)->ip6_frag_id; |
| 117 | 117 | ||
| 118 | /* Fragment the skb. ipv6 header and the remaining fields of the | 118 | /* Fragment the skb. ipv6 header and the remaining fields of the |
| 119 | * fragment header are updated in ipv6_gso_segment() | 119 | * fragment header are updated in ipv6_gso_segment() |
