diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 4 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 1 | ||||
-rw-r--r-- | net/ipv6/anycast.c | 29 | ||||
-rw-r--r-- | net/ipv6/datagram.c | 2 | ||||
-rw-r--r-- | net/ipv6/icmp.c | 4 | ||||
-rw-r--r-- | net/ipv6/ip6_fib.c | 19 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 21 | ||||
-rw-r--r-- | net/ipv6/ip6mr.c | 4 | ||||
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 38 | ||||
-rw-r--r-- | net/ipv6/mcast.c | 1 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 35 | ||||
-rw-r--r-- | net/ipv6/netfilter/Kconfig | 9 | ||||
-rw-r--r-- | net/ipv6/netfilter/Makefile | 1 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_LOG.c | 527 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 60 | ||||
-rw-r--r-- | net/ipv6/raw.c | 2 | ||||
-rw-r--r-- | net/ipv6/reassembly.c | 7 | ||||
-rw-r--r-- | net/ipv6/route.c | 17 | ||||
-rw-r--r-- | net/ipv6/sit.c | 20 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 231 | ||||
-rw-r--r-- | net/ipv6/udp.c | 7 | ||||
-rw-r--r-- | net/ipv6/xfrm6_mode_beet.c | 6 | ||||
-rw-r--r-- | net/ipv6/xfrm6_mode_tunnel.c | 6 | ||||
-rw-r--r-- | net/ipv6/xfrm6_output.c | 2 |
24 files changed, 257 insertions, 796 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index c02280a4d126..6a3bb6077e19 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -434,6 +434,10 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
434 | /* Join all-node multicast group */ | 434 | /* Join all-node multicast group */ |
435 | ipv6_dev_mc_inc(dev, &in6addr_linklocal_allnodes); | 435 | ipv6_dev_mc_inc(dev, &in6addr_linklocal_allnodes); |
436 | 436 | ||
437 | /* Join all-router multicast group if forwarding is set */ | ||
438 | if (ndev->cnf.forwarding && (dev->flags & IFF_MULTICAST)) | ||
439 | ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters); | ||
440 | |||
437 | return ndev; | 441 | return ndev; |
438 | } | 442 | } |
439 | 443 | ||
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 273f48d1df2e..5605f9dca87e 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -214,6 +214,7 @@ lookup_protocol: | |||
214 | inet->mc_ttl = 1; | 214 | inet->mc_ttl = 1; |
215 | inet->mc_index = 0; | 215 | inet->mc_index = 0; |
216 | inet->mc_list = NULL; | 216 | inet->mc_list = NULL; |
217 | inet->rcv_tos = 0; | ||
217 | 218 | ||
218 | if (ipv4_config.no_pmtu_disc) | 219 | if (ipv4_config.no_pmtu_disc) |
219 | inet->pmtudisc = IP_PMTUDISC_DONT; | 220 | inet->pmtudisc = IP_PMTUDISC_DONT; |
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 59402b4637f9..db00d27ffb16 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c | |||
@@ -211,35 +211,6 @@ void ipv6_sock_ac_close(struct sock *sk) | |||
211 | rcu_read_unlock(); | 211 | rcu_read_unlock(); |
212 | } | 212 | } |
213 | 213 | ||
214 | #if 0 | ||
215 | /* The function is not used, which is funny. Apparently, author | ||
216 | * supposed to use it to filter out datagrams inside udp/raw but forgot. | ||
217 | * | ||
218 | * It is OK, anycasts are not special comparing to delivery to unicasts. | ||
219 | */ | ||
220 | |||
221 | int inet6_ac_check(struct sock *sk, struct in6_addr *addr, int ifindex) | ||
222 | { | ||
223 | struct ipv6_ac_socklist *pac; | ||
224 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
225 | int found; | ||
226 | |||
227 | found = 0; | ||
228 | read_lock(&ipv6_sk_ac_lock); | ||
229 | for (pac=np->ipv6_ac_list; pac; pac=pac->acl_next) { | ||
230 | if (ifindex && pac->acl_ifindex != ifindex) | ||
231 | continue; | ||
232 | found = ipv6_addr_equal(&pac->acl_addr, addr); | ||
233 | if (found) | ||
234 | break; | ||
235 | } | ||
236 | read_unlock(&ipv6_sk_ac_lock); | ||
237 | |||
238 | return found; | ||
239 | } | ||
240 | |||
241 | #endif | ||
242 | |||
243 | static void aca_put(struct ifacaddr6 *ac) | 214 | static void aca_put(struct ifacaddr6 *ac) |
244 | { | 215 | { |
245 | if (atomic_dec_and_test(&ac->aca_refcnt)) { | 216 | if (atomic_dec_and_test(&ac->aca_refcnt)) { |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 251e7cd75e89..76832c8dc89d 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -485,7 +485,7 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | |||
485 | } | 485 | } |
486 | 486 | ||
487 | if (np->rxopt.bits.rxtclass) { | 487 | if (np->rxopt.bits.rxtclass) { |
488 | int tclass = (ntohl(*(__be32 *)ipv6_hdr(skb)) >> 20) & 0xff; | 488 | int tclass = ipv6_tclass(ipv6_hdr(skb)); |
489 | put_cmsg(msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass), &tclass); | 489 | put_cmsg(msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass), &tclass); |
490 | } | 490 | } |
491 | 491 | ||
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 01d46bff63c3..af88934e4d79 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -468,6 +468,8 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) | |||
468 | 468 | ||
469 | if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) | 469 | if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) |
470 | fl6.flowi6_oif = np->mcast_oif; | 470 | fl6.flowi6_oif = np->mcast_oif; |
471 | else if (!fl6.flowi6_oif) | ||
472 | fl6.flowi6_oif = np->ucast_oif; | ||
471 | 473 | ||
472 | dst = icmpv6_route_lookup(net, skb, sk, &fl6); | 474 | dst = icmpv6_route_lookup(net, skb, sk, &fl6); |
473 | if (IS_ERR(dst)) | 475 | if (IS_ERR(dst)) |
@@ -553,6 +555,8 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
553 | 555 | ||
554 | if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) | 556 | if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) |
555 | fl6.flowi6_oif = np->mcast_oif; | 557 | fl6.flowi6_oif = np->mcast_oif; |
558 | else if (!fl6.flowi6_oif) | ||
559 | fl6.flowi6_oif = np->ucast_oif; | ||
556 | 560 | ||
557 | err = ip6_dst_lookup(sk, &dst, &fl6); | 561 | err = ip6_dst_lookup(sk, &dst, &fl6); |
558 | if (err) | 562 | if (err) |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index b82bcde53f7a..5b27fbcae346 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -1552,11 +1552,20 @@ static int fib6_age(struct rt6_info *rt, void *arg) | |||
1552 | time_after_eq(now, rt->dst.lastuse + gc_args.timeout)) { | 1552 | time_after_eq(now, rt->dst.lastuse + gc_args.timeout)) { |
1553 | RT6_TRACE("aging clone %p\n", rt); | 1553 | RT6_TRACE("aging clone %p\n", rt); |
1554 | return -1; | 1554 | return -1; |
1555 | } else if ((rt->rt6i_flags & RTF_GATEWAY) && | 1555 | } else if (rt->rt6i_flags & RTF_GATEWAY) { |
1556 | (!(dst_get_neighbour_noref_raw(&rt->dst)->flags & NTF_ROUTER))) { | 1556 | struct neighbour *neigh; |
1557 | RT6_TRACE("purging route %p via non-router but gateway\n", | 1557 | __u8 neigh_flags = 0; |
1558 | rt); | 1558 | |
1559 | return -1; | 1559 | neigh = dst_neigh_lookup(&rt->dst, &rt->rt6i_gateway); |
1560 | if (neigh) { | ||
1561 | neigh_flags = neigh->flags; | ||
1562 | neigh_release(neigh); | ||
1563 | } | ||
1564 | if (neigh_flags & NTF_ROUTER) { | ||
1565 | RT6_TRACE("purging route %p via non-router but gateway\n", | ||
1566 | rt); | ||
1567 | return -1; | ||
1568 | } | ||
1560 | } | 1569 | } |
1561 | gc_args.more++; | 1570 | gc_args.more++; |
1562 | } | 1571 | } |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index d97e07183ce9..b7ca46161cb9 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -388,7 +388,6 @@ int ip6_forward(struct sk_buff *skb) | |||
388 | struct ipv6hdr *hdr = ipv6_hdr(skb); | 388 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
389 | struct inet6_skb_parm *opt = IP6CB(skb); | 389 | struct inet6_skb_parm *opt = IP6CB(skb); |
390 | struct net *net = dev_net(dst->dev); | 390 | struct net *net = dev_net(dst->dev); |
391 | struct neighbour *n; | ||
392 | u32 mtu; | 391 | u32 mtu; |
393 | 392 | ||
394 | if (net->ipv6.devconf_all->forwarding == 0) | 393 | if (net->ipv6.devconf_all->forwarding == 0) |
@@ -463,8 +462,7 @@ int ip6_forward(struct sk_buff *skb) | |||
463 | send redirects to source routed frames. | 462 | send redirects to source routed frames. |
464 | We don't send redirects to frames decapsulated from IPsec. | 463 | We don't send redirects to frames decapsulated from IPsec. |
465 | */ | 464 | */ |
466 | n = dst_get_neighbour_noref(dst); | 465 | if (skb->dev == dst->dev && opt->srcrt == 0 && !skb_sec_path(skb)) { |
467 | if (skb->dev == dst->dev && n && opt->srcrt == 0 && !skb_sec_path(skb)) { | ||
468 | struct in6_addr *target = NULL; | 466 | struct in6_addr *target = NULL; |
469 | struct rt6_info *rt; | 467 | struct rt6_info *rt; |
470 | 468 | ||
@@ -474,8 +472,8 @@ int ip6_forward(struct sk_buff *skb) | |||
474 | */ | 472 | */ |
475 | 473 | ||
476 | rt = (struct rt6_info *) dst; | 474 | rt = (struct rt6_info *) dst; |
477 | if ((rt->rt6i_flags & RTF_GATEWAY)) | 475 | if (rt->rt6i_flags & RTF_GATEWAY) |
478 | target = (struct in6_addr*)&n->primary_key; | 476 | target = &rt->rt6i_gateway; |
479 | else | 477 | else |
480 | target = &hdr->daddr; | 478 | target = &hdr->daddr; |
481 | 479 | ||
@@ -486,7 +484,7 @@ int ip6_forward(struct sk_buff *skb) | |||
486 | and by source (inside ndisc_send_redirect) | 484 | and by source (inside ndisc_send_redirect) |
487 | */ | 485 | */ |
488 | if (inet_peer_xrlim_allow(rt->rt6i_peer, 1*HZ)) | 486 | if (inet_peer_xrlim_allow(rt->rt6i_peer, 1*HZ)) |
489 | ndisc_send_redirect(skb, n, target); | 487 | ndisc_send_redirect(skb, target); |
490 | } else { | 488 | } else { |
491 | int addrtype = ipv6_addr_type(&hdr->saddr); | 489 | int addrtype = ipv6_addr_type(&hdr->saddr); |
492 | 490 | ||
@@ -1416,8 +1414,9 @@ alloc_new_skb: | |||
1416 | */ | 1414 | */ |
1417 | skb->ip_summed = csummode; | 1415 | skb->ip_summed = csummode; |
1418 | skb->csum = 0; | 1416 | skb->csum = 0; |
1419 | /* reserve for fragmentation */ | 1417 | /* reserve for fragmentation and ipsec header */ |
1420 | skb_reserve(skb, hh_len+sizeof(struct frag_hdr)); | 1418 | skb_reserve(skb, hh_len + sizeof(struct frag_hdr) + |
1419 | dst_exthdrlen); | ||
1421 | 1420 | ||
1422 | if (sk->sk_type == SOCK_DGRAM) | 1421 | if (sk->sk_type == SOCK_DGRAM) |
1423 | skb_shinfo(skb)->tx_flags = tx_flags; | 1422 | skb_shinfo(skb)->tx_flags = tx_flags; |
@@ -1425,9 +1424,9 @@ alloc_new_skb: | |||
1425 | /* | 1424 | /* |
1426 | * Find where to start putting bytes | 1425 | * Find where to start putting bytes |
1427 | */ | 1426 | */ |
1428 | data = skb_put(skb, fraglen + dst_exthdrlen); | 1427 | data = skb_put(skb, fraglen); |
1429 | skb_set_network_header(skb, exthdrlen + dst_exthdrlen); | 1428 | skb_set_network_header(skb, exthdrlen); |
1430 | data += fragheaderlen + dst_exthdrlen; | 1429 | data += fragheaderlen; |
1431 | skb->transport_header = (skb->network_header + | 1430 | skb->transport_header = (skb->network_header + |
1432 | fragheaderlen); | 1431 | fragheaderlen); |
1433 | if (fraggap) { | 1432 | if (fraggap) { |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index c7e95c8c579f..5aa3981a3922 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -1926,8 +1926,10 @@ static int ip6mr_forward2(struct net *net, struct mr6_table *mrt, | |||
1926 | }; | 1926 | }; |
1927 | 1927 | ||
1928 | dst = ip6_route_output(net, NULL, &fl6); | 1928 | dst = ip6_route_output(net, NULL, &fl6); |
1929 | if (!dst) | 1929 | if (dst->error) { |
1930 | dst_release(dst); | ||
1930 | goto out_free; | 1931 | goto out_free; |
1932 | } | ||
1931 | 1933 | ||
1932 | skb_dst_drop(skb); | 1934 | skb_dst_drop(skb); |
1933 | skb_dst_set(skb, dst); | 1935 | skb_dst_set(skb, dst); |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 18a2719003c3..63dd1f89ed7d 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -516,6 +516,36 @@ done: | |||
516 | retv = 0; | 516 | retv = 0; |
517 | break; | 517 | break; |
518 | 518 | ||
519 | case IPV6_UNICAST_IF: | ||
520 | { | ||
521 | struct net_device *dev = NULL; | ||
522 | int ifindex; | ||
523 | |||
524 | if (optlen != sizeof(int)) | ||
525 | goto e_inval; | ||
526 | |||
527 | ifindex = (__force int)ntohl((__force __be32)val); | ||
528 | if (ifindex == 0) { | ||
529 | np->ucast_oif = 0; | ||
530 | retv = 0; | ||
531 | break; | ||
532 | } | ||
533 | |||
534 | dev = dev_get_by_index(net, ifindex); | ||
535 | retv = -EADDRNOTAVAIL; | ||
536 | if (!dev) | ||
537 | break; | ||
538 | dev_put(dev); | ||
539 | |||
540 | retv = -EINVAL; | ||
541 | if (sk->sk_bound_dev_if) | ||
542 | break; | ||
543 | |||
544 | np->ucast_oif = ifindex; | ||
545 | retv = 0; | ||
546 | break; | ||
547 | } | ||
548 | |||
519 | case IPV6_MULTICAST_IF: | 549 | case IPV6_MULTICAST_IF: |
520 | if (sk->sk_type == SOCK_STREAM) | 550 | if (sk->sk_type == SOCK_STREAM) |
521 | break; | 551 | break; |
@@ -987,6 +1017,10 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
987 | int hlim = np->mcast_hops; | 1017 | int hlim = np->mcast_hops; |
988 | put_cmsg(&msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim); | 1018 | put_cmsg(&msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim); |
989 | } | 1019 | } |
1020 | if (np->rxopt.bits.rxtclass) { | ||
1021 | int tclass = np->rcv_tclass; | ||
1022 | put_cmsg(&msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass), &tclass); | ||
1023 | } | ||
990 | if (np->rxopt.bits.rxoinfo) { | 1024 | if (np->rxopt.bits.rxoinfo) { |
991 | struct in6_pktinfo src_info; | 1025 | struct in6_pktinfo src_info; |
992 | src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif : | 1026 | src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif : |
@@ -1160,6 +1194,10 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1160 | val = np->mcast_oif; | 1194 | val = np->mcast_oif; |
1161 | break; | 1195 | break; |
1162 | 1196 | ||
1197 | case IPV6_UNICAST_IF: | ||
1198 | val = (__force int)htonl((__u32) np->ucast_oif); | ||
1199 | break; | ||
1200 | |||
1163 | case IPV6_MTU_DISCOVER: | 1201 | case IPV6_MTU_DISCOVER: |
1164 | val = np->pmtudisc; | 1202 | val = np->pmtudisc; |
1165 | break; | 1203 | break; |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index b853f06cc148..16c33e308121 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -257,7 +257,6 @@ static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net, | |||
257 | 257 | ||
258 | if (rt) { | 258 | if (rt) { |
259 | dev = rt->dst.dev; | 259 | dev = rt->dst.dev; |
260 | dev_hold(dev); | ||
261 | dst_release(&rt->dst); | 260 | dst_release(&rt->dst); |
262 | } | 261 | } |
263 | } else | 262 | } else |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index d8f02ef88e59..3dcdb81ec3e8 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -1223,11 +1223,17 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1223 | 1223 | ||
1224 | rt = rt6_get_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev); | 1224 | rt = rt6_get_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev); |
1225 | 1225 | ||
1226 | if (rt) | 1226 | if (rt) { |
1227 | neigh = dst_get_neighbour_noref(&rt->dst); | 1227 | neigh = dst_neigh_lookup(&rt->dst, &ipv6_hdr(skb)->saddr); |
1228 | 1228 | if (!neigh) { | |
1229 | ND_PRINTK0(KERN_ERR | ||
1230 | "ICMPv6 RA: %s() got default router without neighbour.\n", | ||
1231 | __func__); | ||
1232 | dst_release(&rt->dst); | ||
1233 | return; | ||
1234 | } | ||
1235 | } | ||
1229 | if (rt && lifetime == 0) { | 1236 | if (rt && lifetime == 0) { |
1230 | neigh_clone(neigh); | ||
1231 | ip6_del_rt(rt); | 1237 | ip6_del_rt(rt); |
1232 | rt = NULL; | 1238 | rt = NULL; |
1233 | } | 1239 | } |
@@ -1244,7 +1250,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1244 | return; | 1250 | return; |
1245 | } | 1251 | } |
1246 | 1252 | ||
1247 | neigh = dst_get_neighbour_noref(&rt->dst); | 1253 | neigh = dst_neigh_lookup(&rt->dst, &ipv6_hdr(skb)->saddr); |
1248 | if (neigh == NULL) { | 1254 | if (neigh == NULL) { |
1249 | ND_PRINTK0(KERN_ERR | 1255 | ND_PRINTK0(KERN_ERR |
1250 | "ICMPv6 RA: %s() got default router without neighbour.\n", | 1256 | "ICMPv6 RA: %s() got default router without neighbour.\n", |
@@ -1411,7 +1417,7 @@ skip_routeinfo: | |||
1411 | out: | 1417 | out: |
1412 | if (rt) | 1418 | if (rt) |
1413 | dst_release(&rt->dst); | 1419 | dst_release(&rt->dst); |
1414 | else if (neigh) | 1420 | if (neigh) |
1415 | neigh_release(neigh); | 1421 | neigh_release(neigh); |
1416 | } | 1422 | } |
1417 | 1423 | ||
@@ -1506,8 +1512,7 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) | |||
1506 | } | 1512 | } |
1507 | } | 1513 | } |
1508 | 1514 | ||
1509 | void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | 1515 | void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) |
1510 | const struct in6_addr *target) | ||
1511 | { | 1516 | { |
1512 | struct net_device *dev = skb->dev; | 1517 | struct net_device *dev = skb->dev; |
1513 | struct net *net = dev_net(dev); | 1518 | struct net *net = dev_net(dev); |
@@ -1545,9 +1550,10 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1545 | &saddr_buf, &ipv6_hdr(skb)->saddr, dev->ifindex); | 1550 | &saddr_buf, &ipv6_hdr(skb)->saddr, dev->ifindex); |
1546 | 1551 | ||
1547 | dst = ip6_route_output(net, NULL, &fl6); | 1552 | dst = ip6_route_output(net, NULL, &fl6); |
1548 | if (dst == NULL) | 1553 | if (dst->error) { |
1554 | dst_release(dst); | ||
1549 | return; | 1555 | return; |
1550 | 1556 | } | |
1551 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); | 1557 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); |
1552 | if (IS_ERR(dst)) | 1558 | if (IS_ERR(dst)) |
1553 | return; | 1559 | return; |
@@ -1565,6 +1571,13 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1565 | goto release; | 1571 | goto release; |
1566 | 1572 | ||
1567 | if (dev->addr_len) { | 1573 | if (dev->addr_len) { |
1574 | struct neighbour *neigh = dst_neigh_lookup(skb_dst(skb), target); | ||
1575 | if (!neigh) { | ||
1576 | ND_PRINTK2(KERN_WARNING | ||
1577 | "ICMPv6 Redirect: no neigh for target address\n"); | ||
1578 | goto release; | ||
1579 | } | ||
1580 | |||
1568 | read_lock_bh(&neigh->lock); | 1581 | read_lock_bh(&neigh->lock); |
1569 | if (neigh->nud_state & NUD_VALID) { | 1582 | if (neigh->nud_state & NUD_VALID) { |
1570 | memcpy(ha_buf, neigh->ha, dev->addr_len); | 1583 | memcpy(ha_buf, neigh->ha, dev->addr_len); |
@@ -1573,6 +1586,8 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1573 | len += ndisc_opt_addr_space(dev); | 1586 | len += ndisc_opt_addr_space(dev); |
1574 | } else | 1587 | } else |
1575 | read_unlock_bh(&neigh->lock); | 1588 | read_unlock_bh(&neigh->lock); |
1589 | |||
1590 | neigh_release(neigh); | ||
1576 | } | 1591 | } |
1577 | 1592 | ||
1578 | rd_len = min_t(unsigned int, | 1593 | rd_len = min_t(unsigned int, |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 9a68fb5b9e77..d33cddd16fbb 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -154,15 +154,6 @@ config IP6_NF_TARGET_HL | |||
154 | (e.g. when running oldconfig). It selects | 154 | (e.g. when running oldconfig). It selects |
155 | CONFIG_NETFILTER_XT_TARGET_HL. | 155 | CONFIG_NETFILTER_XT_TARGET_HL. |
156 | 156 | ||
157 | config IP6_NF_TARGET_LOG | ||
158 | tristate "LOG target support" | ||
159 | default m if NETFILTER_ADVANCED=n | ||
160 | help | ||
161 | This option adds a `LOG' target, which allows you to create rules in | ||
162 | any iptables table which records the packet header to the syslog. | ||
163 | |||
164 | To compile it as a module, choose M here. If unsure, say N. | ||
165 | |||
166 | config IP6_NF_FILTER | 157 | config IP6_NF_FILTER |
167 | tristate "Packet filtering" | 158 | tristate "Packet filtering" |
168 | default m if NETFILTER_ADVANCED=n | 159 | default m if NETFILTER_ADVANCED=n |
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index 2eaed96db02c..d4dfd0a21097 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
@@ -31,5 +31,4 @@ obj-$(CONFIG_IP6_NF_MATCH_RPFILTER) += ip6t_rpfilter.o | |||
31 | obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o | 31 | obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o |
32 | 32 | ||
33 | # targets | 33 | # targets |
34 | obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o | ||
35 | obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o | 34 | obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o |
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c deleted file mode 100644 index e6af8d72f26b..000000000000 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ /dev/null | |||
@@ -1,527 +0,0 @@ | |||
1 | /* | ||
2 | * This is a module which is used for logging packets. | ||
3 | */ | ||
4 | |||
5 | /* (C) 2001 Jan Rekorajski <baggins@pld.org.pl> | ||
6 | * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/skbuff.h> | ||
15 | #include <linux/if_arp.h> | ||
16 | #include <linux/ip.h> | ||
17 | #include <linux/spinlock.h> | ||
18 | #include <linux/icmpv6.h> | ||
19 | #include <net/udp.h> | ||
20 | #include <net/tcp.h> | ||
21 | #include <net/ipv6.h> | ||
22 | #include <linux/netfilter.h> | ||
23 | #include <linux/netfilter/x_tables.h> | ||
24 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
25 | #include <net/netfilter/nf_log.h> | ||
26 | #include <net/netfilter/xt_log.h> | ||
27 | |||
28 | MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>"); | ||
29 | MODULE_DESCRIPTION("Xtables: IPv6 packet logging to syslog"); | ||
30 | MODULE_LICENSE("GPL"); | ||
31 | |||
32 | struct in_device; | ||
33 | #include <net/route.h> | ||
34 | #include <linux/netfilter_ipv6/ip6t_LOG.h> | ||
35 | |||
36 | /* One level of recursion won't kill us */ | ||
37 | static void dump_packet(struct sbuff *m, | ||
38 | const struct nf_loginfo *info, | ||
39 | const struct sk_buff *skb, unsigned int ip6hoff, | ||
40 | int recurse) | ||
41 | { | ||
42 | u_int8_t currenthdr; | ||
43 | int fragment; | ||
44 | struct ipv6hdr _ip6h; | ||
45 | const struct ipv6hdr *ih; | ||
46 | unsigned int ptr; | ||
47 | unsigned int hdrlen = 0; | ||
48 | unsigned int logflags; | ||
49 | |||
50 | if (info->type == NF_LOG_TYPE_LOG) | ||
51 | logflags = info->u.log.logflags; | ||
52 | else | ||
53 | logflags = NF_LOG_MASK; | ||
54 | |||
55 | ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h); | ||
56 | if (ih == NULL) { | ||
57 | sb_add(m, "TRUNCATED"); | ||
58 | return; | ||
59 | } | ||
60 | |||
61 | /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */ | ||
62 | sb_add(m, "SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr); | ||
63 | |||
64 | /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ | ||
65 | sb_add(m, "LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", | ||
66 | ntohs(ih->payload_len) + sizeof(struct ipv6hdr), | ||
67 | (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20, | ||
68 | ih->hop_limit, | ||
69 | (ntohl(*(__be32 *)ih) & 0x000fffff)); | ||
70 | |||
71 | fragment = 0; | ||
72 | ptr = ip6hoff + sizeof(struct ipv6hdr); | ||
73 | currenthdr = ih->nexthdr; | ||
74 | while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) { | ||
75 | struct ipv6_opt_hdr _hdr; | ||
76 | const struct ipv6_opt_hdr *hp; | ||
77 | |||
78 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
79 | if (hp == NULL) { | ||
80 | sb_add(m, "TRUNCATED"); | ||
81 | return; | ||
82 | } | ||
83 | |||
84 | /* Max length: 48 "OPT (...) " */ | ||
85 | if (logflags & IP6T_LOG_IPOPT) | ||
86 | sb_add(m, "OPT ( "); | ||
87 | |||
88 | switch (currenthdr) { | ||
89 | case IPPROTO_FRAGMENT: { | ||
90 | struct frag_hdr _fhdr; | ||
91 | const struct frag_hdr *fh; | ||
92 | |||
93 | sb_add(m, "FRAG:"); | ||
94 | fh = skb_header_pointer(skb, ptr, sizeof(_fhdr), | ||
95 | &_fhdr); | ||
96 | if (fh == NULL) { | ||
97 | sb_add(m, "TRUNCATED "); | ||
98 | return; | ||
99 | } | ||
100 | |||
101 | /* Max length: 6 "65535 " */ | ||
102 | sb_add(m, "%u ", ntohs(fh->frag_off) & 0xFFF8); | ||
103 | |||
104 | /* Max length: 11 "INCOMPLETE " */ | ||
105 | if (fh->frag_off & htons(0x0001)) | ||
106 | sb_add(m, "INCOMPLETE "); | ||
107 | |||
108 | sb_add(m, "ID:%08x ", ntohl(fh->identification)); | ||
109 | |||
110 | if (ntohs(fh->frag_off) & 0xFFF8) | ||
111 | fragment = 1; | ||
112 | |||
113 | hdrlen = 8; | ||
114 | |||
115 | break; | ||
116 | } | ||
117 | case IPPROTO_DSTOPTS: | ||
118 | case IPPROTO_ROUTING: | ||
119 | case IPPROTO_HOPOPTS: | ||
120 | if (fragment) { | ||
121 | if (logflags & IP6T_LOG_IPOPT) | ||
122 | sb_add(m, ")"); | ||
123 | return; | ||
124 | } | ||
125 | hdrlen = ipv6_optlen(hp); | ||
126 | break; | ||
127 | /* Max Length */ | ||
128 | case IPPROTO_AH: | ||
129 | if (logflags & IP6T_LOG_IPOPT) { | ||
130 | struct ip_auth_hdr _ahdr; | ||
131 | const struct ip_auth_hdr *ah; | ||
132 | |||
133 | /* Max length: 3 "AH " */ | ||
134 | sb_add(m, "AH "); | ||
135 | |||
136 | if (fragment) { | ||
137 | sb_add(m, ")"); | ||
138 | return; | ||
139 | } | ||
140 | |||
141 | ah = skb_header_pointer(skb, ptr, sizeof(_ahdr), | ||
142 | &_ahdr); | ||
143 | if (ah == NULL) { | ||
144 | /* | ||
145 | * Max length: 26 "INCOMPLETE [65535 | ||
146 | * bytes] )" | ||
147 | */ | ||
148 | sb_add(m, "INCOMPLETE [%u bytes] )", | ||
149 | skb->len - ptr); | ||
150 | return; | ||
151 | } | ||
152 | |||
153 | /* Length: 15 "SPI=0xF1234567 */ | ||
154 | sb_add(m, "SPI=0x%x ", ntohl(ah->spi)); | ||
155 | |||
156 | } | ||
157 | |||
158 | hdrlen = (hp->hdrlen+2)<<2; | ||
159 | break; | ||
160 | case IPPROTO_ESP: | ||
161 | if (logflags & IP6T_LOG_IPOPT) { | ||
162 | struct ip_esp_hdr _esph; | ||
163 | const struct ip_esp_hdr *eh; | ||
164 | |||
165 | /* Max length: 4 "ESP " */ | ||
166 | sb_add(m, "ESP "); | ||
167 | |||
168 | if (fragment) { | ||
169 | sb_add(m, ")"); | ||
170 | return; | ||
171 | } | ||
172 | |||
173 | /* | ||
174 | * Max length: 26 "INCOMPLETE [65535 bytes] )" | ||
175 | */ | ||
176 | eh = skb_header_pointer(skb, ptr, sizeof(_esph), | ||
177 | &_esph); | ||
178 | if (eh == NULL) { | ||
179 | sb_add(m, "INCOMPLETE [%u bytes] )", | ||
180 | skb->len - ptr); | ||
181 | return; | ||
182 | } | ||
183 | |||
184 | /* Length: 16 "SPI=0xF1234567 )" */ | ||
185 | sb_add(m, "SPI=0x%x )", ntohl(eh->spi) ); | ||
186 | |||
187 | } | ||
188 | return; | ||
189 | default: | ||
190 | /* Max length: 20 "Unknown Ext Hdr 255" */ | ||
191 | sb_add(m, "Unknown Ext Hdr %u", currenthdr); | ||
192 | return; | ||
193 | } | ||
194 | if (logflags & IP6T_LOG_IPOPT) | ||
195 | sb_add(m, ") "); | ||
196 | |||
197 | currenthdr = hp->nexthdr; | ||
198 | ptr += hdrlen; | ||
199 | } | ||
200 | |||
201 | switch (currenthdr) { | ||
202 | case IPPROTO_TCP: { | ||
203 | struct tcphdr _tcph; | ||
204 | const struct tcphdr *th; | ||
205 | |||
206 | /* Max length: 10 "PROTO=TCP " */ | ||
207 | sb_add(m, "PROTO=TCP "); | ||
208 | |||
209 | if (fragment) | ||
210 | break; | ||
211 | |||
212 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
213 | th = skb_header_pointer(skb, ptr, sizeof(_tcph), &_tcph); | ||
214 | if (th == NULL) { | ||
215 | sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr); | ||
216 | return; | ||
217 | } | ||
218 | |||
219 | /* Max length: 20 "SPT=65535 DPT=65535 " */ | ||
220 | sb_add(m, "SPT=%u DPT=%u ", | ||
221 | ntohs(th->source), ntohs(th->dest)); | ||
222 | /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */ | ||
223 | if (logflags & IP6T_LOG_TCPSEQ) | ||
224 | sb_add(m, "SEQ=%u ACK=%u ", | ||
225 | ntohl(th->seq), ntohl(th->ack_seq)); | ||
226 | /* Max length: 13 "WINDOW=65535 " */ | ||
227 | sb_add(m, "WINDOW=%u ", ntohs(th->window)); | ||
228 | /* Max length: 9 "RES=0x3C " */ | ||
229 | sb_add(m, "RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22)); | ||
230 | /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */ | ||
231 | if (th->cwr) | ||
232 | sb_add(m, "CWR "); | ||
233 | if (th->ece) | ||
234 | sb_add(m, "ECE "); | ||
235 | if (th->urg) | ||
236 | sb_add(m, "URG "); | ||
237 | if (th->ack) | ||
238 | sb_add(m, "ACK "); | ||
239 | if (th->psh) | ||
240 | sb_add(m, "PSH "); | ||
241 | if (th->rst) | ||
242 | sb_add(m, "RST "); | ||
243 | if (th->syn) | ||
244 | sb_add(m, "SYN "); | ||
245 | if (th->fin) | ||
246 | sb_add(m, "FIN "); | ||
247 | /* Max length: 11 "URGP=65535 " */ | ||
248 | sb_add(m, "URGP=%u ", ntohs(th->urg_ptr)); | ||
249 | |||
250 | if ((logflags & IP6T_LOG_TCPOPT) && | ||
251 | th->doff * 4 > sizeof(struct tcphdr)) { | ||
252 | u_int8_t _opt[60 - sizeof(struct tcphdr)]; | ||
253 | const u_int8_t *op; | ||
254 | unsigned int i; | ||
255 | unsigned int optsize = th->doff * 4 | ||
256 | - sizeof(struct tcphdr); | ||
257 | |||
258 | op = skb_header_pointer(skb, | ||
259 | ptr + sizeof(struct tcphdr), | ||
260 | optsize, _opt); | ||
261 | if (op == NULL) { | ||
262 | sb_add(m, "OPT (TRUNCATED)"); | ||
263 | return; | ||
264 | } | ||
265 | |||
266 | /* Max length: 127 "OPT (" 15*4*2chars ") " */ | ||
267 | sb_add(m, "OPT ("); | ||
268 | for (i =0; i < optsize; i++) | ||
269 | sb_add(m, "%02X", op[i]); | ||
270 | sb_add(m, ") "); | ||
271 | } | ||
272 | break; | ||
273 | } | ||
274 | case IPPROTO_UDP: | ||
275 | case IPPROTO_UDPLITE: { | ||
276 | struct udphdr _udph; | ||
277 | const struct udphdr *uh; | ||
278 | |||
279 | if (currenthdr == IPPROTO_UDP) | ||
280 | /* Max length: 10 "PROTO=UDP " */ | ||
281 | sb_add(m, "PROTO=UDP " ); | ||
282 | else /* Max length: 14 "PROTO=UDPLITE " */ | ||
283 | sb_add(m, "PROTO=UDPLITE "); | ||
284 | |||
285 | if (fragment) | ||
286 | break; | ||
287 | |||
288 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
289 | uh = skb_header_pointer(skb, ptr, sizeof(_udph), &_udph); | ||
290 | if (uh == NULL) { | ||
291 | sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr); | ||
292 | return; | ||
293 | } | ||
294 | |||
295 | /* Max length: 20 "SPT=65535 DPT=65535 " */ | ||
296 | sb_add(m, "SPT=%u DPT=%u LEN=%u ", | ||
297 | ntohs(uh->source), ntohs(uh->dest), | ||
298 | ntohs(uh->len)); | ||
299 | break; | ||
300 | } | ||
301 | case IPPROTO_ICMPV6: { | ||
302 | struct icmp6hdr _icmp6h; | ||
303 | const struct icmp6hdr *ic; | ||
304 | |||
305 | /* Max length: 13 "PROTO=ICMPv6 " */ | ||
306 | sb_add(m, "PROTO=ICMPv6 "); | ||
307 | |||
308 | if (fragment) | ||
309 | break; | ||
310 | |||
311 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
312 | ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h); | ||
313 | if (ic == NULL) { | ||
314 | sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr); | ||
315 | return; | ||
316 | } | ||
317 | |||
318 | /* Max length: 18 "TYPE=255 CODE=255 " */ | ||
319 | sb_add(m, "TYPE=%u CODE=%u ", ic->icmp6_type, ic->icmp6_code); | ||
320 | |||
321 | switch (ic->icmp6_type) { | ||
322 | case ICMPV6_ECHO_REQUEST: | ||
323 | case ICMPV6_ECHO_REPLY: | ||
324 | /* Max length: 19 "ID=65535 SEQ=65535 " */ | ||
325 | sb_add(m, "ID=%u SEQ=%u ", | ||
326 | ntohs(ic->icmp6_identifier), | ||
327 | ntohs(ic->icmp6_sequence)); | ||
328 | break; | ||
329 | case ICMPV6_MGM_QUERY: | ||
330 | case ICMPV6_MGM_REPORT: | ||
331 | case ICMPV6_MGM_REDUCTION: | ||
332 | break; | ||
333 | |||
334 | case ICMPV6_PARAMPROB: | ||
335 | /* Max length: 17 "POINTER=ffffffff " */ | ||
336 | sb_add(m, "POINTER=%08x ", ntohl(ic->icmp6_pointer)); | ||
337 | /* Fall through */ | ||
338 | case ICMPV6_DEST_UNREACH: | ||
339 | case ICMPV6_PKT_TOOBIG: | ||
340 | case ICMPV6_TIME_EXCEED: | ||
341 | /* Max length: 3+maxlen */ | ||
342 | if (recurse) { | ||
343 | sb_add(m, "["); | ||
344 | dump_packet(m, info, skb, | ||
345 | ptr + sizeof(_icmp6h), 0); | ||
346 | sb_add(m, "] "); | ||
347 | } | ||
348 | |||
349 | /* Max length: 10 "MTU=65535 " */ | ||
350 | if (ic->icmp6_type == ICMPV6_PKT_TOOBIG) | ||
351 | sb_add(m, "MTU=%u ", ntohl(ic->icmp6_mtu)); | ||
352 | } | ||
353 | break; | ||
354 | } | ||
355 | /* Max length: 10 "PROTO=255 " */ | ||
356 | default: | ||
357 | sb_add(m, "PROTO=%u ", currenthdr); | ||
358 | } | ||
359 | |||
360 | /* Max length: 15 "UID=4294967295 " */ | ||
361 | if ((logflags & IP6T_LOG_UID) && recurse && skb->sk) { | ||
362 | read_lock_bh(&skb->sk->sk_callback_lock); | ||
363 | if (skb->sk->sk_socket && skb->sk->sk_socket->file) | ||
364 | sb_add(m, "UID=%u GID=%u ", | ||
365 | skb->sk->sk_socket->file->f_cred->fsuid, | ||
366 | skb->sk->sk_socket->file->f_cred->fsgid); | ||
367 | read_unlock_bh(&skb->sk->sk_callback_lock); | ||
368 | } | ||
369 | |||
370 | /* Max length: 16 "MARK=0xFFFFFFFF " */ | ||
371 | if (!recurse && skb->mark) | ||
372 | sb_add(m, "MARK=0x%x ", skb->mark); | ||
373 | } | ||
374 | |||
375 | static void dump_mac_header(struct sbuff *m, | ||
376 | const struct nf_loginfo *info, | ||
377 | const struct sk_buff *skb) | ||
378 | { | ||
379 | struct net_device *dev = skb->dev; | ||
380 | unsigned int logflags = 0; | ||
381 | |||
382 | if (info->type == NF_LOG_TYPE_LOG) | ||
383 | logflags = info->u.log.logflags; | ||
384 | |||
385 | if (!(logflags & IP6T_LOG_MACDECODE)) | ||
386 | goto fallback; | ||
387 | |||
388 | switch (dev->type) { | ||
389 | case ARPHRD_ETHER: | ||
390 | sb_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ", | ||
391 | eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, | ||
392 | ntohs(eth_hdr(skb)->h_proto)); | ||
393 | return; | ||
394 | default: | ||
395 | break; | ||
396 | } | ||
397 | |||
398 | fallback: | ||
399 | sb_add(m, "MAC="); | ||
400 | if (dev->hard_header_len && | ||
401 | skb->mac_header != skb->network_header) { | ||
402 | const unsigned char *p = skb_mac_header(skb); | ||
403 | unsigned int len = dev->hard_header_len; | ||
404 | unsigned int i; | ||
405 | |||
406 | if (dev->type == ARPHRD_SIT && | ||
407 | (p -= ETH_HLEN) < skb->head) | ||
408 | p = NULL; | ||
409 | |||
410 | if (p != NULL) { | ||
411 | sb_add(m, "%02x", *p++); | ||
412 | for (i = 1; i < len; i++) | ||
413 | sb_add(m, ":%02x", *p++); | ||
414 | } | ||
415 | sb_add(m, " "); | ||
416 | |||
417 | if (dev->type == ARPHRD_SIT) { | ||
418 | const struct iphdr *iph = | ||
419 | (struct iphdr *)skb_mac_header(skb); | ||
420 | sb_add(m, "TUNNEL=%pI4->%pI4 ", &iph->saddr, &iph->daddr); | ||
421 | } | ||
422 | } else | ||
423 | sb_add(m, " "); | ||
424 | } | ||
425 | |||
426 | static struct nf_loginfo default_loginfo = { | ||
427 | .type = NF_LOG_TYPE_LOG, | ||
428 | .u = { | ||
429 | .log = { | ||
430 | .level = 5, | ||
431 | .logflags = NF_LOG_MASK, | ||
432 | }, | ||
433 | }, | ||
434 | }; | ||
435 | |||
436 | static void | ||
437 | ip6t_log_packet(u_int8_t pf, | ||
438 | unsigned int hooknum, | ||
439 | const struct sk_buff *skb, | ||
440 | const struct net_device *in, | ||
441 | const struct net_device *out, | ||
442 | const struct nf_loginfo *loginfo, | ||
443 | const char *prefix) | ||
444 | { | ||
445 | struct sbuff *m = sb_open(); | ||
446 | |||
447 | if (!loginfo) | ||
448 | loginfo = &default_loginfo; | ||
449 | |||
450 | sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level, | ||
451 | prefix, | ||
452 | in ? in->name : "", | ||
453 | out ? out->name : ""); | ||
454 | |||
455 | if (in != NULL) | ||
456 | dump_mac_header(m, loginfo, skb); | ||
457 | |||
458 | dump_packet(m, loginfo, skb, skb_network_offset(skb), 1); | ||
459 | |||
460 | sb_close(m); | ||
461 | } | ||
462 | |||
463 | static unsigned int | ||
464 | log_tg6(struct sk_buff *skb, const struct xt_action_param *par) | ||
465 | { | ||
466 | const struct ip6t_log_info *loginfo = par->targinfo; | ||
467 | struct nf_loginfo li; | ||
468 | |||
469 | li.type = NF_LOG_TYPE_LOG; | ||
470 | li.u.log.level = loginfo->level; | ||
471 | li.u.log.logflags = loginfo->logflags; | ||
472 | |||
473 | ip6t_log_packet(NFPROTO_IPV6, par->hooknum, skb, par->in, par->out, | ||
474 | &li, loginfo->prefix); | ||
475 | return XT_CONTINUE; | ||
476 | } | ||
477 | |||
478 | |||
479 | static int log_tg6_check(const struct xt_tgchk_param *par) | ||
480 | { | ||
481 | const struct ip6t_log_info *loginfo = par->targinfo; | ||
482 | |||
483 | if (loginfo->level >= 8) { | ||
484 | pr_debug("level %u >= 8\n", loginfo->level); | ||
485 | return -EINVAL; | ||
486 | } | ||
487 | if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') { | ||
488 | pr_debug("prefix not null-terminated\n"); | ||
489 | return -EINVAL; | ||
490 | } | ||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | static struct xt_target log_tg6_reg __read_mostly = { | ||
495 | .name = "LOG", | ||
496 | .family = NFPROTO_IPV6, | ||
497 | .target = log_tg6, | ||
498 | .targetsize = sizeof(struct ip6t_log_info), | ||
499 | .checkentry = log_tg6_check, | ||
500 | .me = THIS_MODULE, | ||
501 | }; | ||
502 | |||
503 | static struct nf_logger ip6t_logger __read_mostly = { | ||
504 | .name = "ip6t_LOG", | ||
505 | .logfn = &ip6t_log_packet, | ||
506 | .me = THIS_MODULE, | ||
507 | }; | ||
508 | |||
509 | static int __init log_tg6_init(void) | ||
510 | { | ||
511 | int ret; | ||
512 | |||
513 | ret = xt_register_target(&log_tg6_reg); | ||
514 | if (ret < 0) | ||
515 | return ret; | ||
516 | nf_log_register(NFPROTO_IPV6, &ip6t_logger); | ||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | static void __exit log_tg6_exit(void) | ||
521 | { | ||
522 | nf_log_unregister(&ip6t_logger); | ||
523 | xt_unregister_target(&log_tg6_reg); | ||
524 | } | ||
525 | |||
526 | module_init(log_tg6_init); | ||
527 | module_exit(log_tg6_exit); | ||
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 7c05e7eacbc6..92cc9f2931ae 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
@@ -88,25 +88,31 @@ static int icmpv6_print_tuple(struct seq_file *s, | |||
88 | ntohs(tuple->src.u.icmp.id)); | 88 | ntohs(tuple->src.u.icmp.id)); |
89 | } | 89 | } |
90 | 90 | ||
91 | static unsigned int *icmpv6_get_timeouts(struct net *net) | ||
92 | { | ||
93 | return &nf_ct_icmpv6_timeout; | ||
94 | } | ||
95 | |||
91 | /* Returns verdict for packet, or -1 for invalid. */ | 96 | /* Returns verdict for packet, or -1 for invalid. */ |
92 | static int icmpv6_packet(struct nf_conn *ct, | 97 | static int icmpv6_packet(struct nf_conn *ct, |
93 | const struct sk_buff *skb, | 98 | const struct sk_buff *skb, |
94 | unsigned int dataoff, | 99 | unsigned int dataoff, |
95 | enum ip_conntrack_info ctinfo, | 100 | enum ip_conntrack_info ctinfo, |
96 | u_int8_t pf, | 101 | u_int8_t pf, |
97 | unsigned int hooknum) | 102 | unsigned int hooknum, |
103 | unsigned int *timeout) | ||
98 | { | 104 | { |
99 | /* Do not immediately delete the connection after the first | 105 | /* Do not immediately delete the connection after the first |
100 | successful reply to avoid excessive conntrackd traffic | 106 | successful reply to avoid excessive conntrackd traffic |
101 | and also to handle correctly ICMP echo reply duplicates. */ | 107 | and also to handle correctly ICMP echo reply duplicates. */ |
102 | nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmpv6_timeout); | 108 | nf_ct_refresh_acct(ct, ctinfo, skb, *timeout); |
103 | 109 | ||
104 | return NF_ACCEPT; | 110 | return NF_ACCEPT; |
105 | } | 111 | } |
106 | 112 | ||
107 | /* Called when a new connection for this protocol found. */ | 113 | /* Called when a new connection for this protocol found. */ |
108 | static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb, | 114 | static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb, |
109 | unsigned int dataoff) | 115 | unsigned int dataoff, unsigned int *timeouts) |
110 | { | 116 | { |
111 | static const u_int8_t valid_new[] = { | 117 | static const u_int8_t valid_new[] = { |
112 | [ICMPV6_ECHO_REQUEST - 128] = 1, | 118 | [ICMPV6_ECHO_REQUEST - 128] = 1, |
@@ -270,6 +276,44 @@ static int icmpv6_nlattr_tuple_size(void) | |||
270 | } | 276 | } |
271 | #endif | 277 | #endif |
272 | 278 | ||
279 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT) | ||
280 | |||
281 | #include <linux/netfilter/nfnetlink.h> | ||
282 | #include <linux/netfilter/nfnetlink_cttimeout.h> | ||
283 | |||
284 | static int icmpv6_timeout_nlattr_to_obj(struct nlattr *tb[], void *data) | ||
285 | { | ||
286 | unsigned int *timeout = data; | ||
287 | |||
288 | if (tb[CTA_TIMEOUT_ICMPV6_TIMEOUT]) { | ||
289 | *timeout = | ||
290 | ntohl(nla_get_be32(tb[CTA_TIMEOUT_ICMPV6_TIMEOUT])) * HZ; | ||
291 | } else { | ||
292 | /* Set default ICMPv6 timeout. */ | ||
293 | *timeout = nf_ct_icmpv6_timeout; | ||
294 | } | ||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static int | ||
299 | icmpv6_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data) | ||
300 | { | ||
301 | const unsigned int *timeout = data; | ||
302 | |||
303 | NLA_PUT_BE32(skb, CTA_TIMEOUT_ICMPV6_TIMEOUT, htonl(*timeout / HZ)); | ||
304 | |||
305 | return 0; | ||
306 | |||
307 | nla_put_failure: | ||
308 | return -ENOSPC; | ||
309 | } | ||
310 | |||
311 | static const struct nla_policy | ||
312 | icmpv6_timeout_nla_policy[CTA_TIMEOUT_ICMPV6_MAX+1] = { | ||
313 | [CTA_TIMEOUT_ICMPV6_TIMEOUT] = { .type = NLA_U32 }, | ||
314 | }; | ||
315 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ | ||
316 | |||
273 | #ifdef CONFIG_SYSCTL | 317 | #ifdef CONFIG_SYSCTL |
274 | static struct ctl_table_header *icmpv6_sysctl_header; | 318 | static struct ctl_table_header *icmpv6_sysctl_header; |
275 | static struct ctl_table icmpv6_sysctl_table[] = { | 319 | static struct ctl_table icmpv6_sysctl_table[] = { |
@@ -293,6 +337,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly = | |||
293 | .invert_tuple = icmpv6_invert_tuple, | 337 | .invert_tuple = icmpv6_invert_tuple, |
294 | .print_tuple = icmpv6_print_tuple, | 338 | .print_tuple = icmpv6_print_tuple, |
295 | .packet = icmpv6_packet, | 339 | .packet = icmpv6_packet, |
340 | .get_timeouts = icmpv6_get_timeouts, | ||
296 | .new = icmpv6_new, | 341 | .new = icmpv6_new, |
297 | .error = icmpv6_error, | 342 | .error = icmpv6_error, |
298 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 343 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
@@ -301,6 +346,15 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly = | |||
301 | .nlattr_to_tuple = icmpv6_nlattr_to_tuple, | 346 | .nlattr_to_tuple = icmpv6_nlattr_to_tuple, |
302 | .nla_policy = icmpv6_nla_policy, | 347 | .nla_policy = icmpv6_nla_policy, |
303 | #endif | 348 | #endif |
349 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT) | ||
350 | .ctnl_timeout = { | ||
351 | .nlattr_to_obj = icmpv6_timeout_nlattr_to_obj, | ||
352 | .obj_to_nlattr = icmpv6_timeout_obj_to_nlattr, | ||
353 | .nlattr_max = CTA_TIMEOUT_ICMP_MAX, | ||
354 | .obj_size = sizeof(unsigned int), | ||
355 | .nla_policy = icmpv6_timeout_nla_policy, | ||
356 | }, | ||
357 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ | ||
304 | #ifdef CONFIG_SYSCTL | 358 | #ifdef CONFIG_SYSCTL |
305 | .ctl_table_header = &icmpv6_sysctl_header, | 359 | .ctl_table_header = &icmpv6_sysctl_header, |
306 | .ctl_table = icmpv6_sysctl_table, | 360 | .ctl_table = icmpv6_sysctl_table, |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index d02f7e4dd611..5bddea778840 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -856,6 +856,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
856 | 856 | ||
857 | if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) | 857 | if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) |
858 | fl6.flowi6_oif = np->mcast_oif; | 858 | fl6.flowi6_oif = np->mcast_oif; |
859 | else if (!fl6.flowi6_oif) | ||
860 | fl6.flowi6_oif = np->ucast_oif; | ||
859 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); | 861 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
860 | 862 | ||
861 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true); | 863 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true); |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index b69fae76a6f1..9447bd69873a 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -336,12 +336,11 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
336 | } | 336 | } |
337 | 337 | ||
338 | found: | 338 | found: |
339 | /* RFC5722, Section 4: | 339 | /* RFC5722, Section 4, amended by Errata ID : 3089 |
340 | * When reassembling an IPv6 datagram, if | 340 | * When reassembling an IPv6 datagram, if |
341 | * one or more its constituent fragments is determined to be an | 341 | * one or more its constituent fragments is determined to be an |
342 | * overlapping fragment, the entire datagram (and any constituent | 342 | * overlapping fragment, the entire datagram (and any constituent |
343 | * fragments, including those not yet received) MUST be silently | 343 | * fragments) MUST be silently discarded. |
344 | * discarded. | ||
345 | */ | 344 | */ |
346 | 345 | ||
347 | /* Check for overlap with preceding fragment. */ | 346 | /* Check for overlap with preceding fragment. */ |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 8c2e3ab58f2a..24c456e8aa1d 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -121,9 +121,22 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) | |||
121 | return p; | 121 | return p; |
122 | } | 122 | } |
123 | 123 | ||
124 | static inline const void *choose_neigh_daddr(struct rt6_info *rt, const void *daddr) | ||
125 | { | ||
126 | struct in6_addr *p = &rt->rt6i_gateway; | ||
127 | |||
128 | if (!ipv6_addr_any(p)) | ||
129 | return (const void *) p; | ||
130 | return daddr; | ||
131 | } | ||
132 | |||
124 | static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const void *daddr) | 133 | static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const void *daddr) |
125 | { | 134 | { |
126 | struct neighbour *n = __ipv6_neigh_lookup(&nd_tbl, dst->dev, daddr); | 135 | struct rt6_info *rt = (struct rt6_info *) dst; |
136 | struct neighbour *n; | ||
137 | |||
138 | daddr = choose_neigh_daddr(rt, daddr); | ||
139 | n = __ipv6_neigh_lookup(&nd_tbl, dst->dev, daddr); | ||
127 | if (n) | 140 | if (n) |
128 | return n; | 141 | return n; |
129 | return neigh_create(&nd_tbl, daddr, dst->dev); | 142 | return neigh_create(&nd_tbl, daddr, dst->dev); |
@@ -1077,7 +1090,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
1077 | struct net *net = dev_net(dev); | 1090 | struct net *net = dev_net(dev); |
1078 | 1091 | ||
1079 | if (unlikely(!idev)) | 1092 | if (unlikely(!idev)) |
1080 | return NULL; | 1093 | return ERR_PTR(-ENODEV); |
1081 | 1094 | ||
1082 | rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev, 0); | 1095 | rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev, 0); |
1083 | if (unlikely(!rt)) { | 1096 | if (unlikely(!rt)) { |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 133768e52912..c4ffd1743528 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -680,9 +680,10 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
680 | /* ISATAP (RFC4214) - must come before 6to4 */ | 680 | /* ISATAP (RFC4214) - must come before 6to4 */ |
681 | if (dev->priv_flags & IFF_ISATAP) { | 681 | if (dev->priv_flags & IFF_ISATAP) { |
682 | struct neighbour *neigh = NULL; | 682 | struct neighbour *neigh = NULL; |
683 | bool do_tx_error = false; | ||
683 | 684 | ||
684 | if (skb_dst(skb)) | 685 | if (skb_dst(skb)) |
685 | neigh = dst_get_neighbour_noref(skb_dst(skb)); | 686 | neigh = dst_neigh_lookup(skb_dst(skb), &iph6->daddr); |
686 | 687 | ||
687 | if (neigh == NULL) { | 688 | if (neigh == NULL) { |
688 | if (net_ratelimit()) | 689 | if (net_ratelimit()) |
@@ -697,6 +698,10 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
697 | ipv6_addr_is_isatap(addr6)) | 698 | ipv6_addr_is_isatap(addr6)) |
698 | dst = addr6->s6_addr32[3]; | 699 | dst = addr6->s6_addr32[3]; |
699 | else | 700 | else |
701 | do_tx_error = true; | ||
702 | |||
703 | neigh_release(neigh); | ||
704 | if (do_tx_error) | ||
700 | goto tx_error; | 705 | goto tx_error; |
701 | } | 706 | } |
702 | 707 | ||
@@ -705,9 +710,10 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
705 | 710 | ||
706 | if (!dst) { | 711 | if (!dst) { |
707 | struct neighbour *neigh = NULL; | 712 | struct neighbour *neigh = NULL; |
713 | bool do_tx_error = false; | ||
708 | 714 | ||
709 | if (skb_dst(skb)) | 715 | if (skb_dst(skb)) |
710 | neigh = dst_get_neighbour_noref(skb_dst(skb)); | 716 | neigh = dst_neigh_lookup(skb_dst(skb), &iph6->daddr); |
711 | 717 | ||
712 | if (neigh == NULL) { | 718 | if (neigh == NULL) { |
713 | if (net_ratelimit()) | 719 | if (net_ratelimit()) |
@@ -723,10 +729,14 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
723 | addr_type = ipv6_addr_type(addr6); | 729 | addr_type = ipv6_addr_type(addr6); |
724 | } | 730 | } |
725 | 731 | ||
726 | if ((addr_type & IPV6_ADDR_COMPATv4) == 0) | 732 | if ((addr_type & IPV6_ADDR_COMPATv4) != 0) |
727 | goto tx_error_icmp; | 733 | dst = addr6->s6_addr32[3]; |
734 | else | ||
735 | do_tx_error = true; | ||
728 | 736 | ||
729 | dst = addr6->s6_addr32[3]; | 737 | neigh_release(neigh); |
738 | if (do_tx_error) | ||
739 | goto tx_error; | ||
730 | } | 740 | } |
731 | 741 | ||
732 | rt = ip_route_output_ports(dev_net(dev), &fl4, NULL, | 742 | rt = ip_route_output_ports(dev_net(dev), &fl4, NULL, |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 3edd05ae4388..12c6ece67f39 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -540,19 +540,7 @@ static void tcp_v6_reqsk_destructor(struct request_sock *req) | |||
540 | static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, | 540 | static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, |
541 | const struct in6_addr *addr) | 541 | const struct in6_addr *addr) |
542 | { | 542 | { |
543 | struct tcp_sock *tp = tcp_sk(sk); | 543 | return tcp_md5_do_lookup(sk, (union tcp_md5_addr *)addr, AF_INET6); |
544 | int i; | ||
545 | |||
546 | BUG_ON(tp == NULL); | ||
547 | |||
548 | if (!tp->md5sig_info || !tp->md5sig_info->entries6) | ||
549 | return NULL; | ||
550 | |||
551 | for (i = 0; i < tp->md5sig_info->entries6; i++) { | ||
552 | if (ipv6_addr_equal(&tp->md5sig_info->keys6[i].addr, addr)) | ||
553 | return &tp->md5sig_info->keys6[i].base; | ||
554 | } | ||
555 | return NULL; | ||
556 | } | 544 | } |
557 | 545 | ||
558 | static struct tcp_md5sig_key *tcp_v6_md5_lookup(struct sock *sk, | 546 | static struct tcp_md5sig_key *tcp_v6_md5_lookup(struct sock *sk, |
@@ -567,136 +555,11 @@ static struct tcp_md5sig_key *tcp_v6_reqsk_md5_lookup(struct sock *sk, | |||
567 | return tcp_v6_md5_do_lookup(sk, &inet6_rsk(req)->rmt_addr); | 555 | return tcp_v6_md5_do_lookup(sk, &inet6_rsk(req)->rmt_addr); |
568 | } | 556 | } |
569 | 557 | ||
570 | static int tcp_v6_md5_do_add(struct sock *sk, const struct in6_addr *peer, | ||
571 | char *newkey, u8 newkeylen) | ||
572 | { | ||
573 | /* Add key to the list */ | ||
574 | struct tcp_md5sig_key *key; | ||
575 | struct tcp_sock *tp = tcp_sk(sk); | ||
576 | struct tcp6_md5sig_key *keys; | ||
577 | |||
578 | key = tcp_v6_md5_do_lookup(sk, peer); | ||
579 | if (key) { | ||
580 | /* modify existing entry - just update that one */ | ||
581 | kfree(key->key); | ||
582 | key->key = newkey; | ||
583 | key->keylen = newkeylen; | ||
584 | } else { | ||
585 | /* reallocate new list if current one is full. */ | ||
586 | if (!tp->md5sig_info) { | ||
587 | tp->md5sig_info = kzalloc(sizeof(*tp->md5sig_info), GFP_ATOMIC); | ||
588 | if (!tp->md5sig_info) { | ||
589 | kfree(newkey); | ||
590 | return -ENOMEM; | ||
591 | } | ||
592 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); | ||
593 | } | ||
594 | if (tp->md5sig_info->entries6 == 0 && | ||
595 | tcp_alloc_md5sig_pool(sk) == NULL) { | ||
596 | kfree(newkey); | ||
597 | return -ENOMEM; | ||
598 | } | ||
599 | if (tp->md5sig_info->alloced6 == tp->md5sig_info->entries6) { | ||
600 | keys = kmalloc((sizeof (tp->md5sig_info->keys6[0]) * | ||
601 | (tp->md5sig_info->entries6 + 1)), GFP_ATOMIC); | ||
602 | |||
603 | if (!keys) { | ||
604 | kfree(newkey); | ||
605 | if (tp->md5sig_info->entries6 == 0) | ||
606 | tcp_free_md5sig_pool(); | ||
607 | return -ENOMEM; | ||
608 | } | ||
609 | |||
610 | if (tp->md5sig_info->entries6) | ||
611 | memmove(keys, tp->md5sig_info->keys6, | ||
612 | (sizeof (tp->md5sig_info->keys6[0]) * | ||
613 | tp->md5sig_info->entries6)); | ||
614 | |||
615 | kfree(tp->md5sig_info->keys6); | ||
616 | tp->md5sig_info->keys6 = keys; | ||
617 | tp->md5sig_info->alloced6++; | ||
618 | } | ||
619 | |||
620 | tp->md5sig_info->keys6[tp->md5sig_info->entries6].addr = *peer; | ||
621 | tp->md5sig_info->keys6[tp->md5sig_info->entries6].base.key = newkey; | ||
622 | tp->md5sig_info->keys6[tp->md5sig_info->entries6].base.keylen = newkeylen; | ||
623 | |||
624 | tp->md5sig_info->entries6++; | ||
625 | } | ||
626 | return 0; | ||
627 | } | ||
628 | |||
629 | static int tcp_v6_md5_add_func(struct sock *sk, struct sock *addr_sk, | ||
630 | u8 *newkey, __u8 newkeylen) | ||
631 | { | ||
632 | return tcp_v6_md5_do_add(sk, &inet6_sk(addr_sk)->daddr, | ||
633 | newkey, newkeylen); | ||
634 | } | ||
635 | |||
636 | static int tcp_v6_md5_do_del(struct sock *sk, const struct in6_addr *peer) | ||
637 | { | ||
638 | struct tcp_sock *tp = tcp_sk(sk); | ||
639 | int i; | ||
640 | |||
641 | for (i = 0; i < tp->md5sig_info->entries6; i++) { | ||
642 | if (ipv6_addr_equal(&tp->md5sig_info->keys6[i].addr, peer)) { | ||
643 | /* Free the key */ | ||
644 | kfree(tp->md5sig_info->keys6[i].base.key); | ||
645 | tp->md5sig_info->entries6--; | ||
646 | |||
647 | if (tp->md5sig_info->entries6 == 0) { | ||
648 | kfree(tp->md5sig_info->keys6); | ||
649 | tp->md5sig_info->keys6 = NULL; | ||
650 | tp->md5sig_info->alloced6 = 0; | ||
651 | tcp_free_md5sig_pool(); | ||
652 | } else { | ||
653 | /* shrink the database */ | ||
654 | if (tp->md5sig_info->entries6 != i) | ||
655 | memmove(&tp->md5sig_info->keys6[i], | ||
656 | &tp->md5sig_info->keys6[i+1], | ||
657 | (tp->md5sig_info->entries6 - i) | ||
658 | * sizeof (tp->md5sig_info->keys6[0])); | ||
659 | } | ||
660 | return 0; | ||
661 | } | ||
662 | } | ||
663 | return -ENOENT; | ||
664 | } | ||
665 | |||
666 | static void tcp_v6_clear_md5_list (struct sock *sk) | ||
667 | { | ||
668 | struct tcp_sock *tp = tcp_sk(sk); | ||
669 | int i; | ||
670 | |||
671 | if (tp->md5sig_info->entries6) { | ||
672 | for (i = 0; i < tp->md5sig_info->entries6; i++) | ||
673 | kfree(tp->md5sig_info->keys6[i].base.key); | ||
674 | tp->md5sig_info->entries6 = 0; | ||
675 | tcp_free_md5sig_pool(); | ||
676 | } | ||
677 | |||
678 | kfree(tp->md5sig_info->keys6); | ||
679 | tp->md5sig_info->keys6 = NULL; | ||
680 | tp->md5sig_info->alloced6 = 0; | ||
681 | |||
682 | if (tp->md5sig_info->entries4) { | ||
683 | for (i = 0; i < tp->md5sig_info->entries4; i++) | ||
684 | kfree(tp->md5sig_info->keys4[i].base.key); | ||
685 | tp->md5sig_info->entries4 = 0; | ||
686 | tcp_free_md5sig_pool(); | ||
687 | } | ||
688 | |||
689 | kfree(tp->md5sig_info->keys4); | ||
690 | tp->md5sig_info->keys4 = NULL; | ||
691 | tp->md5sig_info->alloced4 = 0; | ||
692 | } | ||
693 | |||
694 | static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval, | 558 | static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval, |
695 | int optlen) | 559 | int optlen) |
696 | { | 560 | { |
697 | struct tcp_md5sig cmd; | 561 | struct tcp_md5sig cmd; |
698 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd.tcpm_addr; | 562 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd.tcpm_addr; |
699 | u8 *newkey; | ||
700 | 563 | ||
701 | if (optlen < sizeof(cmd)) | 564 | if (optlen < sizeof(cmd)) |
702 | return -EINVAL; | 565 | return -EINVAL; |
@@ -708,36 +571,22 @@ static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval, | |||
708 | return -EINVAL; | 571 | return -EINVAL; |
709 | 572 | ||
710 | if (!cmd.tcpm_keylen) { | 573 | if (!cmd.tcpm_keylen) { |
711 | if (!tcp_sk(sk)->md5sig_info) | ||
712 | return -ENOENT; | ||
713 | if (ipv6_addr_v4mapped(&sin6->sin6_addr)) | 574 | if (ipv6_addr_v4mapped(&sin6->sin6_addr)) |
714 | return tcp_v4_md5_do_del(sk, sin6->sin6_addr.s6_addr32[3]); | 575 | return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3], |
715 | return tcp_v6_md5_do_del(sk, &sin6->sin6_addr); | 576 | AF_INET); |
577 | return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr, | ||
578 | AF_INET6); | ||
716 | } | 579 | } |
717 | 580 | ||
718 | if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN) | 581 | if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN) |
719 | return -EINVAL; | 582 | return -EINVAL; |
720 | 583 | ||
721 | if (!tcp_sk(sk)->md5sig_info) { | 584 | if (ipv6_addr_v4mapped(&sin6->sin6_addr)) |
722 | struct tcp_sock *tp = tcp_sk(sk); | 585 | return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3], |
723 | struct tcp_md5sig_info *p; | 586 | AF_INET, cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL); |
724 | |||
725 | p = kzalloc(sizeof(struct tcp_md5sig_info), GFP_KERNEL); | ||
726 | if (!p) | ||
727 | return -ENOMEM; | ||
728 | 587 | ||
729 | tp->md5sig_info = p; | 588 | return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr, |
730 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); | 589 | AF_INET6, cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL); |
731 | } | ||
732 | |||
733 | newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL); | ||
734 | if (!newkey) | ||
735 | return -ENOMEM; | ||
736 | if (ipv6_addr_v4mapped(&sin6->sin6_addr)) { | ||
737 | return tcp_v4_md5_do_add(sk, sin6->sin6_addr.s6_addr32[3], | ||
738 | newkey, cmd.tcpm_keylen); | ||
739 | } | ||
740 | return tcp_v6_md5_do_add(sk, &sin6->sin6_addr, newkey, cmd.tcpm_keylen); | ||
741 | } | 590 | } |
742 | 591 | ||
743 | static int tcp_v6_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, | 592 | static int tcp_v6_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, |
@@ -1074,6 +923,13 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
1074 | const struct tcphdr *th = tcp_hdr(skb); | 923 | const struct tcphdr *th = tcp_hdr(skb); |
1075 | u32 seq = 0, ack_seq = 0; | 924 | u32 seq = 0, ack_seq = 0; |
1076 | struct tcp_md5sig_key *key = NULL; | 925 | struct tcp_md5sig_key *key = NULL; |
926 | #ifdef CONFIG_TCP_MD5SIG | ||
927 | const __u8 *hash_location = NULL; | ||
928 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | ||
929 | unsigned char newhash[16]; | ||
930 | int genhash; | ||
931 | struct sock *sk1 = NULL; | ||
932 | #endif | ||
1077 | 933 | ||
1078 | if (th->rst) | 934 | if (th->rst) |
1079 | return; | 935 | return; |
@@ -1082,8 +938,32 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
1082 | return; | 938 | return; |
1083 | 939 | ||
1084 | #ifdef CONFIG_TCP_MD5SIG | 940 | #ifdef CONFIG_TCP_MD5SIG |
1085 | if (sk) | 941 | hash_location = tcp_parse_md5sig_option(th); |
1086 | key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr); | 942 | if (!sk && hash_location) { |
943 | /* | ||
944 | * active side is lost. Try to find listening socket through | ||
945 | * source port, and then find md5 key through listening socket. | ||
946 | * we are not loose security here: | ||
947 | * Incoming packet is checked with md5 hash with finding key, | ||
948 | * no RST generated if md5 hash doesn't match. | ||
949 | */ | ||
950 | sk1 = inet6_lookup_listener(dev_net(skb_dst(skb)->dev), | ||
951 | &tcp_hashinfo, &ipv6h->daddr, | ||
952 | ntohs(th->source), inet6_iif(skb)); | ||
953 | if (!sk1) | ||
954 | return; | ||
955 | |||
956 | rcu_read_lock(); | ||
957 | key = tcp_v6_md5_do_lookup(sk1, &ipv6h->saddr); | ||
958 | if (!key) | ||
959 | goto release_sk1; | ||
960 | |||
961 | genhash = tcp_v6_md5_hash_skb(newhash, key, NULL, NULL, skb); | ||
962 | if (genhash || memcmp(hash_location, newhash, 16) != 0) | ||
963 | goto release_sk1; | ||
964 | } else { | ||
965 | key = sk ? tcp_v6_md5_do_lookup(sk, &ipv6h->saddr) : NULL; | ||
966 | } | ||
1087 | #endif | 967 | #endif |
1088 | 968 | ||
1089 | if (th->ack) | 969 | if (th->ack) |
@@ -1093,6 +973,14 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
1093 | (th->doff << 2); | 973 | (th->doff << 2); |
1094 | 974 | ||
1095 | tcp_v6_send_response(skb, seq, ack_seq, 0, 0, key, 1, 0); | 975 | tcp_v6_send_response(skb, seq, ack_seq, 0, 0, key, 1, 0); |
976 | |||
977 | #ifdef CONFIG_TCP_MD5SIG | ||
978 | release_sk1: | ||
979 | if (sk1) { | ||
980 | rcu_read_unlock(); | ||
981 | sock_put(sk1); | ||
982 | } | ||
983 | #endif | ||
1096 | } | 984 | } |
1097 | 985 | ||
1098 | static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts, | 986 | static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts, |
@@ -1394,6 +1282,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1394 | newnp->opt = NULL; | 1282 | newnp->opt = NULL; |
1395 | newnp->mcast_oif = inet6_iif(skb); | 1283 | newnp->mcast_oif = inet6_iif(skb); |
1396 | newnp->mcast_hops = ipv6_hdr(skb)->hop_limit; | 1284 | newnp->mcast_hops = ipv6_hdr(skb)->hop_limit; |
1285 | newnp->rcv_tclass = ipv6_tclass(ipv6_hdr(skb)); | ||
1397 | 1286 | ||
1398 | /* | 1287 | /* |
1399 | * No need to charge this sock to the relevant IPv6 refcnt debug socks count | 1288 | * No need to charge this sock to the relevant IPv6 refcnt debug socks count |
@@ -1472,6 +1361,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1472 | newnp->opt = NULL; | 1361 | newnp->opt = NULL; |
1473 | newnp->mcast_oif = inet6_iif(skb); | 1362 | newnp->mcast_oif = inet6_iif(skb); |
1474 | newnp->mcast_hops = ipv6_hdr(skb)->hop_limit; | 1363 | newnp->mcast_hops = ipv6_hdr(skb)->hop_limit; |
1364 | newnp->rcv_tclass = ipv6_tclass(ipv6_hdr(skb)); | ||
1475 | 1365 | ||
1476 | /* Clone native IPv6 options from listening socket (if any) | 1366 | /* Clone native IPv6 options from listening socket (if any) |
1477 | 1367 | ||
@@ -1510,10 +1400,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1510 | * memory, then we end up not copying the key | 1400 | * memory, then we end up not copying the key |
1511 | * across. Shucks. | 1401 | * across. Shucks. |
1512 | */ | 1402 | */ |
1513 | char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); | 1403 | tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newnp->daddr, |
1514 | if (newkey != NULL) | 1404 | AF_INET6, key->key, key->keylen, GFP_ATOMIC); |
1515 | tcp_v6_md5_do_add(newsk, &newnp->daddr, | ||
1516 | newkey, key->keylen); | ||
1517 | } | 1405 | } |
1518 | #endif | 1406 | #endif |
1519 | 1407 | ||
@@ -1676,6 +1564,8 @@ ipv6_pktoptions: | |||
1676 | np->mcast_oif = inet6_iif(opt_skb); | 1564 | np->mcast_oif = inet6_iif(opt_skb); |
1677 | if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) | 1565 | if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) |
1678 | np->mcast_hops = ipv6_hdr(opt_skb)->hop_limit; | 1566 | np->mcast_hops = ipv6_hdr(opt_skb)->hop_limit; |
1567 | if (np->rxopt.bits.rxtclass) | ||
1568 | np->rcv_tclass = ipv6_tclass(ipv6_hdr(skb)); | ||
1679 | if (ipv6_opt_accepted(sk, opt_skb)) { | 1569 | if (ipv6_opt_accepted(sk, opt_skb)) { |
1680 | skb_set_owner_r(opt_skb, sk); | 1570 | skb_set_owner_r(opt_skb, sk); |
1681 | opt_skb = xchg(&np->pktoptions, opt_skb); | 1571 | opt_skb = xchg(&np->pktoptions, opt_skb); |
@@ -1898,7 +1788,6 @@ static const struct inet_connection_sock_af_ops ipv6_specific = { | |||
1898 | static const struct tcp_sock_af_ops tcp_sock_ipv6_specific = { | 1788 | static const struct tcp_sock_af_ops tcp_sock_ipv6_specific = { |
1899 | .md5_lookup = tcp_v6_md5_lookup, | 1789 | .md5_lookup = tcp_v6_md5_lookup, |
1900 | .calc_md5_hash = tcp_v6_md5_hash_skb, | 1790 | .calc_md5_hash = tcp_v6_md5_hash_skb, |
1901 | .md5_add = tcp_v6_md5_add_func, | ||
1902 | .md5_parse = tcp_v6_parse_md5_keys, | 1791 | .md5_parse = tcp_v6_parse_md5_keys, |
1903 | }; | 1792 | }; |
1904 | #endif | 1793 | #endif |
@@ -1930,7 +1819,6 @@ static const struct inet_connection_sock_af_ops ipv6_mapped = { | |||
1930 | static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = { | 1819 | static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = { |
1931 | .md5_lookup = tcp_v4_md5_lookup, | 1820 | .md5_lookup = tcp_v4_md5_lookup, |
1932 | .calc_md5_hash = tcp_v4_md5_hash_skb, | 1821 | .calc_md5_hash = tcp_v4_md5_hash_skb, |
1933 | .md5_add = tcp_v6_md5_add_func, | ||
1934 | .md5_parse = tcp_v6_parse_md5_keys, | 1822 | .md5_parse = tcp_v6_parse_md5_keys, |
1935 | }; | 1823 | }; |
1936 | #endif | 1824 | #endif |
@@ -2004,11 +1892,6 @@ static int tcp_v6_init_sock(struct sock *sk) | |||
2004 | 1892 | ||
2005 | static void tcp_v6_destroy_sock(struct sock *sk) | 1893 | static void tcp_v6_destroy_sock(struct sock *sk) |
2006 | { | 1894 | { |
2007 | #ifdef CONFIG_TCP_MD5SIG | ||
2008 | /* Clean up the MD5 key list */ | ||
2009 | if (tcp_sk(sk)->md5sig_info) | ||
2010 | tcp_v6_clear_md5_list(sk); | ||
2011 | #endif | ||
2012 | tcp_v4_destroy_sock(sk); | 1895 | tcp_v4_destroy_sock(sk); |
2013 | inet6_destroy_sock(sk); | 1896 | inet6_destroy_sock(sk); |
2014 | } | 1897 | } |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 4f96b5c63685..37b0699e95e5 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -342,7 +342,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
342 | struct inet_sock *inet = inet_sk(sk); | 342 | struct inet_sock *inet = inet_sk(sk); |
343 | struct sk_buff *skb; | 343 | struct sk_buff *skb; |
344 | unsigned int ulen, copied; | 344 | unsigned int ulen, copied; |
345 | int peeked; | 345 | int peeked, off = 0; |
346 | int err; | 346 | int err; |
347 | int is_udplite = IS_UDPLITE(sk); | 347 | int is_udplite = IS_UDPLITE(sk); |
348 | int is_udp4; | 348 | int is_udp4; |
@@ -359,7 +359,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
359 | 359 | ||
360 | try_again: | 360 | try_again: |
361 | skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), | 361 | skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), |
362 | &peeked, &err); | 362 | &peeked, &off, &err); |
363 | if (!skb) | 363 | if (!skb) |
364 | goto out; | 364 | goto out; |
365 | 365 | ||
@@ -1130,7 +1130,8 @@ do_udp_sendmsg: | |||
1130 | if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) { | 1130 | if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) { |
1131 | fl6.flowi6_oif = np->mcast_oif; | 1131 | fl6.flowi6_oif = np->mcast_oif; |
1132 | connected = 0; | 1132 | connected = 0; |
1133 | } | 1133 | } else if (!fl6.flowi6_oif) |
1134 | fl6.flowi6_oif = np->ucast_oif; | ||
1134 | 1135 | ||
1135 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); | 1136 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
1136 | 1137 | ||
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c index a81ce9450750..9949a356d62c 100644 --- a/net/ipv6/xfrm6_mode_beet.c +++ b/net/ipv6/xfrm6_mode_beet.c | |||
@@ -80,7 +80,6 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) | |||
80 | static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb) | 80 | static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb) |
81 | { | 81 | { |
82 | struct ipv6hdr *ip6h; | 82 | struct ipv6hdr *ip6h; |
83 | const unsigned char *old_mac; | ||
84 | int size = sizeof(struct ipv6hdr); | 83 | int size = sizeof(struct ipv6hdr); |
85 | int err; | 84 | int err; |
86 | 85 | ||
@@ -90,10 +89,7 @@ static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb) | |||
90 | 89 | ||
91 | __skb_push(skb, size); | 90 | __skb_push(skb, size); |
92 | skb_reset_network_header(skb); | 91 | skb_reset_network_header(skb); |
93 | 92 | skb_mac_header_rebuild(skb); | |
94 | old_mac = skb_mac_header(skb); | ||
95 | skb_set_mac_header(skb, -skb->mac_len); | ||
96 | memmove(skb_mac_header(skb), old_mac, skb->mac_len); | ||
97 | 93 | ||
98 | xfrm6_beet_make_header(skb); | 94 | xfrm6_beet_make_header(skb); |
99 | 95 | ||
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c index 261e6e6f487e..9f2095b19ad0 100644 --- a/net/ipv6/xfrm6_mode_tunnel.c +++ b/net/ipv6/xfrm6_mode_tunnel.c | |||
@@ -63,7 +63,6 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) | |||
63 | static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) | 63 | static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) |
64 | { | 64 | { |
65 | int err = -EINVAL; | 65 | int err = -EINVAL; |
66 | const unsigned char *old_mac; | ||
67 | 66 | ||
68 | if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6) | 67 | if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6) |
69 | goto out; | 68 | goto out; |
@@ -80,10 +79,9 @@ static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) | |||
80 | if (!(x->props.flags & XFRM_STATE_NOECN)) | 79 | if (!(x->props.flags & XFRM_STATE_NOECN)) |
81 | ipip6_ecn_decapsulate(skb); | 80 | ipip6_ecn_decapsulate(skb); |
82 | 81 | ||
83 | old_mac = skb_mac_header(skb); | ||
84 | skb_set_mac_header(skb, -skb->mac_len); | ||
85 | memmove(skb_mac_header(skb), old_mac, skb->mac_len); | ||
86 | skb_reset_network_header(skb); | 82 | skb_reset_network_header(skb); |
83 | skb_mac_header_rebuild(skb); | ||
84 | |||
87 | err = 0; | 85 | err = 0; |
88 | 86 | ||
89 | out: | 87 | out: |
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 4eeff89c1aaa..8755a3079d0f 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c | |||
@@ -146,7 +146,7 @@ static int __xfrm6_output(struct sk_buff *skb) | |||
146 | return -EMSGSIZE; | 146 | return -EMSGSIZE; |
147 | } | 147 | } |
148 | 148 | ||
149 | if ((x && x->props.mode == XFRM_MODE_TUNNEL) && | 149 | if (x->props.mode == XFRM_MODE_TUNNEL && |
150 | ((skb->len > mtu && !skb_is_gso(skb)) || | 150 | ((skb->len > mtu && !skb_is_gso(skb)) || |
151 | dst_allfrag(skb_dst(skb)))) { | 151 | dst_allfrag(skb_dst(skb)))) { |
152 | return ip6_fragment(skb, x->outer_mode->afinfo->output_finish); | 152 | return ip6_fragment(skb, x->outer_mode->afinfo->output_finish); |