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.c186
1 files changed, 71 insertions, 115 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 178baaa037e5..3edbf4b26116 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -173,7 +173,7 @@ static DEFINE_SPINLOCK(xfrm_state_gc_lock);
173int __xfrm_state_delete(struct xfrm_state *x); 173int __xfrm_state_delete(struct xfrm_state *x);
174 174
175int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); 175int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
176bool km_is_alive(const struct km_event *c); 176static bool km_is_alive(const struct km_event *c);
177void km_state_expired(struct xfrm_state *x, int hard, u32 portid); 177void km_state_expired(struct xfrm_state *x, int hard, u32 portid);
178 178
179static DEFINE_SPINLOCK(xfrm_type_lock); 179static DEFINE_SPINLOCK(xfrm_type_lock);
@@ -330,100 +330,67 @@ static void xfrm_put_type_offload(const struct xfrm_type_offload *type)
330 module_put(type->owner); 330 module_put(type->owner);
331} 331}
332 332
333static DEFINE_SPINLOCK(xfrm_mode_lock); 333static const struct xfrm_mode xfrm4_mode_map[XFRM_MODE_MAX] = {
334int xfrm_register_mode(struct xfrm_mode *mode, int family) 334 [XFRM_MODE_BEET] = {
335{ 335 .encap = XFRM_MODE_BEET,
336 struct xfrm_state_afinfo *afinfo; 336 .flags = XFRM_MODE_FLAG_TUNNEL,
337 struct xfrm_mode **modemap; 337 .family = AF_INET,
338 int err; 338 },
339 339 [XFRM_MODE_TRANSPORT] = {
340 if (unlikely(mode->encap >= XFRM_MODE_MAX)) 340 .encap = XFRM_MODE_TRANSPORT,
341 return -EINVAL; 341 .family = AF_INET,
342 342 },
343 afinfo = xfrm_state_get_afinfo(family); 343 [XFRM_MODE_TUNNEL] = {
344 if (unlikely(afinfo == NULL)) 344 .encap = XFRM_MODE_TUNNEL,
345 return -EAFNOSUPPORT; 345 .flags = XFRM_MODE_FLAG_TUNNEL,
346 346 .family = AF_INET,
347 err = -EEXIST; 347 },
348 modemap = afinfo->mode_map; 348};
349 spin_lock_bh(&xfrm_mode_lock); 349
350 if (modemap[mode->encap]) 350static const struct xfrm_mode xfrm6_mode_map[XFRM_MODE_MAX] = {
351 goto out; 351 [XFRM_MODE_BEET] = {
352 352 .encap = XFRM_MODE_BEET,
353 err = -ENOENT; 353 .flags = XFRM_MODE_FLAG_TUNNEL,
354 if (!try_module_get(afinfo->owner)) 354 .family = AF_INET6,
355 goto out; 355 },
356 356 [XFRM_MODE_ROUTEOPTIMIZATION] = {
357 mode->afinfo = afinfo; 357 .encap = XFRM_MODE_ROUTEOPTIMIZATION,
358 modemap[mode->encap] = mode; 358 .family = AF_INET6,
359 err = 0; 359 },
360 360 [XFRM_MODE_TRANSPORT] = {
361out: 361 .encap = XFRM_MODE_TRANSPORT,
362 spin_unlock_bh(&xfrm_mode_lock); 362 .family = AF_INET6,
363 rcu_read_unlock(); 363 },
364 return err; 364 [XFRM_MODE_TUNNEL] = {
365} 365 .encap = XFRM_MODE_TUNNEL,
366EXPORT_SYMBOL(xfrm_register_mode); 366 .flags = XFRM_MODE_FLAG_TUNNEL,
367 367 .family = AF_INET6,
368int xfrm_unregister_mode(struct xfrm_mode *mode, int family) 368 },
369{ 369};
370 struct xfrm_state_afinfo *afinfo; 370
371 struct xfrm_mode **modemap; 371static const struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family)
372 int err; 372{
373 373 const struct xfrm_mode *mode;
374 if (unlikely(mode->encap >= XFRM_MODE_MAX))
375 return -EINVAL;
376
377 afinfo = xfrm_state_get_afinfo(family);
378 if (unlikely(afinfo == NULL))
379 return -EAFNOSUPPORT;
380
381 err = -ENOENT;
382 modemap = afinfo->mode_map;
383 spin_lock_bh(&xfrm_mode_lock);
384 if (likely(modemap[mode->encap] == mode)) {
385 modemap[mode->encap] = NULL;
386 module_put(mode->afinfo->owner);
387 err = 0;
388 }
389
390 spin_unlock_bh(&xfrm_mode_lock);
391 rcu_read_unlock();
392 return err;
393}
394EXPORT_SYMBOL(xfrm_unregister_mode);
395
396static struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family)
397{
398 struct xfrm_state_afinfo *afinfo;
399 struct xfrm_mode *mode;
400 int modload_attempted = 0;
401 374
402 if (unlikely(encap >= XFRM_MODE_MAX)) 375 if (unlikely(encap >= XFRM_MODE_MAX))
403 return NULL; 376 return NULL;
404 377
405retry: 378 switch (family) {
406 afinfo = xfrm_state_get_afinfo(family); 379 case AF_INET:
407 if (unlikely(afinfo == NULL)) 380 mode = &xfrm4_mode_map[encap];
408 return NULL; 381 if (mode->family == family)
409 382 return mode;
410 mode = READ_ONCE(afinfo->mode_map[encap]); 383 break;
411 if (unlikely(mode && !try_module_get(mode->owner))) 384 case AF_INET6:
412 mode = NULL; 385 mode = &xfrm6_mode_map[encap];
413 386 if (mode->family == family)
414 rcu_read_unlock(); 387 return mode;
415 if (!mode && !modload_attempted) { 388 break;
416 request_module("xfrm-mode-%d-%d", family, encap); 389 default:
417 modload_attempted = 1; 390 break;
418 goto retry;
419 } 391 }
420 392
421 return mode; 393 return NULL;
422}
423
424static void xfrm_put_mode(struct xfrm_mode *mode)
425{
426 module_put(mode->owner);
427} 394}
428 395
429void xfrm_state_free(struct xfrm_state *x) 396void xfrm_state_free(struct xfrm_state *x)
@@ -444,12 +411,6 @@ static void ___xfrm_state_destroy(struct xfrm_state *x)
444 kfree(x->coaddr); 411 kfree(x->coaddr);
445 kfree(x->replay_esn); 412 kfree(x->replay_esn);
446 kfree(x->preplay_esn); 413 kfree(x->preplay_esn);
447 if (x->inner_mode)
448 xfrm_put_mode(x->inner_mode);
449 if (x->inner_mode_iaf)
450 xfrm_put_mode(x->inner_mode_iaf);
451 if (x->outer_mode)
452 xfrm_put_mode(x->outer_mode);
453 if (x->type_offload) 414 if (x->type_offload)
454 xfrm_put_type_offload(x->type_offload); 415 xfrm_put_type_offload(x->type_offload);
455 if (x->type) { 416 if (x->type) {
@@ -590,8 +551,6 @@ struct xfrm_state *xfrm_state_alloc(struct net *net)
590 x->lft.hard_packet_limit = XFRM_INF; 551 x->lft.hard_packet_limit = XFRM_INF;
591 x->replay_maxage = 0; 552 x->replay_maxage = 0;
592 x->replay_maxdiff = 0; 553 x->replay_maxdiff = 0;
593 x->inner_mode = NULL;
594 x->inner_mode_iaf = NULL;
595 spin_lock_init(&x->lock); 554 spin_lock_init(&x->lock);
596 } 555 }
597 return x; 556 return x;
@@ -2066,7 +2025,7 @@ int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address
2066} 2025}
2067EXPORT_SYMBOL(km_report); 2026EXPORT_SYMBOL(km_report);
2068 2027
2069bool km_is_alive(const struct km_event *c) 2028static bool km_is_alive(const struct km_event *c)
2070{ 2029{
2071 struct xfrm_mgr *km; 2030 struct xfrm_mgr *km;
2072 bool is_alive = false; 2031 bool is_alive = false;
@@ -2082,7 +2041,6 @@ bool km_is_alive(const struct km_event *c)
2082 2041
2083 return is_alive; 2042 return is_alive;
2084} 2043}
2085EXPORT_SYMBOL(km_is_alive);
2086 2044
2087int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen) 2045int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen)
2088{ 2046{
@@ -2195,6 +2153,7 @@ struct xfrm_state_afinfo *xfrm_state_afinfo_get_rcu(unsigned int family)
2195 2153
2196 return rcu_dereference(xfrm_state_afinfo[family]); 2154 return rcu_dereference(xfrm_state_afinfo[family]);
2197} 2155}
2156EXPORT_SYMBOL_GPL(xfrm_state_afinfo_get_rcu);
2198 2157
2199struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family) 2158struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family)
2200{ 2159{
@@ -2242,8 +2201,9 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu)
2242 2201
2243int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload) 2202int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
2244{ 2203{
2245 struct xfrm_state_afinfo *afinfo; 2204 const struct xfrm_state_afinfo *afinfo;
2246 struct xfrm_mode *inner_mode; 2205 const struct xfrm_mode *inner_mode;
2206 const struct xfrm_mode *outer_mode;
2247 int family = x->props.family; 2207 int family = x->props.family;
2248 int err; 2208 int err;
2249 2209
@@ -2269,25 +2229,22 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
2269 goto error; 2229 goto error;
2270 2230
2271 if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) && 2231 if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
2272 family != x->sel.family) { 2232 family != x->sel.family)
2273 xfrm_put_mode(inner_mode);
2274 goto error; 2233 goto error;
2275 }
2276 2234
2277 x->inner_mode = inner_mode; 2235 x->inner_mode = *inner_mode;
2278 } else { 2236 } else {
2279 struct xfrm_mode *inner_mode_iaf; 2237 const struct xfrm_mode *inner_mode_iaf;
2280 int iafamily = AF_INET; 2238 int iafamily = AF_INET;
2281 2239
2282 inner_mode = xfrm_get_mode(x->props.mode, x->props.family); 2240 inner_mode = xfrm_get_mode(x->props.mode, x->props.family);
2283 if (inner_mode == NULL) 2241 if (inner_mode == NULL)
2284 goto error; 2242 goto error;
2285 2243
2286 if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL)) { 2244 if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL))
2287 xfrm_put_mode(inner_mode);
2288 goto error; 2245 goto error;
2289 } 2246
2290 x->inner_mode = inner_mode; 2247 x->inner_mode = *inner_mode;
2291 2248
2292 if (x->props.family == AF_INET) 2249 if (x->props.family == AF_INET)
2293 iafamily = AF_INET6; 2250 iafamily = AF_INET6;
@@ -2295,9 +2252,7 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
2295 inner_mode_iaf = xfrm_get_mode(x->props.mode, iafamily); 2252 inner_mode_iaf = xfrm_get_mode(x->props.mode, iafamily);
2296 if (inner_mode_iaf) { 2253 if (inner_mode_iaf) {
2297 if (inner_mode_iaf->flags & XFRM_MODE_FLAG_TUNNEL) 2254 if (inner_mode_iaf->flags & XFRM_MODE_FLAG_TUNNEL)
2298 x->inner_mode_iaf = inner_mode_iaf; 2255 x->inner_mode_iaf = *inner_mode_iaf;
2299 else
2300 xfrm_put_mode(inner_mode_iaf);
2301 } 2256 }
2302 } 2257 }
2303 2258
@@ -2311,12 +2266,13 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
2311 if (err) 2266 if (err)
2312 goto error; 2267 goto error;
2313 2268
2314 x->outer_mode = xfrm_get_mode(x->props.mode, family); 2269 outer_mode = xfrm_get_mode(x->props.mode, family);
2315 if (x->outer_mode == NULL) { 2270 if (!outer_mode) {
2316 err = -EPROTONOSUPPORT; 2271 err = -EPROTONOSUPPORT;
2317 goto error; 2272 goto error;
2318 } 2273 }
2319 2274
2275 x->outer_mode = *outer_mode;
2320 if (init_replay) { 2276 if (init_replay) {
2321 err = xfrm_init_replay(x); 2277 err = xfrm_init_replay(x);
2322 if (err) 2278 if (err)