static int xfrm6_output_one(struct sk_buff *skb) { struct dst_entry *dst = skb->dst; struct xfrm_state *x = dst->xfrm; int err; if (skb->ip_summed == CHECKSUM_HW) { err = skb_checksum_help(skb, 0); if (err) goto error_nolock; } if (x->props.mode) { err = xfrm6_tunnel_check_size(skb); if (err) goto error_nolock; } do { spin_lock_bh(&x->lock); err = xfrm_state_check(x, skb); if (err) goto error; err = x->mode->output(skb); if (err) goto error; err = x->type->output(x, skb); if (err) goto error; x->curlft.bytes += skb->len; x->curlft.packets++; spin_unlock_bh(&x->lock); skb->nh.raw = skb->data; if (!(skb->dst = dst_pop(dst))) { err = -EHOSTUNREACH; goto error_nolock; } dst = skb->dst; x = dst->xfrm; } while (x && !x->props.mode); IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; err = 0; out_exit: return err; error: spin_unlock_bh(&x->lock); if (err == -EINPROGRESS) goto out_exit; error_nolock: kfree_skb(skb); goto out_exit; }
static inline int xfrm6_output_one(struct sk_buff *skb) { struct dst_entry *dst = skb->dst; struct xfrm_state *x = dst->xfrm; struct ipv6hdr *iph; int err; if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) { err = xfrm6_tunnel_check_size(skb); if (err) goto error_nolock; } err = xfrm_output(skb); if (err) goto error_nolock; iph = ipv6_hdr(skb); iph->payload_len = htons(skb->len - sizeof(*iph)); IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; err = 0; out_exit: return err; error_nolock: kfree_skb(skb); goto out_exit; }
static int xfrm6_output_one(struct sk_buff *skb) { struct dst_entry *dst = skb->dst; struct xfrm_state *x = dst->xfrm; int err; if (skb->ip_summed == CHECKSUM_PARTIAL) { err = skb_checksum_help(skb); if (err) goto error_nolock; } if (x->props.mode == XFRM_MODE_TUNNEL) { err = xfrm6_tunnel_check_size(skb); if (err) goto error_nolock; } do { spin_lock_bh(&x->lock); err = xfrm_state_check(x, skb); if (err) goto error; err = x->mode->output(x, skb); if (err) goto error; err = x->type->output(x, skb); if (err) goto error; x->curlft.bytes += skb->len; x->curlft.packets++; if (x->props.mode == XFRM_MODE_ROUTEOPTIMIZATION) x->lastused = (u64)xtime.tv_sec; spin_unlock_bh(&x->lock); skb->nh.raw = skb->data; if (!(skb->dst = dst_pop(dst))) { err = -EHOSTUNREACH; goto error_nolock; } dst = skb->dst; x = dst->xfrm; } while (x && (x->props.mode != XFRM_MODE_TUNNEL)); IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; err = 0; out_exit: return err; error: spin_unlock_bh(&x->lock); error_nolock: kfree_skb(skb); goto out_exit; }
int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb) { int err; err = xfrm6_tunnel_check_size(skb); if (err) return err; XFRM_MODE_SKB_CB(skb)->protocol = ipv6_hdr(skb)->nexthdr; return xfrm6_extract_header(skb); }
int xfrm6_output(struct sk_buff **pskb) { struct sk_buff *skb = *pskb; struct dst_entry *dst = skb->dst; struct xfrm_state *x = dst->xfrm; int err; if (skb->ip_summed == CHECKSUM_HW) { err = skb_checksum_help(pskb, 0); skb = *pskb; if (err) goto error_nolock; } if (x->props.mode) { err = xfrm6_tunnel_check_size(skb); if (err) goto error_nolock; } spin_lock_bh(&x->lock); err = xfrm_state_check(x, skb); if (err) goto error; xfrm6_encap(skb); err = x->type->output(skb); if (err) goto error; x->curlft.bytes += skb->len; x->curlft.packets++; spin_unlock_bh(&x->lock); skb->nh.raw = skb->data; if (!(skb->dst = dst_pop(dst))) { err = -EHOSTUNREACH; goto error_nolock; } err = NET_XMIT_BYPASS; out_exit: return err; error: spin_unlock_bh(&x->lock); error_nolock: kfree_skb(skb); goto out_exit; }