aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/xfrm/xfrm_policy.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index dbf9d96a2f0b..263e34e45265 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1344,6 +1344,40 @@ xfrm_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int nx,
1344 return err; 1344 return err;
1345} 1345}
1346 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}
1347 1381
1348static int stale_bundle(struct dst_entry *dst); 1382static int stale_bundle(struct dst_entry *dst);
1349 1383
@@ -1532,6 +1566,18 @@ restart:
1532 err = -EHOSTUNREACH; 1566 err = -EHOSTUNREACH;
1533 goto error; 1567 goto error;
1534 } 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
1535 dst->next = policy->bundles; 1581 dst->next = policy->bundles;
1536 policy->bundles = dst; 1582 policy->bundles = dst;
1537 dst_hold(dst); 1583 dst_hold(dst);
@@ -1947,6 +1993,15 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
1947 if (!dst_check(dst->path, ((struct xfrm_dst *)dst)->path_cookie) || 1993 if (!dst_check(dst->path, ((struct xfrm_dst *)dst)->path_cookie) ||
1948 (dst->dev && !netif_running(dst->dev))) 1994 (dst->dev && !netif_running(dst->dev)))
1949 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
1950 2005
1951 last = NULL; 2006 last = NULL;
1952 2007