Commit 41a49cc3 authored by Masahide NAKAMURA's avatar Masahide NAKAMURA Committed by David S. Miller

[XFRM]: Add sorting interface for state and template.

Under two transformation policies it is required to merge them.
This is a platform to sort state for outbound and templates
for inbound respectively.
It will be used when Mobile IPv6 and IPsec are used at the same time.
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 4e81bb83
...@@ -254,6 +254,8 @@ struct xfrm_state_afinfo { ...@@ -254,6 +254,8 @@ struct xfrm_state_afinfo {
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);
int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
}; };
extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo); extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo);
...@@ -1002,6 +1004,24 @@ extern int xfrm_state_add(struct xfrm_state *x); ...@@ -1002,6 +1004,24 @@ 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_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family);
#ifdef CONFIG_XFRM_SUB_POLICY
extern int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src,
int n, unsigned short family);
extern int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src,
int n, unsigned short family);
#else
static inline int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src,
int n, unsigned short family)
{
return -ENOSYS;
}
static inline int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src,
int n, unsigned short family)
{
return -ENOSYS;
}
#endif
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);
......
...@@ -861,6 +861,8 @@ xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, struct flowi *fl, ...@@ -861,6 +861,8 @@ xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, struct flowi *fl,
struct xfrm_state **xfrm, struct xfrm_state **xfrm,
unsigned short family) unsigned short family)
{ {
struct xfrm_state *tp[XFRM_MAX_DEPTH];
struct xfrm_state **tpp = (npols > 1) ? tp : xfrm;
int cnx = 0; int cnx = 0;
int error; int error;
int ret; int ret;
...@@ -871,7 +873,8 @@ xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, struct flowi *fl, ...@@ -871,7 +873,8 @@ xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, struct flowi *fl,
error = -ENOBUFS; error = -ENOBUFS;
goto fail; goto fail;
} }
ret = xfrm_tmpl_resolve_one(pols[i], fl, &xfrm[cnx], family);
ret = xfrm_tmpl_resolve_one(pols[i], fl, &tpp[cnx], family);
if (ret < 0) { if (ret < 0) {
error = ret; error = ret;
goto fail; goto fail;
...@@ -879,11 +882,15 @@ xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, struct flowi *fl, ...@@ -879,11 +882,15 @@ xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, struct flowi *fl,
cnx += ret; cnx += ret;
} }
/* found states are sorted for outbound processing */
if (npols > 1)
xfrm_state_sort(xfrm, tpp, cnx, family);
return cnx; return cnx;
fail: fail:
for (cnx--; cnx>=0; cnx--) for (cnx--; cnx>=0; cnx--)
xfrm_state_put(xfrm[cnx]); xfrm_state_put(tpp[cnx]);
return error; return error;
} }
...@@ -1280,6 +1287,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, ...@@ -1280,6 +1287,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
struct sec_path *sp; struct sec_path *sp;
static struct sec_path dummy; static struct sec_path dummy;
struct xfrm_tmpl *tp[XFRM_MAX_DEPTH]; struct xfrm_tmpl *tp[XFRM_MAX_DEPTH];
struct xfrm_tmpl *stp[XFRM_MAX_DEPTH];
struct xfrm_tmpl **tpp = tp; struct xfrm_tmpl **tpp = tp;
int ti = 0; int ti = 0;
int i, k; int i, k;
...@@ -1297,6 +1305,10 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, ...@@ -1297,6 +1305,10 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
tpp[ti++] = &pols[pi]->xfrm_vec[i]; tpp[ti++] = &pols[pi]->xfrm_vec[i];
} }
xfrm_nr = ti; xfrm_nr = ti;
if (npols > 1) {
xfrm_tmpl_sort(stp, tpp, xfrm_nr, family);
tpp = stp;
}
/* For each tunnel xfrm, find the first matching tmpl. /* For each tunnel xfrm, find the first matching tmpl.
* For each tmpl before that, find corresponding xfrm. * For each tmpl before that, find corresponding xfrm.
......
...@@ -728,6 +728,44 @@ xfrm_find_acq(u8 mode, u32 reqid, u8 proto, ...@@ -728,6 +728,44 @@ xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
} }
EXPORT_SYMBOL(xfrm_find_acq); EXPORT_SYMBOL(xfrm_find_acq);
#ifdef CONFIG_XFRM_SUB_POLICY
int
xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n,
unsigned short family)
{
int err = 0;
struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
if (!afinfo)
return -EAFNOSUPPORT;
spin_lock_bh(&xfrm_state_lock);
if (afinfo->tmpl_sort)
err = afinfo->tmpl_sort(dst, src, n);
spin_unlock_bh(&xfrm_state_lock);
xfrm_state_put_afinfo(afinfo);
return err;
}
EXPORT_SYMBOL(xfrm_tmpl_sort);
int
xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n,
unsigned short family)
{
int err = 0;
struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
if (!afinfo)
return -EAFNOSUPPORT;
spin_lock_bh(&xfrm_state_lock);
if (afinfo->state_sort)
err = afinfo->state_sort(dst, src, n);
spin_unlock_bh(&xfrm_state_lock);
xfrm_state_put_afinfo(afinfo);
return err;
}
EXPORT_SYMBOL(xfrm_state_sort);
#endif
/* Silly enough, but I'm lazy to build resolution list */ /* Silly enough, but I'm lazy to build resolution list */
static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq) static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment