Commit cc621e11 authored by James Morris's avatar James Morris

Merge intercode.com.au:/home/jmorris/bk/net/ipsec-2.5

into intercode.com.au:/home/jmorris/bk/net/net-2.5
parents 352321cb e821464c
...@@ -767,7 +767,8 @@ extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t ...@@ -767,7 +767,8 @@ extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t
unsigned short family); unsigned short family);
extern int xfrm_state_check_expire(struct xfrm_state *x); extern int xfrm_state_check_expire(struct xfrm_state *x);
extern void xfrm_state_insert(struct xfrm_state *x); extern void xfrm_state_insert(struct xfrm_state *x);
extern int xfrm_state_replace(struct xfrm_state *x, int excl); extern int xfrm_state_add(struct xfrm_state *x);
extern int xfrm_state_update(struct xfrm_state *x);
extern int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb); extern int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb);
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_find_acq_byseq(u32 seq); extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
......
...@@ -1221,7 +1221,11 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, ...@@ -1221,7 +1221,11 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
if (IS_ERR(x)) if (IS_ERR(x))
return PTR_ERR(x); return PTR_ERR(x);
err = xfrm_state_replace(x, hdr->sadb_msg_type == SADB_ADD); if (hdr->sadb_msg_type == SADB_ADD)
err = xfrm_state_add(x);
else
err = xfrm_state_update(x);
if (err < 0) { if (err < 0) {
x->km.state = XFRM_STATE_DEAD; x->km.state = XFRM_STATE_DEAD;
xfrm_state_put(x); xfrm_state_put(x);
......
...@@ -306,7 +306,8 @@ EXPORT_SYMBOL(xfrm_state_alloc); ...@@ -306,7 +306,8 @@ EXPORT_SYMBOL(xfrm_state_alloc);
EXPORT_SYMBOL(__xfrm_state_destroy); EXPORT_SYMBOL(__xfrm_state_destroy);
EXPORT_SYMBOL(xfrm_state_find); EXPORT_SYMBOL(xfrm_state_find);
EXPORT_SYMBOL(xfrm_state_insert); EXPORT_SYMBOL(xfrm_state_insert);
EXPORT_SYMBOL(xfrm_state_replace); EXPORT_SYMBOL(xfrm_state_add);
EXPORT_SYMBOL(xfrm_state_update);
EXPORT_SYMBOL(xfrm_state_check_expire); EXPORT_SYMBOL(xfrm_state_check_expire);
EXPORT_SYMBOL(xfrm_state_check_space); EXPORT_SYMBOL(xfrm_state_check_space);
EXPORT_SYMBOL(xfrm_state_lookup); EXPORT_SYMBOL(xfrm_state_lookup);
......
...@@ -395,49 +395,110 @@ void xfrm_state_insert(struct xfrm_state *x) ...@@ -395,49 +395,110 @@ void xfrm_state_insert(struct xfrm_state *x)
spin_unlock_bh(&xfrm_state_lock); spin_unlock_bh(&xfrm_state_lock);
} }
int xfrm_state_replace(struct xfrm_state *x, int excl) int xfrm_state_add(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;
afinfo = xfrm_state_get_afinfo(x->props.family); afinfo = xfrm_state_get_afinfo(x->props.family);
x1 = NULL; if (unlikely(afinfo == NULL))
return -EAFNOSUPPORT;
spin_lock_bh(&xfrm_state_lock); spin_lock_bh(&xfrm_state_lock);
if (afinfo) { x1 = afinfo->state_lookup(&x->id.daddr, x->id.spi, x->id.proto);
x1 = afinfo->state_lookup(&x->id.daddr, x->id.spi, x->id.proto); if (!x1) {
if (!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); if (x1 && x1->id.spi != x->id.spi && x1->id.spi) {
if (x1 && x1->id.spi != x->id.spi && x1->id.spi) {
xfrm_state_put(x1);
x1 = NULL;
}
}
if (x1 && (excl ? x1->id.spi : xfrm_state_kern(x1))) {
xfrm_state_put(x1); xfrm_state_put(x1);
x1 = NULL; x1 = NULL;
err = -EEXIST;
goto out;
} }
} }
if (x1 && x1->id.spi) {
xfrm_state_put(x1);
x1 = NULL;
err = -EEXIST;
goto out;
}
__xfrm_state_insert(x); __xfrm_state_insert(x);
err = 0; err = 0;
out: out:
spin_unlock_bh(&xfrm_state_lock); spin_unlock_bh(&xfrm_state_lock);
xfrm_state_put_afinfo(afinfo);
if (x1) { if (x1) {
xfrm_state_delete(x1); xfrm_state_delete(x1);
xfrm_state_put(x1); xfrm_state_put(x1);
} }
return err;
}
int xfrm_state_update(struct xfrm_state *x)
{
struct xfrm_state_afinfo *afinfo;
struct xfrm_state *x1;
int err;
afinfo = xfrm_state_get_afinfo(x->props.family);
if (unlikely(afinfo == NULL))
return -EAFNOSUPPORT;
spin_lock_bh(&xfrm_state_lock);
x1 = afinfo->state_lookup(&x->id.daddr, x->id.spi, x->id.proto);
err = -ESRCH;
if (!x1)
goto out;
if (xfrm_state_kern(x1)) {
xfrm_state_put(x1);
err = -EEXIST;
goto out;
}
if (x1->km.state == XFRM_STATE_ACQ) {
__xfrm_state_insert(x);
x = NULL;
}
err = 0;
out:
spin_unlock_bh(&xfrm_state_lock);
xfrm_state_put_afinfo(afinfo); xfrm_state_put_afinfo(afinfo);
if (err)
return err;
if (!x) {
xfrm_state_delete(x1);
xfrm_state_put(x1);
return 0;
}
err = -EINVAL;
spin_lock_bh(&x1->lock);
if (likely(x1->km.state == XFRM_STATE_VALID)) {
memcpy(x1->encap, x->encap, sizeof(*x1->encap));
memcpy(&x1->lft, &x->lft, sizeof(x1->lft));
x1->km.dying = 0;
err = 0;
}
spin_unlock_bh(&x1->lock);
if (!mod_timer(&x1->timer, jiffies + HZ))
xfrm_state_hold(x1);
if (x1->curlft.use_time)
xfrm_state_check_expire(x1);
xfrm_state_put(x1);
return err; return err;
} }
......
...@@ -260,7 +260,11 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) ...@@ -260,7 +260,11 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
if (!x) if (!x)
return err; return err;
err = xfrm_state_replace(x, nlh->nlmsg_type == XFRM_MSG_NEWSA); if (nlh->nlmsg_type == XFRM_MSG_NEWSA)
err = xfrm_state_add(x);
else
err = xfrm_state_update(x);
if (err < 0) { if (err < 0) {
x->km.state = XFRM_STATE_DEAD; x->km.state = XFRM_STATE_DEAD;
xfrm_state_put(x); xfrm_state_put(x);
......
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