X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=net%2Fipv6%2Fxfrm6_mode_tunnel.c;h=b809812c8d30a85b13732fd2071d524da6a81807;hb=HEAD;hp=498f17b5c42f87684ce540162e6d1180150ab0aa;hpb=d56f90a7c96da5187f0cdf07ee7434fe6aa78bbc;p=safe%2Fjmp%2Flinux-2.6 diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c index 498f17b..b809812 100644 --- a/net/ipv6/xfrm6_mode_tunnel.c +++ b/net/ipv6/xfrm6_mode_tunnel.c @@ -5,6 +5,7 @@ * Copyright (c) 2004-2006 Herbert Xu */ +#include #include #include #include @@ -18,61 +19,36 @@ static inline void ipip6_ecn_decapsulate(struct sk_buff *skb) { - struct ipv6hdr *outer_iph = skb->nh.ipv6h; - struct ipv6hdr *inner_iph = skb->h.ipv6h; + struct ipv6hdr *outer_iph = ipv6_hdr(skb); + struct ipv6hdr *inner_iph = ipipv6_hdr(skb); if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph))) IP6_ECN_set_ce(inner_iph); } -static inline void ip6ip_ecn_decapsulate(struct sk_buff *skb) -{ - if (INET_ECN_is_ce(ipv6_get_dsfield(skb->nh.ipv6h))) - IP_ECN_set_ce(skb->h.ipiph); -} - /* Add encapsulation header. * - * The top IP header will be constructed per RFC 2401. The following fields - * in it shall be filled in by x->type->output: - * payload_len - * - * On exit, skb->h will be set to the start of the encapsulation header to be - * filled in by x->type->output and skb->nh will be set to the nextheader field - * of the extension header directly preceding the encapsulation header, or in - * its absence, that of the top IP header. The value of skb->data will always - * point to the top IP header. + * The top IP header will be constructed per RFC 2401. */ -static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) +static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) { - struct dst_entry *dst = skb->dst; - struct xfrm_dst *xdst = (struct xfrm_dst*)dst; - struct ipv6hdr *iph, *top_iph; + struct dst_entry *dst = skb_dst(skb); + struct ipv6hdr *top_iph; int dsfield; - skb_push(skb, x->props.header_len); - iph = skb->nh.ipv6h; - - skb_reset_network_header(skb); - top_iph = skb->nh.ipv6h; - skb->nh.raw = &top_iph->nexthdr; - skb->h.ipv6h = top_iph + 1; + skb_set_network_header(skb, -x->props.header_len); + skb->mac_header = skb->network_header + + offsetof(struct ipv6hdr, nexthdr); + skb->transport_header = skb->network_header + sizeof(*top_iph); + top_iph = ipv6_hdr(skb); top_iph->version = 6; - if (xdst->route->ops->family == AF_INET6) { - top_iph->priority = iph->priority; - top_iph->flow_lbl[0] = iph->flow_lbl[0]; - top_iph->flow_lbl[1] = iph->flow_lbl[1]; - top_iph->flow_lbl[2] = iph->flow_lbl[2]; - top_iph->nexthdr = IPPROTO_IPV6; - } else { - top_iph->priority = 0; - top_iph->flow_lbl[0] = 0; - top_iph->flow_lbl[1] = 0; - top_iph->flow_lbl[2] = 0; - top_iph->nexthdr = IPPROTO_IPIP; - } - dsfield = ipv6_get_dsfield(top_iph); + + memcpy(top_iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl, + sizeof(top_iph->flow_lbl)); + top_iph->nexthdr = xfrm_af2proto(skb_dst(skb)->ops->family); + + dsfield = XFRM_MODE_SKB_CB(skb)->tos; dsfield = INET_ECN_encapsulate(dsfield, dsfield); if (x->props.flags & XFRM_STATE_NOECN) dsfield &= ~INET_ECN_MASK; @@ -83,14 +59,12 @@ static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) return 0; } -static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) +static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) { int err = -EINVAL; const unsigned char *old_mac; - const unsigned char *nh = skb_network_header(skb); - if (nh[IP6CB(skb)->nhoff] != IPPROTO_IPV6 && - nh[IP6CB(skb)->nhoff] != IPPROTO_IPIP) + if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6) goto out; if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) goto out; @@ -99,17 +73,12 @@ static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) goto out; - nh = skb_network_header(skb); - if (nh[IP6CB(skb)->nhoff] == IPPROTO_IPV6) { - if (x->props.flags & XFRM_STATE_DECAP_DSCP) - ipv6_copy_dscp(skb->nh.ipv6h, skb->h.ipv6h); - if (!(x->props.flags & XFRM_STATE_NOECN)) - ipip6_ecn_decapsulate(skb); - } else { - if (!(x->props.flags & XFRM_STATE_NOECN)) - ip6ip_ecn_decapsulate(skb); - skb->protocol = htons(ETH_P_IP); - } + if (x->props.flags & XFRM_STATE_DECAP_DSCP) + ipv6_copy_dscp(ipv6_get_dsfield(ipv6_hdr(skb)), + ipipv6_hdr(skb)); + if (!(x->props.flags & XFRM_STATE_NOECN)) + ipip6_ecn_decapsulate(skb); + old_mac = skb_mac_header(skb); skb_set_mac_header(skb, -skb->mac_len); memmove(skb_mac_header(skb), old_mac, skb->mac_len); @@ -121,18 +90,21 @@ out: } static struct xfrm_mode xfrm6_tunnel_mode = { - .input = xfrm6_tunnel_input, - .output = xfrm6_tunnel_output, + .input2 = xfrm6_mode_tunnel_input, + .input = xfrm_prepare_input, + .output2 = xfrm6_mode_tunnel_output, + .output = xfrm6_prepare_output, .owner = THIS_MODULE, .encap = XFRM_MODE_TUNNEL, + .flags = XFRM_MODE_FLAG_TUNNEL, }; -static int __init xfrm6_tunnel_init(void) +static int __init xfrm6_mode_tunnel_init(void) { return xfrm_register_mode(&xfrm6_tunnel_mode, AF_INET6); } -static void __exit xfrm6_tunnel_exit(void) +static void __exit xfrm6_mode_tunnel_exit(void) { int err; @@ -140,7 +112,7 @@ static void __exit xfrm6_tunnel_exit(void) BUG_ON(err); } -module_init(xfrm6_tunnel_init); -module_exit(xfrm6_tunnel_exit); +module_init(xfrm6_mode_tunnel_init); +module_exit(xfrm6_mode_tunnel_exit); MODULE_LICENSE("GPL"); MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_TUNNEL);