Commit e959d8121fcbfee6ec049cc617e9423d1799f2e4
Committed by
David S. Miller
1 parent
f3111502c0
Exists in
master
and in
7 other branches
[XFRM]: fix incorrect xfrm_policy_afinfo_lock use
xfrm_policy_afinfo_lock can be taken in bh context, at: [<c013fe1a>] lockdep_acquire_read+0x54/0x6d [<c0f6e024>] _read_lock+0x15/0x22 [<c0e8fcdb>] xfrm_policy_get_afinfo+0x1a/0x3d [<c0e8fd10>] xfrm_decode_session+0x12/0x32 [<c0e66094>] ip_route_me_harder+0x1c9/0x25b [<c0e770d3>] ip_nat_local_fn+0x94/0xad [<c0e2bbc8>] nf_iterate+0x2e/0x7a [<c0e2bc50>] nf_hook_slow+0x3c/0x9e [<c0e3a342>] ip_push_pending_frames+0x2de/0x3a7 [<c0e53e19>] icmp_push_reply+0x136/0x141 [<c0e543fb>] icmp_reply+0x118/0x1a0 [<c0e54581>] icmp_echo+0x44/0x46 [<c0e53fad>] icmp_rcv+0x111/0x138 [<c0e36764>] ip_local_deliver+0x150/0x1f9 [<c0e36be2>] ip_rcv+0x3d5/0x413 [<c0df760f>] netif_receive_skb+0x337/0x356 [<c0df76c3>] process_backlog+0x95/0x110 [<c0df5fe2>] net_rx_action+0xa5/0x16d [<c012d8a7>] __do_softirq+0x6f/0xe6 [<c0105ec2>] do_softirq+0x52/0xb1 this means that all write-locking of xfrm_policy_afinfo_lock must be bh-safe. This patch fixes xfrm_policy_register_afinfo() and xfrm_policy_unregister_afinfo(). Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 1 changed file with 4 additions and 4 deletions Inline Diff
net/xfrm/xfrm_policy.c
1 | /* | 1 | /* |
2 | * xfrm_policy.c | 2 | * xfrm_policy.c |
3 | * | 3 | * |
4 | * Changes: | 4 | * Changes: |
5 | * Mitsuru KANDA @USAGI | 5 | * Mitsuru KANDA @USAGI |
6 | * Kazunori MIYAZAWA @USAGI | 6 | * Kazunori MIYAZAWA @USAGI |
7 | * Kunihiro Ishiguro <kunihiro@ipinfusion.com> | 7 | * Kunihiro Ishiguro <kunihiro@ipinfusion.com> |
8 | * IPv6 support | 8 | * IPv6 support |
9 | * Kazunori MIYAZAWA @USAGI | 9 | * Kazunori MIYAZAWA @USAGI |
10 | * YOSHIFUJI Hideaki | 10 | * YOSHIFUJI Hideaki |
11 | * Split up af-specific portion | 11 | * Split up af-specific portion |
12 | * Derek Atkins <derek@ihtfp.com> Add the post_input processor | 12 | * Derek Atkins <derek@ihtfp.com> Add the post_input processor |
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/config.h> | 16 | #include <linux/config.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/kmod.h> | 18 | #include <linux/kmod.h> |
19 | #include <linux/list.h> | 19 | #include <linux/list.h> |
20 | #include <linux/spinlock.h> | 20 | #include <linux/spinlock.h> |
21 | #include <linux/workqueue.h> | 21 | #include <linux/workqueue.h> |
22 | #include <linux/notifier.h> | 22 | #include <linux/notifier.h> |
23 | #include <linux/netdevice.h> | 23 | #include <linux/netdevice.h> |
24 | #include <linux/netfilter.h> | 24 | #include <linux/netfilter.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <net/xfrm.h> | 26 | #include <net/xfrm.h> |
27 | #include <net/ip.h> | 27 | #include <net/ip.h> |
28 | 28 | ||
29 | DEFINE_MUTEX(xfrm_cfg_mutex); | 29 | DEFINE_MUTEX(xfrm_cfg_mutex); |
30 | EXPORT_SYMBOL(xfrm_cfg_mutex); | 30 | EXPORT_SYMBOL(xfrm_cfg_mutex); |
31 | 31 | ||
32 | static DEFINE_RWLOCK(xfrm_policy_lock); | 32 | static DEFINE_RWLOCK(xfrm_policy_lock); |
33 | 33 | ||
34 | struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2]; | 34 | struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2]; |
35 | EXPORT_SYMBOL(xfrm_policy_list); | 35 | EXPORT_SYMBOL(xfrm_policy_list); |
36 | 36 | ||
37 | static DEFINE_RWLOCK(xfrm_policy_afinfo_lock); | 37 | static DEFINE_RWLOCK(xfrm_policy_afinfo_lock); |
38 | static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO]; | 38 | static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO]; |
39 | 39 | ||
40 | static kmem_cache_t *xfrm_dst_cache __read_mostly; | 40 | static kmem_cache_t *xfrm_dst_cache __read_mostly; |
41 | 41 | ||
42 | static struct work_struct xfrm_policy_gc_work; | 42 | static struct work_struct xfrm_policy_gc_work; |
43 | static struct list_head xfrm_policy_gc_list = | 43 | static struct list_head xfrm_policy_gc_list = |
44 | LIST_HEAD_INIT(xfrm_policy_gc_list); | 44 | LIST_HEAD_INIT(xfrm_policy_gc_list); |
45 | static DEFINE_SPINLOCK(xfrm_policy_gc_lock); | 45 | static DEFINE_SPINLOCK(xfrm_policy_gc_lock); |
46 | 46 | ||
47 | static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family); | 47 | static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family); |
48 | static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo); | 48 | static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo); |
49 | 49 | ||
50 | int xfrm_register_type(struct xfrm_type *type, unsigned short family) | 50 | int xfrm_register_type(struct xfrm_type *type, unsigned short family) |
51 | { | 51 | { |
52 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); | 52 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); |
53 | struct xfrm_type_map *typemap; | 53 | struct xfrm_type_map *typemap; |
54 | int err = 0; | 54 | int err = 0; |
55 | 55 | ||
56 | if (unlikely(afinfo == NULL)) | 56 | if (unlikely(afinfo == NULL)) |
57 | return -EAFNOSUPPORT; | 57 | return -EAFNOSUPPORT; |
58 | typemap = afinfo->type_map; | 58 | typemap = afinfo->type_map; |
59 | 59 | ||
60 | write_lock_bh(&typemap->lock); | 60 | write_lock_bh(&typemap->lock); |
61 | if (likely(typemap->map[type->proto] == NULL)) | 61 | if (likely(typemap->map[type->proto] == NULL)) |
62 | typemap->map[type->proto] = type; | 62 | typemap->map[type->proto] = type; |
63 | else | 63 | else |
64 | err = -EEXIST; | 64 | err = -EEXIST; |
65 | write_unlock_bh(&typemap->lock); | 65 | write_unlock_bh(&typemap->lock); |
66 | xfrm_policy_put_afinfo(afinfo); | 66 | xfrm_policy_put_afinfo(afinfo); |
67 | return err; | 67 | return err; |
68 | } | 68 | } |
69 | EXPORT_SYMBOL(xfrm_register_type); | 69 | EXPORT_SYMBOL(xfrm_register_type); |
70 | 70 | ||
71 | int xfrm_unregister_type(struct xfrm_type *type, unsigned short family) | 71 | int xfrm_unregister_type(struct xfrm_type *type, unsigned short family) |
72 | { | 72 | { |
73 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); | 73 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); |
74 | struct xfrm_type_map *typemap; | 74 | struct xfrm_type_map *typemap; |
75 | int err = 0; | 75 | int err = 0; |
76 | 76 | ||
77 | if (unlikely(afinfo == NULL)) | 77 | if (unlikely(afinfo == NULL)) |
78 | return -EAFNOSUPPORT; | 78 | return -EAFNOSUPPORT; |
79 | typemap = afinfo->type_map; | 79 | typemap = afinfo->type_map; |
80 | 80 | ||
81 | write_lock_bh(&typemap->lock); | 81 | write_lock_bh(&typemap->lock); |
82 | if (unlikely(typemap->map[type->proto] != type)) | 82 | if (unlikely(typemap->map[type->proto] != type)) |
83 | err = -ENOENT; | 83 | err = -ENOENT; |
84 | else | 84 | else |
85 | typemap->map[type->proto] = NULL; | 85 | typemap->map[type->proto] = NULL; |
86 | write_unlock_bh(&typemap->lock); | 86 | write_unlock_bh(&typemap->lock); |
87 | xfrm_policy_put_afinfo(afinfo); | 87 | xfrm_policy_put_afinfo(afinfo); |
88 | return err; | 88 | return err; |
89 | } | 89 | } |
90 | EXPORT_SYMBOL(xfrm_unregister_type); | 90 | EXPORT_SYMBOL(xfrm_unregister_type); |
91 | 91 | ||
92 | struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family) | 92 | struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family) |
93 | { | 93 | { |
94 | struct xfrm_policy_afinfo *afinfo; | 94 | struct xfrm_policy_afinfo *afinfo; |
95 | struct xfrm_type_map *typemap; | 95 | struct xfrm_type_map *typemap; |
96 | struct xfrm_type *type; | 96 | struct xfrm_type *type; |
97 | int modload_attempted = 0; | 97 | int modload_attempted = 0; |
98 | 98 | ||
99 | retry: | 99 | retry: |
100 | afinfo = xfrm_policy_get_afinfo(family); | 100 | afinfo = xfrm_policy_get_afinfo(family); |
101 | if (unlikely(afinfo == NULL)) | 101 | if (unlikely(afinfo == NULL)) |
102 | return NULL; | 102 | return NULL; |
103 | typemap = afinfo->type_map; | 103 | typemap = afinfo->type_map; |
104 | 104 | ||
105 | read_lock(&typemap->lock); | 105 | read_lock(&typemap->lock); |
106 | type = typemap->map[proto]; | 106 | type = typemap->map[proto]; |
107 | if (unlikely(type && !try_module_get(type->owner))) | 107 | if (unlikely(type && !try_module_get(type->owner))) |
108 | type = NULL; | 108 | type = NULL; |
109 | read_unlock(&typemap->lock); | 109 | read_unlock(&typemap->lock); |
110 | if (!type && !modload_attempted) { | 110 | if (!type && !modload_attempted) { |
111 | xfrm_policy_put_afinfo(afinfo); | 111 | xfrm_policy_put_afinfo(afinfo); |
112 | request_module("xfrm-type-%d-%d", | 112 | request_module("xfrm-type-%d-%d", |
113 | (int) family, (int) proto); | 113 | (int) family, (int) proto); |
114 | modload_attempted = 1; | 114 | modload_attempted = 1; |
115 | goto retry; | 115 | goto retry; |
116 | } | 116 | } |
117 | 117 | ||
118 | xfrm_policy_put_afinfo(afinfo); | 118 | xfrm_policy_put_afinfo(afinfo); |
119 | return type; | 119 | return type; |
120 | } | 120 | } |
121 | 121 | ||
122 | int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, | 122 | int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, |
123 | unsigned short family) | 123 | unsigned short family) |
124 | { | 124 | { |
125 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); | 125 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); |
126 | int err = 0; | 126 | int err = 0; |
127 | 127 | ||
128 | if (unlikely(afinfo == NULL)) | 128 | if (unlikely(afinfo == NULL)) |
129 | return -EAFNOSUPPORT; | 129 | return -EAFNOSUPPORT; |
130 | 130 | ||
131 | if (likely(afinfo->dst_lookup != NULL)) | 131 | if (likely(afinfo->dst_lookup != NULL)) |
132 | err = afinfo->dst_lookup(dst, fl); | 132 | err = afinfo->dst_lookup(dst, fl); |
133 | else | 133 | else |
134 | err = -EINVAL; | 134 | err = -EINVAL; |
135 | xfrm_policy_put_afinfo(afinfo); | 135 | xfrm_policy_put_afinfo(afinfo); |
136 | return err; | 136 | return err; |
137 | } | 137 | } |
138 | EXPORT_SYMBOL(xfrm_dst_lookup); | 138 | EXPORT_SYMBOL(xfrm_dst_lookup); |
139 | 139 | ||
140 | void xfrm_put_type(struct xfrm_type *type) | 140 | void xfrm_put_type(struct xfrm_type *type) |
141 | { | 141 | { |
142 | module_put(type->owner); | 142 | module_put(type->owner); |
143 | } | 143 | } |
144 | 144 | ||
145 | static inline unsigned long make_jiffies(long secs) | 145 | static inline unsigned long make_jiffies(long secs) |
146 | { | 146 | { |
147 | if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ) | 147 | if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ) |
148 | return MAX_SCHEDULE_TIMEOUT-1; | 148 | return MAX_SCHEDULE_TIMEOUT-1; |
149 | else | 149 | else |
150 | return secs*HZ; | 150 | return secs*HZ; |
151 | } | 151 | } |
152 | 152 | ||
153 | static void xfrm_policy_timer(unsigned long data) | 153 | static void xfrm_policy_timer(unsigned long data) |
154 | { | 154 | { |
155 | struct xfrm_policy *xp = (struct xfrm_policy*)data; | 155 | struct xfrm_policy *xp = (struct xfrm_policy*)data; |
156 | unsigned long now = (unsigned long)xtime.tv_sec; | 156 | unsigned long now = (unsigned long)xtime.tv_sec; |
157 | long next = LONG_MAX; | 157 | long next = LONG_MAX; |
158 | int warn = 0; | 158 | int warn = 0; |
159 | int dir; | 159 | int dir; |
160 | 160 | ||
161 | read_lock(&xp->lock); | 161 | read_lock(&xp->lock); |
162 | 162 | ||
163 | if (xp->dead) | 163 | if (xp->dead) |
164 | goto out; | 164 | goto out; |
165 | 165 | ||
166 | dir = xfrm_policy_id2dir(xp->index); | 166 | dir = xfrm_policy_id2dir(xp->index); |
167 | 167 | ||
168 | if (xp->lft.hard_add_expires_seconds) { | 168 | if (xp->lft.hard_add_expires_seconds) { |
169 | long tmo = xp->lft.hard_add_expires_seconds + | 169 | long tmo = xp->lft.hard_add_expires_seconds + |
170 | xp->curlft.add_time - now; | 170 | xp->curlft.add_time - now; |
171 | if (tmo <= 0) | 171 | if (tmo <= 0) |
172 | goto expired; | 172 | goto expired; |
173 | if (tmo < next) | 173 | if (tmo < next) |
174 | next = tmo; | 174 | next = tmo; |
175 | } | 175 | } |
176 | if (xp->lft.hard_use_expires_seconds) { | 176 | if (xp->lft.hard_use_expires_seconds) { |
177 | long tmo = xp->lft.hard_use_expires_seconds + | 177 | long tmo = xp->lft.hard_use_expires_seconds + |
178 | (xp->curlft.use_time ? : xp->curlft.add_time) - now; | 178 | (xp->curlft.use_time ? : xp->curlft.add_time) - now; |
179 | if (tmo <= 0) | 179 | if (tmo <= 0) |
180 | goto expired; | 180 | goto expired; |
181 | if (tmo < next) | 181 | if (tmo < next) |
182 | next = tmo; | 182 | next = tmo; |
183 | } | 183 | } |
184 | if (xp->lft.soft_add_expires_seconds) { | 184 | if (xp->lft.soft_add_expires_seconds) { |
185 | long tmo = xp->lft.soft_add_expires_seconds + | 185 | long tmo = xp->lft.soft_add_expires_seconds + |
186 | xp->curlft.add_time - now; | 186 | xp->curlft.add_time - now; |
187 | if (tmo <= 0) { | 187 | if (tmo <= 0) { |
188 | warn = 1; | 188 | warn = 1; |
189 | tmo = XFRM_KM_TIMEOUT; | 189 | tmo = XFRM_KM_TIMEOUT; |
190 | } | 190 | } |
191 | if (tmo < next) | 191 | if (tmo < next) |
192 | next = tmo; | 192 | next = tmo; |
193 | } | 193 | } |
194 | if (xp->lft.soft_use_expires_seconds) { | 194 | if (xp->lft.soft_use_expires_seconds) { |
195 | long tmo = xp->lft.soft_use_expires_seconds + | 195 | long tmo = xp->lft.soft_use_expires_seconds + |
196 | (xp->curlft.use_time ? : xp->curlft.add_time) - now; | 196 | (xp->curlft.use_time ? : xp->curlft.add_time) - now; |
197 | if (tmo <= 0) { | 197 | if (tmo <= 0) { |
198 | warn = 1; | 198 | warn = 1; |
199 | tmo = XFRM_KM_TIMEOUT; | 199 | tmo = XFRM_KM_TIMEOUT; |
200 | } | 200 | } |
201 | if (tmo < next) | 201 | if (tmo < next) |
202 | next = tmo; | 202 | next = tmo; |
203 | } | 203 | } |
204 | 204 | ||
205 | if (warn) | 205 | if (warn) |
206 | km_policy_expired(xp, dir, 0, 0); | 206 | km_policy_expired(xp, dir, 0, 0); |
207 | if (next != LONG_MAX && | 207 | if (next != LONG_MAX && |
208 | !mod_timer(&xp->timer, jiffies + make_jiffies(next))) | 208 | !mod_timer(&xp->timer, jiffies + make_jiffies(next))) |
209 | xfrm_pol_hold(xp); | 209 | xfrm_pol_hold(xp); |
210 | 210 | ||
211 | out: | 211 | out: |
212 | read_unlock(&xp->lock); | 212 | read_unlock(&xp->lock); |
213 | xfrm_pol_put(xp); | 213 | xfrm_pol_put(xp); |
214 | return; | 214 | return; |
215 | 215 | ||
216 | expired: | 216 | expired: |
217 | read_unlock(&xp->lock); | 217 | read_unlock(&xp->lock); |
218 | if (!xfrm_policy_delete(xp, dir)) | 218 | if (!xfrm_policy_delete(xp, dir)) |
219 | km_policy_expired(xp, dir, 1, 0); | 219 | km_policy_expired(xp, dir, 1, 0); |
220 | xfrm_pol_put(xp); | 220 | xfrm_pol_put(xp); |
221 | } | 221 | } |
222 | 222 | ||
223 | 223 | ||
224 | /* Allocate xfrm_policy. Not used here, it is supposed to be used by pfkeyv2 | 224 | /* Allocate xfrm_policy. Not used here, it is supposed to be used by pfkeyv2 |
225 | * SPD calls. | 225 | * SPD calls. |
226 | */ | 226 | */ |
227 | 227 | ||
228 | struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp) | 228 | struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp) |
229 | { | 229 | { |
230 | struct xfrm_policy *policy; | 230 | struct xfrm_policy *policy; |
231 | 231 | ||
232 | policy = kmalloc(sizeof(struct xfrm_policy), gfp); | 232 | policy = kmalloc(sizeof(struct xfrm_policy), gfp); |
233 | 233 | ||
234 | if (policy) { | 234 | if (policy) { |
235 | memset(policy, 0, sizeof(struct xfrm_policy)); | 235 | memset(policy, 0, sizeof(struct xfrm_policy)); |
236 | atomic_set(&policy->refcnt, 1); | 236 | atomic_set(&policy->refcnt, 1); |
237 | rwlock_init(&policy->lock); | 237 | rwlock_init(&policy->lock); |
238 | init_timer(&policy->timer); | 238 | init_timer(&policy->timer); |
239 | policy->timer.data = (unsigned long)policy; | 239 | policy->timer.data = (unsigned long)policy; |
240 | policy->timer.function = xfrm_policy_timer; | 240 | policy->timer.function = xfrm_policy_timer; |
241 | } | 241 | } |
242 | return policy; | 242 | return policy; |
243 | } | 243 | } |
244 | EXPORT_SYMBOL(xfrm_policy_alloc); | 244 | EXPORT_SYMBOL(xfrm_policy_alloc); |
245 | 245 | ||
246 | /* Destroy xfrm_policy: descendant resources must be released to this moment. */ | 246 | /* Destroy xfrm_policy: descendant resources must be released to this moment. */ |
247 | 247 | ||
248 | void __xfrm_policy_destroy(struct xfrm_policy *policy) | 248 | void __xfrm_policy_destroy(struct xfrm_policy *policy) |
249 | { | 249 | { |
250 | BUG_ON(!policy->dead); | 250 | BUG_ON(!policy->dead); |
251 | 251 | ||
252 | BUG_ON(policy->bundles); | 252 | BUG_ON(policy->bundles); |
253 | 253 | ||
254 | if (del_timer(&policy->timer)) | 254 | if (del_timer(&policy->timer)) |
255 | BUG(); | 255 | BUG(); |
256 | 256 | ||
257 | security_xfrm_policy_free(policy); | 257 | security_xfrm_policy_free(policy); |
258 | kfree(policy); | 258 | kfree(policy); |
259 | } | 259 | } |
260 | EXPORT_SYMBOL(__xfrm_policy_destroy); | 260 | EXPORT_SYMBOL(__xfrm_policy_destroy); |
261 | 261 | ||
262 | static void xfrm_policy_gc_kill(struct xfrm_policy *policy) | 262 | static void xfrm_policy_gc_kill(struct xfrm_policy *policy) |
263 | { | 263 | { |
264 | struct dst_entry *dst; | 264 | struct dst_entry *dst; |
265 | 265 | ||
266 | while ((dst = policy->bundles) != NULL) { | 266 | while ((dst = policy->bundles) != NULL) { |
267 | policy->bundles = dst->next; | 267 | policy->bundles = dst->next; |
268 | dst_free(dst); | 268 | dst_free(dst); |
269 | } | 269 | } |
270 | 270 | ||
271 | if (del_timer(&policy->timer)) | 271 | if (del_timer(&policy->timer)) |
272 | atomic_dec(&policy->refcnt); | 272 | atomic_dec(&policy->refcnt); |
273 | 273 | ||
274 | if (atomic_read(&policy->refcnt) > 1) | 274 | if (atomic_read(&policy->refcnt) > 1) |
275 | flow_cache_flush(); | 275 | flow_cache_flush(); |
276 | 276 | ||
277 | xfrm_pol_put(policy); | 277 | xfrm_pol_put(policy); |
278 | } | 278 | } |
279 | 279 | ||
280 | static void xfrm_policy_gc_task(void *data) | 280 | static void xfrm_policy_gc_task(void *data) |
281 | { | 281 | { |
282 | struct xfrm_policy *policy; | 282 | struct xfrm_policy *policy; |
283 | struct list_head *entry, *tmp; | 283 | struct list_head *entry, *tmp; |
284 | struct list_head gc_list = LIST_HEAD_INIT(gc_list); | 284 | struct list_head gc_list = LIST_HEAD_INIT(gc_list); |
285 | 285 | ||
286 | spin_lock_bh(&xfrm_policy_gc_lock); | 286 | spin_lock_bh(&xfrm_policy_gc_lock); |
287 | list_splice_init(&xfrm_policy_gc_list, &gc_list); | 287 | list_splice_init(&xfrm_policy_gc_list, &gc_list); |
288 | spin_unlock_bh(&xfrm_policy_gc_lock); | 288 | spin_unlock_bh(&xfrm_policy_gc_lock); |
289 | 289 | ||
290 | list_for_each_safe(entry, tmp, &gc_list) { | 290 | list_for_each_safe(entry, tmp, &gc_list) { |
291 | policy = list_entry(entry, struct xfrm_policy, list); | 291 | policy = list_entry(entry, struct xfrm_policy, list); |
292 | xfrm_policy_gc_kill(policy); | 292 | xfrm_policy_gc_kill(policy); |
293 | } | 293 | } |
294 | } | 294 | } |
295 | 295 | ||
296 | /* Rule must be locked. Release descentant resources, announce | 296 | /* Rule must be locked. Release descentant resources, announce |
297 | * entry dead. The rule must be unlinked from lists to the moment. | 297 | * entry dead. The rule must be unlinked from lists to the moment. |
298 | */ | 298 | */ |
299 | 299 | ||
300 | static void xfrm_policy_kill(struct xfrm_policy *policy) | 300 | static void xfrm_policy_kill(struct xfrm_policy *policy) |
301 | { | 301 | { |
302 | int dead; | 302 | int dead; |
303 | 303 | ||
304 | write_lock_bh(&policy->lock); | 304 | write_lock_bh(&policy->lock); |
305 | dead = policy->dead; | 305 | dead = policy->dead; |
306 | policy->dead = 1; | 306 | policy->dead = 1; |
307 | write_unlock_bh(&policy->lock); | 307 | write_unlock_bh(&policy->lock); |
308 | 308 | ||
309 | if (unlikely(dead)) { | 309 | if (unlikely(dead)) { |
310 | WARN_ON(1); | 310 | WARN_ON(1); |
311 | return; | 311 | return; |
312 | } | 312 | } |
313 | 313 | ||
314 | spin_lock(&xfrm_policy_gc_lock); | 314 | spin_lock(&xfrm_policy_gc_lock); |
315 | list_add(&policy->list, &xfrm_policy_gc_list); | 315 | list_add(&policy->list, &xfrm_policy_gc_list); |
316 | spin_unlock(&xfrm_policy_gc_lock); | 316 | spin_unlock(&xfrm_policy_gc_lock); |
317 | 317 | ||
318 | schedule_work(&xfrm_policy_gc_work); | 318 | schedule_work(&xfrm_policy_gc_work); |
319 | } | 319 | } |
320 | 320 | ||
321 | /* Generate new index... KAME seems to generate them ordered by cost | 321 | /* Generate new index... KAME seems to generate them ordered by cost |
322 | * of an absolute inpredictability of ordering of rules. This will not pass. */ | 322 | * of an absolute inpredictability of ordering of rules. This will not pass. */ |
323 | static u32 xfrm_gen_index(int dir) | 323 | static u32 xfrm_gen_index(int dir) |
324 | { | 324 | { |
325 | u32 idx; | 325 | u32 idx; |
326 | struct xfrm_policy *p; | 326 | struct xfrm_policy *p; |
327 | static u32 idx_generator; | 327 | static u32 idx_generator; |
328 | 328 | ||
329 | for (;;) { | 329 | for (;;) { |
330 | idx = (idx_generator | dir); | 330 | idx = (idx_generator | dir); |
331 | idx_generator += 8; | 331 | idx_generator += 8; |
332 | if (idx == 0) | 332 | if (idx == 0) |
333 | idx = 8; | 333 | idx = 8; |
334 | for (p = xfrm_policy_list[dir]; p; p = p->next) { | 334 | for (p = xfrm_policy_list[dir]; p; p = p->next) { |
335 | if (p->index == idx) | 335 | if (p->index == idx) |
336 | break; | 336 | break; |
337 | } | 337 | } |
338 | if (!p) | 338 | if (!p) |
339 | return idx; | 339 | return idx; |
340 | } | 340 | } |
341 | } | 341 | } |
342 | 342 | ||
343 | int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | 343 | int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) |
344 | { | 344 | { |
345 | struct xfrm_policy *pol, **p; | 345 | struct xfrm_policy *pol, **p; |
346 | struct xfrm_policy *delpol = NULL; | 346 | struct xfrm_policy *delpol = NULL; |
347 | struct xfrm_policy **newpos = NULL; | 347 | struct xfrm_policy **newpos = NULL; |
348 | struct dst_entry *gc_list; | 348 | struct dst_entry *gc_list; |
349 | 349 | ||
350 | write_lock_bh(&xfrm_policy_lock); | 350 | write_lock_bh(&xfrm_policy_lock); |
351 | for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL;) { | 351 | for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL;) { |
352 | if (!delpol && memcmp(&policy->selector, &pol->selector, sizeof(pol->selector)) == 0 && | 352 | if (!delpol && memcmp(&policy->selector, &pol->selector, sizeof(pol->selector)) == 0 && |
353 | xfrm_sec_ctx_match(pol->security, policy->security)) { | 353 | xfrm_sec_ctx_match(pol->security, policy->security)) { |
354 | if (excl) { | 354 | if (excl) { |
355 | write_unlock_bh(&xfrm_policy_lock); | 355 | write_unlock_bh(&xfrm_policy_lock); |
356 | return -EEXIST; | 356 | return -EEXIST; |
357 | } | 357 | } |
358 | *p = pol->next; | 358 | *p = pol->next; |
359 | delpol = pol; | 359 | delpol = pol; |
360 | if (policy->priority > pol->priority) | 360 | if (policy->priority > pol->priority) |
361 | continue; | 361 | continue; |
362 | } else if (policy->priority >= pol->priority) { | 362 | } else if (policy->priority >= pol->priority) { |
363 | p = &pol->next; | 363 | p = &pol->next; |
364 | continue; | 364 | continue; |
365 | } | 365 | } |
366 | if (!newpos) | 366 | if (!newpos) |
367 | newpos = p; | 367 | newpos = p; |
368 | if (delpol) | 368 | if (delpol) |
369 | break; | 369 | break; |
370 | p = &pol->next; | 370 | p = &pol->next; |
371 | } | 371 | } |
372 | if (newpos) | 372 | if (newpos) |
373 | p = newpos; | 373 | p = newpos; |
374 | xfrm_pol_hold(policy); | 374 | xfrm_pol_hold(policy); |
375 | policy->next = *p; | 375 | policy->next = *p; |
376 | *p = policy; | 376 | *p = policy; |
377 | atomic_inc(&flow_cache_genid); | 377 | atomic_inc(&flow_cache_genid); |
378 | policy->index = delpol ? delpol->index : xfrm_gen_index(dir); | 378 | policy->index = delpol ? delpol->index : xfrm_gen_index(dir); |
379 | policy->curlft.add_time = (unsigned long)xtime.tv_sec; | 379 | policy->curlft.add_time = (unsigned long)xtime.tv_sec; |
380 | policy->curlft.use_time = 0; | 380 | policy->curlft.use_time = 0; |
381 | if (!mod_timer(&policy->timer, jiffies + HZ)) | 381 | if (!mod_timer(&policy->timer, jiffies + HZ)) |
382 | xfrm_pol_hold(policy); | 382 | xfrm_pol_hold(policy); |
383 | write_unlock_bh(&xfrm_policy_lock); | 383 | write_unlock_bh(&xfrm_policy_lock); |
384 | 384 | ||
385 | if (delpol) | 385 | if (delpol) |
386 | xfrm_policy_kill(delpol); | 386 | xfrm_policy_kill(delpol); |
387 | 387 | ||
388 | read_lock_bh(&xfrm_policy_lock); | 388 | read_lock_bh(&xfrm_policy_lock); |
389 | gc_list = NULL; | 389 | gc_list = NULL; |
390 | for (policy = policy->next; policy; policy = policy->next) { | 390 | for (policy = policy->next; policy; policy = policy->next) { |
391 | struct dst_entry *dst; | 391 | struct dst_entry *dst; |
392 | 392 | ||
393 | write_lock(&policy->lock); | 393 | write_lock(&policy->lock); |
394 | dst = policy->bundles; | 394 | dst = policy->bundles; |
395 | if (dst) { | 395 | if (dst) { |
396 | struct dst_entry *tail = dst; | 396 | struct dst_entry *tail = dst; |
397 | while (tail->next) | 397 | while (tail->next) |
398 | tail = tail->next; | 398 | tail = tail->next; |
399 | tail->next = gc_list; | 399 | tail->next = gc_list; |
400 | gc_list = dst; | 400 | gc_list = dst; |
401 | 401 | ||
402 | policy->bundles = NULL; | 402 | policy->bundles = NULL; |
403 | } | 403 | } |
404 | write_unlock(&policy->lock); | 404 | write_unlock(&policy->lock); |
405 | } | 405 | } |
406 | read_unlock_bh(&xfrm_policy_lock); | 406 | read_unlock_bh(&xfrm_policy_lock); |
407 | 407 | ||
408 | while (gc_list) { | 408 | while (gc_list) { |
409 | struct dst_entry *dst = gc_list; | 409 | struct dst_entry *dst = gc_list; |
410 | 410 | ||
411 | gc_list = dst->next; | 411 | gc_list = dst->next; |
412 | dst_free(dst); | 412 | dst_free(dst); |
413 | } | 413 | } |
414 | 414 | ||
415 | return 0; | 415 | return 0; |
416 | } | 416 | } |
417 | EXPORT_SYMBOL(xfrm_policy_insert); | 417 | EXPORT_SYMBOL(xfrm_policy_insert); |
418 | 418 | ||
419 | struct xfrm_policy *xfrm_policy_bysel_ctx(int dir, struct xfrm_selector *sel, | 419 | struct xfrm_policy *xfrm_policy_bysel_ctx(int dir, struct xfrm_selector *sel, |
420 | struct xfrm_sec_ctx *ctx, int delete) | 420 | struct xfrm_sec_ctx *ctx, int delete) |
421 | { | 421 | { |
422 | struct xfrm_policy *pol, **p; | 422 | struct xfrm_policy *pol, **p; |
423 | 423 | ||
424 | write_lock_bh(&xfrm_policy_lock); | 424 | write_lock_bh(&xfrm_policy_lock); |
425 | for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) { | 425 | for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) { |
426 | if ((memcmp(sel, &pol->selector, sizeof(*sel)) == 0) && | 426 | if ((memcmp(sel, &pol->selector, sizeof(*sel)) == 0) && |
427 | (xfrm_sec_ctx_match(ctx, pol->security))) { | 427 | (xfrm_sec_ctx_match(ctx, pol->security))) { |
428 | xfrm_pol_hold(pol); | 428 | xfrm_pol_hold(pol); |
429 | if (delete) | 429 | if (delete) |
430 | *p = pol->next; | 430 | *p = pol->next; |
431 | break; | 431 | break; |
432 | } | 432 | } |
433 | } | 433 | } |
434 | write_unlock_bh(&xfrm_policy_lock); | 434 | write_unlock_bh(&xfrm_policy_lock); |
435 | 435 | ||
436 | if (pol && delete) { | 436 | if (pol && delete) { |
437 | atomic_inc(&flow_cache_genid); | 437 | atomic_inc(&flow_cache_genid); |
438 | xfrm_policy_kill(pol); | 438 | xfrm_policy_kill(pol); |
439 | } | 439 | } |
440 | return pol; | 440 | return pol; |
441 | } | 441 | } |
442 | EXPORT_SYMBOL(xfrm_policy_bysel_ctx); | 442 | EXPORT_SYMBOL(xfrm_policy_bysel_ctx); |
443 | 443 | ||
444 | struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete) | 444 | struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete) |
445 | { | 445 | { |
446 | struct xfrm_policy *pol, **p; | 446 | struct xfrm_policy *pol, **p; |
447 | 447 | ||
448 | write_lock_bh(&xfrm_policy_lock); | 448 | write_lock_bh(&xfrm_policy_lock); |
449 | for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) { | 449 | for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) { |
450 | if (pol->index == id) { | 450 | if (pol->index == id) { |
451 | xfrm_pol_hold(pol); | 451 | xfrm_pol_hold(pol); |
452 | if (delete) | 452 | if (delete) |
453 | *p = pol->next; | 453 | *p = pol->next; |
454 | break; | 454 | break; |
455 | } | 455 | } |
456 | } | 456 | } |
457 | write_unlock_bh(&xfrm_policy_lock); | 457 | write_unlock_bh(&xfrm_policy_lock); |
458 | 458 | ||
459 | if (pol && delete) { | 459 | if (pol && delete) { |
460 | atomic_inc(&flow_cache_genid); | 460 | atomic_inc(&flow_cache_genid); |
461 | xfrm_policy_kill(pol); | 461 | xfrm_policy_kill(pol); |
462 | } | 462 | } |
463 | return pol; | 463 | return pol; |
464 | } | 464 | } |
465 | EXPORT_SYMBOL(xfrm_policy_byid); | 465 | EXPORT_SYMBOL(xfrm_policy_byid); |
466 | 466 | ||
467 | void xfrm_policy_flush(void) | 467 | void xfrm_policy_flush(void) |
468 | { | 468 | { |
469 | struct xfrm_policy *xp; | 469 | struct xfrm_policy *xp; |
470 | int dir; | 470 | int dir; |
471 | 471 | ||
472 | write_lock_bh(&xfrm_policy_lock); | 472 | write_lock_bh(&xfrm_policy_lock); |
473 | for (dir = 0; dir < XFRM_POLICY_MAX; dir++) { | 473 | for (dir = 0; dir < XFRM_POLICY_MAX; dir++) { |
474 | while ((xp = xfrm_policy_list[dir]) != NULL) { | 474 | while ((xp = xfrm_policy_list[dir]) != NULL) { |
475 | xfrm_policy_list[dir] = xp->next; | 475 | xfrm_policy_list[dir] = xp->next; |
476 | write_unlock_bh(&xfrm_policy_lock); | 476 | write_unlock_bh(&xfrm_policy_lock); |
477 | 477 | ||
478 | xfrm_policy_kill(xp); | 478 | xfrm_policy_kill(xp); |
479 | 479 | ||
480 | write_lock_bh(&xfrm_policy_lock); | 480 | write_lock_bh(&xfrm_policy_lock); |
481 | } | 481 | } |
482 | } | 482 | } |
483 | atomic_inc(&flow_cache_genid); | 483 | atomic_inc(&flow_cache_genid); |
484 | write_unlock_bh(&xfrm_policy_lock); | 484 | write_unlock_bh(&xfrm_policy_lock); |
485 | } | 485 | } |
486 | EXPORT_SYMBOL(xfrm_policy_flush); | 486 | EXPORT_SYMBOL(xfrm_policy_flush); |
487 | 487 | ||
488 | int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), | 488 | int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), |
489 | void *data) | 489 | void *data) |
490 | { | 490 | { |
491 | struct xfrm_policy *xp; | 491 | struct xfrm_policy *xp; |
492 | int dir; | 492 | int dir; |
493 | int count = 0; | 493 | int count = 0; |
494 | int error = 0; | 494 | int error = 0; |
495 | 495 | ||
496 | read_lock_bh(&xfrm_policy_lock); | 496 | read_lock_bh(&xfrm_policy_lock); |
497 | for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) { | 497 | for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) { |
498 | for (xp = xfrm_policy_list[dir]; xp; xp = xp->next) | 498 | for (xp = xfrm_policy_list[dir]; xp; xp = xp->next) |
499 | count++; | 499 | count++; |
500 | } | 500 | } |
501 | 501 | ||
502 | if (count == 0) { | 502 | if (count == 0) { |
503 | error = -ENOENT; | 503 | error = -ENOENT; |
504 | goto out; | 504 | goto out; |
505 | } | 505 | } |
506 | 506 | ||
507 | for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) { | 507 | for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) { |
508 | for (xp = xfrm_policy_list[dir]; xp; xp = xp->next) { | 508 | for (xp = xfrm_policy_list[dir]; xp; xp = xp->next) { |
509 | error = func(xp, dir%XFRM_POLICY_MAX, --count, data); | 509 | error = func(xp, dir%XFRM_POLICY_MAX, --count, data); |
510 | if (error) | 510 | if (error) |
511 | goto out; | 511 | goto out; |
512 | } | 512 | } |
513 | } | 513 | } |
514 | 514 | ||
515 | out: | 515 | out: |
516 | read_unlock_bh(&xfrm_policy_lock); | 516 | read_unlock_bh(&xfrm_policy_lock); |
517 | return error; | 517 | return error; |
518 | } | 518 | } |
519 | EXPORT_SYMBOL(xfrm_policy_walk); | 519 | EXPORT_SYMBOL(xfrm_policy_walk); |
520 | 520 | ||
521 | /* Find policy to apply to this flow. */ | 521 | /* Find policy to apply to this flow. */ |
522 | 522 | ||
523 | static void xfrm_policy_lookup(struct flowi *fl, u32 sk_sid, u16 family, u8 dir, | 523 | static void xfrm_policy_lookup(struct flowi *fl, u32 sk_sid, u16 family, u8 dir, |
524 | void **objp, atomic_t **obj_refp) | 524 | void **objp, atomic_t **obj_refp) |
525 | { | 525 | { |
526 | struct xfrm_policy *pol; | 526 | struct xfrm_policy *pol; |
527 | 527 | ||
528 | read_lock_bh(&xfrm_policy_lock); | 528 | read_lock_bh(&xfrm_policy_lock); |
529 | for (pol = xfrm_policy_list[dir]; pol; pol = pol->next) { | 529 | for (pol = xfrm_policy_list[dir]; pol; pol = pol->next) { |
530 | struct xfrm_selector *sel = &pol->selector; | 530 | struct xfrm_selector *sel = &pol->selector; |
531 | int match; | 531 | int match; |
532 | 532 | ||
533 | if (pol->family != family) | 533 | if (pol->family != family) |
534 | continue; | 534 | continue; |
535 | 535 | ||
536 | match = xfrm_selector_match(sel, fl, family); | 536 | match = xfrm_selector_match(sel, fl, family); |
537 | 537 | ||
538 | if (match) { | 538 | if (match) { |
539 | if (!security_xfrm_policy_lookup(pol, sk_sid, dir)) { | 539 | if (!security_xfrm_policy_lookup(pol, sk_sid, dir)) { |
540 | xfrm_pol_hold(pol); | 540 | xfrm_pol_hold(pol); |
541 | break; | 541 | break; |
542 | } | 542 | } |
543 | } | 543 | } |
544 | } | 544 | } |
545 | read_unlock_bh(&xfrm_policy_lock); | 545 | read_unlock_bh(&xfrm_policy_lock); |
546 | if ((*objp = (void *) pol) != NULL) | 546 | if ((*objp = (void *) pol) != NULL) |
547 | *obj_refp = &pol->refcnt; | 547 | *obj_refp = &pol->refcnt; |
548 | } | 548 | } |
549 | 549 | ||
550 | static inline int policy_to_flow_dir(int dir) | 550 | static inline int policy_to_flow_dir(int dir) |
551 | { | 551 | { |
552 | if (XFRM_POLICY_IN == FLOW_DIR_IN && | 552 | if (XFRM_POLICY_IN == FLOW_DIR_IN && |
553 | XFRM_POLICY_OUT == FLOW_DIR_OUT && | 553 | XFRM_POLICY_OUT == FLOW_DIR_OUT && |
554 | XFRM_POLICY_FWD == FLOW_DIR_FWD) | 554 | XFRM_POLICY_FWD == FLOW_DIR_FWD) |
555 | return dir; | 555 | return dir; |
556 | switch (dir) { | 556 | switch (dir) { |
557 | default: | 557 | default: |
558 | case XFRM_POLICY_IN: | 558 | case XFRM_POLICY_IN: |
559 | return FLOW_DIR_IN; | 559 | return FLOW_DIR_IN; |
560 | case XFRM_POLICY_OUT: | 560 | case XFRM_POLICY_OUT: |
561 | return FLOW_DIR_OUT; | 561 | return FLOW_DIR_OUT; |
562 | case XFRM_POLICY_FWD: | 562 | case XFRM_POLICY_FWD: |
563 | return FLOW_DIR_FWD; | 563 | return FLOW_DIR_FWD; |
564 | }; | 564 | }; |
565 | } | 565 | } |
566 | 566 | ||
567 | static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl, u32 sk_sid) | 567 | static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl, u32 sk_sid) |
568 | { | 568 | { |
569 | struct xfrm_policy *pol; | 569 | struct xfrm_policy *pol; |
570 | 570 | ||
571 | read_lock_bh(&xfrm_policy_lock); | 571 | read_lock_bh(&xfrm_policy_lock); |
572 | if ((pol = sk->sk_policy[dir]) != NULL) { | 572 | if ((pol = sk->sk_policy[dir]) != NULL) { |
573 | int match = xfrm_selector_match(&pol->selector, fl, | 573 | int match = xfrm_selector_match(&pol->selector, fl, |
574 | sk->sk_family); | 574 | sk->sk_family); |
575 | int err = 0; | 575 | int err = 0; |
576 | 576 | ||
577 | if (match) | 577 | if (match) |
578 | err = security_xfrm_policy_lookup(pol, sk_sid, policy_to_flow_dir(dir)); | 578 | err = security_xfrm_policy_lookup(pol, sk_sid, policy_to_flow_dir(dir)); |
579 | 579 | ||
580 | if (match && !err) | 580 | if (match && !err) |
581 | xfrm_pol_hold(pol); | 581 | xfrm_pol_hold(pol); |
582 | else | 582 | else |
583 | pol = NULL; | 583 | pol = NULL; |
584 | } | 584 | } |
585 | read_unlock_bh(&xfrm_policy_lock); | 585 | read_unlock_bh(&xfrm_policy_lock); |
586 | return pol; | 586 | return pol; |
587 | } | 587 | } |
588 | 588 | ||
589 | static void __xfrm_policy_link(struct xfrm_policy *pol, int dir) | 589 | static void __xfrm_policy_link(struct xfrm_policy *pol, int dir) |
590 | { | 590 | { |
591 | pol->next = xfrm_policy_list[dir]; | 591 | pol->next = xfrm_policy_list[dir]; |
592 | xfrm_policy_list[dir] = pol; | 592 | xfrm_policy_list[dir] = pol; |
593 | xfrm_pol_hold(pol); | 593 | xfrm_pol_hold(pol); |
594 | } | 594 | } |
595 | 595 | ||
596 | static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, | 596 | static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, |
597 | int dir) | 597 | int dir) |
598 | { | 598 | { |
599 | struct xfrm_policy **polp; | 599 | struct xfrm_policy **polp; |
600 | 600 | ||
601 | for (polp = &xfrm_policy_list[dir]; | 601 | for (polp = &xfrm_policy_list[dir]; |
602 | *polp != NULL; polp = &(*polp)->next) { | 602 | *polp != NULL; polp = &(*polp)->next) { |
603 | if (*polp == pol) { | 603 | if (*polp == pol) { |
604 | *polp = pol->next; | 604 | *polp = pol->next; |
605 | return pol; | 605 | return pol; |
606 | } | 606 | } |
607 | } | 607 | } |
608 | return NULL; | 608 | return NULL; |
609 | } | 609 | } |
610 | 610 | ||
611 | int xfrm_policy_delete(struct xfrm_policy *pol, int dir) | 611 | int xfrm_policy_delete(struct xfrm_policy *pol, int dir) |
612 | { | 612 | { |
613 | write_lock_bh(&xfrm_policy_lock); | 613 | write_lock_bh(&xfrm_policy_lock); |
614 | pol = __xfrm_policy_unlink(pol, dir); | 614 | pol = __xfrm_policy_unlink(pol, dir); |
615 | write_unlock_bh(&xfrm_policy_lock); | 615 | write_unlock_bh(&xfrm_policy_lock); |
616 | if (pol) { | 616 | if (pol) { |
617 | if (dir < XFRM_POLICY_MAX) | 617 | if (dir < XFRM_POLICY_MAX) |
618 | atomic_inc(&flow_cache_genid); | 618 | atomic_inc(&flow_cache_genid); |
619 | xfrm_policy_kill(pol); | 619 | xfrm_policy_kill(pol); |
620 | return 0; | 620 | return 0; |
621 | } | 621 | } |
622 | return -ENOENT; | 622 | return -ENOENT; |
623 | } | 623 | } |
624 | EXPORT_SYMBOL(xfrm_policy_delete); | 624 | EXPORT_SYMBOL(xfrm_policy_delete); |
625 | 625 | ||
626 | int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) | 626 | int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) |
627 | { | 627 | { |
628 | struct xfrm_policy *old_pol; | 628 | struct xfrm_policy *old_pol; |
629 | 629 | ||
630 | write_lock_bh(&xfrm_policy_lock); | 630 | write_lock_bh(&xfrm_policy_lock); |
631 | old_pol = sk->sk_policy[dir]; | 631 | old_pol = sk->sk_policy[dir]; |
632 | sk->sk_policy[dir] = pol; | 632 | sk->sk_policy[dir] = pol; |
633 | if (pol) { | 633 | if (pol) { |
634 | pol->curlft.add_time = (unsigned long)xtime.tv_sec; | 634 | pol->curlft.add_time = (unsigned long)xtime.tv_sec; |
635 | pol->index = xfrm_gen_index(XFRM_POLICY_MAX+dir); | 635 | pol->index = xfrm_gen_index(XFRM_POLICY_MAX+dir); |
636 | __xfrm_policy_link(pol, XFRM_POLICY_MAX+dir); | 636 | __xfrm_policy_link(pol, XFRM_POLICY_MAX+dir); |
637 | } | 637 | } |
638 | if (old_pol) | 638 | if (old_pol) |
639 | __xfrm_policy_unlink(old_pol, XFRM_POLICY_MAX+dir); | 639 | __xfrm_policy_unlink(old_pol, XFRM_POLICY_MAX+dir); |
640 | write_unlock_bh(&xfrm_policy_lock); | 640 | write_unlock_bh(&xfrm_policy_lock); |
641 | 641 | ||
642 | if (old_pol) { | 642 | if (old_pol) { |
643 | xfrm_policy_kill(old_pol); | 643 | xfrm_policy_kill(old_pol); |
644 | } | 644 | } |
645 | return 0; | 645 | return 0; |
646 | } | 646 | } |
647 | 647 | ||
648 | static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir) | 648 | static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir) |
649 | { | 649 | { |
650 | struct xfrm_policy *newp = xfrm_policy_alloc(GFP_ATOMIC); | 650 | struct xfrm_policy *newp = xfrm_policy_alloc(GFP_ATOMIC); |
651 | 651 | ||
652 | if (newp) { | 652 | if (newp) { |
653 | newp->selector = old->selector; | 653 | newp->selector = old->selector; |
654 | if (security_xfrm_policy_clone(old, newp)) { | 654 | if (security_xfrm_policy_clone(old, newp)) { |
655 | kfree(newp); | 655 | kfree(newp); |
656 | return NULL; /* ENOMEM */ | 656 | return NULL; /* ENOMEM */ |
657 | } | 657 | } |
658 | newp->lft = old->lft; | 658 | newp->lft = old->lft; |
659 | newp->curlft = old->curlft; | 659 | newp->curlft = old->curlft; |
660 | newp->action = old->action; | 660 | newp->action = old->action; |
661 | newp->flags = old->flags; | 661 | newp->flags = old->flags; |
662 | newp->xfrm_nr = old->xfrm_nr; | 662 | newp->xfrm_nr = old->xfrm_nr; |
663 | newp->index = old->index; | 663 | newp->index = old->index; |
664 | memcpy(newp->xfrm_vec, old->xfrm_vec, | 664 | memcpy(newp->xfrm_vec, old->xfrm_vec, |
665 | newp->xfrm_nr*sizeof(struct xfrm_tmpl)); | 665 | newp->xfrm_nr*sizeof(struct xfrm_tmpl)); |
666 | write_lock_bh(&xfrm_policy_lock); | 666 | write_lock_bh(&xfrm_policy_lock); |
667 | __xfrm_policy_link(newp, XFRM_POLICY_MAX+dir); | 667 | __xfrm_policy_link(newp, XFRM_POLICY_MAX+dir); |
668 | write_unlock_bh(&xfrm_policy_lock); | 668 | write_unlock_bh(&xfrm_policy_lock); |
669 | xfrm_pol_put(newp); | 669 | xfrm_pol_put(newp); |
670 | } | 670 | } |
671 | return newp; | 671 | return newp; |
672 | } | 672 | } |
673 | 673 | ||
674 | int __xfrm_sk_clone_policy(struct sock *sk) | 674 | int __xfrm_sk_clone_policy(struct sock *sk) |
675 | { | 675 | { |
676 | struct xfrm_policy *p0 = sk->sk_policy[0], | 676 | struct xfrm_policy *p0 = sk->sk_policy[0], |
677 | *p1 = sk->sk_policy[1]; | 677 | *p1 = sk->sk_policy[1]; |
678 | 678 | ||
679 | sk->sk_policy[0] = sk->sk_policy[1] = NULL; | 679 | sk->sk_policy[0] = sk->sk_policy[1] = NULL; |
680 | if (p0 && (sk->sk_policy[0] = clone_policy(p0, 0)) == NULL) | 680 | if (p0 && (sk->sk_policy[0] = clone_policy(p0, 0)) == NULL) |
681 | return -ENOMEM; | 681 | return -ENOMEM; |
682 | if (p1 && (sk->sk_policy[1] = clone_policy(p1, 1)) == NULL) | 682 | if (p1 && (sk->sk_policy[1] = clone_policy(p1, 1)) == NULL) |
683 | return -ENOMEM; | 683 | return -ENOMEM; |
684 | return 0; | 684 | return 0; |
685 | } | 685 | } |
686 | 686 | ||
687 | /* Resolve list of templates for the flow, given policy. */ | 687 | /* Resolve list of templates for the flow, given policy. */ |
688 | 688 | ||
689 | static int | 689 | static int |
690 | xfrm_tmpl_resolve(struct xfrm_policy *policy, struct flowi *fl, | 690 | xfrm_tmpl_resolve(struct xfrm_policy *policy, struct flowi *fl, |
691 | struct xfrm_state **xfrm, | 691 | struct xfrm_state **xfrm, |
692 | unsigned short family) | 692 | unsigned short family) |
693 | { | 693 | { |
694 | int nx; | 694 | int nx; |
695 | int i, error; | 695 | int i, error; |
696 | xfrm_address_t *daddr = xfrm_flowi_daddr(fl, family); | 696 | xfrm_address_t *daddr = xfrm_flowi_daddr(fl, family); |
697 | xfrm_address_t *saddr = xfrm_flowi_saddr(fl, family); | 697 | xfrm_address_t *saddr = xfrm_flowi_saddr(fl, family); |
698 | 698 | ||
699 | for (nx=0, i = 0; i < policy->xfrm_nr; i++) { | 699 | for (nx=0, i = 0; i < policy->xfrm_nr; i++) { |
700 | struct xfrm_state *x; | 700 | struct xfrm_state *x; |
701 | xfrm_address_t *remote = daddr; | 701 | xfrm_address_t *remote = daddr; |
702 | xfrm_address_t *local = saddr; | 702 | xfrm_address_t *local = saddr; |
703 | struct xfrm_tmpl *tmpl = &policy->xfrm_vec[i]; | 703 | struct xfrm_tmpl *tmpl = &policy->xfrm_vec[i]; |
704 | 704 | ||
705 | if (tmpl->mode) { | 705 | if (tmpl->mode) { |
706 | remote = &tmpl->id.daddr; | 706 | remote = &tmpl->id.daddr; |
707 | local = &tmpl->saddr; | 707 | local = &tmpl->saddr; |
708 | } | 708 | } |
709 | 709 | ||
710 | x = xfrm_state_find(remote, local, fl, tmpl, policy, &error, family); | 710 | x = xfrm_state_find(remote, local, fl, tmpl, policy, &error, family); |
711 | 711 | ||
712 | if (x && x->km.state == XFRM_STATE_VALID) { | 712 | if (x && x->km.state == XFRM_STATE_VALID) { |
713 | xfrm[nx++] = x; | 713 | xfrm[nx++] = x; |
714 | daddr = remote; | 714 | daddr = remote; |
715 | saddr = local; | 715 | saddr = local; |
716 | continue; | 716 | continue; |
717 | } | 717 | } |
718 | if (x) { | 718 | if (x) { |
719 | error = (x->km.state == XFRM_STATE_ERROR ? | 719 | error = (x->km.state == XFRM_STATE_ERROR ? |
720 | -EINVAL : -EAGAIN); | 720 | -EINVAL : -EAGAIN); |
721 | xfrm_state_put(x); | 721 | xfrm_state_put(x); |
722 | } | 722 | } |
723 | 723 | ||
724 | if (!tmpl->optional) | 724 | if (!tmpl->optional) |
725 | goto fail; | 725 | goto fail; |
726 | } | 726 | } |
727 | return nx; | 727 | return nx; |
728 | 728 | ||
729 | fail: | 729 | fail: |
730 | for (nx--; nx>=0; nx--) | 730 | for (nx--; nx>=0; nx--) |
731 | xfrm_state_put(xfrm[nx]); | 731 | xfrm_state_put(xfrm[nx]); |
732 | return error; | 732 | return error; |
733 | } | 733 | } |
734 | 734 | ||
735 | /* Check that the bundle accepts the flow and its components are | 735 | /* Check that the bundle accepts the flow and its components are |
736 | * still valid. | 736 | * still valid. |
737 | */ | 737 | */ |
738 | 738 | ||
739 | static struct dst_entry * | 739 | static struct dst_entry * |
740 | xfrm_find_bundle(struct flowi *fl, struct xfrm_policy *policy, unsigned short family) | 740 | xfrm_find_bundle(struct flowi *fl, struct xfrm_policy *policy, unsigned short family) |
741 | { | 741 | { |
742 | struct dst_entry *x; | 742 | struct dst_entry *x; |
743 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); | 743 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); |
744 | if (unlikely(afinfo == NULL)) | 744 | if (unlikely(afinfo == NULL)) |
745 | return ERR_PTR(-EINVAL); | 745 | return ERR_PTR(-EINVAL); |
746 | x = afinfo->find_bundle(fl, policy); | 746 | x = afinfo->find_bundle(fl, policy); |
747 | xfrm_policy_put_afinfo(afinfo); | 747 | xfrm_policy_put_afinfo(afinfo); |
748 | return x; | 748 | return x; |
749 | } | 749 | } |
750 | 750 | ||
751 | /* Allocate chain of dst_entry's, attach known xfrm's, calculate | 751 | /* Allocate chain of dst_entry's, attach known xfrm's, calculate |
752 | * all the metrics... Shortly, bundle a bundle. | 752 | * all the metrics... Shortly, bundle a bundle. |
753 | */ | 753 | */ |
754 | 754 | ||
755 | static int | 755 | static int |
756 | xfrm_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int nx, | 756 | xfrm_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int nx, |
757 | struct flowi *fl, struct dst_entry **dst_p, | 757 | struct flowi *fl, struct dst_entry **dst_p, |
758 | unsigned short family) | 758 | unsigned short family) |
759 | { | 759 | { |
760 | int err; | 760 | int err; |
761 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); | 761 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); |
762 | if (unlikely(afinfo == NULL)) | 762 | if (unlikely(afinfo == NULL)) |
763 | return -EINVAL; | 763 | return -EINVAL; |
764 | err = afinfo->bundle_create(policy, xfrm, nx, fl, dst_p); | 764 | err = afinfo->bundle_create(policy, xfrm, nx, fl, dst_p); |
765 | xfrm_policy_put_afinfo(afinfo); | 765 | xfrm_policy_put_afinfo(afinfo); |
766 | return err; | 766 | return err; |
767 | } | 767 | } |
768 | 768 | ||
769 | 769 | ||
770 | static int stale_bundle(struct dst_entry *dst); | 770 | static int stale_bundle(struct dst_entry *dst); |
771 | 771 | ||
772 | /* Main function: finds/creates a bundle for given flow. | 772 | /* Main function: finds/creates a bundle for given flow. |
773 | * | 773 | * |
774 | * At the moment we eat a raw IP route. Mostly to speed up lookups | 774 | * At the moment we eat a raw IP route. Mostly to speed up lookups |
775 | * on interfaces with disabled IPsec. | 775 | * on interfaces with disabled IPsec. |
776 | */ | 776 | */ |
777 | int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, | 777 | int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, |
778 | struct sock *sk, int flags) | 778 | struct sock *sk, int flags) |
779 | { | 779 | { |
780 | struct xfrm_policy *policy; | 780 | struct xfrm_policy *policy; |
781 | struct xfrm_state *xfrm[XFRM_MAX_DEPTH]; | 781 | struct xfrm_state *xfrm[XFRM_MAX_DEPTH]; |
782 | struct dst_entry *dst, *dst_orig = *dst_p; | 782 | struct dst_entry *dst, *dst_orig = *dst_p; |
783 | int nx = 0; | 783 | int nx = 0; |
784 | int err; | 784 | int err; |
785 | u32 genid; | 785 | u32 genid; |
786 | u16 family; | 786 | u16 family; |
787 | u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT); | 787 | u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT); |
788 | u32 sk_sid = security_sk_sid(sk, fl, dir); | 788 | u32 sk_sid = security_sk_sid(sk, fl, dir); |
789 | restart: | 789 | restart: |
790 | genid = atomic_read(&flow_cache_genid); | 790 | genid = atomic_read(&flow_cache_genid); |
791 | policy = NULL; | 791 | policy = NULL; |
792 | if (sk && sk->sk_policy[1]) | 792 | if (sk && sk->sk_policy[1]) |
793 | policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl, sk_sid); | 793 | policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl, sk_sid); |
794 | 794 | ||
795 | if (!policy) { | 795 | if (!policy) { |
796 | /* To accelerate a bit... */ | 796 | /* To accelerate a bit... */ |
797 | if ((dst_orig->flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT]) | 797 | if ((dst_orig->flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT]) |
798 | return 0; | 798 | return 0; |
799 | 799 | ||
800 | policy = flow_cache_lookup(fl, sk_sid, dst_orig->ops->family, | 800 | policy = flow_cache_lookup(fl, sk_sid, dst_orig->ops->family, |
801 | dir, xfrm_policy_lookup); | 801 | dir, xfrm_policy_lookup); |
802 | } | 802 | } |
803 | 803 | ||
804 | if (!policy) | 804 | if (!policy) |
805 | return 0; | 805 | return 0; |
806 | 806 | ||
807 | family = dst_orig->ops->family; | 807 | family = dst_orig->ops->family; |
808 | policy->curlft.use_time = (unsigned long)xtime.tv_sec; | 808 | policy->curlft.use_time = (unsigned long)xtime.tv_sec; |
809 | 809 | ||
810 | switch (policy->action) { | 810 | switch (policy->action) { |
811 | case XFRM_POLICY_BLOCK: | 811 | case XFRM_POLICY_BLOCK: |
812 | /* Prohibit the flow */ | 812 | /* Prohibit the flow */ |
813 | err = -EPERM; | 813 | err = -EPERM; |
814 | goto error; | 814 | goto error; |
815 | 815 | ||
816 | case XFRM_POLICY_ALLOW: | 816 | case XFRM_POLICY_ALLOW: |
817 | if (policy->xfrm_nr == 0) { | 817 | if (policy->xfrm_nr == 0) { |
818 | /* Flow passes not transformed. */ | 818 | /* Flow passes not transformed. */ |
819 | xfrm_pol_put(policy); | 819 | xfrm_pol_put(policy); |
820 | return 0; | 820 | return 0; |
821 | } | 821 | } |
822 | 822 | ||
823 | /* Try to find matching bundle. | 823 | /* Try to find matching bundle. |
824 | * | 824 | * |
825 | * LATER: help from flow cache. It is optional, this | 825 | * LATER: help from flow cache. It is optional, this |
826 | * is required only for output policy. | 826 | * is required only for output policy. |
827 | */ | 827 | */ |
828 | dst = xfrm_find_bundle(fl, policy, family); | 828 | dst = xfrm_find_bundle(fl, policy, family); |
829 | if (IS_ERR(dst)) { | 829 | if (IS_ERR(dst)) { |
830 | err = PTR_ERR(dst); | 830 | err = PTR_ERR(dst); |
831 | goto error; | 831 | goto error; |
832 | } | 832 | } |
833 | 833 | ||
834 | if (dst) | 834 | if (dst) |
835 | break; | 835 | break; |
836 | 836 | ||
837 | nx = xfrm_tmpl_resolve(policy, fl, xfrm, family); | 837 | nx = xfrm_tmpl_resolve(policy, fl, xfrm, family); |
838 | 838 | ||
839 | if (unlikely(nx<0)) { | 839 | if (unlikely(nx<0)) { |
840 | err = nx; | 840 | err = nx; |
841 | if (err == -EAGAIN && flags) { | 841 | if (err == -EAGAIN && flags) { |
842 | DECLARE_WAITQUEUE(wait, current); | 842 | DECLARE_WAITQUEUE(wait, current); |
843 | 843 | ||
844 | add_wait_queue(&km_waitq, &wait); | 844 | add_wait_queue(&km_waitq, &wait); |
845 | set_current_state(TASK_INTERRUPTIBLE); | 845 | set_current_state(TASK_INTERRUPTIBLE); |
846 | schedule(); | 846 | schedule(); |
847 | set_current_state(TASK_RUNNING); | 847 | set_current_state(TASK_RUNNING); |
848 | remove_wait_queue(&km_waitq, &wait); | 848 | remove_wait_queue(&km_waitq, &wait); |
849 | 849 | ||
850 | nx = xfrm_tmpl_resolve(policy, fl, xfrm, family); | 850 | nx = xfrm_tmpl_resolve(policy, fl, xfrm, family); |
851 | 851 | ||
852 | if (nx == -EAGAIN && signal_pending(current)) { | 852 | if (nx == -EAGAIN && signal_pending(current)) { |
853 | err = -ERESTART; | 853 | err = -ERESTART; |
854 | goto error; | 854 | goto error; |
855 | } | 855 | } |
856 | if (nx == -EAGAIN || | 856 | if (nx == -EAGAIN || |
857 | genid != atomic_read(&flow_cache_genid)) { | 857 | genid != atomic_read(&flow_cache_genid)) { |
858 | xfrm_pol_put(policy); | 858 | xfrm_pol_put(policy); |
859 | goto restart; | 859 | goto restart; |
860 | } | 860 | } |
861 | err = nx; | 861 | err = nx; |
862 | } | 862 | } |
863 | if (err < 0) | 863 | if (err < 0) |
864 | goto error; | 864 | goto error; |
865 | } | 865 | } |
866 | if (nx == 0) { | 866 | if (nx == 0) { |
867 | /* Flow passes not transformed. */ | 867 | /* Flow passes not transformed. */ |
868 | xfrm_pol_put(policy); | 868 | xfrm_pol_put(policy); |
869 | return 0; | 869 | return 0; |
870 | } | 870 | } |
871 | 871 | ||
872 | dst = dst_orig; | 872 | dst = dst_orig; |
873 | err = xfrm_bundle_create(policy, xfrm, nx, fl, &dst, family); | 873 | err = xfrm_bundle_create(policy, xfrm, nx, fl, &dst, family); |
874 | 874 | ||
875 | if (unlikely(err)) { | 875 | if (unlikely(err)) { |
876 | int i; | 876 | int i; |
877 | for (i=0; i<nx; i++) | 877 | for (i=0; i<nx; i++) |
878 | xfrm_state_put(xfrm[i]); | 878 | xfrm_state_put(xfrm[i]); |
879 | goto error; | 879 | goto error; |
880 | } | 880 | } |
881 | 881 | ||
882 | write_lock_bh(&policy->lock); | 882 | write_lock_bh(&policy->lock); |
883 | if (unlikely(policy->dead || stale_bundle(dst))) { | 883 | if (unlikely(policy->dead || stale_bundle(dst))) { |
884 | /* Wow! While we worked on resolving, this | 884 | /* Wow! While we worked on resolving, this |
885 | * policy has gone. Retry. It is not paranoia, | 885 | * policy has gone. Retry. It is not paranoia, |
886 | * we just cannot enlist new bundle to dead object. | 886 | * we just cannot enlist new bundle to dead object. |
887 | * We can't enlist stable bundles either. | 887 | * We can't enlist stable bundles either. |
888 | */ | 888 | */ |
889 | write_unlock_bh(&policy->lock); | 889 | write_unlock_bh(&policy->lock); |
890 | if (dst) | 890 | if (dst) |
891 | dst_free(dst); | 891 | dst_free(dst); |
892 | 892 | ||
893 | err = -EHOSTUNREACH; | 893 | err = -EHOSTUNREACH; |
894 | goto error; | 894 | goto error; |
895 | } | 895 | } |
896 | dst->next = policy->bundles; | 896 | dst->next = policy->bundles; |
897 | policy->bundles = dst; | 897 | policy->bundles = dst; |
898 | dst_hold(dst); | 898 | dst_hold(dst); |
899 | write_unlock_bh(&policy->lock); | 899 | write_unlock_bh(&policy->lock); |
900 | } | 900 | } |
901 | *dst_p = dst; | 901 | *dst_p = dst; |
902 | dst_release(dst_orig); | 902 | dst_release(dst_orig); |
903 | xfrm_pol_put(policy); | 903 | xfrm_pol_put(policy); |
904 | return 0; | 904 | return 0; |
905 | 905 | ||
906 | error: | 906 | error: |
907 | dst_release(dst_orig); | 907 | dst_release(dst_orig); |
908 | xfrm_pol_put(policy); | 908 | xfrm_pol_put(policy); |
909 | *dst_p = NULL; | 909 | *dst_p = NULL; |
910 | return err; | 910 | return err; |
911 | } | 911 | } |
912 | EXPORT_SYMBOL(xfrm_lookup); | 912 | EXPORT_SYMBOL(xfrm_lookup); |
913 | 913 | ||
914 | /* When skb is transformed back to its "native" form, we have to | 914 | /* When skb is transformed back to its "native" form, we have to |
915 | * check policy restrictions. At the moment we make this in maximally | 915 | * check policy restrictions. At the moment we make this in maximally |
916 | * stupid way. Shame on me. :-) Of course, connected sockets must | 916 | * stupid way. Shame on me. :-) Of course, connected sockets must |
917 | * have policy cached at them. | 917 | * have policy cached at them. |
918 | */ | 918 | */ |
919 | 919 | ||
920 | static inline int | 920 | static inline int |
921 | xfrm_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x, | 921 | xfrm_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x, |
922 | unsigned short family) | 922 | unsigned short family) |
923 | { | 923 | { |
924 | if (xfrm_state_kern(x)) | 924 | if (xfrm_state_kern(x)) |
925 | return tmpl->optional && !xfrm_state_addr_cmp(tmpl, x, family); | 925 | return tmpl->optional && !xfrm_state_addr_cmp(tmpl, x, family); |
926 | return x->id.proto == tmpl->id.proto && | 926 | return x->id.proto == tmpl->id.proto && |
927 | (x->id.spi == tmpl->id.spi || !tmpl->id.spi) && | 927 | (x->id.spi == tmpl->id.spi || !tmpl->id.spi) && |
928 | (x->props.reqid == tmpl->reqid || !tmpl->reqid) && | 928 | (x->props.reqid == tmpl->reqid || !tmpl->reqid) && |
929 | x->props.mode == tmpl->mode && | 929 | x->props.mode == tmpl->mode && |
930 | (tmpl->aalgos & (1<<x->props.aalgo)) && | 930 | (tmpl->aalgos & (1<<x->props.aalgo)) && |
931 | !(x->props.mode && xfrm_state_addr_cmp(tmpl, x, family)); | 931 | !(x->props.mode && xfrm_state_addr_cmp(tmpl, x, family)); |
932 | } | 932 | } |
933 | 933 | ||
934 | static inline int | 934 | static inline int |
935 | xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int start, | 935 | xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int start, |
936 | unsigned short family) | 936 | unsigned short family) |
937 | { | 937 | { |
938 | int idx = start; | 938 | int idx = start; |
939 | 939 | ||
940 | if (tmpl->optional) { | 940 | if (tmpl->optional) { |
941 | if (!tmpl->mode) | 941 | if (!tmpl->mode) |
942 | return start; | 942 | return start; |
943 | } else | 943 | } else |
944 | start = -1; | 944 | start = -1; |
945 | for (; idx < sp->len; idx++) { | 945 | for (; idx < sp->len; idx++) { |
946 | if (xfrm_state_ok(tmpl, sp->xvec[idx], family)) | 946 | if (xfrm_state_ok(tmpl, sp->xvec[idx], family)) |
947 | return ++idx; | 947 | return ++idx; |
948 | if (sp->xvec[idx]->props.mode) | 948 | if (sp->xvec[idx]->props.mode) |
949 | break; | 949 | break; |
950 | } | 950 | } |
951 | return start; | 951 | return start; |
952 | } | 952 | } |
953 | 953 | ||
954 | int | 954 | int |
955 | xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family) | 955 | xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family) |
956 | { | 956 | { |
957 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); | 957 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); |
958 | 958 | ||
959 | if (unlikely(afinfo == NULL)) | 959 | if (unlikely(afinfo == NULL)) |
960 | return -EAFNOSUPPORT; | 960 | return -EAFNOSUPPORT; |
961 | 961 | ||
962 | afinfo->decode_session(skb, fl); | 962 | afinfo->decode_session(skb, fl); |
963 | xfrm_policy_put_afinfo(afinfo); | 963 | xfrm_policy_put_afinfo(afinfo); |
964 | return 0; | 964 | return 0; |
965 | } | 965 | } |
966 | EXPORT_SYMBOL(xfrm_decode_session); | 966 | EXPORT_SYMBOL(xfrm_decode_session); |
967 | 967 | ||
968 | static inline int secpath_has_tunnel(struct sec_path *sp, int k) | 968 | static inline int secpath_has_tunnel(struct sec_path *sp, int k) |
969 | { | 969 | { |
970 | for (; k < sp->len; k++) { | 970 | for (; k < sp->len; k++) { |
971 | if (sp->xvec[k]->props.mode) | 971 | if (sp->xvec[k]->props.mode) |
972 | return 1; | 972 | return 1; |
973 | } | 973 | } |
974 | 974 | ||
975 | return 0; | 975 | return 0; |
976 | } | 976 | } |
977 | 977 | ||
978 | int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | 978 | int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, |
979 | unsigned short family) | 979 | unsigned short family) |
980 | { | 980 | { |
981 | struct xfrm_policy *pol; | 981 | struct xfrm_policy *pol; |
982 | struct flowi fl; | 982 | struct flowi fl; |
983 | u8 fl_dir = policy_to_flow_dir(dir); | 983 | u8 fl_dir = policy_to_flow_dir(dir); |
984 | u32 sk_sid; | 984 | u32 sk_sid; |
985 | 985 | ||
986 | if (xfrm_decode_session(skb, &fl, family) < 0) | 986 | if (xfrm_decode_session(skb, &fl, family) < 0) |
987 | return 0; | 987 | return 0; |
988 | nf_nat_decode_session(skb, &fl, family); | 988 | nf_nat_decode_session(skb, &fl, family); |
989 | 989 | ||
990 | sk_sid = security_sk_sid(sk, &fl, fl_dir); | 990 | sk_sid = security_sk_sid(sk, &fl, fl_dir); |
991 | 991 | ||
992 | /* First, check used SA against their selectors. */ | 992 | /* First, check used SA against their selectors. */ |
993 | if (skb->sp) { | 993 | if (skb->sp) { |
994 | int i; | 994 | int i; |
995 | 995 | ||
996 | for (i=skb->sp->len-1; i>=0; i--) { | 996 | for (i=skb->sp->len-1; i>=0; i--) { |
997 | struct xfrm_state *x = skb->sp->xvec[i]; | 997 | struct xfrm_state *x = skb->sp->xvec[i]; |
998 | if (!xfrm_selector_match(&x->sel, &fl, family)) | 998 | if (!xfrm_selector_match(&x->sel, &fl, family)) |
999 | return 0; | 999 | return 0; |
1000 | } | 1000 | } |
1001 | } | 1001 | } |
1002 | 1002 | ||
1003 | pol = NULL; | 1003 | pol = NULL; |
1004 | if (sk && sk->sk_policy[dir]) | 1004 | if (sk && sk->sk_policy[dir]) |
1005 | pol = xfrm_sk_policy_lookup(sk, dir, &fl, sk_sid); | 1005 | pol = xfrm_sk_policy_lookup(sk, dir, &fl, sk_sid); |
1006 | 1006 | ||
1007 | if (!pol) | 1007 | if (!pol) |
1008 | pol = flow_cache_lookup(&fl, sk_sid, family, fl_dir, | 1008 | pol = flow_cache_lookup(&fl, sk_sid, family, fl_dir, |
1009 | xfrm_policy_lookup); | 1009 | xfrm_policy_lookup); |
1010 | 1010 | ||
1011 | if (!pol) | 1011 | if (!pol) |
1012 | return !skb->sp || !secpath_has_tunnel(skb->sp, 0); | 1012 | return !skb->sp || !secpath_has_tunnel(skb->sp, 0); |
1013 | 1013 | ||
1014 | pol->curlft.use_time = (unsigned long)xtime.tv_sec; | 1014 | pol->curlft.use_time = (unsigned long)xtime.tv_sec; |
1015 | 1015 | ||
1016 | if (pol->action == XFRM_POLICY_ALLOW) { | 1016 | if (pol->action == XFRM_POLICY_ALLOW) { |
1017 | struct sec_path *sp; | 1017 | struct sec_path *sp; |
1018 | static struct sec_path dummy; | 1018 | static struct sec_path dummy; |
1019 | int i, k; | 1019 | int i, k; |
1020 | 1020 | ||
1021 | if ((sp = skb->sp) == NULL) | 1021 | if ((sp = skb->sp) == NULL) |
1022 | sp = &dummy; | 1022 | sp = &dummy; |
1023 | 1023 | ||
1024 | /* For each tunnel xfrm, find the first matching tmpl. | 1024 | /* For each tunnel xfrm, find the first matching tmpl. |
1025 | * For each tmpl before that, find corresponding xfrm. | 1025 | * For each tmpl before that, find corresponding xfrm. |
1026 | * Order is _important_. Later we will implement | 1026 | * Order is _important_. Later we will implement |
1027 | * some barriers, but at the moment barriers | 1027 | * some barriers, but at the moment barriers |
1028 | * are implied between each two transformations. | 1028 | * are implied between each two transformations. |
1029 | */ | 1029 | */ |
1030 | for (i = pol->xfrm_nr-1, k = 0; i >= 0; i--) { | 1030 | for (i = pol->xfrm_nr-1, k = 0; i >= 0; i--) { |
1031 | k = xfrm_policy_ok(pol->xfrm_vec+i, sp, k, family); | 1031 | k = xfrm_policy_ok(pol->xfrm_vec+i, sp, k, family); |
1032 | if (k < 0) | 1032 | if (k < 0) |
1033 | goto reject; | 1033 | goto reject; |
1034 | } | 1034 | } |
1035 | 1035 | ||
1036 | if (secpath_has_tunnel(sp, k)) | 1036 | if (secpath_has_tunnel(sp, k)) |
1037 | goto reject; | 1037 | goto reject; |
1038 | 1038 | ||
1039 | xfrm_pol_put(pol); | 1039 | xfrm_pol_put(pol); |
1040 | return 1; | 1040 | return 1; |
1041 | } | 1041 | } |
1042 | 1042 | ||
1043 | reject: | 1043 | reject: |
1044 | xfrm_pol_put(pol); | 1044 | xfrm_pol_put(pol); |
1045 | return 0; | 1045 | return 0; |
1046 | } | 1046 | } |
1047 | EXPORT_SYMBOL(__xfrm_policy_check); | 1047 | EXPORT_SYMBOL(__xfrm_policy_check); |
1048 | 1048 | ||
1049 | int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) | 1049 | int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) |
1050 | { | 1050 | { |
1051 | struct flowi fl; | 1051 | struct flowi fl; |
1052 | 1052 | ||
1053 | if (xfrm_decode_session(skb, &fl, family) < 0) | 1053 | if (xfrm_decode_session(skb, &fl, family) < 0) |
1054 | return 0; | 1054 | return 0; |
1055 | 1055 | ||
1056 | return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0; | 1056 | return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0; |
1057 | } | 1057 | } |
1058 | EXPORT_SYMBOL(__xfrm_route_forward); | 1058 | EXPORT_SYMBOL(__xfrm_route_forward); |
1059 | 1059 | ||
1060 | static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie) | 1060 | static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie) |
1061 | { | 1061 | { |
1062 | /* If it is marked obsolete, which is how we even get here, | 1062 | /* If it is marked obsolete, which is how we even get here, |
1063 | * then we have purged it from the policy bundle list and we | 1063 | * then we have purged it from the policy bundle list and we |
1064 | * did that for a good reason. | 1064 | * did that for a good reason. |
1065 | */ | 1065 | */ |
1066 | return NULL; | 1066 | return NULL; |
1067 | } | 1067 | } |
1068 | 1068 | ||
1069 | static int stale_bundle(struct dst_entry *dst) | 1069 | static int stale_bundle(struct dst_entry *dst) |
1070 | { | 1070 | { |
1071 | return !xfrm_bundle_ok((struct xfrm_dst *)dst, NULL, AF_UNSPEC); | 1071 | return !xfrm_bundle_ok((struct xfrm_dst *)dst, NULL, AF_UNSPEC); |
1072 | } | 1072 | } |
1073 | 1073 | ||
1074 | void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev) | 1074 | void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev) |
1075 | { | 1075 | { |
1076 | while ((dst = dst->child) && dst->xfrm && dst->dev == dev) { | 1076 | while ((dst = dst->child) && dst->xfrm && dst->dev == dev) { |
1077 | dst->dev = &loopback_dev; | 1077 | dst->dev = &loopback_dev; |
1078 | dev_hold(&loopback_dev); | 1078 | dev_hold(&loopback_dev); |
1079 | dev_put(dev); | 1079 | dev_put(dev); |
1080 | } | 1080 | } |
1081 | } | 1081 | } |
1082 | EXPORT_SYMBOL(xfrm_dst_ifdown); | 1082 | EXPORT_SYMBOL(xfrm_dst_ifdown); |
1083 | 1083 | ||
1084 | static void xfrm_link_failure(struct sk_buff *skb) | 1084 | static void xfrm_link_failure(struct sk_buff *skb) |
1085 | { | 1085 | { |
1086 | /* Impossible. Such dst must be popped before reaches point of failure. */ | 1086 | /* Impossible. Such dst must be popped before reaches point of failure. */ |
1087 | return; | 1087 | return; |
1088 | } | 1088 | } |
1089 | 1089 | ||
1090 | static struct dst_entry *xfrm_negative_advice(struct dst_entry *dst) | 1090 | static struct dst_entry *xfrm_negative_advice(struct dst_entry *dst) |
1091 | { | 1091 | { |
1092 | if (dst) { | 1092 | if (dst) { |
1093 | if (dst->obsolete) { | 1093 | if (dst->obsolete) { |
1094 | dst_release(dst); | 1094 | dst_release(dst); |
1095 | dst = NULL; | 1095 | dst = NULL; |
1096 | } | 1096 | } |
1097 | } | 1097 | } |
1098 | return dst; | 1098 | return dst; |
1099 | } | 1099 | } |
1100 | 1100 | ||
1101 | static void xfrm_prune_bundles(int (*func)(struct dst_entry *)) | 1101 | static void xfrm_prune_bundles(int (*func)(struct dst_entry *)) |
1102 | { | 1102 | { |
1103 | int i; | 1103 | int i; |
1104 | struct xfrm_policy *pol; | 1104 | struct xfrm_policy *pol; |
1105 | struct dst_entry *dst, **dstp, *gc_list = NULL; | 1105 | struct dst_entry *dst, **dstp, *gc_list = NULL; |
1106 | 1106 | ||
1107 | read_lock_bh(&xfrm_policy_lock); | 1107 | read_lock_bh(&xfrm_policy_lock); |
1108 | for (i=0; i<2*XFRM_POLICY_MAX; i++) { | 1108 | for (i=0; i<2*XFRM_POLICY_MAX; i++) { |
1109 | for (pol = xfrm_policy_list[i]; pol; pol = pol->next) { | 1109 | for (pol = xfrm_policy_list[i]; pol; pol = pol->next) { |
1110 | write_lock(&pol->lock); | 1110 | write_lock(&pol->lock); |
1111 | dstp = &pol->bundles; | 1111 | dstp = &pol->bundles; |
1112 | while ((dst=*dstp) != NULL) { | 1112 | while ((dst=*dstp) != NULL) { |
1113 | if (func(dst)) { | 1113 | if (func(dst)) { |
1114 | *dstp = dst->next; | 1114 | *dstp = dst->next; |
1115 | dst->next = gc_list; | 1115 | dst->next = gc_list; |
1116 | gc_list = dst; | 1116 | gc_list = dst; |
1117 | } else { | 1117 | } else { |
1118 | dstp = &dst->next; | 1118 | dstp = &dst->next; |
1119 | } | 1119 | } |
1120 | } | 1120 | } |
1121 | write_unlock(&pol->lock); | 1121 | write_unlock(&pol->lock); |
1122 | } | 1122 | } |
1123 | } | 1123 | } |
1124 | read_unlock_bh(&xfrm_policy_lock); | 1124 | read_unlock_bh(&xfrm_policy_lock); |
1125 | 1125 | ||
1126 | while (gc_list) { | 1126 | while (gc_list) { |
1127 | dst = gc_list; | 1127 | dst = gc_list; |
1128 | gc_list = dst->next; | 1128 | gc_list = dst->next; |
1129 | dst_free(dst); | 1129 | dst_free(dst); |
1130 | } | 1130 | } |
1131 | } | 1131 | } |
1132 | 1132 | ||
1133 | static int unused_bundle(struct dst_entry *dst) | 1133 | static int unused_bundle(struct dst_entry *dst) |
1134 | { | 1134 | { |
1135 | return !atomic_read(&dst->__refcnt); | 1135 | return !atomic_read(&dst->__refcnt); |
1136 | } | 1136 | } |
1137 | 1137 | ||
1138 | static void __xfrm_garbage_collect(void) | 1138 | static void __xfrm_garbage_collect(void) |
1139 | { | 1139 | { |
1140 | xfrm_prune_bundles(unused_bundle); | 1140 | xfrm_prune_bundles(unused_bundle); |
1141 | } | 1141 | } |
1142 | 1142 | ||
1143 | int xfrm_flush_bundles(void) | 1143 | int xfrm_flush_bundles(void) |
1144 | { | 1144 | { |
1145 | xfrm_prune_bundles(stale_bundle); | 1145 | xfrm_prune_bundles(stale_bundle); |
1146 | return 0; | 1146 | return 0; |
1147 | } | 1147 | } |
1148 | 1148 | ||
1149 | static int always_true(struct dst_entry *dst) | 1149 | static int always_true(struct dst_entry *dst) |
1150 | { | 1150 | { |
1151 | return 1; | 1151 | return 1; |
1152 | } | 1152 | } |
1153 | 1153 | ||
1154 | void xfrm_flush_all_bundles(void) | 1154 | void xfrm_flush_all_bundles(void) |
1155 | { | 1155 | { |
1156 | xfrm_prune_bundles(always_true); | 1156 | xfrm_prune_bundles(always_true); |
1157 | } | 1157 | } |
1158 | 1158 | ||
1159 | void xfrm_init_pmtu(struct dst_entry *dst) | 1159 | void xfrm_init_pmtu(struct dst_entry *dst) |
1160 | { | 1160 | { |
1161 | do { | 1161 | do { |
1162 | struct xfrm_dst *xdst = (struct xfrm_dst *)dst; | 1162 | struct xfrm_dst *xdst = (struct xfrm_dst *)dst; |
1163 | u32 pmtu, route_mtu_cached; | 1163 | u32 pmtu, route_mtu_cached; |
1164 | 1164 | ||
1165 | pmtu = dst_mtu(dst->child); | 1165 | pmtu = dst_mtu(dst->child); |
1166 | xdst->child_mtu_cached = pmtu; | 1166 | xdst->child_mtu_cached = pmtu; |
1167 | 1167 | ||
1168 | pmtu = xfrm_state_mtu(dst->xfrm, pmtu); | 1168 | pmtu = xfrm_state_mtu(dst->xfrm, pmtu); |
1169 | 1169 | ||
1170 | route_mtu_cached = dst_mtu(xdst->route); | 1170 | route_mtu_cached = dst_mtu(xdst->route); |
1171 | xdst->route_mtu_cached = route_mtu_cached; | 1171 | xdst->route_mtu_cached = route_mtu_cached; |
1172 | 1172 | ||
1173 | if (pmtu > route_mtu_cached) | 1173 | if (pmtu > route_mtu_cached) |
1174 | pmtu = route_mtu_cached; | 1174 | pmtu = route_mtu_cached; |
1175 | 1175 | ||
1176 | dst->metrics[RTAX_MTU-1] = pmtu; | 1176 | dst->metrics[RTAX_MTU-1] = pmtu; |
1177 | } while ((dst = dst->next)); | 1177 | } while ((dst = dst->next)); |
1178 | } | 1178 | } |
1179 | 1179 | ||
1180 | EXPORT_SYMBOL(xfrm_init_pmtu); | 1180 | EXPORT_SYMBOL(xfrm_init_pmtu); |
1181 | 1181 | ||
1182 | /* Check that the bundle accepts the flow and its components are | 1182 | /* Check that the bundle accepts the flow and its components are |
1183 | * still valid. | 1183 | * still valid. |
1184 | */ | 1184 | */ |
1185 | 1185 | ||
1186 | int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family) | 1186 | int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family) |
1187 | { | 1187 | { |
1188 | struct dst_entry *dst = &first->u.dst; | 1188 | struct dst_entry *dst = &first->u.dst; |
1189 | struct xfrm_dst *last; | 1189 | struct xfrm_dst *last; |
1190 | u32 mtu; | 1190 | u32 mtu; |
1191 | 1191 | ||
1192 | if (!dst_check(dst->path, ((struct xfrm_dst *)dst)->path_cookie) || | 1192 | if (!dst_check(dst->path, ((struct xfrm_dst *)dst)->path_cookie) || |
1193 | (dst->dev && !netif_running(dst->dev))) | 1193 | (dst->dev && !netif_running(dst->dev))) |
1194 | return 0; | 1194 | return 0; |
1195 | 1195 | ||
1196 | last = NULL; | 1196 | last = NULL; |
1197 | 1197 | ||
1198 | do { | 1198 | do { |
1199 | struct xfrm_dst *xdst = (struct xfrm_dst *)dst; | 1199 | struct xfrm_dst *xdst = (struct xfrm_dst *)dst; |
1200 | 1200 | ||
1201 | if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family)) | 1201 | if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family)) |
1202 | return 0; | 1202 | return 0; |
1203 | if (dst->xfrm->km.state != XFRM_STATE_VALID) | 1203 | if (dst->xfrm->km.state != XFRM_STATE_VALID) |
1204 | return 0; | 1204 | return 0; |
1205 | 1205 | ||
1206 | mtu = dst_mtu(dst->child); | 1206 | mtu = dst_mtu(dst->child); |
1207 | if (xdst->child_mtu_cached != mtu) { | 1207 | if (xdst->child_mtu_cached != mtu) { |
1208 | last = xdst; | 1208 | last = xdst; |
1209 | xdst->child_mtu_cached = mtu; | 1209 | xdst->child_mtu_cached = mtu; |
1210 | } | 1210 | } |
1211 | 1211 | ||
1212 | if (!dst_check(xdst->route, xdst->route_cookie)) | 1212 | if (!dst_check(xdst->route, xdst->route_cookie)) |
1213 | return 0; | 1213 | return 0; |
1214 | mtu = dst_mtu(xdst->route); | 1214 | mtu = dst_mtu(xdst->route); |
1215 | if (xdst->route_mtu_cached != mtu) { | 1215 | if (xdst->route_mtu_cached != mtu) { |
1216 | last = xdst; | 1216 | last = xdst; |
1217 | xdst->route_mtu_cached = mtu; | 1217 | xdst->route_mtu_cached = mtu; |
1218 | } | 1218 | } |
1219 | 1219 | ||
1220 | dst = dst->child; | 1220 | dst = dst->child; |
1221 | } while (dst->xfrm); | 1221 | } while (dst->xfrm); |
1222 | 1222 | ||
1223 | if (likely(!last)) | 1223 | if (likely(!last)) |
1224 | return 1; | 1224 | return 1; |
1225 | 1225 | ||
1226 | mtu = last->child_mtu_cached; | 1226 | mtu = last->child_mtu_cached; |
1227 | for (;;) { | 1227 | for (;;) { |
1228 | dst = &last->u.dst; | 1228 | dst = &last->u.dst; |
1229 | 1229 | ||
1230 | mtu = xfrm_state_mtu(dst->xfrm, mtu); | 1230 | mtu = xfrm_state_mtu(dst->xfrm, mtu); |
1231 | if (mtu > last->route_mtu_cached) | 1231 | if (mtu > last->route_mtu_cached) |
1232 | mtu = last->route_mtu_cached; | 1232 | mtu = last->route_mtu_cached; |
1233 | dst->metrics[RTAX_MTU-1] = mtu; | 1233 | dst->metrics[RTAX_MTU-1] = mtu; |
1234 | 1234 | ||
1235 | if (last == first) | 1235 | if (last == first) |
1236 | break; | 1236 | break; |
1237 | 1237 | ||
1238 | last = last->u.next; | 1238 | last = last->u.next; |
1239 | last->child_mtu_cached = mtu; | 1239 | last->child_mtu_cached = mtu; |
1240 | } | 1240 | } |
1241 | 1241 | ||
1242 | return 1; | 1242 | return 1; |
1243 | } | 1243 | } |
1244 | 1244 | ||
1245 | EXPORT_SYMBOL(xfrm_bundle_ok); | 1245 | EXPORT_SYMBOL(xfrm_bundle_ok); |
1246 | 1246 | ||
1247 | int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) | 1247 | int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) |
1248 | { | 1248 | { |
1249 | int err = 0; | 1249 | int err = 0; |
1250 | if (unlikely(afinfo == NULL)) | 1250 | if (unlikely(afinfo == NULL)) |
1251 | return -EINVAL; | 1251 | return -EINVAL; |
1252 | if (unlikely(afinfo->family >= NPROTO)) | 1252 | if (unlikely(afinfo->family >= NPROTO)) |
1253 | return -EAFNOSUPPORT; | 1253 | return -EAFNOSUPPORT; |
1254 | write_lock(&xfrm_policy_afinfo_lock); | 1254 | write_lock_bh(&xfrm_policy_afinfo_lock); |
1255 | if (unlikely(xfrm_policy_afinfo[afinfo->family] != NULL)) | 1255 | if (unlikely(xfrm_policy_afinfo[afinfo->family] != NULL)) |
1256 | err = -ENOBUFS; | 1256 | err = -ENOBUFS; |
1257 | else { | 1257 | else { |
1258 | struct dst_ops *dst_ops = afinfo->dst_ops; | 1258 | struct dst_ops *dst_ops = afinfo->dst_ops; |
1259 | if (likely(dst_ops->kmem_cachep == NULL)) | 1259 | if (likely(dst_ops->kmem_cachep == NULL)) |
1260 | dst_ops->kmem_cachep = xfrm_dst_cache; | 1260 | dst_ops->kmem_cachep = xfrm_dst_cache; |
1261 | if (likely(dst_ops->check == NULL)) | 1261 | if (likely(dst_ops->check == NULL)) |
1262 | dst_ops->check = xfrm_dst_check; | 1262 | dst_ops->check = xfrm_dst_check; |
1263 | if (likely(dst_ops->negative_advice == NULL)) | 1263 | if (likely(dst_ops->negative_advice == NULL)) |
1264 | dst_ops->negative_advice = xfrm_negative_advice; | 1264 | dst_ops->negative_advice = xfrm_negative_advice; |
1265 | if (likely(dst_ops->link_failure == NULL)) | 1265 | if (likely(dst_ops->link_failure == NULL)) |
1266 | dst_ops->link_failure = xfrm_link_failure; | 1266 | dst_ops->link_failure = xfrm_link_failure; |
1267 | if (likely(afinfo->garbage_collect == NULL)) | 1267 | if (likely(afinfo->garbage_collect == NULL)) |
1268 | afinfo->garbage_collect = __xfrm_garbage_collect; | 1268 | afinfo->garbage_collect = __xfrm_garbage_collect; |
1269 | xfrm_policy_afinfo[afinfo->family] = afinfo; | 1269 | xfrm_policy_afinfo[afinfo->family] = afinfo; |
1270 | } | 1270 | } |
1271 | write_unlock(&xfrm_policy_afinfo_lock); | 1271 | write_unlock_bh(&xfrm_policy_afinfo_lock); |
1272 | return err; | 1272 | return err; |
1273 | } | 1273 | } |
1274 | EXPORT_SYMBOL(xfrm_policy_register_afinfo); | 1274 | EXPORT_SYMBOL(xfrm_policy_register_afinfo); |
1275 | 1275 | ||
1276 | int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo) | 1276 | int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo) |
1277 | { | 1277 | { |
1278 | int err = 0; | 1278 | int err = 0; |
1279 | if (unlikely(afinfo == NULL)) | 1279 | if (unlikely(afinfo == NULL)) |
1280 | return -EINVAL; | 1280 | return -EINVAL; |
1281 | if (unlikely(afinfo->family >= NPROTO)) | 1281 | if (unlikely(afinfo->family >= NPROTO)) |
1282 | return -EAFNOSUPPORT; | 1282 | return -EAFNOSUPPORT; |
1283 | write_lock(&xfrm_policy_afinfo_lock); | 1283 | write_lock_bh(&xfrm_policy_afinfo_lock); |
1284 | if (likely(xfrm_policy_afinfo[afinfo->family] != NULL)) { | 1284 | if (likely(xfrm_policy_afinfo[afinfo->family] != NULL)) { |
1285 | if (unlikely(xfrm_policy_afinfo[afinfo->family] != afinfo)) | 1285 | if (unlikely(xfrm_policy_afinfo[afinfo->family] != afinfo)) |
1286 | err = -EINVAL; | 1286 | err = -EINVAL; |
1287 | else { | 1287 | else { |
1288 | struct dst_ops *dst_ops = afinfo->dst_ops; | 1288 | struct dst_ops *dst_ops = afinfo->dst_ops; |
1289 | xfrm_policy_afinfo[afinfo->family] = NULL; | 1289 | xfrm_policy_afinfo[afinfo->family] = NULL; |
1290 | dst_ops->kmem_cachep = NULL; | 1290 | dst_ops->kmem_cachep = NULL; |
1291 | dst_ops->check = NULL; | 1291 | dst_ops->check = NULL; |
1292 | dst_ops->negative_advice = NULL; | 1292 | dst_ops->negative_advice = NULL; |
1293 | dst_ops->link_failure = NULL; | 1293 | dst_ops->link_failure = NULL; |
1294 | afinfo->garbage_collect = NULL; | 1294 | afinfo->garbage_collect = NULL; |
1295 | } | 1295 | } |
1296 | } | 1296 | } |
1297 | write_unlock(&xfrm_policy_afinfo_lock); | 1297 | write_unlock_bh(&xfrm_policy_afinfo_lock); |
1298 | return err; | 1298 | return err; |
1299 | } | 1299 | } |
1300 | EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); | 1300 | EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); |
1301 | 1301 | ||
1302 | static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family) | 1302 | static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family) |
1303 | { | 1303 | { |
1304 | struct xfrm_policy_afinfo *afinfo; | 1304 | struct xfrm_policy_afinfo *afinfo; |
1305 | if (unlikely(family >= NPROTO)) | 1305 | if (unlikely(family >= NPROTO)) |
1306 | return NULL; | 1306 | return NULL; |
1307 | read_lock(&xfrm_policy_afinfo_lock); | 1307 | read_lock(&xfrm_policy_afinfo_lock); |
1308 | afinfo = xfrm_policy_afinfo[family]; | 1308 | afinfo = xfrm_policy_afinfo[family]; |
1309 | if (likely(afinfo != NULL)) | 1309 | if (likely(afinfo != NULL)) |
1310 | read_lock(&afinfo->lock); | 1310 | read_lock(&afinfo->lock); |
1311 | read_unlock(&xfrm_policy_afinfo_lock); | 1311 | read_unlock(&xfrm_policy_afinfo_lock); |
1312 | return afinfo; | 1312 | return afinfo; |
1313 | } | 1313 | } |
1314 | 1314 | ||
1315 | static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo) | 1315 | static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo) |
1316 | { | 1316 | { |
1317 | if (unlikely(afinfo == NULL)) | 1317 | if (unlikely(afinfo == NULL)) |
1318 | return; | 1318 | return; |
1319 | read_unlock(&afinfo->lock); | 1319 | read_unlock(&afinfo->lock); |
1320 | } | 1320 | } |
1321 | 1321 | ||
1322 | static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr) | 1322 | static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr) |
1323 | { | 1323 | { |
1324 | switch (event) { | 1324 | switch (event) { |
1325 | case NETDEV_DOWN: | 1325 | case NETDEV_DOWN: |
1326 | xfrm_flush_bundles(); | 1326 | xfrm_flush_bundles(); |
1327 | } | 1327 | } |
1328 | return NOTIFY_DONE; | 1328 | return NOTIFY_DONE; |
1329 | } | 1329 | } |
1330 | 1330 | ||
1331 | static struct notifier_block xfrm_dev_notifier = { | 1331 | static struct notifier_block xfrm_dev_notifier = { |
1332 | xfrm_dev_event, | 1332 | xfrm_dev_event, |
1333 | NULL, | 1333 | NULL, |
1334 | 0 | 1334 | 0 |
1335 | }; | 1335 | }; |
1336 | 1336 | ||
1337 | static void __init xfrm_policy_init(void) | 1337 | static void __init xfrm_policy_init(void) |
1338 | { | 1338 | { |
1339 | xfrm_dst_cache = kmem_cache_create("xfrm_dst_cache", | 1339 | xfrm_dst_cache = kmem_cache_create("xfrm_dst_cache", |
1340 | sizeof(struct xfrm_dst), | 1340 | sizeof(struct xfrm_dst), |
1341 | 0, SLAB_HWCACHE_ALIGN, | 1341 | 0, SLAB_HWCACHE_ALIGN, |
1342 | NULL, NULL); | 1342 | NULL, NULL); |
1343 | if (!xfrm_dst_cache) | 1343 | if (!xfrm_dst_cache) |
1344 | panic("XFRM: failed to allocate xfrm_dst_cache\n"); | 1344 | panic("XFRM: failed to allocate xfrm_dst_cache\n"); |
1345 | 1345 | ||
1346 | INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task, NULL); | 1346 | INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task, NULL); |
1347 | register_netdevice_notifier(&xfrm_dev_notifier); | 1347 | register_netdevice_notifier(&xfrm_dev_notifier); |
1348 | } | 1348 | } |
1349 | 1349 | ||
1350 | void __init xfrm_init(void) | 1350 | void __init xfrm_init(void) |
1351 | { | 1351 | { |
1352 | xfrm_state_init(); | 1352 | xfrm_state_init(); |
1353 | xfrm_policy_init(); | 1353 | xfrm_policy_init(); |
1354 | xfrm_input_init(); | 1354 | xfrm_input_init(); |
1355 | } | 1355 | } |
1356 | 1356 | ||
1357 | 1357 |