commit cb046cfef1d6b954d3fc09f09a1fc3a7ffeb7593
Author: Chen Minqiang <ptpt52@gmail.com>
Date:   Sun Jul 5 10:42:52 2020 +0800

    options: ext_ip_reserved_ignore support
    
    This make the port forwarding force to work even
    when the router is behind NAT
    
    Signed-off-by: Chen Minqiang <ptpt52@gmail.com>

--- a/getifaddr.c
+++ b/getifaddr.c
@@ -25,6 +25,7 @@
 #if defined(USE_GETIFADDRS) || defined(ENABLE_IPV6) || defined(ENABLE_PCP)
 #include <ifaddrs.h>
 #endif
+#include "upnpglobalvars.h"
 
 int
 getifaddr(const char * ifname, char * buf, int len,
@@ -295,6 +296,11 @@ addr_is_reserved(struct in_addr * addr)
 	uint32_t address = ntohl(addr->s_addr);
 	size_t i;
 
+	if(GETFLAG(EXTIPRESERVEDIGNOREMASK)) {
+		syslog(LOG_NOTICE, "private/reserved address checking is ignore");
+		return 0;
+	}
+
 	for (i = 0; i < sizeof(reserved)/sizeof(reserved[0]); ++i) {
 		if ((address >> reserved[i].rmask) == (reserved[i].address >> reserved[i].rmask))
 			return 1;
--- a/miniupnpd.c
+++ b/miniupnpd.c
@@ -1225,6 +1225,10 @@ init(int argc, char * * argv, struct run
 			case UPNPEXT_IP:
 				use_ext_ip_addr = ary_options[i].value;
 				break;
+			case UPNPEXT_IP_RESERVED_IGNORE:
+				if(strcmp(ary_options[i].value, "yes") == 0)
+					SETFLAG(EXTIPRESERVEDIGNOREMASK);
+				break;
 			case UPNPEXT_PERFORM_STUN:
 				if(strcmp(ary_options[i].value, "yes") == 0)
 					SETFLAG(PERFORMSTUNMASK);
--- a/miniupnpd.conf
+++ b/miniupnpd.conf
@@ -9,6 +9,8 @@
 # Setting ext_ip is also useful in double NAT setup, you can declare here
 # the public IP address.
 #ext_ip=
+#ignore even if ext_ip is reserved: default is no
+#ext_ip_reserved_ignore=yes
 # WAN interface must have public IP address. Otherwise it is behind NAT
 # and port forwarding is impossible. In some cases WAN interface can be
 # behind unrestricted NAT 1:1 when all incoming traffic is NAT-ed and
--- a/options.c
+++ b/options.c
@@ -34,6 +34,7 @@ static const struct {
 	{ UPNPEXT_IFNAME6, "ext_ifname6" },
 #endif
 	{ UPNPEXT_IP,	"ext_ip" },
+	{ UPNPEXT_IP_RESERVED_IGNORE, "ext_ip_reserved_ignore" },
 	{ UPNPEXT_PERFORM_STUN, "ext_perform_stun" },
 	{ UPNPEXT_STUN_HOST, "ext_stun_host" },
 	{ UPNPEXT_STUN_PORT, "ext_stun_port" },
--- a/options.h
+++ b/options.h
@@ -21,6 +21,7 @@ enum upnpconfigoptions {
 	UPNPEXT_IFNAME6,		/* ext_ifname6 */
 #endif
 	UPNPEXT_IP,				/* ext_ip */
+	UPNPEXT_IP_RESERVED_IGNORE, /* ignore if ext_ip is reserved */
 	UPNPEXT_PERFORM_STUN,		/* ext_perform_stun */
 	UPNPEXT_STUN_HOST,		/* ext_stun_host */
 	UPNPEXT_STUN_PORT,		/* ext_stun_port */
--- a/testgetifaddr.c
+++ b/testgetifaddr.c
@@ -13,6 +13,8 @@
 #include "config.h"
 #include "getifaddr.h"
 
+int runtime_flags = 0;
+
 #if defined(__sun)
 /* solaris 10 does not define LOG_PERROR */
 #define LOG_PERROR 0
--- a/testportinuse.c
+++ b/testportinuse.c
@@ -14,6 +14,8 @@
 #include "config.h"
 #include "portinuse.h"
 
+int runtime_flags = 0;
+
 int main(int argc, char * * argv)
 {
 #ifndef CHECK_PORTINUSE
--- a/upnpglobalvars.h
+++ b/upnpglobalvars.h
@@ -84,6 +84,8 @@ extern int runtime_flags;
 
 #define PERFORMSTUNMASK    0x1000
 
+#define EXTIPRESERVEDIGNOREMASK 0x2000
+
 #define SETFLAG(mask)	runtime_flags |= mask
 #define GETFLAG(mask)	(runtime_flags & mask)
 #define CLEARFLAG(mask)	runtime_flags &= ~mask
