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

Commit 58c949d1 authored by Masahide NAKAMURA's avatar Masahide NAKAMURA Committed by David S. Miller
Browse files

[XFRM] IPV6: Add sort functions to combine templates/states for IPsec.



Add sort functions to combine templates/states for IPsec.
Think of outbound transformation order we should be careful with transport AH
which must be the last of all transport ones.

Signed-off-by: default avatarMasahide NAKAMURA <nakam@linux-ipv6.org>
Signed-off-by: default avatarYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f7b6983f
Loading
Loading
Loading
Loading
+97 −0
Original line number Diff line number Diff line
@@ -156,12 +156,109 @@ __xfrm6_find_acq(u8 mode, u32 reqid, u8 proto,
	return x0;
}

static int
__xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n)
{
	int i;
	int j = 0;

	/* Rule 1: select IPsec transport except AH */
	for (i = 0; i < n; i++) {
		if (src[i]->props.mode == XFRM_MODE_TRANSPORT &&
		    src[i]->id.proto != IPPROTO_AH) {
			dst[j++] = src[i];
			src[i] = NULL;
		}
	}
	if (j == n)
		goto end;

	/* XXX: Rule 2: select MIPv6 RO or inbound trigger */

	/* Rule 3: select IPsec transport AH */
	for (i = 0; i < n; i++) {
		if (src[i] &&
		    src[i]->props.mode == XFRM_MODE_TRANSPORT &&
		    src[i]->id.proto == IPPROTO_AH) {
			dst[j++] = src[i];
			src[i] = NULL;
		}
	}
	if (j == n)
		goto end;

	/* Rule 4: select IPsec tunnel */
	for (i = 0; i < n; i++) {
		if (src[i] &&
		    src[i]->props.mode == XFRM_MODE_TUNNEL) {
			dst[j++] = src[i];
			src[i] = NULL;
		}
	}
	if (likely(j == n))
		goto end;

	/* Final rule */
	for (i = 0; i < n; i++) {
		if (src[i]) {
			dst[j++] = src[i];
			src[i] = NULL;
		}
	}

 end:
	return 0;
}

static int
__xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n)
{
	int i;
	int j = 0;

	/* Rule 1: select IPsec transport */
	for (i = 0; i < n; i++) {
		if (src[i]->mode == XFRM_MODE_TRANSPORT) {
			dst[j++] = src[i];
			src[i] = NULL;
		}
	}
	if (j == n)
		goto end;

	/* XXX: Rule 2: select MIPv6 RO or inbound trigger */

	/* Rule 3: select IPsec tunnel */
	for (i = 0; i < n; i++) {
		if (src[i] &&
		    src[i]->mode == XFRM_MODE_TUNNEL) {
			dst[j++] = src[i];
			src[i] = NULL;
		}
	}
	if (likely(j == n))
		goto end;

	/* Final rule */
	for (i = 0; i < n; i++) {
		if (src[i]) {
			dst[j++] = src[i];
			src[i] = NULL;
		}
	}

 end:
	return 0;
}

static struct xfrm_state_afinfo xfrm6_state_afinfo = {
	.family			= AF_INET6,
	.init_tempsel		= __xfrm6_init_tempsel,
	.state_lookup		= __xfrm6_state_lookup,
	.state_lookup_byaddr	= __xfrm6_state_lookup_byaddr,
	.find_acq		= __xfrm6_find_acq,
	.tmpl_sort		= __xfrm6_tmpl_sort,
	.state_sort		= __xfrm6_state_sort,
};

void __init xfrm6_state_init(void)