Merge pull request #45018 from akien-mga/miniupnpc-2.2.1
miniupnpc: Update to version 2.2.2
This commit is contained in:
commit
21b05a3944
|
@ -269,7 +269,7 @@ License: CC0-1.0
|
|||
|
||||
Files: ./thirdparty/miniupnpc/
|
||||
Comment: MiniUPnPc
|
||||
Copyright: 2005-2019, Thomas Bernard
|
||||
Copyright: 2005-2021, Thomas Bernard
|
||||
License: BSD-3-clause
|
||||
|
||||
Files: ./thirdparty/minizip/
|
||||
|
|
|
@ -12,18 +12,19 @@ thirdparty_obj = []
|
|||
if env["builtin_miniupnpc"]:
|
||||
thirdparty_dir = "#thirdparty/miniupnpc/"
|
||||
thirdparty_sources = [
|
||||
"miniupnpc.c",
|
||||
"upnpcommands.c",
|
||||
"miniwget.c",
|
||||
"upnpdev.c",
|
||||
"igd_desc_parse.c",
|
||||
"minissdpc.c",
|
||||
"minisoap.c",
|
||||
"miniupnpc.c",
|
||||
"minixml.c",
|
||||
"connecthostport.c",
|
||||
"receivedata.c",
|
||||
"portlistingparse.c",
|
||||
"minisoap.c",
|
||||
"minissdpc.c",
|
||||
"miniwget.c",
|
||||
"upnpcommands.c",
|
||||
"upnpdev.c",
|
||||
"upnpreplyparse.c",
|
||||
"connecthostport.c",
|
||||
"portlistingparse.c",
|
||||
"receivedata.c",
|
||||
"addr_is_reserved.c",
|
||||
]
|
||||
thirdparty_sources = [thirdparty_dir + "miniupnpc/" + file for file in thirdparty_sources]
|
||||
|
||||
|
|
|
@ -355,17 +355,20 @@ Files extracted from upstream repository:
|
|||
|
||||
## miniupnpc
|
||||
|
||||
- Upstream: https://github.com/miniupnp/miniupnp/tree/master/miniupnpc
|
||||
- Version: git (44366328661826603982d1e0d7ebb4062c5f2bfc, 2020)
|
||||
- Upstream: https://github.com/miniupnp/miniupnp
|
||||
- Version: 2.2.2 (81029a860baf1f727903e5b85307903b3f40cbc8, 2021)
|
||||
- License: BSD-3-Clause
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
||||
- All `*.c` and `*.h` files from `miniupnpc` to `thirdparty/miniupnpc/miniupnpc`
|
||||
- Remove `test*`, `minihttptestserver.c` and `wingenminiupnpcstrings.c`
|
||||
- Remove the following test or sample files:
|
||||
`listdevices.c minihttptestserver.c miniupnpcmodule.c upnpc.c upnperrors.* test* wingenminiupnpcstrings.c`
|
||||
- `LICENSE`
|
||||
|
||||
The only modified file is miniupnpcstrings.h, which was created for Godot
|
||||
(it is usually autogenerated by cmake).
|
||||
The only modified file is `miniupnpcstrings.h`, which was created for Godot
|
||||
(it is usually autogenerated by cmake). Bump the version number for miniupnpc in that
|
||||
file when upgrading.
|
||||
|
||||
|
||||
## minizip
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
MiniUPnP Project
|
||||
Copyright (c) 2005-2019, Thomas BERNARD
|
||||
MiniUPnPc
|
||||
Copyright (c) 2005-2020, Thomas BERNARD
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
@ -24,3 +24,4 @@ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/* $Id: addr_is_reserved.c,v 1.4 2021/03/02 23:40:32 nanard Exp $ */
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* Project : miniupnp
|
||||
* Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||
* Author : Thomas BERNARD
|
||||
* copyright (c) 2005-2021 Thomas Bernard
|
||||
* This software is subjet to the conditions detailed in the
|
||||
* provided LICENSE file. */
|
||||
#ifdef _WIN32
|
||||
/* Win32 Specific includes and defines */
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#if !defined(_MSC_VER)
|
||||
#include <stdint.h>
|
||||
#else /* !defined(_MSC_VER) */
|
||||
typedef unsigned long uint32_t;
|
||||
#endif /* !defined(_MSC_VER) */
|
||||
#else /* _WIN32 */
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/* List of IP address blocks which are private / reserved and therefore not suitable for public external IP addresses */
|
||||
#define IP(a, b, c, d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d))
|
||||
#define MSK(m) (32-(m))
|
||||
static const struct { uint32_t address; uint32_t rmask; } reserved[] = {
|
||||
{ IP( 0, 0, 0, 0), MSK( 8) }, /* RFC1122 "This host on this network" */
|
||||
{ IP( 10, 0, 0, 0), MSK( 8) }, /* RFC1918 Private-Use */
|
||||
{ IP(100, 64, 0, 0), MSK(10) }, /* RFC6598 Shared Address Space */
|
||||
{ IP(127, 0, 0, 0), MSK( 8) }, /* RFC1122 Loopback */
|
||||
{ IP(169, 254, 0, 0), MSK(16) }, /* RFC3927 Link-Local */
|
||||
{ IP(172, 16, 0, 0), MSK(12) }, /* RFC1918 Private-Use */
|
||||
{ IP(192, 0, 0, 0), MSK(24) }, /* RFC6890 IETF Protocol Assignments */
|
||||
{ IP(192, 0, 2, 0), MSK(24) }, /* RFC5737 Documentation (TEST-NET-1) */
|
||||
{ IP(192, 31, 196, 0), MSK(24) }, /* RFC7535 AS112-v4 */
|
||||
{ IP(192, 52, 193, 0), MSK(24) }, /* RFC7450 AMT */
|
||||
{ IP(192, 88, 99, 0), MSK(24) }, /* RFC7526 6to4 Relay Anycast */
|
||||
{ IP(192, 168, 0, 0), MSK(16) }, /* RFC1918 Private-Use */
|
||||
{ IP(192, 175, 48, 0), MSK(24) }, /* RFC7534 Direct Delegation AS112 Service */
|
||||
{ IP(198, 18, 0, 0), MSK(15) }, /* RFC2544 Benchmarking */
|
||||
{ IP(198, 51, 100, 0), MSK(24) }, /* RFC5737 Documentation (TEST-NET-2) */
|
||||
{ IP(203, 0, 113, 0), MSK(24) }, /* RFC5737 Documentation (TEST-NET-3) */
|
||||
{ IP(224, 0, 0, 0), MSK( 4) }, /* RFC1112 Multicast */
|
||||
{ IP(240, 0, 0, 0), MSK( 4) }, /* RFC1112 Reserved for Future Use + RFC919 Limited Broadcast */
|
||||
};
|
||||
#undef IP
|
||||
#undef MSK
|
||||
|
||||
/**
|
||||
* @return 1 or 0
|
||||
*/
|
||||
int addr_is_reserved(const char * addr_str)
|
||||
{
|
||||
uint32_t addr_n, address;
|
||||
size_t i;
|
||||
|
||||
#if defined(_WIN32) && (!defined(_WIN32_WINNT_VISTA) || (_WIN32_WINNT < _WIN32_WINNT_VISTA))
|
||||
addr_n = inet_addr(addr_str);
|
||||
if (addr_n == INADDR_NONE)
|
||||
return 1;
|
||||
#else
|
||||
/* was : addr_n = inet_addr(addr_str); */
|
||||
if (inet_pton(AF_INET, addr_str, &addr_n) <= 0) {
|
||||
/* error */
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
address = ntohl(addr_n);
|
||||
|
||||
for (i = 0; i < sizeof(reserved)/sizeof(reserved[0]); ++i) {
|
||||
if ((address >> reserved[i].rmask) == (reserved[i].address >> reserved[i].rmask))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/* $Id: $ */
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* Project: miniupnp
|
||||
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||
* Author: Thomas Bernard
|
||||
* Copyright (c) 2005-2020 Thomas Bernard
|
||||
* This software is subjects to the conditions detailed
|
||||
* in the LICENCE file provided within this distribution */
|
||||
#ifndef ADDR_IS_RESERVED_H_INCLUDED
|
||||
#define ADDR_IS_RESERVED_H_INCLUDED
|
||||
|
||||
int addr_is_reserved(const char * addr_str);
|
||||
|
||||
#endif /* ADDR_IS_RESERVED_H_INCLUDED */
|
|
@ -1,8 +1,8 @@
|
|||
/* $Id: connecthostport.c,v 1.22 2019/10/13 17:22:08 nanard Exp $ */
|
||||
/* $Id: connecthostport.c,v 1.24 2020/11/09 19:26:53 nanard Exp $ */
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* Project : miniupnp
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2010-2019 Thomas Bernard
|
||||
* Copyright (c) 2010-2020 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution. */
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
|||
#include <ws2tcpip.h>
|
||||
#include <io.h>
|
||||
#define MAXHOSTNAMELEN 64
|
||||
#define snprintf _snprintf
|
||||
#include "win32_snprintf.h"
|
||||
#define herror
|
||||
#define socklen_t int
|
||||
#else /* #ifdef _WIN32 */
|
||||
|
|
|
@ -1,197 +0,0 @@
|
|||
/* $Id: listdevices.c,v 1.6 2015/07/23 20:40:08 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2013-2015 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#endif /* _WIN32 */
|
||||
#include "miniupnpc.h"
|
||||
|
||||
struct upnp_dev_list {
|
||||
struct upnp_dev_list * next;
|
||||
char * descURL;
|
||||
struct UPNPDev * * array;
|
||||
size_t count;
|
||||
size_t allocated_count;
|
||||
};
|
||||
|
||||
#define ADD_DEVICE_COUNT_STEP 16
|
||||
|
||||
void add_device(struct upnp_dev_list * * list_head, struct UPNPDev * dev)
|
||||
{
|
||||
struct upnp_dev_list * elt;
|
||||
size_t i;
|
||||
|
||||
if(dev == NULL)
|
||||
return;
|
||||
for(elt = *list_head; elt != NULL; elt = elt->next) {
|
||||
if(strcmp(elt->descURL, dev->descURL) == 0) {
|
||||
for(i = 0; i < elt->count; i++) {
|
||||
if (strcmp(elt->array[i]->st, dev->st) == 0 && strcmp(elt->array[i]->usn, dev->usn) == 0) {
|
||||
return; /* already found */
|
||||
}
|
||||
}
|
||||
if(elt->count >= elt->allocated_count) {
|
||||
struct UPNPDev * * tmp;
|
||||
elt->allocated_count += ADD_DEVICE_COUNT_STEP;
|
||||
tmp = realloc(elt->array, elt->allocated_count * sizeof(struct UPNPDev *));
|
||||
if(tmp == NULL) {
|
||||
fprintf(stderr, "Failed to realloc(%p, %lu)\n", elt->array, (unsigned long)(elt->allocated_count * sizeof(struct UPNPDev *)));
|
||||
return;
|
||||
}
|
||||
elt->array = tmp;
|
||||
}
|
||||
elt->array[elt->count++] = dev;
|
||||
return;
|
||||
}
|
||||
}
|
||||
elt = malloc(sizeof(struct upnp_dev_list));
|
||||
if(elt == NULL) {
|
||||
fprintf(stderr, "Failed to malloc(%lu)\n", (unsigned long)sizeof(struct upnp_dev_list));
|
||||
return;
|
||||
}
|
||||
elt->next = *list_head;
|
||||
elt->descURL = strdup(dev->descURL);
|
||||
if(elt->descURL == NULL) {
|
||||
fprintf(stderr, "Failed to strdup(%s)\n", dev->descURL);
|
||||
free(elt);
|
||||
return;
|
||||
}
|
||||
elt->allocated_count = ADD_DEVICE_COUNT_STEP;
|
||||
elt->array = malloc(ADD_DEVICE_COUNT_STEP * sizeof(struct UPNPDev *));
|
||||
if(elt->array == NULL) {
|
||||
fprintf(stderr, "Failed to malloc(%lu)\n", (unsigned long)(ADD_DEVICE_COUNT_STEP * sizeof(struct UPNPDev *)));
|
||||
free(elt->descURL);
|
||||
free(elt);
|
||||
return;
|
||||
}
|
||||
elt->array[0] = dev;
|
||||
elt->count = 1;
|
||||
*list_head = elt;
|
||||
}
|
||||
|
||||
void free_device(struct upnp_dev_list * elt)
|
||||
{
|
||||
free(elt->descURL);
|
||||
free(elt->array);
|
||||
free(elt);
|
||||
}
|
||||
|
||||
int main(int argc, char * * argv)
|
||||
{
|
||||
const char * searched_device = NULL;
|
||||
const char * * searched_devices = NULL;
|
||||
const char * multicastif = 0;
|
||||
const char * minissdpdpath = 0;
|
||||
int ipv6 = 0;
|
||||
unsigned char ttl = 2;
|
||||
int error = 0;
|
||||
struct UPNPDev * devlist = 0;
|
||||
struct UPNPDev * dev;
|
||||
struct upnp_dev_list * sorted_list = NULL;
|
||||
struct upnp_dev_list * dev_array;
|
||||
int i;
|
||||
|
||||
#ifdef _WIN32
|
||||
WSADATA wsaData;
|
||||
int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
|
||||
if(nResult != NO_ERROR)
|
||||
{
|
||||
fprintf(stderr, "WSAStartup() failed.\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
for(i = 1; i < argc; i++) {
|
||||
if(strcmp(argv[i], "-6") == 0)
|
||||
ipv6 = 1;
|
||||
else if(strcmp(argv[i], "-d") == 0) {
|
||||
if(++i >= argc) {
|
||||
fprintf(stderr, "%s option needs one argument\n", "-d");
|
||||
return 1;
|
||||
}
|
||||
searched_device = argv[i];
|
||||
} else if(strcmp(argv[i], "-t") == 0) {
|
||||
if(++i >= argc) {
|
||||
fprintf(stderr, "%s option needs one argument\n", "-t");
|
||||
return 1;
|
||||
}
|
||||
ttl = (unsigned char)atoi(argv[i]);
|
||||
} else if(strcmp(argv[i], "-l") == 0) {
|
||||
if(++i >= argc) {
|
||||
fprintf(stderr, "-l option needs at least one argument\n");
|
||||
return 1;
|
||||
}
|
||||
searched_devices = (const char * *)(argv + i);
|
||||
break;
|
||||
} else if(strcmp(argv[i], "-m") == 0) {
|
||||
if(++i >= argc) {
|
||||
fprintf(stderr, "-m option needs one argument\n");
|
||||
return 1;
|
||||
}
|
||||
multicastif = argv[i];
|
||||
} else {
|
||||
printf("usage : %s [options] [-l <device1> <device2> ...]\n", argv[0]);
|
||||
printf("options :\n");
|
||||
printf(" -6 : use IPv6\n");
|
||||
printf(" -m address/ifname : network interface to use for multicast\n");
|
||||
printf(" -d <device string> : search only for this type of device\n");
|
||||
printf(" -l <device1> <device2> ... : search only for theses types of device\n");
|
||||
printf(" -t ttl : set multicast TTL. Default value is 2.\n");
|
||||
printf(" -h : this help\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(searched_device) {
|
||||
printf("searching UPnP device type %s\n", searched_device);
|
||||
devlist = upnpDiscoverDevice(searched_device,
|
||||
2000, multicastif, minissdpdpath,
|
||||
0/*localport*/, ipv6, ttl, &error);
|
||||
} else if(searched_devices) {
|
||||
printf("searching UPnP device types :\n");
|
||||
for(i = 0; searched_devices[i]; i++)
|
||||
printf("\t%s\n", searched_devices[i]);
|
||||
devlist = upnpDiscoverDevices(searched_devices,
|
||||
2000, multicastif, minissdpdpath,
|
||||
0/*localport*/, ipv6, ttl, &error, 1);
|
||||
} else {
|
||||
printf("searching all UPnP devices\n");
|
||||
devlist = upnpDiscoverAll(2000, multicastif, minissdpdpath,
|
||||
0/*localport*/, ipv6, ttl, &error);
|
||||
}
|
||||
if(devlist) {
|
||||
for(dev = devlist, i = 1; dev != NULL; dev = dev->pNext, i++) {
|
||||
printf("%3d: %-48s\n", i, dev->st);
|
||||
printf(" %s\n", dev->descURL);
|
||||
printf(" %s\n", dev->usn);
|
||||
add_device(&sorted_list, dev);
|
||||
}
|
||||
putchar('\n');
|
||||
for (dev_array = sorted_list; dev_array != NULL ; dev_array = dev_array->next) {
|
||||
printf("%s :\n", dev_array->descURL);
|
||||
for(i = 0; (unsigned)i < dev_array->count; i++) {
|
||||
printf("%2d: %s\n", i+1, dev_array->array[i]->st);
|
||||
printf(" %s\n", dev_array->array[i]->usn);
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
freeUPNPDevlist(devlist);
|
||||
while(sorted_list != NULL) {
|
||||
dev_array = sorted_list;
|
||||
sorted_list = sorted_list->next;
|
||||
free_device(dev_array);
|
||||
}
|
||||
} else {
|
||||
printf("no device found.\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
/* $Id: minisoap.c,v 1.25 2017/04/21 10:03:24 nanard Exp $ */
|
||||
/* $Id: minisoap.c,v 1.30 2020/11/09 19:27:42 nanard Exp $ */
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* Project : miniupnp
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005-2018 Thomas Bernard
|
||||
* Copyright (c) 2005-2020 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution.
|
||||
*
|
||||
|
@ -13,7 +13,7 @@
|
|||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#include <winsock2.h>
|
||||
#define snprintf _snprintf
|
||||
#include "win32_snprintf.h"
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
/* $Id: minissdpc.c,v 1.40 2019/04/23 12:12:55 nanard Exp $ */
|
||||
/* $Id: minissdpc.c,v 1.47 2021/03/02 23:38:30 nanard Exp $ */
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* Project : miniupnp
|
||||
* Web : http://miniupnp.free.fr/
|
||||
* Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||
* Author : Thomas BERNARD
|
||||
* copyright (c) 2005-2019 Thomas Bernard
|
||||
* copyright (c) 2005-2021 Thomas Bernard
|
||||
* This software is subjet to the conditions detailed in the
|
||||
* provided LICENCE file. */
|
||||
/*#include <syslog.h>*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#if defined (__NetBSD__)
|
||||
#include <net/if.h>
|
||||
|
@ -20,7 +20,7 @@
|
|||
#include <ws2tcpip.h>
|
||||
#include <io.h>
|
||||
#include <iphlpapi.h>
|
||||
#define snprintf _snprintf
|
||||
#include "win32_snprintf.h"
|
||||
#if !defined(_MSC_VER)
|
||||
#include <stdint.h>
|
||||
#else /* !defined(_MSC_VER) */
|
||||
|
@ -33,6 +33,12 @@ typedef unsigned short uint16_t;
|
|||
#define strncasecmp memicmp
|
||||
#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
|
||||
#endif /* #ifndef strncasecmp */
|
||||
#if defined(WINAPI_FAMILY) && defined(WINAPI_FAMILY_PARTITION)
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP
|
||||
#define in6addr_any in6addr_any_init
|
||||
static const IN6_ADDR in6addr_any_init = {0};
|
||||
#endif
|
||||
#endif
|
||||
#endif /* _WIN32 */
|
||||
#if defined(__amigaos__) || defined(__amigaos4__)
|
||||
#include <sys/socket.h>
|
||||
|
@ -66,7 +72,7 @@ struct sockaddr_un {
|
|||
#define HAS_IP_MREQN
|
||||
#endif
|
||||
|
||||
#if !defined(HAS_IP_MREQN) && !defined(_WIN32)
|
||||
#ifndef _WIN32
|
||||
#include <sys/ioctl.h>
|
||||
#if defined(__sun) || defined(__HAIKU__)
|
||||
#include <sys/sockio.h>
|
||||
|
@ -445,6 +451,36 @@ parseMSEARCHReply(const char * reply, int size,
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(CLOCK_MONOTONIC_FAST)
|
||||
#define UPNP_CLOCKID CLOCK_MONOTONIC_FAST
|
||||
#elif defined(CLOCK_MONOTONIC)
|
||||
#define UPNP_CLOCKID CLOCK_MONOTONIC
|
||||
#endif
|
||||
|
||||
static int upnp_gettimeofday(struct timeval * tv)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
#if defined(_WIN32_WINNT_VISTA) && (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
|
||||
ULONGLONG ts = GetTickCount64();
|
||||
#else
|
||||
DWORD ts = GetTickCount();
|
||||
#endif
|
||||
tv->tv_sec = (long)(ts / 1000);
|
||||
tv->tv_usec = (ts % 1000) * 1000;
|
||||
return 0; /* success */
|
||||
#elif defined(CLOCK_MONOTONIC_FAST) || defined(CLOCK_MONOTONIC)
|
||||
struct timespec ts;
|
||||
int ret_code = clock_gettime(UPNP_CLOCKID, &ts);
|
||||
if (ret_code == 0)
|
||||
{
|
||||
tv->tv_sec = ts.tv_sec;
|
||||
tv->tv_usec = ts.tv_nsec / 1000;
|
||||
}
|
||||
return ret_code;
|
||||
#else
|
||||
return gettimeofday(tv, NULL);
|
||||
#endif
|
||||
}
|
||||
/* port upnp discover : SSDP protocol */
|
||||
#define SSDP_PORT 1900
|
||||
#define XSTR(s) STR(s)
|
||||
|
@ -540,12 +576,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
|
|||
* in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */
|
||||
if(!ipv6) {
|
||||
DWORD ifbestidx;
|
||||
SOCKADDR_IN destAddr;
|
||||
memset(&destAddr, 0, sizeof(destAddr));
|
||||
destAddr.sin_family = AF_INET;
|
||||
destAddr.sin_addr.s_addr = inet_addr("223.255.255.255");
|
||||
destAddr.sin_port = 0;
|
||||
if (GetBestInterfaceEx((struct sockaddr *)&destAddr, &ifbestidx) == NO_ERROR) {
|
||||
if (GetBestInterface(inet_addr("223.255.255.255"), &ifbestidx) == NO_ERROR) {
|
||||
DWORD dwRetVal = NO_ERROR;
|
||||
PIP_ADAPTER_ADDRESSES pAddresses = NULL;
|
||||
ULONG outBufLen = 15360;
|
||||
|
@ -672,6 +703,13 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
|
|||
* MS Windows Vista and MS Windows Server 2008.
|
||||
* http://msdn.microsoft.com/en-us/library/bb408409%28v=vs.85%29.aspx */
|
||||
unsigned int ifindex = if_nametoindex(multicastif); /* eth0, etc. */
|
||||
if(ifindex == 0)
|
||||
{
|
||||
if(error)
|
||||
*error = MINISSDPC_INVALID_INPUT;
|
||||
fprintf(stderr, "Invalid multicast interface name %s\n", multicastif);
|
||||
goto error;
|
||||
}
|
||||
if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) < 0)
|
||||
{
|
||||
PRINT_SOCKET_ERROR("setsockopt IPV6_MULTICAST_IF");
|
||||
|
@ -683,10 +721,17 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
|
|||
#endif
|
||||
} else {
|
||||
struct in_addr mc_if;
|
||||
#if defined(_WIN32) && (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
|
||||
#if defined(_WIN32)
|
||||
#if defined(_WIN32_WINNT_VISTA) && (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
|
||||
InetPtonA(AF_INET, multicastif, &mc_if);
|
||||
#else
|
||||
mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */
|
||||
mc_if.s_addr = inet_addr(multicastif); /* old Windows SDK do not support InetPtoA() */
|
||||
#endif
|
||||
#else
|
||||
/* was : mc_if.s_addr = inet_addr(multicastif); */ /* ex: 192.168.x.x */
|
||||
if (inet_pton(AF_INET, multicastif, &mc_if.s_addr) <= 0) {
|
||||
mc_if.s_addr = INADDR_NONE;
|
||||
}
|
||||
#endif
|
||||
if(mc_if.s_addr != INADDR_NONE)
|
||||
{
|
||||
|
@ -696,16 +741,11 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
|
|||
PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
|
||||
}
|
||||
} else {
|
||||
#ifdef HAS_IP_MREQN
|
||||
/* was not an ip address, try with an interface name */
|
||||
#ifndef _WIN32
|
||||
#ifdef HAS_IP_MREQN
|
||||
struct ip_mreqn reqn; /* only defined with -D_BSD_SOURCE or -D_GNU_SOURCE */
|
||||
memset(&reqn, 0, sizeof(struct ip_mreqn));
|
||||
reqn.imr_ifindex = if_nametoindex(multicastif);
|
||||
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0)
|
||||
{
|
||||
PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
|
||||
}
|
||||
#elif !defined(_WIN32)
|
||||
#endif
|
||||
struct ifreq ifr;
|
||||
int ifrlen = sizeof(ifr);
|
||||
strncpy(ifr.ifr_name, multicastif, IFNAMSIZ);
|
||||
|
@ -713,12 +753,30 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
|
|||
if(ioctl(sudp, SIOCGIFADDR, &ifr, &ifrlen) < 0)
|
||||
{
|
||||
PRINT_SOCKET_ERROR("ioctl(...SIOCGIFADDR...)");
|
||||
goto error;
|
||||
}
|
||||
mc_if.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
|
||||
#ifdef HAS_IP_MREQN
|
||||
memset(&reqn, 0, sizeof(struct ip_mreqn));
|
||||
reqn.imr_address.s_addr = mc_if.s_addr;
|
||||
reqn.imr_ifindex = if_nametoindex(multicastif);
|
||||
if(reqn.imr_ifindex == 0)
|
||||
{
|
||||
if(error)
|
||||
*error = MINISSDPC_INVALID_INPUT;
|
||||
fprintf(stderr, "Invalid multicast ip address / interface name %s\n", multicastif);
|
||||
goto error;
|
||||
}
|
||||
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0)
|
||||
{
|
||||
PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
|
||||
}
|
||||
#else
|
||||
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
|
||||
{
|
||||
PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
|
||||
}
|
||||
#endif
|
||||
#else /* _WIN32 */
|
||||
#ifdef DEBUG
|
||||
printf("Setting of multicast interface not supported with interface name.\n");
|
||||
|
@ -842,73 +900,84 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
|
|||
/* Waiting for SSDP REPLY packet to M-SEARCH
|
||||
* if searchalltypes is set, enter the loop only
|
||||
* when the last deviceType is reached */
|
||||
if((sentok && !searchalltypes) || !deviceTypes[deviceIndex + 1]) do {
|
||||
n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id);
|
||||
if (n < 0) {
|
||||
/* error */
|
||||
if(error)
|
||||
*error = MINISSDPC_SOCKET_ERROR;
|
||||
goto error;
|
||||
} else if (n == 0) {
|
||||
/* no data or Time Out */
|
||||
#ifdef DEBUG
|
||||
printf("NODATA or TIMEOUT\n");
|
||||
#endif /* DEBUG */
|
||||
if (devlist && !searchalltypes) {
|
||||
/* found some devices, stop now*/
|
||||
if((sentok && !searchalltypes) || !deviceTypes[deviceIndex + 1]) {
|
||||
struct timeval start = {0, 0}, current = {0, 0};
|
||||
upnp_gettimeofday(&start);
|
||||
do {
|
||||
n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id);
|
||||
if (n < 0) {
|
||||
/* error */
|
||||
if(error)
|
||||
*error = MINISSDPC_SUCCESS;
|
||||
*error = MINISSDPC_SOCKET_ERROR;
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
const char * descURL=NULL;
|
||||
int urlsize=0;
|
||||
const char * st=NULL;
|
||||
int stsize=0;
|
||||
const char * usn=NULL;
|
||||
int usnsize=0;
|
||||
parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize, &usn, &usnsize);
|
||||
if(st&&descURL) {
|
||||
} else if (n == 0) {
|
||||
/* no data or Time Out */
|
||||
#ifdef DEBUG
|
||||
printf("M-SEARCH Reply:\n ST: %.*s\n USN: %.*s\n Location: %.*s\n",
|
||||
stsize, st, usnsize, (usn?usn:""), urlsize, descURL);
|
||||
printf("NODATA or TIMEOUT\n");
|
||||
#endif /* DEBUG */
|
||||
for(tmp=devlist; tmp; tmp = tmp->pNext) {
|
||||
if(strncmp(tmp->descURL, descURL, urlsize) == 0 &&
|
||||
tmp->descURL[urlsize] == '\0' &&
|
||||
strncmp(tmp->st, st, stsize) == 0 &&
|
||||
tmp->st[stsize] == '\0' &&
|
||||
(usnsize == 0 || strncmp(tmp->usn, usn, usnsize) == 0) &&
|
||||
tmp->usn[usnsize] == '\0')
|
||||
break;
|
||||
}
|
||||
/* at the exit of the loop above, tmp is null if
|
||||
* no duplicate device was found */
|
||||
if(tmp)
|
||||
continue;
|
||||
tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize);
|
||||
if(!tmp) {
|
||||
/* memory allocation error */
|
||||
if (devlist && !searchalltypes) {
|
||||
/* found some devices, stop now*/
|
||||
if(error)
|
||||
*error = MINISSDPC_MEMORY_ERROR;
|
||||
*error = MINISSDPC_SUCCESS;
|
||||
goto error;
|
||||
}
|
||||
tmp->pNext = devlist;
|
||||
tmp->descURL = tmp->buffer;
|
||||
tmp->st = tmp->buffer + 1 + urlsize;
|
||||
tmp->usn = tmp->st + 1 + stsize;
|
||||
memcpy(tmp->buffer, descURL, urlsize);
|
||||
tmp->buffer[urlsize] = '\0';
|
||||
memcpy(tmp->st, st, stsize);
|
||||
tmp->buffer[urlsize+1+stsize] = '\0';
|
||||
if(usn != NULL)
|
||||
memcpy(tmp->usn, usn, usnsize);
|
||||
tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0';
|
||||
tmp->scope_id = scope_id;
|
||||
devlist = tmp;
|
||||
} else {
|
||||
const char * descURL=NULL;
|
||||
int urlsize=0;
|
||||
const char * st=NULL;
|
||||
int stsize=0;
|
||||
const char * usn=NULL;
|
||||
int usnsize=0;
|
||||
parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize, &usn, &usnsize);
|
||||
if(st&&descURL) {
|
||||
#ifdef DEBUG
|
||||
printf("M-SEARCH Reply:\n ST: %.*s\n USN: %.*s\n Location: %.*s\n",
|
||||
stsize, st, usnsize, (usn?usn:""), urlsize, descURL);
|
||||
#endif /* DEBUG */
|
||||
for(tmp=devlist; tmp; tmp = tmp->pNext) {
|
||||
if(strncmp(tmp->descURL, descURL, urlsize) == 0 &&
|
||||
tmp->descURL[urlsize] == '\0' &&
|
||||
strncmp(tmp->st, st, stsize) == 0 &&
|
||||
tmp->st[stsize] == '\0' &&
|
||||
(usnsize == 0 || strncmp(tmp->usn, usn, usnsize) == 0) &&
|
||||
tmp->usn[usnsize] == '\0')
|
||||
break;
|
||||
}
|
||||
/* at the exit of the loop above, tmp is null if
|
||||
* no duplicate device was found */
|
||||
if(tmp)
|
||||
continue;
|
||||
tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize+3);
|
||||
if(!tmp) {
|
||||
/* memory allocation error */
|
||||
if(error)
|
||||
*error = MINISSDPC_MEMORY_ERROR;
|
||||
goto error;
|
||||
}
|
||||
tmp->pNext = devlist;
|
||||
tmp->descURL = tmp->buffer;
|
||||
tmp->st = tmp->buffer + 1 + urlsize;
|
||||
tmp->usn = tmp->st + 1 + stsize;
|
||||
memcpy(tmp->buffer, descURL, urlsize);
|
||||
tmp->buffer[urlsize] = '\0';
|
||||
memcpy(tmp->st, st, stsize);
|
||||
tmp->buffer[urlsize+1+stsize] = '\0';
|
||||
if(usn != NULL)
|
||||
memcpy(tmp->usn, usn, usnsize);
|
||||
tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0';
|
||||
tmp->scope_id = scope_id;
|
||||
devlist = tmp;
|
||||
}
|
||||
if (upnp_gettimeofday(¤t) >= 0) {
|
||||
/* exit the loop if delay is reached */
|
||||
long interval = (current.tv_sec - start.tv_sec) * 1000;
|
||||
interval += (current.tv_usec - start.tv_usec) / 1000;
|
||||
if (interval > (long)delay)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(n > 0);
|
||||
} while(n > 0);
|
||||
}
|
||||
if(ipv6) {
|
||||
/* switch linklocal flag */
|
||||
if(linklocal) {
|
||||
|
@ -923,4 +992,3 @@ error:
|
|||
closesocket(sudp);
|
||||
return devlist;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/* $Id: miniupnpc.c,v 1.154 2019/04/23 12:12:13 nanard Exp $ */
|
||||
/* $Id: miniupnpc.c,v 1.159 2021/03/02 23:36:32 nanard Exp $ */
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* Project : miniupnp
|
||||
* Web : http://miniupnp.free.fr/
|
||||
* Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||
* Author : Thomas BERNARD
|
||||
* copyright (c) 2005-2019 Thomas Bernard
|
||||
* copyright (c) 2005-2021 Thomas Bernard
|
||||
* This software is subjet to the conditions detailed in the
|
||||
* provided LICENSE file. */
|
||||
#include <stdlib.h>
|
||||
|
@ -15,7 +15,7 @@
|
|||
#include <ws2tcpip.h>
|
||||
#include <io.h>
|
||||
#include <iphlpapi.h>
|
||||
#define snprintf _snprintf
|
||||
#include "win32_snprintf.h"
|
||||
#define strdup _strdup
|
||||
#ifndef strncasecmp
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
|
@ -61,6 +61,7 @@
|
|||
#include "minixml.h"
|
||||
#include "upnpcommands.h"
|
||||
#include "connecthostport.h"
|
||||
#include "addr_is_reserved.h"
|
||||
|
||||
/* compare the beginning of a string with a constant string */
|
||||
#define COMPARE(str, cstr) (0==strncmp(str, cstr, sizeof(cstr) - 1))
|
||||
|
@ -73,24 +74,6 @@
|
|||
#define SERVICEPREFIX "u"
|
||||
#define SERVICEPREFIX2 'u'
|
||||
|
||||
/* check if an ip address is a private (LAN) address
|
||||
* see https://tools.ietf.org/html/rfc1918 */
|
||||
static int is_rfc1918addr(const char * addr)
|
||||
{
|
||||
/* 192.168.0.0 - 192.168.255.255 (192.168/16 prefix) */
|
||||
if(COMPARE(addr, "192.168."))
|
||||
return 1;
|
||||
/* 10.0.0.0 - 10.255.255.255 (10/8 prefix) */
|
||||
if(COMPARE(addr, "10."))
|
||||
return 1;
|
||||
/* 172.16.0.0 - 172.31.255.255 (172.16/12 prefix) */
|
||||
if(COMPARE(addr, "172.")) {
|
||||
if((atoi(addr + 4) | 0x0f) == 0x1f)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* root description parsing */
|
||||
MINIUPNP_LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data)
|
||||
{
|
||||
|
@ -337,6 +320,8 @@ upnpDiscoverDevices(const char * const deviceTypes[],
|
|||
return devlist;
|
||||
}
|
||||
}
|
||||
#else /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
|
||||
(void)minissdpdsock; /* unused */
|
||||
#endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
|
||||
|
||||
/* direct discovery if minissdpd responses are not sufficient */
|
||||
|
@ -643,8 +628,7 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
|
|||
/* 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(!is_rfc1918addr(extIpAddr) && (extIpAddr[0] != '\0')
|
||||
&& (0 != strcmp(extIpAddr, "0.0.0.0")))
|
||||
if(!addr_is_reserved(extIpAddr))
|
||||
goto free_and_return;
|
||||
}
|
||||
FreeUPNPUrls(urls);
|
||||
|
@ -665,8 +649,7 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
|
|||
#endif
|
||||
if(is_connected &&
|
||||
(UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) {
|
||||
if(!is_rfc1918addr(extIpAddr) && (extIpAddr[0] != '\0')
|
||||
&& (0 != strcmp(extIpAddr, "0.0.0.0")))
|
||||
if(!addr_is_reserved(extIpAddr))
|
||||
goto free_and_return;
|
||||
}
|
||||
FreeUPNPUrls(urls);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/* $Id: miniupnpc.h,v 1.53 2018/05/07 11:05:16 nanard Exp $ */
|
||||
/* $Id: miniupnpc.h,v 1.58 2021/03/02 23:49:52 nanard Exp $ */
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* Project: miniupnp
|
||||
* http://miniupnp.free.fr/
|
||||
* Author: Thomas Bernard
|
||||
* Copyright (c) 2005-2018 Thomas Bernard
|
||||
* Copyright (c) 2005-2021 Thomas Bernard
|
||||
* This software is subjects to the conditions detailed
|
||||
* in the LICENCE file provided within this distribution */
|
||||
#ifndef MINIUPNPC_H_INCLUDED
|
||||
|
@ -20,7 +20,7 @@
|
|||
#define UPNPDISCOVER_MEMORY_ERROR (-102)
|
||||
|
||||
/* versions : */
|
||||
#define MINIUPNPC_VERSION "2.1"
|
||||
#define MINIUPNPC_VERSION "2.2.2"
|
||||
#define MINIUPNPC_API_VERSION 17
|
||||
|
||||
/* Source port:
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#ifndef MINIUPNPC_SOCKETDEF_H_INCLUDED
|
||||
#define MINIUPNPC_SOCKETDEF_H_INCLUDED
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#ifdef _WIN32
|
||||
|
||||
#define ISINVALID(s) (INVALID_SOCKET==(s))
|
||||
|
||||
|
|
|
@ -1,721 +0,0 @@
|
|||
/* $Id: miniupnpcmodule.c,v 1.34 2019/05/20 19:07:16 nanard Exp $*/
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* Project : miniupnp
|
||||
* Author : Thomas BERNARD
|
||||
* website : https://miniupnp.tuxfamily.org/
|
||||
* copyright (c) 2007-2019 Thomas Bernard
|
||||
* This software is subjet to the conditions detailed in the
|
||||
* provided LICENCE file. */
|
||||
#include <Python.h>
|
||||
#define MINIUPNP_STATICLIB
|
||||
#include "structmember.h"
|
||||
#include "miniupnpc.h"
|
||||
#include "upnpcommands.h"
|
||||
#include "upnperrors.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
/* for compatibility with Python < 2.4 */
|
||||
#ifndef Py_RETURN_NONE
|
||||
#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
|
||||
#endif
|
||||
|
||||
#ifndef Py_RETURN_TRUE
|
||||
#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
|
||||
#endif
|
||||
|
||||
#ifndef Py_RETURN_FALSE
|
||||
#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
|
||||
#endif
|
||||
|
||||
/* for compatibility with Python < 3.0 */
|
||||
#ifndef PyVarObject_HEAD_INIT
|
||||
#define PyVarObject_HEAD_INIT(type, size) \
|
||||
PyObject_HEAD_INIT(type) size,
|
||||
#endif
|
||||
|
||||
#ifndef Py_TYPE
|
||||
#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
/* Type-specific fields go here. */
|
||||
struct UPNPDev * devlist;
|
||||
struct UPNPUrls urls;
|
||||
struct IGDdatas data;
|
||||
unsigned int discoverdelay; /* value passed to upnpDiscover() */
|
||||
unsigned int localport; /* value passed to upnpDiscover() */
|
||||
char lanaddr[40]; /* our ip address on the LAN */
|
||||
char * multicastif;
|
||||
char * minissdpdsocket;
|
||||
} UPnPObject;
|
||||
|
||||
static PyMemberDef UPnP_members[] = {
|
||||
{"lanaddr", T_STRING_INPLACE, offsetof(UPnPObject, lanaddr),
|
||||
READONLY, "ip address on the LAN"
|
||||
},
|
||||
{"discoverdelay", T_UINT, offsetof(UPnPObject, discoverdelay),
|
||||
0/*READWRITE*/, "value in ms used to wait for SSDP responses"
|
||||
},
|
||||
{"localport", T_UINT, offsetof(UPnPObject, localport),
|
||||
0/*READWRITE*/,
|
||||
"If localport is set to UPNP_LOCAL_PORT_SAME(1) "
|
||||
"SSDP packets will be sent from the source port "
|
||||
"1900 (same as destination port), if set to "
|
||||
"UPNP_LOCAL_PORT_ANY(0) system assign a source "
|
||||
"port, any other value will be attempted as the "
|
||||
"source port"
|
||||
},
|
||||
/* T_STRING is allways readonly :( */
|
||||
{"multicastif", T_STRING, offsetof(UPnPObject, multicastif),
|
||||
0, "IP of the network interface to be used for multicast operations"
|
||||
},
|
||||
{"minissdpdsocket", T_STRING, offsetof(UPnPObject, minissdpdsocket),
|
||||
0, "path of the MiniSSDPd unix socket"
|
||||
},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
|
||||
static int UPnP_init(UPnPObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
char* multicastif = NULL;
|
||||
char* minissdpdsocket = NULL;
|
||||
static char *kwlist[] = {
|
||||
"multicastif", "minissdpdsocket", "discoverdelay",
|
||||
"localport", NULL
|
||||
};
|
||||
|
||||
if(!PyArg_ParseTupleAndKeywords(args, kwds, "|zzII", kwlist,
|
||||
&multicastif,
|
||||
&minissdpdsocket,
|
||||
&self->discoverdelay,
|
||||
&self->localport))
|
||||
return -1;
|
||||
|
||||
if(self->localport>1 &&
|
||||
(self->localport>65534||self->localport<1024)) {
|
||||
PyErr_SetString(PyExc_Exception, "Invalid localport value");
|
||||
return -1;
|
||||
}
|
||||
if(multicastif)
|
||||
self->multicastif = strdup(multicastif);
|
||||
if(minissdpdsocket)
|
||||
self->minissdpdsocket = strdup(minissdpdsocket);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
UPnPObject_dealloc(UPnPObject *self)
|
||||
{
|
||||
freeUPNPDevlist(self->devlist);
|
||||
FreeUPNPUrls(&self->urls);
|
||||
free(self->multicastif);
|
||||
free(self->minissdpdsocket);
|
||||
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
UPnP_discover(UPnPObject *self)
|
||||
{
|
||||
struct UPNPDev * dev;
|
||||
int i;
|
||||
PyObject *res = NULL;
|
||||
if(self->devlist)
|
||||
{
|
||||
freeUPNPDevlist(self->devlist);
|
||||
self->devlist = 0;
|
||||
}
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
self->devlist = upnpDiscover((int)self->discoverdelay/*timeout in ms*/,
|
||||
self->multicastif,
|
||||
self->minissdpdsocket,
|
||||
(int)self->localport,
|
||||
0/*ip v6*/,
|
||||
2/* TTL */,
|
||||
0/*error */);
|
||||
Py_END_ALLOW_THREADS
|
||||
/* Py_RETURN_NONE ??? */
|
||||
for(dev = self->devlist, i = 0; dev; dev = dev->pNext)
|
||||
i++;
|
||||
res = Py_BuildValue("i", i);
|
||||
return res;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
UPnP_selectigd(UPnPObject *self)
|
||||
{
|
||||
int r;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
r = UPNP_GetValidIGD(self->devlist, &self->urls, &self->data,
|
||||
self->lanaddr, sizeof(self->lanaddr));
|
||||
Py_END_ALLOW_THREADS
|
||||
if(r)
|
||||
{
|
||||
return Py_BuildValue("s", self->urls.controlURL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TODO: have our own exception type ! */
|
||||
PyErr_SetString(PyExc_Exception, "No UPnP device discovered");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
UPnP_totalbytesent(UPnPObject *self)
|
||||
{
|
||||
UNSIGNED_INTEGER i;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
i = UPNP_GetTotalBytesSent(self->urls.controlURL_CIF,
|
||||
self->data.CIF.servicetype);
|
||||
Py_END_ALLOW_THREADS
|
||||
#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
|
||||
return Py_BuildValue("I", i);
|
||||
#else
|
||||
return Py_BuildValue("i", (int)i);
|
||||
#endif
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
UPnP_totalbytereceived(UPnPObject *self)
|
||||
{
|
||||
UNSIGNED_INTEGER i;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
i = UPNP_GetTotalBytesReceived(self->urls.controlURL_CIF,
|
||||
self->data.CIF.servicetype);
|
||||
Py_END_ALLOW_THREADS
|
||||
#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
|
||||
return Py_BuildValue("I", i);
|
||||
#else
|
||||
return Py_BuildValue("i", (int)i);
|
||||
#endif
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
UPnP_totalpacketsent(UPnPObject *self)
|
||||
{
|
||||
UNSIGNED_INTEGER i;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
i = UPNP_GetTotalPacketsSent(self->urls.controlURL_CIF,
|
||||
self->data.CIF.servicetype);
|
||||
Py_END_ALLOW_THREADS
|
||||
#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
|
||||
return Py_BuildValue("I", i);
|
||||
#else
|
||||
return Py_BuildValue("i", (int)i);
|
||||
#endif
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
UPnP_totalpacketreceived(UPnPObject *self)
|
||||
{
|
||||
UNSIGNED_INTEGER i;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
i = UPNP_GetTotalPacketsReceived(self->urls.controlURL_CIF,
|
||||
self->data.CIF.servicetype);
|
||||
Py_END_ALLOW_THREADS
|
||||
#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
|
||||
return Py_BuildValue("I", i);
|
||||
#else
|
||||
return Py_BuildValue("i", (int)i);
|
||||
#endif
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
UPnP_statusinfo(UPnPObject *self)
|
||||
{
|
||||
char status[64];
|
||||
char lastconnerror[64];
|
||||
unsigned int uptime = 0;
|
||||
int r;
|
||||
status[0] = '\0';
|
||||
lastconnerror[0] = '\0';
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
r = UPNP_GetStatusInfo(self->urls.controlURL, self->data.first.servicetype,
|
||||
status, &uptime, lastconnerror);
|
||||
Py_END_ALLOW_THREADS
|
||||
if(r==UPNPCOMMAND_SUCCESS) {
|
||||
#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
|
||||
return Py_BuildValue("(s,I,s)", status, uptime, lastconnerror);
|
||||
#else
|
||||
return Py_BuildValue("(s,i,s)", status, (int)uptime, lastconnerror);
|
||||
#endif
|
||||
} else {
|
||||
/* TODO: have our own exception type ! */
|
||||
PyErr_SetString(PyExc_Exception, strupnperror(r));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
UPnP_connectiontype(UPnPObject *self)
|
||||
{
|
||||
char connectionType[64];
|
||||
int r;
|
||||
connectionType[0] = '\0';
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
r = UPNP_GetConnectionTypeInfo(self->urls.controlURL,
|
||||
self->data.first.servicetype,
|
||||
connectionType);
|
||||
Py_END_ALLOW_THREADS
|
||||
if(r==UPNPCOMMAND_SUCCESS) {
|
||||
return Py_BuildValue("s", connectionType);
|
||||
} else {
|
||||
/* TODO: have our own exception type ! */
|
||||
PyErr_SetString(PyExc_Exception, strupnperror(r));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
UPnP_externalipaddress(UPnPObject *self)
|
||||
{
|
||||
char externalIPAddress[40];
|
||||
int r;
|
||||
externalIPAddress[0] = '\0';
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
r = UPNP_GetExternalIPAddress(self->urls.controlURL,
|
||||
self->data.first.servicetype,
|
||||
externalIPAddress);
|
||||
Py_END_ALLOW_THREADS
|
||||
if(r==UPNPCOMMAND_SUCCESS) {
|
||||
return Py_BuildValue("s", externalIPAddress);
|
||||
} else {
|
||||
/* TODO: have our own exception type ! */
|
||||
PyErr_SetString(PyExc_Exception, strupnperror(r));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* AddPortMapping(externalPort, protocol, internalHost, internalPort, desc,
|
||||
* remoteHost, leaseDuration)
|
||||
* protocol is 'UDP' or 'TCP' */
|
||||
static PyObject *
|
||||
UPnP_addportmapping(UPnPObject *self, PyObject *args)
|
||||
{
|
||||
char extPort[6];
|
||||
unsigned short ePort;
|
||||
char inPort[6];
|
||||
unsigned short iPort;
|
||||
const char * proto;
|
||||
const char * host;
|
||||
const char * desc;
|
||||
const char * remoteHost;
|
||||
unsigned int intLeaseDuration = 0;
|
||||
char strLeaseDuration[12];
|
||||
int r;
|
||||
#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
|
||||
if (!PyArg_ParseTuple(args, "HssHzz|I", &ePort, &proto,
|
||||
&host, &iPort, &desc, &remoteHost, &intLeaseDuration))
|
||||
#else
|
||||
if (!PyArg_ParseTuple(args, "HssHzz|i", &ePort, &proto,
|
||||
&host, &iPort, &desc, &remoteHost, (int *)&intLeaseDuration))
|
||||
#endif
|
||||
return NULL;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
sprintf(extPort, "%hu", ePort);
|
||||
sprintf(inPort, "%hu", iPort);
|
||||
sprintf(strLeaseDuration, "%u", intLeaseDuration);
|
||||
r = UPNP_AddPortMapping(self->urls.controlURL, self->data.first.servicetype,
|
||||
extPort, inPort, host, desc, proto,
|
||||
remoteHost, strLeaseDuration);
|
||||
Py_END_ALLOW_THREADS
|
||||
if(r==UPNPCOMMAND_SUCCESS)
|
||||
{
|
||||
Py_RETURN_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: RAISE an Exception. See upnpcommands.h for errors codes.
|
||||
// upnperrors.c
|
||||
//Py_RETURN_FALSE;
|
||||
/* TODO: have our own exception type ! */
|
||||
PyErr_SetString(PyExc_Exception, strupnperror(r));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* AddAnyPortMapping(externalPort, protocol, internalHost, internalPort, desc,
|
||||
* remoteHost)
|
||||
* protocol is 'UDP' or 'TCP' */
|
||||
static PyObject *
|
||||
UPnP_addanyportmapping(UPnPObject *self, PyObject *args)
|
||||
{
|
||||
char extPort[6];
|
||||
unsigned short ePort;
|
||||
char inPort[6];
|
||||
unsigned short iPort;
|
||||
char reservedPort[6];
|
||||
const char * proto;
|
||||
const char * host;
|
||||
const char * desc;
|
||||
const char * remoteHost;
|
||||
const char * leaseDuration = "0";
|
||||
int r;
|
||||
if (!PyArg_ParseTuple(args, "HssHzz", &ePort, &proto, &host, &iPort, &desc, &remoteHost))
|
||||
return NULL;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
sprintf(extPort, "%hu", ePort);
|
||||
sprintf(inPort, "%hu", iPort);
|
||||
r = UPNP_AddAnyPortMapping(self->urls.controlURL, self->data.first.servicetype,
|
||||
extPort, inPort, host, desc, proto,
|
||||
remoteHost, leaseDuration, reservedPort);
|
||||
Py_END_ALLOW_THREADS
|
||||
if(r==UPNPCOMMAND_SUCCESS) {
|
||||
return Py_BuildValue("i", atoi(reservedPort));
|
||||
} else {
|
||||
/* TODO: have our own exception type ! */
|
||||
PyErr_SetString(PyExc_Exception, strupnperror(r));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* DeletePortMapping(extPort, proto, removeHost='')
|
||||
* proto = 'UDP', 'TCP' */
|
||||
static PyObject *
|
||||
UPnP_deleteportmapping(UPnPObject *self, PyObject *args)
|
||||
{
|
||||
char extPort[6];
|
||||
unsigned short ePort;
|
||||
const char * proto;
|
||||
const char * remoteHost = "";
|
||||
int r;
|
||||
if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost))
|
||||
return NULL;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
sprintf(extPort, "%hu", ePort);
|
||||
r = UPNP_DeletePortMapping(self->urls.controlURL, self->data.first.servicetype,
|
||||
extPort, proto, remoteHost);
|
||||
Py_END_ALLOW_THREADS
|
||||
if(r==UPNPCOMMAND_SUCCESS) {
|
||||
Py_RETURN_TRUE;
|
||||
} else {
|
||||
/* TODO: have our own exception type ! */
|
||||
PyErr_SetString(PyExc_Exception, strupnperror(r));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* DeletePortMappingRange(extPort, proto, removeHost='')
|
||||
* proto = 'UDP', 'TCP' */
|
||||
static PyObject *
|
||||
UPnP_deleteportmappingrange(UPnPObject *self, PyObject *args)
|
||||
{
|
||||
char extPortStart[6];
|
||||
unsigned short ePortStart;
|
||||
char extPortEnd[6];
|
||||
unsigned short ePortEnd;
|
||||
const char * proto;
|
||||
unsigned char manage;
|
||||
char manageStr[6];
|
||||
int r;
|
||||
if(!PyArg_ParseTuple(args, "HHsb", &ePortStart, &ePortEnd, &proto, &manage))
|
||||
return NULL;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
sprintf(extPortStart, "%hu", ePortStart);
|
||||
sprintf(extPortEnd, "%hu", ePortEnd);
|
||||
sprintf(manageStr, "%hu", (unsigned short)manage);
|
||||
r = UPNP_DeletePortMappingRange(self->urls.controlURL, self->data.first.servicetype,
|
||||
extPortStart, extPortEnd, proto, manageStr);
|
||||
Py_END_ALLOW_THREADS
|
||||
if(r==UPNPCOMMAND_SUCCESS) {
|
||||
Py_RETURN_TRUE;
|
||||
} else {
|
||||
/* TODO: have our own exception type ! */
|
||||
PyErr_SetString(PyExc_Exception, strupnperror(r));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
UPnP_getportmappingnumberofentries(UPnPObject *self)
|
||||
{
|
||||
unsigned int n = 0;
|
||||
int r;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
r = UPNP_GetPortMappingNumberOfEntries(self->urls.controlURL,
|
||||
self->data.first.servicetype,
|
||||
&n);
|
||||
Py_END_ALLOW_THREADS
|
||||
if(r==UPNPCOMMAND_SUCCESS) {
|
||||
#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
|
||||
return Py_BuildValue("I", n);
|
||||
#else
|
||||
return Py_BuildValue("i", (int)n);
|
||||
#endif
|
||||
} else {
|
||||
/* TODO: have our own exception type ! */
|
||||
PyErr_SetString(PyExc_Exception, strupnperror(r));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* GetSpecificPortMapping(ePort, proto, remoteHost='')
|
||||
* proto = 'UDP' or 'TCP' */
|
||||
static PyObject *
|
||||
UPnP_getspecificportmapping(UPnPObject *self, PyObject *args)
|
||||
{
|
||||
char extPort[6];
|
||||
unsigned short ePort;
|
||||
const char * proto;
|
||||
const char * remoteHost = "";
|
||||
char intClient[40];
|
||||
char intPort[6];
|
||||
unsigned short iPort;
|
||||
char desc[80];
|
||||
char enabled[4];
|
||||
char leaseDuration[16];
|
||||
if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost))
|
||||
return NULL;
|
||||
extPort[0] = '\0'; intClient[0] = '\0'; intPort[0] = '\0';
|
||||
desc[0] = '\0'; enabled[0] = '\0'; leaseDuration[0] = '\0';
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
sprintf(extPort, "%hu", ePort);
|
||||
UPNP_GetSpecificPortMappingEntry(self->urls.controlURL,
|
||||
self->data.first.servicetype,
|
||||
extPort, proto, remoteHost,
|
||||
intClient, intPort,
|
||||
desc, enabled, leaseDuration);
|
||||
Py_END_ALLOW_THREADS
|
||||
if(intClient[0])
|
||||
{
|
||||
iPort = (unsigned short)atoi(intPort);
|
||||
return Py_BuildValue("(s,H,s,O,i)",
|
||||
intClient, iPort, desc,
|
||||
PyBool_FromLong(atoi(enabled)),
|
||||
atoi(leaseDuration));
|
||||
}
|
||||
else
|
||||
{
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/* GetGenericPortMapping(index) */
|
||||
static PyObject *
|
||||
UPnP_getgenericportmapping(UPnPObject *self, PyObject *args)
|
||||
{
|
||||
int i, r;
|
||||
char index[8];
|
||||
char intClient[40];
|
||||
char intPort[6];
|
||||
unsigned short iPort;
|
||||
char extPort[6];
|
||||
unsigned short ePort;
|
||||
char protocol[4];
|
||||
char desc[80];
|
||||
char enabled[6];
|
||||
char rHost[64];
|
||||
char duration[16]; /* lease duration */
|
||||
unsigned int dur;
|
||||
if(!PyArg_ParseTuple(args, "i", &i))
|
||||
return NULL;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
snprintf(index, sizeof(index), "%d", i);
|
||||
rHost[0] = '\0'; enabled[0] = '\0';
|
||||
duration[0] = '\0'; desc[0] = '\0';
|
||||
extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0';
|
||||
r = UPNP_GetGenericPortMappingEntry(self->urls.controlURL,
|
||||
self->data.first.servicetype,
|
||||
index,
|
||||
extPort, intClient, intPort,
|
||||
protocol, desc, enabled, rHost,
|
||||
duration);
|
||||
Py_END_ALLOW_THREADS
|
||||
if(r==UPNPCOMMAND_SUCCESS)
|
||||
{
|
||||
ePort = (unsigned short)atoi(extPort);
|
||||
iPort = (unsigned short)atoi(intPort);
|
||||
dur = (unsigned int)strtoul(duration, 0, 0);
|
||||
#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
|
||||
return Py_BuildValue("(H,s,(s,H),s,s,s,I)",
|
||||
ePort, protocol, intClient, iPort,
|
||||
desc, enabled, rHost, dur);
|
||||
#else
|
||||
return Py_BuildValue("(i,s,(s,i),s,s,s,i)",
|
||||
(int)ePort, protocol, intClient, (int)iPort,
|
||||
desc, enabled, rHost, (int)dur);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/* miniupnpc.UPnP object Method Table */
|
||||
static PyMethodDef UPnP_methods[] = {
|
||||
{"discover", (PyCFunction)UPnP_discover, METH_NOARGS,
|
||||
"discover UPnP IGD devices on the network"
|
||||
},
|
||||
{"selectigd", (PyCFunction)UPnP_selectigd, METH_NOARGS,
|
||||
"select a valid UPnP IGD among discovered devices"
|
||||
},
|
||||
{"totalbytesent", (PyCFunction)UPnP_totalbytesent, METH_NOARGS,
|
||||
"return the total number of bytes sent by UPnP IGD"
|
||||
},
|
||||
{"totalbytereceived", (PyCFunction)UPnP_totalbytereceived, METH_NOARGS,
|
||||
"return the total number of bytes received by UPnP IGD"
|
||||
},
|
||||
{"totalpacketsent", (PyCFunction)UPnP_totalpacketsent, METH_NOARGS,
|
||||
"return the total number of packets sent by UPnP IGD"
|
||||
},
|
||||
{"totalpacketreceived", (PyCFunction)UPnP_totalpacketreceived, METH_NOARGS,
|
||||
"return the total number of packets received by UPnP IGD"
|
||||
},
|
||||
{"statusinfo", (PyCFunction)UPnP_statusinfo, METH_NOARGS,
|
||||
"return status and uptime"
|
||||
},
|
||||
{"connectiontype", (PyCFunction)UPnP_connectiontype, METH_NOARGS,
|
||||
"return IGD WAN connection type"
|
||||
},
|
||||
{"externalipaddress", (PyCFunction)UPnP_externalipaddress, METH_NOARGS,
|
||||
"return external IP address"
|
||||
},
|
||||
{"addportmapping", (PyCFunction)UPnP_addportmapping, METH_VARARGS,
|
||||
"add a port mapping"
|
||||
},
|
||||
{"addanyportmapping", (PyCFunction)UPnP_addanyportmapping, METH_VARARGS,
|
||||
"add a port mapping, IGD to select alternative if necessary"
|
||||
},
|
||||
{"deleteportmapping", (PyCFunction)UPnP_deleteportmapping, METH_VARARGS,
|
||||
"delete a port mapping"
|
||||
},
|
||||
{"deleteportmappingrange", (PyCFunction)UPnP_deleteportmappingrange, METH_VARARGS,
|
||||
"delete a range of port mappings"
|
||||
},
|
||||
{"getportmappingnumberofentries", (PyCFunction)UPnP_getportmappingnumberofentries, METH_NOARGS,
|
||||
"-- non standard --"
|
||||
},
|
||||
{"getspecificportmapping", (PyCFunction)UPnP_getspecificportmapping, METH_VARARGS,
|
||||
"get details about a specific port mapping entry"
|
||||
},
|
||||
{"getgenericportmapping", (PyCFunction)UPnP_getgenericportmapping, METH_VARARGS,
|
||||
"get all details about the port mapping at index"
|
||||
},
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
static PyTypeObject UPnPType = {
|
||||
PyVarObject_HEAD_INIT(NULL,
|
||||
0) /*ob_size*/
|
||||
"miniupnpc.UPnP", /*tp_name*/
|
||||
sizeof(UPnPObject), /*tp_basicsize*/
|
||||
0, /*tp_itemsize*/
|
||||
(destructor)UPnPObject_dealloc,/*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
0, /*tp_hash */
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||
"UPnP objects", /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
UPnP_methods, /* tp_methods */
|
||||
UPnP_members, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
(initproc)UPnP_init, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
#ifndef _WIN32
|
||||
PyType_GenericNew,/*UPnP_new,*/ /* tp_new */
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
};
|
||||
|
||||
/* module methods */
|
||||
static PyMethodDef miniupnpc_methods[] = {
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
static struct PyModuleDef moduledef = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"miniupnpc", /* m_name */
|
||||
"miniupnpc module.", /* m_doc */
|
||||
-1, /* m_size */
|
||||
miniupnpc_methods, /* m_methods */
|
||||
NULL, /* m_reload */
|
||||
NULL, /* m_traverse */
|
||||
NULL, /* m_clear */
|
||||
NULL, /* m_free */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
|
||||
#define PyMODINIT_FUNC void
|
||||
#endif
|
||||
|
||||
PyMODINIT_FUNC
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyInit_miniupnpc(void)
|
||||
#else
|
||||
initminiupnpc(void)
|
||||
#endif
|
||||
{
|
||||
PyObject* m;
|
||||
|
||||
#ifdef _WIN32
|
||||
/* initialize Winsock. */
|
||||
WSADATA wsaData;
|
||||
int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
|
||||
if (nResult != 0)
|
||||
{
|
||||
/* error code could be WSASYSNOTREADY WSASYSNOTREADY
|
||||
* WSASYSNOTREADY WSASYSNOTREADY WSASYSNOTREADY */
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return 0;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
UPnPType.tp_new = PyType_GenericNew;
|
||||
#endif
|
||||
if (PyType_Ready(&UPnPType) < 0)
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return 0;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
m = PyModule_Create(&moduledef);
|
||||
#else
|
||||
m = Py_InitModule3("miniupnpc", miniupnpc_methods,
|
||||
"miniupnpc module.");
|
||||
#endif
|
||||
|
||||
Py_INCREF(&UPnPType);
|
||||
PyModule_AddObject(m, "UPnP", (PyObject *)&UPnPType);
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return m;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
#include "core/version.h"
|
||||
|
||||
#define OS_STRING VERSION_NAME "/1.0"
|
||||
#define MINIUPNPC_VERSION_STRING "2.1"
|
||||
#define MINIUPNPC_VERSION_STRING "2.2.2"
|
||||
|
||||
#if 0
|
||||
/* according to "UPnP Device Architecture 1.0" */
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* $Id: miniwget.c,v 1.78 2018/03/13 23:22:18 nanard Exp $ */
|
||||
/* $Id: miniwget.c,v 1.82 2020/05/29 21:14:22 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Website : http://miniupnp.free.fr/
|
||||
* Website : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005-2018 Thomas Bernard
|
||||
* Copyright (c) 2005-2020 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution. */
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
|||
#include <ws2tcpip.h>
|
||||
#include <io.h>
|
||||
#define MAXHOSTNAMELEN 64
|
||||
#define snprintf _snprintf
|
||||
#include "win32_snprintf.h"
|
||||
#define socklen_t int
|
||||
#ifndef strncasecmp
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
|
@ -176,11 +176,14 @@ getHTTPResponse(SOCKET s, int * size, int * status_code)
|
|||
/* Status line
|
||||
* HTTP-Version SP Status-Code SP Reason-Phrase CRLF */
|
||||
int sp;
|
||||
for(sp = 0; sp < i; sp++)
|
||||
for(sp = 0; sp < i - 1; sp++)
|
||||
if(header_buf[sp] == ' ')
|
||||
{
|
||||
if(*status_code < 0)
|
||||
*status_code = atoi(header_buf + sp + 1);
|
||||
{
|
||||
if (header_buf[sp+1] >= '1' && header_buf[sp+1] <= '9')
|
||||
*status_code = atoi(header_buf + sp + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#if defined(__HAIKU__)
|
||||
/* rename our private function because Haiku already defines a atoui() function */
|
||||
#define atoui atoui2
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* list of the elements */
|
||||
static const struct {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* $Id: receivedata.c,v 1.7 2015/11/09 21:51:41 nanard Exp $ */
|
||||
/* $Id: receivedata.c,v 1.10 2021/03/02 23:33:07 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Website : http://miniupnp.free.fr/
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2011-2014 Thomas Bernard
|
||||
* Copyright (c) 2011-2021 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution. */
|
||||
|
||||
|
@ -92,7 +92,13 @@ receivedata(SOCKET socket,
|
|||
#endif /* DEBUG */
|
||||
if(scope_id)
|
||||
*scope_id = src_addr6->sin6_scope_id;
|
||||
} else {
|
||||
if(scope_id)
|
||||
*scope_id = 0;
|
||||
}
|
||||
#else /* MINIUPNPC_GET_SRC_ADDR */
|
||||
if(scope_id)
|
||||
*scope_id = 0;
|
||||
#endif /* MINIUPNPC_GET_SRC_ADDR */
|
||||
return n;
|
||||
}
|
||||
|
|
|
@ -1,864 +0,0 @@
|
|||
/* $Id: upnpc.c,v 1.119 2018/03/13 23:34:46 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005-2020 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#define snprintf _snprintf
|
||||
#else
|
||||
/* for IPPROTO_TCP / IPPROTO_UDP */
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include "miniwget.h"
|
||||
#include "miniupnpc.h"
|
||||
#include "upnpcommands.h"
|
||||
#include "portlistingparse.h"
|
||||
#include "upnperrors.h"
|
||||
#include "miniupnpcstrings.h"
|
||||
|
||||
/* protofix() checks if protocol is "UDP" or "TCP"
|
||||
* returns NULL if not */
|
||||
const char * protofix(const char * proto)
|
||||
{
|
||||
static const char proto_tcp[4] = { 'T', 'C', 'P', 0};
|
||||
static const char proto_udp[4] = { 'U', 'D', 'P', 0};
|
||||
int i, b;
|
||||
for(i=0, b=1; i<4; i++)
|
||||
b = b && ( (proto[i] == proto_tcp[i])
|
||||
|| (proto[i] == (proto_tcp[i] | 32)) );
|
||||
if(b)
|
||||
return proto_tcp;
|
||||
for(i=0, b=1; i<4; i++)
|
||||
b = b && ( (proto[i] == proto_udp[i])
|
||||
|| (proto[i] == (proto_udp[i] | 32)) );
|
||||
if(b)
|
||||
return proto_udp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* is_int() checks if parameter is an integer or not
|
||||
* 1 for integer
|
||||
* 0 for not an integer */
|
||||
int is_int(char const* s)
|
||||
{
|
||||
if(s == NULL)
|
||||
return 0;
|
||||
while(*s) {
|
||||
/* #define isdigit(c) ((c) >= '0' && (c) <= '9') */
|
||||
if(!isdigit(*s))
|
||||
return 0;
|
||||
s++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void DisplayInfos(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data)
|
||||
{
|
||||
char externalIPAddress[40];
|
||||
char connectionType[64];
|
||||
char status[64];
|
||||
char lastconnerr[64];
|
||||
unsigned int uptime = 0;
|
||||
unsigned int brUp, brDown;
|
||||
time_t timenow, timestarted;
|
||||
int r;
|
||||
if(UPNP_GetConnectionTypeInfo(urls->controlURL,
|
||||
data->first.servicetype,
|
||||
connectionType) != UPNPCOMMAND_SUCCESS)
|
||||
printf("GetConnectionTypeInfo failed.\n");
|
||||
else
|
||||
printf("Connection Type : %s\n", connectionType);
|
||||
if(UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype,
|
||||
status, &uptime, lastconnerr) != UPNPCOMMAND_SUCCESS)
|
||||
printf("GetStatusInfo failed.\n");
|
||||
else
|
||||
printf("Status : %s, uptime=%us, LastConnectionError : %s\n",
|
||||
status, uptime, lastconnerr);
|
||||
if(uptime > 0) {
|
||||
timenow = time(NULL);
|
||||
timestarted = timenow - uptime;
|
||||
printf(" Time started : %s", ctime(×tarted));
|
||||
}
|
||||
if(UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, data->CIF.servicetype,
|
||||
&brDown, &brUp) != UPNPCOMMAND_SUCCESS) {
|
||||
printf("GetLinkLayerMaxBitRates failed.\n");
|
||||
} else {
|
||||
printf("MaxBitRateDown : %u bps", brDown);
|
||||
if(brDown >= 1000000) {
|
||||
printf(" (%u.%u Mbps)", brDown / 1000000, (brDown / 100000) % 10);
|
||||
} else if(brDown >= 1000) {
|
||||
printf(" (%u Kbps)", brDown / 1000);
|
||||
}
|
||||
printf(" MaxBitRateUp %u bps", brUp);
|
||||
if(brUp >= 1000000) {
|
||||
printf(" (%u.%u Mbps)", brUp / 1000000, (brUp / 100000) % 10);
|
||||
} else if(brUp >= 1000) {
|
||||
printf(" (%u Kbps)", brUp / 1000);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
r = UPNP_GetExternalIPAddress(urls->controlURL,
|
||||
data->first.servicetype,
|
||||
externalIPAddress);
|
||||
if(r != UPNPCOMMAND_SUCCESS) {
|
||||
printf("GetExternalIPAddress failed. (errorcode=%d)\n", r);
|
||||
} else {
|
||||
printf("ExternalIPAddress = %s\n", externalIPAddress);
|
||||
}
|
||||
}
|
||||
|
||||
static void GetConnectionStatus(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data)
|
||||
{
|
||||
unsigned int bytessent, bytesreceived, packetsreceived, packetssent;
|
||||
DisplayInfos(urls, data);
|
||||
bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype);
|
||||
bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype);
|
||||
packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype);
|
||||
packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype);
|
||||
printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived);
|
||||
printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived);
|
||||
}
|
||||
|
||||
static void ListRedirections(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data)
|
||||
{
|
||||
int r;
|
||||
int i = 0;
|
||||
char index[6];
|
||||
char intClient[40];
|
||||
char intPort[6];
|
||||
char extPort[6];
|
||||
char protocol[4];
|
||||
char desc[80];
|
||||
char enabled[6];
|
||||
char rHost[64];
|
||||
char duration[16];
|
||||
/*unsigned int num=0;
|
||||
UPNP_GetPortMappingNumberOfEntries(urls->controlURL, data->servicetype, &num);
|
||||
printf("PortMappingNumberOfEntries : %u\n", num);*/
|
||||
printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n");
|
||||
do {
|
||||
snprintf(index, 6, "%d", i);
|
||||
rHost[0] = '\0'; enabled[0] = '\0';
|
||||
duration[0] = '\0'; desc[0] = '\0';
|
||||
extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0';
|
||||
r = UPNP_GetGenericPortMappingEntry(urls->controlURL,
|
||||
data->first.servicetype,
|
||||
index,
|
||||
extPort, intClient, intPort,
|
||||
protocol, desc, enabled,
|
||||
rHost, duration);
|
||||
if(r==0)
|
||||
/*
|
||||
printf("%02d - %s %s->%s:%s\tenabled=%s leaseDuration=%s\n"
|
||||
" desc='%s' rHost='%s'\n",
|
||||
i, protocol, extPort, intClient, intPort,
|
||||
enabled, duration,
|
||||
desc, rHost);
|
||||
*/
|
||||
printf("%2d %s %5s->%s:%-5s '%s' '%s' %s\n",
|
||||
i, protocol, extPort, intClient, intPort,
|
||||
desc, rHost, duration);
|
||||
else
|
||||
printf("GetGenericPortMappingEntry() returned %d (%s)\n",
|
||||
r, strupnperror(r));
|
||||
i++;
|
||||
} while(r==0);
|
||||
}
|
||||
|
||||
static void NewListRedirections(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data)
|
||||
{
|
||||
int r;
|
||||
int i = 0;
|
||||
struct PortMappingParserData pdata;
|
||||
struct PortMapping * pm;
|
||||
|
||||
memset(&pdata, 0, sizeof(struct PortMappingParserData));
|
||||
r = UPNP_GetListOfPortMappings(urls->controlURL,
|
||||
data->first.servicetype,
|
||||
"0",
|
||||
"65535",
|
||||
"TCP",
|
||||
"1000",
|
||||
&pdata);
|
||||
if(r == UPNPCOMMAND_SUCCESS)
|
||||
{
|
||||
printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n");
|
||||
for(pm = pdata.l_head; pm != NULL; pm = pm->l_next)
|
||||
{
|
||||
printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n",
|
||||
i, pm->protocol, pm->externalPort, pm->internalClient,
|
||||
pm->internalPort,
|
||||
pm->description, pm->remoteHost,
|
||||
(unsigned)pm->leaseTime);
|
||||
i++;
|
||||
}
|
||||
FreePortListing(&pdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("GetListOfPortMappings() returned %d (%s)\n",
|
||||
r, strupnperror(r));
|
||||
}
|
||||
r = UPNP_GetListOfPortMappings(urls->controlURL,
|
||||
data->first.servicetype,
|
||||
"0",
|
||||
"65535",
|
||||
"UDP",
|
||||
"1000",
|
||||
&pdata);
|
||||
if(r == UPNPCOMMAND_SUCCESS)
|
||||
{
|
||||
for(pm = pdata.l_head; pm != NULL; pm = pm->l_next)
|
||||
{
|
||||
printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n",
|
||||
i, pm->protocol, pm->externalPort, pm->internalClient,
|
||||
pm->internalPort,
|
||||
pm->description, pm->remoteHost,
|
||||
(unsigned)pm->leaseTime);
|
||||
i++;
|
||||
}
|
||||
FreePortListing(&pdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("GetListOfPortMappings() returned %d (%s)\n",
|
||||
r, strupnperror(r));
|
||||
}
|
||||
}
|
||||
|
||||
/* Test function
|
||||
* 1 - get connection type
|
||||
* 2 - get extenal ip address
|
||||
* 3 - Add port mapping
|
||||
* 4 - get this port mapping from the IGD */
|
||||
static int SetRedirectAndTest(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
const char * iaddr,
|
||||
const char * iport,
|
||||
const char * eport,
|
||||
const char * proto,
|
||||
const char * leaseDuration,
|
||||
const char * remoteHost,
|
||||
const char * description,
|
||||
int addAny)
|
||||
{
|
||||
char externalIPAddress[40];
|
||||
char intClient[40];
|
||||
char intPort[6];
|
||||
char reservedPort[6];
|
||||
char duration[16];
|
||||
int r;
|
||||
|
||||
if(!iaddr || !iport || !eport || !proto)
|
||||
{
|
||||
fprintf(stderr, "Wrong arguments\n");
|
||||
return -1;
|
||||
}
|
||||
proto = protofix(proto);
|
||||
if(!proto)
|
||||
{
|
||||
fprintf(stderr, "invalid protocol\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = UPNP_GetExternalIPAddress(urls->controlURL,
|
||||
data->first.servicetype,
|
||||
externalIPAddress);
|
||||
if(r!=UPNPCOMMAND_SUCCESS)
|
||||
printf("GetExternalIPAddress failed.\n");
|
||||
else
|
||||
printf("ExternalIPAddress = %s\n", externalIPAddress);
|
||||
|
||||
if (addAny) {
|
||||
r = UPNP_AddAnyPortMapping(urls->controlURL, data->first.servicetype,
|
||||
eport, iport, iaddr, description,
|
||||
proto, remoteHost, leaseDuration, reservedPort);
|
||||
if(r==UPNPCOMMAND_SUCCESS)
|
||||
eport = reservedPort;
|
||||
else
|
||||
printf("AddAnyPortMapping(%s, %s, %s) failed with code %d (%s)\n",
|
||||
eport, iport, iaddr, r, strupnperror(r));
|
||||
} else {
|
||||
r = UPNP_AddPortMapping(urls->controlURL, data->first.servicetype,
|
||||
eport, iport, iaddr, description,
|
||||
proto, remoteHost, leaseDuration);
|
||||
if(r!=UPNPCOMMAND_SUCCESS) {
|
||||
printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
|
||||
eport, iport, iaddr, r, strupnperror(r));
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
r = UPNP_GetSpecificPortMappingEntry(urls->controlURL,
|
||||
data->first.servicetype,
|
||||
eport, proto, remoteHost,
|
||||
intClient, intPort, NULL/*desc*/,
|
||||
NULL/*enabled*/, duration);
|
||||
if(r!=UPNPCOMMAND_SUCCESS) {
|
||||
printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n",
|
||||
r, strupnperror(r));
|
||||
return -2;
|
||||
} else {
|
||||
printf("InternalIP:Port = %s:%s\n", intClient, intPort);
|
||||
printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n",
|
||||
externalIPAddress, eport, proto, intClient, intPort, duration);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
RemoveRedirect(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
const char * eport,
|
||||
const char * proto,
|
||||
const char * remoteHost)
|
||||
{
|
||||
int r;
|
||||
if(!proto || !eport)
|
||||
{
|
||||
fprintf(stderr, "invalid arguments\n");
|
||||
return -1;
|
||||
}
|
||||
proto = protofix(proto);
|
||||
if(!proto)
|
||||
{
|
||||
fprintf(stderr, "protocol invalid\n");
|
||||
return -1;
|
||||
}
|
||||
r = UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, remoteHost);
|
||||
if(r!=UPNPCOMMAND_SUCCESS) {
|
||||
printf("UPNP_DeletePortMapping() failed with code : %d\n", r);
|
||||
return -2;
|
||||
}else {
|
||||
printf("UPNP_DeletePortMapping() returned : %d\n", r);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
RemoveRedirectRange(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
const char * ePortStart, char const * ePortEnd,
|
||||
const char * proto, const char * manage)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!manage)
|
||||
manage = "0";
|
||||
|
||||
if(!proto || !ePortStart || !ePortEnd)
|
||||
{
|
||||
fprintf(stderr, "invalid arguments\n");
|
||||
return -1;
|
||||
}
|
||||
proto = protofix(proto);
|
||||
if(!proto)
|
||||
{
|
||||
fprintf(stderr, "protocol invalid\n");
|
||||
return -1;
|
||||
}
|
||||
r = UPNP_DeletePortMappingRange(urls->controlURL, data->first.servicetype, ePortStart, ePortEnd, proto, manage);
|
||||
if(r!=UPNPCOMMAND_SUCCESS) {
|
||||
printf("UPNP_DeletePortMappingRange() failed with code : %d\n", r);
|
||||
return -2;
|
||||
}else {
|
||||
printf("UPNP_DeletePortMappingRange() returned : %d\n", r);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* IGD:2, functions for service WANIPv6FirewallControl:1 */
|
||||
static void GetFirewallStatus(struct UPNPUrls * urls, struct IGDdatas * data)
|
||||
{
|
||||
unsigned int bytessent, bytesreceived, packetsreceived, packetssent;
|
||||
int firewallEnabled = 0, inboundPinholeAllowed = 0;
|
||||
|
||||
UPNP_GetFirewallStatus(urls->controlURL_6FC, data->IPv6FC.servicetype, &firewallEnabled, &inboundPinholeAllowed);
|
||||
printf("FirewallEnabled: %d & Inbound Pinhole Allowed: %d\n", firewallEnabled, inboundPinholeAllowed);
|
||||
printf("GetFirewallStatus:\n Firewall Enabled: %s\n Inbound Pinhole Allowed: %s\n", (firewallEnabled)? "Yes":"No", (inboundPinholeAllowed)? "Yes":"No");
|
||||
|
||||
bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype);
|
||||
bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype);
|
||||
packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype);
|
||||
packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype);
|
||||
printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived);
|
||||
printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived);
|
||||
}
|
||||
|
||||
/* Test function
|
||||
* 1 - Add pinhole
|
||||
* 2 - Check if pinhole is working from the IGD side */
|
||||
static void SetPinholeAndTest(struct UPNPUrls * urls, struct IGDdatas * data,
|
||||
const char * remoteaddr, const char * eport,
|
||||
const char * intaddr, const char * iport,
|
||||
const char * proto, const char * lease_time)
|
||||
{
|
||||
char uniqueID[8];
|
||||
/*int isWorking = 0;*/
|
||||
int r;
|
||||
char proto_tmp[8];
|
||||
|
||||
if(!intaddr || !remoteaddr || !iport || !eport || !proto || !lease_time)
|
||||
{
|
||||
fprintf(stderr, "Wrong arguments\n");
|
||||
return;
|
||||
}
|
||||
if(atoi(proto) == 0)
|
||||
{
|
||||
const char * protocol;
|
||||
protocol = protofix(proto);
|
||||
if(protocol && (strcmp("TCP", protocol) == 0))
|
||||
{
|
||||
snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_TCP);
|
||||
proto = proto_tmp;
|
||||
}
|
||||
else if(protocol && (strcmp("UDP", protocol) == 0))
|
||||
{
|
||||
snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_UDP);
|
||||
proto = proto_tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "invalid protocol\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
r = UPNP_AddPinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, lease_time, uniqueID);
|
||||
if(r!=UPNPCOMMAND_SUCCESS)
|
||||
printf("AddPinhole([%s]:%s -> [%s]:%s) failed with code %d (%s)\n",
|
||||
remoteaddr, eport, intaddr, iport, r, strupnperror(r));
|
||||
else
|
||||
{
|
||||
printf("AddPinhole: ([%s]:%s -> [%s]:%s) / Pinhole ID = %s\n",
|
||||
remoteaddr, eport, intaddr, iport, uniqueID);
|
||||
/*r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->servicetype_6FC, uniqueID, &isWorking);
|
||||
if(r!=UPNPCOMMAND_SUCCESS)
|
||||
printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r));
|
||||
printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");*/
|
||||
}
|
||||
}
|
||||
|
||||
/* Test function
|
||||
* 1 - Check if pinhole is working from the IGD side
|
||||
* 2 - Update pinhole */
|
||||
static void GetPinholeAndUpdate(struct UPNPUrls * urls, struct IGDdatas * data,
|
||||
const char * uniqueID, const char * lease_time)
|
||||
{
|
||||
int isWorking = 0;
|
||||
int r;
|
||||
|
||||
if(!uniqueID || !lease_time)
|
||||
{
|
||||
fprintf(stderr, "Wrong arguments\n");
|
||||
return;
|
||||
}
|
||||
r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking);
|
||||
printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");
|
||||
if(r!=UPNPCOMMAND_SUCCESS)
|
||||
printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r));
|
||||
if(isWorking || r==709)
|
||||
{
|
||||
r = UPNP_UpdatePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, lease_time);
|
||||
printf("UpdatePinhole: Pinhole ID = %s with Lease Time: %s\n", uniqueID, lease_time);
|
||||
if(r!=UPNPCOMMAND_SUCCESS)
|
||||
printf("UpdatePinhole: ID (%s) failed with code %d (%s)\n", uniqueID, r, strupnperror(r));
|
||||
}
|
||||
}
|
||||
|
||||
/* Test function
|
||||
* Get pinhole timeout
|
||||
*/
|
||||
static void GetPinholeOutboundTimeout(struct UPNPUrls * urls, struct IGDdatas * data,
|
||||
const char * remoteaddr, const char * eport,
|
||||
const char * intaddr, const char * iport,
|
||||
const char * proto)
|
||||
{
|
||||
int timeout = 0;
|
||||
int r;
|
||||
|
||||
if(!intaddr || !remoteaddr || !iport || !eport || !proto)
|
||||
{
|
||||
fprintf(stderr, "Wrong arguments\n");
|
||||
return;
|
||||
}
|
||||
|
||||
r = UPNP_GetOutboundPinholeTimeout(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, &timeout);
|
||||
if(r!=UPNPCOMMAND_SUCCESS)
|
||||
printf("GetOutboundPinholeTimeout([%s]:%s -> [%s]:%s) failed with code %d (%s)\n",
|
||||
intaddr, iport, remoteaddr, eport, r, strupnperror(r));
|
||||
else
|
||||
printf("GetOutboundPinholeTimeout: ([%s]:%s -> [%s]:%s) / Timeout = %d\n", intaddr, iport, remoteaddr, eport, timeout);
|
||||
}
|
||||
|
||||
static void
|
||||
GetPinholePackets(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data, const char * uniqueID)
|
||||
{
|
||||
int r, pinholePackets = 0;
|
||||
if(!uniqueID)
|
||||
{
|
||||
fprintf(stderr, "invalid arguments\n");
|
||||
return;
|
||||
}
|
||||
r = UPNP_GetPinholePackets(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &pinholePackets);
|
||||
if(r!=UPNPCOMMAND_SUCCESS)
|
||||
printf("GetPinholePackets() failed with code %d (%s)\n", r, strupnperror(r));
|
||||
else
|
||||
printf("GetPinholePackets: Pinhole ID = %s / PinholePackets = %d\n", uniqueID, pinholePackets);
|
||||
}
|
||||
|
||||
static void
|
||||
CheckPinhole(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data, const char * uniqueID)
|
||||
{
|
||||
int r, isWorking = 0;
|
||||
if(!uniqueID)
|
||||
{
|
||||
fprintf(stderr, "invalid arguments\n");
|
||||
return;
|
||||
}
|
||||
r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking);
|
||||
if(r!=UPNPCOMMAND_SUCCESS)
|
||||
printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r));
|
||||
else
|
||||
printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");
|
||||
}
|
||||
|
||||
static void
|
||||
RemovePinhole(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data, const char * uniqueID)
|
||||
{
|
||||
int r;
|
||||
if(!uniqueID)
|
||||
{
|
||||
fprintf(stderr, "invalid arguments\n");
|
||||
return;
|
||||
}
|
||||
r = UPNP_DeletePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID);
|
||||
printf("UPNP_DeletePinhole() returned : %d\n", r);
|
||||
}
|
||||
|
||||
|
||||
/* sample upnp client program */
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
char command = 0;
|
||||
char ** commandargv = 0;
|
||||
int commandargc = 0;
|
||||
struct UPNPDev * devlist = 0;
|
||||
char lanaddr[64] = "unset"; /* my ip address on the LAN */
|
||||
int i;
|
||||
const char * rootdescurl = 0;
|
||||
const char * multicastif = 0;
|
||||
const char * minissdpdpath = 0;
|
||||
int localport = UPNP_LOCAL_PORT_ANY;
|
||||
int retcode = 0;
|
||||
int error = 0;
|
||||
int ipv6 = 0;
|
||||
unsigned char ttl = 2; /* defaulting to 2 */
|
||||
const char * description = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
WSADATA wsaData;
|
||||
int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
|
||||
if(nResult != NO_ERROR)
|
||||
{
|
||||
fprintf(stderr, "WSAStartup() failed.\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
printf("upnpc : miniupnpc library test client, version %s.\n", MINIUPNPC_VERSION_STRING);
|
||||
printf(" (c) 2005-2020 Thomas Bernard.\n");
|
||||
printf("Go to http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/\n"
|
||||
"for more information.\n");
|
||||
/* command line processing */
|
||||
for(i=1; i<argc; i++)
|
||||
{
|
||||
if(0 == strcmp(argv[i], "--help") || 0 == strcmp(argv[i], "-h"))
|
||||
{
|
||||
command = 0;
|
||||
break;
|
||||
}
|
||||
if(argv[i][0] == '-')
|
||||
{
|
||||
if(argv[i][1] == 'u')
|
||||
rootdescurl = argv[++i];
|
||||
else if(argv[i][1] == 'm')
|
||||
{
|
||||
multicastif = argv[++i];
|
||||
minissdpdpath = ""; /* Disable usage of minissdpd */
|
||||
}
|
||||
else if(argv[i][1] == 'z')
|
||||
{
|
||||
char junk;
|
||||
if(sscanf(argv[++i], "%d%c", &localport, &junk)!=1 ||
|
||||
localport<0 || localport>65535 ||
|
||||
(localport >1 && localport < 1024))
|
||||
{
|
||||
fprintf(stderr, "Invalid localport '%s'\n", argv[i]);
|
||||
localport = UPNP_LOCAL_PORT_ANY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(argv[i][1] == 'p')
|
||||
minissdpdpath = argv[++i];
|
||||
else if(argv[i][1] == '6')
|
||||
ipv6 = 1;
|
||||
else if(argv[i][1] == 'e')
|
||||
description = argv[++i];
|
||||
else if(argv[i][1] == 't')
|
||||
ttl = (unsigned char)atoi(argv[++i]);
|
||||
else
|
||||
{
|
||||
command = argv[i][1];
|
||||
i++;
|
||||
commandargv = argv + i;
|
||||
commandargc = argc - i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "option '%s' invalid\n", argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if(!command
|
||||
|| (command == 'a' && commandargc<4)
|
||||
|| (command == 'd' && argc<2)
|
||||
|| (command == 'r' && argc<2)
|
||||
|| (command == 'A' && commandargc<6)
|
||||
|| (command == 'U' && commandargc<2)
|
||||
|| (command == 'D' && commandargc<1))
|
||||
{
|
||||
fprintf(stderr, "Usage :\t%s [options] -a ip port external_port protocol [duration] [remote host]\n\t\tAdd port redirection\n", argv[0]);
|
||||
fprintf(stderr, " \t%s [options] -d external_port protocol [remote host]\n\t\tDelete port redirection\n", argv[0]);
|
||||
fprintf(stderr, " \t%s [options] -s\n\t\tGet Connection status\n", argv[0]);
|
||||
fprintf(stderr, " \t%s [options] -l\n\t\tList redirections\n", argv[0]);
|
||||
fprintf(stderr, " \t%s [options] -L\n\t\tList redirections (using GetListOfPortMappings (for IGD:2 only)\n", argv[0]);
|
||||
fprintf(stderr, " \t%s [options] -n ip port external_port protocol [duration] [remote host]\n\t\tAdd (any) port redirection allowing IGD to use alternative external_port (for IGD:2 only)\n", argv[0]);
|
||||
fprintf(stderr, " \t%s [options] -N external_port_start external_port_end protocol [manage]\n\t\tDelete range of port redirections (for IGD:2 only)\n", argv[0]);
|
||||
fprintf(stderr, " \t%s [options] -r port1 [external_port1] protocol1 [port2 [external_port2] protocol2] [...]\n\t\tAdd all redirections to the current host\n", argv[0]);
|
||||
fprintf(stderr, " \t%s [options] -A remote_ip remote_port internal_ip internal_port protocol lease_time\n\t\tAdd Pinhole (for IGD:2 only)\n", argv[0]);
|
||||
fprintf(stderr, " \t%s [options] -U uniqueID new_lease_time\n\t\tUpdate Pinhole (for IGD:2 only)\n", argv[0]);
|
||||
fprintf(stderr, " \t%s [options] -C uniqueID\n\t\tCheck if Pinhole is Working (for IGD:2 only)\n", argv[0]);
|
||||
fprintf(stderr, " \t%s [options] -K uniqueID\n\t\tGet Number of packets going through the rule (for IGD:2 only)\n", argv[0]);
|
||||
fprintf(stderr, " \t%s [options] -D uniqueID\n\t\tDelete Pinhole (for IGD:2 only)\n", argv[0]);
|
||||
fprintf(stderr, " \t%s [options] -S\n\t\tGet Firewall status (for IGD:2 only)\n", argv[0]);
|
||||
fprintf(stderr, " \t%s [options] -G remote_ip remote_port internal_ip internal_port protocol\n\t\tGet Outbound Pinhole Timeout (for IGD:2 only)\n", argv[0]);
|
||||
fprintf(stderr, " \t%s [options] -P\n\t\tGet Presentation url\n", argv[0]);
|
||||
fprintf(stderr, "\nprotocol is UDP or TCP\n");
|
||||
fprintf(stderr, "Options:\n");
|
||||
fprintf(stderr, " -e description : set description for port mapping.\n");
|
||||
fprintf(stderr, " -6 : use ip v6 instead of ip v4.\n");
|
||||
fprintf(stderr, " -u url : bypass discovery process by providing the XML root description url.\n");
|
||||
fprintf(stderr, " -m address/interface : provide ip address (ip v4) or interface name (ip v4 or v6) to use for sending SSDP multicast packets.\n");
|
||||
fprintf(stderr, " -z localport : SSDP packets local (source) port (1024-65535).\n");
|
||||
fprintf(stderr, " -p path : use this path for MiniSSDPd socket.\n");
|
||||
fprintf(stderr, " -t ttl : set multicast TTL. Default value is 2.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( rootdescurl
|
||||
|| (devlist = upnpDiscover(2000, multicastif, minissdpdpath,
|
||||
localport, ipv6, ttl, &error)))
|
||||
{
|
||||
struct UPNPDev * device;
|
||||
struct UPNPUrls urls;
|
||||
struct IGDdatas data;
|
||||
if(devlist)
|
||||
{
|
||||
printf("List of UPNP devices found on the network :\n");
|
||||
for(device = devlist; device; device = device->pNext)
|
||||
{
|
||||
printf(" desc: %s\n st: %s\n\n",
|
||||
device->descURL, device->st);
|
||||
}
|
||||
}
|
||||
else if(!rootdescurl)
|
||||
{
|
||||
printf("upnpDiscover() error code=%d\n", error);
|
||||
}
|
||||
i = 1;
|
||||
if( (rootdescurl && UPNP_GetIGDFromUrl(rootdescurl, &urls, &data, lanaddr, sizeof(lanaddr)))
|
||||
|| (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr))))
|
||||
{
|
||||
switch(i) {
|
||||
case 1:
|
||||
printf("Found valid IGD : %s\n", urls.controlURL);
|
||||
break;
|
||||
case 2:
|
||||
printf("Found a (not connected?) IGD : %s\n", urls.controlURL);
|
||||
printf("Trying to continue anyway\n");
|
||||
break;
|
||||
case 3:
|
||||
printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL);
|
||||
printf("Trying to continue anyway\n");
|
||||
break;
|
||||
default:
|
||||
printf("Found device (igd ?) : %s\n", urls.controlURL);
|
||||
printf("Trying to continue anyway\n");
|
||||
}
|
||||
printf("Local LAN ip address : %s\n", lanaddr);
|
||||
#if 0
|
||||
printf("getting \"%s\"\n", urls.ipcondescURL);
|
||||
descXML = miniwget(urls.ipcondescURL, &descXMLsize);
|
||||
if(descXML)
|
||||
{
|
||||
/*fwrite(descXML, 1, descXMLsize, stdout);*/
|
||||
free(descXML); descXML = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch(command)
|
||||
{
|
||||
case 'l':
|
||||
DisplayInfos(&urls, &data);
|
||||
ListRedirections(&urls, &data);
|
||||
break;
|
||||
case 'L':
|
||||
NewListRedirections(&urls, &data);
|
||||
break;
|
||||
case 'a':
|
||||
if (SetRedirectAndTest(&urls, &data,
|
||||
commandargv[0], commandargv[1],
|
||||
commandargv[2], commandargv[3],
|
||||
(commandargc > 4)&is_int(commandargv[4])?commandargv[4]:"0",
|
||||
(commandargc > 4)&!is_int(commandargv[4])?commandargv[4]:(commandargc > 5)?commandargv[5]:NULL,
|
||||
description, 0) < 0)
|
||||
retcode = 2;
|
||||
break;
|
||||
case 'd':
|
||||
if (RemoveRedirect(&urls, &data, commandargv[0], commandargv[1],
|
||||
commandargc > 2 ? commandargv[2] : NULL) < 0)
|
||||
retcode = 2;
|
||||
break;
|
||||
case 'n': /* aNy */
|
||||
if (SetRedirectAndTest(&urls, &data,
|
||||
commandargv[0], commandargv[1],
|
||||
commandargv[2], commandargv[3],
|
||||
(commandargc > 4)&is_int(commandargv[4])?commandargv[4]:"0",
|
||||
(commandargc > 4)&!is_int(commandargv[4])?commandargv[4]:(commandargc > 5)?commandargv[5]:NULL,
|
||||
description, 1) < 0)
|
||||
retcode = 2;
|
||||
break;
|
||||
case 'N':
|
||||
if (commandargc < 3)
|
||||
fprintf(stderr, "too few arguments\n");
|
||||
|
||||
if (RemoveRedirectRange(&urls, &data, commandargv[0], commandargv[1], commandargv[2],
|
||||
commandargc > 3 ? commandargv[3] : NULL) < 0)
|
||||
retcode = 2;
|
||||
break;
|
||||
case 's':
|
||||
GetConnectionStatus(&urls, &data);
|
||||
break;
|
||||
case 'r':
|
||||
i = 0;
|
||||
while(i<commandargc)
|
||||
{
|
||||
if(!is_int(commandargv[i])) {
|
||||
/* 1st parameter not an integer : error */
|
||||
fprintf(stderr, "command -r : %s is not an port number\n", commandargv[i]);
|
||||
retcode = 1;
|
||||
break;
|
||||
} else if(is_int(commandargv[i+1])){
|
||||
/* 2nd parameter is an integer : <port> <external_port> <protocol> */
|
||||
if (SetRedirectAndTest(&urls, &data,
|
||||
lanaddr, commandargv[i],
|
||||
commandargv[i+1], commandargv[i+2], "0", NULL,
|
||||
description, 0) < 0)
|
||||
retcode = 2;
|
||||
i+=3; /* 3 parameters parsed */
|
||||
} else {
|
||||
/* 2nd parameter not an integer : <port> <protocol> */
|
||||
if (SetRedirectAndTest(&urls, &data,
|
||||
lanaddr, commandargv[i],
|
||||
commandargv[i], commandargv[i+1], "0", NULL,
|
||||
description, 0) < 0)
|
||||
retcode = 2;
|
||||
i+=2; /* 2 parameters parsed */
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'A':
|
||||
SetPinholeAndTest(&urls, &data,
|
||||
commandargv[0], commandargv[1],
|
||||
commandargv[2], commandargv[3],
|
||||
commandargv[4], commandargv[5]);
|
||||
break;
|
||||
case 'U':
|
||||
GetPinholeAndUpdate(&urls, &data,
|
||||
commandargv[0], commandargv[1]);
|
||||
break;
|
||||
case 'C':
|
||||
for(i=0; i<commandargc; i++)
|
||||
{
|
||||
CheckPinhole(&urls, &data, commandargv[i]);
|
||||
}
|
||||
break;
|
||||
case 'K':
|
||||
for(i=0; i<commandargc; i++)
|
||||
{
|
||||
GetPinholePackets(&urls, &data, commandargv[i]);
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
for(i=0; i<commandargc; i++)
|
||||
{
|
||||
RemovePinhole(&urls, &data, commandargv[i]);
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
GetFirewallStatus(&urls, &data);
|
||||
break;
|
||||
case 'G':
|
||||
GetPinholeOutboundTimeout(&urls, &data,
|
||||
commandargv[0], commandargv[1],
|
||||
commandargv[2], commandargv[3],
|
||||
commandargv[4]);
|
||||
break;
|
||||
case 'P':
|
||||
printf("Presentation URL found:\n");
|
||||
printf(" %s\n", data.presentationurl);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown switch -%c\n", command);
|
||||
retcode = 1;
|
||||
}
|
||||
|
||||
FreeUPNPUrls(&urls);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n");
|
||||
retcode = 1;
|
||||
}
|
||||
freeUPNPDevlist(devlist); devlist = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "No IGD UPnP Device found on the network !\n");
|
||||
retcode = 1;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
nResult = WSACleanup();
|
||||
if(nResult != NO_ERROR) {
|
||||
fprintf(stderr, "WSACleanup() failed.\n");
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
return retcode;
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
/* $Id: upnpdev.h,v 1.1 2015/08/28 12:14:19 nanard Exp $ */
|
||||
/* $Id: upnpdev.h,v 1.3 2020/05/29 15:57:42 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Web : http://miniupnp.free.fr/
|
||||
* Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||
* Author : Thomas BERNARD
|
||||
* copyright (c) 2005-2018 Thomas Bernard
|
||||
* copyright (c) 2005-2020 Thomas Bernard
|
||||
* This software is subjet to the conditions detailed in the
|
||||
* provided LICENSE file. */
|
||||
#ifndef UPNPDEV_H_INCLUDED
|
||||
|
@ -20,7 +20,15 @@ struct UPNPDev {
|
|||
char * st;
|
||||
char * usn;
|
||||
unsigned int scope_id;
|
||||
char buffer[3];
|
||||
#if defined(__STDC_VERSION) && __STDC_VERSION__ >= 199901L
|
||||
/* C99 flexible array member */
|
||||
char buffer[];
|
||||
#elif defined(__GNUC__)
|
||||
char buffer[0];
|
||||
#else
|
||||
/* Fallback to a hack */
|
||||
char buffer[1];
|
||||
#endif
|
||||
};
|
||||
|
||||
/* freeUPNPDevlist()
|
||||
|
|
|
@ -1,112 +0,0 @@
|
|||
/* $Id: upnperrors.c,v 1.10 2019/08/24 08:49:53 nanard Exp $ */
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* Project : miniupnp
|
||||
* Author : Thomas BERNARD
|
||||
* copyright (c) 2007-2019 Thomas Bernard
|
||||
* All Right reserved.
|
||||
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||
* This software is subjet to the conditions detailed in the
|
||||
* provided LICENCE file. */
|
||||
#include <string.h>
|
||||
#include "upnperrors.h"
|
||||
#include "upnpcommands.h"
|
||||
#include "miniupnpc.h"
|
||||
|
||||
const char * strupnperror(int err)
|
||||
{
|
||||
const char * s = NULL;
|
||||
switch(err) {
|
||||
case UPNPCOMMAND_SUCCESS:
|
||||
s = "Success";
|
||||
break;
|
||||
case UPNPCOMMAND_UNKNOWN_ERROR:
|
||||
s = "Miniupnpc Unknown Error";
|
||||
break;
|
||||
case UPNPCOMMAND_INVALID_ARGS:
|
||||
s = "Miniupnpc Invalid Arguments";
|
||||
break;
|
||||
case UPNPCOMMAND_INVALID_RESPONSE:
|
||||
s = "Miniupnpc Invalid response";
|
||||
break;
|
||||
case UPNPCOMMAND_HTTP_ERROR:
|
||||
s = "Miniupnpc HTTP error";
|
||||
break;
|
||||
case UPNPDISCOVER_SOCKET_ERROR:
|
||||
s = "Miniupnpc Socket error";
|
||||
break;
|
||||
case UPNPDISCOVER_MEMORY_ERROR:
|
||||
case UPNPCOMMAND_MEM_ALLOC_ERROR:
|
||||
s = "Miniupnpc Memory allocation error";
|
||||
break;
|
||||
case 401:
|
||||
s = "Invalid Action";
|
||||
break;
|
||||
case 402:
|
||||
s = "Invalid Args";
|
||||
break;
|
||||
case 501:
|
||||
s = "Action Failed";
|
||||
break;
|
||||
case 606:
|
||||
s = "Action not authorized";
|
||||
break;
|
||||
case 701:
|
||||
s = "PinholeSpaceExhausted";
|
||||
break;
|
||||
case 702:
|
||||
s = "FirewallDisabled";
|
||||
break;
|
||||
case 703:
|
||||
s = "InboundPinholeNotAllowed";
|
||||
break;
|
||||
case 704:
|
||||
s = "NoSuchEntry";
|
||||
break;
|
||||
case 705:
|
||||
s = "ProtocolNotSupported";
|
||||
break;
|
||||
case 706:
|
||||
s = "InternalPortWildcardingNotAllowed";
|
||||
break;
|
||||
case 707:
|
||||
s = "ProtocolWildcardingNotAllowed";
|
||||
break;
|
||||
case 708:
|
||||
s = "InvalidLayer2Address";
|
||||
break;
|
||||
case 709:
|
||||
s = "NoPacketSent";
|
||||
break;
|
||||
case 713:
|
||||
s = "SpecifiedArrayIndexInvalid";
|
||||
break;
|
||||
case 714:
|
||||
s = "NoSuchEntryInArray";
|
||||
break;
|
||||
case 715:
|
||||
s = "WildCardNotPermittedInSrcIP";
|
||||
break;
|
||||
case 716:
|
||||
s = "WildCardNotPermittedInExtPort";
|
||||
break;
|
||||
case 718:
|
||||
s = "ConflictInMappingEntry";
|
||||
break;
|
||||
case 724:
|
||||
s = "SamePortValuesRequired";
|
||||
break;
|
||||
case 725:
|
||||
s = "OnlyPermanentLeasesSupported";
|
||||
break;
|
||||
case 726:
|
||||
s = "RemoteHostOnlySupportsWildcard";
|
||||
break;
|
||||
case 727:
|
||||
s = "ExternalPortOnlySupportsWildcard";
|
||||
break;
|
||||
default:
|
||||
s = "UnknownError";
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
/* $Id: upnperrors.h,v 1.2 2008/07/02 23:31:15 nanard Exp $ */
|
||||
/* (c) 2007-2015 Thomas Bernard
|
||||
* All rights reserved.
|
||||
* MiniUPnP Project.
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* This software is subjet to the conditions detailed in the
|
||||
* provided LICENCE file. */
|
||||
#ifndef UPNPERRORS_H_INCLUDED
|
||||
#define UPNPERRORS_H_INCLUDED
|
||||
|
||||
#include "miniupnpc_declspec.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* strupnperror()
|
||||
* Return a string description of the UPnP error code
|
||||
* or NULL for undefinded errors */
|
||||
MINIUPNP_LIBSPEC const char * strupnperror(int err);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,71 @@
|
|||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||
* (c) 2020 Pali Rohár
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
|
||||
#ifndef WIN32_SNPRINTF_H
|
||||
#define WIN32_SNPRINTF_H
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* snprintf is supported by:
|
||||
* - Visual Studio 2015 or new
|
||||
* - mingw32 with iso c ext
|
||||
* - mingw-w64 with ansi stdio
|
||||
* - mingw-w64 6.0.0 or new with ucrt
|
||||
* - mingw-w64 8.0.0 or new with iso c ext
|
||||
*/
|
||||
#if ( \
|
||||
(defined(_MSC_VER) && _MSC_VER < 1900) /* Visual Studio older than 2015 */ || \
|
||||
(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) && defined(__NO_ISOCEXT)) /* mingw32 without iso c ext */ || \
|
||||
(defined(__MINGW64_VERSION_MAJOR) && /* mingw-w64 not ... */ !( \
|
||||
(defined (__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO != 0)) /* ... with ansi stdio */ || \
|
||||
(__MINGW64_VERSION_MAJOR >= 6 && defined(_UCRT)) /* ... at least 6.0.0 with ucrt */ || \
|
||||
(__MINGW64_VERSION_MAJOR >= 8 && !defined(__NO_ISOCEXT)) /* ... at least 8.0.0 with iso c ext */ || \
|
||||
0) || \
|
||||
0)
|
||||
|
||||
/* _scprintf is supported by:
|
||||
* - Visual Studio 2002 or new
|
||||
* - msvcr70.dll or new
|
||||
* - msvcrt.dll on Windows XP or new
|
||||
*/
|
||||
#if ( \
|
||||
(defined(_MSC_VER) && _MSC_VER < 1300) /* Visual Studio older than 2002 */ || \
|
||||
(defined(__MSVCRT_VERSION__) && __MSVCRT_VERSION__ < 0x700) /* msvcrt older than 7.0 */ || \
|
||||
0)
|
||||
#define CHECK_SCPRINTF 0
|
||||
#define IF_SCPRINTF(expr) 0
|
||||
#define ELSE_SCPRINTF(expr) expr
|
||||
#else
|
||||
#define CHECK_SCPRINTF 1
|
||||
#define IF_SCPRINTF(expr) expr
|
||||
#define ELSE_SCPRINTF(expr) 0
|
||||
#endif
|
||||
|
||||
/* Emulation of snprintf for win32 */
|
||||
#define snprintf(buf, size, fmt, ...) ( \
|
||||
(((size) != 0 && (buf) != NULL) ? ( /* _snprintf does not work with NULL buffer */ \
|
||||
_snprintf((buf), (size), (fmt), __VA_ARGS__), /* _snprintf returns -1 on overflow, so ignore its value */ \
|
||||
(((char *)buf)[(size_t)(size)-1] = 0), /* _snprintf does not fill nul byte on overflow */ \
|
||||
0) : 0), \
|
||||
(CHECK_SCPRINTF ? IF_SCPRINTF( \
|
||||
_scprintf((fmt), __VA_ARGS__) /* calculate return value for snprintf via _scprintf */ \
|
||||
) : ELSE_SCPRINTF( \
|
||||
((size) != 0 && (buf) != NULL) ? \
|
||||
strlen((buf)) /* return just length of buffer */ \
|
||||
: \
|
||||
1 /* no buffer, impossible to calculate, return just non-zero number */ \
|
||||
) \
|
||||
) \
|
||||
)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#endif /* WIN32_SNPRINTF_H */
|
Loading…
Reference in New Issue