From 1b91cd2663b95c47942448222e74e22176466457 Mon Sep 17 00:00:00 2001
From: Steven Barth <cyrus@openwrt.org>
Date: Tue, 8 Sep 2015 12:13:29 +0000
Subject: [PATCH] map: be less restrictive when matching lw4over6 prefixes

Signed-off-by: Steven Barth <steven@midlink.org>

SVN-Revision: 46819
---
 package/network/ipv6/map/Makefile      |  2 +-
 package/network/ipv6/map/src/mapcalc.c | 15 ++++++++++-----
 2 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/package/network/ipv6/map/Makefile b/package/network/ipv6/map/Makefile
index 1d423150b9..f6f2cd6fde 100644
--- a/package/network/ipv6/map/Makefile
+++ b/package/network/ipv6/map/Makefile
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=map
 PKG_VERSION:=4
-PKG_RELEASE:=4
+PKG_RELEASE:=5
 PKG_LICENSE:=GPL-2.0
 
 include $(INCLUDE_DIR)/package.mk
diff --git a/package/network/ipv6/map/src/mapcalc.c b/package/network/ipv6/map/src/mapcalc.c
index 7aa28e57d5..648840d9b6 100644
--- a/package/network/ipv6/map/src/mapcalc.c
+++ b/package/network/ipv6/map/src/mapcalc.c
@@ -3,6 +3,7 @@
  *
  * Author: Steven Barth <cyrus@openwrt.org>
  * Copyright (c) 2014-2015 cisco Systems, Inc.
+ * Copyright (c) 2015 Steven Barth <cyrus@openwrt.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2
@@ -112,7 +113,7 @@ static void handle_dump(struct ubus_request *req __attribute__((unused)),
 }
 
 static void match_prefix(int *pdlen, struct in6_addr *pd, struct blob_attr *cur,
-		const struct in6_addr *ipv6prefix, int prefix6len)
+		const struct in6_addr *ipv6prefix, int prefix6len, bool lw4o6)
 {
 	struct blob_attr *d;
 	unsigned drem;
@@ -133,13 +134,17 @@ static void match_prefix(int *pdlen, struct in6_addr *pd, struct blob_attr *cur,
 		inet_pton(AF_INET6, blobmsg_get_string(ptb[PREFIX_ATTR_ADDRESS]), &prefix);
 
 		// lw4over6 /128-address-as-PD matching madness workaround
-		if (mask == 128)
+		if (lw4o6 && mask == 128)
 			mask = 64;
 
 		if (*pdlen < mask && mask >= prefix6len &&
 				!bmemcmp(&prefix, ipv6prefix, prefix6len)) {
 			bmemcpy(pd, &prefix, mask);
 			*pdlen = mask;
+		} else if (lw4o6 && *pdlen < prefix6len && mask < prefix6len &&
+				!bmemcmp(&prefix, ipv6prefix, mask)) {
+			bmemcpy(pd, ipv6prefix, prefix6len);
+			*pdlen = prefix6len;
 		}
 	}
 }
@@ -237,7 +242,7 @@ int main(int argc, char *argv[])
 				ealen = intval;
 			} else if (idx == OPT_PREFIX4LEN && (intval = strtoul(value, NULL, 0)) <= 32 && !errno) {
 				prefix4len = intval;
-			} else if (idx == OPT_PREFIX6LEN && (intval = strtoul(value, NULL, 0)) <= 112 && !errno) {
+			} else if (idx == OPT_PREFIX6LEN && (intval = strtoul(value, NULL, 0)) <= 128 && !errno) {
 				prefix6len = intval;
 			} else if (idx == OPT_IPV4PREFIX && inet_pton(AF_INET, value, &ipv4prefix) == 1) {
 				// dummy
@@ -289,10 +294,10 @@ int main(int argc, char *argv[])
 						blobmsg_get_string(tb[IFACE_ATTR_INTERFACE]))))
 					continue;
 
-				match_prefix(&pdlen, &pd, tb[IFACE_ATTR_PREFIX], &ipv6prefix, prefix6len);
+				match_prefix(&pdlen, &pd, tb[IFACE_ATTR_PREFIX], &ipv6prefix, prefix6len, lw4o6);
 
 				if (lw4o6)
-					match_prefix(&pdlen, &pd, tb[IFACE_ATTR_ADDRESS], &ipv6prefix, prefix6len);
+					match_prefix(&pdlen, &pd, tb[IFACE_ATTR_ADDRESS], &ipv6prefix, prefix6len, lw4o6);
 
 				if (pdlen >= 0) {
 					iface = blobmsg_get_string(tb[IFACE_ATTR_INTERFACE]);
-- 
2.30.2