#include <linux/module.h>
#include <asm/uaccess.h>
+struct sock *xfrm_nl;
+EXPORT_SYMBOL(xfrm_nl);
+
u32 sysctl_xfrm_aevent_etime = XFRM_AE_ETIME;
+EXPORT_SYMBOL(sysctl_xfrm_aevent_etime);
+
u32 sysctl_xfrm_aevent_rseqth = XFRM_AE_SEQT_SIZE;
+EXPORT_SYMBOL(sysctl_xfrm_aevent_rseqth);
+
/* Each xfrm_state may be linked to two tables:
1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl)
kfree(x->ealg);
kfree(x->calg);
kfree(x->encap);
+ if (x->mode)
+ xfrm_put_mode(x->mode);
if (x->type) {
x->type->destructor(x);
xfrm_put_type(x->type);
xfrm_state_put(x);
}
+static void xfrm_replay_timer_handler(unsigned long data);
+
struct xfrm_state *xfrm_state_alloc(void)
{
struct xfrm_state *x;
case XFRM_REPLAY_UPDATE:
if (x->replay_maxdiff &&
(x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
- (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff))
- return;
+ (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) {
+ if (x->xflags & XFRM_TIME_DEFER)
+ event = XFRM_REPLAY_TIMEOUT;
+ else
+ return;
+ }
break;
case XFRM_REPLAY_TIMEOUT:
if ((x->replay.seq == x->preplay.seq) &&
(x->replay.bitmap == x->preplay.bitmap) &&
- (x->replay.oseq == x->preplay.oseq))
+ (x->replay.oseq == x->preplay.oseq)) {
+ x->xflags |= XFRM_TIME_DEFER;
return;
+ }
break;
}
c.data.aevent = event;
km_state_notify(x, &c);
-resched:
if (x->replay_maxage &&
- !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
+ !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) {
xfrm_state_hold(x);
-
+ x->xflags &= ~XFRM_TIME_DEFER;
+ }
}
+EXPORT_SYMBOL(xfrm_replay_notify);
static void xfrm_replay_timer_handler(unsigned long data)
{
spin_lock(&x->lock);
- if (xfrm_aevent_is_on() && x->km.state == XFRM_STATE_VALID)
- xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT);
+ if (x->km.state == XFRM_STATE_VALID) {
+ if (xfrm_aevent_is_on())
+ xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT);
+ else
+ x->xflags |= XFRM_TIME_DEFER;
+ }
spin_unlock(&x->lock);
+ xfrm_state_put(x);
}
int xfrm_replay_check(struct xfrm_state *x, u32 seq)
if (hard)
wake_up(&km_waitq);
}
+EXPORT_SYMBOL(km_policy_expired);
int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen)
{
return -EINVAL;
if (unlikely(afinfo->family >= NPROTO))
return -EAFNOSUPPORT;
- write_lock(&xfrm_state_afinfo_lock);
+ write_lock_bh(&xfrm_state_afinfo_lock);
if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL))
err = -ENOBUFS;
else {
afinfo->state_byspi = xfrm_state_byspi;
xfrm_state_afinfo[afinfo->family] = afinfo;
}
- write_unlock(&xfrm_state_afinfo_lock);
+ write_unlock_bh(&xfrm_state_afinfo_lock);
return err;
}
EXPORT_SYMBOL(xfrm_state_register_afinfo);
return -EINVAL;
if (unlikely(afinfo->family >= NPROTO))
return -EAFNOSUPPORT;
- write_lock(&xfrm_state_afinfo_lock);
+ write_lock_bh(&xfrm_state_afinfo_lock);
if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) {
if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo))
err = -EINVAL;
afinfo->state_bydst = NULL;
}
}
- write_unlock(&xfrm_state_afinfo_lock);
+ write_unlock_bh(&xfrm_state_afinfo_lock);
return err;
}
EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
return NULL;
read_lock(&xfrm_state_afinfo_lock);
afinfo = xfrm_state_afinfo[family];
- if (likely(afinfo != NULL))
- read_lock(&afinfo->lock);
- read_unlock(&xfrm_state_afinfo_lock);
+ if (unlikely(!afinfo))
+ read_unlock(&xfrm_state_afinfo_lock);
return afinfo;
}
static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
{
- if (unlikely(afinfo == NULL))
- return;
- read_unlock(&afinfo->lock);
+ read_unlock(&xfrm_state_afinfo_lock);
}
/* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */
if (err)
goto error;
+ x->mode = xfrm_get_mode(x->props.mode, family);
+ if (x->mode == NULL)
+ goto error;
+
x->km.state = XFRM_STATE_VALID;
error: