static int xfrm4_output_one(struct sk_buff *skb) { struct dst_entry *dst = skb->dst; struct xfrm_state *x = dst->xfrm; int err; err = skb_checksum_setup(skb); if (err) goto error_nolock; if (skb->ip_summed == CHECKSUM_HW) { err = skb_checksum_help(skb, 0); if (err) goto error_nolock; } if (x->props.mode) { err = xfrm4_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); if (!(skb->dst = dst_pop(dst))) { err = -EHOSTUNREACH; goto error_nolock; } dst = skb->dst; x = dst->xfrm; } while (x && !x->props.mode); IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED; err = 0; out_exit: return err; error: spin_unlock_bh(&x->lock); error_nolock: kfree_skb(skb); goto out_exit; }
static int ipip_output(struct sk_buff *skb) { struct dst_entry *dst = skb->dst; struct xfrm_state *x = dst->xfrm; struct iphdr *iph, *top_iph; int tos, err; if ((err = xfrm4_tunnel_check_size(skb)) != 0) goto error_nolock; iph = skb->nh.iph; spin_lock_bh(&x->lock); tos = iph->tos; top_iph = (struct iphdr *) skb_push(skb, x->props.header_len); top_iph->ihl = 5; top_iph->version = 4; top_iph->tos = INET_ECN_encapsulate(tos, iph->tos); top_iph->tot_len = htons(skb->len); top_iph->frag_off = iph->frag_off & ~htons(IP_MF|IP_OFFSET); if (!(iph->frag_off & htons(IP_DF))) { #ifdef NETIF_F_TSO __ip_select_ident(top_iph, dst, 0); #else __ip_select_ident(top_iph, dst); #endif } top_iph->ttl = iph->ttl; top_iph->protocol = IPPROTO_IPIP; top_iph->check = 0; top_iph->saddr = x->props.saddr.a4; top_iph->daddr = x->id.daddr.a4; memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); ip_send_check(top_iph); skb->nh.raw = skb->data; x->curlft.bytes += skb->len; x->curlft.packets++; spin_unlock_bh(&x->lock); if ((skb->dst = dst_pop(dst)) == NULL) { kfree_skb(skb); err = -EHOSTUNREACH; goto error_nolock; } return NET_XMIT_BYPASS; error_nolock: kfree_skb(skb); return err; }
int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb) { int err; err = xfrm4_tunnel_check_size(skb); if (err) return err; XFRM_MODE_SKB_CB(skb)->protocol = ip_hdr(skb)->protocol; return xfrm4_extract_header(skb); }
int xfrm4_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; } spin_lock_bh(&x->lock); err = xfrm_state_check(x, skb); if (err) goto error; if (x->props.mode) { err = xfrm4_tunnel_check_size(skb); if (err) goto error; } xfrm4_encap(skb); err = x->type->output(pskb); skb = *pskb; if (err) goto error; x->curlft.bytes += skb->len; x->curlft.packets++; spin_unlock_bh(&x->lock); 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; }
static int xfrm4_output_one(struct sk_buff *skb) { struct dst_entry *dst = skb->dst; struct xfrm_state *x = dst->xfrm; int err; /* purpose: 0014838 author: paul.chen date: 2011-12-06 */ /* description: Fix reboot & plug in crash for VPN G2G wildcard */ if(skb && skb->nh.iph && skb->nh.iph->protocol==IPPROTO_IGMP) { err = -EINVAL; goto error_nolock; } if (skb->ip_summed == CHECKSUM_HW) { err = skb_checksum_help(skb, 0); if (err) goto error_nolock; } if (x->props.mode) { err = xfrm4_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; #if defined(CONFIG_CAVIUM_OCTEON_IPSEC) && defined(CONFIG_NET_KEY) /* * If Octeon IPSEC Acceleration module has been loaded * call it, otherwise, follow the software path */ if(cavium_ipsec_process) { if (skb_is_nonlinear(skb) && skb_linearize(skb, GFP_ATOMIC) != 0) { err = -ENOMEM; goto error; } err = cavium_ipsec_process(x->sa_handle, skb, 0, 1 /*ENCRYPT*/); } else { xfrm4_encap(skb); err = x->type->output(x, skb); } #else xfrm4_encap(skb); err = x->type->output(x, skb); #endif if (err) goto error; x->curlft.bytes += skb->len; x->curlft.packets++; spin_unlock_bh(&x->lock); if (!(skb->dst = dst_pop(dst))) { err = -EHOSTUNREACH; goto error_nolock; } dst = skb->dst; x = dst->xfrm; } while (x && !x->props.mode); IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED; err = 0; out_exit: return err; error: spin_unlock_bh(&x->lock); error_nolock: kfree_skb(skb); goto out_exit; }