[IPSEC]: Move IP protocol setting from transforms into xfrm4_input.c

This patch makes the IPv4 x->type->input functions return the next protocol
instead of setting it directly.  This is identical to how we do things in
IPv6 and will help us merge common code on the input path.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 60925fe..4e8e3b0 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -125,6 +125,7 @@
 {
 	int ah_hlen;
 	int ihl;
+	int nexthdr;
 	int err = -EINVAL;
 	struct iphdr *iph;
 	struct ip_auth_hdr *ah;
@@ -136,6 +137,7 @@
 
 	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) &&
@@ -182,13 +184,12 @@
 			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;
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 8377bed..6b1a31a74 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -257,12 +257,11 @@
 			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;
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 32b02de..0bfeb02 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -75,7 +75,6 @@
 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))
@@ -84,12 +83,14 @@
 	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;
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index 2fa1082..e9bbfde 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -54,12 +54,14 @@
 	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;
@@ -82,9 +84,12 @@
 		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;
 
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index e1fafc1..1312417 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -18,7 +18,7 @@
 
 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)