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

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

[XFRM] STATE: Search by address using source address list.



This is a support to search transformation states by its addresses
by using source address list for Mobile IPv6 usage.
To use it from user-space, it is also added a message type for
source address as a xfrm state option.
Based on MIPL2 kernel patch.

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 6c44e6b7
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -234,6 +234,7 @@ enum xfrm_attr_type_t {
	XFRMA_REPLAY_VAL,
	XFRMA_REPLAY_VAL,
	XFRMA_REPLAY_THRESH,
	XFRMA_REPLAY_THRESH,
	XFRMA_ETIMER_THRESH,
	XFRMA_ETIMER_THRESH,
	XFRMA_SRCADDR,		/* xfrm_address_t */
	__XFRMA_MAX
	__XFRMA_MAX


#define XFRMA_MAX (__XFRMA_MAX - 1)
#define XFRMA_MAX (__XFRMA_MAX - 1)
+2 −0
Original line number Original line Diff line number Diff line
@@ -244,6 +244,7 @@ struct xfrm_state_afinfo {
						struct xfrm_tmpl *tmpl,
						struct xfrm_tmpl *tmpl,
						xfrm_address_t *daddr, xfrm_address_t *saddr);
						xfrm_address_t *daddr, xfrm_address_t *saddr);
	struct xfrm_state	*(*state_lookup)(xfrm_address_t *daddr, u32 spi, u8 proto);
	struct xfrm_state	*(*state_lookup)(xfrm_address_t *daddr, u32 spi, u8 proto);
	struct xfrm_state	*(*state_lookup_byaddr)(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto);
	struct xfrm_state	*(*find_acq)(u8 mode, u32 reqid, u8 proto, 
	struct xfrm_state	*(*find_acq)(u8 mode, u32 reqid, u8 proto, 
					     xfrm_address_t *daddr, xfrm_address_t *saddr, 
					     xfrm_address_t *daddr, xfrm_address_t *saddr, 
					     int create);
					     int create);
@@ -937,6 +938,7 @@ extern void xfrm_state_insert(struct xfrm_state *x);
extern int xfrm_state_add(struct xfrm_state *x);
extern int xfrm_state_add(struct xfrm_state *x);
extern int xfrm_state_update(struct xfrm_state *x);
extern int xfrm_state_update(struct xfrm_state *x);
extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family);
extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family);
extern struct xfrm_state *xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family);
extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
extern int xfrm_state_delete(struct xfrm_state *x);
extern int xfrm_state_delete(struct xfrm_state *x);
extern void xfrm_state_flush(u8 proto);
extern void xfrm_state_flush(u8 proto);
+9 −0
Original line number Original line Diff line number Diff line
@@ -80,6 +80,14 @@ __xfrm4_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto)
	return NULL;
	return NULL;
}
}


/* placeholder until ipv4's code is written */
static struct xfrm_state *
__xfrm4_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr,
			    u8 proto)
{
	return NULL;
}

static struct xfrm_state *
static struct xfrm_state *
__xfrm4_find_acq(u8 mode, u32 reqid, u8 proto, 
__xfrm4_find_acq(u8 mode, u32 reqid, u8 proto, 
		 xfrm_address_t *daddr, xfrm_address_t *saddr, 
		 xfrm_address_t *daddr, xfrm_address_t *saddr, 
@@ -137,6 +145,7 @@ static struct xfrm_state_afinfo xfrm4_state_afinfo = {
	.init_flags		= xfrm4_init_flags,
	.init_flags		= xfrm4_init_flags,
	.init_tempsel		= __xfrm4_init_tempsel,
	.init_tempsel		= __xfrm4_init_tempsel,
	.state_lookup		= __xfrm4_state_lookup,
	.state_lookup		= __xfrm4_state_lookup,
	.state_lookup_byaddr	= __xfrm4_state_lookup_byaddr,
	.find_acq		= __xfrm4_find_acq,
	.find_acq		= __xfrm4_find_acq,
};
};


+21 −0
Original line number Original line Diff line number Diff line
@@ -63,6 +63,26 @@ __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl,
	x->props.family = AF_INET6;
	x->props.family = AF_INET6;
}
}


static struct xfrm_state *
__xfrm6_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr,
			    u8 proto)
{
	struct xfrm_state *x = NULL;
	unsigned h;

	h = __xfrm6_src_hash(saddr);
	list_for_each_entry(x, xfrm6_state_afinfo.state_bysrc+h, bysrc) {
		if (x->props.family == AF_INET6 &&
		    ipv6_addr_equal((struct in6_addr *)daddr, (struct in6_addr *)x->id.daddr.a6) &&
		    ipv6_addr_equal((struct in6_addr *)saddr, (struct in6_addr *)x->props.saddr.a6) &&
		    proto == x->id.proto) {
			xfrm_state_hold(x);
			return x;
		}
	}
	return NULL;
}

static struct xfrm_state *
static struct xfrm_state *
__xfrm6_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto)
__xfrm6_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto)
{
{
@@ -140,6 +160,7 @@ static struct xfrm_state_afinfo xfrm6_state_afinfo = {
	.family			= AF_INET6,
	.family			= AF_INET6,
	.init_tempsel		= __xfrm6_init_tempsel,
	.init_tempsel		= __xfrm6_init_tempsel,
	.state_lookup		= __xfrm6_state_lookup,
	.state_lookup		= __xfrm6_state_lookup,
	.state_lookup_byaddr	= __xfrm6_state_lookup_byaddr,
	.find_acq		= __xfrm6_find_acq,
	.find_acq		= __xfrm6_find_acq,
};
};


+33 −4
Original line number Original line Diff line number Diff line
@@ -487,6 +487,16 @@ void xfrm_state_insert(struct xfrm_state *x)
}
}
EXPORT_SYMBOL(xfrm_state_insert);
EXPORT_SYMBOL(xfrm_state_insert);


static inline struct xfrm_state *
__xfrm_state_locate(struct xfrm_state_afinfo *afinfo, struct xfrm_state *x,
		    int use_spi)
{
	if (use_spi)
		return afinfo->state_lookup(&x->id.daddr, x->id.spi, x->id.proto);
	else
		return afinfo->state_lookup_byaddr(&x->id.daddr, &x->props.saddr, x->id.proto);
}

static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq);
static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq);


int xfrm_state_add(struct xfrm_state *x)
int xfrm_state_add(struct xfrm_state *x)
@@ -495,6 +505,7 @@ int xfrm_state_add(struct xfrm_state *x)
	struct xfrm_state *x1;
	struct xfrm_state *x1;
	int family;
	int family;
	int err;
	int err;
	int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);


	family = x->props.family;
	family = x->props.family;
	afinfo = xfrm_state_get_afinfo(family);
	afinfo = xfrm_state_get_afinfo(family);
@@ -503,7 +514,7 @@ int xfrm_state_add(struct xfrm_state *x)


	spin_lock_bh(&xfrm_state_lock);
	spin_lock_bh(&xfrm_state_lock);


	x1 = afinfo->state_lookup(&x->id.daddr, x->id.spi, x->id.proto);
	x1 = __xfrm_state_locate(afinfo, x, use_spi);
	if (x1) {
	if (x1) {
		xfrm_state_put(x1);
		xfrm_state_put(x1);
		x1 = NULL;
		x1 = NULL;
@@ -511,7 +522,7 @@ int xfrm_state_add(struct xfrm_state *x)
		goto out;
		goto out;
	}
	}


	if (x->km.seq) {
	if (use_spi && x->km.seq) {
		x1 = __xfrm_find_acq_byseq(x->km.seq);
		x1 = __xfrm_find_acq_byseq(x->km.seq);
		if (x1 && xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family)) {
		if (x1 && xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family)) {
			xfrm_state_put(x1);
			xfrm_state_put(x1);
@@ -519,7 +530,7 @@ int xfrm_state_add(struct xfrm_state *x)
		}
		}
	}
	}


	if (!x1)
	if (use_spi && !x1)
		x1 = afinfo->find_acq(
		x1 = afinfo->find_acq(
			x->props.mode, x->props.reqid, x->id.proto,
			x->props.mode, x->props.reqid, x->id.proto,
			&x->id.daddr, &x->props.saddr, 0);
			&x->id.daddr, &x->props.saddr, 0);
@@ -548,13 +559,14 @@ int xfrm_state_update(struct xfrm_state *x)
	struct xfrm_state_afinfo *afinfo;
	struct xfrm_state_afinfo *afinfo;
	struct xfrm_state *x1;
	struct xfrm_state *x1;
	int err;
	int err;
	int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);


	afinfo = xfrm_state_get_afinfo(x->props.family);
	afinfo = xfrm_state_get_afinfo(x->props.family);
	if (unlikely(afinfo == NULL))
	if (unlikely(afinfo == NULL))
		return -EAFNOSUPPORT;
		return -EAFNOSUPPORT;


	spin_lock_bh(&xfrm_state_lock);
	spin_lock_bh(&xfrm_state_lock);
	x1 = afinfo->state_lookup(&x->id.daddr, x->id.spi, x->id.proto);
	x1 = __xfrm_state_locate(afinfo, x, use_spi);


	err = -ESRCH;
	err = -ESRCH;
	if (!x1)
	if (!x1)
@@ -674,6 +686,23 @@ xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto,
}
}
EXPORT_SYMBOL(xfrm_state_lookup);
EXPORT_SYMBOL(xfrm_state_lookup);


struct xfrm_state *
xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr,
			 u8 proto, unsigned short family)
{
	struct xfrm_state *x;
	struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
	if (!afinfo)
		return NULL;

	spin_lock_bh(&xfrm_state_lock);
	x = afinfo->state_lookup_byaddr(daddr, saddr, proto);
	spin_unlock_bh(&xfrm_state_lock);
	xfrm_state_put_afinfo(afinfo);
	return x;
}
EXPORT_SYMBOL(xfrm_state_lookup_byaddr);

struct xfrm_state *
struct xfrm_state *
xfrm_find_acq(u8 mode, u32 reqid, u8 proto, 
xfrm_find_acq(u8 mode, u32 reqid, u8 proto, 
	      xfrm_address_t *daddr, xfrm_address_t *saddr, 
	      xfrm_address_t *daddr, xfrm_address_t *saddr, 
Loading