[IPSEC] xfrm: Abstract out encapsulation modes
This patch adds the structure xfrm_mode. It is meant to represent the operations carried out by transport/tunnel modes. By doing this we allow additional encapsulation modes to be added without clogging up the xfrm_input/xfrm_output paths. Candidate modes include 4-to-6 tunnel mode, 6-to-4 tunnel mode, and BEET modes. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
546be2405b
commit
b59f45d0b2
@@ -138,6 +138,89 @@ void xfrm_put_type(struct xfrm_type *type)
|
||||
module_put(type->owner);
|
||||
}
|
||||
|
||||
int xfrm_register_mode(struct xfrm_mode *mode, int family)
|
||||
{
|
||||
struct xfrm_policy_afinfo *afinfo;
|
||||
struct xfrm_mode **modemap;
|
||||
int err;
|
||||
|
||||
if (unlikely(mode->encap >= XFRM_MODE_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
afinfo = xfrm_policy_lock_afinfo(family);
|
||||
if (unlikely(afinfo == NULL))
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
err = -EEXIST;
|
||||
modemap = afinfo->mode_map;
|
||||
if (likely(modemap[mode->encap] == NULL)) {
|
||||
modemap[mode->encap] = mode;
|
||||
err = 0;
|
||||
}
|
||||
|
||||
xfrm_policy_unlock_afinfo(afinfo);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_register_mode);
|
||||
|
||||
int xfrm_unregister_mode(struct xfrm_mode *mode, int family)
|
||||
{
|
||||
struct xfrm_policy_afinfo *afinfo;
|
||||
struct xfrm_mode **modemap;
|
||||
int err;
|
||||
|
||||
if (unlikely(mode->encap >= XFRM_MODE_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
afinfo = xfrm_policy_lock_afinfo(family);
|
||||
if (unlikely(afinfo == NULL))
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
err = -ENOENT;
|
||||
modemap = afinfo->mode_map;
|
||||
if (likely(modemap[mode->encap] == mode)) {
|
||||
modemap[mode->encap] = NULL;
|
||||
err = 0;
|
||||
}
|
||||
|
||||
xfrm_policy_unlock_afinfo(afinfo);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_unregister_mode);
|
||||
|
||||
struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family)
|
||||
{
|
||||
struct xfrm_policy_afinfo *afinfo;
|
||||
struct xfrm_mode *mode;
|
||||
int modload_attempted = 0;
|
||||
|
||||
if (unlikely(encap >= XFRM_MODE_MAX))
|
||||
return NULL;
|
||||
|
||||
retry:
|
||||
afinfo = xfrm_policy_get_afinfo(family);
|
||||
if (unlikely(afinfo == NULL))
|
||||
return NULL;
|
||||
|
||||
mode = afinfo->mode_map[encap];
|
||||
if (unlikely(mode && !try_module_get(mode->owner)))
|
||||
mode = NULL;
|
||||
if (!mode && !modload_attempted) {
|
||||
xfrm_policy_put_afinfo(afinfo);
|
||||
request_module("xfrm-mode-%d-%d", family, encap);
|
||||
modload_attempted = 1;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
xfrm_policy_put_afinfo(afinfo);
|
||||
return mode;
|
||||
}
|
||||
|
||||
void xfrm_put_mode(struct xfrm_mode *mode)
|
||||
{
|
||||
module_put(mode->owner);
|
||||
}
|
||||
|
||||
static inline unsigned long make_jiffies(long secs)
|
||||
{
|
||||
if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ)
|
||||
|
Reference in New Issue
Block a user