diff options
Diffstat (limited to 'net/ipv6/xfrm6_mode_tunnel.c')
-rw-r--r-- | net/ipv6/xfrm6_mode_tunnel.c | 31 |
1 files changed, 10 insertions, 21 deletions
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c index 9a43ea722481..d45ce5d44197 100644 --- a/net/ipv6/xfrm6_mode_tunnel.c +++ b/net/ipv6/xfrm6_mode_tunnel.c | |||
@@ -38,33 +38,22 @@ static inline void ip6ip_ecn_decapsulate(struct sk_buff *skb) | |||
38 | static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) | 38 | static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) |
39 | { | 39 | { |
40 | struct dst_entry *dst = skb->dst; | 40 | struct dst_entry *dst = skb->dst; |
41 | struct xfrm_dst *xdst = (struct xfrm_dst*)dst; | 41 | struct ipv6hdr *top_iph; |
42 | struct ipv6hdr *iph, *top_iph; | ||
43 | int dsfield; | 42 | int dsfield; |
44 | 43 | ||
45 | iph = ipv6_hdr(skb); | ||
46 | |||
47 | skb_set_network_header(skb, -x->props.header_len); | 44 | skb_set_network_header(skb, -x->props.header_len); |
48 | skb->mac_header = skb->network_header + | 45 | skb->mac_header = skb->network_header + |
49 | offsetof(struct ipv6hdr, nexthdr); | 46 | offsetof(struct ipv6hdr, nexthdr); |
50 | skb->transport_header = skb->network_header + sizeof(*iph); | 47 | skb->transport_header = skb->network_header + sizeof(*top_iph); |
51 | top_iph = ipv6_hdr(skb); | 48 | top_iph = ipv6_hdr(skb); |
52 | 49 | ||
53 | top_iph->version = 6; | 50 | top_iph->version = 6; |
54 | if (xdst->route->ops->family == AF_INET6) { | 51 | |
55 | top_iph->priority = iph->priority; | 52 | memcpy(top_iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl, |
56 | top_iph->flow_lbl[0] = iph->flow_lbl[0]; | 53 | sizeof(top_iph->flow_lbl)); |
57 | top_iph->flow_lbl[1] = iph->flow_lbl[1]; | 54 | top_iph->nexthdr = x->inner_mode->afinfo->proto; |
58 | top_iph->flow_lbl[2] = iph->flow_lbl[2]; | 55 | |
59 | top_iph->nexthdr = IPPROTO_IPV6; | 56 | dsfield = XFRM_MODE_SKB_CB(skb)->tos; |
60 | } else { | ||
61 | top_iph->priority = 0; | ||
62 | top_iph->flow_lbl[0] = 0; | ||
63 | top_iph->flow_lbl[1] = 0; | ||
64 | top_iph->flow_lbl[2] = 0; | ||
65 | top_iph->nexthdr = IPPROTO_IPIP; | ||
66 | } | ||
67 | dsfield = ipv6_get_dsfield(top_iph); | ||
68 | dsfield = INET_ECN_encapsulate(dsfield, dsfield); | 57 | dsfield = INET_ECN_encapsulate(dsfield, dsfield); |
69 | if (x->props.flags & XFRM_STATE_NOECN) | 58 | if (x->props.flags & XFRM_STATE_NOECN) |
70 | dsfield &= ~INET_ECN_MASK; | 59 | dsfield &= ~INET_ECN_MASK; |
@@ -72,7 +61,6 @@ static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) | |||
72 | top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT); | 61 | top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT); |
73 | ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); | 62 | ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); |
74 | ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); | 63 | ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); |
75 | skb->protocol = htons(ETH_P_IPV6); | ||
76 | return 0; | 64 | return 0; |
77 | } | 65 | } |
78 | 66 | ||
@@ -116,7 +104,8 @@ out: | |||
116 | 104 | ||
117 | static struct xfrm_mode xfrm6_tunnel_mode = { | 105 | static struct xfrm_mode xfrm6_tunnel_mode = { |
118 | .input = xfrm6_tunnel_input, | 106 | .input = xfrm6_tunnel_input, |
119 | .output = xfrm6_tunnel_output, | 107 | .output2 = xfrm6_tunnel_output, |
108 | .output = xfrm6_prepare_output, | ||
120 | .owner = THIS_MODULE, | 109 | .owner = THIS_MODULE, |
121 | .encap = XFRM_MODE_TUNNEL, | 110 | .encap = XFRM_MODE_TUNNEL, |
122 | .flags = XFRM_MODE_FLAG_TUNNEL, | 111 | .flags = XFRM_MODE_FLAG_TUNNEL, |