netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
To: davem@davemloft.net
Cc: yoshfuji@linux-ipv6.org, anttit@tcs.hut.fi, vnuorval@tcs.hut.fi,
	netdev@vger.kernel.org, usagi-core@linux-ipv6.org,
	Masahide NAKAMURA <nakam@linux-ipv6.org>
Subject: [PATCH 40/44] [XFRM] POLICY: sub policy support.
Date: Thu, 24 Aug 2006 00:02:41 +0900	[thread overview]
Message-ID: <11563453671273-git-send-email-yoshfuji@linux-ipv6.org> (raw)
In-Reply-To: <11563453672872-git-send-email-yoshfuji@linux-ipv6.org>

From: Masahide NAKAMURA <nakam@linux-ipv6.org>

Sub policy is introduced. Main and sub policy are applied the same flow.
(Policy that current kernel uses is named as main.)
It is required another transformation policy management to keep IPsec
and Mobile IPv6 lives separate.
Policy which lives shorter time in kernel should be a sub i.e. normally
main is for IPsec and sub is for Mobile IPv6.
(Such usage as two IPsec policies on different database can be used, too.)

Limitation or TODOs:
 - Sub policy is not supported for per socket one (it is always inserted as main).
 - Current kernel makes cached outbound with flowi to skip searching database.
   However this patch makes it disabled only when "two policies are used and
   the first matched one is bypass case" because neither flowi nor bundle
   information knows about transformation template size.

Signed-off-by: Masahide NAKAMURA <nakam@linux-ipv6.org>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
---
 include/linux/xfrm.h   |    7 +
 include/net/xfrm.h     |   45 +++++++--
 net/xfrm/xfrm_policy.c |  252 +++++++++++++++++++++++++++++++++++++++++-------
 3 files changed, 260 insertions(+), 44 deletions(-)

diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index 4009f44..492fb98 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -104,6 +104,13 @@ struct xfrm_stats {
 
 enum
 {
+	XFRM_POLICY_TYPE_MAIN	= 0,
+	XFRM_POLICY_TYPE_SUB	= 1,
+	XFRM_POLICY_TYPE_MAX	= 2
+};
+
+enum
+{
 	XFRM_POLICY_IN	= 0,
 	XFRM_POLICY_OUT	= 1,
 	XFRM_POLICY_FWD	= 2,
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 00784d9..5bd6beb 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -342,6 +342,7 @@ struct xfrm_policy
 	atomic_t		refcnt;
 	struct timer_list	timer;
 
+	u8			type;
 	u32			priority;
 	u32			index;
 	struct xfrm_selector	selector;
@@ -390,6 +391,19 @@ extern int xfrm_unregister_km(struct xfr
 
 
 extern struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2];
+#ifdef CONFIG_XFRM_SUB_POLICY
+extern struct xfrm_policy *xfrm_policy_list_sub[XFRM_POLICY_MAX*2];
+
+static inline int xfrm_policy_lists_empty(int dir)
+{
+	return (!xfrm_policy_list[dir] && !xfrm_policy_list_sub[dir]);
+}
+#else
+static inline int xfrm_policy_lists_empty(int dir)
+{
+	return (!xfrm_policy_list[dir]);
+}
+#endif
 
 static inline void xfrm_pol_hold(struct xfrm_policy *policy)
 {
@@ -405,6 +419,20 @@ static inline void xfrm_pol_put(struct x
 		__xfrm_policy_destroy(policy);
 }
 
+#ifdef CONFIG_XFRM_SUB_POLICY
+static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols)
+{
+	int i;
+	for (i = npols - 1; i >= 0; --i)
+		xfrm_pol_put(pols[i]);
+}
+#else
+static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols)
+{
+	xfrm_pol_put(pols[0]);
+}
+#endif
+
 #define XFRM_DST_HSIZE		1024
 
 static __inline__
@@ -738,8 +766,8 @@ static inline int xfrm_policy_check(stru
 {
 	if (sk && sk->sk_policy[XFRM_POLICY_IN])
 		return __xfrm_policy_check(sk, dir, skb, family);
-		
-	return	(!xfrm_policy_list[dir] && !skb->sp) ||
+
+	return	(xfrm_policy_lists_empty(dir) && !skb->sp) ||
 		(skb->dst->flags & DST_NOPOLICY) ||
 		__xfrm_policy_check(sk, dir, skb, family);
 }
@@ -759,7 +787,7 @@ extern int __xfrm_route_forward(struct s
 
 static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
 {
-	return	!xfrm_policy_list[XFRM_POLICY_OUT] ||
+	return	xfrm_policy_lists_empty(XFRM_POLICY_OUT) ||
 		(skb->dst->flags & DST_NOXFRM) ||
 		__xfrm_route_forward(skb, family);
 }
@@ -1023,18 +1051,19 @@ static inline int xfrm_dst_lookup(struct
 #endif
 
 struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp);
-extern int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), void *);
+extern int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*), void *);
 int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
-struct xfrm_policy *xfrm_policy_bysel_ctx(int dir, struct xfrm_selector *sel,
+struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
+					  struct xfrm_selector *sel,
 					  struct xfrm_sec_ctx *ctx, int delete);
-struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete);
-void xfrm_policy_flush(void);
+struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete);
+void xfrm_policy_flush(u8 type);
 u32 xfrm_get_acqseq(void);
 void xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
 struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto, 
 				  xfrm_address_t *daddr, xfrm_address_t *saddr, 
 				  int create, unsigned short family);
-extern void xfrm_policy_flush(void);
+extern void xfrm_policy_flush(u8 type);
 extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
 extern int xfrm_flush_bundles(void);
 extern void xfrm_flush_all_bundles(void);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 7b446a9..65e84b1 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -32,6 +32,24 @@ static DEFINE_RWLOCK(xfrm_policy_lock);
 
 struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2];
 EXPORT_SYMBOL(xfrm_policy_list);
+#ifdef CONFIG_XFRM_SUB_POLICY
+struct xfrm_policy *xfrm_policy_list_sub[XFRM_POLICY_MAX*2];
+EXPORT_SYMBOL(xfrm_policy_list_sub);
+
+#define XFRM_POLICY_LISTS(type) \
+	((type == XFRM_POLICY_TYPE_SUB) ? xfrm_policy_list_sub : \
+	 xfrm_policy_list)
+#define XFRM_POLICY_LISTHEAD(type, dir) \
+	((type == XFRM_POLICY_TYPE_SUB) ? xfrm_policy_list_sub[dir] : \
+	 xfrm_policy_list[dir])
+#define XFRM_POLICY_LISTHEADP(type, dir) \
+	((type == XFRM_POLICY_TYPE_SUB) ? &xfrm_policy_list_sub[dir] : \
+	 &xfrm_policy_list[dir])
+#else
+#define XFRM_POLICY_LISTS(type)              xfrm_policy_list
+#define XFRM_POLICY_LISTHEAD(type, dif)      xfrm_policy_list[dir]
+#define XFRM_POLICY_LISTHEADP(type, dif)     &xfrm_policy_list[dir]
+#endif
 
 static DEFINE_RWLOCK(xfrm_policy_afinfo_lock);
 static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO];
@@ -397,7 +415,7 @@ static void xfrm_policy_kill(struct xfrm
 
 /* Generate new index... KAME seems to generate them ordered by cost
  * of an absolute inpredictability of ordering of rules. This will not pass. */
-static u32 xfrm_gen_index(int dir)
+static u32 xfrm_gen_index(u8 type, int dir)
 {
 	u32 idx;
 	struct xfrm_policy *p;
@@ -408,7 +426,7 @@ static u32 xfrm_gen_index(int dir)
 		idx_generator += 8;
 		if (idx == 0)
 			idx = 8;
-		for (p = xfrm_policy_list[dir]; p; p = p->next) {
+		for (p = XFRM_POLICY_LISTHEAD(type, dir); p; p = p->next) {
 			if (p->index == idx)
 				break;
 		}
@@ -425,7 +443,7 @@ int xfrm_policy_insert(int dir, struct x
 	struct dst_entry *gc_list;
 
 	write_lock_bh(&xfrm_policy_lock);
-	for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL;) {
+	for (p = XFRM_POLICY_LISTHEADP(policy->type, dir); (pol=*p)!=NULL;) {
 		if (!delpol && memcmp(&policy->selector, &pol->selector, sizeof(pol->selector)) == 0 &&
 		    xfrm_sec_ctx_match(pol->security, policy->security)) {
 			if (excl) {
@@ -452,7 +470,7 @@ int xfrm_policy_insert(int dir, struct x
 	policy->next = *p;
 	*p = policy;
 	atomic_inc(&flow_cache_genid);
-	policy->index = delpol ? delpol->index : xfrm_gen_index(dir);
+	policy->index = delpol ? delpol->index : xfrm_gen_index(policy->type, dir);
 	policy->curlft.add_time = (unsigned long)xtime.tv_sec;
 	policy->curlft.use_time = 0;
 	if (!mod_timer(&policy->timer, jiffies + HZ))
@@ -493,13 +511,14 @@ int xfrm_policy_insert(int dir, struct x
 }
 EXPORT_SYMBOL(xfrm_policy_insert);
 
-struct xfrm_policy *xfrm_policy_bysel_ctx(int dir, struct xfrm_selector *sel,
+struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
+					  struct xfrm_selector *sel,
 					  struct xfrm_sec_ctx *ctx, int delete)
 {
 	struct xfrm_policy *pol, **p;
 
 	write_lock_bh(&xfrm_policy_lock);
-	for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) {
+	for (p = XFRM_POLICY_LISTHEADP(type, dir); (pol=*p)!=NULL; p = &pol->next) {
 		if ((memcmp(sel, &pol->selector, sizeof(*sel)) == 0) &&
 		    (xfrm_sec_ctx_match(ctx, pol->security))) {
 			xfrm_pol_hold(pol);
@@ -518,12 +537,12 @@ struct xfrm_policy *xfrm_policy_bysel_ct
 }
 EXPORT_SYMBOL(xfrm_policy_bysel_ctx);
 
-struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete)
+struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete)
 {
 	struct xfrm_policy *pol, **p;
 
 	write_lock_bh(&xfrm_policy_lock);
-	for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) {
+	for (p = XFRM_POLICY_LISTHEADP(type, dir); (pol=*p)!=NULL; p = &pol->next) {
 		if (pol->index == id) {
 			xfrm_pol_hold(pol);
 			if (delete)
@@ -541,15 +560,16 @@ struct xfrm_policy *xfrm_policy_byid(int
 }
 EXPORT_SYMBOL(xfrm_policy_byid);
 
-void xfrm_policy_flush(void)
+void xfrm_policy_flush(u8 type)
 {
 	struct xfrm_policy *xp;
+	struct xfrm_policy **p_list = XFRM_POLICY_LISTS(type);
 	int dir;
 
 	write_lock_bh(&xfrm_policy_lock);
 	for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
-		while ((xp = xfrm_policy_list[dir]) != NULL) {
-			xfrm_policy_list[dir] = xp->next;
+		while ((xp = p_list[dir]) != NULL) {
+			p_list[dir] = xp->next;
 			write_unlock_bh(&xfrm_policy_lock);
 
 			xfrm_policy_kill(xp);
@@ -562,7 +582,7 @@ void xfrm_policy_flush(void)
 }
 EXPORT_SYMBOL(xfrm_policy_flush);
 
-int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*),
+int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*),
 		     void *data)
 {
 	struct xfrm_policy *xp;
@@ -572,7 +592,7 @@ int xfrm_policy_walk(int (*func)(struct 
 
 	read_lock_bh(&xfrm_policy_lock);
 	for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) {
-		for (xp = xfrm_policy_list[dir]; xp; xp = xp->next)
+		for (xp = XFRM_POLICY_LISTHEAD(type, dir); xp; xp = xp->next)
 			count++;
 	}
 
@@ -582,7 +602,7 @@ int xfrm_policy_walk(int (*func)(struct 
 	}
 
 	for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) {
-		for (xp = xfrm_policy_list[dir]; xp; xp = xp->next) {
+		for (xp = XFRM_POLICY_LISTHEAD(type, dir); xp; xp = xp->next) {
 			error = func(xp, dir%XFRM_POLICY_MAX, --count, data);
 			if (error)
 				goto out;
@@ -597,13 +617,13 @@ EXPORT_SYMBOL(xfrm_policy_walk);
 
 /* Find policy to apply to this flow. */
 
-static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
-			       void **objp, atomic_t **obj_refp)
+static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl,
+						     u16 family, u8 dir)
 {
 	struct xfrm_policy *pol;
 
 	read_lock_bh(&xfrm_policy_lock);
-	for (pol = xfrm_policy_list[dir]; pol; pol = pol->next) {
+	for (pol = XFRM_POLICY_LISTHEAD(type, dir); pol; pol = pol->next) {
 		struct xfrm_selector *sel = &pol->selector;
 		int match;
 
@@ -620,6 +640,25 @@ static void xfrm_policy_lookup(struct fl
 		}
 	}
 	read_unlock_bh(&xfrm_policy_lock);
+
+	return pol;
+}
+
+static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
+			       void **objp, atomic_t **obj_refp)
+{
+	struct xfrm_policy *pol;
+
+#ifdef CONFIG_XFRM_SUB_POLICY
+	pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_SUB, fl, family, dir);
+	if (pol)
+		goto end;
+#endif
+	pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN, fl, family, dir);
+
+#ifdef CONFIG_XFRM_SUB_POLICY
+ end:
+#endif
 	if ((*objp = (void *) pol) != NULL)
 		*obj_refp = &pol->refcnt;
 }
@@ -665,8 +704,10 @@ static struct xfrm_policy *xfrm_sk_polic
 
 static void __xfrm_policy_link(struct xfrm_policy *pol, int dir)
 {
-	pol->next = xfrm_policy_list[dir];
-	xfrm_policy_list[dir] = pol;
+	struct xfrm_policy **p_list = XFRM_POLICY_LISTS(pol->type);
+
+	pol->next = p_list[dir];
+	p_list[dir] = pol;
 	xfrm_pol_hold(pol);
 }
 
@@ -675,7 +716,7 @@ static struct xfrm_policy *__xfrm_policy
 {
 	struct xfrm_policy **polp;
 
-	for (polp = &xfrm_policy_list[dir];
+	for (polp = XFRM_POLICY_LISTHEADP(pol->type, dir);
 	     *polp != NULL; polp = &(*polp)->next) {
 		if (*polp == pol) {
 			*polp = pol->next;
@@ -704,12 +745,17 @@ int xfrm_sk_policy_insert(struct sock *s
 {
 	struct xfrm_policy *old_pol;
 
+#ifdef CONFIG_XFRM_SUB_POLICY
+	if (pol && pol->type != XFRM_POLICY_TYPE_MAIN)
+		return -EINVAL;
+#endif
+
 	write_lock_bh(&xfrm_policy_lock);
 	old_pol = sk->sk_policy[dir];
 	sk->sk_policy[dir] = pol;
 	if (pol) {
 		pol->curlft.add_time = (unsigned long)xtime.tv_sec;
-		pol->index = xfrm_gen_index(XFRM_POLICY_MAX+dir);
+		pol->index = xfrm_gen_index(pol->type, XFRM_POLICY_MAX+dir);
 		__xfrm_policy_link(pol, XFRM_POLICY_MAX+dir);
 	}
 	if (old_pol)
@@ -738,6 +784,7 @@ static struct xfrm_policy *clone_policy(
 		newp->flags = old->flags;
 		newp->xfrm_nr = old->xfrm_nr;
 		newp->index = old->index;
+		newp->type = old->type;
 		memcpy(newp->xfrm_vec, old->xfrm_vec,
 		       newp->xfrm_nr*sizeof(struct xfrm_tmpl));
 		write_lock_bh(&xfrm_policy_lock);
@@ -764,9 +811,9 @@ int __xfrm_sk_clone_policy(struct sock *
 /* Resolve list of templates for the flow, given policy. */
 
 static int
-xfrm_tmpl_resolve(struct xfrm_policy *policy, struct flowi *fl,
-		  struct xfrm_state **xfrm,
-		  unsigned short family)
+xfrm_tmpl_resolve_one(struct xfrm_policy *policy, struct flowi *fl,
+		      struct xfrm_state **xfrm,
+		      unsigned short family)
 {
 	int nx;
 	int i, error;
@@ -809,6 +856,38 @@ fail:
 	return error;
 }
 
+static int
+xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, struct flowi *fl,
+		  struct xfrm_state **xfrm,
+		  unsigned short family)
+{
+	int cnx = 0;
+	int error;
+	int ret;
+	int i;
+
+	for (i = 0; i < npols; i++) {
+		if (cnx + pols[i]->xfrm_nr >= XFRM_MAX_DEPTH) {
+			error = -ENOBUFS;
+			goto fail;
+		}
+		ret = xfrm_tmpl_resolve_one(pols[i], fl, &xfrm[cnx], family);
+		if (ret < 0) {
+			error = ret;
+			goto fail;
+		} else
+			cnx += ret;
+	}
+
+	return cnx;
+
+ fail:
+	for (cnx--; cnx>=0; cnx--)
+		xfrm_state_put(xfrm[cnx]);
+	return error;
+
+}
+
 /* Check that the bundle accepts the flow and its components are
  * still valid.
  */
@@ -855,6 +934,11 @@ int xfrm_lookup(struct dst_entry **dst_p
 		struct sock *sk, int flags)
 {
 	struct xfrm_policy *policy;
+	struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
+	int npols;
+	int pol_dead;
+	int xfrm_nr;
+	int pi;
 	struct xfrm_state *xfrm[XFRM_MAX_DEPTH];
 	struct dst_entry *dst, *dst_orig = *dst_p;
 	int nx = 0;
@@ -866,12 +950,18 @@ int xfrm_lookup(struct dst_entry **dst_p
 restart:
 	genid = atomic_read(&flow_cache_genid);
 	policy = NULL;
+	for (pi = 0; pi < ARRAY_SIZE(pols); pi++)
+		pols[pi] = NULL;
+	npols = 0;
+	pol_dead = 0;
+	xfrm_nr = 0;
+
 	if (sk && sk->sk_policy[1])
 		policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
 
 	if (!policy) {
 		/* To accelerate a bit...  */
-		if ((dst_orig->flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT])
+		if ((dst_orig->flags & DST_NOXFRM) || xfrm_policy_lists_empty(XFRM_POLICY_OUT))
 			return 0;
 
 		policy = flow_cache_lookup(fl, dst_orig->ops->family,
@@ -883,6 +973,9 @@ restart:
 
 	family = dst_orig->ops->family;
 	policy->curlft.use_time = (unsigned long)xtime.tv_sec;
+	pols[0] = policy;
+	npols ++;
+	xfrm_nr += pols[0]->xfrm_nr;
 
 	switch (policy->action) {
 	case XFRM_POLICY_BLOCK:
@@ -891,11 +984,13 @@ restart:
 		goto error;
 
 	case XFRM_POLICY_ALLOW:
+#ifndef CONFIG_XFRM_SUB_POLICY
 		if (policy->xfrm_nr == 0) {
 			/* Flow passes not transformed. */
 			xfrm_pol_put(policy);
 			return 0;
 		}
+#endif
 
 		/* Try to find matching bundle.
 		 *
@@ -911,7 +1006,36 @@ restart:
 		if (dst)
 			break;
 
-		nx = xfrm_tmpl_resolve(policy, fl, xfrm, family);
+#ifdef CONFIG_XFRM_SUB_POLICY
+		if (pols[0]->type != XFRM_POLICY_TYPE_MAIN) {
+			pols[1] = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN,
+							    fl, family,
+							    XFRM_POLICY_OUT);
+			if (pols[1]) {
+				if (pols[1]->action == XFRM_POLICY_BLOCK) {
+					err = -EPERM;
+					goto error;
+				}
+				npols ++;
+				xfrm_nr += pols[1]->xfrm_nr;
+			}
+		}
+
+		/*
+		 * Because neither flowi nor bundle information knows about
+		 * transformation template size. On more than one policy usage
+		 * we can realize whether all of them is bypass or not after
+		 * they are searched. See above not-transformed bypass
+		 * is surrounded by non-sub policy configuration, too.
+		 */
+		if (xfrm_nr == 0) {
+			/* Flow passes not transformed. */
+			xfrm_pols_put(pols, npols);
+			return 0;
+		}
+
+#endif
+		nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family);
 
 		if (unlikely(nx<0)) {
 			err = nx;
@@ -924,7 +1048,7 @@ restart:
 				set_current_state(TASK_RUNNING);
 				remove_wait_queue(&km_waitq, &wait);
 
-				nx = xfrm_tmpl_resolve(policy, fl, xfrm, family);
+				nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family);
 
 				if (nx == -EAGAIN && signal_pending(current)) {
 					err = -ERESTART;
@@ -932,7 +1056,7 @@ restart:
 				}
 				if (nx == -EAGAIN ||
 				    genid != atomic_read(&flow_cache_genid)) {
-					xfrm_pol_put(policy);
+					xfrm_pols_put(pols, npols);
 					goto restart;
 				}
 				err = nx;
@@ -942,7 +1066,7 @@ restart:
 		}
 		if (nx == 0) {
 			/* Flow passes not transformed. */
-			xfrm_pol_put(policy);
+			xfrm_pols_put(pols, npols);
 			return 0;
 		}
 
@@ -956,8 +1080,14 @@ restart:
 			goto error;
 		}
 
+		for (pi = 0; pi < npols; pi++) {
+			read_lock_bh(&pols[pi]->lock);
+			pol_dead |= pols[pi]->dead;
+			read_unlock_bh(&pols[pi]->lock);
+		}
+
 		write_lock_bh(&policy->lock);
-		if (unlikely(policy->dead || stale_bundle(dst))) {
+		if (unlikely(pol_dead || stale_bundle(dst))) {
 			/* Wow! While we worked on resolving, this
 			 * policy has gone. Retry. It is not paranoia,
 			 * we just cannot enlist new bundle to dead object.
@@ -977,12 +1107,12 @@ restart:
 	}
 	*dst_p = dst;
 	dst_release(dst_orig);
-	xfrm_pol_put(policy);
+ 	xfrm_pols_put(pols, npols);
 	return 0;
 
 error:
 	dst_release(dst_orig);
-	xfrm_pol_put(policy);
+	xfrm_pols_put(pols, npols);
 	*dst_p = NULL;
 	return err;
 }
@@ -1090,6 +1220,10 @@ int __xfrm_policy_check(struct sock *sk,
 			unsigned short family)
 {
 	struct xfrm_policy *pol;
+	struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
+	int npols = 0;
+	int xfrm_nr;
+	int pi;
 	struct flowi fl;
 	u8 fl_dir = policy_to_flow_dir(dir);
 	int xerr_idx = -1;
@@ -1128,22 +1262,50 @@ int __xfrm_policy_check(struct sock *sk,
 
 	pol->curlft.use_time = (unsigned long)xtime.tv_sec;
 
+	pols[0] = pol;
+	npols ++;
+#ifdef CONFIG_XFRM_SUB_POLICY
+	if (pols[0]->type != XFRM_POLICY_TYPE_MAIN) {
+		pols[1] = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN,
+						    &fl, family,
+						    XFRM_POLICY_IN);
+		if (pols[1]) {
+			pols[1]->curlft.use_time = (unsigned long)xtime.tv_sec;
+			npols ++;
+		}
+	}
+#endif
+
 	if (pol->action == XFRM_POLICY_ALLOW) {
 		struct sec_path *sp;
 		static struct sec_path dummy;
+		struct xfrm_tmpl *tp[XFRM_MAX_DEPTH];
+		struct xfrm_tmpl **tpp = tp;
+		int ti = 0;
 		int i, k;
 
 		if ((sp = skb->sp) == NULL)
 			sp = &dummy;
 
+		for (pi = 0; pi < npols; pi++) {
+			if (pols[pi] != pol &&
+			    pols[pi]->action != XFRM_POLICY_ALLOW)
+				goto reject;
+			if (ti + pols[pi]->xfrm_nr >= XFRM_MAX_DEPTH)
+				goto reject_error;
+			for (i = 0; i < pols[pi]->xfrm_nr; i++)
+				tpp[ti++] = &pols[pi]->xfrm_vec[i];
+		}
+		xfrm_nr = ti;
+
 		/* For each tunnel xfrm, find the first matching tmpl.
 		 * For each tmpl before that, find corresponding xfrm.
 		 * Order is _important_. Later we will implement
 		 * some barriers, but at the moment barriers
 		 * are implied between each two transformations.
 		 */
-		for (i = pol->xfrm_nr-1, k = 0; i >= 0; i--) {
-			k = xfrm_policy_ok(pol->xfrm_vec+i, sp, k, family);
+		for (i = xfrm_nr-1, k = 0; i >= 0; i--) {
+			k = xfrm_policy_ok(tpp[i], sp, k, family);
 			if (k < 0) {
 				if (k < -1 && xerr_idxp)
 					*xerr_idxp = -(2+k);
@@ -1154,13 +1316,14 @@ int __xfrm_policy_check(struct sock *sk,
 		if (secpath_has_nontransport(sp, k, xerr_idxp))
 			goto reject;
 
-		xfrm_pol_put(pol);
+		xfrm_pols_put(pols, npols);
 		return 1;
 	}
 
 reject:
 	xfrm_secpath_reject(xerr_idx, skb, &fl);
-	xfrm_pol_put(pol);
+reject_error:
+	xfrm_pols_put(pols, npols);
 	return 0;
 }
 EXPORT_SYMBOL(__xfrm_policy_check);
@@ -1226,6 +1389,23 @@ static void xfrm_prune_bundles(int (*fun
 
 	read_lock_bh(&xfrm_policy_lock);
 	for (i=0; i<2*XFRM_POLICY_MAX; i++) {
+#ifdef CONFIG_XFRM_SUB_POLICY
+		for (pol = xfrm_policy_list_sub[i]; pol; pol = pol->next) {
+			write_lock(&pol->lock);
+			dstp = &pol->bundles;
+			while ((dst=*dstp) != NULL) {
+				if (func(dst)) {
+					*dstp = dst->next;
+					dst->next = gc_list;
+					gc_list = dst;
+				} else {
+					dstp = &dst->next;
+				}
+			}
+			write_unlock(&pol->lock);
+		}
+
+#endif
 		for (pol = xfrm_policy_list[i]; pol; pol = pol->next) {
 			write_lock(&pol->lock);
 			dstp = &pol->bundles;
-- 
1.4.0


  reply	other threads:[~2006-08-23 15:02 UTC|newest]

Thread overview: 116+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-08-23 15:02 [PATCH 0/44] Mobile IPv6 Platform, Take 2 (for net-2.6.19) YOSHIFUJI Hideaki
2006-08-23 15:02 ` [PATCH 1/44] [XFRM]: Add XFRM_MODE_xxx for future use YOSHIFUJI Hideaki
2006-08-23 15:02   ` [PATCH 2/44] [XFRM]: Introduce a helper to compare id protocol YOSHIFUJI Hideaki
2006-08-23 15:02     ` [PATCH 3/44] [XFRM] STATE: Allow non IPsec protocol YOSHIFUJI Hideaki
2006-08-23 15:02       ` [PATCH 4/44] [XFRM]: Expand XFRM_MAX_DEPTH for route optimization YOSHIFUJI Hideaki
2006-08-23 15:02         ` [PATCH 5/44] [XFRM] STATE: Add source address list YOSHIFUJI Hideaki
2006-08-23 15:02           ` [PATCH 6/44] [XFRM] STATE: Search by address using " YOSHIFUJI Hideaki
2006-08-23 15:02             ` [PATCH 7/44] [XFRM] STATE: Add a hook to find offset to be inserted header in outbound YOSHIFUJI Hideaki
2006-08-23 15:02               ` [PATCH 8/44] [XFRM] STATE: Introduce route optimization mode YOSHIFUJI Hideaki
2006-08-23 15:02                 ` [PATCH 9/44] [XFRM]: Restrict authentication algorithm only when inbound transformation protocol is IPsec YOSHIFUJI Hideaki
2006-08-23 15:02                   ` [PATCH 10/44] [XFRM] STATE: Common receive function for route optimization extension headers YOSHIFUJI Hideaki
2006-08-23 15:02                     ` [PATCH 11/44] [XFRM]: Rename secpath_has_tunnel to secpath_has_nontransport YOSHIFUJI Hideaki
2006-08-23 15:02                       ` [PATCH 12/44] [XFRM] STATE: Add a hook to obtain local/remote outbound address YOSHIFUJI Hideaki
2006-08-23 15:02                         ` [PATCH 13/44] [XFRM] STATE: Support non-fragment outbound transformation headers YOSHIFUJI Hideaki
2006-08-23 15:02                           ` [PATCH 14/44] [XFRM] STATE: Introduce care-of address YOSHIFUJI Hideaki
2006-08-23 15:02                             ` [PATCH 15/44] [XFRM] IPV6: Update outbound state timestamp for each sending YOSHIFUJI Hideaki
2006-08-23 15:02                               ` [PATCH 16/44] [XFRM] IPV6: Restrict bundle reusing YOSHIFUJI Hideaki
2006-08-23 15:02                                 ` [PATCH 17/44] [XFRM]: Fix message about transformation user interface YOSHIFUJI Hideaki
2006-08-23 15:02                                   ` [PATCH 18/44] [IPV6]: Add Kconfig to enable Mobile IPv6 YOSHIFUJI Hideaki
2006-08-23 15:02                                     ` [PATCH 19/44] [IPV6] MIP6: Add routing header type 2 definition YOSHIFUJI Hideaki
2006-08-23 15:02                                       ` [PATCH 20/44] [IPV6] MIP6: Add inbound interface of routing header type 2 YOSHIFUJI Hideaki
2006-08-23 15:02                                         ` [PATCH 21/44] [IPV6] MIP6: Add socket option and ancillary data " YOSHIFUJI Hideaki
2006-08-23 15:02                                           ` [PATCH 22/44] [IPV6]: Find option offset by type YOSHIFUJI Hideaki
2006-08-23 15:02                                             ` [PATCH 23/44] [IPV6]: Allow to replace skbuff by TLV parser YOSHIFUJI Hideaki
2006-08-23 15:02                                               ` [PATCH 24/44] [IPV6] MIP6: Add home address option definition YOSHIFUJI Hideaki
2006-08-23 15:02                                                 ` [PATCH 25/44] [IPV6] MIP6: Add inbound interface of home address option YOSHIFUJI Hideaki
2006-08-23 15:02                                                   ` [PATCH 26/44] [IPV6] MIP6: Revert address to send ICMPv6 error YOSHIFUJI Hideaki
2006-08-23 15:02                                                     ` [PATCH 27/44] [IPV6] IPSEC: Support sending with Mobile IPv6 extension headers YOSHIFUJI Hideaki
2006-08-23 15:02                                                       ` [PATCH 28/44] [IPV6] MIP6: Add routing header type 2 transformation YOSHIFUJI Hideaki
2006-08-23 15:02                                                         ` [PATCH 29/44] [IPV6] MIP6: Add destination options header transformation YOSHIFUJI Hideaki
2006-08-23 15:02                                                           ` [PATCH 30/44] [XFRM] STATE: Add Mobile IPv6 route optimization protocols to netlink interface YOSHIFUJI Hideaki
2006-08-23 15:02                                                             ` [PATCH 31/44] [IPV6] MIP6: Add Mobility header definition YOSHIFUJI Hideaki
2006-08-23 15:02                                                               ` [PATCH 32/44] [IPV6] MIP6: Add receiving mobility header functions through raw socket YOSHIFUJI Hideaki
2006-08-23 15:02                                                                 ` [PATCH 33/44] [IPV6] MIP6: Add sending " YOSHIFUJI Hideaki
2006-08-23 15:02                                                                   ` [PATCH 34/44] [IPV6] MIP6: Transformation support mobility header YOSHIFUJI Hideaki
2006-08-23 15:02                                                                     ` [PATCH 35/44] [XFRM]: Trace which secpath state is reject factor YOSHIFUJI Hideaki
2006-08-23 15:02                                                                       ` [PATCH 36/44] [XFRM]: Introduce XFRM_MSG_REPORT YOSHIFUJI Hideaki
2006-08-23 15:02                                                                         ` [PATCH 37/44] [IPV6] MIP6: Report to user-space when home address option is rejected YOSHIFUJI Hideaki
2006-08-23 15:02                                                                           ` [PATCH 38/44] [IPV6] MIP6: Ignore to report if mobility headers " YOSHIFUJI Hideaki
2006-08-23 15:02                                                                             ` [PATCH 39/44] [XFRM] POLICY: Add Kconfig to support sub policy YOSHIFUJI Hideaki
2006-08-23 15:02                                                                               ` YOSHIFUJI Hideaki [this message]
2006-08-23 15:02                                                                                 ` [PATCH 41/44] [XFRM]: Add sorting interface for state and template YOSHIFUJI Hideaki
2006-08-23 15:02                                                                                   ` [PATCH 42/44] [XFRM] POLICY: Support netlink socket interface for sub policy YOSHIFUJI Hideaki
2006-08-23 15:02                                                                                     ` [PATCH 43/44] [XFRM] IPV6: Add sort functions to combine templates/states for IPsec YOSHIFUJI Hideaki
2006-08-23 15:02                                                                                       ` [PATCH 44/44] [XFRM] IPV6: Support Mobile IPv6 extension headers sorting YOSHIFUJI Hideaki
2006-08-24  5:57                                                                                         ` David Miller
2006-08-24  6:04                                                                                           ` YOSHIFUJI Hideaki / 吉藤英明
2006-08-24  6:54                                                                                             ` David Miller
2006-08-24  7:05                                                                                               ` Masahide NAKAMURA
2006-08-24 11:58                                                                                                 ` David Miller
2006-08-25  0:56                                                                                                   ` Masahide NAKAMURA
2006-08-25 10:06                                                                                                     ` Masahide NAKAMURA
2006-08-25 10:16                                                                                                       ` David Miller
2006-08-25 14:29                                                                                                         ` Masahide NAKAMURA
2006-08-25 22:47                                                                                                           ` David Miller
2006-08-31 12:00                                                                                                             ` [PATCH] [XFRM] STATE: Fix flusing with hash mask Masahide NAKAMURA
2006-08-31 22:15                                                                                                               ` David Miller
2006-09-01  1:20                                                                                                                 ` Masahide NAKAMURA
2010-12-08  7:31                                                                                                         ` [PATCH 44/44] [XFRM] IPV6: Support Mobile IPv6 extension headers sorting wisalsami
2006-08-24  5:51                                                                                       ` [PATCH 43/44] [XFRM] IPV6: Add sort functions to combine templates/states for IPsec David Miller
2006-08-24  5:49                                                                                     ` [PATCH 42/44] [XFRM] POLICY: Support netlink socket interface for sub policy David Miller
2006-08-24  5:48                                                                                   ` [PATCH 41/44] [XFRM]: Add sorting interface for state and template David Miller
2006-08-24  5:48                                                                                 ` [PATCH 40/44] [XFRM] POLICY: sub policy support David Miller
2006-08-25  1:45                                                                                   ` Herbert Xu
2006-08-24  5:41                                                                               ` [PATCH 39/44] [XFRM] POLICY: Add Kconfig to support sub policy David Miller
2006-08-24  3:48                                                                             ` [PATCH 38/44] [IPV6] MIP6: Ignore to report if mobility headers is rejected David Miller
2006-08-24  3:46                                                                           ` [PATCH 37/44] [IPV6] MIP6: Report to user-space when home address option " David Miller
2006-08-24  3:43                                                                         ` [PATCH 36/44] [XFRM]: Introduce XFRM_MSG_REPORT David Miller
2006-08-24  6:48                                                                           ` Masahide NAKAMURA
2006-08-24  6:53                                                                             ` David Miller
2006-08-24  3:41                                                                       ` [PATCH 35/44] [XFRM]: Trace which secpath state is reject factor David Miller
2006-08-24  3:39                                                                     ` [PATCH 34/44] [IPV6] MIP6: Transformation support mobility header David Miller
2006-08-24  3:37                                                                   ` [PATCH 33/44] [IPV6] MIP6: Add sending mobility header functions through raw socket David Miller
2006-08-24  3:36                                                                 ` [PATCH 32/44] [IPV6] MIP6: Add receiving " David Miller
2006-08-24  3:34                                                               ` [PATCH 31/44] [IPV6] MIP6: Add Mobility header definition David Miller
2006-08-24  3:33                                                             ` [PATCH 30/44] [XFRM] STATE: Add Mobile IPv6 route optimization protocols to netlink interface David Miller
2006-08-24  3:32                                                           ` [PATCH 29/44] [IPV6] MIP6: Add destination options header transformation David Miller
2006-08-24  3:31                                                         ` [PATCH 28/44] [IPV6] MIP6: Add routing header type 2 transformation David Miller
2006-08-23 20:36                                                       ` [PATCH 27/44] [IPV6] IPSEC: Support sending with Mobile IPv6 extension headers YOSHIFUJI Hideaki / 吉藤英明
2006-08-24  2:31                                                       ` David Miller
2006-08-24  2:27                                                     ` [PATCH 26/44] [IPV6] MIP6: Revert address to send ICMPv6 error David Miller
2006-08-24  2:26                                                   ` [PATCH 25/44] [IPV6] MIP6: Add inbound interface of home address option David Miller
2006-08-24  2:21                                                 ` [PATCH 24/44] [IPV6] MIP6: Add home address option definition David Miller
2006-08-24  2:20                                               ` [PATCH 23/44] [IPV6]: Allow to replace skbuff by TLV parser David Miller
2006-08-31 12:05                                                 ` [IPV6] MIP6: Fix to update IP6CB when cloned skbuff is received at HAO. (Re: [PATCH 23/44] [IPV6]: Allow to replace skbuff by TLV parser.) Masahide NAKAMURA
2006-08-31 22:20                                                   ` [IPV6] MIP6: Fix to update IP6CB when cloned skbuff is received at HAO David Miller
2006-08-23 17:22                                             ` [PATCH 22/44] [IPV6]: Find option offset by type Brian Haley
2006-08-23 20:26                                               ` YOSHIFUJI Hideaki / 吉藤英明
2006-08-24  2:18                                             ` David Miller
2006-08-24  2:17                                           ` [PATCH 21/44] [IPV6] MIP6: Add socket option and ancillary data interface of routing header type 2 David Miller
2006-08-24  2:16                                         ` [PATCH 20/44] [IPV6] MIP6: Add inbound " David Miller
2006-08-24  2:15                                       ` [PATCH 19/44] [IPV6] MIP6: Add routing header type 2 definition David Miller
2006-08-24  2:14                                     ` [PATCH 18/44] [IPV6]: Add Kconfig to enable Mobile IPv6 David Miller
2006-08-24  2:55                                       ` Masahide NAKAMURA
2006-08-24  2:13                                   ` [PATCH 17/44] [XFRM]: Fix message about transformation user interface David Miller
2006-08-24  2:12                                 ` [PATCH 16/44] [XFRM] IPV6: Restrict bundle reusing David Miller
2006-08-24  2:54                                   ` Masahide NAKAMURA
2006-08-24  1:20                               ` [PATCH 15/44] [XFRM] IPV6: Update outbound state timestamp for each sending David Miller
2006-08-24  1:19                             ` [PATCH 14/44] [XFRM] STATE: Introduce care-of address David Miller
2006-08-24  1:12                           ` [PATCH 13/44] [XFRM] STATE: Support non-fragment outbound transformation headers David Miller
2006-08-24  1:10                         ` [PATCH 12/44] [XFRM] STATE: Add a hook to obtain local/remote outbound address David Miller
2006-08-24  1:09                       ` [PATCH 11/44] [XFRM]: Rename secpath_has_tunnel to secpath_has_nontransport David Miller
2006-08-24  1:08                     ` [PATCH 10/44] [XFRM] STATE: Common receive function for route optimization extension headers David Miller
2006-08-24  1:01                   ` [PATCH 9/44] [XFRM]: Restrict authentication algorithm only when inbound transformation protocol is IPsec David Miller
2006-08-24  1:00                 ` [PATCH 8/44] [XFRM] STATE: Introduce route optimization mode David Miller
2006-08-24  0:57               ` [PATCH 7/44] [XFRM] STATE: Add a hook to find offset to be inserted header in outbound David Miller
2006-08-24  0:56             ` [PATCH 6/44] [XFRM] STATE: Search by address using source address list David Miller
2006-08-24  0:54           ` [PATCH 5/44] [XFRM] STATE: Add " David Miller
2006-08-24  1:19             ` Masahide NAKAMURA
2006-08-24  2:08               ` David Miller
2006-08-24  0:52         ` [PATCH 4/44] [XFRM]: Expand XFRM_MAX_DEPTH for route optimization David Miller
2006-08-24  0:50       ` [PATCH 3/44] [XFRM] STATE: Allow non IPsec protocol David Miller
2006-08-24  0:48     ` [PATCH 2/44] [XFRM]: Introduce a helper to compare id protocol David Miller
2006-08-24  0:47   ` [PATCH 1/44] [XFRM]: Add XFRM_MODE_xxx for future use David Miller
2006-08-23 15:22 ` [PATCH 0/44] Mobile IPv6 Platform, Take 2 (for net-2.6.19) YOSHIFUJI Hideaki / 吉藤英明
2006-08-24  0:06 ` David Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=11563453671273-git-send-email-yoshfuji@linux-ipv6.org \
    --to=yoshfuji@linux-ipv6.org \
    --cc=anttit@tcs.hut.fi \
    --cc=davem@davemloft.net \
    --cc=nakam@linux-ipv6.org \
    --cc=netdev@vger.kernel.org \
    --cc=usagi-core@linux-ipv6.org \
    --cc=vnuorval@tcs.hut.fi \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).