[IPSEC] Add complete xfrm event notification
Heres the final patch. What this patch provides - netlink xfrm events - ability to have events generated by netlink propagated to pfkey and vice versa. - fixes the acquire lets-be-happy-with-one-success issue Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
committed by
David S. Miller
parent
3aa3dfb372
commit
26b15dad9f
@@ -50,7 +50,7 @@ static DEFINE_SPINLOCK(xfrm_state_gc_lock);
|
||||
|
||||
static int xfrm_state_gc_flush_bundles;
|
||||
|
||||
static void __xfrm_state_delete(struct xfrm_state *x);
|
||||
static int __xfrm_state_delete(struct xfrm_state *x);
|
||||
|
||||
static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
|
||||
static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
|
||||
@@ -215,8 +215,10 @@ void __xfrm_state_destroy(struct xfrm_state *x)
|
||||
}
|
||||
EXPORT_SYMBOL(__xfrm_state_destroy);
|
||||
|
||||
static void __xfrm_state_delete(struct xfrm_state *x)
|
||||
static int __xfrm_state_delete(struct xfrm_state *x)
|
||||
{
|
||||
int err = -ESRCH;
|
||||
|
||||
if (x->km.state != XFRM_STATE_DEAD) {
|
||||
x->km.state = XFRM_STATE_DEAD;
|
||||
spin_lock(&xfrm_state_lock);
|
||||
@@ -245,14 +247,21 @@ static void __xfrm_state_delete(struct xfrm_state *x)
|
||||
* is what we are dropping here.
|
||||
*/
|
||||
atomic_dec(&x->refcnt);
|
||||
err = 0;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void xfrm_state_delete(struct xfrm_state *x)
|
||||
int xfrm_state_delete(struct xfrm_state *x)
|
||||
{
|
||||
int err;
|
||||
|
||||
spin_lock_bh(&x->lock);
|
||||
__xfrm_state_delete(x);
|
||||
err = __xfrm_state_delete(x);
|
||||
spin_unlock_bh(&x->lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_state_delete);
|
||||
|
||||
@@ -796,34 +805,60 @@ EXPORT_SYMBOL(xfrm_replay_advance);
|
||||
static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list);
|
||||
static DEFINE_RWLOCK(xfrm_km_lock);
|
||||
|
||||
static void km_state_expired(struct xfrm_state *x, int hard)
|
||||
void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
|
||||
{
|
||||
struct xfrm_mgr *km;
|
||||
|
||||
read_lock(&xfrm_km_lock);
|
||||
list_for_each_entry(km, &xfrm_km_list, list)
|
||||
if (km->notify_policy)
|
||||
km->notify_policy(xp, dir, c);
|
||||
read_unlock(&xfrm_km_lock);
|
||||
}
|
||||
|
||||
void km_state_notify(struct xfrm_state *x, struct km_event *c)
|
||||
{
|
||||
struct xfrm_mgr *km;
|
||||
read_lock(&xfrm_km_lock);
|
||||
list_for_each_entry(km, &xfrm_km_list, list)
|
||||
if (km->notify)
|
||||
km->notify(x, c);
|
||||
read_unlock(&xfrm_km_lock);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(km_policy_notify);
|
||||
EXPORT_SYMBOL(km_state_notify);
|
||||
|
||||
static void km_state_expired(struct xfrm_state *x, int hard)
|
||||
{
|
||||
struct km_event c;
|
||||
|
||||
if (hard)
|
||||
x->km.state = XFRM_STATE_EXPIRED;
|
||||
else
|
||||
x->km.dying = 1;
|
||||
|
||||
read_lock(&xfrm_km_lock);
|
||||
list_for_each_entry(km, &xfrm_km_list, list)
|
||||
km->notify(x, hard);
|
||||
read_unlock(&xfrm_km_lock);
|
||||
c.data = hard;
|
||||
c.event = XFRM_SAP_EXPIRED;
|
||||
km_state_notify(x, &c);
|
||||
|
||||
if (hard)
|
||||
wake_up(&km_waitq);
|
||||
}
|
||||
|
||||
/*
|
||||
* We send to all registered managers regardless of failure
|
||||
* We are happy with one success
|
||||
*/
|
||||
static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol)
|
||||
{
|
||||
int err = -EINVAL;
|
||||
int err = -EINVAL, acqret;
|
||||
struct xfrm_mgr *km;
|
||||
|
||||
read_lock(&xfrm_km_lock);
|
||||
list_for_each_entry(km, &xfrm_km_list, list) {
|
||||
err = km->acquire(x, t, pol, XFRM_POLICY_OUT);
|
||||
if (!err)
|
||||
break;
|
||||
acqret = km->acquire(x, t, pol, XFRM_POLICY_OUT);
|
||||
if (!acqret)
|
||||
err = acqret;
|
||||
}
|
||||
read_unlock(&xfrm_km_lock);
|
||||
return err;
|
||||
@@ -848,13 +883,12 @@ EXPORT_SYMBOL(km_new_mapping);
|
||||
|
||||
void km_policy_expired(struct xfrm_policy *pol, int dir, int hard)
|
||||
{
|
||||
struct xfrm_mgr *km;
|
||||
struct km_event c;
|
||||
|
||||
read_lock(&xfrm_km_lock);
|
||||
list_for_each_entry(km, &xfrm_km_list, list)
|
||||
if (km->notify_policy)
|
||||
km->notify_policy(pol, dir, hard);
|
||||
read_unlock(&xfrm_km_lock);
|
||||
c.data = hard;
|
||||
c.data = hard;
|
||||
c.event = XFRM_SAP_EXPIRED;
|
||||
km_policy_notify(pol, dir, &c);
|
||||
|
||||
if (hard)
|
||||
wake_up(&km_waitq);
|
||||
|
Reference in New Issue
Block a user