xfrm_put_type(x->type);
}
kfree(x);
+ wake_up(&km_waitq);
}
static void xfrm_state_gc_task(void *data)
x = list_entry(entry, struct xfrm_state, bydst);
xfrm_state_gc_destroy(x);
}
- wake_up(&km_waitq);
}
static inline unsigned long make_jiffies(long secs)
spin_lock_bh(&xfrm_state_lock);
x1 = afinfo->state_lookup(&x->id.daddr, x->id.spi, x->id.proto);
- if (x1) {
+ if (!x1) {
+ x1 = afinfo->find_acq(
+ x->props.mode, x->props.reqid, x->id.proto,
+ &x->id.daddr, &x->props.saddr, 0);
+ if (x1 && x1->id.spi != x->id.spi && x1->id.spi) {
+ xfrm_state_put(x1);
+ x1 = NULL;
+ }
+ }
+
+ if (x1 && x1->id.spi) {
xfrm_state_put(x1);
x1 = NULL;
err = -EEXIST;
goto out;
}
- x1 = afinfo->find_acq(
- x->props.mode, x->props.reqid, x->id.proto,
- &x->id.daddr, &x->props.saddr, 0);
-
__xfrm_state_insert(x);
err = 0;
for (h=0; h<maxspi-minspi+1; h++) {
spi = minspi + net_random()%(maxspi-minspi+1);
x0 = xfrm_state_lookup(&x->id.daddr, htonl(spi), x->id.proto, x->props.family);
- if (x0 == NULL) {
- x->id.spi = htonl(spi);
+ if (x0 == NULL)
break;
- }
xfrm_state_put(x0);
}
+ x->id.spi = htonl(spi);
}
if (x->id.spi) {
spin_lock_bh(&xfrm_state_lock);