lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:	Tue,  5 Dec 2006 19:15:47 +0900
From:	Masahide NAKAMURA <nakam@...ux-ipv6.org>
To:	shemminger@...l.org
Cc:	netdev@...r.kernel.org, Masahide NAKAMURA <nakam@...ux-ipv6.org>
Subject: [PATCH 5/7] [IP] XFRM: Mobile IPv6 route optimization support.

To support Mobile IPv6 RO, the following extension is included:
o Use XFRM_MODE_XXX macro instead of magic number
o New attribute option for all state: source address for
  deleting or getting message
o New attribute options for RO: care-of address, last-used timestamp
  and wild-receive flag

Note:
Flush command like `ip xfrm state flush` is to remove all XFRM state.
It has been effected for IPsec SAD but with this patch it flushes both
IPsec SAD and Mobile IPv6 RO states.
To make only IPsec SA flush, it is recommanded to specify each XFRM
protocol like below:
 `ip x s f proto esp ; ip x s f proto ah ; ip x s f proto comp`

Signed-off-by: Masahide NAKAMURA <nakam@...ux-ipv6.org>
---
 ip/ipxfrm.c      |   84 ++++++++++++++++++++++++++++++++++++++----
 ip/xfrm.h        |    2 +
 ip/xfrm_policy.c |    7 ++--
 ip/xfrm_state.c  |  107 ++++++++++++++++++++++++++++++++++++++++++++----------
 4 files changed, 169 insertions(+), 31 deletions(-)

diff --git a/ip/ipxfrm.c b/ip/ipxfrm.c
index 79fc133..7c9fd0b 100644
--- a/ip/ipxfrm.c
+++ b/ip/ipxfrm.c
@@ -94,6 +94,19 @@ int xfrm_addr_match(xfrm_address_t *x1, 
 	return 0;
 }
 
+int xfrm_xfrmproto_is_ipsec(__u8 proto)
+{
+	return (proto ==  IPPROTO_ESP ||
+		proto ==  IPPROTO_AH  ||
+		proto ==  IPPROTO_COMP);
+}
+
+int xfrm_xfrmproto_is_ro(__u8 proto)
+{
+	return (proto ==  IPPROTO_ROUTING ||
+		proto ==  IPPROTO_DSTOPTS);
+}
+
 struct typeent {
 	const char *t_name;
 	int t_type;
@@ -101,6 +114,7 @@ struct typeent {
 
 static const struct typeent xfrmproto_types[]= {
 	{ "esp", IPPROTO_ESP }, { "ah", IPPROTO_AH }, { "comp", IPPROTO_COMP },
+	{ "route2", IPPROTO_ROUTING }, { "hao", IPPROTO_DSTOPTS },
 	{ NULL, -1 }
 };
 
@@ -276,13 +290,19 @@ void xfrm_id_info_print(xfrm_address_t *
 
 	fprintf(fp, "mode ");
 	switch (mode) {
-	case 0:
+	case XFRM_MODE_TRANSPORT:
 		fprintf(fp, "transport");
 		break;
-	case 1:
+	case XFRM_MODE_TUNNEL:
 		fprintf(fp, "tunnel");
 		break;
-	case 4:
+	case XFRM_MODE_ROUTEOPTIMIZATION:
+		fprintf(fp, "ro");
+		break;
+	case XFRM_MODE_IN_TRIGGER:
+		fprintf(fp, "in_trigger");
+		break;
+	case XFRM_MODE_BEET:
 		fprintf(fp, "beet");
 		break;
 	default:
@@ -643,6 +663,48 @@ void xfrm_xfrma_print(struct rtattr *tb[
 		xfrm_tmpl_print((struct xfrm_user_tmpl *) RTA_DATA(rta),
 				RTA_PAYLOAD(rta), family, fp, prefix);
 	}
+
+	if (tb[XFRMA_COADDR]) {
+		char abuf[256];
+		xfrm_address_t *coa;
+
+		if (prefix)
+			fprintf(fp, prefix);
+		fprintf(fp, "coa ");
+
+		coa = (xfrm_address_t *)RTA_DATA(tb[XFRMA_COADDR]);
+
+		if (RTA_PAYLOAD(tb[XFRMA_COADDR]) < sizeof(*coa)) {
+			fprintf(fp, "(ERROR truncated)");
+			fprintf(fp, "%s", _SL_);
+			return;
+		}
+
+		memset(abuf, '\0', sizeof(abuf));
+		fprintf(fp, "%s",
+			rt_addr_n2a(family, sizeof(*coa), coa, 
+				    abuf, sizeof(abuf)));
+		fprintf(fp, "%s", _SL_);
+	}
+
+	if (tb[XFRMA_LASTUSED]) {
+		__u64 lastused;
+
+		if (prefix)
+			fprintf(fp, prefix);
+		fprintf(fp, "lastused ");
+
+		if (RTA_PAYLOAD(tb[XFRMA_LASTUSED]) < sizeof(lastused)) {
+			fprintf(fp, "(ERROR truncated)");
+			fprintf(fp, "%s", _SL_);
+			return;
+		}
+
+		lastused = *(__u64 *)RTA_DATA(tb[XFRMA_LASTUSED]);
+
+		fprintf(fp, "%s", strxf_time(lastused));
+		fprintf(fp, "%s", _SL_);
+	}
 }
 
 static int xfrm_selector_iszero(struct xfrm_selector *s)
@@ -659,12 +721,13 @@ void xfrm_state_info_print(struct xfrm_u
 			    const char *title)
 {
 	char buf[STRBUF_SIZE];
+	int force_spi = xfrm_xfrmproto_is_ipsec(xsinfo->id.proto);
 
 	memset(buf, '\0', sizeof(buf));
 
 	xfrm_id_info_print(&xsinfo->saddr, &xsinfo->id, xsinfo->mode,
-			   xsinfo->reqid, xsinfo->family, 1, fp, prefix,
-			   title);
+			   xsinfo->reqid, xsinfo->family, force_spi, fp,
+			   prefix, title);
 
 	if (prefix)
 		STRBUF_CAT(buf, prefix);
@@ -680,6 +743,7 @@ void xfrm_state_info_print(struct xfrm_u
 		fprintf(fp, "flag ");
 		XFRM_FLAG_PRINT(fp, flags, XFRM_STATE_NOECN, "noecn");
 		XFRM_FLAG_PRINT(fp, flags, XFRM_STATE_DECAP_DSCP, "decap-dscp");
+		XFRM_FLAG_PRINT(fp, flags, XFRM_STATE_WILDRECV, "wildrecv");
 		if (flags)
 			fprintf(fp, "%x", flags);
 		if (show_stats > 0)
@@ -884,11 +948,15 @@ int xfrm_mode_parse(__u8 *mode, int *arg
 	char **argv = *argvp;
 
 	if (matches(*argv, "transport") == 0)
-		*mode = 0;
+		*mode = XFRM_MODE_TRANSPORT;
 	else if (matches(*argv, "tunnel") == 0)
-		*mode = 1;
+		*mode = XFRM_MODE_TUNNEL;
+	else if (matches(*argv, "ro") == 0)
+		*mode = XFRM_MODE_ROUTEOPTIMIZATION;
+	else if (matches(*argv, "in_trigger") == 0)
+		*mode = XFRM_MODE_IN_TRIGGER;
 	else if (matches(*argv, "beet") == 0)
-		*mode = 4;
+		*mode = XFRM_MODE_BEET;
 	else
 		invarg("\"MODE\" is invalid", *argv);
 
diff --git a/ip/xfrm.h b/ip/xfrm.h
index 7a53e59..51ffa4b 100644
--- a/ip/xfrm.h
+++ b/ip/xfrm.h
@@ -110,6 +110,8 @@ int do_xfrm_policy(int argc, char **argv
 int do_xfrm_monitor(int argc, char **argv);
 
 int xfrm_addr_match(xfrm_address_t *x1, xfrm_address_t *x2, int bits);
+int xfrm_xfrmproto_is_ipsec(__u8 proto);
+int xfrm_xfrmproto_is_ro(__u8 proto);
 int xfrm_xfrmproto_getbyname(char *name);
 int xfrm_algotype_getbyname(char *name);
 const char *strxf_xfrmproto(__u8 proto);
diff --git a/ip/xfrm_policy.c b/ip/xfrm_policy.c
index 6be7bfd..44aff79 100644
--- a/ip/xfrm_policy.c
+++ b/ip/xfrm_policy.c
@@ -82,12 +82,13 @@ static void usage(void)
 	fprintf(stderr, "TMPL := ID [ mode MODE ] [ reqid REQID ] [ level LEVEL ]\n");
 	fprintf(stderr, "ID := [ src ADDR ] [ dst ADDR ] [ proto XFRM_PROTO ] [ spi SPI ]\n");
 
-	//fprintf(stderr, "XFRM_PROTO := [ esp | ah | comp ]\n");
 	fprintf(stderr, "XFRM_PROTO := [ ");
 	fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_ESP));
 	fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_AH));
-	fprintf(stderr, "%s", strxf_xfrmproto(IPPROTO_COMP));
-	fprintf(stderr, " ]\n");
+	fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_COMP));
+	fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_ROUTING));
+	fprintf(stderr, "%s ", strxf_xfrmproto(IPPROTO_DSTOPTS));
+	fprintf(stderr, "]\n");
 
  	fprintf(stderr, "MODE := [ transport | tunnel | beet ](default=transport)\n");
  	//fprintf(stderr, "REQID - number(default=0)\n");
diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c
index bb073c0..57dc4b5 100644
--- a/ip/xfrm_state.c
+++ b/ip/xfrm_state.c
@@ -55,7 +55,7 @@ static void usage(void) __attribute__((n
 
 static void usage(void)
 {
-	fprintf(stderr, "Usage: ip xfrm state { add | update } ID [ ALGO-LIST ] [ mode MODE ]\n");
+	fprintf(stderr, "Usage: ip xfrm state { add | update } ID [ XFRM_OPT ] [ mode MODE ]\n");
 	fprintf(stderr, "        [ reqid REQID ] [ seq SEQ ] [ replay-window SIZE ] [ flag FLAG-LIST ]\n");
 	fprintf(stderr, "        [ encap ENCAP ] [ sel SELECTOR ] [ LIMIT-LIST ]\n");
 	fprintf(stderr, "Usage: ip xfrm state allocspi ID [ mode MODE ] [ reqid REQID ] [ seq SEQ ]\n");
@@ -70,16 +70,18 @@ static void usage(void)
 	fprintf(stderr, "XFRM_PROTO := [ ");
 	fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_ESP));
 	fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_AH));
-	fprintf(stderr, "%s ", strxf_xfrmproto(IPPROTO_COMP));
+	fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_COMP));
+	fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_ROUTING));
+	fprintf(stderr, "%s ", strxf_xfrmproto(IPPROTO_DSTOPTS));
 	fprintf(stderr, "]\n");
 
 	//fprintf(stderr, "SPI - security parameter index(default=0)\n");
 
- 	fprintf(stderr, "MODE := [ transport | tunnel | beet ](default=transport)\n");
+ 	fprintf(stderr, "MODE := [ transport | tunnel | ro | beet ](default=transport)\n");
  	//fprintf(stderr, "REQID - number(default=0)\n");
 
 	fprintf(stderr, "FLAG-LIST := [ FLAG-LIST ] FLAG\n");
-	fprintf(stderr, "FLAG := [ noecn | decap-dscp ]\n");
+	fprintf(stderr, "FLAG := [ noecn | decap-dscp | wildrecv ]\n");
  
         fprintf(stderr, "ENCAP := ENCAP-TYPE SPORT DPORT OADDR\n");
         fprintf(stderr, "ENCAP-TYPE := espinudp | espinudp-nonike\n");
@@ -200,6 +202,8 @@ static int xfrm_state_flag_parse(__u8 *f
 				*flags |= XFRM_STATE_NOECN;
 			else if (strcmp(*argv, "decap-dscp") == 0)
 				*flags |= XFRM_STATE_DECAP_DSCP;
+			else if (strcmp(*argv, "wildrecv") == 0)
+				*flags |= XFRM_STATE_WILDRECV;
 			else {
 				PREV_ARG(); /* back track */
 				break;
@@ -231,6 +235,7 @@ static int xfrm_state_modify(int cmd, un
 	char *ealgop = NULL;
 	char *aalgop = NULL;
 	char *calgop = NULL;
+	char *coap = NULL;
 
 	memset(&req, 0, sizeof(req));
 
@@ -285,6 +290,27 @@ static int xfrm_state_modify(int cmd, un
 			memcpy(&encap.encap_oa, &oa.data, sizeof(encap.encap_oa));
 			addattr_l(&req.n, sizeof(req.buf), XFRMA_ENCAP,
 				  (void *)&encap, sizeof(encap));
+		} else if (strcmp(*argv, "coa") == 0) {
+			inet_prefix coa;
+			xfrm_address_t xcoa;
+
+			if (coap)
+				duparg("coa", *argv);
+			coap = *argv;
+
+			NEXT_ARG();
+
+			get_prefix(&coa, *argv, preferred_family);
+			if (coa.family == AF_UNSPEC)
+				invarg("\"coa\" address family is AF_UNSPEC", *argv);
+			if (coa.bytelen > sizeof(xcoa))
+				invarg("\"coa\" address length is too large", *argv);
+
+			memset(&xcoa, 0, sizeof(xcoa));
+			memcpy(&xcoa, &coa.data, coa.bytelen);
+
+			addattr_l(&req.n, sizeof(req.buf), XFRMA_COADDR,
+				  (void *)&xcoa, sizeof(xcoa));
 		} else {
 			/* try to assume ALGO */
 			int type = xfrm_algotype_getbyname(*argv);
@@ -364,18 +390,56 @@ static int xfrm_state_modify(int cmd, un
 		exit(1);
 	}
 
+	switch (req.xsinfo.mode) {
+	case XFRM_MODE_TRANSPORT:
+	case XFRM_MODE_TUNNEL:
+		if (!xfrm_xfrmproto_is_ipsec(req.xsinfo.id.proto)) {
+			fprintf(stderr, "\"mode\" is invalid with proto=%s\n",
+				strxf_xfrmproto(req.xsinfo.id.proto));
+			exit(1);
+		}
+		break;
+	case XFRM_MODE_ROUTEOPTIMIZATION:
+	case XFRM_MODE_IN_TRIGGER:
+		if (!xfrm_xfrmproto_is_ro(req.xsinfo.id.proto)) {
+			fprintf(stderr, "\"mode\" is invalid with proto=%s\n",
+				strxf_xfrmproto(req.xsinfo.id.proto));
+			exit(1);
+		}
+		if (req.xsinfo.id.spi != 0) {
+			fprintf(stderr, "\"spi\" must be 0 with proto=%s\n",
+				strxf_xfrmproto(req.xsinfo.id.proto));
+			exit(1);
+		}
+		break;
+	default:
+		break;
+	}
+
 	if (ealgop || aalgop || calgop) {
-		if (req.xsinfo.id.proto != IPPROTO_ESP &&
-		    req.xsinfo.id.proto != IPPROTO_AH &&
-		    req.xsinfo.id.proto != IPPROTO_COMP) {
-			fprintf(stderr, "\"ALGO\" is invalid with proto=%s\n", strxf_xfrmproto(req.xsinfo.id.proto));
+		if (!xfrm_xfrmproto_is_ipsec(req.xsinfo.id.proto)) {
+			fprintf(stderr, "\"ALGO\" is invalid with proto=%s\n",
+				strxf_xfrmproto(req.xsinfo.id.proto));
+			exit(1);
+		}
+	} else {
+		if (xfrm_xfrmproto_is_ipsec(req.xsinfo.id.proto)) {
+			fprintf(stderr, "\"ALGO\" is required with proto=%s\n",
+				strxf_xfrmproto(req.xsinfo.id.proto));
+			exit (1);
+		}
+	}
+
+	if (coap) {
+		if (!xfrm_xfrmproto_is_ro(req.xsinfo.id.proto)) {
+			fprintf(stderr, "\"coa\" is invalid with proto=%s\n",
+				strxf_xfrmproto(req.xsinfo.id.proto));
 			exit(1);
 		}
 	} else {
-		if (req.xsinfo.id.proto == IPPROTO_ESP ||
-		    req.xsinfo.id.proto == IPPROTO_AH ||
-		    req.xsinfo.id.proto == IPPROTO_COMP) {
-			fprintf(stderr, "\"ALGO\" is required with proto=%s\n", strxf_xfrmproto(req.xsinfo.id.proto));
+		if (xfrm_xfrmproto_is_ro(req.xsinfo.id.proto)) {
+			fprintf(stderr, "\"coa\" is required with proto=%s\n",
+				strxf_xfrmproto(req.xsinfo.id.proto));
 			exit (1);
 		}
 	}
@@ -645,6 +709,7 @@ static int xfrm_state_get_or_delete(int 
 	struct {
 		struct nlmsghdr 	n;
 		struct xfrm_usersa_id	xsid;
+		char   			buf[RTA_BUF_SIZE];
 	} req;
 	struct xfrm_id id;
 	char *idp = NULL;
@@ -657,12 +722,7 @@ static int xfrm_state_get_or_delete(int 
 	req.xsid.family = preferred_family;
 
 	while (argc > 0) {
-		/*
-		 * XXX: Source address is not used and ignore it to follow
-		 * XXX: a manner of setkey e.g. in the case of deleting/getting
-		 * XXX: message of IPsec SA.
-		 */
-		xfrm_address_t ignore_saddr;
+		xfrm_address_t saddr;
 
 		if (idp)
 			invarg("unknown", *argv);
@@ -670,13 +730,17 @@ static int xfrm_state_get_or_delete(int 
 
 		/* ID */
 		memset(&id, 0, sizeof(id));
-		xfrm_id_parse(&ignore_saddr, &id, &req.xsid.family, 0,
+		memset(&saddr, 0, sizeof(saddr));
+		xfrm_id_parse(&saddr, &id, &req.xsid.family, 0,
 			      &argc, &argv);
 
 		memcpy(&req.xsid.daddr, &id.daddr, sizeof(req.xsid.daddr));
 		req.xsid.spi = id.spi;
 		req.xsid.proto = id.proto;
 
+		addattr_l(&req.n, sizeof(req.buf), XFRMA_SRCADDR,
+			  (void *)&saddr, sizeof(saddr));
+
 		argc--; argv++;
 	}
 
@@ -756,6 +820,9 @@ static int xfrm_state_keep(const struct 
 	xsid->spi = xsinfo->id.spi;
 	xsid->proto = xsinfo->id.proto;
 
+	addattr_l(new_n, xb->size, XFRMA_SRCADDR, &xsinfo->saddr,
+		  sizeof(xsid->daddr));
+
 	xb->offset += new_n->nlmsg_len;
 	xb->nlmsg_count ++;
 
@@ -880,7 +947,7 @@ static int xfrm_state_flush(int argc, ch
 	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsf));
 	req.n.nlmsg_flags = NLM_F_REQUEST;
 	req.n.nlmsg_type = XFRM_MSG_FLUSHSA;
-	req.xsf.proto = IPSEC_PROTO_ANY;
+	req.xsf.proto = 0;
 
 	while (argc > 0) {
 		if (strcmp(*argv, "proto") == 0) {
-- 
1.4.2

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists