aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/af_inet6.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/af_inet6.c')
-rw-r--r--net/ipv6/af_inet6.c52
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
612int 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
662EXPORT_SYMBOL_GPL(inet6_sk_rebuild_header);
663
612int 664int
613snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign) 665snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign)
614{ 666{