diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/Kconfig | 1 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 7 | ||||
-rw-r--r-- | net/ipv6/exthdrs_core.c | 2 | ||||
-rw-r--r-- | net/ipv6/exthdrs_offload.c | 4 | ||||
-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 | 34 | ||||
-rw-r--r-- | net/ipv6/ip6mr.c | 13 | ||||
-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/route.c | 2 | ||||
-rw-r--r-- | net/ipv6/sit.c | 19 | ||||
-rw-r--r-- | net/ipv6/udp_offload.c | 2 |
15 files changed, 156 insertions, 33 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..344e972426df 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -1103,8 +1103,11 @@ retry: | |||
1103 | * Lifetime is greater than REGEN_ADVANCE time units. In particular, | 1103 | * Lifetime is greater than REGEN_ADVANCE time units. In particular, |
1104 | * an implementation must not create a temporary address with a zero | 1104 | * an implementation must not create a temporary address with a zero |
1105 | * Preferred Lifetime. | 1105 | * Preferred Lifetime. |
1106 | * Use age calculation as in addrconf_verify to avoid unnecessary | ||
1107 | * temporary addresses being generated. | ||
1106 | */ | 1108 | */ |
1107 | if (tmp_prefered_lft <= regen_advance) { | 1109 | age = (now - tmp_tstamp + ADDRCONF_TIMER_FUZZ_MINUS) / HZ; |
1110 | if (tmp_prefered_lft <= regen_advance + age) { | ||
1108 | in6_ifa_put(ifp); | 1111 | in6_ifa_put(ifp); |
1109 | in6_dev_put(idev); | 1112 | in6_dev_put(idev); |
1110 | ret = -1; | 1113 | ret = -1; |
@@ -2783,6 +2786,8 @@ static void addrconf_gre_config(struct net_device *dev) | |||
2783 | ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); | 2786 | ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); |
2784 | if (!ipv6_generate_eui64(addr.s6_addr + 8, dev)) | 2787 | if (!ipv6_generate_eui64(addr.s6_addr + 8, dev)) |
2785 | addrconf_add_linklocal(idev, &addr); | 2788 | addrconf_add_linklocal(idev, &addr); |
2789 | else | ||
2790 | addrconf_prefix_route(&addr, 64, dev, 0, 0); | ||
2786 | } | 2791 | } |
2787 | #endif | 2792 | #endif |
2788 | 2793 | ||
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/exthdrs_offload.c b/net/ipv6/exthdrs_offload.c index cf77f3abfd06..447a7fbd1bb6 100644 --- a/net/ipv6/exthdrs_offload.c +++ b/net/ipv6/exthdrs_offload.c | |||
@@ -25,11 +25,11 @@ int __init ipv6_exthdrs_offload_init(void) | |||
25 | int ret; | 25 | int ret; |
26 | 26 | ||
27 | ret = inet6_add_offload(&rthdr_offload, IPPROTO_ROUTING); | 27 | ret = inet6_add_offload(&rthdr_offload, IPPROTO_ROUTING); |
28 | if (!ret) | 28 | if (ret) |
29 | goto out; | 29 | goto out; |
30 | 30 | ||
31 | ret = inet6_add_offload(&dstopt_offload, IPPROTO_DSTOPTS); | 31 | ret = inet6_add_offload(&dstopt_offload, IPPROTO_DSTOPTS); |
32 | if (!ret) | 32 | if (ret) |
33 | goto out_rt; | 33 | goto out_rt; |
34 | 34 | ||
35 | out: | 35 | out: |
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..64d6073731d3 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 | ||
@@ -1091,21 +1101,19 @@ static void ip6_append_data_mtu(unsigned int *mtu, | |||
1091 | unsigned int fragheaderlen, | 1101 | unsigned int fragheaderlen, |
1092 | struct sk_buff *skb, | 1102 | struct sk_buff *skb, |
1093 | struct rt6_info *rt, | 1103 | struct rt6_info *rt, |
1094 | bool pmtuprobe) | 1104 | unsigned int orig_mtu) |
1095 | { | 1105 | { |
1096 | if (!(rt->dst.flags & DST_XFRM_TUNNEL)) { | 1106 | if (!(rt->dst.flags & DST_XFRM_TUNNEL)) { |
1097 | if (skb == NULL) { | 1107 | if (skb == NULL) { |
1098 | /* first fragment, reserve header_len */ | 1108 | /* first fragment, reserve header_len */ |
1099 | *mtu = *mtu - rt->dst.header_len; | 1109 | *mtu = orig_mtu - rt->dst.header_len; |
1100 | 1110 | ||
1101 | } else { | 1111 | } else { |
1102 | /* | 1112 | /* |
1103 | * this fragment is not first, the headers | 1113 | * this fragment is not first, the headers |
1104 | * space is regarded as data space. | 1114 | * space is regarded as data space. |
1105 | */ | 1115 | */ |
1106 | *mtu = min(*mtu, pmtuprobe ? | 1116 | *mtu = orig_mtu; |
1107 | rt->dst.dev->mtu : | ||
1108 | dst_mtu(rt->dst.path)); | ||
1109 | } | 1117 | } |
1110 | *maxfraglen = ((*mtu - fragheaderlen) & ~7) | 1118 | *maxfraglen = ((*mtu - fragheaderlen) & ~7) |
1111 | + fragheaderlen - sizeof(struct frag_hdr); | 1119 | + fragheaderlen - sizeof(struct frag_hdr); |
@@ -1122,7 +1130,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1122 | struct ipv6_pinfo *np = inet6_sk(sk); | 1130 | struct ipv6_pinfo *np = inet6_sk(sk); |
1123 | struct inet_cork *cork; | 1131 | struct inet_cork *cork; |
1124 | struct sk_buff *skb, *skb_prev = NULL; | 1132 | struct sk_buff *skb, *skb_prev = NULL; |
1125 | unsigned int maxfraglen, fragheaderlen, mtu; | 1133 | unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu; |
1126 | int exthdrlen; | 1134 | int exthdrlen; |
1127 | int dst_exthdrlen; | 1135 | int dst_exthdrlen; |
1128 | int hh_len; | 1136 | int hh_len; |
@@ -1204,6 +1212,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1204 | dst_exthdrlen = 0; | 1212 | dst_exthdrlen = 0; |
1205 | mtu = cork->fragsize; | 1213 | mtu = cork->fragsize; |
1206 | } | 1214 | } |
1215 | orig_mtu = mtu; | ||
1207 | 1216 | ||
1208 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); | 1217 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); |
1209 | 1218 | ||
@@ -1301,8 +1310,7 @@ alloc_new_skb: | |||
1301 | if (skb == NULL || skb_prev == NULL) | 1310 | if (skb == NULL || skb_prev == NULL) |
1302 | ip6_append_data_mtu(&mtu, &maxfraglen, | 1311 | ip6_append_data_mtu(&mtu, &maxfraglen, |
1303 | fragheaderlen, skb, rt, | 1312 | fragheaderlen, skb, rt, |
1304 | np->pmtudisc >= | 1313 | orig_mtu); |
1305 | IPV6_PMTUDISC_PROBE); | ||
1306 | 1314 | ||
1307 | skb_prev = skb; | 1315 | skb_prev = skb; |
1308 | 1316 | ||
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 0eb4038a4d63..8737400af0a0 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -2349,13 +2349,14 @@ int ip6mr_get_route(struct net *net, | |||
2349 | } | 2349 | } |
2350 | 2350 | ||
2351 | static int ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb, | 2351 | static int ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb, |
2352 | u32 portid, u32 seq, struct mfc6_cache *c, int cmd) | 2352 | u32 portid, u32 seq, struct mfc6_cache *c, int cmd, |
2353 | int flags) | ||
2353 | { | 2354 | { |
2354 | struct nlmsghdr *nlh; | 2355 | struct nlmsghdr *nlh; |
2355 | struct rtmsg *rtm; | 2356 | struct rtmsg *rtm; |
2356 | int err; | 2357 | int err; |
2357 | 2358 | ||
2358 | nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), NLM_F_MULTI); | 2359 | nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), flags); |
2359 | if (nlh == NULL) | 2360 | if (nlh == NULL) |
2360 | return -EMSGSIZE; | 2361 | return -EMSGSIZE; |
2361 | 2362 | ||
@@ -2423,7 +2424,7 @@ static void mr6_netlink_event(struct mr6_table *mrt, struct mfc6_cache *mfc, | |||
2423 | if (skb == NULL) | 2424 | if (skb == NULL) |
2424 | goto errout; | 2425 | goto errout; |
2425 | 2426 | ||
2426 | err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd); | 2427 | err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd, 0); |
2427 | if (err < 0) | 2428 | if (err < 0) |
2428 | goto errout; | 2429 | goto errout; |
2429 | 2430 | ||
@@ -2462,7 +2463,8 @@ static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) | |||
2462 | if (ip6mr_fill_mroute(mrt, skb, | 2463 | if (ip6mr_fill_mroute(mrt, skb, |
2463 | NETLINK_CB(cb->skb).portid, | 2464 | NETLINK_CB(cb->skb).portid, |
2464 | cb->nlh->nlmsg_seq, | 2465 | cb->nlh->nlmsg_seq, |
2465 | mfc, RTM_NEWROUTE) < 0) | 2466 | mfc, RTM_NEWROUTE, |
2467 | NLM_F_MULTI) < 0) | ||
2466 | goto done; | 2468 | goto done; |
2467 | next_entry: | 2469 | next_entry: |
2468 | e++; | 2470 | e++; |
@@ -2476,7 +2478,8 @@ next_entry: | |||
2476 | if (ip6mr_fill_mroute(mrt, skb, | 2478 | if (ip6mr_fill_mroute(mrt, skb, |
2477 | NETLINK_CB(cb->skb).portid, | 2479 | NETLINK_CB(cb->skb).portid, |
2478 | cb->nlh->nlmsg_seq, | 2480 | cb->nlh->nlmsg_seq, |
2479 | mfc, RTM_NEWROUTE) < 0) { | 2481 | mfc, RTM_NEWROUTE, |
2482 | NLM_F_MULTI) < 0) { | ||
2480 | spin_unlock_bh(&mfc_unres_lock); | 2483 | spin_unlock_bh(&mfc_unres_lock); |
2481 | goto done; | 2484 | goto done; |
2482 | } | 2485 | } |
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/route.c b/net/ipv6/route.c index 11dac21e6586..fba54a407bb2 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -1513,7 +1513,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1513 | if (!table) | 1513 | if (!table) |
1514 | goto out; | 1514 | goto out; |
1515 | 1515 | ||
1516 | rt = ip6_dst_alloc(net, NULL, DST_NOCOUNT, table); | 1516 | rt = ip6_dst_alloc(net, NULL, (cfg->fc_flags & RTF_ADDRCONF) ? 0 : DST_NOCOUNT, table); |
1517 | 1517 | ||
1518 | if (!rt) { | 1518 | if (!rt) { |
1519 | err = -ENOMEM; | 1519 | err = -ENOMEM; |
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() |