{
int ah_hlen;
int ihl;
+ int nexthdr;
int err = -EINVAL;
struct iphdr *iph;
struct ip_auth_hdr *ah;
ah = (struct ip_auth_hdr *)skb->data;
ahp = x->data;
+ nexthdr = ah->nexthdr;
ah_hlen = (ah->hdrlen + 2) << 2;
if (ah_hlen != XFRM_ALIGN8(sizeof(*ah) + ahp->icv_full_len) &&
goto out;
}
}
- ((struct iphdr*)work_buf)->protocol = ah->nexthdr;
skb->network_header += ah_hlen;
memcpy(skb_network_header(skb), work_buf, ihl);
skb->transport_header = skb->network_header;
__skb_pull(skb, ah_hlen + ihl);
- return 0;
+ return nexthdr;
out:
return err;
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
- iph->protocol = nexthdr[1];
pskb_trim(skb, skb->len - alen - padlen - 2);
__skb_pull(skb, sizeof(*esph) + esp->conf.ivlen);
skb_set_transport_header(skb, -ihl);
- return 0;
+ return nexthdr[1];
out:
return -EINVAL;
static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
{
int err = -ENOMEM;
- struct iphdr *iph;
struct ip_comp_hdr *ipch;
if (skb_linearize_cow(skb))
skb->ip_summed = CHECKSUM_NONE;
/* Remove ipcomp header and decompress original payload */
- iph = ip_hdr(skb);
ipch = (void *)skb->data;
- iph->protocol = ipch->nexthdr;
skb->transport_header = skb->network_header + sizeof(*ipch);
__skb_pull(skb, sizeof(*ipch));
err = ipcomp_decompress(x, skb);
+ if (err)
+ goto out;
+
+ err = ipch->nexthdr;
out:
return err;
int xfrm_nr = 0;
int decaps = 0;
int err = xfrm4_parse_spi(skb, ip_hdr(skb)->protocol, &spi, &seq);
+ unsigned int nhoff = offsetof(struct iphdr, protocol);
if (err != 0)
goto drop;
do {
const struct iphdr *iph = ip_hdr(skb);
+ int nexthdr;
if (xfrm_nr == XFRM_MAX_DEPTH)
goto drop;
if (xfrm_state_check_expire(x))
goto drop_unlock;
- if (x->type->input(x, skb))
+ nexthdr = x->type->input(x, skb);
+ if (nexthdr <= 0)
goto drop_unlock;
+ skb_network_header(skb)[nhoff] = nexthdr;
+
/* only the first xfrm gets the encap type */
encap_type = 0;
static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb)
{
- return 0;
+ return IPPROTO_IP;
}
static int ipip_init_state(struct xfrm_state *x)