aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm')
-rw-r--r--net/xfrm/xfrm_input.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 4218164f4f5e..85d1d4764612 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -16,6 +16,81 @@
16 16
17static struct kmem_cache *secpath_cachep __read_mostly; 17static struct kmem_cache *secpath_cachep __read_mostly;
18 18
19static DEFINE_SPINLOCK(xfrm_input_afinfo_lock);
20static struct xfrm_input_afinfo __rcu *xfrm_input_afinfo[NPROTO];
21
22int xfrm_input_register_afinfo(struct xfrm_input_afinfo *afinfo)
23{
24 int err = 0;
25
26 if (unlikely(afinfo == NULL))
27 return -EINVAL;
28 if (unlikely(afinfo->family >= NPROTO))
29 return -EAFNOSUPPORT;
30 spin_lock_bh(&xfrm_input_afinfo_lock);
31 if (unlikely(xfrm_input_afinfo[afinfo->family] != NULL))
32 err = -ENOBUFS;
33 else
34 rcu_assign_pointer(xfrm_input_afinfo[afinfo->family], afinfo);
35 spin_unlock_bh(&xfrm_input_afinfo_lock);
36 return err;
37}
38EXPORT_SYMBOL(xfrm_input_register_afinfo);
39
40int xfrm_input_unregister_afinfo(struct xfrm_input_afinfo *afinfo)
41{
42 int err = 0;
43
44 if (unlikely(afinfo == NULL))
45 return -EINVAL;
46 if (unlikely(afinfo->family >= NPROTO))
47 return -EAFNOSUPPORT;
48 spin_lock_bh(&xfrm_input_afinfo_lock);
49 if (likely(xfrm_input_afinfo[afinfo->family] != NULL)) {
50 if (unlikely(xfrm_input_afinfo[afinfo->family] != afinfo))
51 err = -EINVAL;
52 else
53 RCU_INIT_POINTER(xfrm_input_afinfo[afinfo->family], NULL);
54 }
55 spin_unlock_bh(&xfrm_input_afinfo_lock);
56 synchronize_rcu();
57 return err;
58}
59EXPORT_SYMBOL(xfrm_input_unregister_afinfo);
60
61static struct xfrm_input_afinfo *xfrm_input_get_afinfo(unsigned int family)
62{
63 struct xfrm_input_afinfo *afinfo;
64
65 if (unlikely(family >= NPROTO))
66 return NULL;
67 rcu_read_lock();
68 afinfo = rcu_dereference(xfrm_input_afinfo[family]);
69 if (unlikely(!afinfo))
70 rcu_read_unlock();
71 return afinfo;
72}
73
74static void xfrm_input_put_afinfo(struct xfrm_input_afinfo *afinfo)
75{
76 rcu_read_unlock();
77}
78
79static int xfrm_rcv_cb(struct sk_buff *skb, unsigned int family, u8 protocol,
80 int err)
81{
82 int ret;
83 struct xfrm_input_afinfo *afinfo = xfrm_input_get_afinfo(family);
84
85 if (!afinfo)
86 return -EAFNOSUPPORT;
87
88 ret = afinfo->callback(skb, protocol, err);
89 xfrm_input_put_afinfo(afinfo);
90
91 return ret;
92}
93
19void __secpath_destroy(struct sec_path *sp) 94void __secpath_destroy(struct sec_path *sp)
20{ 95{
21 int i; 96 int i;