aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_state.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm/xfrm_state.c')
-rw-r--r--net/xfrm/xfrm_state.c74
1 files changed, 54 insertions, 20 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index d11747c2a763..918a94c552a5 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -50,7 +50,7 @@ static DEFINE_SPINLOCK(xfrm_state_gc_lock);
50 50
51static int xfrm_state_gc_flush_bundles; 51static int xfrm_state_gc_flush_bundles;
52 52
53static void __xfrm_state_delete(struct xfrm_state *x); 53static int __xfrm_state_delete(struct xfrm_state *x);
54 54
55static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family); 55static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
56static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); 56static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
@@ -215,8 +215,10 @@ void __xfrm_state_destroy(struct xfrm_state *x)
215} 215}
216EXPORT_SYMBOL(__xfrm_state_destroy); 216EXPORT_SYMBOL(__xfrm_state_destroy);
217 217
218static void __xfrm_state_delete(struct xfrm_state *x) 218static int __xfrm_state_delete(struct xfrm_state *x)
219{ 219{
220 int err = -ESRCH;
221
220 if (x->km.state != XFRM_STATE_DEAD) { 222 if (x->km.state != XFRM_STATE_DEAD) {
221 x->km.state = XFRM_STATE_DEAD; 223 x->km.state = XFRM_STATE_DEAD;
222 spin_lock(&xfrm_state_lock); 224 spin_lock(&xfrm_state_lock);
@@ -245,14 +247,21 @@ static void __xfrm_state_delete(struct xfrm_state *x)
245 * is what we are dropping here. 247 * is what we are dropping here.
246 */ 248 */
247 atomic_dec(&x->refcnt); 249 atomic_dec(&x->refcnt);
250 err = 0;
248 } 251 }
252
253 return err;
249} 254}
250 255
251void xfrm_state_delete(struct xfrm_state *x) 256int xfrm_state_delete(struct xfrm_state *x)
252{ 257{
258 int err;
259
253 spin_lock_bh(&x->lock); 260 spin_lock_bh(&x->lock);
254 __xfrm_state_delete(x); 261 err = __xfrm_state_delete(x);
255 spin_unlock_bh(&x->lock); 262 spin_unlock_bh(&x->lock);
263
264 return err;
256} 265}
257EXPORT_SYMBOL(xfrm_state_delete); 266EXPORT_SYMBOL(xfrm_state_delete);
258 267
@@ -796,34 +805,60 @@ EXPORT_SYMBOL(xfrm_replay_advance);
796static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list); 805static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list);
797static DEFINE_RWLOCK(xfrm_km_lock); 806static DEFINE_RWLOCK(xfrm_km_lock);
798 807
799static void km_state_expired(struct xfrm_state *x, int hard) 808void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
800{ 809{
801 struct xfrm_mgr *km; 810 struct xfrm_mgr *km;
802 811
803 if (hard) 812 read_lock(&xfrm_km_lock);
804 x->km.state = XFRM_STATE_EXPIRED; 813 list_for_each_entry(km, &xfrm_km_list, list)
805 else 814 if (km->notify_policy)
806 x->km.dying = 1; 815 km->notify_policy(xp, dir, c);
816 read_unlock(&xfrm_km_lock);
817}
807 818
819void km_state_notify(struct xfrm_state *x, struct km_event *c)
820{
821 struct xfrm_mgr *km;
808 read_lock(&xfrm_km_lock); 822 read_lock(&xfrm_km_lock);
809 list_for_each_entry(km, &xfrm_km_list, list) 823 list_for_each_entry(km, &xfrm_km_list, list)
810 km->notify(x, hard); 824 if (km->notify)
825 km->notify(x, c);
811 read_unlock(&xfrm_km_lock); 826 read_unlock(&xfrm_km_lock);
827}
828
829EXPORT_SYMBOL(km_policy_notify);
830EXPORT_SYMBOL(km_state_notify);
831
832static void km_state_expired(struct xfrm_state *x, int hard)
833{
834 struct km_event c;
835
836 if (hard)
837 x->km.state = XFRM_STATE_EXPIRED;
838 else
839 x->km.dying = 1;
840 c.data = hard;
841 c.event = XFRM_SAP_EXPIRED;
842 km_state_notify(x, &c);
812 843
813 if (hard) 844 if (hard)
814 wake_up(&km_waitq); 845 wake_up(&km_waitq);
815} 846}
816 847
848/*
849 * We send to all registered managers regardless of failure
850 * We are happy with one success
851*/
817static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol) 852static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol)
818{ 853{
819 int err = -EINVAL; 854 int err = -EINVAL, acqret;
820 struct xfrm_mgr *km; 855 struct xfrm_mgr *km;
821 856
822 read_lock(&xfrm_km_lock); 857 read_lock(&xfrm_km_lock);
823 list_for_each_entry(km, &xfrm_km_list, list) { 858 list_for_each_entry(km, &xfrm_km_list, list) {
824 err = km->acquire(x, t, pol, XFRM_POLICY_OUT); 859 acqret = km->acquire(x, t, pol, XFRM_POLICY_OUT);
825 if (!err) 860 if (!acqret)
826 break; 861 err = acqret;
827 } 862 }
828 read_unlock(&xfrm_km_lock); 863 read_unlock(&xfrm_km_lock);
829 return err; 864 return err;
@@ -848,13 +883,12 @@ EXPORT_SYMBOL(km_new_mapping);
848 883
849void km_policy_expired(struct xfrm_policy *pol, int dir, int hard) 884void km_policy_expired(struct xfrm_policy *pol, int dir, int hard)
850{ 885{
851 struct xfrm_mgr *km; 886 struct km_event c;
852 887
853 read_lock(&xfrm_km_lock); 888 c.data = hard;
854 list_for_each_entry(km, &xfrm_km_list, list) 889 c.data = hard;
855 if (km->notify_policy) 890 c.event = XFRM_SAP_EXPIRED;
856 km->notify_policy(pol, dir, hard); 891 km_policy_notify(pol, dir, &c);
857 read_unlock(&xfrm_km_lock);
858 892
859 if (hard) 893 if (hard)
860 wake_up(&km_waitq); 894 wake_up(&km_waitq);