From c0a50ce33e3b99ce8a96fd43049bb5b53ffac62f Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Wed, 8 May 2024 17:37:17 +0200 Subject: [PATCH] miniupnpc: distinguish between not connected IGD and connected to a private IP fixes #732 --- miniupnpc/CMakeLists.txt | 2 +- miniupnpc/Changelog.txt | 3 +++ miniupnpc/Makefile | 2 +- miniupnpc/apiversions.txt | 5 ++++ miniupnpc/include/miniupnpc.h | 19 +++++++------ miniupnpc/man3/miniupnpc.3 | 2 +- miniupnpc/src/miniupnpc.c | 50 ++++++++++++++++++++++------------- miniupnpc/src/upnpc.c | 10 ++++--- 8 files changed, 60 insertions(+), 33 deletions(-) diff --git a/miniupnpc/CMakeLists.txt b/miniupnpc/CMakeLists.txt index 0cacf3e..b5c8f08 100644 --- a/miniupnpc/CMakeLists.txt +++ b/miniupnpc/CMakeLists.txt @@ -6,7 +6,7 @@ project (miniupnpc HOMEPAGE_URL https://miniupnp.tuxfamily.org/ LANGUAGES C) -set (MINIUPNPC_API_VERSION 17) +set (MINIUPNPC_API_VERSION 18) option (UPNPC_BUILD_STATIC "Build static library" TRUE) option (UPNPC_BUILD_SHARED "Build shared library" TRUE) diff --git a/miniupnpc/Changelog.txt b/miniupnpc/Changelog.txt index 8767741..8e02806 100644 --- a/miniupnpc/Changelog.txt +++ b/miniupnpc/Changelog.txt @@ -3,6 +3,9 @@ miniUPnP client Changelog. 2024/05/08: upnpc.c: Add -f option to upnpc program (delete multiple port redirections) + UPNP_GetValidIGD(): distinguish between not connected and connected to a + "private" network (with a reserved IP address). + Increments API_VERSION to 18 VERSION 2.2.7 : released 2024/03/20 diff --git a/miniupnpc/Makefile b/miniupnpc/Makefile index d6c11e5..909e008 100644 --- a/miniupnpc/Makefile +++ b/miniupnpc/Makefile @@ -84,7 +84,7 @@ ifneq (, $(findstring sun, $(OS))$(findstring solaris, $(OS))) endif # APIVERSION is used to build SONAME -APIVERSION = 17 +APIVERSION = 18 SRCS = $(wildcard $(SRCDIR)/*.c) diff --git a/miniupnpc/apiversions.txt b/miniupnpc/apiversions.txt index 90d169b..9e05060 100644 --- a/miniupnpc/apiversions.txt +++ b/miniupnpc/apiversions.txt @@ -2,6 +2,11 @@ $Id: apiversions.txt,v 1.9 2016/01/24 17:24:36 nanard Exp $ Differences in API between miniUPnPc versions +API version 18 + change UPNP_GetValidIGD() prototype and return values + updated macro : + #define MINIUPNPC_API_VERSION 18 + API version 17 change struct UPNPDev move getHTTPResponse() to miniwget_private.h diff --git a/miniupnpc/include/miniupnpc.h b/miniupnpc/include/miniupnpc.h index 808c6ad..91a3373 100644 --- a/miniupnpc/include/miniupnpc.h +++ b/miniupnpc/include/miniupnpc.h @@ -1,9 +1,9 @@ -/* $Id: miniupnpc.h,v 1.63 2024/01/04 00:45:17 nanard Exp $ */ +/* $Id: miniupnpc.h,v 1.64 2024/03/19 23:26:06 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * Project: miniupnp * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ * Author: Thomas Bernard - * Copyright (c) 2005-2022 Thomas Bernard + * Copyright (c) 2005-2024 Thomas Bernard * This software is subjects to the conditions detailed * in the LICENCE file provided within this distribution */ #ifndef MINIUPNPC_H_INCLUDED @@ -20,8 +20,8 @@ #define UPNPDISCOVER_MEMORY_ERROR (-102) /* versions : */ -#define MINIUPNPC_VERSION "2.2.6" -#define MINIUPNPC_API_VERSION 17 +#define MINIUPNPC_VERSION "2.2.7" +#define MINIUPNPC_API_VERSION 18 /* Source port: Using "1" as an alias for 1900 for backwards compatibility @@ -108,9 +108,11 @@ struct UPNPUrls { * return values : * 0 = NO IGD found * 1 = A valid connected IGD has been found - * 2 = A valid IGD has been found but it reported as + * 2 = A valid connected IGD has been found but its + * IP address is reserved (non routable) + * 3 = A valid IGD has been found but it reported as * not connected - * 3 = an UPnP device has been found but was not recognized as an IGD + * 4 = an UPnP device has been found but was not recognized as an IGD * * In any non zero return case, the urls and data structures * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to @@ -119,8 +121,9 @@ struct UPNPUrls { MINIUPNP_LIBSPEC int UPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPUrls * urls, - struct IGDdatas * data, - char * lanaddr, int lanaddrlen); + struct IGDdatas * data, + char * lanaddr, int lanaddrlen, + char * wanaddr, int wanaddrlen); /* UPNP_GetIGDFromUrl() * Used when skipping the discovery process. diff --git a/miniupnpc/man3/miniupnpc.3 b/miniupnpc/man3/miniupnpc.3 index e5c3ec8..4150e4b 100644 --- a/miniupnpc/man3/miniupnpc.3 +++ b/miniupnpc/man3/miniupnpc.3 @@ -38,7 +38,7 @@ be attempted as the source port. If ipv6 is not 0, IPv6 is used instead of IPv4 for the discovery process. .IP "void freeUPNPDevlist(struct UPNPDev * devlist);" free the list returned by upnpDiscover(). -.IP "int UPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen);" +.IP "int UPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen, char * wanaddr, int wanaddrlen);" browse the list of device returned by upnpDiscover(), find a live UPnP internet gateway device and fill structures passed as arguments with data used for UPNP methods invocation. diff --git a/miniupnpc/src/miniupnpc.c b/miniupnpc/src/miniupnpc.c index 696af93..e9ec4c2 100644 --- a/miniupnpc/src/miniupnpc.c +++ b/miniupnpc/src/miniupnpc.c @@ -3,7 +3,7 @@ * Project : miniupnp * Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ * Author : Thomas BERNARD - * copyright (c) 2005-2021 Thomas Bernard + * copyright (c) 2005-2024 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENSE file. */ #include @@ -534,9 +534,11 @@ UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data) * -1 = Internal error * 0 = NO IGD found * 1 = A valid connected IGD has been found - * 2 = A valid IGD has been found but it reported as + * 2 = A valid connected IGD has been found but its + * IP address is reserved (non routable) + * 3 = A valid IGD has been found but it reported as * not connected - * 3 = an UPnP device has been found but was not recognized as an IGD + * 4 = an UPnP device has been found but was not recognized as an IGD * * In any positive non zero return case, the urls and data structures * passed as parameters are set. Don't forget to call FreeUPNPUrls(urls) to @@ -545,11 +547,13 @@ UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data) MINIUPNP_LIBSPEC int UPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPUrls * urls, - struct IGDdatas * data, - char * lanaddr, int lanaddrlen) + struct IGDdatas * data, + char * lanaddr, int lanaddrlen, + char * wanaddr, int wanaddrlen) { struct xml_desc { char lanaddr[40]; + char wanaddr[40]; char * xml; int size; int is_igd; @@ -557,8 +561,8 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPDev * dev; int ndev = 0; int i; - int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */ - char extIpAddr[16]; + int state = -1; /* state 1 : IGD connected. State 2 : connected with reserved IP. + * State 3 : IGD. State 4 : anything */ int status_code = -1; if(!devlist) @@ -602,7 +606,7 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, } } /* iterate the list to find a device depending on state */ - for(state = 1; state <= 3; state++) + for(state = 1; state <= 4; state++) { for(dev = devlist, i = 0; dev; dev = dev->pNext, i++) { @@ -611,14 +615,14 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, memset(data, 0, sizeof(struct IGDdatas)); memset(urls, 0, sizeof(struct UPNPUrls)); parserootdesc(desc[i].xml, desc[i].size, data); - if(desc[i].is_igd || state >= 3 ) + if(desc[i].is_igd || state >= 4 ) { int is_connected; GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); - /* in state 2 and 3 we don't test if device is connected ! */ - if(state >= 2) + /* in state 3 and 4 we don't test if device is connected ! */ + if(state >= 3) goto free_and_return; is_connected = UPNPIGD_IsConnected(urls, data); #ifdef DEBUG @@ -626,9 +630,11 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, urls->controlURL, is_connected); #endif /* checks that status is connected AND there is a external IP address assigned */ - if(is_connected && - (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) { - if(!addr_is_reserved(extIpAddr)) + if(is_connected) { + if(state >= 2) + goto free_and_return; + if(UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, desc[i].wanaddr) == 0 + && !addr_is_reserved(desc[i].wanaddr)) goto free_and_return; } FreeUPNPUrls(urls); @@ -647,9 +653,11 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, printf("UPNPIGD_IsConnected(%s) = %d\n", urls->controlURL, is_connected); #endif - if(is_connected && - (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) { - if(!addr_is_reserved(extIpAddr)) + if(is_connected) { + if(state >= 2) + goto free_and_return; + if(UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, desc[i].wanaddr) == 0 + && !addr_is_reserved(desc[i].wanaddr)) goto free_and_return; } FreeUPNPUrls(urls); @@ -661,8 +669,12 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, } state = 0; free_and_return: - if (lanaddr != NULL && state >= 1 && state <= 3 && i < ndev) - strncpy(lanaddr, desc[i].lanaddr, lanaddrlen); + if (state >= 1 && state <= 4 && i < ndev) { + if (lanaddr != NULL) + strncpy(lanaddr, desc[i].lanaddr, lanaddrlen); + if (wanaddr != NULL) + strncpy(wanaddr, desc[i].wanaddr, wanaddrlen); + } for(i = 0; i < ndev; i++) free(desc[i].xml); free(desc); diff --git a/miniupnpc/src/upnpc.c b/miniupnpc/src/upnpc.c index 64672fd..51ff2ec 100644 --- a/miniupnpc/src/upnpc.c +++ b/miniupnpc/src/upnpc.c @@ -604,6 +604,7 @@ int main(int argc, char ** argv) int commandargc = 0; struct UPNPDev * devlist = 0; char lanaddr[64] = "unset"; /* my ip address on the LAN */ + char wanaddr[64] = "unsed"; /* up address of the IGD on the WAN */ int i; const char * rootdescurl = 0; const char * multicastif = 0; @@ -727,17 +728,20 @@ int main(int argc, char ** argv) } i = 1; if( (rootdescurl && UPNP_GetIGDFromUrl(rootdescurl, &urls, &data, lanaddr, sizeof(lanaddr))) - || (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)))) + || (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr), wanaddr, sizeof(wanaddr)))) { switch(i) { case 1: printf("Found valid IGD : %s\n", urls.controlURL); break; case 2: + printf("Found an IGD with a reserved IP address (%s) : %s\n", wanaddr, urls.controlURL); + break; + case 3: printf("Found a (not connected?) IGD : %s\n", urls.controlURL); if (ignore) printf("Trying to continue anyway\n"); break; - case 3: + case 4: printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL); if (ignore) printf("Trying to continue anyway\n"); break; @@ -745,7 +749,7 @@ int main(int argc, char ** argv) printf("Found device (igd ?) : %s\n", urls.controlURL); if (ignore) printf("Trying to continue anyway\n"); } - if(i==1 || ignore) { + if(i==1 || i==2 || ignore) { printf("Local LAN ip address : %s\n", lanaddr); #if 0