aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_policy.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm/xfrm_policy.c')
-rw-r--r--net/xfrm/xfrm_policy.c71
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
582static DEFINE_MUTEX(hash_resize_mutex); 582void 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}
595EXPORT_SYMBOL(xfrm_spd_getinfo);
583 596
597static DEFINE_MUTEX(hash_resize_mutex);
584static void xfrm_hash_resize(struct work_struct *__unused) 598static 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
1347static int inline
1348xfrm_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
1359static int inline
1360xfrm_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
1371static int inline
1372xfrm_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
1334static int stale_bundle(struct dst_entry *dst); 1382static 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