diff options
Diffstat (limited to 'net/xfrm/xfrm_policy.c')
| -rw-r--r-- | net/xfrm/xfrm_policy.c | 71 |
1 files changed, 70 insertions, 1 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 762926009c04..263e34e45265 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
| @@ -579,8 +579,22 @@ static inline int xfrm_byidx_should_resize(int total) | |||
| 579 | return 0; | 579 | return 0; |
| 580 | } | 580 | } |
| 581 | 581 | ||
| 582 | static DEFINE_MUTEX(hash_resize_mutex); | 582 | void xfrm_spd_getinfo(struct xfrm_spdinfo *si) |
| 583 | { | ||
| 584 | read_lock_bh(&xfrm_policy_lock); | ||
| 585 | si->incnt = xfrm_policy_count[XFRM_POLICY_IN]; | ||
| 586 | si->outcnt = xfrm_policy_count[XFRM_POLICY_OUT]; | ||
| 587 | si->fwdcnt = xfrm_policy_count[XFRM_POLICY_FWD]; | ||
| 588 | si->inscnt = xfrm_policy_count[XFRM_POLICY_IN+XFRM_POLICY_MAX]; | ||
| 589 | si->outscnt = xfrm_policy_count[XFRM_POLICY_OUT+XFRM_POLICY_MAX]; | ||
| 590 | si->fwdscnt = xfrm_policy_count[XFRM_POLICY_FWD+XFRM_POLICY_MAX]; | ||
| 591 | si->spdhcnt = xfrm_idx_hmask; | ||
| 592 | si->spdhmcnt = xfrm_policy_hashmax; | ||
| 593 | read_unlock_bh(&xfrm_policy_lock); | ||
| 594 | } | ||
| 595 | EXPORT_SYMBOL(xfrm_spd_getinfo); | ||
| 583 | 596 | ||
| 597 | static DEFINE_MUTEX(hash_resize_mutex); | ||
| 584 | static void xfrm_hash_resize(struct work_struct *__unused) | 598 | static void xfrm_hash_resize(struct work_struct *__unused) |
| 585 | { | 599 | { |
| 586 | int dir, total; | 600 | int dir, total; |
| @@ -1330,6 +1344,40 @@ xfrm_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int nx, | |||
| 1330 | return err; | 1344 | return err; |
| 1331 | } | 1345 | } |
| 1332 | 1346 | ||
| 1347 | static int inline | ||
| 1348 | xfrm_dst_alloc_copy(void **target, void *src, int size) | ||
| 1349 | { | ||
| 1350 | if (!*target) { | ||
| 1351 | *target = kmalloc(size, GFP_ATOMIC); | ||
| 1352 | if (!*target) | ||
| 1353 | return -ENOMEM; | ||
| 1354 | } | ||
| 1355 | memcpy(*target, src, size); | ||
| 1356 | return 0; | ||
| 1357 | } | ||
| 1358 | |||
| 1359 | static int inline | ||
| 1360 | xfrm_dst_update_parent(struct dst_entry *dst, struct xfrm_selector *sel) | ||
| 1361 | { | ||
| 1362 | #ifdef CONFIG_XFRM_SUB_POLICY | ||
| 1363 | struct xfrm_dst *xdst = (struct xfrm_dst *)dst; | ||
| 1364 | return xfrm_dst_alloc_copy((void **)&(xdst->partner), | ||
| 1365 | sel, sizeof(*sel)); | ||
| 1366 | #else | ||
| 1367 | return 0; | ||
| 1368 | #endif | ||
| 1369 | } | ||
| 1370 | |||
| 1371 | static int inline | ||
| 1372 | xfrm_dst_update_origin(struct dst_entry *dst, struct flowi *fl) | ||
| 1373 | { | ||
| 1374 | #ifdef CONFIG_XFRM_SUB_POLICY | ||
| 1375 | struct xfrm_dst *xdst = (struct xfrm_dst *)dst; | ||
| 1376 | return xfrm_dst_alloc_copy((void **)&(xdst->origin), fl, sizeof(*fl)); | ||
| 1377 | #else | ||
| 1378 | return 0; | ||
| 1379 | #endif | ||
| 1380 | } | ||
| 1333 | 1381 | ||
| 1334 | static int stale_bundle(struct dst_entry *dst); | 1382 | static int stale_bundle(struct dst_entry *dst); |
| 1335 | 1383 | ||
| @@ -1518,6 +1566,18 @@ restart: | |||
| 1518 | err = -EHOSTUNREACH; | 1566 | err = -EHOSTUNREACH; |
| 1519 | goto error; | 1567 | goto error; |
| 1520 | } | 1568 | } |
| 1569 | |||
| 1570 | if (npols > 1) | ||
| 1571 | err = xfrm_dst_update_parent(dst, &pols[1]->selector); | ||
| 1572 | else | ||
| 1573 | err = xfrm_dst_update_origin(dst, fl); | ||
| 1574 | if (unlikely(err)) { | ||
| 1575 | write_unlock_bh(&policy->lock); | ||
| 1576 | if (dst) | ||
| 1577 | dst_free(dst); | ||
| 1578 | goto error; | ||
| 1579 | } | ||
| 1580 | |||
| 1521 | dst->next = policy->bundles; | 1581 | dst->next = policy->bundles; |
| 1522 | policy->bundles = dst; | 1582 | policy->bundles = dst; |
| 1523 | dst_hold(dst); | 1583 | dst_hold(dst); |
| @@ -1933,6 +1993,15 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first, | |||
| 1933 | if (!dst_check(dst->path, ((struct xfrm_dst *)dst)->path_cookie) || | 1993 | if (!dst_check(dst->path, ((struct xfrm_dst *)dst)->path_cookie) || |
| 1934 | (dst->dev && !netif_running(dst->dev))) | 1994 | (dst->dev && !netif_running(dst->dev))) |
| 1935 | return 0; | 1995 | return 0; |
| 1996 | #ifdef CONFIG_XFRM_SUB_POLICY | ||
| 1997 | if (fl) { | ||
| 1998 | if (first->origin && !flow_cache_uli_match(first->origin, fl)) | ||
| 1999 | return 0; | ||
| 2000 | if (first->partner && | ||
| 2001 | !xfrm_selector_match(first->partner, fl, family)) | ||
| 2002 | return 0; | ||
| 2003 | } | ||
| 2004 | #endif | ||
| 1936 | 2005 | ||
| 1937 | last = NULL; | 2006 | last = NULL; |
| 1938 | 2007 | ||
