Browse Source

map: add support for lw4o6 address matching, minor optimizations

Signed-off-by: Steven Barth <[email protected]>

SVN-Revision: 45770
Steven Barth 10 years ago
parent
commit
a28470a3cc
2 changed files with 58 additions and 38 deletions
  1. 2 2
      package/network/ipv6/map/Makefile
  2. 56 36
      package/network/ipv6/map/src/mapcalc.c

+ 2 - 2
package/network/ipv6/map/Makefile

@@ -8,8 +8,8 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=map
-PKG_VERSION:=3
-PKG_RELEASE:=4
+PKG_VERSION:=4
+PKG_RELEASE:=1
 PKG_LICENSE:=GPL-2.0
 
 include $(INCLUDE_DIR)/package.mk

+ 56 - 36
package/network/ipv6/map/src/mapcalc.c

@@ -37,12 +37,14 @@ static const struct blobmsg_policy dump_attrs[DUMP_ATTR_MAX] = {
 enum {
 	IFACE_ATTR_INTERFACE,
 	IFACE_ATTR_PREFIX,
+	IFACE_ATTR_ADDRESS,
 	IFACE_ATTR_MAX,
 };
 
 static const struct blobmsg_policy iface_attrs[IFACE_ATTR_MAX] = {
 	[IFACE_ATTR_INTERFACE] = { .name = "interface", .type = BLOBMSG_TYPE_STRING },
 	[IFACE_ATTR_PREFIX] = { .name = "ipv6-prefix", .type = BLOBMSG_TYPE_ARRAY },
+	[IFACE_ATTR_ADDRESS] = { .name = "ipv6-address", .type = BLOBMSG_TYPE_ARRAY },
 };
 
 
@@ -109,6 +111,39 @@ static void handle_dump(struct ubus_request *req __attribute__((unused)),
 	dump = blob_memdup(tb[DUMP_ATTR_INTERFACE]);
 }
 
+static void match_prefix(int *pdlen, struct in6_addr *pd, struct blob_attr *cur,
+		const struct in6_addr *ipv6prefix, int prefix6len)
+{
+	struct blob_attr *d;
+	unsigned drem;
+
+	if (!cur || blobmsg_type(cur) != BLOBMSG_TYPE_ARRAY || !blobmsg_check_attr(cur, NULL))
+		return;
+
+	blobmsg_for_each_attr(d, cur, drem) {
+		struct blob_attr *ptb[PREFIX_ATTR_MAX];
+		blobmsg_parse(prefix_attrs, PREFIX_ATTR_MAX, ptb,
+				blobmsg_data(d), blobmsg_data_len(d));
+
+		if (!ptb[PREFIX_ATTR_ADDRESS] || !ptb[PREFIX_ATTR_MASK])
+			continue;
+
+		struct in6_addr prefix = IN6ADDR_ANY_INIT;
+		int mask = blobmsg_get_u32(ptb[PREFIX_ATTR_MASK]);
+		inet_pton(AF_INET6, blobmsg_get_string(ptb[PREFIX_ATTR_ADDRESS]), &prefix);
+
+		// lw4over6 /128-address-as-PD matching madness workaround
+		if (mask == 128)
+			mask = 64;
+
+		if (*pdlen < mask && mask >= prefix6len &&
+				!bmemcmp(&prefix, ipv6prefix, prefix6len)) {
+			bmemcpy(pd, &prefix, mask);
+			*pdlen = mask;
+		}
+	}
+}
+
 enum {
 	OPT_TYPE,
 	OPT_FMR,
@@ -226,11 +261,16 @@ int main(int argc, char *argv[])
 		if (offset < 0)
 			offset = (lw4o6) ? 0 : (legacy) ? 4 : 6;
 
-		if (lw4o6 && ealen < 0 && psidlen >= 0)
+		// LW4over6 doesn't have an EALEN and has no psid-autodetect
+		if (lw4o6) {
+			if (psidlen < 0)
+				psidlen = 0;
+
 			ealen = psidlen;
+		}
 
 		// Find PD
-		struct blob_attr *c, *cur;
+		struct blob_attr *c;
 		unsigned rem;
 		blobmsg_for_each_attr(c, dump, rem) {
 			struct blob_attr *tb[IFACE_ATTR_MAX];
@@ -240,34 +280,14 @@ int main(int argc, char *argv[])
 					blobmsg_get_string(tb[IFACE_ATTR_INTERFACE]))))
 				continue;
 
-			if ((cur = tb[IFACE_ATTR_PREFIX])) {
-				if (blobmsg_type(cur) != BLOBMSG_TYPE_ARRAY || !blobmsg_check_attr(cur, NULL))
-					continue;
-
-				struct blob_attr *d;
-				unsigned drem;
-				blobmsg_for_each_attr(d, cur, drem) {
-					struct blob_attr *ptb[PREFIX_ATTR_MAX];
-					blobmsg_parse(prefix_attrs, PREFIX_ATTR_MAX, ptb,
-							blobmsg_data(d), blobmsg_data_len(d));
-
-					if (!ptb[PREFIX_ATTR_ADDRESS] || !ptb[PREFIX_ATTR_MASK])
-						continue;
-
-					struct in6_addr prefix = IN6ADDR_ANY_INIT;
-					int mask = blobmsg_get_u32(ptb[PREFIX_ATTR_MASK]);
-					inet_pton(AF_INET6, blobmsg_get_string(ptb[PREFIX_ATTR_ADDRESS]), &prefix);
-
-					if (mask >= prefix6len && !bmemcmp(&prefix, &ipv6prefix, prefix6len)) {
-						pd = prefix;
-						pdlen = mask;
-						iface = blobmsg_get_string(tb[IFACE_ATTR_INTERFACE]);
-						break;
-					}
-				}
-
-				if (pdlen >= 0)
-					break;
+			match_prefix(&pdlen, &pd, tb[IFACE_ATTR_PREFIX], &ipv6prefix, prefix6len);
+
+			if (lw4o6)
+				match_prefix(&pdlen, &pd, tb[IFACE_ATTR_ADDRESS], &ipv6prefix, prefix6len);
+
+			if (pdlen >= 0) {
+				iface = blobmsg_get_string(tb[IFACE_ATTR_INTERFACE]);
+				break;
 			}
 		}
 
@@ -286,6 +306,12 @@ int main(int argc, char *argv[])
 
 		psid16 = cpu_to_be16(psid >> (16 - psidlen));
 
+		if (prefix4len < 0 || prefix6len < 0 || ealen < 0 || ealen < psidlen) {
+			fprintf(stderr, "Skipping invalid or incomplete rule: %s\n", argv[i]);
+			status = 1;
+			continue;
+		}
+
 		if ((pdlen >= 0 || ealen == psidlen) && ealen >= psidlen) {
 			bmemcpys64(&ipv4addr, &pd, prefix6len, ealen - psidlen);
 			ipv4addr.s_addr = htonl(ntohl(ipv4addr.s_addr) >> prefix4len);
@@ -295,12 +321,6 @@ int main(int argc, char *argv[])
 				addr4len = prefix4len + ealen;
 		}
 
-		if (prefix4len < 0 || prefix6len < 0 || ealen < 0 || ealen < psidlen) {
-			fprintf(stderr, "Skipping invalid or incomplete rule: %s\n", argv[i]);
-			status = 1;
-			continue;
-		}
-
 		if (pdlen < 0 && !fmr) {
 			fprintf(stderr, "Skipping non-FMR without matching PD: %s\n", argv[i]);
 			status = 1;