Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 37fedd3a authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller
Browse files

[IPSEC]: Use IPv6 calling convention as the convention for x->mode->output



The IPv6 calling convention for x->mode->output is more general and could
help an eventual protocol-generic x->type->output implementation.  This
patch adopts it for IPv4 as well and modifies the IPv4 type output functions
accordingly.

It also rewrites the IPv6 mac/transport header calculation to be based off
the network header where practical.

Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7b277b1a
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -300,6 +300,18 @@ extern void xfrm_put_type(struct xfrm_type *type);

struct xfrm_mode {
	int (*input)(struct xfrm_state *x, struct sk_buff *skb);

	/*
	 * Add encapsulation header.
	 *
	 * On exit, the transport header will be set to the start of the
	 * encapsulation header to be filled in by x->type->output and
	 * the mac header will be set to the nextheader (protocol for
	 * IPv4) field of the extension header directly preceding the
	 * encapsulation header, or in its absence, that of the top IP
	 * header.  The value of the network header will always point
	 * to the top IP header while skb->data will point to the payload.
	 */
	int (*output)(struct xfrm_state *x,struct sk_buff *skb);

	struct module *owner;
+3 −3
Original line number Diff line number Diff line
@@ -82,14 +82,14 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
			goto error;
	}

	ah = (struct ip_auth_hdr *)((char *)top_iph+top_iph->ihl*4);
	ah->nexthdr = top_iph->protocol;
	ah = (struct ip_auth_hdr *)skb_transport_header(skb);
	ah->nexthdr = *skb_mac_header(skb);
	*skb_mac_header(skb) = IPPROTO_AH;

	top_iph->tos = 0;
	top_iph->tot_len = htons(skb->len);
	top_iph->frag_off = 0;
	top_iph->ttl = 0;
	top_iph->protocol = IPPROTO_AH;
	top_iph->check = 0;

	ahp = x->data;
+5 −6
Original line number Diff line number Diff line
@@ -60,10 +60,10 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)

	skb_push(skb, -skb_network_offset(skb));
	top_iph = ip_hdr(skb);
	esph = (struct ip_esp_hdr *)(skb_network_header(skb) +
				     top_iph->ihl * 4);
	esph = (struct ip_esp_hdr *)skb_transport_header(skb);
	top_iph->tot_len = htons(skb->len + alen);
	*(skb_tail_pointer(trailer) - 1) = top_iph->protocol;
	*(skb_tail_pointer(trailer) - 1) = *skb_mac_header(skb);
	*skb_mac_header(skb) = IPPROTO_ESP;

	spin_lock_bh(&x->lock);

@@ -91,9 +91,8 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
			break;
		}

		top_iph->protocol = IPPROTO_UDP;
	} else
		top_iph->protocol = IPPROTO_ESP;
		*skb_mac_header(skb) = IPPROTO_UDP;
	}

	esph->spi = x->id.spi;
	esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq);
+5 −5
Original line number Diff line number Diff line
@@ -98,10 +98,10 @@ static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb)
{
	struct ipcomp_data *ipcd = x->data;
	const int ihlen = ip_hdrlen(skb);
	const int ihlen = skb_transport_offset(skb);
	const int plen = skb->len - ihlen;
	int dlen = IPCOMP_SCRATCH_SIZE;
	u8 *start = skb->data + ihlen;
	u8 *start = skb_transport_header(skb);
	const int cpu = get_cpu();
	u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
	struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu);
@@ -154,11 +154,11 @@ static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb)

	/* Install ipcomp header, convert into ipcomp datagram. */
	iph->tot_len = htons(skb->len);
	ipch = (struct ip_comp_hdr *)((char *)iph + iph->ihl * 4);
	ipch->nexthdr = iph->protocol;
	ipch = (struct ip_comp_hdr *)skb_transport_header(skb);
	ipch->nexthdr = *skb_mac_header(skb);
	ipch->flags = 0;
	ipch->cpi = htons((u16 )ntohl(x->id.spi));
	iph->protocol = IPPROTO_COMP;
	*skb_mac_header(skb) = IPPROTO_COMP;
	ip_send_check(iph);
	return 0;

+7 −10
Original line number Diff line number Diff line
@@ -23,17 +23,14 @@
 * The following fields in it shall be filled in by x->type->output:
 *      tot_len
 *      check
 *
 * On exit, skb->h will be set to the start of the payload to be processed
 * by x->type->output and skb->nh will be set to the top IP header.
 */
static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
{
	struct ip_beet_phdr *ph;
	struct iphdr *iph, *top_iph;
	int hdrlen, optlen;

	iph = ip_hdr(skb);
	skb->transport_header = skb->network_header;

	hdrlen = 0;
	optlen = iph->ihl * 4 - sizeof(*iph);
@@ -42,17 +39,17 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)

	skb_set_network_header(skb, IPV4_BEET_PHMAXLEN - x->props.header_len -
				    hdrlen);
	top_iph = ip_hdr(skb);
	skb->transport_header += sizeof(*iph) - hdrlen;
	__skb_pull(skb, sizeof(*iph) - hdrlen);
	skb->mac_header = skb->network_header +
			  offsetof(struct iphdr, protocol);
	skb->transport_header = skb->network_header + sizeof(*iph);

	ph = (struct ip_beet_phdr *)__skb_pull(skb, sizeof(*iph) - hdrlen);

	top_iph = ip_hdr(skb);
	memmove(top_iph, iph, sizeof(*iph));
	if (unlikely(optlen)) {
		struct ip_beet_phdr *ph;

		BUG_ON(optlen < 0);

		ph = (struct ip_beet_phdr *)skb_transport_header(skb);
		ph->padlen = 4 - (optlen & 4);
		ph->hdrlen = optlen / 8;
		ph->nexthdr = top_iph->protocol;
Loading