Here is a patch that creates the xfrm_tmpl structures in the order
required by the RFCs.  The patch requires that the application order
of new transformations/protocols be specified for transport mode
in order to have an xfrm_tmpl structure created.  If this is not
desired, an additional transport mode loop can be placed ahead of the
COMP/ESP/AH transport mode loops that creates xfrm_tmpl structures
for protocols other than COMP/ESP/AH.
Tom
--- linux-2.5.62-orig/net/key/af_key.c	2003-02-17 16:56:09.000000000 -0600
+++ linux-2.5.62/net/key/af_key.c	2003-02-19 09:00:53.000000000 -0600
@@ -1562,12 +1562,58 @@
 parse_ipsecrequests(struct xfrm_policy *xp, struct sadb_x_policy *pol)
 {
 	int err;
-	int len = pol->sadb_x_policy_len*8 - sizeof(struct sadb_x_policy);
-	struct sadb_x_ipsecrequest *rq = (void*)(pol+1);
+	int len;
+	struct sadb_x_ipsecrequest *rq;
 
+	/* The order of template creation is important (RFC2401/RFC3173):
+		Transport templates first
+			COMP then
+			ESP then
+			AH then
+		Tunnel templates in any order */
+	len = pol->sadb_x_policy_len*8 - sizeof(struct sadb_x_policy);
+	rq = (void*)(pol+1);
 	while (len >= sizeof(struct sadb_x_ipsecrequest)) {
-		if ((err = parse_ipsecrequest(xp, rq)) < 0)
-			return err;
+		if (rq->sadb_x_ipsecrequest_mode == IPSEC_MODE_TRANSPORT &&
+		    rq->sadb_x_ipsecrequest_proto == IPPROTO_COMP) {
+			if ((err = parse_ipsecrequest(xp, rq)) < 0)
+				return err;
+		}
+		len -= rq->sadb_x_ipsecrequest_len;
+		rq = (void*)((u8*)rq + rq->sadb_x_ipsecrequest_len);
+	}
+	
+	len = pol->sadb_x_policy_len*8 - sizeof(struct sadb_x_policy);
+	rq = (void*)(pol+1);
+	while (len >= sizeof(struct sadb_x_ipsecrequest)) {
+		if (rq->sadb_x_ipsecrequest_mode == IPSEC_MODE_TRANSPORT &&
+		    rq->sadb_x_ipsecrequest_proto == IPPROTO_ESP) {
+			if ((err = parse_ipsecrequest(xp, rq)) < 0)
+				return err;
+		}
+		len -= rq->sadb_x_ipsecrequest_len;
+		rq = (void*)((u8*)rq + rq->sadb_x_ipsecrequest_len);
+	}
+	
+	len = pol->sadb_x_policy_len*8 - sizeof(struct sadb_x_policy);
+	rq = (void*)(pol+1);
+	while (len >= sizeof(struct sadb_x_ipsecrequest)) {
+		if (rq->sadb_x_ipsecrequest_mode == IPSEC_MODE_TRANSPORT &&
+		    rq->sadb_x_ipsecrequest_proto == IPPROTO_AH) {
+			if ((err = parse_ipsecrequest(xp, rq)) < 0)
+				return err;
+		}
+		len -= rq->sadb_x_ipsecrequest_len;
+		rq = (void*)((u8*)rq + rq->sadb_x_ipsecrequest_len);
+	}
+	
+	len = pol->sadb_x_policy_len*8 - sizeof(struct sadb_x_policy);
+	rq = (void*)(pol+1);
+	while (len >= sizeof(struct sadb_x_ipsecrequest)) {
+		if (rq->sadb_x_ipsecrequest_mode != IPSEC_MODE_TRANSPORT) {
+			if ((err = parse_ipsecrequest(xp, rq)) < 0)
+				return err;
+		}
 		len -= rq->sadb_x_ipsecrequest_len;
 		rq = (void*)((u8*)rq + rq->sadb_x_ipsecrequest_len);
 	}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/