static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
{
	int err = -EINVAL;

	if (skb->nh.raw[IP6CB(skb)->nhoff] != IPPROTO_IPV6)
		goto out;
	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
		goto out;

	if (skb_cloned(skb) &&
	    (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
		goto out;

	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);
	skb->mac.raw = memmove(skb->data - skb->mac_len,
			       skb->mac.raw, skb->mac_len);
	skb->nh.raw = skb->data;
	err = 0;

out:
	return err;
}
static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
{
	int err = -EINVAL;

	if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6)
		goto out;
	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
		goto out;

	if (skb_cloned(skb) &&
	    (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
		goto out;

	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);

	skb_reset_network_header(skb);
	skb_mac_header_rebuild(skb);

	err = 0;

out:
	return err;
}
static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
{
	int err = -EINVAL;
	const unsigned char *nh = skb_network_header(skb);

	if (nh[IP6CB(skb)->nhoff] != IPPROTO_IPV6 &&
	    nh[IP6CB(skb)->nhoff] != IPPROTO_IPIP)
		goto out;
	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
		goto out;

	err = skb_unclone(skb, GFP_ATOMIC);
	if (err)
		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);
	}
	skb->mac.raw = memmove(skb->data - skb->mac_len,
			       skb->mac.raw, skb->mac_len);
	skb_reset_network_header(skb);
	err = 0;

out:
	return err;
}
Beispiel #4
0
static void ip6ip6_dscp_ecn_decapsulate(struct ip6_tnl *t,
					struct ipv6hdr *ipv6h,
					struct sk_buff *skb)
{
	if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY)
		ipv6_copy_dscp(ipv6_get_dsfield(ipv6h), ipv6_hdr(skb));

	if (INET_ECN_is_ce(ipv6_get_dsfield(ipv6h)))
		IP6_ECN_set_ce(ipv6_hdr(skb));
}
Beispiel #5
0
static int
ip6ip6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
{
	struct sk_buff *skb = *pskb;
	struct ipv6hdr *ipv6h;
	struct ip6_tnl *t;

	if (!pskb_may_pull(skb, sizeof (*ipv6h)))
		goto discard;

	ipv6h = skb->nh.ipv6h;

	read_lock(&ip6ip6_lock);

	if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) {
		if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
			read_unlock(&ip6ip6_lock);
			kfree_skb(skb);
			return 0;
		}

		if (!ip6_tnl_rcv_ctl(t)) {
			t->stat.rx_dropped++;
			read_unlock(&ip6ip6_lock);
			goto discard;
		}
		secpath_reset(skb);
		skb->mac.raw = skb->nh.raw;
		skb->nh.raw = skb->data;
		skb->protocol = htons(ETH_P_IPV6);
		skb->pkt_type = PACKET_HOST;
		memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
		skb->dev = t->dev;
		dst_release(skb->dst);
		skb->dst = NULL;
		if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY)
			ipv6_copy_dscp(ipv6h, skb->nh.ipv6h);
		ip6ip6_ecn_decapsulate(ipv6h, skb);
		t->stat.rx_packets++;
		t->stat.rx_bytes += skb->len;
		netif_rx(skb);
		read_unlock(&ip6ip6_lock);
		return 0;
	}
	read_unlock(&ip6ip6_lock);
	icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev);
discard:
	return 1;
}