|
@@ -3,7 +3,7 @@
|
|
* Project : miniupnp
|
|
* Project : miniupnp
|
|
* Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
|
* Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
|
* Author : Thomas BERNARD
|
|
* 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
|
|
* This software is subjet to the conditions detailed in the
|
|
* provided LICENSE file. */
|
|
* provided LICENSE file. */
|
|
#include <stdlib.h>
|
|
#include <stdlib.h>
|
|
@@ -92,15 +92,15 @@ MINIUPNP_LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGD
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
-/* simpleUPnPcommand2 :
|
|
|
|
|
|
+/* simpleUPnPcommand :
|
|
* not so simple !
|
|
* not so simple !
|
|
* return values :
|
|
* return values :
|
|
* pointer - OK
|
|
* pointer - OK
|
|
* NULL - error */
|
|
* NULL - error */
|
|
-static char *
|
|
|
|
-simpleUPnPcommand2(SOCKET s, const char * url, const char * service,
|
|
|
|
- const char * action, struct UPNParg * args,
|
|
|
|
- int * bufsize, const char * httpversion)
|
|
|
|
|
|
+char *
|
|
|
|
+simpleUPnPcommand(int s, const char * url, const char * service,
|
|
|
|
+ const char * action, struct UPNParg * args,
|
|
|
|
+ int * bufsize)
|
|
{
|
|
{
|
|
char hostname[MAXHOSTNAMELEN+1];
|
|
char hostname[MAXHOSTNAMELEN+1];
|
|
unsigned short port = 0;
|
|
unsigned short port = 0;
|
|
@@ -197,15 +197,15 @@ simpleUPnPcommand2(SOCKET s, const char * url, const char * service,
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
if(!parseURL(url, hostname, &port, &path, NULL)) return NULL;
|
|
if(!parseURL(url, hostname, &port, &path, NULL)) return NULL;
|
|
- if(ISINVALID(s)) {
|
|
|
|
|
|
+ if(ISINVALID((SOCKET)s)) {
|
|
s = connecthostport(hostname, port, 0);
|
|
s = connecthostport(hostname, port, 0);
|
|
- if(ISINVALID(s)) {
|
|
|
|
|
|
+ if(ISINVALID((SOCKET)s)) {
|
|
/* failed to connect */
|
|
/* failed to connect */
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, httpversion);
|
|
|
|
|
|
+ n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, "1.1");
|
|
if(n<=0) {
|
|
if(n<=0) {
|
|
#ifdef DEBUG
|
|
#ifdef DEBUG
|
|
printf("Error sending SOAP request\n");
|
|
printf("Error sending SOAP request\n");
|
|
@@ -229,33 +229,6 @@ simpleUPnPcommand2(SOCKET s, const char * url, const char * service,
|
|
return buf;
|
|
return buf;
|
|
}
|
|
}
|
|
|
|
|
|
-/* simpleUPnPcommand :
|
|
|
|
- * not so simple !
|
|
|
|
- * return values :
|
|
|
|
- * pointer - OK
|
|
|
|
- * NULL - error */
|
|
|
|
-char *
|
|
|
|
-simpleUPnPcommand(int s, const char * url, const char * service,
|
|
|
|
- const char * action, struct UPNParg * args,
|
|
|
|
- int * bufsize)
|
|
|
|
-{
|
|
|
|
- char * buf;
|
|
|
|
-
|
|
|
|
-#if 1
|
|
|
|
- buf = simpleUPnPcommand2((SOCKET)s, url, service, action, args, bufsize, "1.1");
|
|
|
|
-#else
|
|
|
|
- buf = simpleUPnPcommand2((SOCKET)s, url, service, action, args, bufsize, "1.0");
|
|
|
|
- if (!buf || *bufsize == 0)
|
|
|
|
- {
|
|
|
|
-#if DEBUG
|
|
|
|
- printf("Error or no result from SOAP request; retrying with HTTP/1.1\n");
|
|
|
|
-#endif
|
|
|
|
- buf = simpleUPnPcommand2((SOCKET)s, url, service, action, args, bufsize, "1.1");
|
|
|
|
- }
|
|
|
|
-#endif
|
|
|
|
- return buf;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
/* upnpDiscoverDevices() :
|
|
/* upnpDiscoverDevices() :
|
|
* return a chained list of all devices found or NULL if
|
|
* return a chained list of all devices found or NULL if
|
|
* no devices was found.
|
|
* no devices was found.
|
|
@@ -534,9 +507,11 @@ UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data)
|
|
* -1 = Internal error
|
|
* -1 = Internal error
|
|
* 0 = NO IGD found
|
|
* 0 = NO IGD found
|
|
* 1 = A valid connected IGD has been 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
|
|
* 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
|
|
* 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
|
|
* passed as parameters are set. Don't forget to call FreeUPNPUrls(urls) to
|
|
@@ -545,11 +520,13 @@ UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data)
|
|
MINIUPNP_LIBSPEC int
|
|
MINIUPNP_LIBSPEC int
|
|
UPNP_GetValidIGD(struct UPNPDev * devlist,
|
|
UPNP_GetValidIGD(struct UPNPDev * devlist,
|
|
struct UPNPUrls * urls,
|
|
struct UPNPUrls * urls,
|
|
- struct IGDdatas * data,
|
|
|
|
- char * lanaddr, int lanaddrlen)
|
|
|
|
|
|
+ struct IGDdatas * data,
|
|
|
|
+ char * lanaddr, int lanaddrlen,
|
|
|
|
+ char * wanaddr, int wanaddrlen)
|
|
{
|
|
{
|
|
struct xml_desc {
|
|
struct xml_desc {
|
|
char lanaddr[40];
|
|
char lanaddr[40];
|
|
|
|
+ char wanaddr[40];
|
|
char * xml;
|
|
char * xml;
|
|
int size;
|
|
int size;
|
|
int is_igd;
|
|
int is_igd;
|
|
@@ -557,8 +534,8 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
|
|
struct UPNPDev * dev;
|
|
struct UPNPDev * dev;
|
|
int ndev = 0;
|
|
int ndev = 0;
|
|
int i;
|
|
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;
|
|
int status_code = -1;
|
|
|
|
|
|
if(!devlist)
|
|
if(!devlist)
|
|
@@ -602,7 +579,7 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* iterate the list to find a device depending on state */
|
|
/* 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++)
|
|
for(dev = devlist, i = 0; dev; dev = dev->pNext, i++)
|
|
{
|
|
{
|
|
@@ -611,14 +588,14 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
|
|
memset(data, 0, sizeof(struct IGDdatas));
|
|
memset(data, 0, sizeof(struct IGDdatas));
|
|
memset(urls, 0, sizeof(struct UPNPUrls));
|
|
memset(urls, 0, sizeof(struct UPNPUrls));
|
|
parserootdesc(desc[i].xml, desc[i].size, data);
|
|
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;
|
|
int is_connected;
|
|
|
|
|
|
GetUPNPUrls(urls, data, dev->descURL, dev->scope_id);
|
|
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;
|
|
goto free_and_return;
|
|
is_connected = UPNPIGD_IsConnected(urls, data);
|
|
is_connected = UPNPIGD_IsConnected(urls, data);
|
|
#ifdef DEBUG
|
|
#ifdef DEBUG
|
|
@@ -626,9 +603,11 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
|
|
urls->controlURL, is_connected);
|
|
urls->controlURL, is_connected);
|
|
#endif
|
|
#endif
|
|
/* checks that status is connected AND there is a external IP address assigned */
|
|
/* 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;
|
|
goto free_and_return;
|
|
}
|
|
}
|
|
FreeUPNPUrls(urls);
|
|
FreeUPNPUrls(urls);
|
|
@@ -647,9 +626,11 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
|
|
printf("UPNPIGD_IsConnected(%s) = %d\n",
|
|
printf("UPNPIGD_IsConnected(%s) = %d\n",
|
|
urls->controlURL, is_connected);
|
|
urls->controlURL, is_connected);
|
|
#endif
|
|
#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;
|
|
goto free_and_return;
|
|
}
|
|
}
|
|
FreeUPNPUrls(urls);
|
|
FreeUPNPUrls(urls);
|
|
@@ -661,8 +642,12 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
|
|
}
|
|
}
|
|
state = 0;
|
|
state = 0;
|
|
free_and_return:
|
|
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++)
|
|
for(i = 0; i < ndev; i++)
|
|
free(desc[i].xml);
|
|
free(desc[i].xml);
|
|
free(desc);
|
|
free(desc);
|