diff options
Diffstat (limited to 'net/xfrm/xfrm_state.c')
-rw-r--r-- | net/xfrm/xfrm_state.c | 74 |
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 | ||
51 | static int xfrm_state_gc_flush_bundles; | 51 | static int xfrm_state_gc_flush_bundles; |
52 | 52 | ||
53 | static void __xfrm_state_delete(struct xfrm_state *x); | 53 | static int __xfrm_state_delete(struct xfrm_state *x); |
54 | 54 | ||
55 | static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family); | 55 | static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family); |
56 | static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); | 56 | static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); |
@@ -215,8 +215,10 @@ void __xfrm_state_destroy(struct xfrm_state *x) | |||
215 | } | 215 | } |
216 | EXPORT_SYMBOL(__xfrm_state_destroy); | 216 | EXPORT_SYMBOL(__xfrm_state_destroy); |
217 | 217 | ||
218 | static void __xfrm_state_delete(struct xfrm_state *x) | 218 | static 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 | ||
251 | void xfrm_state_delete(struct xfrm_state *x) | 256 | int 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 | } |
257 | EXPORT_SYMBOL(xfrm_state_delete); | 266 | EXPORT_SYMBOL(xfrm_state_delete); |
258 | 267 | ||
@@ -796,34 +805,60 @@ EXPORT_SYMBOL(xfrm_replay_advance); | |||
796 | static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list); | 805 | static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list); |
797 | static DEFINE_RWLOCK(xfrm_km_lock); | 806 | static DEFINE_RWLOCK(xfrm_km_lock); |
798 | 807 | ||
799 | static void km_state_expired(struct xfrm_state *x, int hard) | 808 | void 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 | ||
819 | void 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 | |||
829 | EXPORT_SYMBOL(km_policy_notify); | ||
830 | EXPORT_SYMBOL(km_state_notify); | ||
831 | |||
832 | static 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 | */ | ||
817 | static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol) | 852 | static 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 | ||
849 | void km_policy_expired(struct xfrm_policy *pol, int dir, int hard) | 884 | void 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); |