From dd6a05adab60f745e366ce2dcb82531857b193c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Thu, 5 Jun 2025 17:58:09 +0200 Subject: [PATCH] miniupnpc: Update to 2.3.3 --- COPYRIGHT.txt | 2 +- thirdparty/README.md | 2 +- thirdparty/miniupnpc/LICENSE | 2 +- .../include/miniupnpc/igd_desc_parse.h | 50 +- .../miniupnpc/include/miniupnpc/miniupnpc.h | 259 ++++++-- .../include/miniupnpc/miniupnpc_declspec.h | 3 +- .../include/miniupnpc/miniupnpctypes.h | 24 +- .../miniupnpc/include/miniupnpc/miniwget.h | 39 +- .../include/miniupnpc/portlistingparse.h | 74 ++- .../include/miniupnpc/upnpcommands.h | 585 +++++++++++++----- .../miniupnpc/include/miniupnpc/upnpdev.h | 22 +- .../include/miniupnpc/upnpreplyparse.h | 59 +- thirdparty/miniupnpc/src/addr_is_reserved.c | 10 +- thirdparty/miniupnpc/src/connecthostport.c | 26 +- thirdparty/miniupnpc/src/minisoap.c | 6 +- thirdparty/miniupnpc/src/minissdpc.c | 32 +- thirdparty/miniupnpc/src/miniupnpc.c | 29 +- thirdparty/miniupnpc/src/miniupnpcstrings.h | 2 +- thirdparty/miniupnpc/src/miniwget.c | 5 +- thirdparty/miniupnpc/src/miniwget_private.h | 41 +- thirdparty/miniupnpc/src/portlistingparse.c | 8 +- thirdparty/miniupnpc/src/receivedata.c | 5 +- thirdparty/miniupnpc/src/upnpcommands.c | 553 ++++++++--------- thirdparty/miniupnpc/src/upnpreplyparse.c | 56 +- 24 files changed, 1240 insertions(+), 654 deletions(-) diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index c7d7140ce00..2f5d0e8ba97 100644 --- a/COPYRIGHT.txt +++ b/COPYRIGHT.txt @@ -416,7 +416,7 @@ License: CC0-1.0 Files: thirdparty/miniupnpc/* Comment: MiniUPnP Project -Copyright: 2005-2024, Thomas Bernard +Copyright: 2005-2025, Thomas Bernard License: BSD-3-clause Files: thirdparty/minizip/* diff --git a/thirdparty/README.md b/thirdparty/README.md index f5730f30bde..64fe5b6586d 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -712,7 +712,7 @@ Patches: ## miniupnpc - Upstream: https://github.com/miniupnp/miniupnp -- Version: 2.2.8 (b55145ec095652289a59c33603f3abafee898273, 2024) +- Version: 2.3.3 (bf4215a7574f88aa55859db9db00e3ae58cf42d6, 2025) - License: BSD-3-Clause Files extracted from upstream source: diff --git a/thirdparty/miniupnpc/LICENSE b/thirdparty/miniupnpc/LICENSE index 2755844d49c..3bdbedc6e45 100644 --- a/thirdparty/miniupnpc/LICENSE +++ b/thirdparty/miniupnpc/LICENSE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2005-2024, Thomas BERNARD +Copyright (c) 2005-2025, Thomas BERNARD All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/thirdparty/miniupnpc/include/miniupnpc/igd_desc_parse.h b/thirdparty/miniupnpc/include/miniupnpc/igd_desc_parse.h index 0de546b6979..52a4ab3e31a 100644 --- a/thirdparty/miniupnpc/include/miniupnpc/igd_desc_parse.h +++ b/thirdparty/miniupnpc/include/miniupnpc/igd_desc_parse.h @@ -1,46 +1,72 @@ -/* $Id: igd_desc_parse.h,v 1.12 2014/11/17 17:19:13 nanard Exp $ */ +/* $Id: igd_desc_parse.h,v 1.14 2025/02/08 23:15:16 nanard Exp $ */ /* Project : miniupnp - * http://miniupnp.free.fr/ + * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ * Author : Thomas Bernard - * Copyright (c) 2005-2014 Thomas Bernard + * Copyright (c) 2005-2025 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * */ #ifndef IGD_DESC_PARSE_H_INCLUDED #define IGD_DESC_PARSE_H_INCLUDED -/* Structure to store the result of the parsing of UPnP - * descriptions of Internet Gateway Devices */ +/*! \file igd_desc_parse.h + * \brief API to parse UPNP device description XML + * \todo should not be exposed in the public API + */ + +/*! \brief maximum lenght of URLs */ #define MINIUPNPC_URL_MAXSIZE (128) + +/*! \brief Structure to store the result of the parsing of UPnP + * descriptions of Internet Gateway Devices services */ struct IGDdatas_service { + /*! \brief controlURL for the service */ char controlurl[MINIUPNPC_URL_MAXSIZE]; + /*! \brief eventSubURL for the service */ char eventsuburl[MINIUPNPC_URL_MAXSIZE]; + /*! \brief SCPDURL for the service */ char scpdurl[MINIUPNPC_URL_MAXSIZE]; + /*! \brief serviceType */ char servicetype[MINIUPNPC_URL_MAXSIZE]; /*char devicetype[MINIUPNPC_URL_MAXSIZE];*/ }; +/*! \brief Structure to store the result of the parsing of UPnP + * descriptions of Internet Gateway Devices */ struct IGDdatas { + /*! \brief current element name */ char cureltname[MINIUPNPC_URL_MAXSIZE]; + /*! \brief URLBase */ char urlbase[MINIUPNPC_URL_MAXSIZE]; + /*! \brief presentationURL */ char presentationurl[MINIUPNPC_URL_MAXSIZE]; + /*! \brief depth into the XML tree */ int level; - /*int state;*/ - /* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */ + /*! \brief "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */ struct IGDdatas_service CIF; - /* "urn:schemas-upnp-org:service:WANIPConnection:1" - * "urn:schemas-upnp-org:service:WANPPPConnection:1" */ + /*! \brief first of "urn:schemas-upnp-org:service:WANIPConnection:1" + * or "urn:schemas-upnp-org:service:WANPPPConnection:1" */ struct IGDdatas_service first; - /* if both WANIPConnection and WANPPPConnection are present */ + /*! \brief second of "urn:schemas-upnp-org:service:WANIPConnection:1" + * or "urn:schemas-upnp-org:service:WANPPPConnection:1" */ struct IGDdatas_service second; - /* "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1" */ + /*! \brief "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1" */ struct IGDdatas_service IPv6FC; - /* tmp */ + /*! \brief currently parsed service */ struct IGDdatas_service tmp; }; +/*! + * \brief XML start element handler + */ void IGDstartelt(void *, const char *, int); +/*! + * \brief XML end element handler + */ void IGDendelt(void *, const char *, int); +/*! + * \brief XML characted data handler + */ void IGDdata(void *, const char *, int); #ifdef DEBUG void printIGD(struct IGDdatas *); diff --git a/thirdparty/miniupnpc/include/miniupnpc/miniupnpc.h b/thirdparty/miniupnpc/include/miniupnpc/miniupnpc.h index fd951a0836b..1022d84de32 100644 --- a/thirdparty/miniupnpc/include/miniupnpc/miniupnpc.h +++ b/thirdparty/miniupnpc/include/miniupnpc/miniupnpc.h @@ -1,32 +1,54 @@ -/* $Id: miniupnpc.h,v 1.66 2024/06/08 22:13:14 nanard Exp $ */ +/* $Id: miniupnpc.h,v 1.80 2025/05/26 22:56:40 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * Project: miniupnp * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ * Author: Thomas Bernard - * Copyright (c) 2005-2024 Thomas Bernard + * Copyright (c) 2005-2025 Thomas Bernard * This software is subjects to the conditions detailed * in the LICENCE file provided within this distribution */ #ifndef MINIUPNPC_H_INCLUDED #define MINIUPNPC_H_INCLUDED +/*! \file miniupnpc.h + * \brief Main C API for MiniUPnPc + * + * Contains functions to discover devices and check for device validity + * or connectivity. + * + * \mainpage MiniUPnPc API documentation + * MiniUPnPc (MiniUPnP client) is a library implementing a UPnP + * Internet Gateway Device (IGD) control point. + * + * It should be used by applications that need to listen to incoming + * traffic from the internet which are running on a LAN where a + * UPnP IGD is running on the router (or gateway). + * + * See more documentation on the website http://miniupnp.free.fr + * or https://miniupnp.tuxfamily.org/ or GitHub : + * https://github.com/miniupnp/miniupnp/tree/master/miniupnpc + */ #include "miniupnpc_declspec.h" #include "igd_desc_parse.h" #include "upnpdev.h" /* error codes : */ +/*! \brief value for success */ #define UPNPDISCOVER_SUCCESS (0) +/*! \brief value for unknown error */ #define UPNPDISCOVER_UNKNOWN_ERROR (-1) +/*! \brief value for a socket error */ #define UPNPDISCOVER_SOCKET_ERROR (-101) +/*! \brief value for a memory allocation error */ #define UPNPDISCOVER_MEMORY_ERROR (-102) -/* versions : */ -#define MINIUPNPC_VERSION "2.2.8" -#define MINIUPNPC_API_VERSION 18 +/*! \brief software version */ +#define MINIUPNPC_VERSION "2.3.3" +/*! \brief C API version */ +#define MINIUPNPC_API_VERSION 21 -/* Source port: - Using "1" as an alias for 1900 for backwards compatibility - (presuming one would have used that for the "sameport" parameter) */ +/*! \brief any (ie system chosen) port */ #define UPNP_LOCAL_PORT_ANY 0 +/*! \brief Use as an alias for 1900 for backwards compatibility */ #define UPNP_LOCAL_PORT_SAME 1 #ifdef __cplusplus @@ -34,49 +56,126 @@ extern "C" { #endif /* Structures definitions : */ -struct UPNParg { const char * elt; const char * val; }; +/*! + * \brief UPnP method argument + */ +struct UPNParg { + const char * elt; /*!< \brief UPnP argument name */ + const char * val; /*!< \brief UPnP argument value */ +}; + +/*! + * \brief execute a UPnP method (SOAP action) + * + * \todo error reporting should be improved + * + * \param[in] url Control URL for the service + * \param[in] service service to use + * \param[in] action action to call + * \param[in] args action arguments + * \param[out] bufsize the size of the returned buffer + * \return NULL in case of error or the raw XML response + */ char * -simpleUPnPcommand(int, const char *, const char *, - const char *, struct UPNParg *, - int *); +simpleUPnPcommand(const char * url, const char * service, + const char * action, const struct UPNParg * args, + int * bufsize); -/* upnpDiscover() - * discover UPnP devices on the network. +/*! + * \brief Discover UPnP IGD on the network. + * * The discovered devices are returned as a chained list. * It is up to the caller to free the list with freeUPNPDevlist(). - * delay (in millisecond) is the maximum time for waiting any device - * response. * If available, device list will be obtained from MiniSSDPd. - * Default path for minissdpd socket will be used if minissdpdsock argument - * is NULL. - * If multicastif is not NULL, it will be used instead of the default - * multicast interface for sending SSDP discover packets. - * 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. - * "searchalltypes" parameter is useful when searching several types, - * if 0, the discovery will stop with the first type returning results. - * TTL should default to 2. */ + * + * \param[in] delay (in millisecond) maximum time for waiting any device + * response + * \param[in] multicastif If not NULL, used instead of the default + * multicast interface for sending SSDP discover packets + * \param[in] minissdpdsock Path to minissdpd socket, default is used if + * NULL + * \param[in] localport Source port to send SSDP packets. + * #UPNP_LOCAL_PORT_SAME for 1900 (same as destination port) + * #UPNP_LOCAL_PORT_ANY to let system assign a source port + * \param[in] ipv6 0 for IPv4, 1 of IPv6 + * \param[in] ttl should default to 2 as advised by UDA 1.1 + * \param[out] error error code when NULL is returned + * \return NULL or a linked list + */ MINIUPNP_LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif, const char * minissdpdsock, int localport, int ipv6, unsigned char ttl, int * error); +/*! + * \brief Discover all UPnP devices on the network + * + * search for "ssdp:all" + * \param[in] delay (in millisecond) maximum time for waiting any device + * response + * \param[in] multicastif If not NULL, used instead of the default + * multicast interface for sending SSDP discover packets + * \param[in] minissdpdsock Path to minissdpd socket, default is used if + * NULL + * \param[in] localport Source port to send SSDP packets. + * #UPNP_LOCAL_PORT_SAME for 1900 (same as destination port) + * #UPNP_LOCAL_PORT_ANY to let system assign a source port + * \param[in] ipv6 0 for IPv4, 1 of IPv6 + * \param[in] ttl should default to 2 as advised by UDA 1.1 + * \param[out] error error code when NULL is returned + * \return NULL or a linked list + */ MINIUPNP_LIBSPEC struct UPNPDev * upnpDiscoverAll(int delay, const char * multicastif, const char * minissdpdsock, int localport, int ipv6, unsigned char ttl, int * error); +/*! + * \brief Discover one type of UPnP devices + * + * \param[in] device device type to search + * \param[in] delay (in millisecond) maximum time for waiting any device + * response + * \param[in] multicastif If not NULL, used instead of the default + * multicast interface for sending SSDP discover packets + * \param[in] minissdpdsock Path to minissdpd socket, default is used if + * NULL + * \param[in] localport Source port to send SSDP packets. + * #UPNP_LOCAL_PORT_SAME for 1900 (same as destination port) + * #UPNP_LOCAL_PORT_ANY to let system assign a source port + * \param[in] ipv6 0 for IPv4, 1 of IPv6 + * \param[in] ttl should default to 2 as advised by UDA 1.1 + * \param[out] error error code when NULL is returned + * \return NULL or a linked list + */ MINIUPNP_LIBSPEC struct UPNPDev * upnpDiscoverDevice(const char * device, int delay, const char * multicastif, const char * minissdpdsock, int localport, int ipv6, unsigned char ttl, int * error); +/*! + * \brief Discover one or several type of UPnP devices + * + * \param[in] deviceTypes array of device types to search (ending with NULL) + * \param[in] delay (in millisecond) maximum time for waiting any device + * response + * \param[in] multicastif If not NULL, used instead of the default + * multicast interface for sending SSDP discover packets + * \param[in] minissdpdsock Path to minissdpd socket, default is used if + * NULL + * \param[in] localport Source port to send SSDP packets. + * #UPNP_LOCAL_PORT_SAME for 1900 (same as destination port) + * #UPNP_LOCAL_PORT_ANY to let system assign a source port + * \param[in] ipv6 0 for IPv4, 1 of IPv6 + * \param[in] ttl should default to 2 as advised by UDA 1.1 + * \param[out] error error code when NULL is returned + * \param[in] searchalltypes 0 to stop with the first type returning results + * \return NULL or a linked list + */ MINIUPNP_LIBSPEC struct UPNPDev * upnpDiscoverDevices(const char * const deviceTypes[], int delay, const char * multicastif, @@ -85,38 +184,60 @@ upnpDiscoverDevices(const char * const deviceTypes[], int * error, int searchalltypes); -/* parserootdesc() : - * parse root XML description of a UPnP device and fill the IGDdatas - * structure. */ -MINIUPNP_LIBSPEC void parserootdesc(const char *, int, struct IGDdatas *); +/*! + * \brief parse root XML description of a UPnP device + * + * fill the IGDdatas structure. + * \param[in] buffer character buffer containing the XML description + * \param[in] bufsize size in bytes of the buffer + * \param[out] data IGDdatas structure to fill + */ +MINIUPNP_LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data); -/* structure used to get fast access to urls - * controlURL: controlURL of the WANIPConnection - * ipcondescURL: url of the description of the WANIPConnection - * controlURL_CIF: controlURL of the WANCommonInterfaceConfig - * controlURL_6FC: controlURL of the WANIPv6FirewallControl +/*! + * \brief structure used to get fast access to urls */ struct UPNPUrls { + /*! \brief controlURL of the WANIPConnection */ char * controlURL; + /*! \brief url of the description of the WANIPConnection */ char * ipcondescURL; + /*! \brief controlURL of the WANCommonInterfaceConfig */ char * controlURL_CIF; + /*! \brief controlURL of the WANIPv6FirewallControl */ char * controlURL_6FC; + /*! \brief url of the root description */ char * rootdescURL; }; -/* UPNP_GetValidIGD() : - * return values : - * 0 = NO IGD found - * 1 = A valid connected IGD has been found - * 2 = A valid connected IGD has been found but its - * IP address is reserved (non routable) - * 3 = A valid IGD has been found but it reported as - * not connected - * 4 = an UPnP device has been found but was not recognized as an IGD +/*! \brief NO IGD found */ +#define UPNP_NO_IGD (0) +/*! \brief valid and connected IGD */ +#define UPNP_CONNECTED_IGD (1) +/*! \brief valid and connected IGD but with a reserved address + * (non routable) */ +#define UPNP_PRIVATEIP_IGD (2) +/*! \brief valid but not connected IGD */ +#define UPNP_DISCONNECTED_IGD (3) +/*! \brief UPnP device not recognized as an IGD */ +#define UPNP_UNKNOWN_DEVICE (4) + +/*! + * \brief look for a valid and possibly connected IGD in the list * * In any non zero return case, the urls and data structures * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to * free allocated memory. + * \param[in] devlist A device list obtained with upnpDiscover() / + * upnpDiscoverAll() / upnpDiscoverDevice() / upnpDiscoverDevices() + * \param[out] urls Urls for the IGD found + * \param[out] data datas for the IGD found + * \param[out] lanaddr buffer to copy the local address of the host to reach the IGD + * \param[in] lanaddrlen size of the lanaddr buffer + * \param[out] wanaddr buffer to copy the public address of the IGD + * \param[in] wanaddrlen size of the wanaddr buffer + * \return #UPNP_NO_IGD / #UPNP_CONNECTED_IGD / #UPNP_PRIVATEIP_IGD / + * #UPNP_DISCONNECTED_IGD / #UPNP_UNKNOWN_DEVICE */ MINIUPNP_LIBSPEC int UPNP_GetValidIGD(struct UPNPDev * devlist, @@ -125,27 +246,55 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, char * lanaddr, int lanaddrlen, char * wanaddr, int wanaddrlen); -/* UPNP_GetIGDFromUrl() +/*! + * \brief Get IGD URLs and data for URL + * * Used when skipping the discovery process. - * When succeding, urls, data, and lanaddr arguments are set. - * return value : - * 0 - Not ok - * 1 - OK */ + * \param[in] rootdescurl Root description URL of the device + * \param[out] urls Urls for the IGD found + * \param[out] data datas for the IGD found + * \param[out] lanaddr buffer to copy the local address of the host to reach the IGD + * \param[in] lanaddrlen size of the lanaddr buffer + * \return 0 Not ok / 1 OK + */ MINIUPNP_LIBSPEC int UPNP_GetIGDFromUrl(const char * rootdescurl, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen); +/*! + * \brief Prepare the URLs for usage + * + * build absolute URLs from the root description + * \param[out] urls URL structure to initialize + * \param[in] data datas for the IGD + * \param[in] descURL root description URL for the IGD + * \param[in] scope_id if not 0, add the scope to the linklocal IPv6 + * addresses in URLs + */ MINIUPNP_LIBSPEC void -GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, - const char *, unsigned int); +GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data, + const char * descURL, unsigned int scope_id); +/*! + * \brief free the members of a UPNPUrls struct + * + * All URLs buffers are freed and zeroed + * \param[out] urls URL structure to free + */ MINIUPNP_LIBSPEC void -FreeUPNPUrls(struct UPNPUrls *); +FreeUPNPUrls(struct UPNPUrls * urls); -/* return 0 or 1 */ -MINIUPNP_LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *); +/*! + * \brief check the current connection status of an IGD + * + * it uses UPNP_GetStatusInfo() + * \param[in] urls IGD URLs + * \param[in] data IGD data + * \return 1 Connected / 0 Disconnected + */ +MINIUPNP_LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data); #ifdef __cplusplus diff --git a/thirdparty/miniupnpc/include/miniupnpc/miniupnpc_declspec.h b/thirdparty/miniupnpc/include/miniupnpc/miniupnpc_declspec.h index 40adb922ec3..e0e9d2b3f7d 100644 --- a/thirdparty/miniupnpc/include/miniupnpc/miniupnpc_declspec.h +++ b/thirdparty/miniupnpc/include/miniupnpc/miniupnpc_declspec.h @@ -1,6 +1,8 @@ #ifndef MINIUPNPC_DECLSPEC_H_INCLUDED #define MINIUPNPC_DECLSPEC_H_INCLUDED +/*! \file miniupnpc_declspec.h + * \brief define #MINIUPNP_LIBSPEC for dll exports and imports */ #if defined(_WIN32) && !defined(MINIUPNP_STATICLIB) /* for windows dll */ #ifdef MINIUPNP_EXPORTS @@ -18,4 +20,3 @@ #endif #endif /* MINIUPNPC_DECLSPEC_H_INCLUDED */ - diff --git a/thirdparty/miniupnpc/include/miniupnpc/miniupnpctypes.h b/thirdparty/miniupnpc/include/miniupnpc/miniupnpctypes.h index 26ed4f00592..c832e017201 100644 --- a/thirdparty/miniupnpc/include/miniupnpc/miniupnpctypes.h +++ b/thirdparty/miniupnpc/include/miniupnpc/miniupnpctypes.h @@ -1,21 +1,27 @@ -/* $Id: miniupnpctypes.h,v 1.1 2011/02/15 11:10:40 nanard Exp $ */ -/* Miniupnp project : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org - * Author : Thomas Bernard - * Copyright (c) 2021 Thomas Bernard +/* $Id: miniupnpctypes.h,v 1.4 2025/02/08 23:15:16 nanard Exp $ */ +/* Project: miniupnp + * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org + * Author: Thomas Bernard + * Copyright (c) 2021-2025 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided within this distribution */ #ifndef MINIUPNPCTYPES_H_INCLUDED #define MINIUPNPCTYPES_H_INCLUDED -/* Use unsigned long long when available : - * strtoull is C99 */ +/*! \file miniupnpctypes.h + * \brief type definitions + * + * Use unsigned long long when available : + * strtoull is C99 + * + * \def UNSIGNED_INTEGER + * \brief `unsigned long long` or `unsigned int` + * \todo int can be 16 bits, so it should be `unsigned long` + */ #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define UNSIGNED_INTEGER unsigned long long -#define STRTOUI strtoull #else #define UNSIGNED_INTEGER unsigned int -#define STRTOUI strtoul #endif #endif - diff --git a/thirdparty/miniupnpc/include/miniupnpc/miniwget.h b/thirdparty/miniupnpc/include/miniupnpc/miniwget.h index f5572c25449..ed5364c2f14 100644 --- a/thirdparty/miniupnpc/include/miniupnpc/miniwget.h +++ b/thirdparty/miniupnpc/include/miniupnpc/miniwget.h @@ -1,24 +1,51 @@ -/* $Id: miniwget.h,v 1.12 2016/01/24 17:24:36 nanard Exp $ */ +/* $Id: miniwget.h,v 1.14 2025/02/08 23:15:17 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2005-2016 Thomas Bernard + * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ + * Copyright (c) 2005-2025 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * */ #ifndef MINIWGET_H_INCLUDED #define MINIWGET_H_INCLUDED +/*! \file miniwget.h + * \brief Lightweight HTTP client API + */ #include "miniupnpc_declspec.h" #ifdef __cplusplus extern "C" { #endif -MINIUPNP_LIBSPEC void * miniwget(const char *, int *, unsigned int, int *); +/*! \brief perform HTTP GET on an URL + * + * \param[in] url HTTP URL to GET + * \param[out] size length of the returned buffer. -1 in case of memory + * allocation error + * \param[in] scope_id interface id for IPv6 to use if not specified in the URL + * \param[out] status_code HTTP response status code (200, 404, etc.) + * \return the body of the HTTP response + */ +MINIUPNP_LIBSPEC void * miniwget(const char * url, int * size, + unsigned int scope_id, int * status_code); -MINIUPNP_LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int, unsigned int, int *); - -int parseURL(const char *, char *, unsigned short *, char * *, unsigned int *); +/*! \brief perform HTTP GET on an URL + * + * Also get the local address used to reach the HTTP server + * + * \param[in] url HTTP URL to GET + * \param[out] size length of the returned buffer. -1 in case of memory + * allocation error + * \param[out] addr local address used to connect to the server + * \param[in] addrlen size of the addr buffer + * \param[in] scope_id interface id for IPv6 to use if not specified in the URL + * \param[out] status_code HTTP response status code (200, 404, etc.) + * \return the body of the HTTP response + */ +MINIUPNP_LIBSPEC void * miniwget_getaddr(const char * url, int * size, + char * addr, int addrlen, + unsigned int scope_id, int * status_code); #ifdef __cplusplus } diff --git a/thirdparty/miniupnpc/include/miniupnpc/portlistingparse.h b/thirdparty/miniupnpc/include/miniupnpc/portlistingparse.h index e3957a3f4c1..6b4e415aa78 100644 --- a/thirdparty/miniupnpc/include/miniupnpc/portlistingparse.h +++ b/thirdparty/miniupnpc/include/miniupnpc/portlistingparse.h @@ -1,12 +1,29 @@ -/* $Id: portlistingparse.h,v 1.10 2014/11/01 10:37:32 nanard Exp $ */ +/* $Id: portlistingparse.h,v 1.12 2025/02/08 23:15:17 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2011-2015 Thomas Bernard + * (c) 2011-2025 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ #ifndef PORTLISTINGPARSE_H_INCLUDED #define PORTLISTINGPARSE_H_INCLUDED +/*! \file portlistingparse.h + * \brief Parsing of the list of port mappings + * + * As returned by GetListOfPortMappings. + * Sample of PortMappingEntry : + * + * + * 202.233.2.1 + * 2345 + * TCP + * 2345 + * 192.168.1.137 + * 1 + * dooom + * 345 + * + */ #include "miniupnpc_declspec.h" /* for the definition of UNSIGNED_INTEGER */ #include "miniupnpctypes.h" @@ -15,17 +32,8 @@ extern "C" { #endif -/* sample of PortMappingEntry : - - 202.233.2.1 - 2345 - TCP - 2345 - 192.168.1.137 - 1 - dooom - 345 - +/*! + * \brief enum of all XML elements */ typedef enum { PortMappingEltNone, PortMappingEntry, NewRemoteHost, @@ -34,27 +42,45 @@ typedef enum { PortMappingEltNone, NewEnabled, NewDescription, NewLeaseTime } portMappingElt; +/*! + * \brief linked list of port mappings + */ struct PortMapping { - struct PortMapping * l_next; /* list next element */ - UNSIGNED_INTEGER leaseTime; - unsigned short externalPort; - unsigned short internalPort; - char remoteHost[64]; - char internalClient[64]; - char description[64]; - char protocol[4]; - unsigned char enabled; + struct PortMapping * l_next; /*!< \brief next list element */ + UNSIGNED_INTEGER leaseTime; /*!< \brief in seconds */ + unsigned short externalPort; /*!< \brief external port */ + unsigned short internalPort; /*!< \brief internal port */ + char remoteHost[64]; /*!< \brief empty for wildcard */ + char internalClient[64]; /*!< \brief internal IP address */ + char description[64]; /*!< \brief description */ + char protocol[4]; /*!< \brief `TCP` or `UDP` */ + unsigned char enabled; /*!< \brief 0 (false) or 1 (true) */ }; +/*! + * \brief structure for ParsePortListing() + */ struct PortMappingParserData { - struct PortMapping * l_head; /* list head */ - portMappingElt curelt; + struct PortMapping * l_head; /*!< \brief list head */ + portMappingElt curelt; /*!< \brief currently parsed element */ }; +/*! + * \brief parse the NewPortListing part of GetListOfPortMappings response + * + * \param[in] buffer XML data + * \param[in] bufsize length of XML data + * \param[out] pdata Parsed data + */ MINIUPNP_LIBSPEC void ParsePortListing(const char * buffer, int bufsize, struct PortMappingParserData * pdata); +/*! + * \brief free parsed data structure + * + * \param[in] pdata Parsed data to free + */ MINIUPNP_LIBSPEC void FreePortListing(struct PortMappingParserData * pdata); diff --git a/thirdparty/miniupnpc/include/miniupnpc/upnpcommands.h b/thirdparty/miniupnpc/include/miniupnpc/upnpcommands.h index 1b6d4477325..592fea543d0 100644 --- a/thirdparty/miniupnpc/include/miniupnpc/upnpcommands.h +++ b/thirdparty/miniupnpc/include/miniupnpc/upnpcommands.h @@ -1,21 +1,41 @@ -/* $Id: upnpcommands.h,v 1.32 2018/03/13 23:34:47 nanard Exp $ */ -/* Miniupnp project : http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2005-2018 Thomas Bernard +/* $Id: upnpcommands.h,v 1.36 2025/03/18 23:40:15 nanard Exp $ */ +/* vim: tabstop=4 shiftwidth=4 noexpandtab + * Project: miniupnp + * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ + * Author: Thomas Bernard + * Copyright (c) 2005-2025 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided within this distribution */ #ifndef UPNPCOMMANDS_H_INCLUDED #define UPNPCOMMANDS_H_INCLUDED +/*! \file upnpcommands.h + * \brief Internet Gateway Device methods + * + * See the documentation for both IGD v1 and IGD v2 : + * - https://upnp.org/specs/gw/UPnP-gw-InternetGatewayDevice-v1-Device.pdf + * - https://upnp.org/specs/gw/UPnP-gw-InternetGatewayDevice-v2-Device.pdf + * + * The methods are from WANIPConnection:1 or 2, WANCommonInterfaceConfig:1, + * and WANIPv6FirewallControl:1 + * + */ + #include "miniupnpc_declspec.h" #include "miniupnpctypes.h" /* MiniUPnPc return codes : */ +/*! \brief value for success */ #define UPNPCOMMAND_SUCCESS (0) +/*! \brief value for unknown error */ #define UPNPCOMMAND_UNKNOWN_ERROR (-1) +/*! \brief error while checking the arguments */ #define UPNPCOMMAND_INVALID_ARGS (-2) +/*! \brief HTTP communication error */ #define UPNPCOMMAND_HTTP_ERROR (-3) +/*! \brief The response contains invalid values */ #define UPNPCOMMAND_INVALID_RESPONSE (-4) +/*! \brief Memory allocation error */ #define UPNPCOMMAND_MEM_ALLOC_ERROR (-5) #ifdef __cplusplus @@ -24,27 +44,70 @@ extern "C" { struct PortMappingParserData; +/*! \brief WANCommonInterfaceConfig:GetTotalBytesSent + * + * Note: this is a 32bits unsigned value and rolls over to 0 after reaching + * the maximum value + * + * \param[in] controlURL controlURL of the WANCommonInterfaceConfig of + * a WANDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 + */ MINIUPNP_LIBSPEC UNSIGNED_INTEGER UPNP_GetTotalBytesSent(const char * controlURL, const char * servicetype); +/*! \brief WANCommonInterfaceConfig:GetTotalBytesReceived + * + * Note: this is a 32bits unsigned value and rolls over to 0 after reaching + * the maximum value + * + * \param[in] controlURL controlURL of the WANCommonInterfaceConfig of a WANDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 + */ MINIUPNP_LIBSPEC UNSIGNED_INTEGER UPNP_GetTotalBytesReceived(const char * controlURL, const char * servicetype); +/*! \brief WANCommonInterfaceConfig:GetTotalPacketsSent + * + * Note: this is a 32bits unsigned value and rolls over to 0 after reaching + * the maximum value + * + * \param[in] controlURL controlURL of the WANCommonInterfaceConfig of a WANDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 + */ MINIUPNP_LIBSPEC UNSIGNED_INTEGER UPNP_GetTotalPacketsSent(const char * controlURL, const char * servicetype); +/*! \brief WANCommonInterfaceConfig:GetTotalBytesReceived + * + * Note: this is a 32bits unsigned value and rolls over to 0 after reaching + * the maximum value + * + * \param[in] controlURL controlURL of the WANCommonInterfaceConfig of a WANDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 + */ MINIUPNP_LIBSPEC UNSIGNED_INTEGER UPNP_GetTotalPacketsReceived(const char * controlURL, const char * servicetype); -/* UPNP_GetStatusInfo() - * status and lastconnerror are 64 byte buffers - * Return values : - * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error code */ +/*! \brief WANIPConnection:GetStatusInfo() + * + * \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1 + * \param[out] status 64 bytes buffer : `Unconfigured`, `Connecting`, + * `Connected`, `PendingDisconnect`, `Disconnecting`, `Disconnected` + * \param[out] uptime time in seconds + * \param[out] lastconnerror 64 bytes buffer : `ERROR_NONE`, + * `ERROR_COMMAND_ABORTED`, `ERROR_NOT_ENABLED_FOR_INTERNET`, + * `ERROR_USER_DISCONNECT`, `ERROR_ISP_DISCONNECT`, + * `ERROR_IDLE_DISCONNECT`, `ERROR_FORCED_DISCONNECT`, + * `ERROR_NO_CARRIER`, `ERROR_IP_CONFIGURATION`, `ERROR_UNKNOWN` + * \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS, + * #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP Error code + */ MINIUPNP_LIBSPEC int UPNP_GetStatusInfo(const char * controlURL, const char * servicetype, @@ -52,76 +115,87 @@ UPNP_GetStatusInfo(const char * controlURL, unsigned int * uptime, char * lastconnerror); -/* UPNP_GetConnectionTypeInfo() - * argument connectionType is a 64 character buffer - * Return Values : - * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error code */ +/*! \brief WANIPConnection:GetConnectionTypeInfo() + * + * \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1 + * \param[out] connectionType 64 characters buffer : `Unconfigured`, + * `IP_Routed`, `IP_Bridged` + * \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS, + * #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP Error code + */ MINIUPNP_LIBSPEC int UPNP_GetConnectionTypeInfo(const char * controlURL, const char * servicetype, char * connectionType); -/* UPNP_GetExternalIPAddress() call the corresponding UPNP method. - * if the third arg is not null the value is copied to it. - * at least 16 bytes must be available - * - * Return values : - * 0 : SUCCESS - * NON ZERO : ERROR Either an UPnP error code or an unknown error. +/*! \brief WANIPConnection:GetExternalIPAddress() * * possible UPnP Errors : - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 501 Action Failed - See UPnP Device Architecture section on Control. */ + * - 402 Invalid Args - See UPnP Device Architecture section on Control. + * - 501 Action Failed - See UPnP Device Architecture section on Control. + * + * \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1 + * \param[out] extIpAdd 16 bytes buffer + * \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_UNKNOWN_ERROR, + * #UPNPCOMMAND_INVALID_ARGS, #UPNPCOMMAND_HTTP_ERROR or an + * UPnP error code + */ MINIUPNP_LIBSPEC int UPNP_GetExternalIPAddress(const char * controlURL, const char * servicetype, char * extIpAdd); -/* UPNP_GetLinkLayerMaxBitRates() - * call WANCommonInterfaceConfig:1#GetCommonLinkProperties +/*! \brief UPNP_GetLinkLayerMaxBitRates() + * call `WANCommonInterfaceConfig:GetCommonLinkProperties` * - * return values : - * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error Code. */ + * \param[in] controlURL controlURL of the WANCommonInterfaceConfig of a WANDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 + * \param[out] bitrateDown bits per second + * \param[out] bitrateUp bits per second + * \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS, + * #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP Error Code. + */ MINIUPNP_LIBSPEC int UPNP_GetLinkLayerMaxBitRates(const char* controlURL, const char* servicetype, unsigned int * bitrateDown, unsigned int * bitrateUp); -/* UPNP_AddPortMapping() - * if desc is NULL, it will be defaulted to "libminiupnpc" - * remoteHost is usually NULL because IGD don't support it. - * - * Return values : - * 0 : SUCCESS - * NON ZERO : ERROR. Either an UPnP error code or an unknown error. +/*! \brief WANIPConnection:AddPortMapping() * * List of possible UPnP errors for AddPortMapping : - * errorCode errorDescription (short) - Description (long) - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 501 Action Failed - See UPnP Device Architecture section on Control. - * 606 Action not authorized - The action requested REQUIRES authorization and - * the sender was not authorized. - * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be - * wild-carded - * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded - * 718 ConflictInMappingEntry - The port mapping entry specified conflicts - * with a mapping assigned previously to another client - * 724 SamePortValuesRequired - Internal and External port values - * must be the same - * 725 OnlyPermanentLeasesSupported - The NAT implementation only supports - * permanent lease times on port mappings - * 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard - * and cannot be a specific IP address or DNS name - * 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and - * cannot be a specific port value - * 728 NoPortMapsAvailable - There are not enough free ports available to - * complete port mapping. - * 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed - * due to conflict with other mechanisms. - * 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded + * errorCode errorDescription (short) | Description (long) + * ---------------------------------- | ----------------- + * 402 Invalid Args | See UPnP Device Architecture section on Control. + * 501 Action Failed | See UPnP Device Architecture section on Control. + * 606 Action not authorized | The action requested REQUIRES authorization and the sender was not authorized. + * 715 WildCardNotPermittedInSrcIP | The source IP address cannot be wild-carded + * 716 WildCardNotPermittedInExtPort | The external port cannot be wild-carded + * 718 ConflictInMappingEntry | The port mapping entry specified conflicts with a mapping assigned previously to another client + * 724 SamePortValuesRequired | Internal and External port values must be the same + * 725 OnlyPermanentLeasesSupported | The NAT implementation only supports permanent lease times on port mappings + * 726 RemoteHostOnlySupportsWildcard | RemoteHost must be a wildcard and cannot be a specific IP address or DNS name + * 727 ExternalPortOnlySupportsWildcard | ExternalPort must be a wildcard and cannot be a specific port value + * 728 NoPortMapsAvailable | There are not enough free ports available to complete port mapping. + * 729 ConflictWithOtherMechanisms | Attempted port mapping is not allowed due to conflict with other mechanisms. + * 732 WildCardNotPermittedInIntPort | The internal port cannot be wild-carded + * + * \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1 + * \param[in] extPort External port + * \param[in] inPort Internal port + * \param[in] inClient IP of Internal client. + * \param[in] desc Port Mapping description. if NULL, defaults to + * "libminiupnpc" + * \param[in] proto `TCP` or `UDP` + * \param[in] remoteHost IP or empty string for wildcard. Most IGD don't + * support it + * \param[in] leaseDuration between 0 and 604800 + * \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS, + * #UPNPCOMMAND_MEM_ALLOC_ERROR, #UPNPCOMMAND_HTTP_ERROR, + * #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP error code. */ MINIUPNP_LIBSPEC int UPNP_AddPortMapping(const char * controlURL, const char * servicetype, @@ -133,28 +207,38 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype, const char * remoteHost, const char * leaseDuration); -/* UPNP_AddAnyPortMapping() - * if desc is NULL, it will be defaulted to "libminiupnpc" - * remoteHost is usually NULL because IGD don't support it. +/*! \brief WANIPConnection:AddAnyPortMapping() * - * Return values : - * 0 : SUCCESS - * NON ZERO : ERROR. Either an UPnP error code or an unknown error. + * Only in WANIPConnection:2 * * List of possible UPnP errors for AddPortMapping : - * errorCode errorDescription (short) - Description (long) - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 501 Action Failed - See UPnP Device Architecture section on Control. - * 606 Action not authorized - The action requested REQUIRES authorization and - * the sender was not authorized. - * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be - * wild-carded - * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded - * 728 NoPortMapsAvailable - There are not enough free ports available to - * complete port mapping. - * 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed - * due to conflict with other mechanisms. - * 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded + * errorCode errorDescription (short) | Description (long) + * ---------------------------------- | ------------------ + * 402 Invalid Args | See UPnP Device Architecture section on Control. + * 501 Action Failed | See UPnP Device Architecture section on Control. + * 606 Action not authorized | The action requested REQUIRES authorization and the sender was not authorized. + * 715 WildCardNotPermittedInSrcIP | The source IP address cannot be wild-carded + * 716 WildCardNotPermittedInExtPort | The external port cannot be wild-carded + * 728 NoPortMapsAvailable | There are not enough free ports available to complete port mapping. + * 729 ConflictWithOtherMechanisms | Attempted port mapping is not allowed due to conflict with other mechanisms. + * 732 WildCardNotPermittedInIntPort | The internal port cannot be wild-carded + * + * \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:2 + * \param[in] extPort External port + * \param[in] inPort Internal port + * \param[in] inClient IP of Internal client. + * \param[in] desc Port Mapping description. if NULL, defaults to + * "libminiupnpc" + * \param[in] proto `TCP` or `UDP` + * \param[in] remoteHost IP or empty string for wildcard. Most IGD don't + * support it + * \param[in] leaseDuration between 0 and 604800 + * \param[out] reservedPort 6 bytes buffer + * \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS, + * #UPNPCOMMAND_MEM_ALLOC_ERROR, #UPNPCOMMAND_HTTP_ERROR, + * #UPNPCOMMAND_INVALID_RESPONSE, #UPNPCOMMAND_UNKNOWN_ERROR + * or a UPnP error code. */ MINIUPNP_LIBSPEC int UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype, @@ -167,24 +251,35 @@ UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype, const char * leaseDuration, char * reservedPort); -/* UPNP_DeletePortMapping() - * Use same argument values as what was used for AddPortMapping(). - * remoteHost is usually NULL because IGD don't support it. - * Return Values : - * 0 : SUCCESS - * NON ZERO : error. Either an UPnP error code or an undefined error. +/*! \brief WANIPConnection:DeletePortMapping() * - * List of possible UPnP errors for DeletePortMapping : - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 606 Action not authorized - The action requested REQUIRES authorization - * and the sender was not authorized. - * 714 NoSuchEntryInArray - The specified value does not exist in the array */ + * Use same argument values as what was used for UPNP_AddPortMapping() + * + * List of possible UPnP errors for UPNP_DeletePortMapping() : + * errorCode errorDescription (short) | Description (long) + * ---------------------------------- | ------------------ + * 402 Invalid Args | See UPnP Device Architecture section on Control. + * 606 Action not authorized | The action requested REQUIRES authorization and the sender was not authorized. + * 714 NoSuchEntryInArray | The specified value does not exist in the array + * + * \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1 + * \param[in] extPort External port + * \param[in] proto `TCP` or `UDP` + * \param[in] remoteHost IP or empty string for wildcard. Most IGD don't + * support it + * \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS, + * #UPNPCOMMAND_MEM_ALLOC_ERROR, #UPNPCOMMAND_HTTP_ERROR, + * #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP error code. + */ MINIUPNP_LIBSPEC int UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, const char * extPort, const char * proto, const char * remoteHost); -/* UPNP_DeletePortRangeMapping() +/*! \brief WANIPConnection:DeletePortRangeMapping() + * + * Only in WANIPConnection:2 * Use same argument values as what was used for AddPortMapping(). * remoteHost is usually NULL because IGD don't support it. * Return Values : @@ -192,46 +287,66 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, * NON ZERO : error. Either an UPnP error code or an undefined error. * * List of possible UPnP errors for DeletePortMapping : - * 606 Action not authorized - The action requested REQUIRES authorization - * and the sender was not authorized. - * 730 PortMappingNotFound - This error message is returned if no port - * mapping is found in the specified range. - * 733 InconsistentParameters - NewStartPort and NewEndPort values are not consistent. */ + * errorCode errorDescription (short) | Description (long) + * ---------------------------------- | ------------------ + * 606 Action not authorized | The action requested REQUIRES authorization and the sender was not authorized. + * 730 PortMappingNotFound | This error message is returned if no port mapping is found in the specified range. + * 733 InconsistentParameters | NewStartPort and NewEndPort values are not consistent. + * \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:2 + * \param[in] extPortStart External port range start + * \param[in] extPortEnd External port range end + * \param[in] proto `TCP` or `UDP` + * \param[in] manage `0` to remove only the port mappings of this IGD, + * `1` to remove port mappings also for other clients + * \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS, + * #UPNPCOMMAND_MEM_ALLOC_ERROR, #UPNPCOMMAND_HTTP_ERROR, + * #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP error code. + */ MINIUPNP_LIBSPEC int UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype, const char * extPortStart, const char * extPortEnd, const char * proto, const char * manage); -/* UPNP_GetPortMappingNumberOfEntries() - * not supported by all routers */ +/*! \brief WANIPConnection:GetPortMappingNumberOfEntries() + * + * not supported by all routers + * + * \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1 + * \param[out] numEntries Port mappings count + * \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_HTTP_ERROR, + * #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP error code. + */ MINIUPNP_LIBSPEC int UPNP_GetPortMappingNumberOfEntries(const char * controlURL, const char * servicetype, unsigned int * numEntries); -/* UPNP_GetSpecificPortMappingEntry() - * retrieves an existing port mapping - * params : - * in extPort - * in proto - * in remoteHost - * out intClient (16 bytes) - * out intPort (6 bytes) - * out desc (80 bytes) - * out enabled (4 bytes) - * out leaseDuration (16 bytes) +/*! \brief retrieves an existing port mapping for a port:protocol * - * return value : - * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error Code. + * List of possible UPnP errors for UPNP_GetSpecificPortMappingEntry() : + * errorCode errorDescription (short) | Description (long) + * ---------------------------------- | ------------------ + * 402 Invalid Args | See UPnP Device Architecture section on Control. + * 501 Action Failed | See UPnP Device Architecture section on Control. + * 606 Action not authorized | The action requested REQUIRES authorization and the sender was not authorized. + * 714 NoSuchEntryInArray | The specified value does not exist in the array. * - * List of possible UPnP errors for _GetSpecificPortMappingEntry : - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 501 Action Failed - See UPnP Device Architecture section on Control. - * 606 Action not authorized - The action requested REQUIRES authorization - * and the sender was not authorized. - * 714 NoSuchEntryInArray - The specified value does not exist in the array. + * \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1 + * \param[in] extPort External port + * \param[in] proto `TCP` or `UDP` + * \param[in] remoteHost IP or empty string for wildcard. Most IGD don't + * support it + * \param[out] intClient 16 bytes buffer + * \param[out] intPort 6 bytes buffer + * \param[out] desc 80 bytes buffer + * \param[out] enabled 4 bytes buffer + * \param[out] leaseDuration 16 bytes + * \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS, + * #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP Error Code. */ MINIUPNP_LIBSPEC int UPNP_GetSpecificPortMappingEntry(const char * controlURL, @@ -245,27 +360,65 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL, char * enabled, char * leaseDuration); -/* UPNP_GetGenericPortMappingEntry() - * params : - * in index - * out extPort (6 bytes) - * out intClient (16 bytes) - * out intPort (6 bytes) - * out protocol (4 bytes) - * out desc (80 bytes) - * out enabled (4 bytes) - * out rHost (64 bytes) - * out duration (16 bytes) +/*! \brief retrieves an existing port mapping for a port:protocol * - * return value : - * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error Code. + * List of possible UPnP errors for UPNP_GetSpecificPortMappingEntry() : + * errorCode errorDescription (short) | Description (long) + * ---------------------------------- | ------------------ + * 402 Invalid Args | See UPnP Device Architecture section on Control. + * 501 Action Failed | See UPnP Device Architecture section on Control. + * 606 Action not authorized | The action requested REQUIRES authorization and the sender was not authorized. + * 714 NoSuchEntryInArray | The specified value does not exist in the array. * - * Possible UPNP Error codes : - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 606 Action not authorized - The action requested REQUIRES authorization - * and the sender was not authorized. - * 713 SpecifiedArrayIndexInvalid - The specified array index is out of bounds + * \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1 + * \param[in] extPort External port + * \param[in] proto `TCP` or `UDP` + * \param[in] remoteHost IP or empty string for wildcard. Most IGD don't + * support it + * \param[out] intClient 16 bytes buffer + * \param[out] intPort 6 bytes buffer + * \param[out] desc desclen bytes buffer + * \param[in] desclen desc buffer length + * \param[out] enabled 4 bytes buffer + * \param[out] leaseDuration 16 bytes + * \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS, + * #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP Error Code. + */ +MINIUPNP_LIBSPEC int +UPNP_GetSpecificPortMappingEntryExt(const char * controlURL, + const char * servicetype, + const char * extPort, + const char * proto, + const char * remoteHost, + char * intClient, + char * intPort, + char * desc, + size_t desclen, + char * enabled, + char * leaseDuration); + +/*! \brief WANIPConnection:GetGenericPortMappingEntry() + * + * errorCode errorDescription (short) | Description (long) + * ---------------------------------- | ------------------ + * 402 Invalid Args | See UPnP Device Architecture section on Control. + * 606 Action not authorized | The action requested REQUIRES authorization and the sender was not authorized. + * 713 SpecifiedArrayIndexInvalid | The specified array index is out of bounds + * + * \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1 + * \param[in] index + * \param[out] extPort 6 bytes buffer + * \param[out] intClient 16 bytes buffer + * \param[out] intPort 6 bytes buffer + * \param[out] protocol 4 bytes buffer + * \param[out] desc 80 bytes buffer + * \param[out] enabled 4 bytes buffer + * \param[out] rHost 64 bytes buffer + * \param[out] duration 16 bytes buffer + * \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS, + * #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP Error Code. */ MINIUPNP_LIBSPEC int UPNP_GetGenericPortMappingEntry(const char * controlURL, @@ -280,14 +433,64 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL, char * rHost, char * duration); -/* UPNP_GetListOfPortMappings() Available in IGD v2 +/*! \brief WANIPConnection:GetGenericPortMappingEntry() * + * errorCode errorDescription (short) | Description (long) + * ---------------------------------- | ------------------ + * 402 Invalid Args | See UPnP Device Architecture section on Control. + * 606 Action not authorized | The action requested REQUIRES authorization and the sender was not authorized. + * 713 SpecifiedArrayIndexInvalid | The specified array index is out of bounds * - * Possible UPNP Error codes : - * 606 Action not Authorized - * 730 PortMappingNotFound - no port mapping is found in the specified range. - * 733 InconsistantParameters - NewStartPort and NewEndPort values are not - * consistent. + * \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1 + * \param[in] index + * \param[out] extPort 6 bytes buffer + * \param[out] intClient 16 bytes buffer + * \param[out] intPort 6 bytes buffer + * \param[out] protocol 4 bytes buffer + * \param[out] desc desclen bytes buffer + * \param[in] desclen desc buffer length + * \param[out] enabled 4 bytes buffer + * \param[out] rHost desclen bytes buffer + * \param[in] rHostlen rHost buffer length + * \param[out] duration 16 bytes buffer + * \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS, + * #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP Error Code. + */ +MINIUPNP_LIBSPEC int +UPNP_GetGenericPortMappingEntryExt(const char * controlURL, + const char * servicetype, + const char * index, + char * extPort, + char * intClient, + char * intPort, + char * protocol, + char * desc, + size_t desclen, + char * enabled, + char * rHost, + size_t rHostlen, + char * duration); + +/*! \brief retrieval of a list of existing port mappings + * + * Available in IGD v2 : WANIPConnection:GetListOfPortMappings() + * + * errorCode errorDescription (short) | Description (long) + * ---------------------------------- | ------------------ + * 606 Action not authorized | The action requested REQUIRES authorization and the sender was not authorized. + * 730 PortMappingNotFound | no port mapping is found in the specified range. + * 733 InconsistantParameters | NewStartPort and NewEndPort values are not consistent. + * + * \param[in] controlURL controlURL of the WANIPConnection of a + * WANConnectionDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:2 + * \param[in] startPort port interval start + * \param[in] endPort port interval end + * \param[in] protocol `TCP` or `UDP` + * \param[in] numberOfPorts size limit of the list returned. `0` to request + * all port mappings + * \param[out] data port mappings list */ MINIUPNP_LIBSPEC int UPNP_GetListOfPortMappings(const char * controlURL, @@ -298,15 +501,48 @@ UPNP_GetListOfPortMappings(const char * controlURL, const char * numberOfPorts, struct PortMappingParserData * data); -/* IGD:2, functions for service WANIPv6FirewallControl:1 */ +/*! \brief GetFirewallStatus() retrieves whether the firewall is enabled + * and pinhole can be created through UPnP + * + * IGD:2, functions for service WANIPv6FirewallControl:1 + * + * \param[in] controlURL controlURL of the WANIPv6FirewallControl of a + * WANConnectionDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANIPv6FirewallControl:1 + * \param[out] firewallEnabled false (0) or true (1) + * \param[out] inboundPinholeAllowed false (0) or true (1) + * \return #UPNPCOMMAND_UNKNOWN_ERROR, #UPNPCOMMAND_INVALID_ARGS, + * #UPNPCOMMAND_HTTP_ERROR, #UPNPCOMMAND_SUCCESS or an UPnP error code + */ MINIUPNP_LIBSPEC int UPNP_GetFirewallStatus(const char * controlURL, const char * servicetype, int * firewallEnabled, int * inboundPinholeAllowed); +/*! \brief retrieve default value after which automatically created pinholes + * expire + * + * The returned value may be specific to the \p proto, \p remoteHost, + * \p remotePort, \p intClient and \p intPort, but this behavior depends + * on the implementation of the firewall. + * + * \param[in] controlURL controlURL of the WANIPv6FirewallControl of a + * WANConnectionDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANIPv6FirewallControl:1 + * \param[in] remoteHost + * \param[in] remotePort + * \param[in] intClient + * \param[in] intPort + * \param[in] proto `TCP` or `UDP` + * \param[out] opTimeout lifetime in seconds of an inbound "automatic" + * firewall pinhole created by an outbound traffic initiation. + * \return #UPNPCOMMAND_UNKNOWN_ERROR, #UPNPCOMMAND_INVALID_ARGS, + * #UPNPCOMMAND_HTTP_ERROR, #UPNPCOMMAND_SUCCESS or an UPnP error code + */ MINIUPNP_LIBSPEC int -UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype, +UPNP_GetOutboundPinholeTimeout(const char * controlURL, + const char * servicetype, const char * remoteHost, const char * remotePort, const char * intClient, @@ -314,6 +550,24 @@ UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype const char * proto, int * opTimeout); +/*! \brief create a new pinhole that allows incoming traffic to pass + * through the firewall + * + * \param[in] controlURL controlURL of the WANIPv6FirewallControl of a + * WANConnectionDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANIPv6FirewallControl:1 + * \param[in] remoteHost literal presentation of IPv6 address or domain name. + * empty string for wildcard + * \param[in] remotePort remote host port. Likely 0 (for wildcard) + * \param[in] intClient IP address of internal client. cannot be wildcarded + * \param[in] intPort client port. 0 for wildcard + * \param[in] proto IP protocol integer (6 for TCP, 17 for UDP, etc.) + * 65535 for wildcard. + * \param[in] leaseTime in seconds + * \param[out] uniqueID 8 bytes buffer + * \return #UPNPCOMMAND_UNKNOWN_ERROR, #UPNPCOMMAND_INVALID_ARGS, + * #UPNPCOMMAND_HTTP_ERROR, #UPNPCOMMAND_SUCCESS or an UPnP error code + */ MINIUPNP_LIBSPEC int UPNP_AddPinhole(const char * controlURL, const char * servicetype, const char * remoteHost, @@ -324,18 +578,61 @@ UPNP_AddPinhole(const char * controlURL, const char * servicetype, const char * leaseTime, char * uniqueID); +/*! \brief update a pinhole’s lease time + * + * \param[in] controlURL controlURL of the WANIPv6FirewallControl of a + * WANConnectionDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANIPv6FirewallControl:1 + * \param[in] uniqueID value obtained through UPNP_AddPinhole() + * \param[in] leaseTime in seconds + * \return #UPNPCOMMAND_UNKNOWN_ERROR, #UPNPCOMMAND_INVALID_ARGS, + * #UPNPCOMMAND_HTTP_ERROR, #UPNPCOMMAND_SUCCESS or an UPnP error code + */ MINIUPNP_LIBSPEC int UPNP_UpdatePinhole(const char * controlURL, const char * servicetype, const char * uniqueID, const char * leaseTime); +/*! \brief remove a pinhole + * + * \param[in] controlURL controlURL of the WANIPv6FirewallControl of a + * WANConnectionDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANIPv6FirewallControl:1 + * \param[in] uniqueID value obtained through UPNP_AddPinhole() + * \return #UPNPCOMMAND_UNKNOWN_ERROR, #UPNPCOMMAND_INVALID_ARGS, + * #UPNPCOMMAND_HTTP_ERROR, #UPNPCOMMAND_SUCCESS or an UPnP error code + */ MINIUPNP_LIBSPEC int -UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID); +UPNP_DeletePinhole(const char * controlURL, + const char * servicetype, + const char * uniqueID); +/*! \brief checking if a certain pinhole allows traffic to pass through the firewall + * + * \param[in] controlURL controlURL of the WANIPv6FirewallControl of a + * WANConnectionDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANIPv6FirewallControl:1 + * \param[in] uniqueID value obtained through UPNP_AddPinhole() + * \param[out] isWorking `0` for false, `1` for true + * \return #UPNPCOMMAND_UNKNOWN_ERROR, #UPNPCOMMAND_INVALID_ARGS, + * #UPNPCOMMAND_HTTP_ERROR, #UPNPCOMMAND_SUCCESS or an UPnP error code + */ MINIUPNP_LIBSPEC int UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype, const char * uniqueID, int * isWorking); +/*! \brief get the total number of IP packets which have been going through + * the specified pinhole + * \todo \p packets should be #UNSIGNED_INTEGER + * \param[in] controlURL controlURL of the WANIPv6FirewallControl of a + * WANConnectionDevice + * \param[in] servicetype urn:schemas-upnp-org:service:WANIPv6FirewallControl:1 + * \param[in] uniqueID value obtained through UPNP_AddPinhole() + * \param[out] packets how many IP packets have been going through the + * specified pinhole + * \return #UPNPCOMMAND_UNKNOWN_ERROR, #UPNPCOMMAND_INVALID_ARGS, + * #UPNPCOMMAND_HTTP_ERROR, #UPNPCOMMAND_SUCCESS or an UPnP error code + */ MINIUPNP_LIBSPEC int UPNP_GetPinholePackets(const char * controlURL, const char * servicetype, const char * uniqueID, int * packets); diff --git a/thirdparty/miniupnpc/include/miniupnpc/upnpdev.h b/thirdparty/miniupnpc/include/miniupnpc/upnpdev.h index 171d495be35..1a3f0360725 100644 --- a/thirdparty/miniupnpc/include/miniupnpc/upnpdev.h +++ b/thirdparty/miniupnpc/include/miniupnpc/upnpdev.h @@ -1,27 +1,40 @@ -/* $Id: upnpdev.h,v 1.4 2021/08/21 09:45:01 nanard Exp $ */ +/* $Id: upnpdev.h,v 1.6 2025/02/08 23:15:17 nanard Exp $ */ /* Project : miniupnp * Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ * Author : Thomas BERNARD - * copyright (c) 2005-2021 Thomas Bernard + * copyright (c) 2005-2025 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENSE file. */ #ifndef UPNPDEV_H_INCLUDED #define UPNPDEV_H_INCLUDED +/*! \file upnpdev.h + * \brief UPNPDev device linked-list structure + * \todo could be merged into miniupnpc.h + */ #include "miniupnpc_declspec.h" #ifdef __cplusplus extern "C" { #endif +/*! + * \brief UPnP device linked-list + */ struct UPNPDev { + /*! \brief pointer to the next element */ struct UPNPDev * pNext; + /*! \brief root description URL */ char * descURL; + /*! \brief ST: as advertised */ char * st; + /*! \brief USN: as advertised */ char * usn; + /*! \brief IPv6 scope id of the network interface */ unsigned int scope_id; #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 flexible array member */ + /*! \brief buffer for descURL, st and usn */ char buffer[]; #elif defined(__GNUC__) char buffer[0]; @@ -31,8 +44,9 @@ struct UPNPDev { #endif }; -/* freeUPNPDevlist() - * free list returned by upnpDiscover() */ +/*! \brief free list returned by upnpDiscover() + * \param[in] devlist linked list to free + */ MINIUPNP_LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist); diff --git a/thirdparty/miniupnpc/include/miniupnpc/upnpreplyparse.h b/thirdparty/miniupnpc/include/miniupnpc/upnpreplyparse.h index 6badd15b26a..59f16e8eb2c 100644 --- a/thirdparty/miniupnpc/include/miniupnpc/upnpreplyparse.h +++ b/thirdparty/miniupnpc/include/miniupnpc/upnpreplyparse.h @@ -1,53 +1,73 @@ -/* $Id: upnpreplyparse.h,v 1.19 2014/10/27 16:33:19 nanard Exp $ */ +/* $Id: upnpreplyparse.h,v 1.22 2025/03/29 17:58:12 nanard Exp $ */ /* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard + * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ + * (c) 2006-2025 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ #ifndef UPNPREPLYPARSE_H_INCLUDED #define UPNPREPLYPARSE_H_INCLUDED +/*! \file upnpreplyparse.h + * \brief Parsing of UPnP SOAP responses + */ + #ifdef __cplusplus extern "C" { #endif -struct NameValue { - struct NameValue * l_next; - char name[64]; - char value[128]; -}; +/*! \brief Name/Value linked list + * not exposed in the public API + */ +struct NameValue; +/*! \brief data structure for parsing */ struct NameValueParserData { + /*! \brief name/value linked list */ struct NameValue * l_head; + /*! \brief current element name */ char curelt[64]; + /*! \brief port listing array */ char * portListing; + /*! \brief port listing array length */ int portListingLength; + /*! \brief flag indicating the current element is */ int topelt; + /*! \brief top element character data */ const char * cdata; + /*! \brief top element character data length */ int cdatalen; }; -/* ParseNameValue() */ +/*! + * \brief Parse XML and fill the structure + * + * \param[in] buffer XML data + * \param[in] bufsize buffer length + * \param[out] data structure to fill + */ void ParseNameValue(const char * buffer, int bufsize, struct NameValueParserData * data); -/* ClearNameValueList() */ +/*! + * \brief free memory + * + * \param[in,out] pdata data structure + */ void ClearNameValueList(struct NameValueParserData * pdata); -/* GetValueFromNameValueList() */ +/*! + * \brief get a value from the parsed data + * + * \param[in] pdata data structure + * \param[in] name name + * \return the value or NULL if not found + */ char * GetValueFromNameValueList(struct NameValueParserData * pdata, - const char * Name); - -#if 0 -/* GetValueFromNameValueListIgnoreNS() */ -char * -GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, - const char * Name); -#endif + const char * name); /* DisplayNameValueList() */ #ifdef DEBUG @@ -60,4 +80,3 @@ DisplayNameValueList(char * buffer, int bufsize); #endif #endif - diff --git a/thirdparty/miniupnpc/src/addr_is_reserved.c b/thirdparty/miniupnpc/src/addr_is_reserved.c index 145b504823a..736dc386ffa 100644 --- a/thirdparty/miniupnpc/src/addr_is_reserved.c +++ b/thirdparty/miniupnpc/src/addr_is_reserved.c @@ -1,13 +1,14 @@ -/* $Id: addr_is_reserved.c,v 1.4 2021/03/02 23:40:32 nanard Exp $ */ +/* $Id: addr_is_reserved.c,v 1.7 2025/01/12 15:47:17 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-2024 Thomas Bernard + * copyright (c) 2005-2025 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENSE file. */ #ifdef _WIN32 /* Win32 Specific includes and defines */ +#define WIN32_LEAN_AND_MEAN #include #include #if !defined(_MSC_VER) @@ -15,6 +16,9 @@ #else /* !defined(_MSC_VER) */ typedef unsigned long uint32_t; #endif /* !defined(_MSC_VER) */ +#if !defined(_WIN32_WINNT_VISTA) +#define _WIN32_WINNT_VISTA 0x0600 +#endif #else /* _WIN32 */ #include #include @@ -59,7 +63,7 @@ int addr_is_reserved(const char * addr_str) uint32_t addr_n, address; size_t i; -#if defined(_WIN32) && _WIN32_WINNT < 0x0600 // _WIN32_WINNT_VISTA +#if defined(_WIN32) && (_WIN32_WINNT < _WIN32_WINNT_VISTA) addr_n = inet_addr(addr_str); if (addr_n == INADDR_NONE) return 1; diff --git a/thirdparty/miniupnpc/src/connecthostport.c b/thirdparty/miniupnpc/src/connecthostport.c index 79f832b8dbf..1085550bffb 100644 --- a/thirdparty/miniupnpc/src/connecthostport.c +++ b/thirdparty/miniupnpc/src/connecthostport.c @@ -1,8 +1,9 @@ -/* $Id: connecthostport.c,v 1.24 2020/11/09 19:26:53 nanard Exp $ */ +/* $Id: connecthostport.c,v 1.25 2025/05/24 15:59:08 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) 2010-2020 Thomas Bernard + * Copyright (c) 2010-2025 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ @@ -15,6 +16,7 @@ #include #include #ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN #include #include #include @@ -123,8 +125,12 @@ SOCKET connecthostport(const char * host, unsigned short port, #else n = select(s + 1, NULL, &wset, NULL, NULL); #endif - if(n == -1 && errno == EINTR) - continue; + if(n < 0) { + if (errno == EINTR) + continue; /* try again */ + else + break; /* EBADF, EFAULT, EINVAL */ + } #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT if(n == 0) { errno = ETIMEDOUT; @@ -132,8 +138,6 @@ SOCKET connecthostport(const char * host, unsigned short port, break; } #endif - /*len = 0;*/ - /*n = getpeername(s, NULL, &len);*/ len = sizeof(err); if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { PRINT_SOCKET_ERROR("getsockopt"); @@ -240,8 +244,12 @@ SOCKET connecthostport(const char * host, unsigned short port, #else n = select(s + 1, NULL, &wset, NULL, NULL); #endif - if(n == -1 && errno == EINTR) - continue; + if(n < 0) { + if (errno == EINTR) + continue; /* try again */ + else + break; /* EBADF, EFAULT, EINVAL */ + } #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT if(n == 0) { errno = ETIMEDOUT; @@ -249,8 +257,6 @@ SOCKET connecthostport(const char * host, unsigned short port, break; } #endif - /*len = 0;*/ - /*n = getpeername(s, NULL, &len);*/ len = sizeof(err); if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { PRINT_SOCKET_ERROR("getsockopt"); diff --git a/thirdparty/miniupnpc/src/minisoap.c b/thirdparty/miniupnpc/src/minisoap.c index 5c6bf016845..aed7a30fc77 100644 --- a/thirdparty/miniupnpc/src/minisoap.c +++ b/thirdparty/miniupnpc/src/minisoap.c @@ -1,8 +1,8 @@ -/* $Id: minisoap.c,v 1.32 2023/07/05 22:43:50 nanard Exp $ */ +/* $Id: minisoap.c,v 1.35 2025/04/27 21:13:45 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2005-2024 Thomas Bernard + * Copyright (c) 2005-2025 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * @@ -11,6 +11,7 @@ #include #include #ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN #include #include #include "win32_snprintf.h" @@ -99,7 +100,6 @@ int soapPostSubmit(SOCKET fd, #endif "SOAPAction: \"%s\"\r\n" "Connection: close\r\n" - "Cache-Control: no-cache\r\n" /* ??? */ "\r\n", url, httpversion, host, portstr, bodysize, action); if ((unsigned int)headerssize >= sizeof(headerbuf)) diff --git a/thirdparty/miniupnpc/src/minissdpc.c b/thirdparty/miniupnpc/src/minissdpc.c index 57cb99962e6..82a11060237 100644 --- a/thirdparty/miniupnpc/src/minissdpc.c +++ b/thirdparty/miniupnpc/src/minissdpc.c @@ -1,9 +1,9 @@ -/* $Id: minissdpc.c,v 1.51 2024/05/16 00:12:05 nanard Exp $ */ +/* $Id: minissdpc.c,v 1.54 2025/03/29 17:59:01 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-2024 Thomas Bernard + * copyright (c) 2005-2025 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENCE file. */ #include @@ -16,6 +16,7 @@ #endif #if defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__) #ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN #include #include #include @@ -39,6 +40,9 @@ typedef unsigned short uint16_t; static const IN6_ADDR in6addr_any_init = {0}; #endif #endif +#if !defined(_WIN32_WINNT_VISTA) +#define _WIN32_WINNT_VISTA 0x0600 +#endif #endif /* _WIN32 */ #if defined(__amigaos__) || defined(__amigaos4__) #include @@ -387,7 +391,7 @@ free_tmp_and_return: * the last 4 arguments are filled during the parsing : * - location/locationsize : "location:" field of the SSDP reply packet * - st/stsize : "st:" field of the SSDP reply packet. - * - usn/usnsize : "usn:" filed of the SSDP reply packet + * - usn/usnsize : "usn:" field of the SSDP reply packet * The strings are NOT null terminated */ static void parseMSEARCHReply(const char * reply, int size, @@ -460,7 +464,7 @@ parseMSEARCHReply(const char * reply, int size, static int upnp_gettimeofday(struct timeval * tv) { #if defined(_WIN32) -#if _WIN32_WINNT >= 0x0600 // _WIN32_WINNT_VISTA +#if _WIN32_WINNT >= _WIN32_WINNT_VISTA ULONGLONG ts = GetTickCount64(); #else DWORD ts = GetTickCount(); @@ -539,10 +543,10 @@ ssdpDiscoverDevices(const char * const deviceTypes[], int n; struct sockaddr_storage sockudp_r; unsigned int mx; + int rv; #ifdef NO_GETADDRINFO struct sockaddr_storage sockudp_w; #else - int rv; struct addrinfo hints, *servinfo; #endif #ifdef _WIN32 @@ -591,8 +595,8 @@ ssdpDiscoverDevices(const char * const deviceTypes[], * in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */ if(!ipv6) { DWORD ifbestidx; -#if _WIN32_WINNT >= 0x0600 // _WIN32_WINNT_VISTA - // While we don't need IPv6 support, the IPv4 only funciton is not available in UWP apps. +#if _WIN32_WINNT >= _WIN32_WINNT_VISTA + // While we don't need IPv6 support, the IPv4 only function is not available in UWP apps. SOCKADDR_IN destAddr; memset(&destAddr, 0, sizeof(destAddr)); destAddr.sin_family = AF_INET; @@ -747,7 +751,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[], } else { struct in_addr mc_if; #if defined(_WIN32) -#if _WIN32_WINNT >= 0x0600 // _WIN32_WINNT_VISTA +#if _WIN32_WINNT >= _WIN32_WINNT_VISTA InetPtonA(AF_INET, multicastif, &mc_if); #else mc_if.s_addr = inet_addr(multicastif); /* old Windows SDK do not support InetPtoA() */ @@ -871,9 +875,9 @@ ssdpDiscoverDevices(const char * const deviceTypes[], p->sin_port = htons(SSDP_PORT); p->sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR); } - n = sendto(sudp, bufr, n, 0, &sockudp_w, - ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)); - if (n < 0) { + rv = sendto(sudp, bufr, n, 0, (struct sockaddr *)&sockudp_w, + ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)); + if (rv < 0) { if(error) *error = MINISSDPC_SOCKET_ERROR; PRINT_SOCKET_ERROR("sendto"); @@ -899,9 +903,11 @@ ssdpDiscoverDevices(const char * const deviceTypes[], break; } else { struct addrinfo *p; + /* as getaddrinfo() returns a linked list, we are iterating it + * even thought it should only return one result here */ for(p = servinfo; p; p = p->ai_next) { - n = sendto(sudp, bufr, n, 0, p->ai_addr, MSC_CAST_INT p->ai_addrlen); - if (n < 0) { + rv = sendto(sudp, bufr, n, 0, p->ai_addr, MSC_CAST_INT p->ai_addrlen); + if (rv < 0) { #ifdef DEBUG char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; if (getnameinfo(p->ai_addr, (socklen_t)p->ai_addrlen, hbuf, sizeof(hbuf), sbuf, diff --git a/thirdparty/miniupnpc/src/miniupnpc.c b/thirdparty/miniupnpc/src/miniupnpc.c index 9da1496b378..fd2c8969c13 100644 --- a/thirdparty/miniupnpc/src/miniupnpc.c +++ b/thirdparty/miniupnpc/src/miniupnpc.c @@ -1,9 +1,9 @@ -/* $Id: miniupnpc.c,v 1.159 2021/03/02 23:36:32 nanard Exp $ */ +/* $Id: miniupnpc.c,v 1.165 2025/01/10 22:57:21 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-2024 Thomas Bernard + * copyright (c) 2005-2025 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENSE file. */ #include @@ -11,6 +11,7 @@ #include #ifdef _WIN32 /* Win32 Specific includes and defines */ +#define WIN32_LEAN_AND_MEAN #include #include #include @@ -98,8 +99,8 @@ MINIUPNP_LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGD * pointer - OK * NULL - error */ char * -simpleUPnPcommand(int s, const char * url, const char * service, - const char * action, struct UPNParg * args, +simpleUPnPcommand(const char * url, const char * service, + const char * action, const struct UPNParg * args, int * bufsize) { char hostname[MAXHOSTNAMELEN+1]; @@ -111,6 +112,7 @@ simpleUPnPcommand(int s, const char * url, const char * service, char * buf; int n; int status_code; + SOCKET s; *bufsize = 0; snprintf(soapact, sizeof(soapact), "%s#%s", service, action); @@ -197,12 +199,10 @@ simpleUPnPcommand(int s, const char * url, const char * service, return NULL; } if(!parseURL(url, hostname, &port, &path, NULL)) return NULL; - if(ISINVALID((SOCKET)s)) { - s = connecthostport(hostname, port, 0); - if(ISINVALID((SOCKET)s)) { - /* failed to connect */ - return NULL; - } + s = connecthostport(hostname, port, 0); + if(ISINVALID(s)) { + /* failed to connect */ + return NULL; } n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, "1.1"); @@ -505,13 +505,14 @@ UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data) /* UPNP_GetValidIGD() : * return values : * -1 = Internal error - * 0 = NO IGD found - * 1 = A valid connected IGD has been found + * 0 = NO IGD found (UPNP_NO_IGD) + * 1 = A valid connected IGD has been found (UPNP_CONNECTED_IGD) * 2 = A valid connected IGD has been found but its - * IP address is reserved (non routable) + * IP address is reserved (non routable) (UPNP_PRIVATEIP_IGD) * 3 = A valid IGD has been found but it reported as - * not connected + * not connected (UPNP_DISCONNECTED_IGD) * 4 = an UPnP device has been found but was not recognized as an IGD + * (UPNP_UNKNOWN_DEVICE) * * In any positive non zero return case, the urls and data structures * passed as parameters are set. Don't forget to call FreeUPNPUrls(urls) to diff --git a/thirdparty/miniupnpc/src/miniupnpcstrings.h b/thirdparty/miniupnpc/src/miniupnpcstrings.h index d40c2455ba8..d30901d5854 100644 --- a/thirdparty/miniupnpc/src/miniupnpcstrings.h +++ b/thirdparty/miniupnpc/src/miniupnpcstrings.h @@ -2,7 +2,7 @@ #define MINIUPNPCSTRINGS_H_INCLUDED #define OS_STRING "Godot Engine/1.0" -#define MINIUPNPC_VERSION_STRING "2.2.8" +#define MINIUPNPC_VERSION_STRING "2.3.3" #if 0 /* according to "UPnP Device Architecture 1.0" */ diff --git a/thirdparty/miniupnpc/src/miniwget.c b/thirdparty/miniupnpc/src/miniwget.c index a7a32dfdbaf..4f1a55b1e3e 100644 --- a/thirdparty/miniupnpc/src/miniwget.c +++ b/thirdparty/miniupnpc/src/miniwget.c @@ -1,8 +1,8 @@ -/* $Id: miniwget.c,v 1.85 2023/06/15 21:47:50 nanard Exp $ */ +/* $Id: miniwget.c,v 1.88 2025/05/25 21:56:49 nanard Exp $ */ /* Project : miniupnp * Website : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ * Author : Thomas Bernard - * Copyright (c) 2005-2024 Thomas Bernard + * Copyright (c) 2005-2025 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ @@ -11,6 +11,7 @@ #include #include #ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN #include #include #include diff --git a/thirdparty/miniupnpc/src/miniwget_private.h b/thirdparty/miniupnpc/src/miniwget_private.h index e4eaac80851..0585de9e4d4 100644 --- a/thirdparty/miniupnpc/src/miniwget_private.h +++ b/thirdparty/miniupnpc/src/miniwget_private.h @@ -1,15 +1,54 @@ /* $Id: miniwget_private.h,v 1.1 2018/04/06 10:17:58 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2018 Thomas Bernard + * Copyright (c) 2018-2025 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * */ #ifndef MINIWGET_INTERNAL_H_INCLUDED #define MINIWGET_INTERNAL_H_INCLUDED +/*! \file miniwget_private.h + * \brief Lightweight HTTP client private API + */ #include "miniupnpc_socketdef.h" +/*! \brief Read a HTTP response from a socket + * + * Processed HTTP headers : + * - `Content-Length` + * - `Transfer-encoding` + * return a pointer to the content buffer, which length is saved + * to the length parameter. + * \param[in] s socket + * \param[out] size returned content buffer size + * \param[out] status_code HTTP Status code + * \return malloc'ed content buffer + */ void * getHTTPResponse(SOCKET s, int * size, int * status_code); +/*! \brief parse a HTTP URL + * + * URL formats supported : + * - `http://192.168.1.1/path/xxx` + * - `http://192.168.1.1:8080/path/xxx` + * - `http://[2a00:1234:5678:90ab::123]/path/xxx` + * - `http://[2a00:1234:5678:90ab::123]:8080/path/xxx` + * - `http://[fe80::1234:5678:90ab%%eth0]/path/xxx` + * - `http://[fe80::1234:5678:90ab%%eth0]:8080/path/xxx` + * + * `%` may be encoded as `%25` + * + * \param[in] url URL to parse + * \param[out] hostname hostname part of the URL (size of MAXHOSTNAMELEN+1) + * \param[out] port set to the port specified in the URL or 80 + * \param[out] path set to the begining of the path part of the URL + * \param[out] scope_id set to the interface id if specified in the + * link-local IPv6 address + * \return 0 for failure, 1 for success + */ +int parseURL(const char * url, + char * hostname, unsigned short * port, char * * path, + unsigned int * scope_id); + #endif diff --git a/thirdparty/miniupnpc/src/portlistingparse.c b/thirdparty/miniupnpc/src/portlistingparse.c index 162cf8b7ec8..d28df70a59d 100644 --- a/thirdparty/miniupnpc/src/portlistingparse.c +++ b/thirdparty/miniupnpc/src/portlistingparse.c @@ -1,7 +1,7 @@ -/* $Id: portlistingparse.c,v 1.9 2015/07/15 12:41:13 nanard Exp $ */ +/* $Id: portlistingparse.c,v 1.12 2025/03/29 17:58:33 nanard Exp $ */ /* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2011-2020 Thomas Bernard + * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ + * (c) 2011-2025 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ #include @@ -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 { diff --git a/thirdparty/miniupnpc/src/receivedata.c b/thirdparty/miniupnpc/src/receivedata.c index 7f187f6e562..ef923d91d54 100644 --- a/thirdparty/miniupnpc/src/receivedata.c +++ b/thirdparty/miniupnpc/src/receivedata.c @@ -1,14 +1,15 @@ -/* $Id: receivedata.c,v 1.10 2021/03/02 23:33:07 nanard Exp $ */ +/* $Id: receivedata.c,v 1.11 2025/05/25 21:56:49 nanard Exp $ */ /* Project : miniupnp * Website : http://miniupnp.free.fr/ * Author : Thomas Bernard - * Copyright (c) 2011-2021 Thomas Bernard + * Copyright (c) 2011-2025 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ #include #include #ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN #include #include #else /* _WIN32 */ diff --git a/thirdparty/miniupnpc/src/upnpcommands.c b/thirdparty/miniupnpc/src/upnpcommands.c index 1e1ee6786f1..50560b71d7e 100644 --- a/thirdparty/miniupnpc/src/upnpcommands.c +++ b/thirdparty/miniupnpc/src/upnpcommands.c @@ -1,8 +1,8 @@ -/* $Id: upnpcommands.c,v 1.51 2019/04/23 11:45:15 nanard Exp $ */ +/* $Id: upnpcommands.c,v 1.56 2025/03/29 18:08:59 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2005-2018 Thomas Bernard + * Copyright (c) 2005-2025 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * */ @@ -14,6 +14,17 @@ #include "portlistingparse.h" #include "upnpreplyparse.h" +/*! \file upnpcommands.c + * \brief Internet Gateway Device methods implementations + * \def STRTOUI + * \brief strtoull() if available, strtol() if not + */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#define STRTOUI strtoull +#else +#define STRTOUI strtoul +#endif + static UNSIGNED_INTEGER my_atoui(const char * s) { @@ -31,7 +42,7 @@ UPNP_GetTotalBytesSent(const char * controlURL, int bufsize; unsigned int r = 0; char * p; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + if(!(buffer = simpleUPnPcommand(controlURL, servicetype, "GetTotalBytesSent", 0, &bufsize))) { return (UNSIGNED_INTEGER)UPNPCOMMAND_HTTP_ERROR; } @@ -55,7 +66,7 @@ UPNP_GetTotalBytesReceived(const char * controlURL, int bufsize; unsigned int r = 0; char * p; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + if(!(buffer = simpleUPnPcommand(controlURL, servicetype, "GetTotalBytesReceived", 0, &bufsize))) { return (UNSIGNED_INTEGER)UPNPCOMMAND_HTTP_ERROR; } @@ -79,7 +90,7 @@ UPNP_GetTotalPacketsSent(const char * controlURL, int bufsize; unsigned int r = 0; char * p; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + if(!(buffer = simpleUPnPcommand(controlURL, servicetype, "GetTotalPacketsSent", 0, &bufsize))) { return (UNSIGNED_INTEGER)UPNPCOMMAND_HTTP_ERROR; } @@ -103,7 +114,7 @@ UPNP_GetTotalPacketsReceived(const char * controlURL, int bufsize; unsigned int r = 0; char * p; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + if(!(buffer = simpleUPnPcommand(controlURL, servicetype, "GetTotalPacketsReceived", 0, &bufsize))) { return (UNSIGNED_INTEGER)UPNPCOMMAND_HTTP_ERROR; } @@ -136,7 +147,7 @@ UPNP_GetStatusInfo(const char * controlURL, if(!status && !uptime) return UPNPCOMMAND_INVALID_ARGS; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + if(!(buffer = simpleUPnPcommand(controlURL, servicetype, "GetStatusInfo", 0, &bufsize))) { return UPNPCOMMAND_HTTP_ERROR; } @@ -158,9 +169,7 @@ UPNP_GetStatusInfo(const char * controlURL, } if(uptime) { - if(up) - sscanf(up,"%u",uptime); - else + if(!up || sscanf(up,"%u",uptime) != 1) *uptime = 0; } @@ -174,8 +183,8 @@ UPNP_GetStatusInfo(const char * controlURL, p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); + if(sscanf(p, "%d", &ret) != 1) + ret = UPNPCOMMAND_UNKNOWN_ERROR; } ClearNameValueList(&pdata); return ret; @@ -197,7 +206,7 @@ UPNP_GetConnectionTypeInfo(const char * controlURL, if(!connectionType) return UPNPCOMMAND_INVALID_ARGS; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + if(!(buffer = simpleUPnPcommand(controlURL, servicetype, "GetConnectionTypeInfo", 0, &bufsize))) { return UPNPCOMMAND_HTTP_ERROR; } @@ -214,8 +223,8 @@ UPNP_GetConnectionTypeInfo(const char * controlURL, connectionType[0] = '\0'; p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); + if(sscanf(p, "%d", &ret) != 1) + ret = UPNPCOMMAND_UNKNOWN_ERROR; } ClearNameValueList(&pdata); return ret; @@ -244,7 +253,7 @@ UPNP_GetLinkLayerMaxBitRates(const char * controlURL, return UPNPCOMMAND_INVALID_ARGS; /* shouldn't we use GetCommonLinkProperties ? */ - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + if(!(buffer = simpleUPnPcommand(controlURL, servicetype, "GetCommonLinkProperties", 0, &bufsize))) { /*"GetLinkLayerMaxBitRates", 0, &bufsize);*/ return UPNPCOMMAND_HTTP_ERROR; @@ -262,22 +271,18 @@ UPNP_GetLinkLayerMaxBitRates(const char * controlURL, ret = UPNPCOMMAND_SUCCESS; if(bitrateDown) { - if(down) - sscanf(down,"%u",bitrateDown); - else + if(!down || sscanf(down,"%u",bitrateDown) != 1) *bitrateDown = 0; } if(bitrateUp) { - if(up) - sscanf(up,"%u",bitrateUp); - else + if(!up || sscanf(up,"%u",bitrateUp) != 1) *bitrateUp = 0; } p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); + if(sscanf(p, "%d", &ret) != 1) + ret = UPNPCOMMAND_UNKNOWN_ERROR; } ClearNameValueList(&pdata); return ret; @@ -309,7 +314,7 @@ UPNP_GetExternalIPAddress(const char * controlURL, if(!extIpAdd || !controlURL || !servicetype) return UPNPCOMMAND_INVALID_ARGS; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + if(!(buffer = simpleUPnPcommand(controlURL, servicetype, "GetExternalIPAddress", 0, &bufsize))) { return UPNPCOMMAND_HTTP_ERROR; } @@ -327,8 +332,8 @@ UPNP_GetExternalIPAddress(const char * controlURL, p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); + if(sscanf(p, "%d", &ret) != 1) + ret = UPNPCOMMAND_UNKNOWN_ERROR; } ClearNameValueList(&pdata); @@ -345,7 +350,17 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype, const char * remoteHost, const char * leaseDuration) { - struct UPNParg * AddPortMappingArgs; + struct UPNParg AddPortMappingArgs[] = { + {"NewRemoteHost", remoteHost}, + {"NewExternalPort", extPort}, + {"NewProtocol", proto}, + {"NewInternalPort", inPort}, + {"NewInternalClient", inClient}, + {"NewEnabled", "1"}, + {"NewPortMappingDescription", desc?desc:"libminiupnpc"}, + {"NewLeaseDuration", leaseDuration?leaseDuration:"0"}, + {NULL, NULL} + }; char * buffer; int bufsize; struct NameValueParserData pdata; @@ -355,29 +370,9 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype, if(!inPort || !inClient || !proto || !extPort) return UPNPCOMMAND_INVALID_ARGS; - AddPortMappingArgs = calloc(9, sizeof(struct UPNParg)); - if(AddPortMappingArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - AddPortMappingArgs[0].elt = "NewRemoteHost"; - AddPortMappingArgs[0].val = remoteHost; - AddPortMappingArgs[1].elt = "NewExternalPort"; - AddPortMappingArgs[1].val = extPort; - AddPortMappingArgs[2].elt = "NewProtocol"; - AddPortMappingArgs[2].val = proto; - AddPortMappingArgs[3].elt = "NewInternalPort"; - AddPortMappingArgs[3].val = inPort; - AddPortMappingArgs[4].elt = "NewInternalClient"; - AddPortMappingArgs[4].val = inClient; - AddPortMappingArgs[5].elt = "NewEnabled"; - AddPortMappingArgs[5].val = "1"; - AddPortMappingArgs[6].elt = "NewPortMappingDescription"; - AddPortMappingArgs[6].val = desc?desc:"libminiupnpc"; - AddPortMappingArgs[7].elt = "NewLeaseDuration"; - AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0"; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, + buffer = simpleUPnPcommand(controlURL, servicetype, "AddPortMapping", AddPortMappingArgs, &bufsize); - free(AddPortMappingArgs); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; } @@ -389,8 +384,8 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype, resVal = GetValueFromNameValueList(&pdata, "errorCode"); if(resVal) { /*printf("AddPortMapping errorCode = '%s'\n", resVal); */ - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); + if(sscanf(resVal, "%d", &ret) != 1) + ret = UPNPCOMMAND_UNKNOWN_ERROR; } else { ret = UPNPCOMMAND_SUCCESS; } @@ -409,39 +404,28 @@ UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype, const char * leaseDuration, char * reservedPort) { - struct UPNParg * AddPortMappingArgs; + struct UPNParg AddAnyPortMappingArgs[] = { + {"NewRemoteHost", remoteHost}, + {"NewExternalPort", extPort}, + {"NewProtocol", proto}, + {"NewInternalPort", inPort}, + {"NewInternalClient", inClient}, + {"NewEnabled", "1"}, + {"NewPortMappingDescription", desc?desc:"libminiupnpc"}, + {"NewLeaseDuration", leaseDuration?leaseDuration:"0"}, + {NULL, NULL} + }; char * buffer; int bufsize; struct NameValueParserData pdata; const char * resVal; int ret; - if(!inPort || !inClient || !proto || !extPort) + if(!inPort || !inClient || !proto || !extPort || !reservedPort) return UPNPCOMMAND_INVALID_ARGS; - - AddPortMappingArgs = calloc(9, sizeof(struct UPNParg)); - if(AddPortMappingArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - AddPortMappingArgs[0].elt = "NewRemoteHost"; - AddPortMappingArgs[0].val = remoteHost; - AddPortMappingArgs[1].elt = "NewExternalPort"; - AddPortMappingArgs[1].val = extPort; - AddPortMappingArgs[2].elt = "NewProtocol"; - AddPortMappingArgs[2].val = proto; - AddPortMappingArgs[3].elt = "NewInternalPort"; - AddPortMappingArgs[3].val = inPort; - AddPortMappingArgs[4].elt = "NewInternalClient"; - AddPortMappingArgs[4].val = inClient; - AddPortMappingArgs[5].elt = "NewEnabled"; - AddPortMappingArgs[5].val = "1"; - AddPortMappingArgs[6].elt = "NewPortMappingDescription"; - AddPortMappingArgs[6].val = desc?desc:"libminiupnpc"; - AddPortMappingArgs[7].elt = "NewLeaseDuration"; - AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0"; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "AddAnyPortMapping", AddPortMappingArgs, + buffer = simpleUPnPcommand(controlURL, servicetype, + "AddAnyPortMapping", AddAnyPortMappingArgs, &bufsize); - free(AddPortMappingArgs); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; } @@ -449,8 +433,8 @@ UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype, free(buffer); resVal = GetValueFromNameValueList(&pdata, "errorCode"); if(resVal) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); + if(sscanf(resVal, "%d", &ret) != 1) + ret = UPNPCOMMAND_UNKNOWN_ERROR; } else { char *p; @@ -473,7 +457,12 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, const char * remoteHost) { /*struct NameValueParserData pdata;*/ - struct UPNParg * DeletePortMappingArgs; + struct UPNParg DeletePortMappingArgs[] = { + {"NewRemoteHost", remoteHost}, + {"NewExternalPort", extPort}, + {"NewProtocol", proto}, + {NULL, NULL} + }; char * buffer; int bufsize; struct NameValueParserData pdata; @@ -483,19 +472,9 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, if(!extPort || !proto) return UPNPCOMMAND_INVALID_ARGS; - DeletePortMappingArgs = calloc(4, sizeof(struct UPNParg)); - if(DeletePortMappingArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - DeletePortMappingArgs[0].elt = "NewRemoteHost"; - DeletePortMappingArgs[0].val = remoteHost; - DeletePortMappingArgs[1].elt = "NewExternalPort"; - DeletePortMappingArgs[1].val = extPort; - DeletePortMappingArgs[2].elt = "NewProtocol"; - DeletePortMappingArgs[2].val = proto; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, + buffer = simpleUPnPcommand(controlURL, servicetype, "DeletePortMapping", DeletePortMappingArgs, &bufsize); - free(DeletePortMappingArgs); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; } @@ -504,8 +483,8 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, free(buffer); resVal = GetValueFromNameValueList(&pdata, "errorCode"); if(resVal) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); + if(sscanf(resVal, "%d", &ret) != 1) + ret = UPNPCOMMAND_UNKNOWN_ERROR; } else { ret = UPNPCOMMAND_SUCCESS; } @@ -515,11 +494,17 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, MINIUPNP_LIBSPEC int UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype, - const char * extPortStart, const char * extPortEnd, - const char * proto, - const char * manage) + const char * extPortStart, const char * extPortEnd, + const char * proto, + const char * manage) { - struct UPNParg * DeletePortMappingArgs; + struct UPNParg DeletePortMappingRangeArgs[] = { + {"NewStartPort", extPortStart}, + {"NewEndPort", extPortEnd}, + {"NewProtocol", proto}, + {"NewManage", manage}, + {NULL, NULL} + }; char * buffer; int bufsize; struct NameValueParserData pdata; @@ -529,22 +514,10 @@ UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype, if(!extPortStart || !extPortEnd || !proto || !manage) return UPNPCOMMAND_INVALID_ARGS; - DeletePortMappingArgs = calloc(5, sizeof(struct UPNParg)); - if(DeletePortMappingArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - DeletePortMappingArgs[0].elt = "NewStartPort"; - DeletePortMappingArgs[0].val = extPortStart; - DeletePortMappingArgs[1].elt = "NewEndPort"; - DeletePortMappingArgs[1].val = extPortEnd; - DeletePortMappingArgs[2].elt = "NewProtocol"; - DeletePortMappingArgs[2].val = proto; - DeletePortMappingArgs[3].elt = "NewManage"; - DeletePortMappingArgs[3].val = manage; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, + buffer = simpleUPnPcommand(controlURL, servicetype, "DeletePortMappingRange", - DeletePortMappingArgs, &bufsize); - free(DeletePortMappingArgs); + DeletePortMappingRangeArgs, &bufsize); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; } @@ -552,8 +525,8 @@ UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype, free(buffer); resVal = GetValueFromNameValueList(&pdata, "errorCode"); if(resVal) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); + if(sscanf(resVal, "%d", &ret) != 1) + ret = UPNPCOMMAND_UNKNOWN_ERROR; } else { ret = UPNPCOMMAND_SUCCESS; } @@ -564,35 +537,51 @@ UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype, MINIUPNP_LIBSPEC int UPNP_GetGenericPortMappingEntry(const char * controlURL, const char * servicetype, - const char * index, - char * extPort, - char * intClient, - char * intPort, - char * protocol, - char * desc, - char * enabled, - char * rHost, - char * duration) + const char * index, + char * extPort, + char * intClient, + char * intPort, + char * protocol, + char * desc, + char * enabled, + char * rHost, + char * duration) +{ + return UPNP_GetGenericPortMappingEntryExt(controlURL, servicetype, index, + extPort, intClient, intPort, + protocol, desc, 80, enabled, + rHost, 64, duration); +} + +MINIUPNP_LIBSPEC int +UPNP_GetGenericPortMappingEntryExt(const char * controlURL, + const char * servicetype, + const char * index, + char * extPort, + char * intClient, + char * intPort, + char * protocol, + char * desc, + size_t desclen, + char * enabled, + char * rHost, + size_t rHostlen, + char * duration) { struct NameValueParserData pdata; - struct UPNParg * GetPortMappingArgs; + struct UPNParg GetPortMappingArgs[] = { + {"NewPortMappingIndex", index}, + {NULL, NULL} + }; char * buffer; int bufsize; char * p; - int r = UPNPCOMMAND_UNKNOWN_ERROR; - if(!index) + int ret = UPNPCOMMAND_UNKNOWN_ERROR; + if(!index || !extPort || !intClient || !intPort || !protocol) return UPNPCOMMAND_INVALID_ARGS; - intClient[0] = '\0'; - intPort[0] = '\0'; - GetPortMappingArgs = calloc(2, sizeof(struct UPNParg)); - if(GetPortMappingArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - GetPortMappingArgs[0].elt = "NewPortMappingIndex"; - GetPortMappingArgs[0].val = index; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, + buffer = simpleUPnPcommand(controlURL, servicetype, "GetGenericPortMappingEntry", GetPortMappingArgs, &bufsize); - free(GetPortMappingArgs); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; } @@ -602,28 +591,40 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL, p = GetValueFromNameValueList(&pdata, "NewRemoteHost"); if(p && rHost) { - strncpy(rHost, p, 64); - rHost[63] = '\0'; + strncpy(rHost, p, rHostlen); + rHost[rHostlen-1] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewExternalPort"); - if(p && extPort) + if(p) { strncpy(extPort, p, 6); extPort[5] = '\0'; - r = UPNPCOMMAND_SUCCESS; + ret = UPNPCOMMAND_SUCCESS; + } + else + { + extPort[0] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewProtocol"); - if(p && protocol) + if(p) { strncpy(protocol, p, 4); protocol[3] = '\0'; } + else + { + protocol[0] = '\0'; + } p = GetValueFromNameValueList(&pdata, "NewInternalClient"); if(p) { strncpy(intClient, p, 16); intClient[15] = '\0'; - r = 0; + ret = 0; + } + else + { + intClient[0] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewInternalPort"); if(p) @@ -631,6 +632,10 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL, strncpy(intPort, p, 6); intPort[5] = '\0'; } + else + { + intPort[0] = '\0'; + } p = GetValueFromNameValueList(&pdata, "NewEnabled"); if(p && enabled) { @@ -640,8 +645,8 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL, p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription"); if(p && desc) { - strncpy(desc, p, 80); - desc[79] = '\0'; + strncpy(desc, p, desclen); + desc[desclen-1] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewLeaseDuration"); if(p && duration) @@ -651,11 +656,11 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL, } p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { - r = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &r); + if(sscanf(p, "%d", &ret) != 1) + ret = UPNPCOMMAND_UNKNOWN_ERROR; } ClearNameValueList(&pdata); - return r; + return ret; } MINIUPNP_LIBSPEC int @@ -663,12 +668,12 @@ UPNP_GetPortMappingNumberOfEntries(const char * controlURL, const char * servicetype, unsigned int * numEntries) { - struct NameValueParserData pdata; - char * buffer; - int bufsize; - char* p; + struct NameValueParserData pdata; + char * buffer; + int bufsize; + char* p; int ret = UPNPCOMMAND_UNKNOWN_ERROR; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + if(!(buffer = simpleUPnPcommand(controlURL, servicetype, "GetPortMappingNumberOfEntries", 0, &bufsize))) { return UPNPCOMMAND_HTTP_ERROR; @@ -676,23 +681,23 @@ UPNP_GetPortMappingNumberOfEntries(const char * controlURL, #ifdef DEBUG DisplayNameValueList(buffer, bufsize); #endif - ParseNameValue(buffer, bufsize, &pdata); + ParseNameValue(buffer, bufsize, &pdata); free(buffer); - p = GetValueFromNameValueList(&pdata, "NewPortMappingNumberOfEntries"); - if(numEntries && p) { + p = GetValueFromNameValueList(&pdata, "NewPortMappingNumberOfEntries"); + if(numEntries && p) { *numEntries = 0; - sscanf(p, "%u", numEntries); + sscanf(p, "%u", numEntries); ret = UPNPCOMMAND_SUCCESS; - } + } p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); + if(sscanf(p, "%d", &ret) != 1) + ret = UPNPCOMMAND_UNKNOWN_ERROR; } - ClearNameValueList(&pdata); + ClearNameValueList(&pdata); return ret; } @@ -710,9 +715,34 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL, char * desc, char * enabled, char * leaseDuration) +{ + return UPNP_GetSpecificPortMappingEntryExt(controlURL, servicetype, + extPort, proto, remoteHost, + intClient, intPort, + desc, 80, enabled, + leaseDuration); +} + +MINIUPNP_LIBSPEC int +UPNP_GetSpecificPortMappingEntryExt(const char * controlURL, + const char * servicetype, + const char * extPort, + const char * proto, + const char * remoteHost, + char * intClient, + char * intPort, + char * desc, + size_t desclen, + char * enabled, + char * leaseDuration) { struct NameValueParserData pdata; - struct UPNParg * GetPortMappingArgs; + struct UPNParg GetPortMappingArgs[] = { + {"NewRemoteHost", remoteHost}, + {"NewExternalPort", extPort}, + {"NewProtocol", proto}, + {NULL, NULL} + }; char * buffer; int bufsize; char * p; @@ -721,19 +751,9 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL, if(!intPort || !intClient || !extPort || !proto) return UPNPCOMMAND_INVALID_ARGS; - GetPortMappingArgs = calloc(4, sizeof(struct UPNParg)); - if(GetPortMappingArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - GetPortMappingArgs[0].elt = "NewRemoteHost"; - GetPortMappingArgs[0].val = remoteHost; - GetPortMappingArgs[1].elt = "NewExternalPort"; - GetPortMappingArgs[1].val = extPort; - GetPortMappingArgs[2].elt = "NewProtocol"; - GetPortMappingArgs[2].val = proto; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, + buffer = simpleUPnPcommand(controlURL, servicetype, "GetSpecificPortMappingEntry", GetPortMappingArgs, &bufsize); - free(GetPortMappingArgs); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; } @@ -764,8 +784,8 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL, p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription"); if(p && desc) { - strncpy(desc, p, 80); - desc[79] = '\0'; + strncpy(desc, p, desclen); + desc[desclen-1] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewLeaseDuration"); @@ -777,8 +797,8 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL, p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); + if(sscanf(p, "%d", &ret) != 1) + ret = UPNPCOMMAND_UNKNOWN_ERROR; } ClearNameValueList(&pdata); @@ -803,7 +823,14 @@ UPNP_GetListOfPortMappings(const char * controlURL, struct PortMappingParserData * data) { struct NameValueParserData pdata; - struct UPNParg * GetListOfPortMappingsArgs; + struct UPNParg GetListOfPortMappingsArgs[] = { + {"NewStartPort", startPort}, + {"NewEndPort", endPort}, + {"NewProtocol", protocol}, + {"NewManage", "1"}, + {"NewNumberOfPorts", numberOfPorts?numberOfPorts:"1000"}, + {NULL, NULL} + }; const char * p; char * buffer; int bufsize; @@ -812,24 +839,9 @@ UPNP_GetListOfPortMappings(const char * controlURL, if(!startPort || !endPort || !protocol) return UPNPCOMMAND_INVALID_ARGS; - GetListOfPortMappingsArgs = calloc(6, sizeof(struct UPNParg)); - if(GetListOfPortMappingsArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - GetListOfPortMappingsArgs[0].elt = "NewStartPort"; - GetListOfPortMappingsArgs[0].val = startPort; - GetListOfPortMappingsArgs[1].elt = "NewEndPort"; - GetListOfPortMappingsArgs[1].val = endPort; - GetListOfPortMappingsArgs[2].elt = "NewProtocol"; - GetListOfPortMappingsArgs[2].val = protocol; - GetListOfPortMappingsArgs[3].elt = "NewManage"; - GetListOfPortMappingsArgs[3].val = "1"; - GetListOfPortMappingsArgs[4].elt = "NewNumberOfPorts"; - GetListOfPortMappingsArgs[4].val = numberOfPorts?numberOfPorts:"1000"; - - buffer = simpleUPnPcommand(-1, controlURL, servicetype, + buffer = simpleUPnPcommand(controlURL, servicetype, "GetListOfPortMappings", GetListOfPortMappingsArgs, &bufsize); - free(GetListOfPortMappingsArgs); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; } @@ -866,8 +878,8 @@ UPNP_GetListOfPortMappings(const char * controlURL, p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); + if(sscanf(p, "%d", &ret) != 1) + ret = UPNPCOMMAND_UNKNOWN_ERROR; } ClearNameValueList(&pdata); @@ -892,7 +904,7 @@ UPNP_GetFirewallStatus(const char * controlURL, if(!firewallEnabled || !inboundPinholeAllowed) return UPNPCOMMAND_INVALID_ARGS; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, + buffer = simpleUPnPcommand(controlURL, servicetype, "GetFirewallStatus", 0, &bufsize); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; @@ -914,8 +926,8 @@ UPNP_GetFirewallStatus(const char * controlURL, p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); + if(sscanf(p, "%d", &ret) != 1) + ret = UPNPCOMMAND_UNKNOWN_ERROR; } ClearNameValueList(&pdata); return ret; @@ -930,7 +942,14 @@ UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype const char * proto, int * opTimeout) { - struct UPNParg * GetOutboundPinholeTimeoutArgs; + struct UPNParg GetOutboundPinholeTimeoutArgs[] = { + {"RemoteHost", remoteHost}, + {"RemotePort", remotePort}, + {"Protocol", proto}, + {"InternalPort", intPort}, + {"InternalClient", intClient}, + {NULL, NULL} + }; char * buffer; int bufsize; struct NameValueParserData pdata; @@ -940,22 +959,8 @@ UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype if(!intPort || !intClient || !proto || !remotePort || !remoteHost) return UPNPCOMMAND_INVALID_ARGS; - GetOutboundPinholeTimeoutArgs = calloc(6, sizeof(struct UPNParg)); - if(GetOutboundPinholeTimeoutArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - GetOutboundPinholeTimeoutArgs[0].elt = "RemoteHost"; - GetOutboundPinholeTimeoutArgs[0].val = remoteHost; - GetOutboundPinholeTimeoutArgs[1].elt = "RemotePort"; - GetOutboundPinholeTimeoutArgs[1].val = remotePort; - GetOutboundPinholeTimeoutArgs[2].elt = "Protocol"; - GetOutboundPinholeTimeoutArgs[2].val = proto; - GetOutboundPinholeTimeoutArgs[3].elt = "InternalPort"; - GetOutboundPinholeTimeoutArgs[3].val = intPort; - GetOutboundPinholeTimeoutArgs[4].elt = "InternalClient"; - GetOutboundPinholeTimeoutArgs[4].val = intClient; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, + buffer = simpleUPnPcommand(controlURL, servicetype, "GetOutboundPinholeTimeout", GetOutboundPinholeTimeoutArgs, &bufsize); - free(GetOutboundPinholeTimeoutArgs); if(!buffer) return UPNPCOMMAND_HTTP_ERROR; ParseNameValue(buffer, bufsize, &pdata); @@ -963,8 +968,8 @@ UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype resVal = GetValueFromNameValueList(&pdata, "errorCode"); if(resVal) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); + if(sscanf(resVal, "%d", &ret) != 1) + ret = UPNPCOMMAND_UNKNOWN_ERROR; } else { @@ -987,7 +992,15 @@ UPNP_AddPinhole(const char * controlURL, const char * servicetype, const char * leaseTime, char * uniqueID) { - struct UPNParg * AddPinholeArgs; + struct UPNParg AddPinholeArgs[] = { + {"RemoteHost", ""}, + {"RemotePort", remotePort}, + {"Protocol", proto}, + {"InternalPort", intPort}, + {"InternalClient", ""}, + {"LeaseTime", leaseTime}, + {NULL, NULL} + }; char * buffer; int bufsize; struct NameValueParserData pdata; @@ -998,41 +1011,14 @@ UPNP_AddPinhole(const char * controlURL, const char * servicetype, if(!intPort || !intClient || !proto || !remoteHost || !remotePort || !leaseTime) return UPNPCOMMAND_INVALID_ARGS; - AddPinholeArgs = calloc(7, sizeof(struct UPNParg)); - if(AddPinholeArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - /* RemoteHost can be wilcarded */ - if(strncmp(remoteHost, "empty", 5)==0) - { - AddPinholeArgs[0].elt = "RemoteHost"; - AddPinholeArgs[0].val = ""; - } - else - { - AddPinholeArgs[0].elt = "RemoteHost"; + /* RemoteHost and InternalClient can be wilcarded + * accept both the empty string and "empty" as wildcard */ + if(strncmp(remoteHost, "empty", 5) != 0) AddPinholeArgs[0].val = remoteHost; - } - AddPinholeArgs[1].elt = "RemotePort"; - AddPinholeArgs[1].val = remotePort; - AddPinholeArgs[2].elt = "Protocol"; - AddPinholeArgs[2].val = proto; - AddPinholeArgs[3].elt = "InternalPort"; - AddPinholeArgs[3].val = intPort; - if(strncmp(intClient, "empty", 5)==0) - { - AddPinholeArgs[4].elt = "InternalClient"; - AddPinholeArgs[4].val = ""; - } - else - { - AddPinholeArgs[4].elt = "InternalClient"; + if(strncmp(intClient, "empty", 5) != 0) AddPinholeArgs[4].val = intClient; - } - AddPinholeArgs[5].elt = "LeaseTime"; - AddPinholeArgs[5].val = leaseTime; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, + buffer = simpleUPnPcommand(controlURL, servicetype, "AddPinhole", AddPinholeArgs, &bufsize); - free(AddPinholeArgs); if(!buffer) return UPNPCOMMAND_HTTP_ERROR; ParseNameValue(buffer, bufsize, &pdata); @@ -1047,8 +1033,8 @@ UPNP_AddPinhole(const char * controlURL, const char * servicetype, if(resVal) { /*printf("AddPortMapping errorCode = '%s'\n", resVal);*/ - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); + if(sscanf(resVal, "%d", &ret) != 1) + ret = UPNPCOMMAND_UNKNOWN_ERROR; } else { @@ -1063,7 +1049,11 @@ UPNP_UpdatePinhole(const char * controlURL, const char * servicetype, const char * uniqueID, const char * leaseTime) { - struct UPNParg * UpdatePinholeArgs; + struct UPNParg UpdatePinholeArgs[] = { + {"UniqueID", uniqueID}, + {"NewLeaseTime", leaseTime}, + {NULL, NULL} + }; char * buffer; int bufsize; struct NameValueParserData pdata; @@ -1073,16 +1063,8 @@ UPNP_UpdatePinhole(const char * controlURL, const char * servicetype, if(!uniqueID || !leaseTime) return UPNPCOMMAND_INVALID_ARGS; - UpdatePinholeArgs = calloc(3, sizeof(struct UPNParg)); - if(UpdatePinholeArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - UpdatePinholeArgs[0].elt = "UniqueID"; - UpdatePinholeArgs[0].val = uniqueID; - UpdatePinholeArgs[1].elt = "NewLeaseTime"; - UpdatePinholeArgs[1].val = leaseTime; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, + buffer = simpleUPnPcommand(controlURL, servicetype, "UpdatePinhole", UpdatePinholeArgs, &bufsize); - free(UpdatePinholeArgs); if(!buffer) return UPNPCOMMAND_HTTP_ERROR; ParseNameValue(buffer, bufsize, &pdata); @@ -1091,8 +1073,8 @@ UPNP_UpdatePinhole(const char * controlURL, const char * servicetype, if(resVal) { /*printf("AddPortMapping errorCode = '%s'\n", resVal); */ - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); + if(sscanf(resVal, "%d", &ret) != 1) + ret = UPNPCOMMAND_UNKNOWN_ERROR; } else { @@ -1106,7 +1088,10 @@ MINIUPNP_LIBSPEC int UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID) { /*struct NameValueParserData pdata;*/ - struct UPNParg * DeletePinholeArgs; + struct UPNParg DeletePinholeArgs[] = { + {"UniqueID", uniqueID}, + {NULL, NULL} + }; char * buffer; int bufsize; struct NameValueParserData pdata; @@ -1116,14 +1101,8 @@ UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char if(!uniqueID) return UPNPCOMMAND_INVALID_ARGS; - DeletePinholeArgs = calloc(2, sizeof(struct UPNParg)); - if(DeletePinholeArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - DeletePinholeArgs[0].elt = "UniqueID"; - DeletePinholeArgs[0].val = uniqueID; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, + buffer = simpleUPnPcommand(controlURL, servicetype, "DeletePinhole", DeletePinholeArgs, &bufsize); - free(DeletePinholeArgs); if(!buffer) return UPNPCOMMAND_HTTP_ERROR; /*DisplayNameValueList(buffer, bufsize);*/ @@ -1132,8 +1111,8 @@ UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char resVal = GetValueFromNameValueList(&pdata, "errorCode"); if(resVal) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); + if(sscanf(resVal, "%d", &ret) != 1) + ret = UPNPCOMMAND_UNKNOWN_ERROR; } else { @@ -1148,7 +1127,10 @@ UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype, const char * uniqueID, int * isWorking) { struct NameValueParserData pdata; - struct UPNParg * CheckPinholeWorkingArgs; + struct UPNParg CheckPinholeWorkingArgs[] = { + {"UniqueID", uniqueID}, + {NULL, NULL} + }; char * buffer; int bufsize; char * p; @@ -1157,14 +1139,8 @@ UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype, if(!uniqueID) return UPNPCOMMAND_INVALID_ARGS; - CheckPinholeWorkingArgs = calloc(4, sizeof(struct UPNParg)); - if(CheckPinholeWorkingArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - CheckPinholeWorkingArgs[0].elt = "UniqueID"; - CheckPinholeWorkingArgs[0].val = uniqueID; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, + buffer = simpleUPnPcommand(controlURL, servicetype, "CheckPinholeWorking", CheckPinholeWorkingArgs, &bufsize); - free(CheckPinholeWorkingArgs); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; @@ -1184,8 +1160,8 @@ UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype, p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); + if(sscanf(p, "%d", &ret) != 1) + ret = UPNPCOMMAND_UNKNOWN_ERROR; } ClearNameValueList(&pdata); @@ -1197,7 +1173,10 @@ UPNP_GetPinholePackets(const char * controlURL, const char * servicetype, const char * uniqueID, int * packets) { struct NameValueParserData pdata; - struct UPNParg * GetPinholePacketsArgs; + struct UPNParg GetPinholePacketsArgs[] = { + {"UniqueID", uniqueID}, + {NULL, NULL} + }; char * buffer; int bufsize; char * p; @@ -1206,14 +1185,8 @@ UPNP_GetPinholePackets(const char * controlURL, const char * servicetype, if(!uniqueID) return UPNPCOMMAND_INVALID_ARGS; - GetPinholePacketsArgs = calloc(4, sizeof(struct UPNParg)); - if(GetPinholePacketsArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - GetPinholePacketsArgs[0].elt = "UniqueID"; - GetPinholePacketsArgs[0].val = uniqueID; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, + buffer = simpleUPnPcommand(controlURL, servicetype, "GetPinholePackets", GetPinholePacketsArgs, &bufsize); - free(GetPinholePacketsArgs); if(!buffer) return UPNPCOMMAND_HTTP_ERROR; ParseNameValue(buffer, bufsize, &pdata); @@ -1229,8 +1202,8 @@ UPNP_GetPinholePackets(const char * controlURL, const char * servicetype, p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); + if(sscanf(p, "%d", &ret) != 1) + ret = UPNPCOMMAND_UNKNOWN_ERROR; } ClearNameValueList(&pdata); diff --git a/thirdparty/miniupnpc/src/upnpreplyparse.c b/thirdparty/miniupnpc/src/upnpreplyparse.c index 4d06f0585d8..24a5f1670a7 100644 --- a/thirdparty/miniupnpc/src/upnpreplyparse.c +++ b/thirdparty/miniupnpc/src/upnpreplyparse.c @@ -1,8 +1,8 @@ -/* $Id: upnpreplyparse.c,v 1.20 2017/12/12 11:26:25 nanard Exp $ */ +/* $Id: upnpreplyparse.c,v 1.22 2025/02/08 23:12:26 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2019 Thomas Bernard + * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ + * (c) 2006-2025 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -13,6 +13,23 @@ #include "upnpreplyparse.h" #include "minixml.h" +struct NameValue { + /*! \brief pointer to the next element */ + struct NameValue * l_next; + /*! \brief name */ + char name[64]; +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + /* C99 flexible array member */ + /*! \brief character value */ + char value[]; +#elif defined(__GNUC__) + char value[0]; +#else + /* Fallback to a hack */ + char value[1]; +#endif +}; + static void NameValueParserStartElt(void * d, const char * name, int l) { @@ -40,7 +57,7 @@ NameValueParserEndElt(void * d, const char * name, int namelen) int l; /* standard case. Limited to n chars strings */ l = data->cdatalen; - nv = malloc(sizeof(struct NameValue)); + nv = malloc(sizeof(struct NameValue) + l + 1); if(nv == NULL) { /* malloc error */ @@ -50,8 +67,6 @@ NameValueParserEndElt(void * d, const char * name, int namelen) #endif /* DEBUG */ return; } - if(l>=(int)sizeof(nv->value)) - l = sizeof(nv->value) - 1; strncpy(nv->name, data->curelt, 64); nv->name[63] = '\0'; if(data->cdata != NULL) @@ -137,7 +152,7 @@ ClearNameValueList(struct NameValueParserData * pdata) char * GetValueFromNameValueList(struct NameValueParserData * pdata, - const char * Name) + const char * name) { struct NameValue * nv; char * p = NULL; @@ -145,37 +160,12 @@ GetValueFromNameValueList(struct NameValueParserData * pdata, (nv != NULL) && (p == NULL); nv = nv->l_next) { - if(strcmp(nv->name, Name) == 0) + if(strcmp(nv->name, name) == 0) p = nv->value; } return p; } -#if 0 -/* useless now that minixml ignores namespaces by itself */ -char * -GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, - const char * Name) -{ - struct NameValue * nv; - char * p = NULL; - char * pname; - for(nv = pdata->head.lh_first; - (nv != NULL) && (p == NULL); - nv = nv->entries.le_next) - { - pname = strrchr(nv->name, ':'); - if(pname) - pname++; - else - pname = nv->name; - if(strcmp(pname, Name)==0) - p = nv->value; - } - return p; -} -#endif - /* debug all-in-one function * do parsing then display to stdout */ #ifdef DEBUG