diff options
Diffstat (limited to 'net/ipv6/af_inet6.c')
-rw-r--r-- | net/ipv6/af_inet6.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index d9546380fa04..fd040e9a1f47 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -609,6 +609,58 @@ inet6_unregister_protosw(struct inet_protosw *p) | |||
609 | } | 609 | } |
610 | } | 610 | } |
611 | 611 | ||
612 | int inet6_sk_rebuild_header(struct sock *sk) | ||
613 | { | ||
614 | int err; | ||
615 | struct dst_entry *dst; | ||
616 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
617 | |||
618 | dst = __sk_dst_check(sk, np->dst_cookie); | ||
619 | |||
620 | if (dst == NULL) { | ||
621 | struct inet_sock *inet = inet_sk(sk); | ||
622 | struct in6_addr *final_p = NULL, final; | ||
623 | struct flowi fl; | ||
624 | |||
625 | memset(&fl, 0, sizeof(fl)); | ||
626 | fl.proto = sk->sk_protocol; | ||
627 | ipv6_addr_copy(&fl.fl6_dst, &np->daddr); | ||
628 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | ||
629 | fl.fl6_flowlabel = np->flow_label; | ||
630 | fl.oif = sk->sk_bound_dev_if; | ||
631 | fl.fl_ip_dport = inet->dport; | ||
632 | fl.fl_ip_sport = inet->sport; | ||
633 | |||
634 | if (np->opt && np->opt->srcrt) { | ||
635 | struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; | ||
636 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
637 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
638 | final_p = &final; | ||
639 | } | ||
640 | |||
641 | err = ip6_dst_lookup(sk, &dst, &fl); | ||
642 | if (err) { | ||
643 | sk->sk_route_caps = 0; | ||
644 | return err; | ||
645 | } | ||
646 | if (final_p) | ||
647 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
648 | |||
649 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) { | ||
650 | sk->sk_err_soft = -err; | ||
651 | return err; | ||
652 | } | ||
653 | |||
654 | ip6_dst_store(sk, dst, NULL); | ||
655 | sk->sk_route_caps = dst->dev->features & | ||
656 | ~(NETIF_F_IP_CSUM | NETIF_F_TSO); | ||
657 | } | ||
658 | |||
659 | return 0; | ||
660 | } | ||
661 | |||
662 | EXPORT_SYMBOL_GPL(inet6_sk_rebuild_header); | ||
663 | |||
612 | int | 664 | int |
613 | snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign) | 665 | snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign) |
614 | { | 666 | { |