- added support for miniupnpc 1.9, this fixes #79 (cherry-pick to develop & RC)

This commit is contained in:
SoftCoder 2015-10-21 18:11:19 -07:00 committed by filux
parent 41baf43bf5
commit 75077c4a50
50 changed files with 2419 additions and 1090 deletions

View File

@ -19,11 +19,12 @@ CMAKE_ONLY=0
MAKE_ONLY=0 MAKE_ONLY=0
CLANG_FORCED=0 CLANG_FORCED=0
WANT_STATIC_LIBS="-DWANT_STATIC_LIBS=ON" WANT_STATIC_LIBS="-DWANT_STATIC_LIBS=ON"
FORCE_EMBEDDED_LIBS=0
LUA_FORCED_VERSION=0 LUA_FORCED_VERSION=0
FORCE_32BIT_CROSS_COMPILE=0 FORCE_32BIT_CROSS_COMPILE=0
BUILD_MEGAGLEST_TESTS="ON" BUILD_MEGAGLEST_TESTS="ON"
while getopts "c:dfhl:mnx" option; do while getopts "c:defhl:mnx" option; do
case "${option}" in case "${option}" in
c) c)
CPU_COUNT=${OPTARG} CPU_COUNT=${OPTARG}
@ -31,6 +32,10 @@ while getopts "c:dfhl:mnx" option; do
;; ;;
d) d)
WANT_STATIC_LIBS="-DWANT_STATIC_LIBS=OFF" WANT_STATIC_LIBS="-DWANT_STATIC_LIBS=OFF"
# echo "${option} value: ${OPTARG}"
;;
e)
FORCE_EMBEDDED_LIBS=1
# echo "${option} value: ${OPTARG}" # echo "${option} value: ${OPTARG}"
;; ;;
f) f)
@ -39,10 +44,11 @@ while getopts "c:dfhl:mnx" option; do
;; ;;
h) h)
echo "Usage: $0 <option>" echo "Usage: $0 <option>"
echo " where <option> can be: -c x, -d, -f, -m, -n, -h, -l x, -x" echo " where <option> can be: -c x, -d, -e, -f, -m, -n, -h, -l x, -x"
echo " option descriptions:" echo " option descriptions:"
echo " -c x : Force the cpu / cores count to x - example: -c 4" echo " -c x : Force the cpu / cores count to x - example: -c 4"
echo " -d : Force DYNAMIC compile (do not want static libs)" echo " -d : Force DYNAMIC compile (do not want static libs)"
echo " -e : Force compile with EMBEDDED libraries"
echo " -f : Force using CLANG compiler" echo " -f : Force using CLANG compiler"
echo " -l x : Force using LUA version x - example: -l 5.3" echo " -l x : Force using LUA version x - example: -l 5.3"
echo " -m : Force running CMAKE only to create Make files (do not compile)" echo " -m : Force running CMAKE only to create Make files (do not compile)"
@ -227,6 +233,10 @@ if [ "$LUA_FORCED_VERSION" != "0" ] && [ "$LUA_FORCED_VERSION" != "" ]; then
#echo "USER WANTS TO FORCE USE of LUA $LUA_FORCED_VERSION" #echo "USER WANTS TO FORCE USE of LUA $LUA_FORCED_VERSION"
fi fi
if [ "$FORCE_EMBEDDED_LIBS" != "0" ] && [ "$FORCE_EMBEDDED_LIBS" != "" ]; then
EXTRA_CMAKE_OPTIONS="${EXTRA_CMAKE_OPTIONS} -DFORCE_EMBEDDED_LIBS=ON"
fi
if [ $FORCE_32BIT_CROSS_COMPILE != 0 ]; then if [ $FORCE_32BIT_CROSS_COMPILE != 0 ]; then
EXTRA_CMAKE_OPTIONS="${EXTRA_CMAKE_OPTIONS} -DCMAKE_TOOLCHAIN_FILE=../mk/cmake/Modules/Toolchain-linux32.cmake" EXTRA_CMAKE_OPTIONS="${EXTRA_CMAKE_OPTIONS} -DCMAKE_TOOLCHAIN_FILE=../mk/cmake/Modules/Toolchain-linux32.cmake"
@ -261,4 +271,3 @@ else
echo 'Or change into mk/linux and run it from there:' echo 'Or change into mk/linux and run it from there:'
echo ' ./megaglest --ini-path=./ --data-path=./' echo ' ./megaglest --ini-path=./ --data-path=./'
fi fi

View File

@ -16,19 +16,22 @@ MAKE_ONLY=0
USE_XCODE=0 USE_XCODE=0
CLANG_FORCED=0 CLANG_FORCED=0
WANT_STATIC_LIBS="-DWANT_STATIC_LIBS=ON" WANT_STATIC_LIBS="-DWANT_STATIC_LIBS=ON"
FORCE_EMBEDDED_LIBS=0
LUA_FORCED_VERSION=0 LUA_FORCED_VERSION=0
while getopts "c:dfhl:mnxb" option; do while getopts "c:defhl:mnxb" option; do
case "${option}" in case "${option}" in
c) CPU_COUNT=${OPTARG};; c) CPU_COUNT=${OPTARG};;
d) WANT_STATIC_LIBS="-DWANT_STATIC_LIBS=OFF";; d) WANT_STATIC_LIBS="-DWANT_STATIC_LIBS=OFF";;
e) FORCE_EMBEDDED_LIBS=1;;
f) CLANG_FORCED=1;; f) CLANG_FORCED=1;;
h) echo "Usage: $0 <option>" h) echo "Usage: $0 <option>"
echo " where <option> can be: -b, -c x, -d, -f, -m, -n, -h, -l x, -x" echo " where <option> can be: -b, -c x, -d, -e, -f, -m, -n, -h, -l x, -x"
echo " option descriptions:" echo " option descriptions:"
echo " -b : Force default configuration designed for bundle/release." echo " -b : Force default configuration designed for bundle/release."
echo " -c x : Force the cpu / cores count to x - example: -c 4" echo " -c x : Force the cpu / cores count to x - example: -c 4"
echo " -d : Force DYNAMIC compile (do not want static libs)" echo " -d : Force DYNAMIC compile (do not want static libs)"
echo " -e : Force compile with EMBEDDED libraries"
echo " -f : Force using Clang compiler" echo " -f : Force using Clang compiler"
echo " -l x : Force using LUA version x - example: -l 5.3" echo " -l x : Force using LUA version x - example: -l 5.3"
echo " -m : Force running CMAKE only to create Make files (do not compile)" echo " -m : Force running CMAKE only to create Make files (do not compile)"
@ -172,6 +175,10 @@ if [ "$LUA_FORCED_VERSION" != "0" ] && [ "$LUA_FORCED_VERSION" != "" ]; then
#echo "USER WANTS TO FORCE USE of LUA $LUA_FORCED_VERSION" #echo "USER WANTS TO FORCE USE of LUA $LUA_FORCED_VERSION"
fi fi
if [ "$FORCE_EMBEDDED_LIBS" != "0" ] && [ "$FORCE_EMBEDDED_LIBS" != "" ]; then
EXTRA_CMAKE_OPTIONS="${EXTRA_CMAKE_OPTIONS} -DFORCE_EMBEDDED_LIBS=ON"
fi
if [ "$MAKE_ONLY" -eq "0" ]; then if [ "$MAKE_ONLY" -eq "0" ]; then
EXTRA_CMAKE_OPTIONS="${EXTRA_CMAKE_OPTIONS} -DWANT_DEV_OUTPATH=ON $WANT_STATIC_LIBS -DBREAKPAD_ROOT=$BREAKPAD_ROOT" EXTRA_CMAKE_OPTIONS="${EXTRA_CMAKE_OPTIONS} -DWANT_DEV_OUTPATH=ON $WANT_STATIC_LIBS -DBREAKPAD_ROOT=$BREAKPAD_ROOT"
if [ "$BUILD_BUNDLE" -ne "1" ]; then if [ "$BUILD_BUNDLE" -ne "1" ]; then

View File

@ -253,10 +253,15 @@ IF(BUILD_MEGAGLEST_MODEL_VIEWER OR BUILD_MEGAGLEST_MAP_EDITOR OR BUILD_MEGAGLEST
#IF(NOT WANT_STATIC_LIBS) #IF(NOT WANT_STATIC_LIBS)
#MESSAGE(STATUS "*** Searching for miniupnpc since WANT_STATIC_LIBS is off ...") #MESSAGE(STATUS "*** Searching for miniupnpc since WANT_STATIC_LIBS is off ...")
#MESSAGE(STATUS "*** Searching for miniupnpc ...") #MESSAGE(STATUS "*** Searching for miniupnpc ...")
OPTION(FORCE_USE_EMBEDDED_Miniupnpc "Use embedded to source code version of miniupnpc" OFF) OPTION(FORCE_EMBEDDED_LIBS "Force use of embedded libraries' code." OFF)
IF(NOT FORCE_USE_EMBEDDED_Miniupnpc) IF(FORCE_EMBEDDED_LIBS)
SET(FORCE_USE_EMBEDDED_Miniupnpc ON)
ELSE()
OPTION(FORCE_USE_EMBEDDED_Miniupnpc "Use embedded to source code version of miniupnpc" OFF)
ENDIF()
IF(NOT FORCE_USE_EMBEDDED_Miniupnpc)
FIND_PACKAGE(Miniupnpc) FIND_PACKAGE(Miniupnpc)
ENDIF() ENDIF()
@ -264,7 +269,7 @@ IF(BUILD_MEGAGLEST_MODEL_VIEWER OR BUILD_MEGAGLEST_MAP_EDITOR OR BUILD_MEGAGLEST
if(NOT FORCE_USE_EMBEDDED_Miniupnpc) if(NOT FORCE_USE_EMBEDDED_Miniupnpc)
MESSAGE(STATUS "*** Using EMBEDDED miniupnpc since dev system does not have it... MINIUPNP_FOUND [${MINIUPNP_FOUND}]") MESSAGE(STATUS "*** Using EMBEDDED miniupnpc since dev system does not have it... MINIUPNP_FOUND [${MINIUPNP_FOUND}]")
else() else()
MESSAGE(STATUS "*** Using EMBEDDED miniupnpc because it was forced by option 'FORCE_USE_EMBEDDED_Miniupnpc'") MESSAGE(STATUS "*** Using EMBEDDED miniupnpc because it was forced by option")
endif() endif()
if (NOT WIN32) if (NOT WIN32)
@ -325,7 +330,11 @@ IF(BUILD_MEGAGLEST_MODEL_VIEWER OR BUILD_MEGAGLEST_MAP_EDITOR OR BUILD_MEGAGLEST
INCLUDE_DIRECTORIES("sources/") INCLUDE_DIRECTORIES("sources/")
OPTION(WANT_USE_Ircclient "Enable libircclient support" ON) OPTION(WANT_USE_Ircclient "Enable libircclient support" ON)
OPTION(FORCE_USE_EMBEDDED_Ircclient "Use embedded to source code version of ircclient" OFF) IF(FORCE_EMBEDDED_LIBS)
SET(FORCE_USE_EMBEDDED_Ircclient ON)
ELSE()
OPTION(FORCE_USE_EMBEDDED_Ircclient "Use embedded to source code version of ircclient" OFF)
ENDIF()
IF(WANT_USE_Ircclient) IF(WANT_USE_Ircclient)
#IF(NOT WANT_STATIC_LIBS) #IF(NOT WANT_STATIC_LIBS)
@ -338,7 +347,7 @@ IF(BUILD_MEGAGLEST_MODEL_VIEWER OR BUILD_MEGAGLEST_MAP_EDITOR OR BUILD_MEGAGLEST
if(NOT FORCE_USE_EMBEDDED_Ircclient) if(NOT FORCE_USE_EMBEDDED_Ircclient)
MESSAGE(STATUS "*** Using EMBEDDED libircclient since this system does not have it... IRCCLIENT_FOUND [${IRCCLIENT_FOUND}]") MESSAGE(STATUS "*** Using EMBEDDED libircclient since this system does not have it... IRCCLIENT_FOUND [${IRCCLIENT_FOUND}]")
else() else()
MESSAGE(STATUS "*** Using EMBEDDED libircclient because it was forced by option 'FORCE_USE_EMBEDDED_Ircclient'") MESSAGE(STATUS "*** Using EMBEDDED libircclient because it was forced by option")
endif() endif()
SET(MG_SOURCE_FILES ${MG_SOURCE_FILES} ${PROJECT_SOURCE_DIR}/source/shared_lib/sources/libircclient/src/libircclient.c) SET(MG_SOURCE_FILES ${MG_SOURCE_FILES} ${PROJECT_SOURCE_DIR}/source/shared_lib/sources/libircclient/src/libircclient.c)
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/source/shared_lib/include/libircclient/include) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/source/shared_lib/include/libircclient/include)

View File

@ -1,19 +1,39 @@
/* $Id: codelength.h,v 1.3 2011/07/30 13:10:05 nanard Exp $ */ /* $Id: codelength.h,v 1.5 2015/07/09 12:40:18 nanard Exp $ */
/* Project : miniupnp /* Project : miniupnp
* Author : Thomas BERNARD * Author : Thomas BERNARD
* copyright (c) 2005-2011 Thomas Bernard * copyright (c) 2005-2015 Thomas Bernard
* This software is subjet to the conditions detailed in the * This software is subjet to the conditions detailed in the
* provided LICENCE file. */ * provided LICENCE file. */
#ifndef __CODELENGTH_H__ #ifndef CODELENGTH_H_INCLUDED
#define __CODELENGTH_H__ #define CODELENGTH_H_INCLUDED
/* Encode length by using 7bit per Byte : /* Encode length by using 7bit per Byte :
* Most significant bit of each byte specifies that the * Most significant bit of each byte specifies that the
* following byte is part of the code */ * following byte is part of the code */
/* n : unsigned
* p : unsigned char *
*/
#define DECODELENGTH(n, p) n = 0; \ #define DECODELENGTH(n, p) n = 0; \
do { n = (n << 7) | (*p & 0x7f); } \ do { n = (n << 7) | (*p & 0x7f); } \
while((*(p++)&0x80) && (n<(1<<25))); while((*(p++)&0x80) && (n<(1<<25)));
/* n : unsigned
* READ : function/macro to read one byte (unsigned char)
*/
#define DECODELENGTH_READ(n, READ) \
n = 0; \
do { \
unsigned char c; \
READ(c); \
n = (n << 7) | (c & 0x07f); \
if(!(c&0x80)) break; \
} while(n<(1<<25));
/* n : unsigned
* p : unsigned char *
* p_limit : unsigned char *
*/
#define DECODELENGTH_CHECKLIMIT(n, p, p_limit) \ #define DECODELENGTH_CHECKLIMIT(n, p, p_limit) \
n = 0; \ n = 0; \
do { \ do { \
@ -21,11 +41,14 @@
n = (n << 7) | (*(p) & 0x7f); \ n = (n << 7) | (*(p) & 0x7f); \
} while((*((p)++)&0x80) && (n<(1<<25))); } while((*((p)++)&0x80) && (n<(1<<25)));
/* n : unsigned
* p : unsigned char *
*/
#define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \ #define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \
if(n>=2097152) *(p++) = (n >> 21) | 0x80; \ if(n>=2097152) *(p++) = (n >> 21) | 0x80; \
if(n>=16384) *(p++) = (n >> 14) | 0x80; \ if(n>=16384) *(p++) = (n >> 14) | 0x80; \
if(n>=128) *(p++) = (n >> 7) | 0x80; \ if(n>=128) *(p++) = (n >> 7) | 0x80; \
*(p++) = n & 0x7f; *(p++) = n & 0x7f;
#endif #endif /* CODELENGTH_H_INCLUDED */

View File

@ -1,12 +1,12 @@
/* $Id: connecthostport.h,v 1.2 2012/06/23 22:32:33 nanard Exp $ */ /* $Id: connecthostport.h,v 1.3 2012/09/27 15:42:10 nanard Exp $ */
/* Project: miniupnp /* Project: miniupnp
* http://miniupnp.free.fr/ * http://miniupnp.free.fr/
* Author: Thomas Bernard * Author: Thomas Bernard
* Copyright (c) 2010-2012 Thomas Bernard * Copyright (c) 2010-2012 Thomas Bernard
* This software is subjects to the conditions detailed * This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */ * in the LICENCE file provided within this distribution */
#ifndef __CONNECTHOSTPORT_H__ #ifndef CONNECTHOSTPORT_H_INCLUDED
#define __CONNECTHOSTPORT_H__ #define CONNECTHOSTPORT_H_INCLUDED
/* connecthostport() /* connecthostport()
* return a socket connected (TCP) to the host and port * return a socket connected (TCP) to the host and port

View File

@ -1,13 +1,13 @@
/* $Id: igd_desc_parse.h,v 1.10 2011/04/11 09:19:24 nanard Exp $ */ /* $Id: igd_desc_parse.h,v 1.12 2014/11/17 17:19:13 nanard Exp $ */
/* Project : miniupnp /* Project : miniupnp
* http://miniupnp.free.fr/ * http://miniupnp.free.fr/
* Author : Thomas Bernard * Author : Thomas Bernard
* Copyright (c) 2005-2010 Thomas Bernard * Copyright (c) 2005-2014 Thomas Bernard
* This software is subject to the conditions detailed in the * This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. * LICENCE file provided in this distribution.
* */ * */
#ifndef __IGD_DESC_PARSE_H__ #ifndef IGD_DESC_PARSE_H_INCLUDED
#define __IGD_DESC_PARSE_H__ #define IGD_DESC_PARSE_H_INCLUDED
/* Structure to store the result of the parsing of UPnP /* Structure to store the result of the parsing of UPnP
* descriptions of Internet Gateway Devices */ * descriptions of Internet Gateway Devices */
@ -42,7 +42,8 @@ struct IGDdatas {
void IGDstartelt(void *, const char *, int); void IGDstartelt(void *, const char *, int);
void IGDendelt(void *, const char *, int); void IGDendelt(void *, const char *, int);
void IGDdata(void *, const char *, int); void IGDdata(void *, const char *, int);
#ifdef DEBUG
void printIGD(struct IGDdatas *); void printIGD(struct IGDdatas *);
#endif /* DEBUG */
#endif #endif /* IGD_DESC_PARSE_H_INCLUDED */

View File

@ -1,11 +1,11 @@
/* $Id: minisoap.h,v 1.4 2010/04/12 20:39:41 nanard Exp $ */ /* $Id: minisoap.h,v 1.5 2012/09/27 15:42:10 nanard Exp $ */
/* Project : miniupnp /* Project : miniupnp
* Author : Thomas Bernard * Author : Thomas Bernard
* Copyright (c) 2005 Thomas Bernard * Copyright (c) 2005 Thomas Bernard
* This software is subject to the conditions detailed in the * This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */ * LICENCE file provided in this distribution. */
#ifndef __MINISOAP_H__ #ifndef MINISOAP_H_INCLUDED
#define __MINISOAP_H__ #define MINISOAP_H_INCLUDED
/*int httpWrite(int, const char *, int, const char *);*/ /*int httpWrite(int, const char *, int, const char *);*/
int soapPostSubmit(int, const char *, const char *, unsigned short, int soapPostSubmit(int, const char *, const char *, unsigned short,

View File

@ -1,15 +1,58 @@
/* $Id: minissdpc.h,v 1.1 2007/08/31 15:15:33 nanard Exp $ */ /* $Id: minissdpc.h,v 1.7 2015/10/08 16:15:47 nanard Exp $ */
/* Project: miniupnp /* Project: miniupnp
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author: Thomas Bernard * Author: Thomas Bernard
* Copyright (c) 2005-2007 Thomas Bernard * Copyright (c) 2005-2015 Thomas Bernard
* This software is subjects to the conditions detailed * This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */ * in the LICENCE file provided within this distribution */
#ifndef __MINISSDPC_H__ #ifndef MINISSDPC_H_INCLUDED
#define __MINISSDPC_H__ #define MINISSDPC_H_INCLUDED
struct UPNPDev * #include "miniupnpc_declspec.h"
getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath); #include "upnpdev.h"
/* error codes : */
#define MINISSDPC_SUCCESS (0)
#define MINISSDPC_UNKNOWN_ERROR (-1)
#define MINISSDPC_SOCKET_ERROR (-101)
#define MINISSDPC_MEMORY_ERROR (-102)
#define MINISSDPC_INVALID_INPUT (-103)
#define MINISSDPC_INVALID_SERVER_REPLY (-104)
#ifdef __cplusplus
extern "C" {
#endif
#if !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__))
MINIUPNP_LIBSPEC struct UPNPDev *
getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath, int * error);
MINIUPNP_LIBSPEC int
connectToMiniSSDPD(const char * socketpath);
MINIUPNP_LIBSPEC int
disconnectFromMiniSSDPD(int fd);
MINIUPNP_LIBSPEC int
requestDevicesFromMiniSSDPD(int fd, const char * devtype);
MINIUPNP_LIBSPEC struct UPNPDev *
receiveDevicesFromMiniSSDPD(int fd, int * error);
#endif /* !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)) */
MINIUPNP_LIBSPEC struct UPNPDev *
ssdpDiscoverDevices(const char * const deviceTypes[],
int delay, const char * multicastif,
int localport,
int ipv6, unsigned char ttl,
int * error,
int searchalltypes);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@ -1,15 +1,16 @@
/* $Id: miniupnpc.h,v 1.30 2012/06/28 18:52:12 nanard Exp $ */ /* $Id: miniupnpc.h,v 1.48 2015/10/08 16:19:40 nanard Exp $ */
/* Project: miniupnp /* Project: miniupnp
* http://miniupnp.free.fr/ * http://miniupnp.free.fr/
* Author: Thomas Bernard * Author: Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard * Copyright (c) 2005-2015 Thomas Bernard
* This software is subjects to the conditions detailed * This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */ * in the LICENCE file provided within this distribution */
#ifndef __MINIUPNPC_H__ #ifndef MINIUPNPC_H_INCLUDED
#define __MINIUPNPC_H__ #define MINIUPNPC_H_INCLUDED
#include "declspec.h" #include "miniupnpc_declspec.h"
#include "igd_desc_parse.h" #include "igd_desc_parse.h"
#include "upnpdev.h"
/* error codes : */ /* error codes : */
#define UPNPDISCOVER_SUCCESS (0) #define UPNPDISCOVER_SUCCESS (0)
@ -18,8 +19,14 @@
#define UPNPDISCOVER_MEMORY_ERROR (-102) #define UPNPDISCOVER_MEMORY_ERROR (-102)
/* versions : */ /* versions : */
#define MINIUPNPC_VERSION "1.7.20120830" #define MINIUPNPC_VERSION "1.9.20151008"
#define MINIUPNPC_API_VERSION 9 #define MINIUPNPC_API_VERSION 15
/* Source port:
Using "1" as an alias for 1900 for backwards compatability
(presuming one would have used that for the "sameport" parameter) */
#define UPNP_LOCAL_PORT_ANY 0
#define UPNP_LOCAL_PORT_SAME 1
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -33,14 +40,6 @@ simpleUPnPcommand(int, const char *, const char *,
const char *, struct UPNParg *, const char *, struct UPNParg *,
int *); int *);
struct UPNPDev {
struct UPNPDev * pNext;
char * descURL;
char * st;
unsigned int scope_id;
char buffer[2];
};
/* upnpDiscover() /* upnpDiscover()
* discover UPnP devices on the network. * discover UPnP devices on the network.
* The discovered devices are returned as a chained list. * The discovered devices are returned as a chained list.
@ -52,21 +51,43 @@ struct UPNPDev {
* is NULL. * is NULL.
* If multicastif is not NULL, it will be used instead of the default * If multicastif is not NULL, it will be used instead of the default
* multicast interface for sending SSDP discover packets. * multicast interface for sending SSDP discover packets.
* If sameport is not null, SSDP packets will be sent from the source port * If localport is set to UPNP_LOCAL_PORT_SAME(1) SSDP packets will be sent
* 1900 (same as destination port) otherwise system assign a source port. */ * from the source port 1900 (same as destination port), if set to
LIBSPEC struct UPNPDev * * 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. */
MINIUPNP_LIBSPEC struct UPNPDev *
upnpDiscover(int delay, const char * multicastif, upnpDiscover(int delay, const char * multicastif,
const char * minissdpdsock, int sameport, const char * minissdpdsock, int localport,
int ipv6, int ipv6, unsigned char ttl,
int * error); int * error);
/* freeUPNPDevlist()
* free list returned by upnpDiscover() */ MINIUPNP_LIBSPEC struct UPNPDev *
LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist); upnpDiscoverAll(int delay, const char * multicastif,
const char * minissdpdsock, int localport,
int ipv6, unsigned char ttl,
int * error);
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);
MINIUPNP_LIBSPEC struct UPNPDev *
upnpDiscoverDevices(const char * const deviceTypes[],
int delay, const char * multicastif,
const char * minissdpdsock, int localport,
int ipv6, unsigned char ttl,
int * error,
int searchalltypes);
/* parserootdesc() : /* parserootdesc() :
* parse root XML description of a UPnP device and fill the IGDdatas * parse root XML description of a UPnP device and fill the IGDdatas
* structure. */ * structure. */
LIBSPEC void parserootdesc(const char *, int, struct IGDdatas *); MINIUPNP_LIBSPEC void parserootdesc(const char *, int, struct IGDdatas *);
/* structure used to get fast access to urls /* structure used to get fast access to urls
* controlURL: controlURL of the WANIPConnection * controlURL: controlURL of the WANIPConnection
@ -94,7 +115,7 @@ struct UPNPUrls {
* passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
* free allocated memory. * free allocated memory.
*/ */
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetValidIGD(struct UPNPDev * devlist, UPNP_GetValidIGD(struct UPNPDev * devlist,
struct UPNPUrls * urls, struct UPNPUrls * urls,
struct IGDdatas * data, struct IGDdatas * data,
@ -102,24 +123,25 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
/* UPNP_GetIGDFromUrl() /* UPNP_GetIGDFromUrl()
* Used when skipping the discovery process. * Used when skipping the discovery process.
* When succeding, urls, data, and lanaddr arguments are set.
* return value : * return value :
* 0 - Not ok * 0 - Not ok
* 1 - OK */ * 1 - OK */
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetIGDFromUrl(const char * rootdescurl, UPNP_GetIGDFromUrl(const char * rootdescurl,
struct UPNPUrls * urls, struct UPNPUrls * urls,
struct IGDdatas * data, struct IGDdatas * data,
char * lanaddr, int lanaddrlen); char * lanaddr, int lanaddrlen);
LIBSPEC void MINIUPNP_LIBSPEC void
GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *,
const char *, unsigned int); const char *, unsigned int);
LIBSPEC void MINIUPNP_LIBSPEC void
FreeUPNPUrls(struct UPNPUrls *); FreeUPNPUrls(struct UPNPUrls *);
/* return 0 or 1 */ /* return 0 or 1 */
LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *); MINIUPNP_LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -0,0 +1,21 @@
#ifndef MINIUPNPC_DECLSPEC_H_INCLUDED
#define MINIUPNPC_DECLSPEC_H_INCLUDED
#if defined(_WIN32) && !defined(MINIUPNP_STATICLIB)
/* for windows dll */
#ifdef MINIUPNP_EXPORTS
#define MINIUPNP_LIBSPEC __declspec(dllexport)
#else
#define MINIUPNP_LIBSPEC __declspec(dllimport)
#endif
#else
#if defined(__GNUC__) && __GNUC__ >= 4
/* fix dynlib for OS X 10.9.2 and Apple LLVM version 5.0 */
#define MINIUPNP_LIBSPEC __attribute__ ((visibility ("default")))
#else
#define MINIUPNP_LIBSPEC
#endif
#endif
#endif /* MINIUPNPC_DECLSPEC_H_INCLUDED */

View File

@ -20,7 +20,9 @@
#define OS_STRING "Other/unknown" #define OS_STRING "Other/unknown"
#endif #endif
#define MINIUPNPC_VERSION_STRING "1.6" #define MINIUPNPC_VERSION_STRING "1.9"
#define UPNP_VERSION_STRING "UPnP/1.1"
#define MINIUPNPC_API_VERSION 15
#endif #endif

View File

@ -0,0 +1,23 @@
/* $Id: miniupnpcstrings.h.in,v 1.6 2014/11/04 22:31:55 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author: Thomas Bernard
* Copyright (c) 2005-2014 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef MINIUPNPCSTRINGS_H_INCLUDED
#define MINIUPNPCSTRINGS_H_INCLUDED
#define OS_STRING "OS/version"
#define MINIUPNPC_VERSION_STRING "version"
#if 0
/* according to "UPnP Device Architecture 1.0" */
#define UPNP_VERSION_STRING "UPnP/1.0"
#else
/* according to "UPnP Device Architecture 1.1" */
#define UPNP_VERSION_STRING "UPnP/1.1"
#endif
#endif

View File

@ -1,11 +1,11 @@
/* $Id: miniupnpctypes.h,v 1.1 2011/02/15 11:10:40 nanard Exp $ */ /* $Id: miniupnpctypes.h,v 1.2 2012/09/27 15:42:10 nanard Exp $ */
/* Miniupnp project : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org /* Miniupnp project : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org
* Author : Thomas Bernard * Author : Thomas Bernard
* Copyright (c) 2011 Thomas Bernard * Copyright (c) 2011 Thomas Bernard
* This software is subject to the conditions detailed in the * This software is subject to the conditions detailed in the
* LICENCE file provided within this distribution */ * LICENCE file provided within this distribution */
#ifndef __MINIUPNPCTYPES_H__ #ifndef MINIUPNPCTYPES_H_INCLUDED
#define __MINIUPNPCTYPES_H__ #define MINIUPNPCTYPES_H_INCLUDED
#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) #if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
#define UNSIGNED_INTEGER unsigned long long #define UNSIGNED_INTEGER unsigned long long

View File

@ -1,24 +1,24 @@
/* $Id: miniwget.h,v 1.7 2012/06/23 22:35:59 nanard Exp $ */ /* $Id: miniwget.h,v 1.10 2015/07/21 13:16:55 nanard Exp $ */
/* Project : miniupnp /* Project : miniupnp
* Author : Thomas Bernard * Author : Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard * Copyright (c) 2005-2015 Thomas Bernard
* This software is subject to the conditions detailed in the * This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. * LICENCE file provided in this distribution.
* */ * */
#ifndef __MINIWGET_H__ #ifndef MINIWGET_H_INCLUDED
#define __MINIWGET_H__ #define MINIWGET_H_INCLUDED
#include "declspec.h" #include "miniupnpc_declspec.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
LIBSPEC void * getHTTPResponse(int s, int * size); MINIUPNP_LIBSPEC void * getHTTPResponse(int s, int * size);
LIBSPEC void * miniwget(const char *, int *, unsigned int); MINIUPNP_LIBSPEC void * miniwget(const char *, int *, unsigned int);
LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int, unsigned int); MINIUPNP_LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int, unsigned int);
int parseURL(const char *, char *, unsigned short *, char * *, unsigned int *); int parseURL(const char *, char *, unsigned short *, char * *, unsigned int *);

View File

@ -1,4 +1,4 @@
/* $Id: minixml.h,v 1.6 2006/11/30 11:47:21 nanard Exp $ */ /* $Id: minixml.h,v 1.7 2012/09/27 15:42:10 nanard Exp $ */
/* minimal xml parser /* minimal xml parser
* *
* Project : miniupnp * Project : miniupnp
@ -8,8 +8,8 @@
* This software is subject to the conditions detailed in the * This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. * LICENCE file provided in this distribution.
* */ * */
#ifndef __MINIXML_H__ #ifndef MINIXML_H_INCLUDED
#define __MINIXML_H__ #define MINIXML_H_INCLUDED
#define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n')) #define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n'))
/* if a callback function pointer is set to NULL, /* if a callback function pointer is set to NULL,

View File

@ -1,22 +1,16 @@
/* $Id: portlistingparse.h,v 1.6 2012/03/05 19:42:47 nanard Exp $ */ /* $Id: portlistingparse.h,v 1.11 2015/07/21 13:16:55 nanard Exp $ */
/* MiniUPnP project /* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2011-2012 Thomas Bernard * (c) 2011-2015 Thomas Bernard
* This software is subject to the conditions detailed * This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */ * in the LICENCE file provided within the distribution */
#ifndef __PORTLISTINGPARSE_H__ #ifndef PORTLISTINGPARSE_H_INCLUDED
#define __PORTLISTINGPARSE_H__ #define PORTLISTINGPARSE_H_INCLUDED
#include "declspec.h" #include "miniupnpc_declspec.h"
/* for the definition of UNSIGNED_INTEGER */ /* for the definition of UNSIGNED_INTEGER */
#include "miniupnpctypes.h" #include "miniupnpctypes.h"
#if defined(NO_SYS_QUEUE_H) || defined(_WIN32) || defined(__HAIKU__)
#include "bsdqueue.h"
#else
#include <sys/queue.h>
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -41,7 +35,7 @@ typedef enum { PortMappingEltNone,
NewLeaseTime } portMappingElt; NewLeaseTime } portMappingElt;
struct PortMapping { struct PortMapping {
LIST_ENTRY(PortMapping) entries; struct PortMapping * l_next; /* list next element */
UNSIGNED_INTEGER leaseTime; UNSIGNED_INTEGER leaseTime;
unsigned short externalPort; unsigned short externalPort;
unsigned short internalPort; unsigned short internalPort;
@ -53,15 +47,15 @@ struct PortMapping {
}; };
struct PortMappingParserData { struct PortMappingParserData {
LIST_HEAD(portmappinglisthead, PortMapping) head; struct PortMapping * l_head; /* list head */
portMappingElt curelt; portMappingElt curelt;
}; };
LIBSPEC void MINIUPNP_LIBSPEC void
ParsePortListing(const char * buffer, int bufsize, ParsePortListing(const char * buffer, int bufsize,
struct PortMappingParserData * pdata); struct PortMappingParserData * pdata);
LIBSPEC void MINIUPNP_LIBSPEC void
FreePortListing(struct PortMappingParserData * pdata); FreePortListing(struct PortMappingParserData * pdata);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,12 +1,12 @@
/* $Id: receivedata.h,v 1.3 2012/06/23 22:34:47 nanard Exp $ */ /* $Id: receivedata.h,v 1.4 2012/09/27 15:42:10 nanard Exp $ */
/* Project: miniupnp /* Project: miniupnp
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author: Thomas Bernard * Author: Thomas Bernard
* Copyright (c) 2011-2012 Thomas Bernard * Copyright (c) 2011-2012 Thomas Bernard
* This software is subjects to the conditions detailed * This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */ * in the LICENCE file provided within this distribution */
#ifndef __RECEIVEDATA_H__ #ifndef RECEIVEDATA_H_INCLUDED
#define __RECEIVEDATA_H__ #define RECEIVEDATA_H_INCLUDED
/* Reads data from the specified socket. /* Reads data from the specified socket.
* Returns the number of bytes read if successful, zero if no bytes were * Returns the number of bytes read if successful, zero if no bytes were

View File

@ -1,15 +1,15 @@
/* $Id: upnpcommands.h,v 1.24 2012/03/05 19:42:47 nanard Exp $ */ /* $Id: upnpcommands.h,v 1.31 2015/07/21 13:16:55 nanard Exp $ */
/* Miniupnp project : http://miniupnp.free.fr/ /* Miniupnp project : http://miniupnp.free.fr/
* Author : Thomas Bernard * Author : Thomas Bernard
* Copyright (c) 2005-2011 Thomas Bernard * Copyright (c) 2005-2015 Thomas Bernard
* This software is subject to the conditions detailed in the * This software is subject to the conditions detailed in the
* LICENCE file provided within this distribution */ * LICENCE file provided within this distribution */
#ifndef __UPNPCOMMANDS_H__ #ifndef UPNPCOMMANDS_H_INCLUDED
#define __UPNPCOMMANDS_H__ #define UPNPCOMMANDS_H_INCLUDED
#include "upnpreplyparse.h" #include "upnpreplyparse.h"
#include "portlistingparse.h" #include "portlistingparse.h"
#include "declspec.h" #include "miniupnpc_declspec.h"
#include "miniupnpctypes.h" #include "miniupnpctypes.h"
/* MiniUPnPc return codes : */ /* MiniUPnPc return codes : */
@ -17,24 +17,26 @@
#define UPNPCOMMAND_UNKNOWN_ERROR (-1) #define UPNPCOMMAND_UNKNOWN_ERROR (-1)
#define UPNPCOMMAND_INVALID_ARGS (-2) #define UPNPCOMMAND_INVALID_ARGS (-2)
#define UPNPCOMMAND_HTTP_ERROR (-3) #define UPNPCOMMAND_HTTP_ERROR (-3)
#define UPNPCOMMAND_INVALID_RESPONSE (-4)
#define UPNPCOMMAND_MEM_ALLOC_ERROR (-5)
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
LIBSPEC UNSIGNED_INTEGER MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalBytesSent(const char * controlURL, UPNP_GetTotalBytesSent(const char * controlURL,
const char * servicetype); const char * servicetype);
LIBSPEC UNSIGNED_INTEGER MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalBytesReceived(const char * controlURL, UPNP_GetTotalBytesReceived(const char * controlURL,
const char * servicetype); const char * servicetype);
LIBSPEC UNSIGNED_INTEGER MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalPacketsSent(const char * controlURL, UPNP_GetTotalPacketsSent(const char * controlURL,
const char * servicetype); const char * servicetype);
LIBSPEC UNSIGNED_INTEGER MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalPacketsReceived(const char * controlURL, UPNP_GetTotalPacketsReceived(const char * controlURL,
const char * servicetype); const char * servicetype);
@ -43,7 +45,7 @@ UPNP_GetTotalPacketsReceived(const char * controlURL,
* Return values : * Return values :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
* or a UPnP Error code */ * or a UPnP Error code */
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetStatusInfo(const char * controlURL, UPNP_GetStatusInfo(const char * controlURL,
const char * servicetype, const char * servicetype,
char * status, char * status,
@ -55,7 +57,7 @@ UPNP_GetStatusInfo(const char * controlURL,
* Return Values : * Return Values :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
* or a UPnP Error code */ * or a UPnP Error code */
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetConnectionTypeInfo(const char * controlURL, UPNP_GetConnectionTypeInfo(const char * controlURL,
const char * servicetype, const char * servicetype,
char * connectionType); char * connectionType);
@ -71,7 +73,7 @@ UPNP_GetConnectionTypeInfo(const char * controlURL,
* possible UPnP Errors : * possible UPnP Errors :
* 402 Invalid Args - 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. */ * 501 Action Failed - See UPnP Device Architecture section on Control. */
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetExternalIPAddress(const char * controlURL, UPNP_GetExternalIPAddress(const char * controlURL,
const char * servicetype, const char * servicetype,
char * extIpAdd); char * extIpAdd);
@ -82,7 +84,7 @@ UPNP_GetExternalIPAddress(const char * controlURL,
* return values : * return values :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
* or a UPnP Error Code. */ * or a UPnP Error Code. */
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetLinkLayerMaxBitRates(const char* controlURL, UPNP_GetLinkLayerMaxBitRates(const char* controlURL,
const char* servicetype, const char* servicetype,
unsigned int * bitrateDown, unsigned int * bitrateDown,
@ -100,6 +102,8 @@ UPNP_GetLinkLayerMaxBitRates(const char* controlURL,
* errorCode errorDescription (short) - Description (long) * errorCode errorDescription (short) - Description (long)
* 402 Invalid Args - 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. * 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 * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be
* wild-carded * wild-carded
* 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded
@ -112,16 +116,56 @@ UPNP_GetLinkLayerMaxBitRates(const char* controlURL,
* 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard * 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard
* and cannot be a specific IP address or DNS name * and cannot be a specific IP address or DNS name
* 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and * 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and
* cannot be a specific port value */ * cannot be a specific port value
LIBSPEC int * 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
*/
MINIUPNP_LIBSPEC int
UPNP_AddPortMapping(const char * controlURL, const char * servicetype, UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
const char * extPort, const char * extPort,
const char * inPort, const char * inPort,
const char * inClient, const char * inClient,
const char * desc, const char * desc,
const char * proto, const char * proto,
const char * remoteHost, const char * remoteHost,
const char * leaseDuration); 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.
*
* Return values :
* 0 : SUCCESS
* NON ZERO : ERROR. Either an UPnP error code or an unknown error.
*
* 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
*/
MINIUPNP_LIBSPEC int
UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype,
const char * extPort,
const char * inPort,
const char * inClient,
const char * desc,
const char * proto,
const char * remoteHost,
const char * leaseDuration,
char * reservedPort);
/* UPNP_DeletePortMapping() /* UPNP_DeletePortMapping()
* Use same argument values as what was used for AddPortMapping(). * Use same argument values as what was used for AddPortMapping().
@ -132,15 +176,36 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
* *
* List of possible UPnP errors for DeletePortMapping : * List of possible UPnP errors for DeletePortMapping :
* 402 Invalid Args - See UPnP Device Architecture section on Control. * 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 */ * 714 NoSuchEntryInArray - The specified value does not exist in the array */
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
const char * extPort, const char * proto, const char * extPort, const char * proto,
const char * remoteHost); const char * remoteHost);
/* UPNP_DeletePortRangeMapping()
* 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.
*
* 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. */
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() /* UPNP_GetPortMappingNumberOfEntries()
* not supported by all routers */ * not supported by all routers */
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetPortMappingNumberOfEntries(const char* controlURL, UPNP_GetPortMappingNumberOfEntries(const char* controlURL,
const char* servicetype, const char* servicetype,
unsigned int * num); unsigned int * num);
@ -150,6 +215,7 @@ UPNP_GetPortMappingNumberOfEntries(const char* controlURL,
* params : * params :
* in extPort * in extPort
* in proto * in proto
* in remoteHost
* out intClient (16 bytes) * out intClient (16 bytes)
* out intPort (6 bytes) * out intPort (6 bytes)
* out desc (80 bytes) * out desc (80 bytes)
@ -158,12 +224,21 @@ UPNP_GetPortMappingNumberOfEntries(const char* controlURL,
* *
* return value : * return value :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
* or a UPnP Error Code. */ * or a UPnP Error Code.
LIBSPEC int *
* 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.
*/
MINIUPNP_LIBSPEC int
UPNP_GetSpecificPortMappingEntry(const char * controlURL, UPNP_GetSpecificPortMappingEntry(const char * controlURL,
const char * servicetype, const char * servicetype,
const char * extPort, const char * extPort,
const char * proto, const char * proto,
const char * remoteHost,
char * intClient, char * intClient,
char * intPort, char * intPort,
char * desc, char * desc,
@ -188,9 +263,11 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
* *
* Possible UPNP Error codes : * Possible UPNP Error codes :
* 402 Invalid Args - See UPnP Device Architecture section on Control. * 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 * 713 SpecifiedArrayIndexInvalid - The specified array index is out of bounds
*/ */
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetGenericPortMappingEntry(const char * controlURL, UPNP_GetGenericPortMappingEntry(const char * controlURL,
const char * servicetype, const char * servicetype,
const char * index, const char * index,
@ -212,7 +289,7 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL,
* 733 InconsistantParameters - NewStartPort and NewEndPort values are not * 733 InconsistantParameters - NewStartPort and NewEndPort values are not
* consistent. * consistent.
*/ */
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetListOfPortMappings(const char * controlURL, UPNP_GetListOfPortMappings(const char * controlURL,
const char * servicetype, const char * servicetype,
const char * startPort, const char * startPort,
@ -222,13 +299,13 @@ UPNP_GetListOfPortMappings(const char * controlURL,
struct PortMappingParserData * data); struct PortMappingParserData * data);
/* IGD:2, functions for service WANIPv6FirewallControl:1 */ /* IGD:2, functions for service WANIPv6FirewallControl:1 */
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetFirewallStatus(const char * controlURL, UPNP_GetFirewallStatus(const char * controlURL,
const char * servicetype, const char * servicetype,
int * firewallEnabled, int * firewallEnabled,
int * inboundPinholeAllowed); int * inboundPinholeAllowed);
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype, UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype,
const char * remoteHost, const char * remoteHost,
const char * remotePort, const char * remotePort,
@ -237,7 +314,7 @@ UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype
const char * proto, const char * proto,
int * opTimeout); int * opTimeout);
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_AddPinhole(const char * controlURL, const char * servicetype, UPNP_AddPinhole(const char * controlURL, const char * servicetype,
const char * remoteHost, const char * remoteHost,
const char * remotePort, const char * remotePort,
@ -247,19 +324,19 @@ UPNP_AddPinhole(const char * controlURL, const char * servicetype,
const char * leaseTime, const char * leaseTime,
char * uniqueID); char * uniqueID);
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_UpdatePinhole(const char * controlURL, const char * servicetype, UPNP_UpdatePinhole(const char * controlURL, const char * servicetype,
const char * uniqueID, const char * uniqueID,
const char * leaseTime); const char * leaseTime);
LIBSPEC int 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);
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype, UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype,
const char * uniqueID, int * isWorking); const char * uniqueID, int * isWorking);
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetPinholePackets(const char * controlURL, const char * servicetype, UPNP_GetPinholePackets(const char * controlURL, const char * servicetype,
const char * uniqueID, int * packets); const char * uniqueID, int * packets);

View File

@ -0,0 +1,36 @@
/* $Id: upnpdev.h,v 1.1 2015/08/28 12:14:19 nanard Exp $ */
/* Project : miniupnp
* Web : http://miniupnp.free.fr/
* Author : Thomas BERNARD
* copyright (c) 2005-2015 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENSE file. */
#ifndef UPNPDEV_H_INCLUDED
#define UPNPDEV_H_INCLUDED
#include "miniupnpc_declspec.h"
#ifdef __cplusplus
extern "C" {
#endif
struct UPNPDev {
struct UPNPDev * pNext;
char * descURL;
char * st;
unsigned int scope_id;
char * usn;
char buffer[3];
};
/* freeUPNPDevlist()
* free list returned by upnpDiscover() */
MINIUPNP_LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist);
#ifdef __cplusplus
}
#endif
#endif /* UPNPDEV_H_INCLUDED */

View File

@ -1,14 +1,14 @@
/* $Id: upnperrors.h,v 1.3 2012/03/05 19:42:47 nanard Exp $ */ /* $Id: upnperrors.h,v 1.6 2015/07/21 13:16:55 nanard Exp $ */
/* (c) 2007 Thomas Bernard /* (c) 2007-2015 Thomas Bernard
* All rights reserved. * All rights reserved.
* MiniUPnP Project. * MiniUPnP Project.
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* This software is subjet to the conditions detailed in the * This software is subjet to the conditions detailed in the
* provided LICENCE file. */ * provided LICENCE file. */
#ifndef __UPNPERRORS_H__ #ifndef UPNPERRORS_H_INCLUDED
#define __UPNPERRORS_H__ #define UPNPERRORS_H_INCLUDED
#include "declspec.h" #include "miniupnpc_declspec.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -17,7 +17,7 @@ extern "C" {
/* strupnperror() /* strupnperror()
* Return a string description of the UPnP error code * Return a string description of the UPnP error code
* or NULL for undefinded errors */ * or NULL for undefinded errors */
LIBSPEC const char * strupnperror(int err); MINIUPNP_LIBSPEC const char * strupnperror(int err);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,34 +1,31 @@
/* $Id: upnpreplyparse.h,v 1.13 2012/03/05 19:42:48 nanard Exp $ */ /* $Id: upnpreplyparse.h,v 1.19 2014/10/27 16:33:19 nanard Exp $ */
/* MiniUPnP project /* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard * (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed * This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */ * in the LICENCE file provided within the distribution */
#ifndef __UPNPREPLYPARSE_H__ #ifndef UPNPREPLYPARSE_H_INCLUDED
#define __UPNPREPLYPARSE_H__ #define UPNPREPLYPARSE_H_INCLUDED
#if defined(NO_SYS_QUEUE_H) || defined(_WIN32) || defined(__HAIKU__)
#include "bsdqueue.h"
#else
#include <sys/queue.h>
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
struct NameValue { struct NameValue {
LIST_ENTRY(NameValue) entries; struct NameValue * l_next;
char name[64]; char name[64];
char value[64]; char value[128];
}; };
struct NameValueParserData { struct NameValueParserData {
LIST_HEAD(listhead, NameValue) head; struct NameValue * l_head;
char curelt[64]; char curelt[64];
char * portListing; char * portListing;
int portListingLength; int portListingLength;
int topelt;
const char * cdata;
int cdatalen;
}; };
/* ParseNameValue() */ /* ParseNameValue() */
@ -45,10 +42,12 @@ char *
GetValueFromNameValueList(struct NameValueParserData * pdata, GetValueFromNameValueList(struct NameValueParserData * pdata,
const char * Name); const char * Name);
#if 0
/* GetValueFromNameValueListIgnoreNS() */ /* GetValueFromNameValueListIgnoreNS() */
char * char *
GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
const char * Name); const char * Name);
#endif
/* DisplayNameValueList() */ /* DisplayNameValueList() */
#ifdef DEBUG #ifdef DEBUG

View File

@ -1,6 +1,137 @@
$Id: Changelog.txt,v 1.177 2012/08/29 07:51:29 nanard Exp $ $Id: Changelog.txt,v 1.216 2015/10/08 16:15:45 nanard Exp $
miniUPnP client Changelog. miniUPnP client Changelog.
2015/10/08:
Change sameport to localport
see https://github.com/miniupnp/miniupnp/pull/120
increments API_VERSION to 15
2015/09/15:
Fix buffer overflow in igd_desc_parse.c/IGDstartelt()
Discovered by Aleksandar Nikolic of Cisco Talos
2015/08/28:
move ssdpDiscoverDevices() to minissdpc.c
2015/08/27:
avoid unix socket leak in getDevicesFromMiniSSDPD()
2015/08/16:
Also accept "Up" as ConnectionStatus value
2015/07/23:
split getDevicesFromMiniSSDPD
add ttl argument to upnpDiscover() functions
increments API_VERSION to 14
2015/07/22:
Read USN from SSDP messages.
2015/07/15:
Check malloc/calloc
2015/06/16:
update getDevicesFromMiniSSDPD() to process longer minissdpd
responses
2015/05/22:
add searchalltypes param to upnpDiscoverDevices()
increments API_VERSION to 13
2015/04/30:
upnpc: output version on the terminal
2015/04/27:
_BSD_SOURCE is deprecated in favor of _DEFAULT_SOURCE
fix CMakeLists.txt COMPILE_DEFINITIONS
fix getDevicesFromMiniSSDPD() not setting scope_id
improve -r command of upnpc command line tool
2014/11/17:
search all :
upnpDiscoverDevices() / upnpDiscoverAll() functions
listdevices executable
increment API_VERSION to 12
validate igd_desc_parse
2014/11/13:
increment API_VERSION to 11
2014/11/05:
simplified function GetUPNPUrls()
2014/09/11:
use remoteHost arg of DeletePortMapping
2014/09/06:
Fix python3 build
2014/07/01:
Fix parsing of IGD2 root descriptions
2014/06/10:
rename LIBSPEC to MINIUPNP_LIBSPEC
2014/05/15:
Add support for IGD2 AddAnyPortMapping and DeletePortMappingRange
2014/02/05:
handle EINPROGRESS after connect()
2014/02/03:
minixml now handle XML comments
VERSION 1.9 : released 2014/01/31
2014/01/31:
added argument remoteHost to UPNP_GetSpecificPortMappingEntry()
increment API_VERSION to 10
2013/12/09:
--help and -h arguments in upnpc.c
2013/10/07:
fixed potential buffer overrun in miniwget.c
Modified UPNP_GetValidIGD() to check for ExternalIpAddress
2013/08/01:
define MAXHOSTNAMELEN if not already done
2013/06/06:
update upnpreplyparse to allow larger values (128 chars instead of 64)
2013/05/14:
Update upnpreplyparse to take into account "empty" elements
validate upnpreplyparse.c code with "make check"
2013/05/03:
Fix Solaris build thanks to Maciej Małecki
2013/04/27:
Fix testminiwget.sh for BSD
2013/03/23:
Fixed Makefile for *BSD
2013/03/11:
Update Makefile to use JNAerator version 0.11
2013/02/11:
Fix testminiwget.sh for use with dash
Use $(DESTDIR) in Makefile
VERSION 1.8 : released 2013/02/06
2012/10/16:
fix testminiwget with no IPv6 support
2012/09/27:
Rename all include guards to not clash with C99
(7.1.3 Reserved identifiers).
2012/08/30:
Added -e option to upnpc program (set description for port mappings)
2012/08/29: 2012/08/29:
Python 3 support (thanks to Christopher Foo) Python 3 support (thanks to Christopher Foo)

View File

@ -1,5 +1,5 @@
MiniUPnPc MiniUPnPc
Copyright (c) 2005-2011, Thomas BERNARD Copyright (c) 2005-2015, Thomas BERNARD
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without

View File

@ -1,15 +1,15 @@
# $Id: Makefile,v 1.98 2012/08/29 07:51:30 nanard Exp $ # $Id: Makefile,v 1.131 2015/10/08 16:15:46 nanard Exp $
# MiniUPnP Project # MiniUPnP Project
# http://miniupnp.free.fr/ # http://miniupnp.free.fr/
# http://miniupnp.tuxfamily.org/ # http://miniupnp.tuxfamily.org/
# https://github.com/miniupnp/miniupnp # https://github.com/miniupnp/miniupnp
# (c) 2005-2012 Thomas Bernard # (c) 2005-2015 Thomas Bernard
# to install use : # to install use :
# $ PREFIX=/tmp/dummylocation make install # $ make DESTDIR=/tmp/dummylocation install
# or # or
# $ INSTALLPREFIX=/usr/local make install # $ INSTALLPREFIX=/usr/local make install
# or # or
# make install (will go to /usr/bin, /usr/lib, etc...) # $ make install (default INSTALLPREFIX is /usr)
OS = $(shell uname -s) OS = $(shell uname -s)
VERSION = $(shell cat VERSION) VERSION = $(shell cat VERSION)
@ -19,6 +19,12 @@ endif
ifeq ($(OS), Linux) ifeq ($(OS), Linux)
JARSUFFIX=linux JARSUFFIX=linux
endif endif
ifneq (,$(findstring NT-5.1,$(OS)))
JARSUFFIX=win32
endif
HAVE_IPV6 ?= yes
export HAVE_IPV6
CC ?= gcc CC ?= gcc
#AR = gar #AR = gar
@ -29,30 +35,50 @@ CFLAGS += -W -Wstrict-prototypes
CFLAGS += -fno-common CFLAGS += -fno-common
CFLAGS += -DMINIUPNPC_SET_SOCKET_TIMEOUT CFLAGS += -DMINIUPNPC_SET_SOCKET_TIMEOUT
CFLAGS += -DMINIUPNPC_GET_SRC_ADDR CFLAGS += -DMINIUPNPC_GET_SRC_ADDR
CFLAGS += -D_BSD_SOURCE -D_POSIX_C_SOURCE=1 CFLAGS += -D_BSD_SOURCE
CFLAGS += -ansi CFLAGS += -D_DEFAULT_SOURCE
ifneq ($(OS), FreeBSD)
ifneq ($(OS), Darwin)
#CFLAGS += -D_POSIX_C_SOURCE=200112L
CFLAGS += -D_XOPEN_SOURCE=600
endif
endif
#CFLAGS += -ansi
# -DNO_GETADDRINFO # -DNO_GETADDRINFO
INSTALL = install INSTALL = install
SH = /bin/sh SH = /bin/sh
JAVA = java JAVA = java
# see http://code.google.com/p/jnaerator/ # see http://code.google.com/p/jnaerator/
JNAERATOR = jnaerator-0.9.7.jar #JNAERATOR = jnaerator-0.9.7.jar
JNAERATORBASEURL = http://jnaerator.googlecode.com/files/ #JNAERATOR = jnaerator-0.9.8-shaded.jar
#following libs are needed on Solaris #JNAERATORARGS = -library miniupnpc
#LDLIBS=-lsocket -lnsl -lresolv #JNAERATOR = jnaerator-0.10-shaded.jar
#JNAERATOR = jnaerator-0.11-shaded.jar
# https://repo1.maven.org/maven2/com/nativelibs4java/jnaerator/0.12/jnaerator-0.12-shaded.jar
JNAERATOR = jnaerator-0.12-shaded.jar
JNAERATORARGS = -mode StandaloneJar -runtime JNAerator -library miniupnpc
#JNAERATORBASEURL = http://jnaerator.googlecode.com/files/
JNAERATORBASEURL = https://repo1.maven.org/maven2/com/nativelibs4java/jnaerator/0.12
ifeq (SunOS, $(OS))
LDFLAGS=-lsocket -lnsl -lresolv
endif
# APIVERSION is used to build SONAME # APIVERSION is used to build SONAME
APIVERSION = 9 APIVERSION = 15
SRCS = igd_desc_parse.c miniupnpc.c minixml.c minisoap.c miniwget.c \ SRCS = igd_desc_parse.c miniupnpc.c minixml.c minisoap.c miniwget.c \
upnpc.c upnpcommands.c upnpreplyparse.c testminixml.c \ upnpc.c upnpcommands.c upnpreplyparse.c testminixml.c \
minixmlvalid.c testupnpreplyparse.c minissdpc.c \ minixmlvalid.c testupnpreplyparse.c minissdpc.c \
upnperrors.c testigddescparse.c testminiwget.c \ upnperrors.c testigddescparse.c testminiwget.c \
connecthostport.c portlistringparse.c receivedata.c connecthostport.c portlistingparse.c receivedata.c \
upnpdev.c testportlistingparse.c miniupnpcmodule.c \
minihttptestserver.c \
listdevices.c
LIBOBJS = miniwget.o minixml.o igd_desc_parse.o minisoap.o \ LIBOBJS = miniwget.o minixml.o igd_desc_parse.o minisoap.o \
miniupnpc.o upnpreplyparse.o upnpcommands.o upnperrors.o \ miniupnpc.o upnpreplyparse.o upnpcommands.o upnperrors.o \
connecthostport.o portlistingparse.o receivedata.o connecthostport.o portlistingparse.o receivedata.o upnpdev.o
ifneq ($(OS), AmigaOS) ifneq ($(OS), AmigaOS)
CFLAGS := -fPIC $(CFLAGS) CFLAGS := -fPIC $(CFLAGS)
@ -65,22 +91,28 @@ OBJS = $(patsubst %.c,%.o,$(SRCS))
HEADERS = miniupnpc.h miniwget.h upnpcommands.h igd_desc_parse.h \ HEADERS = miniupnpc.h miniwget.h upnpcommands.h igd_desc_parse.h \
upnpreplyparse.h upnperrors.h miniupnpctypes.h \ upnpreplyparse.h upnperrors.h miniupnpctypes.h \
portlistingparse.h \ portlistingparse.h \
declspec.h upnpdev.h \
miniupnpc_declspec.h
# library names # library names
LIBRARY = libminiupnpc.a LIBRARY = libminiupnpc.a
ifeq ($(OS), Darwin) ifeq ($(OS), Darwin)
SHAREDLIBRARY = libminiupnpc.dylib SHAREDLIBRARY = libminiupnpc.dylib
SONAME = $(basename $(SHAREDLIBRARY)).$(APIVERSION).dylib SONAME = $(basename $(SHAREDLIBRARY)).$(APIVERSION).dylib
CFLAGS := -DMACOSX -D_DARWIN_C_SOURCE $(CFLAGS) CFLAGS := -D_DARWIN_C_SOURCE $(CFLAGS)
else else
ifeq ($(JARSUFFIX), win32)
SHAREDLIBRARY = miniupnpc.dll
else
# Linux/BSD/etc.
SHAREDLIBRARY = libminiupnpc.so SHAREDLIBRARY = libminiupnpc.so
SONAME = $(SHAREDLIBRARY).$(APIVERSION) SONAME = $(SHAREDLIBRARY).$(APIVERSION)
endif endif
endif
EXECUTABLES = upnpc-static EXECUTABLES = upnpc-static listdevices
EXECUTABLES_ADDTESTS = testminixml minixmlvalid testupnpreplyparse \ EXECUTABLES_ADDTESTS = testminixml minixmlvalid testupnpreplyparse \
testigddescparse testminiwget testigddescparse testminiwget testportlistingparse
TESTMINIXMLOBJS = minixml.o igd_desc_parse.o testminixml.o TESTMINIXMLOBJS = minixml.o igd_desc_parse.o testminixml.o
@ -88,6 +120,8 @@ TESTMINIWGETOBJS = miniwget.o testminiwget.o connecthostport.o receivedata.o
TESTUPNPREPLYPARSE = testupnpreplyparse.o minixml.o upnpreplyparse.o TESTUPNPREPLYPARSE = testupnpreplyparse.o minixml.o upnpreplyparse.o
TESTPORTLISTINGPARSE = testportlistingparse.o minixml.o portlistingparse.o
TESTIGDDESCPARSE = testigddescparse.o igd_desc_parse.o minixml.o \ TESTIGDDESCPARSE = testigddescparse.o igd_desc_parse.o minixml.o \
miniupnpc.o miniwget.o upnpcommands.o upnpreplyparse.o \ miniupnpc.o miniwget.o upnpcommands.o upnpreplyparse.o \
minisoap.o connecthostport.o receivedata.o \ minisoap.o connecthostport.o receivedata.o \
@ -99,10 +133,11 @@ TESTMINIWGETOBJS := $(TESTMINIWGETOBJS) minissdpc.o
TESTIGDDESCPARSE := $(TESTIGDDESCPARSE) minissdpc.o TESTIGDDESCPARSE := $(TESTIGDDESCPARSE) minissdpc.o
endif endif
LIBDIR ?= lib
# install directories # install directories
INSTALLPREFIX ?= $(PREFIX)/usr INSTALLPREFIX ?= $(PREFIX)/usr
INSTALLDIRINC = $(INSTALLPREFIX)/include/miniupnpc INSTALLDIRINC = $(INSTALLPREFIX)/include/miniupnpc
INSTALLDIRLIB = $(INSTALLPREFIX)/lib INSTALLDIRLIB = $(INSTALLPREFIX)/$(LIBDIR)
INSTALLDIRBIN = $(INSTALLPREFIX)/bin INSTALLDIRBIN = $(INSTALLPREFIX)/bin
INSTALLDIRMAN = $(INSTALLPREFIX)/share/man INSTALLDIRMAN = $(INSTALLPREFIX)/share/man
@ -120,7 +155,8 @@ all: $(LIBRARY) $(EXECUTABLES)
test: check test: check
check: validateminixml validateminiwget check: validateminixml validateminiwget validateupnpreplyparse \
validateportlistingparse validateigddescparse
everything: all $(EXECUTABLES_ADDTESTS) everything: all $(EXECUTABLES_ADDTESTS)
@ -148,45 +184,78 @@ validateminiwget: testminiwget minihttptestserver testminiwget.sh
./testminiwget.sh ./testminiwget.sh
touch $@ touch $@
validateupnpreplyparse: testupnpreplyparse testupnpreplyparse.sh
@echo "upnpreplyparse validation test"
./testupnpreplyparse.sh
touch $@
validateportlistingparse: testportlistingparse
@echo "portlistingparse validation test"
./testportlistingparse
touch $@
validateigddescparse: testigddescparse
@echo "igd desc parse validation test"
./testigddescparse testdesc/new_LiveBox_desc.xml testdesc/new_LiveBox_desc.values
./testigddescparse testdesc/linksys_WAG200G_desc.xml testdesc/linksys_WAG200G_desc.values
touch $@
clean: clean:
$(RM) $(LIBRARY) $(SHAREDLIBRARY) $(EXECUTABLES) $(OBJS) miniupnpcstrings.h $(RM) $(LIBRARY) $(SHAREDLIBRARY) $(EXECUTABLES) $(OBJS) miniupnpcstrings.h
$(RM) $(EXECUTABLES_ADDTESTS)
# clean python stuff # clean python stuff
$(RM) pythonmodule pythonmodule3 validateminixml validateminiwget $(RM) pythonmodule pythonmodule3
$(RM) validateminixml validateminiwget validateupnpreplyparse
$(RM) validateigddescparse
$(RM) minihttptestserver
$(RM) -r build/ dist/ $(RM) -r build/ dist/
#python setup.py clean #python setup.py clean
# clean jnaerator stuff # clean jnaerator stuff
$(RM) _jnaerator.* java/miniupnpc_$(OS).jar $(RM) _jnaerator.* java/miniupnpc_$(OS).jar
distclean: clean
$(RM) $(JNAERATOR) java/*.jar java/*.class out.errors.txt
updateversion: miniupnpc.h updateversion: miniupnpc.h
cp miniupnpc.h miniupnpc.h.bak cp miniupnpc.h miniupnpc.h.bak
sed 's/\(.*MINIUPNPC_API_VERSION\s\+\)[0-9]\+/\1$(APIVERSION)/' < miniupnpc.h.bak > miniupnpc.h sed 's/\(.*MINIUPNPC_API_VERSION\s\+\)[0-9]\+/\1$(APIVERSION)/' < miniupnpc.h.bak > miniupnpc.h
install: updateversion $(FILESTOINSTALL) install: updateversion $(FILESTOINSTALL)
$(INSTALL) -d $(INSTALLDIRINC) $(INSTALL) -d $(DESTDIR)$(INSTALLDIRINC)
$(INSTALL) -m 644 $(HEADERS) $(INSTALLDIRINC) $(INSTALL) -m 644 $(HEADERS) $(DESTDIR)$(INSTALLDIRINC)
$(INSTALL) -d $(INSTALLDIRLIB) $(INSTALL) -d $(DESTDIR)$(INSTALLDIRLIB)
$(INSTALL) -m 644 $(LIBRARY) $(INSTALLDIRLIB) $(INSTALL) -m 644 $(LIBRARY) $(DESTDIR)$(INSTALLDIRLIB)
ifneq ($(OS), AmigaOS) ifneq ($(OS), AmigaOS)
$(INSTALL) -m 644 $(SHAREDLIBRARY) $(INSTALLDIRLIB)/$(SONAME) $(INSTALL) -m 644 $(SHAREDLIBRARY) $(DESTDIR)$(INSTALLDIRLIB)/$(SONAME)
ln -fs $(SONAME) $(INSTALLDIRLIB)/$(SHAREDLIBRARY) ln -fs $(SONAME) $(DESTDIR)$(INSTALLDIRLIB)/$(SHAREDLIBRARY)
endif endif
$(INSTALL) -d $(INSTALLDIRBIN) $(INSTALL) -d $(DESTDIR)$(INSTALLDIRBIN)
ifeq ($(OS), AmigaOS) ifeq ($(OS), AmigaOS)
$(INSTALL) -m 755 upnpc-static $(INSTALLDIRBIN)/upnpc $(INSTALL) -m 755 upnpc-static $(DESTDIR)$(INSTALLDIRBIN)/upnpc
else else
$(INSTALL) -m 755 upnpc-shared $(INSTALLDIRBIN)/upnpc $(INSTALL) -m 755 upnpc-shared $(DESTDIR)$(INSTALLDIRBIN)/upnpc
endif endif
$(INSTALL) -m 755 external-ip.sh $(INSTALLDIRBIN)/external-ip $(INSTALL) -m 755 external-ip.sh $(DESTDIR)$(INSTALLDIRBIN)/external-ip
ifneq ($(OS), AmigaOS) ifneq ($(OS), AmigaOS)
$(INSTALL) -d $(INSTALLDIRMAN)/man3 $(INSTALL) -d $(DESTDIR)$(INSTALLDIRMAN)/man3
$(INSTALL) man3/miniupnpc.3 $(INSTALLDIRMAN)/man3/miniupnpc.3 $(INSTALL) -m 644 man3/miniupnpc.3 $(DESTDIR)$(INSTALLDIRMAN)/man3/miniupnpc.3
ifeq ($(OS), Linux)
gzip -f $(DESTDIR)$(INSTALLDIRMAN)/man3/miniupnpc.3
endif
endif endif
install-static: updateversion $(FILESTOINSTALL)
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRINC)
$(INSTALL) -m 644 $(HEADERS) $(DESTDIR)$(INSTALLDIRINC)
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRLIB)
$(INSTALL) -m 644 $(LIBRARY) $(DESTDIR)$(INSTALLDIRLIB)
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRBIN)
$(INSTALL) -m 755 external-ip.sh $(DESTDIR)$(INSTALLDIRBIN)/external-ip
cleaninstall: cleaninstall:
$(RM) -r $(INSTALLDIRINC) $(RM) -r $(DESTDIR)$(INSTALLDIRINC)
$(RM) $(INSTALLDIRLIB)/$(LIBRARY) $(RM) $(DESTDIR)$(INSTALLDIRLIB)/$(LIBRARY)
$(RM) $(INSTALLDIRLIB)/$(SHAREDLIBRARY) $(RM) $(DESTDIR)$(INSTALLDIRLIB)/$(SHAREDLIBRARY)
depend: depend:
makedepend -Y -- $(CFLAGS) -- $(SRCS) 2>/dev/null makedepend -Y -- $(CFLAGS) -- $(SRCS) 2>/dev/null
@ -202,10 +271,13 @@ else
$(CC) -shared $(LDFLAGS) -Wl,-soname,$(SONAME) -o $@ $^ $(CC) -shared $(LDFLAGS) -Wl,-soname,$(SONAME) -o $@ $^
endif endif
upnpc-static: upnpc.o $(LIBRARY) $(LDLIBS) upnpc-static: upnpc.o $(LIBRARY)
$(CC) $(LDFLAGS) -o $@ $^ $(CC) $(LDFLAGS) -o $@ $^
upnpc-shared: upnpc.o $(SHAREDLIBRARY) $(LDLIBS) upnpc-shared: upnpc.o $(SHAREDLIBRARY)
$(CC) $(LDFLAGS) -o $@ $^
listdevices: listdevices.o $(LIBRARY) $(LDLIBS)
$(CC) $(LDFLAGS) -o $@ $^ $(CC) $(LDFLAGS) -o $@ $^
testminixml: $(TESTMINIXMLOBJS) testminixml: $(TESTMINIXMLOBJS)
@ -218,21 +290,20 @@ testupnpreplyparse: $(TESTUPNPREPLYPARSE)
testigddescparse: $(TESTIGDDESCPARSE) testigddescparse: $(TESTIGDDESCPARSE)
testportlistingparse: $(TESTPORTLISTINGPARSE)
miniupnpcstrings.h: miniupnpcstrings.h.in updateminiupnpcstrings.sh VERSION miniupnpcstrings.h: miniupnpcstrings.h.in updateminiupnpcstrings.sh VERSION
$(SH) updateminiupnpcstrings.sh $(SH) updateminiupnpcstrings.sh
jnaerator-0.9.8-shaded.jar: # ftp tool supplied with OpenBSD can download files from http.
wget $(JNAERATORBASEURL)/$@ || curl -o $@ $(JNAERATORBASEURL)/$@ jnaerator-%.jar:
wget $(JNAERATORBASEURL)/$@ || \
jnaerator-0.9.7.jar: curl -o $@ $(JNAERATORBASEURL)/$@ || \
wget $(JNAERATORBASEURL)/$@ || curl -o $@ $(JNAERATORBASEURL)/$@ ftp $(JNAERATORBASEURL)/$@
jnaerator-0.9.3.jar:
wget $(JNAERATORBASEURL)/$@ || curl -o $@ $(JNAERATORBASEURL)/$@
jar: $(SHAREDLIBRARY) $(JNAERATOR) jar: $(SHAREDLIBRARY) $(JNAERATOR)
$(JAVA) -jar $(JNAERATOR) -library miniupnpc \ $(JAVA) -jar $(JNAERATOR) $(JNAERATORARGS) \
miniupnpc.h declspec.h upnpcommands.h upnpreplyparse.h \ miniupnpc.h miniupnpc_declspec.h upnpcommands.h upnpreplyparse.h \
igd_desc_parse.h miniwget.h upnperrors.h $(SHAREDLIBRARY) \ igd_desc_parse.h miniwget.h upnperrors.h $(SHAREDLIBRARY) \
-package fr.free.miniupnp -o . -jar java/miniupnpc_$(JARSUFFIX).jar -v -package fr.free.miniupnp -o . -jar java/miniupnpc_$(JARSUFFIX).jar -v
@ -265,27 +336,40 @@ minihttptestserver: minihttptestserver.o
# DO NOT DELETE THIS LINE -- make depend depends on it. # DO NOT DELETE THIS LINE -- make depend depends on it.
igd_desc_parse.o: igd_desc_parse.h igd_desc_parse.o: igd_desc_parse.h
miniupnpc.o: miniupnpc.h declspec.h igd_desc_parse.h minissdpc.h miniwget.h miniupnpc.o: miniupnpc.h miniupnpc_declspec.h igd_desc_parse.h upnpdev.h
miniupnpc.o: minisoap.h minixml.h upnpcommands.h upnpreplyparse.h miniupnpc.o: minissdpc.h miniwget.h minisoap.h minixml.h upnpcommands.h
miniupnpc.o: portlistingparse.h miniupnpctypes.h connecthostport.h miniupnpc.o: upnpreplyparse.h portlistingparse.h miniupnpctypes.h
miniupnpc.o: receivedata.h miniupnpc.o: connecthostport.h
minixml.o: minixml.h minixml.o: minixml.h
minisoap.o: minisoap.h miniupnpcstrings.h minisoap.o: minisoap.h miniupnpcstrings.h
miniwget.o: miniupnpcstrings.h miniwget.h declspec.h connecthostport.h miniwget.o: miniupnpcstrings.h miniwget.h miniupnpc_declspec.h
miniwget.o: receivedata.h miniwget.o: connecthostport.h receivedata.h
upnpc.o: miniwget.h declspec.h miniupnpc.h igd_desc_parse.h upnpcommands.h upnpc.o: miniwget.h miniupnpc_declspec.h miniupnpc.h igd_desc_parse.h
upnpc.o: upnpreplyparse.h portlistingparse.h miniupnpctypes.h upnperrors.h upnpc.o: upnpdev.h upnpcommands.h upnpreplyparse.h portlistingparse.h
upnpcommands.o: upnpcommands.h upnpreplyparse.h portlistingparse.h declspec.h upnpc.o: miniupnpctypes.h upnperrors.h miniupnpcstrings.h
upnpcommands.o: miniupnpctypes.h miniupnpc.h igd_desc_parse.h upnpcommands.o: upnpcommands.h upnpreplyparse.h portlistingparse.h
upnpcommands.o: miniupnpc_declspec.h miniupnpctypes.h miniupnpc.h
upnpcommands.o: igd_desc_parse.h upnpdev.h
upnpreplyparse.o: upnpreplyparse.h minixml.h upnpreplyparse.o: upnpreplyparse.h minixml.h
testminixml.o: minixml.h igd_desc_parse.h testminixml.o: minixml.h igd_desc_parse.h
minixmlvalid.o: minixml.h minixmlvalid.o: minixml.h
testupnpreplyparse.o: upnpreplyparse.h testupnpreplyparse.o: upnpreplyparse.h
minissdpc.o: minissdpc.h miniupnpc.h declspec.h igd_desc_parse.h codelength.h minissdpc.o: minissdpc.h miniupnpc_declspec.h upnpdev.h miniupnpc.h
upnperrors.o: upnperrors.h declspec.h upnpcommands.h upnpreplyparse.h minissdpc.o: igd_desc_parse.h receivedata.h codelength.h
upnperrors.o: portlistingparse.h miniupnpctypes.h miniupnpc.h upnperrors.o: upnperrors.h miniupnpc_declspec.h upnpcommands.h
upnperrors.o: igd_desc_parse.h upnperrors.o: upnpreplyparse.h portlistingparse.h miniupnpctypes.h
testigddescparse.o: igd_desc_parse.h minixml.h miniupnpc.h declspec.h upnperrors.o: miniupnpc.h igd_desc_parse.h upnpdev.h
testminiwget.o: miniwget.h declspec.h testigddescparse.o: igd_desc_parse.h minixml.h miniupnpc.h
testigddescparse.o: miniupnpc_declspec.h upnpdev.h
testminiwget.o: miniwget.h miniupnpc_declspec.h
connecthostport.o: connecthostport.h connecthostport.o: connecthostport.h
portlistingparse.o: portlistingparse.h miniupnpc_declspec.h miniupnpctypes.h
portlistingparse.o: minixml.h
receivedata.o: receivedata.h receivedata.o: receivedata.h
upnpdev.o: upnpdev.h miniupnpc_declspec.h
testportlistingparse.o: portlistingparse.h miniupnpc_declspec.h
testportlistingparse.o: miniupnpctypes.h
miniupnpcmodule.o: miniupnpc.h miniupnpc_declspec.h igd_desc_parse.h
miniupnpcmodule.o: upnpdev.h upnpcommands.h upnpreplyparse.h
miniupnpcmodule.o: portlistingparse.h miniupnpctypes.h upnperrors.h
listdevices.o: miniupnpc.h miniupnpc_declspec.h igd_desc_parse.h upnpdev.h

View File

@ -1,7 +1,7 @@
# $Id: Makefile.mingw,v 1.16 2011/04/18 17:39:31 nanard Exp $ # $Id: Makefile.mingw,v 1.21 2015/09/18 12:45:16 nanard Exp $
# Miniupnp project. # Miniupnp project.
# http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ # http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
# (c) 2005-2011 Thomas Bernard # (c) 2005-2015 Thomas Bernard
# This Makefile is made for MinGW # This Makefile is made for MinGW
# #
CC = gcc CC = gcc
@ -9,11 +9,13 @@ CC = gcc
CFLAGS = -Wall -Os -DNDEBUG -D_WIN32_WINNT=0X501 CFLAGS = -Wall -Os -DNDEBUG -D_WIN32_WINNT=0X501
LDLIBS = -lws2_32 -liphlpapi LDLIBS = -lws2_32 -liphlpapi
# -lwsock32 # -lwsock32
# -liphlpapi is used for GetBestRoute() # -liphlpapi is needed for GetBestRoute() and GetIpAddrTable()
PYTHON=\utils\python25\python PYTHON=\utils\python25\python
OBJS=miniwget.o minixml.o igd_desc_parse.o minisoap.o \ OBJS=miniwget.o minixml.o igd_desc_parse.o minisoap.o \
minissdpc.o \
miniupnpc.o upnpreplyparse.o upnpcommands.o upnperrors.o \ miniupnpc.o upnpreplyparse.o upnpcommands.o upnperrors.o \
connecthostport.o portlistingparse.o receivedata.o connecthostport.o portlistingparse.o receivedata.o \
upnpdev.o
OBJSDLL=$(addprefix dll/, $(OBJS)) OBJSDLL=$(addprefix dll/, $(OBJS))
all: init upnpc-static upnpc-shared testminixml libminiupnpc.a miniupnpc.dll all: init upnpc-static upnpc-shared testminixml libminiupnpc.a miniupnpc.dll
@ -50,18 +52,19 @@ dll/upnpc.o: upnpc.o
echo $@ generated with $< echo $@ generated with $<
.c.o: .c.o:
$(CC) $(CFLAGS) -DSTATICLIB -c -o $@ $< $(CC) $(CFLAGS) -DMINIUPNP_STATICLIB -c -o $@ $<
$(CC) $(CFLAGS) -DMINIUPNP_EXPORTS -c -o dll/$@ $< $(CC) $(CFLAGS) -DMINIUPNP_EXPORTS -c -o dll/$@ $<
upnpc.o: upnpc.o:
$(CC) $(CFLAGS) -DSTATICLIB -c -o $@ $< $(CC) $(CFLAGS) -DMINIUPNP_STATICLIB -c -o $@ $<
$(CC) $(CFLAGS) -c -o dll/$@ $< $(CC) $(CFLAGS) -c -o dll/$@ $<
# --enable-stdcall-fixup
upnpc-static: upnpc.o libminiupnpc.a upnpc-static: upnpc.o libminiupnpc.a
$(CC) -enable-stdcall-fixup -o $@ $^ $(LDLIBS) $(CC) -o $@ $^ $(LDLIBS)
upnpc-shared: dll/upnpc.o miniupnpc.lib upnpc-shared: dll/upnpc.o miniupnpc.lib
$(CC) -enable-stdcall-fixup -o $@ $^ $(LDLIBS) $(CC) -o $@ $^ $(LDLIBS)
wingenminiupnpcstrings: wingenminiupnpcstrings.o wingenminiupnpcstrings: wingenminiupnpcstrings.o
@ -70,9 +73,10 @@ wingenminiupnpcstrings.o: wingenminiupnpcstrings.c
miniupnpcstrings.h: miniupnpcstrings.h.in wingenminiupnpcstrings miniupnpcstrings.h: miniupnpcstrings.h.in wingenminiupnpcstrings
wingenminiupnpcstrings $< $@ wingenminiupnpcstrings $< $@
minixml.o: minixml.c minixml.h miniupnpcstrings.h minixml.o: minixml.c minixml.h
upnpc.o: upnpc.c miniwget.h minisoap.h miniupnpc.h igd_desc_parse.h upnpreplyparse.h upnpcommands.h upnperrors.h upnpc.o: upnpc.c miniwget.h minisoap.h miniupnpc.h igd_desc_parse.h
upnpc.o: upnpreplyparse.h upnpcommands.h upnperrors.h miniupnpcstrings.h
miniwget.o: miniwget.c miniwget.h miniupnpcstrings.h connecthostport.h miniwget.o: miniwget.c miniwget.h miniupnpcstrings.h connecthostport.h
@ -88,3 +92,7 @@ upnpreplyparse.o: upnpreplyparse.c upnpreplyparse.h minixml.h
upnpcommands.o: upnpcommands.c upnpcommands.h upnpreplyparse.h miniupnpc.h portlistingparse.h upnpcommands.o: upnpcommands.c upnpcommands.h upnpreplyparse.h miniupnpc.h portlistingparse.h
minissdpc.o: minissdpc.c minissdpc.h receivedata.h
upnpdev.o: upnpdev.c upnpdev.h

View File

@ -3,16 +3,11 @@ Project web page: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
github: https://github.com/miniupnp/miniupnp github: https://github.com/miniupnp/miniupnp
freecode: http://freecode.com/projects/miniupnp freecode: http://freecode.com/projects/miniupnp
Author: Thomas Bernard Author: Thomas Bernard
Copyright (c) 2005-2012 Thomas Bernard Copyright (c) 2005-2014 Thomas Bernard
This software is subject to the conditions detailed in the This software is subject to the conditions detailed in the
LICENSE file provided within this distribution. LICENSE file provided within this distribution.
For the comfort of Win32 users, bsdqueue.h is included in the distribution.
Its licence is included in the header of the file.
bsdqueue.h is a copy of the sys/queue.h of an OpenBSD system.
* miniUPnP Client - miniUPnPc * * miniUPnP Client - miniUPnPc *
To compile, simply run 'gmake' (could be 'make' on your system). To compile, simply run 'gmake' (could be 'make' on your system).

View File

@ -1,7 +1,7 @@
/* $Id: connecthostport.c,v 1.9 2012/06/26 00:00:27 nanard Exp $ */ /* $Id: connecthostport.c,v 1.14 2015/10/02 11:08:34 nanard Exp $ */
/* Project : miniupnp /* Project : miniupnp
* Author : Thomas Bernard * Author : Thomas Bernard
* Copyright (c) 2010-2012 Thomas Bernard * Copyright (c) 2010-2015 Thomas Bernard
* This software is subject to the conditions detailed in the * This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */ * LICENCE file provided in this distribution. */
@ -23,7 +23,12 @@
#define socklen_t int #define socklen_t int
#else /* #ifdef _WIN32 */ #else /* #ifdef _WIN32 */
#include <unistd.h> #include <unistd.h>
#include <sys/types.h>
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
#include <sys/time.h>
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
#include <sys/param.h> #include <sys/param.h>
#include <sys/select.h>
#include <errno.h> #include <errno.h>
#define closesocket close #define closesocket close
#include <netdb.h> #include <netdb.h>
@ -32,8 +37,8 @@
* during the connect() call */ * during the connect() call */
#define MINIUPNPC_IGNORE_EINTR #define MINIUPNPC_IGNORE_EINTR
#ifndef USE_GETHOSTBYNAME #ifndef USE_GETHOSTBYNAME
#include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/select.h>
#endif /* #ifndef USE_GETHOSTBYNAME */ #endif /* #ifndef USE_GETHOSTBYNAME */
#endif /* #else _WIN32 */ #endif /* #else _WIN32 */
@ -50,6 +55,10 @@
#include "connecthostport.h" #include "connecthostport.h"
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
/* connecthostport() /* connecthostport()
* return a socket connected (TCP) to the host and port * return a socket connected (TCP) to the host and port
* or -1 in case of error */ * or -1 in case of error */
@ -104,7 +113,10 @@ int connecthostport(const char * host, unsigned short port,
dest.sin_port = htons(port); dest.sin_port = htons(port);
n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in)); n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in));
#ifdef MINIUPNPC_IGNORE_EINTR #ifdef MINIUPNPC_IGNORE_EINTR
while(n < 0 && errno == EINTR) /* EINTR The system call was interrupted by a signal that was caught
* EINPROGRESS The socket is nonblocking and the connection cannot
* be completed immediately. */
while(n < 0 && (errno == EINTR || errno = EINPROGRESS))
{ {
socklen_t len; socklen_t len;
fd_set wset; fd_set wset;
@ -143,8 +155,7 @@ int connecthostport(const char * host, unsigned short port,
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_UNSPEC; /* AF_INET, AF_INET6 or AF_UNSPEC */ hints.ai_family = AF_UNSPEC; /* AF_INET, AF_INET6 or AF_UNSPEC */
/* hints.ai_protocol = IPPROTO_TCP; */ /* hints.ai_protocol = IPPROTO_TCP; */
snprintf(port_str, 7, "%hu", port); snprintf(port_str, sizeof(port_str), "%hu", port);
port_str[7] = '\0';
if(host[0] == '[') if(host[0] == '[')
{ {
/* literal ip v6 address */ /* literal ip v6 address */
@ -199,7 +210,10 @@ int connecthostport(const char * host, unsigned short port,
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
n = connect(s, p->ai_addr, p->ai_addrlen); n = connect(s, p->ai_addr, p->ai_addrlen);
#ifdef MINIUPNPC_IGNORE_EINTR #ifdef MINIUPNPC_IGNORE_EINTR
while(n < 0 && errno == EINTR) /* EINTR The system call was interrupted by a signal that was caught
* EINPROGRESS The socket is nonblocking and the connection cannot
* be completed immediately. */
while(n < 0 && (errno == EINTR || errno == EINPROGRESS))
{ {
socklen_t len; socklen_t len;
fd_set wset; fd_set wset;

View File

@ -1,8 +1,8 @@
/* $Id: igd_desc_parse.c,v 1.14 2011/04/11 09:19:24 nanard Exp $ */ /* $Id: igd_desc_parse.c,v 1.17 2015/09/15 13:30:04 nanard Exp $ */
/* Project : miniupnp /* Project : miniupnp
* http://miniupnp.free.fr/ * http://miniupnp.free.fr/
* Author : Thomas Bernard * Author : Thomas Bernard
* Copyright (c) 2005-2010 Thomas Bernard * Copyright (c) 2005-2015 Thomas Bernard
* This software is subject to the conditions detailed in the * This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */ * LICENCE file provided in this distribution. */
@ -15,7 +15,9 @@
void IGDstartelt(void * d, const char * name, int l) void IGDstartelt(void * d, const char * name, int l)
{ {
struct IGDdatas * datas = (struct IGDdatas *)d; struct IGDdatas * datas = (struct IGDdatas *)d;
memcpy( datas->cureltname, name, l); if(l >= MINIUPNPC_URL_MAXSIZE)
l = MINIUPNPC_URL_MAXSIZE-1;
memcpy(datas->cureltname, name, l);
datas->cureltname[l] = '\0'; datas->cureltname[l] = '\0';
datas->level++; datas->level++;
if( (l==7) && !memcmp(name, "service", l) ) { if( (l==7) && !memcmp(name, "service", l) ) {
@ -26,6 +28,8 @@ void IGDstartelt(void * d, const char * name, int l)
} }
} }
#define COMPARE(str, cstr) (0==memcmp(str, cstr, sizeof(cstr) - 1))
/* End element handler : /* End element handler :
* update nesting level counter and update parser state if * update nesting level counter and update parser state if
* service element is parsed */ * service element is parsed */
@ -36,23 +40,16 @@ void IGDendelt(void * d, const char * name, int l)
/*printf("endelt %2d %.*s\n", datas->level, l, name);*/ /*printf("endelt %2d %.*s\n", datas->level, l, name);*/
if( (l==7) && !memcmp(name, "service", l) ) if( (l==7) && !memcmp(name, "service", l) )
{ {
/* if(COMPARE(datas->tmp.servicetype,
if( datas->state < 1 "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:")) {
&& !strcmp(datas->servicetype,
// "urn:schemas-upnp-org:service:WANIPConnection:1") )
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"))
datas->state ++;
*/
if(0==strcmp(datas->tmp.servicetype,
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")) {
memcpy(&datas->CIF, &datas->tmp, sizeof(struct IGDdatas_service)); memcpy(&datas->CIF, &datas->tmp, sizeof(struct IGDdatas_service));
} else if(0==strcmp(datas->tmp.servicetype, } else if(COMPARE(datas->tmp.servicetype,
"urn:schemas-upnp-org:service:WANIPv6FirewallControl:1")) { "urn:schemas-upnp-org:service:WANIPv6FirewallControl:")) {
memcpy(&datas->IPv6FC, &datas->tmp, sizeof(struct IGDdatas_service)); memcpy(&datas->IPv6FC, &datas->tmp, sizeof(struct IGDdatas_service));
} else if(0==strcmp(datas->tmp.servicetype, } else if(COMPARE(datas->tmp.servicetype,
"urn:schemas-upnp-org:service:WANIPConnection:1") "urn:schemas-upnp-org:service:WANIPConnection:")
|| 0==strcmp(datas->tmp.servicetype, || COMPARE(datas->tmp.servicetype,
"urn:schemas-upnp-org:service:WANPPPConnection:1") ) { "urn:schemas-upnp-org:service:WANPPPConnection:") ) {
if(datas->first.servicetype[0] == '\0') { if(datas->first.servicetype[0] == '\0') {
memcpy(&datas->first, &datas->tmp, sizeof(struct IGDdatas_service)); memcpy(&datas->first, &datas->tmp, sizeof(struct IGDdatas_service));
} else { } else {
@ -93,6 +90,7 @@ void IGDdata(void * d, const char * data, int l)
} }
} }
#ifdef DEBUG
void printIGD(struct IGDdatas * d) void printIGD(struct IGDdatas * d)
{ {
printf("urlbase = '%s'\n", d->urlbase); printf("urlbase = '%s'\n", d->urlbase);
@ -121,5 +119,5 @@ void printIGD(struct IGDdatas * d)
printf(" eventSubURL = '%s'\n", d->IPv6FC.eventsuburl); printf(" eventSubURL = '%s'\n", d->IPv6FC.eventsuburl);
printf(" SCPDURL = '%s'\n", d->IPv6FC.scpdurl); printf(" SCPDURL = '%s'\n", d->IPv6FC.scpdurl);
} }
#endif /* DEBUG */

View File

@ -1,7 +1,7 @@
/* $Id: minisoap.c,v 1.22 2012/01/21 13:30:31 nanard Exp $ */ /* $Id: minisoap.c,v 1.23 2014/11/04 22:31:55 nanard Exp $ */
/* Project : miniupnp /* Project : miniupnp
* Author : Thomas Bernard * Author : Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard * Copyright (c) 2005-2014 Thomas Bernard
* This software is subject to the conditions detailed in the * This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. * LICENCE file provided in this distribution.
* *
@ -96,7 +96,7 @@ int soapPostSubmit(int fd,
headerssize = snprintf(headerbuf, sizeof(headerbuf), headerssize = snprintf(headerbuf, sizeof(headerbuf),
"POST %s HTTP/%s\r\n" "POST %s HTTP/%s\r\n"
"Host: %s%s\r\n" "Host: %s%s\r\n"
"User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n" "User-Agent: " OS_STRING ", " UPNP_VERSION_STRING ", MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
"Content-Length: %d\r\n" "Content-Length: %d\r\n"
"Content-Type: text/xml\r\n" "Content-Type: text/xml\r\n"
"SOAPAction: \"%s\"\r\n" "SOAPAction: \"%s\"\r\n"

View File

@ -1,71 +1,194 @@
/* $Id: minissdpc.c,v 1.16 2012/03/05 19:42:46 nanard Exp $ */ /* $Id: minissdpc.c,v 1.29 2015/10/08 16:15:47 nanard Exp $ */
/* Project : miniupnp /* Project : miniupnp
* Web : http://miniupnp.free.fr/ * Web : http://miniupnp.free.fr/
* Author : Thomas BERNARD * Author : Thomas BERNARD
* copyright (c) 2005-2012 Thomas Bernard * copyright (c) 2005-2015 Thomas Bernard
* This software is subjet to the conditions detailed in the * This software is subjet to the conditions detailed in the
* provided LICENCE file. */ * provided LICENCE file. */
/*#include <syslog.h>*/ /*#include <syslog.h>*/
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#ifndef _WIN32
#include <unistd.h>
#endif
#include <sys/types.h> #include <sys/types.h>
#if defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__) #if defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)
#ifdef _WIN32 #ifdef _WIN32
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
#include <io.h> #include <io.h>
#include <iphlpapi.h>
#include <winsock.h> #include <winsock.h>
#define snprintf _snprintf
#if !defined(_MSC_VER)
#include <stdint.h> #include <stdint.h>
#else /* !defined(_MSC_VER) */
typedef SSIZE_T ssize_t; typedef unsigned short uint16_t;
#endif #endif /* !defined(_MSC_VER) */
#ifndef strncasecmp
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
#define strncasecmp _memicmp
#else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
#define strncasecmp memicmp
#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
#endif /* #ifndef strncasecmp */
#endif /* _WIN32 */
#if defined(__amigaos__) || defined(__amigaos4__) #if defined(__amigaos__) || defined(__amigaos4__)
#include <sys/socket.h> #include <sys/socket.h>
#endif #endif /* defined(__amigaos__) || defined(__amigaos4__) */
#if defined(__amigaos__) #if defined(__amigaos__)
#define uint16_t unsigned short #define uint16_t unsigned short
#endif #endif /* defined(__amigaos__) */
/* Hack */ /* Hack */
#define UNIX_PATH_LEN 108 #define UNIX_PATH_LEN 108
struct sockaddr_un { struct sockaddr_un {
uint16_t sun_family; uint16_t sun_family;
char sun_path[UNIX_PATH_LEN]; char sun_path[UNIX_PATH_LEN];
}; };
#else #else /* defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__) */
#include <strings.h>
#include <unistd.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/un.h> #include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <net/if.h>
#define closesocket close
#endif
#ifdef _WIN32
#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
#else
#define PRINT_SOCKET_ERROR(x) perror(x)
#endif
#if !defined(__DragonFly__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__APPLE__) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__sun) && !defined(__GNU__) && !defined(__FreeBSD_kernel__)
#define HAS_IP_MREQN
#endif
#if defined(HAS_IP_MREQN) && defined(NEED_STRUCT_IP_MREQN)
/* Several versions of glibc don't define this structure,
* define it here and compile with CFLAGS NEED_STRUCT_IP_MREQN */
struct ip_mreqn
{
struct in_addr imr_multiaddr; /* IP multicast address of group */
struct in_addr imr_address; /* local IP address of interface */
int imr_ifindex; /* Interface index */
};
#endif
#if defined(__amigaos__) || defined(__amigaos4__)
/* Amiga OS specific stuff */
#define TIMEVAL struct timeval
#endif #endif
#include "minissdpc.h" #include "minissdpc.h"
#include "miniupnpc.h" #include "miniupnpc.h"
#include "receivedata.h"
#if !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__))
#include "codelength.h" #include "codelength.h"
struct UPNPDev * struct UPNPDev *
getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath) getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath, int * error)
{ {
struct UPNPDev * tmp;
struct UPNPDev * devlist = NULL; struct UPNPDev * devlist = NULL;
unsigned char buffer[2048]; int s;
ssize_t n; int res;
unsigned char * p;
unsigned char * url; s = connectToMiniSSDPD(socketpath);
unsigned int i; if (s < 0) {
unsigned int urlsize, stsize, usnsize, l; if (error)
*error = s;
return NULL;
}
res = requestDevicesFromMiniSSDPD(s, devtype);
if (res < 0) {
if (error)
*error = res;
} else {
devlist = receiveDevicesFromMiniSSDPD(s, error);
}
disconnectFromMiniSSDPD(s);
return devlist;
}
/* macros used to read from unix socket */
#define READ_BYTE_BUFFER(c) \
if((int)bufferindex >= n) { \
n = read(s, buffer, sizeof(buffer)); \
if(n<=0) break; \
bufferindex = 0; \
} \
c = buffer[bufferindex++];
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif /* MIN */
#define READ_COPY_BUFFER(dst, len) \
for(l = len, p = (unsigned char *)dst; l > 0; ) { \
unsigned int lcopy; \
if((int)bufferindex >= n) { \
n = read(s, buffer, sizeof(buffer)); \
if(n<=0) break; \
bufferindex = 0; \
} \
lcopy = MIN(l, (n - bufferindex)); \
memcpy(p, buffer + bufferindex, lcopy); \
l -= lcopy; \
p += lcopy; \
bufferindex += lcopy; \
}
#define READ_DISCARD_BUFFER(len) \
for(l = len; l > 0; ) { \
unsigned int lcopy; \
if(bufferindex >= n) { \
n = read(s, buffer, sizeof(buffer)); \
if(n<=0) break; \
bufferindex = 0; \
} \
lcopy = MIN(l, (n - bufferindex)); \
l -= lcopy; \
bufferindex += lcopy; \
}
int
connectToMiniSSDPD(const char * socketpath)
{
int s; int s;
struct sockaddr_un addr; struct sockaddr_un addr;
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
struct timeval timeout;
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
s = socket(AF_UNIX, SOCK_STREAM, 0); s = socket(AF_UNIX, SOCK_STREAM, 0);
if(s < 0) if(s < 0)
{ {
/*syslog(LOG_ERR, "socket(unix): %m");*/ /*syslog(LOG_ERR, "socket(unix): %m");*/
perror("socket(unix)"); perror("socket(unix)");
return NULL; return MINISSDPC_SOCKET_ERROR;
} }
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
/* setting a 3 seconds timeout */
timeout.tv_sec = 3;
timeout.tv_usec = 0;
if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0)
{
perror("setsockopt");
}
timeout.tv_sec = 3;
timeout.tv_usec = 0;
if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0)
{
perror("setsockopt");
}
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
if(!socketpath)
socketpath = "/var/run/minissdpd.sock";
addr.sun_family = AF_UNIX; addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socketpath, sizeof(addr.sun_path)); strncpy(addr.sun_path, socketpath, sizeof(addr.sun_path));
/* TODO : check if we need to handle the EINTR */ /* TODO : check if we need to handle the EINTR */
@ -73,17 +196,45 @@ getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath)
{ {
/*syslog(LOG_WARNING, "connect(\"%s\"): %m", socketpath);*/ /*syslog(LOG_WARNING, "connect(\"%s\"): %m", socketpath);*/
close(s); close(s);
return NULL; return MINISSDPC_SOCKET_ERROR;
} }
return s;
}
int
disconnectFromMiniSSDPD(int s)
{
if (close(s) < 0)
return MINISSDPC_SOCKET_ERROR;
return MINISSDPC_SUCCESS;
}
int
requestDevicesFromMiniSSDPD(int s, const char * devtype)
{
unsigned char buffer[256];
unsigned char * p;
unsigned int stsize, l;
stsize = strlen(devtype); stsize = strlen(devtype);
buffer[0] = 1; /* request type 1 : request devices/services by type */ if(stsize == 8 && 0 == memcmp(devtype, "ssdp:all", 8))
{
buffer[0] = 3; /* request type 3 : everything */
}
else
{
buffer[0] = 1; /* request type 1 : request devices/services by type */
}
p = buffer + 1; p = buffer + 1;
l = stsize; CODELENGTH(l, p); l = stsize; CODELENGTH(l, p);
if(p + stsize > buffer + sizeof(buffer)) if(p + stsize > buffer + sizeof(buffer))
{ {
/* devtype is too long ! */ /* devtype is too long ! */
close(s); #ifdef DEBUG
return NULL; fprintf(stderr, "devtype is too long ! stsize=%u sizeof(buffer)=%u\n",
stsize, (unsigned)sizeof(buffer));
#endif /* DEBUG */
return MINISSDPC_INVALID_INPUT;
} }
memcpy(p, devtype, stsize); memcpy(p, devtype, stsize);
p += stsize; p += stsize;
@ -91,47 +242,603 @@ getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath)
{ {
/*syslog(LOG_ERR, "write(): %m");*/ /*syslog(LOG_ERR, "write(): %m");*/
perror("minissdpc.c: write()"); perror("minissdpc.c: write()");
close(s); return MINISSDPC_SOCKET_ERROR;
return NULL;
} }
return MINISSDPC_SUCCESS;
}
struct UPNPDev *
receiveDevicesFromMiniSSDPD(int s, int * error)
{
struct UPNPDev * tmp;
struct UPNPDev * devlist = NULL;
unsigned char buffer[256];
ssize_t n;
unsigned char * p;
unsigned char * url;
unsigned char * st;
unsigned int bufferindex;
unsigned int i, ndev;
unsigned int urlsize, stsize, usnsize, l;
n = read(s, buffer, sizeof(buffer)); n = read(s, buffer, sizeof(buffer));
if(n<=0) if(n<=0)
{ {
perror("minissdpc.c: read()"); perror("minissdpc.c: read()");
close(s); if (error)
*error = MINISSDPC_SOCKET_ERROR;
return NULL; return NULL;
} }
p = buffer + 1; ndev = buffer[0];
for(i = 0; i < buffer[0]; i++) bufferindex = 1;
for(i = 0; i < ndev; i++)
{ {
if(p+2>=buffer+sizeof(buffer)) DECODELENGTH_READ(urlsize, READ_BYTE_BUFFER);
break; if(n<=0) {
DECODELENGTH(urlsize, p); if (error)
if(p+urlsize+2>=buffer+sizeof(buffer)) *error = MINISSDPC_INVALID_SERVER_REPLY;
break; return devlist;
url = p; }
p += urlsize; #ifdef DEBUG
DECODELENGTH(stsize, p); printf(" urlsize=%u", urlsize);
if(p+stsize+2>=buffer+sizeof(buffer)) #endif /* DEBUG */
break; url = malloc(urlsize);
tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize); if(url == NULL) {
if (error)
*error = MINISSDPC_MEMORY_ERROR;
return devlist;
}
READ_COPY_BUFFER(url, urlsize);
if(n<=0) {
if (error)
*error = MINISSDPC_INVALID_SERVER_REPLY;
goto free_url_and_return;
}
DECODELENGTH_READ(stsize, READ_BYTE_BUFFER);
if(n<=0) {
if (error)
*error = MINISSDPC_INVALID_SERVER_REPLY;
goto free_url_and_return;
}
#ifdef DEBUG
printf(" stsize=%u", stsize);
#endif /* DEBUG */
st = malloc(stsize);
if (st == NULL) {
if (error)
*error = MINISSDPC_MEMORY_ERROR;
goto free_url_and_return;
}
READ_COPY_BUFFER(st, stsize);
if(n<=0) {
if (error)
*error = MINISSDPC_INVALID_SERVER_REPLY;
goto free_url_and_st_and_return;
}
DECODELENGTH_READ(usnsize, READ_BYTE_BUFFER);
if(n<=0) {
if (error)
*error = MINISSDPC_INVALID_SERVER_REPLY;
goto free_url_and_st_and_return;
}
#ifdef DEBUG
printf(" usnsize=%u\n", usnsize);
#endif /* DEBUG */
tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize);
if(tmp == NULL) {
if (error)
*error = MINISSDPC_MEMORY_ERROR;
goto free_url_and_st_and_return;
}
tmp->pNext = devlist; tmp->pNext = devlist;
tmp->descURL = tmp->buffer; tmp->descURL = tmp->buffer;
tmp->st = tmp->buffer + 1 + urlsize; tmp->st = tmp->buffer + 1 + urlsize;
memcpy(tmp->buffer, url, urlsize); memcpy(tmp->buffer, url, urlsize);
tmp->buffer[urlsize] = '\0'; tmp->buffer[urlsize] = '\0';
memcpy(tmp->buffer + urlsize + 1, p, stsize); memcpy(tmp->st, st, stsize);
p += stsize;
tmp->buffer[urlsize+1+stsize] = '\0'; tmp->buffer[urlsize+1+stsize] = '\0';
free(url);
free(st);
url = NULL;
st = NULL;
tmp->usn = tmp->buffer + 1 + urlsize + 1 + stsize;
READ_COPY_BUFFER(tmp->usn, usnsize);
if(n<=0) {
if (error)
*error = MINISSDPC_INVALID_SERVER_REPLY;
goto free_tmp_and_return;
}
tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0';
tmp->scope_id = 0; /* default value. scope_id is not available with MiniSSDPd */
devlist = tmp; devlist = tmp;
/* added for compatibility with recent versions of MiniSSDPd
* >= 2007/12/19 */
DECODELENGTH(usnsize, p);
p += usnsize;
if(p>buffer + sizeof(buffer))
break;
} }
close(s); if (error)
*error = MINISSDPC_SUCCESS;
return devlist;
free_url_and_st_and_return:
free(st);
free_url_and_return:
free(url);
return devlist;
free_tmp_and_return:
free(tmp);
return devlist;
}
#endif /* !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)) */
/* parseMSEARCHReply()
* 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.
* The strings are NOT null terminated */
static void
parseMSEARCHReply(const char * reply, int size,
const char * * location, int * locationsize,
const char * * st, int * stsize,
const char * * usn, int * usnsize)
{
int a, b, i;
i = 0;
a = i; /* start of the line */
b = 0; /* end of the "header" (position of the colon) */
while(i<size)
{
switch(reply[i])
{
case ':':
if(b==0)
{
b = i; /* end of the "header" */
/*for(j=a; j<b; j++)
{
putchar(reply[j]);
}
*/
}
break;
case '\x0a':
case '\x0d':
if(b!=0)
{
/*for(j=b+1; j<i; j++)
{
putchar(reply[j]);
}
putchar('\n');*/
/* skip the colon and white spaces */
do { b++; } while(reply[b]==' ');
if(0==strncasecmp(reply+a, "location", 8))
{
*location = reply+b;
*locationsize = i-b;
}
else if(0==strncasecmp(reply+a, "st", 2))
{
*st = reply+b;
*stsize = i-b;
}
else if(0==strncasecmp(reply+a, "usn", 3))
{
*usn = reply+b;
*usnsize = i-b;
}
b = 0;
}
a = i+1;
break;
default:
break;
}
i++;
}
}
/* port upnp discover : SSDP protocol */
#define SSDP_PORT 1900
#define XSTR(s) STR(s)
#define STR(s) #s
#define UPNP_MCAST_ADDR "239.255.255.250"
/* for IPv6 */
#define UPNP_MCAST_LL_ADDR "FF02::C" /* link-local */
#define UPNP_MCAST_SL_ADDR "FF05::C" /* site-local */
/* direct discovery if minissdpd responses are not sufficient */
/* ssdpDiscoverDevices() :
* return a chained list of all devices found or NULL if
* no devices was found.
* It is up to the caller to free the chained list
* delay is in millisecond (poll).
* UDA v1.1 says :
* The TTL for the IP packet SHOULD default to 2 and
* SHOULD be configurable. */
struct UPNPDev *
ssdpDiscoverDevices(const char * const deviceTypes[],
int delay, const char * multicastif,
int localport,
int ipv6, unsigned char ttl,
int * error,
int searchalltypes)
{
struct UPNPDev * tmp;
struct UPNPDev * devlist = 0;
unsigned int scope_id = 0;
int opt = 1;
static const char MSearchMsgFmt[] =
"M-SEARCH * HTTP/1.1\r\n"
"HOST: %s:" XSTR(SSDP_PORT) "\r\n"
"ST: %s\r\n"
"MAN: \"ssdp:discover\"\r\n"
"MX: %u\r\n"
"\r\n";
int deviceIndex;
char bufr[1536]; /* reception and emission buffer */
int sudp;
int n;
struct sockaddr_storage sockudp_r;
unsigned int mx;
#ifdef NO_GETADDRINFO
struct sockaddr_storage sockudp_w;
#else
int rv;
struct addrinfo hints, *servinfo, *p;
#endif
#ifdef _WIN32
MIB_IPFORWARDROW ip_forward;
unsigned long _ttl = (unsigned long)ttl;
#endif
int linklocal = 1;
if(error)
*error = MINISSDPC_UNKNOWN_ERROR;
if(localport==UPNP_LOCAL_PORT_SAME)
localport = SSDP_PORT;
#ifdef _WIN32
sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP);
#else
sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, 0);
#endif
if(sudp < 0)
{
if(error)
*error = MINISSDPC_SOCKET_ERROR;
PRINT_SOCKET_ERROR("socket");
return NULL;
}
/* reception */
memset(&sockudp_r, 0, sizeof(struct sockaddr_storage));
if(ipv6) {
struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_r;
p->sin6_family = AF_INET6;
if(localport > 0 && localport < 65536)
p->sin6_port = htons((unsigned short)localport);
p->sin6_addr = in6addr_any; /* in6addr_any is not available with MinGW32 3.4.2 */
} else {
struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_r;
p->sin_family = AF_INET;
if(localport > 0 && localport < 65536)
p->sin_port = htons((unsigned short)localport);
p->sin_addr.s_addr = INADDR_ANY;
}
#ifdef _WIN32
/* This code could help us to use the right Network interface for
* SSDP multicast traffic */
/* Get IP associated with the index given in the ip_forward struct
* in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */
if(!ipv6
&& (GetBestRoute(inet_addr("223.255.255.255"), 0, &ip_forward) == NO_ERROR)) {
DWORD dwRetVal = 0;
PMIB_IPADDRTABLE pIPAddrTable;
DWORD dwSize = 0;
#ifdef DEBUG
IN_ADDR IPAddr;
#endif
int i;
#ifdef DEBUG
printf("ifIndex=%lu nextHop=%lx \n", ip_forward.dwForwardIfIndex, ip_forward.dwForwardNextHop);
#endif
pIPAddrTable = (MIB_IPADDRTABLE *) malloc(sizeof (MIB_IPADDRTABLE));
if(pIPAddrTable) {
if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) {
free(pIPAddrTable);
pIPAddrTable = (MIB_IPADDRTABLE *) malloc(dwSize);
}
}
if(pIPAddrTable) {
dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 );
if (dwRetVal == NO_ERROR) {
#ifdef DEBUG
printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries);
#endif
for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) {
#ifdef DEBUG
printf("\n\tInterface Index[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwIndex);
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr;
printf("\tIP Address[%d]: \t%s\n", i, inet_ntoa(IPAddr) );
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask;
printf("\tSubnet Mask[%d]: \t%s\n", i, inet_ntoa(IPAddr) );
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr;
printf("\tBroadCast[%d]: \t%s (%ld)\n", i, inet_ntoa(IPAddr), pIPAddrTable->table[i].dwBCastAddr);
printf("\tReassembly size[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwReasmSize);
printf("\tType and State[%d]:", i);
printf("\n");
#endif
if (pIPAddrTable->table[i].dwIndex == ip_forward.dwForwardIfIndex) {
/* Set the address of this interface to be used */
struct in_addr mc_if;
memset(&mc_if, 0, sizeof(mc_if));
mc_if.s_addr = pIPAddrTable->table[i].dwAddr;
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) {
PRINT_SOCKET_ERROR("setsockopt");
}
((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = pIPAddrTable->table[i].dwAddr;
#ifndef DEBUG
break;
#endif
}
}
}
free(pIPAddrTable);
pIPAddrTable = NULL;
}
}
#endif /* _WIN32 */
#ifdef _WIN32
if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0)
#else
if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0)
#endif
{
if(error)
*error = MINISSDPC_SOCKET_ERROR;
PRINT_SOCKET_ERROR("setsockopt(SO_REUSEADDR,...)");
return NULL;
}
#ifdef _WIN32
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&_ttl, sizeof(_ttl)) < 0)
#else /* _WIN32 */
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
#endif /* _WIN32 */
{
/* not a fatal error */
PRINT_SOCKET_ERROR("setsockopt(IP_MULTICAST_TTL,...)");
}
if(multicastif)
{
if(ipv6) {
#if !defined(_WIN32)
/* according to MSDN, if_nametoindex() is supported since
* MS Windows Vista and MS Windows Server 2008.
* http://msdn.microsoft.com/en-us/library/bb408409%28v=vs.85%29.aspx */
unsigned int ifindex = if_nametoindex(multicastif); /* eth0, etc. */
if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) < 0)
{
PRINT_SOCKET_ERROR("setsockopt");
}
#else
#ifdef DEBUG
printf("Setting of multicast interface not supported in IPv6 under Windows.\n");
#endif
#endif
} else {
struct in_addr mc_if;
mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */
if(mc_if.s_addr != INADDR_NONE)
{
((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr;
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
{
PRINT_SOCKET_ERROR("setsockopt");
}
} else {
#ifdef HAS_IP_MREQN
/* was not an ip address, try with an interface name */
struct ip_mreqn reqn; /* only defined with -D_BSD_SOURCE or -D_GNU_SOURCE */
memset(&reqn, 0, sizeof(struct ip_mreqn));
reqn.imr_ifindex = if_nametoindex(multicastif);
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0)
{
PRINT_SOCKET_ERROR("setsockopt");
}
#else
#ifdef DEBUG
printf("Setting of multicast interface not supported with interface name.\n");
#endif
#endif
}
}
}
/* Before sending the packed, we first "bind" in order to be able
* to receive the response */
if (bind(sudp, (const struct sockaddr *)&sockudp_r,
ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) != 0)
{
if(error)
*error = MINISSDPC_SOCKET_ERROR;
PRINT_SOCKET_ERROR("bind");
closesocket(sudp);
return NULL;
}
if(error)
*error = MINISSDPC_SUCCESS;
/* Calculating maximum response time in seconds */
mx = ((unsigned int)delay) / 1000u;
if(mx == 0) {
mx = 1;
delay = 1000;
}
/* receiving SSDP response packet */
for(deviceIndex = 0; deviceTypes[deviceIndex]; deviceIndex++) {
/* sending the SSDP M-SEARCH packet */
n = snprintf(bufr, sizeof(bufr),
MSearchMsgFmt,
ipv6 ?
(linklocal ? "[" UPNP_MCAST_LL_ADDR "]" : "[" UPNP_MCAST_SL_ADDR "]")
: UPNP_MCAST_ADDR,
deviceTypes[deviceIndex], mx);
#ifdef DEBUG
/*printf("Sending %s", bufr);*/
printf("Sending M-SEARCH request to %s with ST: %s\n",
ipv6 ?
(linklocal ? "[" UPNP_MCAST_LL_ADDR "]" : "[" UPNP_MCAST_SL_ADDR "]")
: UPNP_MCAST_ADDR,
deviceTypes[deviceIndex]);
#endif
#ifdef NO_GETADDRINFO
/* the following code is not using getaddrinfo */
/* emission */
memset(&sockudp_w, 0, sizeof(struct sockaddr_storage));
if(ipv6) {
struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_w;
p->sin6_family = AF_INET6;
p->sin6_port = htons(SSDP_PORT);
inet_pton(AF_INET6,
linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR,
&(p->sin6_addr));
} else {
struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_w;
p->sin_family = AF_INET;
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) {
if(error)
*error = MINISSDPC_SOCKET_ERROR;
PRINT_SOCKET_ERROR("sendto");
break;
}
#else /* #ifdef NO_GETADDRINFO */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; /* AF_INET6 or AF_INET */
hints.ai_socktype = SOCK_DGRAM;
/*hints.ai_flags = */
if ((rv = getaddrinfo(ipv6
? (linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR)
: UPNP_MCAST_ADDR,
XSTR(SSDP_PORT), &hints, &servinfo)) != 0) {
if(error)
*error = MINISSDPC_SOCKET_ERROR;
#ifdef _WIN32
fprintf(stderr, "getaddrinfo() failed: %d\n", rv);
#else
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
#endif
break;
}
for(p = servinfo; p; p = p->ai_next) {
n = sendto(sudp, bufr, n, 0, p->ai_addr, p->ai_addrlen);
if (n < 0) {
#ifdef DEBUG
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
if (getnameinfo(p->ai_addr, p->ai_addrlen, hbuf, sizeof(hbuf), sbuf,
sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
fprintf(stderr, "host:%s port:%s\n", hbuf, sbuf);
}
#endif
PRINT_SOCKET_ERROR("sendto");
continue;
}
}
freeaddrinfo(servinfo);
if(n < 0) {
if(error)
*error = MINISSDPC_SOCKET_ERROR;
break;
}
#endif /* #ifdef NO_GETADDRINFO */
/* Waiting for SSDP REPLY packet to M-SEARCH
* if searchalltypes is set, enter the loop only
* when the last deviceType is reached */
if(!searchalltypes || !deviceTypes[deviceIndex + 1]) do {
n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id);
if (n < 0) {
/* error */
if(error)
*error = MINISSDPC_SOCKET_ERROR;
goto error;
} else if (n == 0) {
/* no data or Time Out */
#ifdef DEBUG
printf("NODATA or TIMEOUT\n");
#endif /* DEBUG */
if (devlist && !searchalltypes) {
/* found some devices, stop now*/
if(error)
*error = MINISSDPC_SUCCESS;
goto error;
}
} else {
const char * descURL=NULL;
int urlsize=0;
const char * st=NULL;
int stsize=0;
const char * usn=NULL;
int usnsize=0;
parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize, &usn, &usnsize);
if(st&&descURL) {
#ifdef DEBUG
printf("M-SEARCH Reply:\n ST: %.*s\n USN: %.*s\n Location: %.*s\n",
stsize, st, usnsize, (usn?usn:""), urlsize, descURL);
#endif /* DEBUG */
for(tmp=devlist; tmp; tmp = tmp->pNext) {
if(memcmp(tmp->descURL, descURL, urlsize) == 0 &&
tmp->descURL[urlsize] == '\0' &&
memcmp(tmp->st, st, stsize) == 0 &&
tmp->st[stsize] == '\0' &&
(usnsize == 0 || memcmp(tmp->usn, usn, usnsize) == 0) &&
tmp->usn[usnsize] == '\0')
break;
}
/* at the exit of the loop above, tmp is null if
* no duplicate device was found */
if(tmp)
continue;
tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize);
if(!tmp) {
/* memory allocation error */
if(error)
*error = MINISSDPC_MEMORY_ERROR;
goto error;
}
tmp->pNext = devlist;
tmp->descURL = tmp->buffer;
tmp->st = tmp->buffer + 1 + urlsize;
tmp->usn = tmp->st + 1 + stsize;
memcpy(tmp->buffer, descURL, urlsize);
tmp->buffer[urlsize] = '\0';
memcpy(tmp->st, st, stsize);
tmp->buffer[urlsize+1+stsize] = '\0';
if(usn != NULL)
memcpy(tmp->usn, usn, usnsize);
tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0';
tmp->scope_id = scope_id;
devlist = tmp;
}
}
} while(n > 0);
if(ipv6) {
/* switch linklocal flag */
if(linklocal) {
linklocal = 0;
--deviceIndex;
} else {
linklocal = 1;
}
}
}
error:
closesocket(sudp);
return devlist; return devlist;
} }

View File

@ -1,26 +1,10 @@
/* $Id: miniupnpc.c,v 1.110 2012/08/11 05:52:48 nanard Exp $ */ /* $Id: miniupnpc.c,v 1.140 2015/10/08 16:15:47 nanard Exp $ */
/* Project : miniupnp /* Project : miniupnp
* Web : http://miniupnp.free.fr/ * Web : http://miniupnp.free.fr/
* Author : Thomas BERNARD * Author : Thomas BERNARD
* copyright (c) 2005-2012 Thomas Bernard * copyright (c) 2005-2015 Thomas Bernard
* This software is subjet to the conditions detailed in the * This software is subjet to the conditions detailed in the
* provided LICENSE file. */ * provided LICENSE file. */
#define __EXTENSIONS__ 1
#if !defined(MACOSX) && !defined(__sun)
#if !defined(_XOPEN_SOURCE) && !defined(__OpenBSD__) && !defined(__NetBSD__)
#ifndef __cplusplus
#define _XOPEN_SOURCE 600
#endif
#endif
#ifndef __BSD_VISIBLE
#define __BSD_VISIBLE 1
#endif
#endif
#if !defined(__DragonFly__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(MACOSX) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__sun)
#define HAS_IP_MREQN
#endif
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -31,6 +15,7 @@
#include <io.h> #include <io.h>
#include <iphlpapi.h> #include <iphlpapi.h>
#define snprintf _snprintf #define snprintf _snprintf
#define strdup _strdup
#ifndef strncasecmp #ifndef strncasecmp
#if defined(_MSC_VER) && (_MSC_VER >= 1400) #if defined(_MSC_VER) && (_MSC_VER >= 1400)
#define strncasecmp _memicmp #define strncasecmp _memicmp
@ -62,14 +47,11 @@
#include <errno.h> #include <errno.h>
#define closesocket close #define closesocket close
#endif /* #else _WIN32 */ #endif /* #else _WIN32 */
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT #ifdef __GNU__
#include <sys/time.h> #define MAXHOSTNAMELEN 64
#endif
#if defined(__amigaos__) || defined(__amigaos4__)
/* Amiga OS specific stuff */
#define TIMEVAL struct timeval
#endif #endif
#include "miniupnpc.h" #include "miniupnpc.h"
#include "minissdpc.h" #include "minissdpc.h"
#include "miniwget.h" #include "miniwget.h"
@ -77,12 +59,12 @@
#include "minixml.h" #include "minixml.h"
#include "upnpcommands.h" #include "upnpcommands.h"
#include "connecthostport.h" #include "connecthostport.h"
#include "receivedata.h"
#ifdef _WIN32 /* compare the begining of a string with a constant string */
#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); #define COMPARE(str, cstr) (0==memcmp(str, cstr, sizeof(cstr) - 1))
#else
#define PRINT_SOCKET_ERROR(x) perror(x) #ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif #endif
#define SOAPPREFIX "s" #define SOAPPREFIX "s"
@ -90,7 +72,7 @@
#define SERVICEPREFIX2 'u' #define SERVICEPREFIX2 'u'
/* root description parsing */ /* root description parsing */
LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data) MINIUPNP_LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data)
{ {
struct xmlparser parser; struct xmlparser parser;
/* xmlparser object */ /* xmlparser object */
@ -244,98 +226,92 @@ char * simpleUPnPcommand(int s, const char * url, const char * service,
return buf; return buf;
} }
/* parseMSEARCHReply() /* upnpDiscoverDevices() :
* 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.
* The strings are NOT null terminated */
static void
parseMSEARCHReply(const char * reply, int size,
const char * * location, int * locationsize,
const char * * st, int * stsize)
{
int a, b, i;
i = 0;
a = i; /* start of the line */
b = 0; /* end of the "header" (position of the colon) */
while(i<size)
{
switch(reply[i])
{
case ':':
if(b==0)
{
b = i; /* end of the "header" */
/*for(j=a; j<b; j++)
{
putchar(reply[j]);
}
*/
}
break;
case '\x0a':
case '\x0d':
if(b!=0)
{
/*for(j=b+1; j<i; j++)
{
putchar(reply[j]);
}
putchar('\n');*/
/* skip the colon and white spaces */
do { b++; } while(reply[b]==' ');
if(0==strncasecmp(reply+a, "location", 8))
{
*location = reply+b;
*locationsize = i-b;
}
else if(0==strncasecmp(reply+a, "st", 2))
{
*st = reply+b;
*stsize = i-b;
}
b = 0;
}
a = i+1;
break;
default:
break;
}
i++;
}
}
/* port upnp discover : SSDP protocol */
#define PORT 1900
#define XSTR(s) STR(s)
#define STR(s) #s
#define UPNP_MCAST_ADDR "239.255.255.250"
/* for IPv6 */
#define UPNP_MCAST_LL_ADDR "FF02::C" /* link-local */
#define UPNP_MCAST_SL_ADDR "FF05::C" /* site-local */
/* upnpDiscover() :
* return a chained list of all devices found or NULL if * return a chained list of all devices found or NULL if
* no devices was found. * no devices was found.
* It is up to the caller to free the chained list * It is up to the caller to free the chained list
* delay is in millisecond (poll) */ * delay is in millisecond (poll).
LIBSPEC struct UPNPDev * * UDA v1.1 says :
upnpDiscover(int delay, const char * multicastif, * The TTL for the IP packet SHOULD default to 2 and
const char * minissdpdsock, int sameport, * SHOULD be configurable. */
int ipv6, MINIUPNP_LIBSPEC struct UPNPDev *
int * error) upnpDiscoverDevices(const char * const deviceTypes[],
int delay, const char * multicastif,
const char * minissdpdsock, int localport,
int ipv6, unsigned char ttl,
int * error,
int searchalltypes)
{ {
struct UPNPDev * tmp; struct UPNPDev * tmp;
struct UPNPDev * devlist = 0; struct UPNPDev * devlist = 0;
unsigned int scope_id = 0; #if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__)
int opt = 1; int deviceIndex;
static const char MSearchMsgFmt[] = #endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
"M-SEARCH * HTTP/1.1\r\n"
"HOST: %s:" XSTR(PORT) "\r\n" if(error)
"ST: %s\r\n" *error = UPNPDISCOVER_UNKNOWN_ERROR;
"MAN: \"ssdp:discover\"\r\n" #if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__)
"MX: %u\r\n" /* first try to get infos from minissdpd ! */
"\r\n"; if(!minissdpdsock)
minissdpdsock = "/var/run/minissdpd.sock";
for(deviceIndex = 0; deviceTypes[deviceIndex]; deviceIndex++) {
struct UPNPDev * minissdpd_devlist;
int only_rootdevice = 1;
minissdpd_devlist = getDevicesFromMiniSSDPD(deviceTypes[deviceIndex],
minissdpdsock, 0);
if(minissdpd_devlist) {
#ifdef DEBUG
printf("returned by MiniSSDPD: %s\t%s\n",
minissdpd_devlist->st, minissdpd_devlist->descURL);
#endif /* DEBUG */
if(!strstr(minissdpd_devlist->st, "rootdevice"))
only_rootdevice = 0;
for(tmp = minissdpd_devlist; tmp->pNext != NULL; tmp = tmp->pNext) {
#ifdef DEBUG
printf("returned by MiniSSDPD: %s\t%s\n",
tmp->pNext->st, tmp->pNext->descURL);
#endif /* DEBUG */
if(!strstr(tmp->st, "rootdevice"))
only_rootdevice = 0;
}
tmp->pNext = devlist;
devlist = minissdpd_devlist;
if(!searchalltypes && !only_rootdevice)
break;
}
}
for(tmp = devlist; tmp != NULL; tmp = tmp->pNext) {
/* We return what we have found if it was not only a rootdevice */
if(!strstr(tmp->st, "rootdevice")) {
if(error)
*error = UPNPDISCOVER_SUCCESS;
return devlist;
}
}
#endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
/* direct discovery if minissdpd responses are not sufficient */
{
struct UPNPDev * discovered_devlist;
discovered_devlist = ssdpDiscoverDevices(deviceTypes, delay, multicastif, localport,
ipv6, ttl, error, searchalltypes);
if(devlist == NULL)
devlist = discovered_devlist;
else {
for(tmp = devlist; tmp->pNext != NULL; tmp = tmp->pNext);
tmp->pNext = discovered_devlist;
}
}
return devlist;
}
/* upnpDiscover() Discover IGD device */
MINIUPNP_LIBSPEC struct UPNPDev *
upnpDiscover(int delay, const char * multicastif,
const char * minissdpdsock, int localport,
int ipv6, unsigned char ttl,
int * error)
{
static const char * const deviceList[] = { static const char * const deviceList[] = {
#if 0 #if 0
"urn:schemas-upnp-org:device:InternetGatewayDevice:2", "urn:schemas-upnp-org:device:InternetGatewayDevice:2",
@ -345,485 +321,147 @@ upnpDiscover(int delay, const char * multicastif,
"urn:schemas-upnp-org:service:WANIPConnection:1", "urn:schemas-upnp-org:service:WANIPConnection:1",
"urn:schemas-upnp-org:service:WANPPPConnection:1", "urn:schemas-upnp-org:service:WANPPPConnection:1",
"upnp:rootdevice", "upnp:rootdevice",
/*"ssdp:all",*/
0 0
}; };
int deviceIndex = 0; return upnpDiscoverDevices(deviceList,
char bufr[1536]; /* reception and emission buffer */ delay, multicastif, minissdpdsock, localport,
int sudp; ipv6, ttl, error, 0);
int n;
struct sockaddr_storage sockudp_r;
unsigned int mx;
#ifdef NO_GETADDRINFO
struct sockaddr_storage sockudp_w;
#else
int rv;
struct addrinfo hints, *servinfo, *p;
#endif
#ifdef _WIN32
MIB_IPFORWARDROW ip_forward;
#endif
int linklocal = 1;
if(error)
*error = UPNPDISCOVER_UNKNOWN_ERROR;
#if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__)
/* first try to get infos from minissdpd ! */
if(!minissdpdsock)
minissdpdsock = "/var/run/minissdpd.sock";
while(!devlist && deviceList[deviceIndex]) {
devlist = getDevicesFromMiniSSDPD(deviceList[deviceIndex],
minissdpdsock);
/* We return what we have found if it was not only a rootdevice */
if(devlist && !strstr(deviceList[deviceIndex], "rootdevice")) {
if(error)
*error = UPNPDISCOVER_SUCCESS;
return devlist;
}
deviceIndex++;
}
deviceIndex = 0;
#endif
/* fallback to direct discovery */
#ifdef _WIN32
sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP);
#else
sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, 0);
#endif
if(sudp < 0)
{
if(error)
*error = UPNPDISCOVER_SOCKET_ERROR;
PRINT_SOCKET_ERROR("socket");
return NULL;
}
/* reception */
memset(&sockudp_r, 0, sizeof(struct sockaddr_storage));
if(ipv6) {
struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_r;
p->sin6_family = AF_INET6;
if(sameport)
p->sin6_port = htons(PORT);
p->sin6_addr = in6addr_any; /* in6addr_any is not available with MinGW32 3.4.2 */
} else {
struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_r;
p->sin_family = AF_INET;
if(sameport)
p->sin_port = htons(PORT);
p->sin_addr.s_addr = INADDR_ANY;
}
#ifdef _WIN32
/* This code could help us to use the right Network interface for
* SSDP multicast traffic */
/* Get IP associated with the index given in the ip_forward struct
* in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */
if(!ipv6
&& (GetBestRoute(inet_addr("223.255.255.255"), 0, &ip_forward) == NO_ERROR)) {
DWORD dwRetVal = 0;
PMIB_IPADDRTABLE pIPAddrTable;
DWORD dwSize = 0;
#ifdef DEBUG
IN_ADDR IPAddr;
#endif
int i;
#ifdef DEBUG
printf("ifIndex=%lu nextHop=%lx \n", ip_forward.dwForwardIfIndex, ip_forward.dwForwardNextHop);
#endif
pIPAddrTable = (MIB_IPADDRTABLE *) malloc(sizeof (MIB_IPADDRTABLE));
if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) {
free(pIPAddrTable);
pIPAddrTable = (MIB_IPADDRTABLE *) malloc(dwSize);
}
if(pIPAddrTable) {
dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 );
#ifdef DEBUG
printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries);
#endif
for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) {
#ifdef DEBUG
printf("\n\tInterface Index[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwIndex);
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr;
printf("\tIP Address[%d]: \t%s\n", i, inet_ntoa(IPAddr) );
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask;
printf("\tSubnet Mask[%d]: \t%s\n", i, inet_ntoa(IPAddr) );
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr;
printf("\tBroadCast[%d]: \t%s (%ld)\n", i, inet_ntoa(IPAddr), pIPAddrTable->table[i].dwBCastAddr);
printf("\tReassembly size[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwReasmSize);
printf("\tType and State[%d]:", i);
printf("\n");
#endif
if (pIPAddrTable->table[i].dwIndex == ip_forward.dwForwardIfIndex) {
/* Set the address of this interface to be used */
struct in_addr mc_if;
memset(&mc_if, 0, sizeof(mc_if));
mc_if.s_addr = pIPAddrTable->table[i].dwAddr;
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) {
PRINT_SOCKET_ERROR("setsockopt");
}
((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = pIPAddrTable->table[i].dwAddr;
#ifndef DEBUG
break;
#endif
}
}
free(pIPAddrTable);
pIPAddrTable = NULL;
}
}
#endif
#ifdef _WIN32
if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0)
#else
if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0)
#endif
{
if(error)
*error = UPNPDISCOVER_SOCKET_ERROR;
PRINT_SOCKET_ERROR("setsockopt");
return NULL;
}
if(multicastif)
{
if(ipv6) {
#if !defined(_WIN32)
/* according to MSDN, if_nametoindex() is supported since
* MS Windows Vista and MS Windows Server 2008.
* http://msdn.microsoft.com/en-us/library/bb408409%28v=vs.85%29.aspx */
unsigned int ifindex = if_nametoindex(multicastif); /* eth0, etc. */
if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(&ifindex)) < 0)
{
PRINT_SOCKET_ERROR("setsockopt");
}
#else
#ifdef DEBUG
printf("Setting of multicast interface not supported in IPv6 under Windows.\n");
#endif
#endif
} else {
struct in_addr mc_if;
mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */
if(mc_if.s_addr != INADDR_NONE)
{
((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr;
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
{
PRINT_SOCKET_ERROR("setsockopt");
}
} else {
#ifdef HAS_IP_MREQN
/* was not an ip address, try with an interface name */
struct ip_mreqn reqn; /* only defined with -D_BSD_SOURCE or -D_GNU_SOURCE */
memset(&reqn, 0, sizeof(struct ip_mreqn));
reqn.imr_ifindex = if_nametoindex(multicastif);
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0)
{
PRINT_SOCKET_ERROR("setsockopt");
}
#else
#ifdef DEBUG
printf("Setting of multicast interface not supported with interface name.\n");
#endif
#endif
}
}
}
/* Avant d'envoyer le paquet on bind pour recevoir la reponse */
if (bind(sudp, (const struct sockaddr *)&sockudp_r,
ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) != 0)
{
if(error)
*error = UPNPDISCOVER_SOCKET_ERROR;
PRINT_SOCKET_ERROR("bind");
closesocket(sudp);
return NULL;
}
if(error)
*error = UPNPDISCOVER_SUCCESS;
/* Calculating maximum response time in seconds */
mx = ((unsigned int)delay) / 1000u;
/* receiving SSDP response packet */
for(n = 0; deviceList[deviceIndex]; deviceIndex++)
{
if(n == 0)
{
/* sending the SSDP M-SEARCH packet */
n = snprintf(bufr, sizeof(bufr),
MSearchMsgFmt,
ipv6 ?
(linklocal ? "[" UPNP_MCAST_LL_ADDR "]" : "[" UPNP_MCAST_SL_ADDR "]")
: UPNP_MCAST_ADDR,
deviceList[deviceIndex], mx);
#ifdef DEBUG
printf("Sending %s", bufr);
#endif
#ifdef NO_GETADDRINFO
/* the following code is not using getaddrinfo */
/* emission */
memset(&sockudp_w, 0, sizeof(struct sockaddr_storage));
if(ipv6) {
struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_w;
p->sin6_family = AF_INET6;
p->sin6_port = htons(PORT);
inet_pton(AF_INET6,
linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR,
&(p->sin6_addr));
} else {
struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_w;
p->sin_family = AF_INET;
p->sin_port = htons(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) {
if(error)
*error = UPNPDISCOVER_SOCKET_ERROR;
PRINT_SOCKET_ERROR("sendto");
break;
}
#else /* #ifdef NO_GETADDRINFO */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; /* AF_INET6 or AF_INET */
hints.ai_socktype = SOCK_DGRAM;
/*hints.ai_flags = */
if ((rv = getaddrinfo(ipv6
? (linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR)
: UPNP_MCAST_ADDR,
XSTR(PORT), &hints, &servinfo)) != 0) {
if(error)
*error = UPNPDISCOVER_SOCKET_ERROR;
#ifdef _WIN32
fprintf(stderr, "getaddrinfo() failed: %d\n", rv);
#else
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
#endif
break;
}
for(p = servinfo; p; p = p->ai_next) {
n = sendto(sudp, bufr, n, 0, p->ai_addr, p->ai_addrlen);
if (n < 0) {
#ifdef DEBUG
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
if (getnameinfo(p->ai_addr, p->ai_addrlen, hbuf, sizeof(hbuf), sbuf,
sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
fprintf(stderr, "host:%s port:%s\n", hbuf, sbuf);
}
#endif
PRINT_SOCKET_ERROR("sendto");
continue;
}
}
freeaddrinfo(servinfo);
if(n < 0) {
if(error)
*error = UPNPDISCOVER_SOCKET_ERROR;
break;
}
#endif /* #ifdef NO_GETADDRINFO */
}
/* Waiting for SSDP REPLY packet to M-SEARCH */
n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id);
if (n < 0) {
/* error */
if(error)
*error = UPNPDISCOVER_SOCKET_ERROR;
break;
} else if (n == 0) {
/* no data or Time Out */
if (devlist) {
/* no more device type to look for... */
if(error)
*error = UPNPDISCOVER_SUCCESS;
break;
}
if(ipv6) {
if(linklocal) {
linklocal = 0;
--deviceIndex;
} else {
linklocal = 1;
}
}
} else {
const char * descURL=NULL;
int urlsize=0;
const char * st=NULL;
int stsize=0;
/*printf("%d byte(s) :\n%s\n", n, bufr);*/ /* affichage du message */
parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize);
if(st&&descURL)
{
#ifdef DEBUG
printf("M-SEARCH Reply:\nST: %.*s\nLocation: %.*s\n",
stsize, st, urlsize, descURL);
#endif
for(tmp=devlist; tmp; tmp = tmp->pNext) {
if(memcmp(tmp->descURL, descURL, urlsize) == 0 &&
tmp->descURL[urlsize] == '\0' &&
memcmp(tmp->st, st, stsize) == 0 &&
tmp->st[stsize] == '\0')
break;
}
/* at the exit of the loop above, tmp is null if
* no duplicate device was found */
if(tmp)
continue;
tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize);
if(!tmp) {
/* memory allocation error */
if(error)
*error = UPNPDISCOVER_MEMORY_ERROR;
break;
}
tmp->pNext = devlist;
tmp->descURL = tmp->buffer;
tmp->st = tmp->buffer + 1 + urlsize;
memcpy(tmp->buffer, descURL, urlsize);
tmp->buffer[urlsize] = '\0';
memcpy(tmp->buffer + urlsize + 1, st, stsize);
tmp->buffer[urlsize+1+stsize] = '\0';
tmp->scope_id = scope_id;
devlist = tmp;
}
}
}
closesocket(sudp);
return devlist;
} }
/* freeUPNPDevlist() should be used to /* upnpDiscoverAll() Discover all UPnP devices */
* free the chained list returned by upnpDiscover() */ MINIUPNP_LIBSPEC struct UPNPDev *
LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist) upnpDiscoverAll(int delay, const char * multicastif,
const char * minissdpdsock, int localport,
int ipv6, unsigned char ttl,
int * error)
{ {
struct UPNPDev * next; static const char * const deviceList[] = {
while(devlist) /*"upnp:rootdevice",*/
{ "ssdp:all",
next = devlist->pNext; 0
free(devlist); };
devlist = next; return upnpDiscoverDevices(deviceList,
} delay, multicastif, minissdpdsock, localport,
ipv6, ttl, error, 0);
} }
static void /* upnpDiscoverDevice() Discover a specific device */
url_cpy_or_cat(char * dst, const char * src, int n) 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)
{ {
if( (src[0] == 'h') const char * const deviceList[] = {
&&(src[1] == 't') device,
&&(src[2] == 't') 0
&&(src[3] == 'p') };
&&(src[4] == ':') return upnpDiscoverDevices(deviceList,
&&(src[5] == '/') delay, multicastif, minissdpdsock, localport,
&&(src[6] == '/')) ipv6, ttl, error, 0);
{
strncpy(dst, src, n);
}
else
{
int l = strlen(dst);
if(src[0] != '/')
dst[l++] = '/';
if(l<=n)
strncpy(dst + l, src, n - l);
}
} }
/* Prepare the Urls for usage... static char *
*/ build_absolute_url(const char * baseurl, const char * descURL,
LIBSPEC void const char * url, unsigned int scope_id)
GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data,
const char * descURL, unsigned int scope_id)
{ {
int l, n;
char * s;
const char * base;
char * p; char * p;
int n1, n2, n3, n4;
#if defined(IF_NAMESIZE) && !defined(_WIN32) #if defined(IF_NAMESIZE) && !defined(_WIN32)
char ifname[IF_NAMESIZE]; char ifname[IF_NAMESIZE];
#else #else /* defined(IF_NAMESIZE) && !defined(_WIN32) */
char scope_str[8]; char scope_str[8];
#endif #endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */
n1 = strlen(data->urlbase); if( (url[0] == 'h')
if(n1==0) &&(url[1] == 't')
n1 = strlen(descURL); &&(url[2] == 't')
&&(url[3] == 'p')
&&(url[4] == ':')
&&(url[5] == '/')
&&(url[6] == '/'))
return strdup(url);
base = (baseurl[0] == '\0') ? descURL : baseurl;
n = strlen(base);
if(n > 7) {
p = strchr(base + 7, '/');
if(p)
n = p - base;
}
l = n + strlen(url) + 1;
if(url[0] != '/')
l++;
if(scope_id != 0) { if(scope_id != 0) {
#if defined(IF_NAMESIZE) && !defined(_WIN32) #if defined(IF_NAMESIZE) && !defined(_WIN32)
if(if_indextoname(scope_id, ifname)) { if(if_indextoname(scope_id, ifname)) {
n1 += 3 + strlen(ifname); /* 3 == strlen(%25) */ l += 3 + strlen(ifname); /* 3 == strlen(%25) */
} }
#else #else /* defined(IF_NAMESIZE) && !defined(_WIN32) */
/* under windows, scope is numerical */ /* under windows, scope is numerical */
snprintf(scope_str, sizeof(scope_str), "%u", scope_id); l += 3 + snprintf(scope_str, sizeof(scope_str), "%u", scope_id);
#endif #endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */
} }
n1 += 2; /* 1 byte more for Null terminator, 1 byte for '/' if needed */ s = malloc(l);
n2 = n1; n3 = n1; n4 = n1; if(s == NULL) return NULL;
n1 += strlen(data->first.scpdurl); memcpy(s, base, n);
n2 += strlen(data->first.controlurl);
n3 += strlen(data->CIF.controlurl);
n4 += strlen(data->IPv6FC.controlurl);
/* allocate memory to store URLs */
urls->ipcondescURL = (char *)malloc(n1);
urls->controlURL = (char *)malloc(n2);
urls->controlURL_CIF = (char *)malloc(n3);
urls->controlURL_6FC = (char *)malloc(n4);
/* strdup descURL */
urls->rootdescURL = strdup(descURL);
/* get description of WANIPConnection */
if(data->urlbase[0] != '\0')
strncpy(urls->ipcondescURL, data->urlbase, n1);
else
strncpy(urls->ipcondescURL, descURL, n1);
p = strchr(urls->ipcondescURL+7, '/');
if(p) p[0] = '\0';
if(scope_id != 0) { if(scope_id != 0) {
if(0 == memcmp(urls->ipcondescURL, "http://[fe80:", 13)) { s[n] = '\0';
if(0 == memcmp(s, "http://[fe80:", 13)) {
/* this is a linklocal IPv6 address */ /* this is a linklocal IPv6 address */
p = strchr(urls->ipcondescURL, ']'); p = strchr(s, ']');
if(p) { if(p) {
/* insert %25<scope> into URL */ /* insert %25<scope> into URL */
#if defined(IF_NAMESIZE) && !defined(_WIN32) #if defined(IF_NAMESIZE) && !defined(_WIN32)
memmove(p + 3 + strlen(ifname), p, strlen(p) + 1); memmove(p + 3 + strlen(ifname), p, strlen(p) + 1);
memcpy(p, "%25", 3); memcpy(p, "%25", 3);
memcpy(p + 3, ifname, strlen(ifname)); memcpy(p + 3, ifname, strlen(ifname));
#else n += 3 + strlen(ifname);
#else /* defined(IF_NAMESIZE) && !defined(_WIN32) */
memmove(p + 3 + strlen(scope_str), p, strlen(p) + 1); memmove(p + 3 + strlen(scope_str), p, strlen(p) + 1);
memcpy(p, "%25", 3); memcpy(p, "%25", 3);
memcpy(p + 3, scope_str, strlen(scope_str)); memcpy(p + 3, scope_str, strlen(scope_str));
#endif n += 3 + strlen(scope_str);
#endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */
} }
} }
} }
strncpy(urls->controlURL, urls->ipcondescURL, n2); if(url[0] != '/')
strncpy(urls->controlURL_CIF, urls->ipcondescURL, n3); s[n++] = '/';
strncpy(urls->controlURL_6FC, urls->ipcondescURL, n4); memcpy(s + n, url, l - n);
return s;
}
url_cpy_or_cat(urls->ipcondescURL, data->first.scpdurl, n1); /* Prepare the Urls for usage...
*/
MINIUPNP_LIBSPEC void
GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data,
const char * descURL, unsigned int scope_id)
{
/* strdup descURL */
urls->rootdescURL = strdup(descURL);
url_cpy_or_cat(urls->controlURL, data->first.controlurl, n2); /* get description of WANIPConnection */
urls->ipcondescURL = build_absolute_url(data->urlbase, descURL,
url_cpy_or_cat(urls->controlURL_CIF, data->CIF.controlurl, n3); data->first.scpdurl, scope_id);
urls->controlURL = build_absolute_url(data->urlbase, descURL,
url_cpy_or_cat(urls->controlURL_6FC, data->IPv6FC.controlurl, n4); data->first.controlurl, scope_id);
urls->controlURL_CIF = build_absolute_url(data->urlbase, descURL,
data->CIF.controlurl, scope_id);
urls->controlURL_6FC = build_absolute_url(data->urlbase, descURL,
data->IPv6FC.controlurl, scope_id);
#ifdef DEBUG #ifdef DEBUG
printf("urls->ipcondescURL='%s' %u n1=%d\n", urls->ipcondescURL, printf("urls->ipcondescURL='%s'\n", urls->ipcondescURL);
(unsigned)strlen(urls->ipcondescURL), n1); printf("urls->controlURL='%s'\n", urls->controlURL);
printf("urls->controlURL='%s' %u n2=%d\n", urls->controlURL, printf("urls->controlURL_CIF='%s'\n", urls->controlURL_CIF);
(unsigned)strlen(urls->controlURL), n2); printf("urls->controlURL_6FC='%s'\n", urls->controlURL_6FC);
printf("urls->controlURL_CIF='%s' %u n3=%d\n", urls->controlURL_CIF,
(unsigned)strlen(urls->controlURL_CIF), n3);
printf("urls->controlURL_6FC='%s' %u n4=%d\n", urls->controlURL_6FC,
(unsigned)strlen(urls->controlURL_6FC), n4);
#endif #endif
} }
LIBSPEC void MINIUPNP_LIBSPEC void
FreeUPNPUrls(struct UPNPUrls * urls) FreeUPNPUrls(struct UPNPUrls * urls)
{ {
if(!urls) if(!urls)
@ -849,9 +487,9 @@ UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data)
UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype, UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype,
status, &uptime, NULL); status, &uptime, NULL);
if(0 == strcmp("Connected", status)) if(0 == strcmp("Connected", status))
{
return 1; return 1;
} else if(0 == strcmp("Up", status)) /* Also accept "Up" */
return 1;
else else
return 0; return 0;
} }
@ -866,11 +504,11 @@ UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data)
* not connected * not connected
* 3 = an UPnP device has been found but was not recognized as an IGD * 3 = an UPnP device has been found but was not recognized as an IGD
* *
* In any non zero return case, the urls and data structures * In any positive non zero return case, the urls and data structures
* passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
* free allocated memory. * free allocated memory.
*/ */
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetValidIGD(struct UPNPDev * devlist, UPNP_GetValidIGD(struct UPNPDev * devlist,
struct UPNPUrls * urls, struct UPNPUrls * urls,
struct IGDdatas * data, struct IGDdatas * data,
@ -879,11 +517,14 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
struct xml_desc { struct xml_desc {
char * xml; char * xml;
int size; int size;
int is_igd;
} * desc = NULL; } * desc = NULL;
struct UPNPDev * dev; struct UPNPDev * dev;
int ndev = 0; int ndev = 0;
int i; int i;
int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */ int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */
int n_igd = 0;
char extIpAddr[16];
if(!devlist) if(!devlist)
{ {
#ifdef DEBUG #ifdef DEBUG
@ -891,6 +532,7 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
#endif #endif
return 0; return 0;
} }
/* counting total number of devices in the list */
for(dev = devlist; dev; dev = dev->pNext) for(dev = devlist; dev; dev = dev->pNext)
ndev++; ndev++;
if(ndev > 0) if(ndev > 0)
@ -899,41 +541,58 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
if(!desc) if(!desc)
return -1; /* memory allocation error */ return -1; /* memory allocation error */
} }
/* Step 1 : downloading descriptions and testing type */
for(dev = devlist, i = 0; dev; dev = dev->pNext, i++)
{
/* we should choose an internet gateway device.
* with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */
desc[i].xml = miniwget_getaddr(dev->descURL, &(desc[i].size),
lanaddr, lanaddrlen,
dev->scope_id);
#ifdef DEBUG
if(!desc[i].xml)
{
printf("error getting XML description %s\n", dev->descURL);
}
#endif
if(desc[i].xml)
{
memset(data, 0, sizeof(struct IGDdatas));
memset(urls, 0, sizeof(struct UPNPUrls));
parserootdesc(desc[i].xml, desc[i].size, data);
if(COMPARE(data->CIF.servicetype,
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:"))
{
desc[i].is_igd = 1;
n_igd++;
}
}
}
/* iterate the list to find a device depending on state */
for(state = 1; state <= 3; state++) for(state = 1; state <= 3; state++)
{ {
for(dev = devlist, i = 0; dev; dev = dev->pNext, i++) for(dev = devlist, i = 0; dev; dev = dev->pNext, i++)
{ {
/* we should choose an internet gateway device.
* with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */
if(state == 1)
{
desc[i].xml = miniwget_getaddr(dev->descURL, &(desc[i].size),
lanaddr, lanaddrlen,
dev->scope_id);
#ifdef DEBUG
if(!desc[i].xml)
{
printf("error getting XML description %s\n", dev->descURL);
}
#endif
}
if(desc[i].xml) if(desc[i].xml)
{ {
memset(data, 0, sizeof(struct IGDdatas)); memset(data, 0, sizeof(struct IGDdatas));
memset(urls, 0, sizeof(struct UPNPUrls)); memset(urls, 0, sizeof(struct UPNPUrls));
parserootdesc(desc[i].xml, desc[i].size, data); parserootdesc(desc[i].xml, desc[i].size, data);
if(0==strcmp(data->CIF.servicetype, if(desc[i].is_igd || state >= 3 )
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")
|| state >= 3 )
{ {
GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); GetUPNPUrls(urls, data, dev->descURL, dev->scope_id);
/* in state 2 and 3 we dont test if device is connected ! */
if(state >= 2)
goto free_and_return;
#ifdef DEBUG #ifdef DEBUG
printf("UPNPIGD_IsConnected(%s) = %d\n", printf("UPNPIGD_IsConnected(%s) = %d\n",
urls->controlURL, urls->controlURL,
UPNPIGD_IsConnected(urls, data)); UPNPIGD_IsConnected(urls, data));
#endif #endif
if((state >= 2) || UPNPIGD_IsConnected(urls, data)) /* checks that status is connected AND there is a external IP address assigned */
if(UPNPIGD_IsConnected(urls, data)
&& (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0))
goto free_and_return; goto free_and_return;
FreeUPNPUrls(urls); FreeUPNPUrls(urls);
if(data->second.servicetype[0] != '\0') { if(data->second.servicetype[0] != '\0') {
@ -951,7 +610,8 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
urls->controlURL, urls->controlURL,
UPNPIGD_IsConnected(urls, data)); UPNPIGD_IsConnected(urls, data));
#endif #endif
if((state >= 2) || UPNPIGD_IsConnected(urls, data)) if(UPNPIGD_IsConnected(urls, data)
&& (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0))
goto free_and_return; goto free_and_return;
FreeUPNPUrls(urls); FreeUPNPUrls(urls);
} }

View File

@ -1,5 +1,6 @@
LIBRARY LIBRARY
; miniupnpc library ; miniupnpc library
miniupnpc
EXPORTS EXPORTS
; miniupnpc ; miniupnpc
@ -23,7 +24,9 @@ EXPORTS
UPNP_GetExternalIPAddress UPNP_GetExternalIPAddress
UPNP_GetLinkLayerMaxBitRates UPNP_GetLinkLayerMaxBitRates
UPNP_AddPortMapping UPNP_AddPortMapping
UPNP_AddAnyPortMapping
UPNP_DeletePortMapping UPNP_DeletePortMapping
UPNP_DeletePortMappingRange
UPNP_GetPortMappingNumberOfEntries UPNP_GetPortMappingNumberOfEntries
UPNP_GetSpecificPortMappingEntry UPNP_GetSpecificPortMappingEntry
UPNP_GetGenericPortMappingEntry UPNP_GetGenericPortMappingEntry

View File

@ -1,15 +1,23 @@
/* $Id: miniupnpcstrings.h.in,v 1.4 2011/01/04 11:41:53 nanard Exp $ */ /* $Id: miniupnpcstrings.h.in,v 1.6 2014/11/04 22:31:55 nanard Exp $ */
/* Project: miniupnp /* Project: miniupnp
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author: Thomas Bernard * Author: Thomas Bernard
* Copyright (c) 2005-2011 Thomas Bernard * Copyright (c) 2005-2014 Thomas Bernard
* This software is subjects to the conditions detailed * This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */ * in the LICENCE file provided within this distribution */
#ifndef __MINIUPNPCSTRINGS_H__ #ifndef MINIUPNPCSTRINGS_H_INCLUDED
#define __MINIUPNPCSTRINGS_H__ #define MINIUPNPCSTRINGS_H_INCLUDED
#define OS_STRING "OS/version" #define OS_STRING "OS/version"
#define MINIUPNPC_VERSION_STRING "version" #define MINIUPNPC_VERSION_STRING "version"
#if 0
/* according to "UPnP Device Architecture 1.0" */
#define UPNP_VERSION_STRING "UPnP/1.0"
#else
/* according to "UPnP Device Architecture 1.1" */
#define UPNP_VERSION_STRING "UPnP/1.1"
#endif
#endif #endif

View File

@ -1,8 +1,8 @@
/* $Id: miniwget.c,v 1.58 2012/08/11 05:52:49 nanard Exp $ */ /* $Id: miniwget.c,v 1.71 2015/08/06 09:54:20 nanard Exp $ */
/* Project : miniupnp /* Project : miniupnp
* Website : http://miniupnp.free.fr/ * Website : http://miniupnp.free.fr/
* Author : Thomas Bernard * Author : Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard * Copyright (c) 2005-2015 Thomas Bernard
* This software is subject to the conditions detailed in the * This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */ * LICENCE file provided in this distribution. */
@ -15,7 +15,6 @@
#include <ws2tcpip.h> #include <ws2tcpip.h>
#include <io.h> #include <io.h>
#define MAXHOSTNAMELEN 64 #define MAXHOSTNAMELEN 64
#define MIN(x,y) (((x)<(y))?(x):(y))
#define snprintf _snprintf #define snprintf _snprintf
#define socklen_t int #define socklen_t int
#ifndef strncasecmp #ifndef strncasecmp
@ -39,19 +38,26 @@
#include <net/if.h> #include <net/if.h>
#include <netdb.h> #include <netdb.h>
#define closesocket close #define closesocket close
/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions #include <strings.h>
* during the connect() call */
#define MINIUPNPC_IGNORE_EINTR
#endif /* #else _WIN32 */ #endif /* #else _WIN32 */
#if defined(__sun) || defined(sun) #ifdef __GNU__
#define MAXHOSTNAMELEN 64
#endif /* __GNU__ */
#ifndef MIN
#define MIN(x,y) (((x)<(y))?(x):(y)) #define MIN(x,y) (((x)<(y))?(x):(y))
#endif #endif /* MIN */
#include "miniupnpcstrings.h" #include "miniupnpcstrings.h"
#include "miniwget.h" #include "miniwget.h"
#include "connecthostport.h" #include "connecthostport.h"
#include "receivedata.h" #include "receivedata.h"
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
/* /*
* Read a HTTP response from a socket. * Read a HTTP response from a socket.
* Process Content-Length and Transfer-encoding headers. * Process Content-Length and Transfer-encoding headers.
@ -79,7 +85,24 @@ getHTTPResponse(int s, int * size)
unsigned int chunksize_buf_index; unsigned int chunksize_buf_index;
header_buf = malloc(header_buf_len); header_buf = malloc(header_buf_len);
if(header_buf == NULL)
{
#ifdef DEBUG
fprintf(stderr, "%s: Memory allocation error\n", "getHTTPResponse");
#endif /* DEBUG */
*size = -1;
return NULL;
}
content_buf = malloc(content_buf_len); content_buf = malloc(content_buf_len);
if(content_buf == NULL)
{
free(header_buf);
#ifdef DEBUG
fprintf(stderr, "%s: Memory allocation error\n", "getHTTPResponse");
#endif /* DEBUG */
*size = -1;
return NULL;
}
chunksize_buf[0] = '\0'; chunksize_buf[0] = '\0';
chunksize_buf_index = 0; chunksize_buf_index = 0;
@ -92,7 +115,15 @@ getHTTPResponse(int s, int * size)
int colon=0; int colon=0;
int valuestart=0; int valuestart=0;
if(header_buf_used + n > header_buf_len) { if(header_buf_used + n > header_buf_len) {
header_buf = realloc(header_buf, header_buf_used + n); char * tmp = realloc(header_buf, header_buf_used + n);
if(tmp == NULL) {
/* memory allocation error */
free(header_buf);
free(content_buf);
*size = -1;
return NULL;
}
header_buf = tmp;
header_buf_len = header_buf_used + n; header_buf_len = header_buf_used + n;
} }
memcpy(header_buf + header_buf_used, buf, n); memcpy(header_buf + header_buf_used, buf, n);
@ -158,7 +189,7 @@ getHTTPResponse(int s, int * size)
chunked = 1; chunked = 1;
} }
} }
while(header_buf[i]=='\r' || header_buf[i] == '\n') while((i < (int)header_buf_used) && (header_buf[i]=='\r' || header_buf[i] == '\n'))
i++; i++;
linestart = i; linestart = i;
colon = linestart; colon = linestart;
@ -227,13 +258,21 @@ getHTTPResponse(int s, int * size)
bytestocopy = ((int)chunksize < (n - i))?chunksize:(unsigned int)(n - i); bytestocopy = ((int)chunksize < (n - i))?chunksize:(unsigned int)(n - i);
if((content_buf_used + bytestocopy) > content_buf_len) if((content_buf_used + bytestocopy) > content_buf_len)
{ {
char * tmp;
if(content_length >= (int)(content_buf_used + bytestocopy)) { if(content_length >= (int)(content_buf_used + bytestocopy)) {
content_buf_len = content_length; content_buf_len = content_length;
} else { } else {
content_buf_len = content_buf_used + bytestocopy; content_buf_len = content_buf_used + bytestocopy;
} }
content_buf = (char *)realloc((void *)content_buf, tmp = realloc(content_buf, content_buf_len);
content_buf_len); if(tmp == NULL) {
/* memory allocation error */
free(content_buf);
free(header_buf);
*size = -1;
return NULL;
}
content_buf = tmp;
} }
memcpy(content_buf + content_buf_used, buf + i, bytestocopy); memcpy(content_buf + content_buf_used, buf + i, bytestocopy);
content_buf_used += bytestocopy; content_buf_used += bytestocopy;
@ -251,13 +290,21 @@ getHTTPResponse(int s, int * size)
} }
if(content_buf_used + n > content_buf_len) if(content_buf_used + n > content_buf_len)
{ {
char * tmp;
if(content_length >= (int)(content_buf_used + n)) { if(content_length >= (int)(content_buf_used + n)) {
content_buf_len = content_length; content_buf_len = content_length;
} else { } else {
content_buf_len = content_buf_used + n; content_buf_len = content_buf_used + n;
} }
content_buf = (char *)realloc((void *)content_buf, tmp = realloc(content_buf, content_buf_len);
content_buf_len); if(tmp == NULL) {
/* memory allocation error */
free(content_buf);
free(header_buf);
*size = -1;
return NULL;
}
content_buf = tmp;
} }
memcpy(content_buf + content_buf_used, buf, n); memcpy(content_buf + content_buf_used, buf, n);
content_buf_used += n; content_buf_used += n;
@ -363,7 +410,7 @@ miniwget3(const char * host,
"GET %s HTTP/%s\r\n" "GET %s HTTP/%s\r\n"
"Host: %s:%d\r\n" "Host: %s:%d\r\n"
"Connection: Close\r\n" "Connection: Close\r\n"
"User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n" "User-Agent: " OS_STRING ", " UPNP_VERSION_STRING ", MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
"\r\n", "\r\n",
path, httpversion, host, port); path, httpversion, host, port);

View File

@ -1,10 +1,10 @@
/* $Id: minixml.c,v 1.10 2012/03/05 19:42:47 nanard Exp $ */ /* $Id: minixml.c,v 1.11 2014/02/03 15:54:12 nanard Exp $ */
/* minixml.c : the minimum size a xml parser can be ! */ /* minixml.c : the minimum size a xml parser can be ! */
/* Project : miniupnp /* Project : miniupnp
* webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author : Thomas Bernard * Author : Thomas Bernard
Copyright (c) 2005-2011, Thomas BERNARD Copyright (c) 2005-2014, Thomas BERNARD
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@ -113,7 +113,20 @@ static void parseelt(struct xmlparser * p)
const char * elementname; const char * elementname;
while(p->xml < (p->xmlend - 1)) while(p->xml < (p->xmlend - 1))
{ {
if((p->xml)[0]=='<' && (p->xml)[1]!='?') if((p->xml + 4) <= p->xmlend && (0 == memcmp(p->xml, "<!--", 4)))
{
p->xml += 3;
/* ignore comments */
do
{
p->xml++;
if ((p->xml + 3) >= p->xmlend)
return;
}
while(memcmp(p->xml, "-->", 3) != 0);
p->xml += 3;
}
else if((p->xml)[0]=='<' && (p->xml)[1]!='?')
{ {
i = 0; elementname = ++p->xml; i = 0; elementname = ++p->xml;
while( !IS_WHITE_SPACE(*p->xml) while( !IS_WHITE_SPACE(*p->xml)

View File

@ -1,4 +1,4 @@
/* $Id: minixmlvalid.c,v 1.6 2012/05/01 16:24:07 nanard Exp $ */ /* $Id: minixmlvalid.c,v 1.7 2015/07/15 12:41:15 nanard Exp $ */
/* MiniUPnP Project /* MiniUPnP Project
* http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/ * http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/
* minixmlvalid.c : * minixmlvalid.c :
@ -128,6 +128,11 @@ int testxmlparser(const char * xml, int size)
struct xmlparser parser; struct xmlparser parser;
evtlist.n = 0; evtlist.n = 0;
evtlist.events = malloc(sizeof(struct event)*100); evtlist.events = malloc(sizeof(struct event)*100);
if(evtlist.events == NULL)
{
fprintf(stderr, "Memory allocation error.\n");
return -1;
}
memset(&parser, 0, sizeof(parser)); memset(&parser, 0, sizeof(parser));
parser.xmlstart = xml; parser.xmlstart = xml;
parser.xmlsize = size; parser.xmlsize = size;

View File

@ -41,7 +41,7 @@
<Tool <Tool
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS;WIN32;STATICLIB;DEBUG" PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS;MINIUPNP_STATICLIB;DEBUG"
MinimalRebuild="true" MinimalRebuild="true"
BasicRuntimeChecks="3" BasicRuntimeChecks="3"
RuntimeLibrary="3" RuntimeLibrary="3"
@ -104,7 +104,7 @@
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="2" Optimization="2"
EnableIntrinsicFunctions="true" EnableIntrinsicFunctions="true"
PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS;WIN32;STATICLIB" PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS;MINIUPNP_STATICLIB"
RuntimeLibrary="2" RuntimeLibrary="2"
EnableFunctionLevelLinking="true" EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0" UsePrecompiledHeader="0"
@ -160,6 +160,10 @@
RelativePath="..\minisoap.c" RelativePath="..\minisoap.c"
> >
</File> </File>
<File
RelativePath="..\minissdpc.c"
>
</File>
<File <File
RelativePath="..\miniupnpc.c" RelativePath="..\miniupnpc.c"
> >
@ -184,6 +188,10 @@
RelativePath="..\upnpcommands.c" RelativePath="..\upnpcommands.c"
> >
</File> </File>
<File
RelativePath="..\upnpdev.c"
>
</File>
<File <File
RelativePath="..\upnperrors.c" RelativePath="..\upnperrors.c"
> >
@ -198,10 +206,6 @@
Filter="h;hpp;hxx;hm;inl;inc;xsd" Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
> >
<File
RelativePath="..\bsdqueue.h"
>
</File>
<File <File
RelativePath="..\connecthostport.h" RelativePath="..\connecthostport.h"
> >
@ -218,6 +222,10 @@
RelativePath="..\minisoap.h" RelativePath="..\minisoap.h"
> >
</File> </File>
<File
RelativePath="..\minissdpc.h"
>
</File>
<File <File
RelativePath="..\miniupnpc.h" RelativePath="..\miniupnpc.h"
> >
@ -250,6 +258,10 @@
RelativePath="..\upnpcommands.h" RelativePath="..\upnpcommands.h"
> >
</File> </File>
<File
RelativePath="..\upnpdev.h"
>
</File>
<File <File
RelativePath="..\upnperrors.h" RelativePath="..\upnperrors.h"
> >

View File

@ -41,7 +41,7 @@
<Tool <Tool
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;STATICLIB;DEBUG;_CRT_SECURE_NO_WARNINGS" PreprocessorDefinitions="_DEBUG;_CONSOLE;MINIUPNP_STATICLIB;DEBUG;_CRT_SECURE_NO_WARNINGS"
MinimalRebuild="true" MinimalRebuild="true"
BasicRuntimeChecks="3" BasicRuntimeChecks="3"
RuntimeLibrary="3" RuntimeLibrary="3"
@ -115,7 +115,7 @@
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="2" Optimization="2"
EnableIntrinsicFunctions="true" EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;STATICLIB" PreprocessorDefinitions="NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;MINIUPNP_STATICLIB"
RuntimeLibrary="2" RuntimeLibrary="2"
EnableFunctionLevelLinking="true" EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0" UsePrecompiledHeader="0"

View File

@ -1,11 +1,14 @@
/* $Id: portlistingparse.c,v 1.6 2012/05/29 10:26:51 nanard Exp $ */ /* $Id: portlistingparse.c,v 1.9 2015/07/15 12:41:13 nanard Exp $ */
/* MiniUPnP project /* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2011 Thomas Bernard * (c) 2011-2015 Thomas Bernard
* This software is subject to the conditions detailed * This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */ * in the LICENCE file provided within the distribution */
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef DEBUG
#include <stdio.h>
#endif /* DEBUG */
#include "portlistingparse.h" #include "portlistingparse.h"
#include "minixml.h" #include "minixml.h"
@ -62,7 +65,17 @@ startelt(void * d, const char * name, int l)
{ {
struct PortMapping * pm; struct PortMapping * pm;
pm = calloc(1, sizeof(struct PortMapping)); pm = calloc(1, sizeof(struct PortMapping));
LIST_INSERT_HEAD( &(pdata->head), pm, entries); if(pm == NULL)
{
/* malloc error */
#ifdef DEBUG
fprintf(stderr, "%s: error allocating memory",
"startelt");
#endif /* DEBUG */
return;
}
pm->l_next = pdata->l_head; /* insert in list */
pdata->l_head = pm;
} }
} }
@ -82,7 +95,7 @@ data(void * d, const char * data, int l)
{ {
struct PortMapping * pm; struct PortMapping * pm;
struct PortMappingParserData * pdata = (struct PortMappingParserData *)d; struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;
pm = pdata->head.lh_first; pm = pdata->l_head;
if(!pm) if(!pm)
return; return;
if(l > 63) if(l > 63)
@ -134,7 +147,6 @@ ParsePortListing(const char * buffer, int bufsize,
struct xmlparser parser; struct xmlparser parser;
memset(pdata, 0, sizeof(struct PortMappingParserData)); memset(pdata, 0, sizeof(struct PortMappingParserData));
LIST_INIT(&(pdata->head));
/* init xmlparser */ /* init xmlparser */
parser.xmlstart = buffer; parser.xmlstart = buffer;
parser.xmlsize = bufsize; parser.xmlsize = bufsize;
@ -150,9 +162,10 @@ void
FreePortListing(struct PortMappingParserData * pdata) FreePortListing(struct PortMappingParserData * pdata)
{ {
struct PortMapping * pm; struct PortMapping * pm;
while((pm = pdata->head.lh_first) != NULL) while((pm = pdata->l_head) != NULL)
{ {
LIST_REMOVE(pm, entries); /* remove from list */
pdata->l_head = pm->l_next;
free(pm); free(pm);
} }
} }

View File

@ -1,16 +1,17 @@
/* $Id: receivedata.c,v 1.4 2012/06/23 22:34:47 nanard Exp $ */ /* $Id: receivedata.c,v 1.6 2014/11/13 13:51:52 nanard Exp $ */
/* Project : miniupnp /* Project : miniupnp
* Website : http://miniupnp.free.fr/ * Website : http://miniupnp.free.fr/
* Author : Thomas Bernard * Author : Thomas Bernard
* Copyright (c) 2011-2012 Thomas Bernard * Copyright (c) 2011-2014 Thomas Bernard
* This software is subject to the conditions detailed in the * This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */ * LICENCE file provided in this distribution. */
#include <stdio.h> #include <stdio.h>
#include <string.h>
#ifdef _WIN32 #ifdef _WIN32
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
#else #else /* _WIN32 */
#include <unistd.h> #include <unistd.h>
#if defined(__amigaos__) && !defined(__amigaos4__) #if defined(__amigaos__) && !defined(__amigaos4__)
#define socklen_t int #define socklen_t int
@ -21,10 +22,10 @@
#include <netinet/in.h> #include <netinet/in.h>
#if !defined(__amigaos__) && !defined(__amigaos4__) #if !defined(__amigaos__) && !defined(__amigaos4__)
#include <poll.h> #include <poll.h>
#endif #endif /* !defined(__amigaos__) && !defined(__amigaos4__) */
#include <errno.h> #include <errno.h>
#define MINIUPNPC_IGNORE_EINTR #define MINIUPNPC_IGNORE_EINTR
#endif #endif /* _WIN32 */
#ifdef _WIN32 #ifdef _WIN32
#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); #define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
@ -42,20 +43,20 @@ receivedata(int socket,
#if MINIUPNPC_GET_SRC_ADDR #if MINIUPNPC_GET_SRC_ADDR
struct sockaddr_storage src_addr; struct sockaddr_storage src_addr;
socklen_t src_addr_len = sizeof(src_addr); socklen_t src_addr_len = sizeof(src_addr);
#endif #endif /* MINIUPNPC_GET_SRC_ADDR */
int n; int n;
#if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) #if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__)
/* using poll */ /* using poll */
struct pollfd fds[1]; /* for the poll */ struct pollfd fds[1]; /* for the poll */
#ifdef MINIUPNPC_IGNORE_EINTR #ifdef MINIUPNPC_IGNORE_EINTR
do { do {
#endif #endif /* MINIUPNPC_IGNORE_EINTR */
fds[0].fd = socket; fds[0].fd = socket;
fds[0].events = POLLIN; fds[0].events = POLLIN;
n = poll(fds, 1, timeout); n = poll(fds, 1, timeout);
#ifdef MINIUPNPC_IGNORE_EINTR #ifdef MINIUPNPC_IGNORE_EINTR
} while(n < 0 && errno == EINTR); } while(n < 0 && errno == EINTR);
#endif #endif /* MINIUPNPC_IGNORE_EINTR */
if(n < 0) { if(n < 0) {
PRINT_SOCKET_ERROR("poll"); PRINT_SOCKET_ERROR("poll");
return -1; return -1;
@ -63,7 +64,7 @@ receivedata(int socket,
/* timeout */ /* timeout */
return 0; return 0;
} }
#else /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ #else /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
/* using select under _WIN32 and amigaos */ /* using select under _WIN32 and amigaos */
fd_set socketSet; fd_set socketSet;
TIMEVAL timeval; TIMEVAL timeval;
@ -78,13 +79,14 @@ receivedata(int socket,
} else if(n == 0) { } else if(n == 0) {
return 0; return 0;
} }
#endif #endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
#if MINIUPNPC_GET_SRC_ADDR #if MINIUPNPC_GET_SRC_ADDR
memset(&src_addr, 0, sizeof(src_addr));
n = recvfrom(socket, data, length, 0, n = recvfrom(socket, data, length, 0,
(struct sockaddr *)&src_addr, &src_addr_len); (struct sockaddr *)&src_addr, &src_addr_len);
#else #else /* MINIUPNPC_GET_SRC_ADDR */
n = recv(socket, data, length, 0); n = recv(socket, data, length, 0);
#endif #endif /* MINIUPNPC_GET_SRC_ADDR */
if(n<0) { if(n<0) {
PRINT_SOCKET_ERROR("recv"); PRINT_SOCKET_ERROR("recv");
} }
@ -93,12 +95,11 @@ receivedata(int socket,
const struct sockaddr_in6 * src_addr6 = (struct sockaddr_in6 *)&src_addr; const struct sockaddr_in6 * src_addr6 = (struct sockaddr_in6 *)&src_addr;
#ifdef DEBUG #ifdef DEBUG
printf("scope_id=%u\n", src_addr6->sin6_scope_id); printf("scope_id=%u\n", src_addr6->sin6_scope_id);
#endif #endif /* DEBUG */
if(scope_id) if(scope_id)
*scope_id = src_addr6->sin6_scope_id; *scope_id = src_addr6->sin6_scope_id;
} }
#endif #endif /* MINIUPNPC_GET_SRC_ADDR */
return n; return n;
} }

View File

@ -1,18 +1,24 @@
#! /usr/bin/python #! /usr/bin/python
# $Id: setup.py,v 1.9 2012/05/23 08:50:10 nanard Exp $ # $Id: setup.py,v 1.11 2015/07/09 12:43:29 nanard Exp $
# the MiniUPnP Project (c) 2007-2012 Thomas Bernard # the MiniUPnP Project (c) 2007-2014 Thomas Bernard
# http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/ # http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/
# #
# python script to build the miniupnpc module under unix # python script to build the miniupnpc module under unix
# #
# replace libminiupnpc.a by libminiupnpc.so for shared library usage # replace libminiupnpc.a by libminiupnpc.so for shared library usage
from distutils.core import setup, Extension from setuptools import setup, Extension
from distutils import sysconfig from distutils import sysconfig
sysconfig.get_config_vars()["OPT"] = '' sysconfig.get_config_vars()["OPT"] = ''
sysconfig.get_config_vars()["CFLAGS"] = '' sysconfig.get_config_vars()["CFLAGS"] = ''
setup(name="miniupnpc", version="1.7", setup(name="miniupnpc",
version=open('VERSION').read().strip(),
author='Thomas BERNARD',
author_email='miniupnp@free.fr',
license=open('LICENSE').read(),
url='http://miniupnp.free.fr/',
description='miniUPnP client',
ext_modules=[ ext_modules=[
Extension(name="miniupnpc", sources=["miniupnpcmodule.c"], Extension(name="miniupnpc", sources=["miniupnpcmodule.c"],
extra_objects=["libminiupnpc.a"]) extra_objects=["libminiupnpc.a"])
]) ])

View File

@ -1,6 +1,6 @@
#! /usr/bin/python #! /usr/bin/python
# $Id: setupmingw32.py,v 1.8 2012/05/23 08:50:10 nanard Exp $ # $Id: setupmingw32.py,v 1.9 2014/05/19 22:31:52 nanard Exp $
# the MiniUPnP Project (c) 2007-2012 Thomas Bernard # the MiniUPnP Project (c) 2007-2014 Thomas Bernard
# http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/ # http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/
# #
# python script to build the miniupnpc module under windows (using mingw32) # python script to build the miniupnpc module under windows (using mingw32)
@ -9,10 +9,16 @@ from distutils.core import setup, Extension
from distutils import sysconfig from distutils import sysconfig
sysconfig.get_config_vars()["OPT"] = '' sysconfig.get_config_vars()["OPT"] = ''
sysconfig.get_config_vars()["CFLAGS"] = '' sysconfig.get_config_vars()["CFLAGS"] = ''
setup(name="miniupnpc", version="1.7", setup(name="miniupnpc",
version=open('VERSION').read().strip(),
author='Thomas BERNARD',
author_email='miniupnp@free.fr',
license=open('LICENSE').read(),
url='http://miniupnp.free.fr/',
description='miniUPnP client',
ext_modules=[ ext_modules=[
Extension(name="miniupnpc", sources=["miniupnpcmodule.c"], Extension(name="miniupnpc", sources=["miniupnpcmodule.c"],
libraries=["ws2_32", "iphlpapi"], libraries=["ws2_32", "iphlpapi"],
extra_objects=["libminiupnpc.a"]) extra_objects=["libminiupnpc.a"])
]) ])

View File

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# $Id: testminiwget.sh,v 1.6 2012/05/29 13:03:40 nanard Exp $ # $Id: testminiwget.sh,v 1.13 2015/09/03 17:57:44 nanard Exp $
# project miniupnp : http://miniupnp.free.fr/ # project miniupnp : http://miniupnp.free.fr/
# (c) 2011-2012 Thomas Bernard # (c) 2011-2015 Thomas Bernard
# #
# test program for miniwget.c # test program for miniwget.c
# is usually invoked by "make check" # is usually invoked by "make check"
@ -13,22 +13,33 @@
# 4 - kills the local HTTP server and exits # 4 - kills the local HTTP server and exits
# #
# The script was tested and works with ksh, bash # The script was tested and works with ksh, bash
# It fails to run with dash 0.5.5.1 because of "kill %1" # it should now also run with dash
TMPDIR=`mktemp -d` TMPD=`mktemp -d -t miniwgetXXXXXXXXXX`
HTTPSERVEROUT="${TMPDIR}/httpserverout" HTTPSERVEROUT="${TMPD}/httpserverout"
EXPECTEDFILE="${TMPDIR}/expectedfile" EXPECTEDFILE="${TMPD}/expectedfile"
DOWNLOADEDFILE="${TMPDIR}/downloadedfile" DOWNLOADEDFILE="${TMPD}/downloadedfile"
#ADDR=localhost
ADDR="[::1]"
PORT= PORT=
RET=0 RET=0
case "$HAVE_IPV6" in
n|no|0)
ADDR=localhost
SERVERARGS=""
;;
*)
ADDR="[::1]"
SERVERARGS="-6"
;;
esac
#make minihttptestserver #make minihttptestserver
#make testminiwget #make testminiwget
# launching the test HTTP server # launching the test HTTP server
./minihttptestserver -6 -e $EXPECTEDFILE > $HTTPSERVEROUT & ./minihttptestserver $SERVERARGS -e $EXPECTEDFILE > $HTTPSERVEROUT &
SERVERPID=$!
while [ -z "$PORT" ]; do while [ -z "$PORT" ]; do
sleep 1 sleep 1
PORT=`cat $HTTPSERVEROUT | sed 's/Listening on port \([0-9]*\)/\1/' ` PORT=`cat $HTTPSERVEROUT | sed 's/Listening on port \([0-9]*\)/\1/' `
@ -67,8 +78,8 @@ else
fi fi
# kill the test HTTP server # kill the test HTTP server
kill %1 kill $SERVERPID
wait %1 wait $SERVERPID
# remove temporary files (for success cases) # remove temporary files (for success cases)
if [ $RET -eq 0 ]; then if [ $RET -eq 0 ]; then
@ -76,10 +87,10 @@ if [ $RET -eq 0 ]; then
rm -f "${DOWNLOADEDFILE}.2" rm -f "${DOWNLOADEDFILE}.2"
rm -f "${DOWNLOADEDFILE}.3" rm -f "${DOWNLOADEDFILE}.3"
rm -f $EXPECTEDFILE $HTTPSERVEROUT rm -f $EXPECTEDFILE $HTTPSERVEROUT
rmdir ${TMPDIR} rmdir ${TMPD}
else else
echo "at least one of the test FAILED" echo "at least one of the test FAILED"
echo "directory ${TMPDIR} is left intact" echo "directory ${TMPD} is left intact"
fi fi
exit $RET exit $RET

View File

@ -1,7 +1,7 @@
/* $Id: upnpc.c,v 1.97 2012/06/23 23:16:00 nanard Exp $ */ /* $Id: upnpc.c,v 1.112 2015/10/08 16:15:48 nanard Exp $ */
/* Project : miniupnp /* Project : miniupnp
* Author : Thomas Bernard * Author : Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard * Copyright (c) 2005-2015 Thomas Bernard
* This software is subject to the conditions detailed in the * This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */ * LICENCE file provided in this distribution. */
@ -16,10 +16,12 @@
/* for IPPROTO_TCP / IPPROTO_UDP */ /* for IPPROTO_TCP / IPPROTO_UDP */
#include <netinet/in.h> #include <netinet/in.h>
#endif #endif
#include <ctype.h>
#include "miniwget.h" #include "miniwget.h"
#include "miniupnpc.h" #include "miniupnpc.h"
#include "upnpcommands.h" #include "upnpcommands.h"
#include "upnperrors.h" #include "upnperrors.h"
#include "miniupnpcstrings.h"
/* protofix() checks if protocol is "UDP" or "TCP" /* protofix() checks if protocol is "UDP" or "TCP"
* returns NULL if not */ * returns NULL if not */
@ -41,6 +43,22 @@ const char * protofix(const char * proto)
return 0; return 0;
} }
/* is_int() checks if parameter is an integer or not
* 1 for integer
* 0 for not an integer */
int is_int(char const* s)
{
if(s == NULL)
return 0;
while(*s) {
/* #define isdigit(c) ((c) >= '0' && (c) <= '9') */
if(!isdigit(*s))
return 0;
s++;
}
return 1;
}
static void DisplayInfos(struct UPNPUrls * urls, static void DisplayInfos(struct UPNPUrls * urls,
struct IGDdatas * data) struct IGDdatas * data)
{ {
@ -174,7 +192,7 @@ static void NewListRedirections(struct UPNPUrls * urls,
if(r == UPNPCOMMAND_SUCCESS) if(r == UPNPCOMMAND_SUCCESS)
{ {
printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n"); printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n");
for(pm = pdata.head.lh_first; pm != NULL; pm = pm->entries.le_next) for(pm = pdata.l_head; pm != NULL; pm = pm->l_next)
{ {
printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n", printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n",
i, pm->protocol, pm->externalPort, pm->internalClient, i, pm->protocol, pm->externalPort, pm->internalClient,
@ -199,7 +217,7 @@ static void NewListRedirections(struct UPNPUrls * urls,
&pdata); &pdata);
if(r == UPNPCOMMAND_SUCCESS) if(r == UPNPCOMMAND_SUCCESS)
{ {
for(pm = pdata.head.lh_first; pm != NULL; pm = pm->entries.le_next) for(pm = pdata.l_head; pm != NULL; pm = pm->l_next)
{ {
printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n", printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n",
i, pm->protocol, pm->externalPort, pm->internalClient, i, pm->protocol, pm->externalPort, pm->internalClient,
@ -223,16 +241,19 @@ static void NewListRedirections(struct UPNPUrls * urls,
* 3 - Add port mapping * 3 - Add port mapping
* 4 - get this port mapping from the IGD */ * 4 - get this port mapping from the IGD */
static void SetRedirectAndTest(struct UPNPUrls * urls, static void SetRedirectAndTest(struct UPNPUrls * urls,
struct IGDdatas * data, struct IGDdatas * data,
const char * iaddr, const char * iaddr,
const char * iport, const char * iport,
const char * eport, const char * eport,
const char * proto, const char * proto,
const char * leaseDuration) const char * leaseDuration,
const char * description,
int addAny)
{ {
char externalIPAddress[40]; char externalIPAddress[40];
char intClient[40]; char intClient[40];
char intPort[6]; char intPort[6];
char reservedPort[6];
char duration[16]; char duration[16];
int r; int r;
@ -248,30 +269,41 @@ static void SetRedirectAndTest(struct UPNPUrls * urls,
return; return;
} }
UPNP_GetExternalIPAddress(urls->controlURL, r = UPNP_GetExternalIPAddress(urls->controlURL,
data->first.servicetype, data->first.servicetype,
externalIPAddress); externalIPAddress);
if(externalIPAddress[0])
printf("ExternalIPAddress = %s\n", externalIPAddress);
else
printf("GetExternalIPAddress failed.\n");
r = UPNP_AddPortMapping(urls->controlURL, data->first.servicetype,
eport, iport, iaddr, 0, proto, 0, leaseDuration);
if(r!=UPNPCOMMAND_SUCCESS) if(r!=UPNPCOMMAND_SUCCESS)
printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", printf("GetExternalIPAddress failed.\n");
eport, iport, iaddr, r, strupnperror(r)); else
printf("ExternalIPAddress = %s\n", externalIPAddress);
if (addAny) {
r = UPNP_AddAnyPortMapping(urls->controlURL, data->first.servicetype,
eport, iport, iaddr, description,
proto, 0, leaseDuration, reservedPort);
if(r==UPNPCOMMAND_SUCCESS)
eport = reservedPort;
else
printf("AddAnyPortMapping(%s, %s, %s) failed with code %d (%s)\n",
eport, iport, iaddr, r, strupnperror(r));
} else {
r = UPNP_AddPortMapping(urls->controlURL, data->first.servicetype,
eport, iport, iaddr, description,
proto, 0, leaseDuration);
if(r!=UPNPCOMMAND_SUCCESS)
printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
eport, iport, iaddr, r, strupnperror(r));
}
r = UPNP_GetSpecificPortMappingEntry(urls->controlURL, r = UPNP_GetSpecificPortMappingEntry(urls->controlURL,
data->first.servicetype, data->first.servicetype,
eport, proto, eport, proto, NULL/*remoteHost*/,
intClient, intPort, NULL/*desc*/, intClient, intPort, NULL/*desc*/,
NULL/*enabled*/, duration); NULL/*enabled*/, duration);
if(r!=UPNPCOMMAND_SUCCESS) if(r!=UPNPCOMMAND_SUCCESS)
printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n", printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n",
r, strupnperror(r)); r, strupnperror(r));
else {
if(intClient[0]) {
printf("InternalIP:Port = %s:%s\n", intClient, intPort); printf("InternalIP:Port = %s:%s\n", intClient, intPort);
printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n", printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n",
externalIPAddress, eport, proto, intClient, intPort, duration); externalIPAddress, eport, proto, intClient, intPort, duration);
@ -281,8 +313,9 @@ static void SetRedirectAndTest(struct UPNPUrls * urls,
static void static void
RemoveRedirect(struct UPNPUrls * urls, RemoveRedirect(struct UPNPUrls * urls,
struct IGDdatas * data, struct IGDdatas * data,
const char * eport, const char * eport,
const char * proto) const char * proto,
const char * remoteHost)
{ {
int r; int r;
if(!proto || !eport) if(!proto || !eport)
@ -296,10 +329,36 @@ RemoveRedirect(struct UPNPUrls * urls,
fprintf(stderr, "protocol invalid\n"); fprintf(stderr, "protocol invalid\n");
return; return;
} }
r = UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, 0); r = UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, remoteHost);
printf("UPNP_DeletePortMapping() returned : %d\n", r); printf("UPNP_DeletePortMapping() returned : %d\n", r);
} }
static void
RemoveRedirectRange(struct UPNPUrls * urls,
struct IGDdatas * data,
const char * ePortStart, char const * ePortEnd,
const char * proto, const char * manage)
{
int r;
if (!manage)
manage = "0";
if(!proto || !ePortStart || !ePortEnd)
{
fprintf(stderr, "invalid arguments\n");
return;
}
proto = protofix(proto);
if(!proto)
{
fprintf(stderr, "protocol invalid\n");
return;
}
r = UPNP_DeletePortMappingRange(urls->controlURL, data->first.servicetype, ePortStart, ePortEnd, proto, manage);
printf("UPNP_DeletePortMappingRange() returned : %d\n", r);
}
/* IGD:2, functions for service WANIPv6FirewallControl:1 */ /* IGD:2, functions for service WANIPv6FirewallControl:1 */
static void GetFirewallStatus(struct UPNPUrls * urls, struct IGDdatas * data) static void GetFirewallStatus(struct UPNPUrls * urls, struct IGDdatas * data)
{ {
@ -484,9 +543,12 @@ int main(int argc, char ** argv)
const char * rootdescurl = 0; const char * rootdescurl = 0;
const char * multicastif = 0; const char * multicastif = 0;
const char * minissdpdpath = 0; const char * minissdpdpath = 0;
int localport = UPNP_LOCAL_PORT_ANY;
int retcode = 0; int retcode = 0;
int error = 0; int error = 0;
int ipv6 = 0; int ipv6 = 0;
unsigned char ttl = 2; /* defaulting to 2 */
const char * description = 0;
#ifdef _WIN32 #ifdef _WIN32
WSADATA wsaData; WSADATA wsaData;
@ -497,22 +559,44 @@ int main(int argc, char ** argv)
return -1; return -1;
} }
#endif #endif
printf("upnpc : miniupnpc library test client. (c) 2006-2012 Thomas Bernard\n"); printf("upnpc : miniupnpc library test client, version %s.\n", MINIUPNPC_VERSION_STRING);
printf(" (c) 2005-2015 Thomas Bernard.\n");
printf("Go to http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/\n" printf("Go to http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/\n"
"for more information.\n"); "for more information.\n");
/* command line processing */ /* command line processing */
for(i=1; i<argc; i++) for(i=1; i<argc; i++)
{ {
if(0 == strcmp(argv[i], "--help") || 0 == strcmp(argv[i], "-h"))
{
command = 0;
break;
}
if(argv[i][0] == '-') if(argv[i][0] == '-')
{ {
if(argv[i][1] == 'u') if(argv[i][1] == 'u')
rootdescurl = argv[++i]; rootdescurl = argv[++i];
else if(argv[i][1] == 'm') else if(argv[i][1] == 'm')
multicastif = argv[++i]; multicastif = argv[++i];
else if(argv[i][1] == 'z')
{
char junk;
if(sscanf(argv[++i], "%d%c", &localport, &junk)!=1 ||
localport<0 || localport>65535 ||
(localport >1 && localport < 1024))
{
fprintf(stderr, "Invalid localport '%s'\n", argv[i]);
localport = UPNP_LOCAL_PORT_ANY;
break;
}
}
else if(argv[i][1] == 'p') else if(argv[i][1] == 'p')
minissdpdpath = argv[++i]; minissdpdpath = argv[++i];
else if(argv[i][1] == '6') else if(argv[i][1] == '6')
ipv6 = 1; ipv6 = 1;
else if(argv[i][1] == 'e')
description = argv[++i];
else if(argv[i][1] == 't')
ttl = (unsigned char)atoi(argv[++i]);
else else
{ {
command = argv[i][1]; command = argv[i][1];
@ -528,7 +612,8 @@ int main(int argc, char ** argv)
} }
} }
if(!command || (command == 'a' && commandargc<4) if(!command
|| (command == 'a' && commandargc<4)
|| (command == 'd' && argc<2) || (command == 'd' && argc<2)
|| (command == 'r' && argc<2) || (command == 'r' && argc<2)
|| (command == 'A' && commandargc<6) || (command == 'A' && commandargc<6)
@ -536,11 +621,13 @@ int main(int argc, char ** argv)
|| (command == 'D' && commandargc<1)) || (command == 'D' && commandargc<1))
{ {
fprintf(stderr, "Usage :\t%s [options] -a ip port external_port protocol [duration]\n\t\tAdd port redirection\n", argv[0]); fprintf(stderr, "Usage :\t%s [options] -a ip port external_port protocol [duration]\n\t\tAdd port redirection\n", argv[0]);
fprintf(stderr, " \t%s [options] -d external_port protocol [port2 protocol2] [...]\n\t\tDelete port redirection\n", argv[0]); fprintf(stderr, " \t%s [options] -d external_port protocol <remote host>\n\t\tDelete port redirection\n", argv[0]);
fprintf(stderr, " \t%s [options] -s\n\t\tGet Connection status\n", argv[0]); fprintf(stderr, " \t%s [options] -s\n\t\tGet Connection status\n", argv[0]);
fprintf(stderr, " \t%s [options] -l\n\t\tList redirections\n", argv[0]); fprintf(stderr, " \t%s [options] -l\n\t\tList redirections\n", argv[0]);
fprintf(stderr, " \t%s [options] -L\n\t\tList redirections (using GetListOfPortMappings, IGD v2)\n", argv[0]); fprintf(stderr, " \t%s [options] -L\n\t\tList redirections (using GetListOfPortMappings (for IGD:2 only)\n", argv[0]);
fprintf(stderr, " \t%s [options] -r port1 protocol1 [port2 protocol2] [...]\n\t\tAdd all redirections to the current host\n", argv[0]); fprintf(stderr, " \t%s [options] -n ip port external_port protocol [duration]\n\t\tAdd (any) port redirection allowing IGD to use alternative external_port (for IGD:2 only)\n", argv[0]);
fprintf(stderr, " \t%s [options] -N external_port_start external_port_end protocol [manage]\n\t\tDelete range of port redirections (for IGD:2 only)\n", argv[0]);
fprintf(stderr, " \t%s [options] -r port1 [external_port1] protocol1 [port2 [external_port2] protocol2] [...]\n\t\tAdd all redirections to the current host\n", argv[0]);
fprintf(stderr, " \t%s [options] -A remote_ip remote_port internal_ip internal_port protocol lease_time\n\t\tAdd Pinhole (for IGD:2 only)\n", argv[0]); fprintf(stderr, " \t%s [options] -A remote_ip remote_port internal_ip internal_port protocol lease_time\n\t\tAdd Pinhole (for IGD:2 only)\n", argv[0]);
fprintf(stderr, " \t%s [options] -U uniqueID new_lease_time\n\t\tUpdate Pinhole (for IGD:2 only)\n", argv[0]); fprintf(stderr, " \t%s [options] -U uniqueID new_lease_time\n\t\tUpdate Pinhole (for IGD:2 only)\n", argv[0]);
fprintf(stderr, " \t%s [options] -C uniqueID\n\t\tCheck if Pinhole is Working (for IGD:2 only)\n", argv[0]); fprintf(stderr, " \t%s [options] -C uniqueID\n\t\tCheck if Pinhole is Working (for IGD:2 only)\n", argv[0]);
@ -551,16 +638,19 @@ int main(int argc, char ** argv)
fprintf(stderr, " \t%s [options] -P\n\t\tGet Presentation url\n", argv[0]); fprintf(stderr, " \t%s [options] -P\n\t\tGet Presentation url\n", argv[0]);
fprintf(stderr, "\nprotocol is UDP or TCP\n"); fprintf(stderr, "\nprotocol is UDP or TCP\n");
fprintf(stderr, "Options:\n"); fprintf(stderr, "Options:\n");
fprintf(stderr, " -e description : set description for port mapping.\n");
fprintf(stderr, " -6 : use ip v6 instead of ip v4.\n"); fprintf(stderr, " -6 : use ip v6 instead of ip v4.\n");
fprintf(stderr, " -u url : bypass discovery process by providing the XML root description url.\n"); fprintf(stderr, " -u url : bypass discovery process by providing the XML root description url.\n");
fprintf(stderr, " -m address/interface : provide ip address (ip v4) or interface name (ip v4 or v6) to use for sending SSDP multicast packets.\n"); fprintf(stderr, " -m address/interface : provide ip address (ip v4) or interface name (ip v4 or v6) to use for sending SSDP multicast packets.\n");
fprintf(stderr, " -z localport : SSDP packets local (source) port (1024-65535).\n");
fprintf(stderr, " -p path : use this path for MiniSSDPd socket.\n"); fprintf(stderr, " -p path : use this path for MiniSSDPd socket.\n");
fprintf(stderr, " -t ttl : set multicast TTL. Default value is 2.\n");
return 1; return 1;
} }
if( rootdescurl if( rootdescurl
|| (devlist = upnpDiscover(2000, multicastif, minissdpdpath, || (devlist = upnpDiscover(2000, multicastif, minissdpdpath,
0/*sameport*/, ipv6, &error))) localport, ipv6, ttl, &error)))
{ {
struct UPNPDev * device; struct UPNPDev * device;
struct UPNPUrls urls; struct UPNPUrls urls;
@ -574,7 +664,7 @@ int main(int argc, char ** argv)
device->descURL, device->st); device->descURL, device->st);
} }
} }
else else if(!rootdescurl)
{ {
printf("upnpDiscover() error code=%d\n", error); printf("upnpDiscover() error code=%d\n", error);
} }
@ -620,26 +710,56 @@ int main(int argc, char ** argv)
break; break;
case 'a': case 'a':
SetRedirectAndTest(&urls, &data, SetRedirectAndTest(&urls, &data,
commandargv[0], commandargv[1], commandargv[0], commandargv[1],
commandargv[2], commandargv[3], commandargv[2], commandargv[3],
(commandargc > 4)?commandargv[4]:"0"); (commandargc > 4)?commandargv[4]:"0",
description, 0);
break; break;
case 'd': case 'd':
for(i=0; i<commandargc; i+=2) RemoveRedirect(&urls, &data, commandargv[0], commandargv[1],
{ commandargc > 2 ? commandargv[2] : NULL);
RemoveRedirect(&urls, &data, commandargv[i], commandargv[i+1]); break;
} case 'n': /* aNy */
SetRedirectAndTest(&urls, &data,
commandargv[0], commandargv[1],
commandargv[2], commandargv[3],
(commandargc > 4)?commandargv[4]:"0",
description, 1);
break;
case 'N':
if (commandargc < 3)
fprintf(stderr, "too few arguments\n");
RemoveRedirectRange(&urls, &data, commandargv[0], commandargv[1], commandargv[2],
commandargc > 3 ? commandargv[3] : NULL);
break; break;
case 's': case 's':
GetConnectionStatus(&urls, &data); GetConnectionStatus(&urls, &data);
break; break;
case 'r': case 'r':
for(i=0; i<commandargc; i+=2) i = 0;
while(i<commandargc)
{ {
/*printf("port %s protocol %s\n", argv[i], argv[i+1]);*/ if(!is_int(commandargv[i])) {
SetRedirectAndTest(&urls, &data, /* 1st parameter not an integer : error */
lanaddr, commandargv[i], fprintf(stderr, "command -r : %s is not an port number\n", commandargv[i]);
commandargv[i], commandargv[i+1], "0"); retcode = 1;
break;
} else if(is_int(commandargv[i+1])){
/* 2nd parameter is an integer : <port> <external_port> <protocol> */
SetRedirectAndTest(&urls, &data,
lanaddr, commandargv[i],
commandargv[i+1], commandargv[i+2], "0",
description, 0);
i+=3; /* 3 parameters parsed */
} else {
/* 2nd parameter not an integer : <port> <protocol> */
SetRedirectAndTest(&urls, &data,
lanaddr, commandargv[i],
commandargv[i], commandargv[i+1], "0",
description, 0);
i+=2; /* 2 parameters parsed */
}
} }
break; break;
case 'A': case 'A':
@ -702,6 +822,12 @@ int main(int argc, char ** argv)
fprintf(stderr, "No IGD UPnP Device found on the network !\n"); fprintf(stderr, "No IGD UPnP Device found on the network !\n");
retcode = 1; retcode = 1;
} }
#ifdef _WIN32
nResult = WSACleanup();
if(nResult != NO_ERROR) {
fprintf(stderr, "WSACleanup() failed.\n");
}
#endif /* _WIN32 */
return retcode; return retcode;
} }

View File

@ -1,7 +1,7 @@
/* $Id: upnpcommands.c,v 1.40 2012/06/23 22:36:35 nanard Exp $ */ /* $Id: upnpcommands.c,v 1.46 2015/07/15 12:19:00 nanard Exp $ */
/* Project : miniupnp /* Project : miniupnp
* Author : Thomas Bernard * Author : Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard * Copyright (c) 2005-2015 Thomas Bernard
* This software is subject to the conditions detailed in the * This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. * LICENCE file provided in this distribution.
* */ * */
@ -20,7 +20,7 @@ my_atoui(const char * s)
/* /*
* */ * */
LIBSPEC UNSIGNED_INTEGER MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalBytesSent(const char * controlURL, UPNP_GetTotalBytesSent(const char * controlURL,
const char * servicetype) const char * servicetype)
{ {
@ -44,7 +44,7 @@ UPNP_GetTotalBytesSent(const char * controlURL,
/* /*
* */ * */
LIBSPEC UNSIGNED_INTEGER MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalBytesReceived(const char * controlURL, UPNP_GetTotalBytesReceived(const char * controlURL,
const char * servicetype) const char * servicetype)
{ {
@ -68,7 +68,7 @@ UPNP_GetTotalBytesReceived(const char * controlURL,
/* /*
* */ * */
LIBSPEC UNSIGNED_INTEGER MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalPacketsSent(const char * controlURL, UPNP_GetTotalPacketsSent(const char * controlURL,
const char * servicetype) const char * servicetype)
{ {
@ -92,7 +92,7 @@ UPNP_GetTotalPacketsSent(const char * controlURL,
/* /*
* */ * */
LIBSPEC UNSIGNED_INTEGER MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalPacketsReceived(const char * controlURL, UPNP_GetTotalPacketsReceived(const char * controlURL,
const char * servicetype) const char * servicetype)
{ {
@ -116,7 +116,7 @@ UPNP_GetTotalPacketsReceived(const char * controlURL,
/* UPNP_GetStatusInfo() call the corresponding UPNP method /* UPNP_GetStatusInfo() call the corresponding UPNP method
* returns the current status and uptime */ * returns the current status and uptime */
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetStatusInfo(const char * controlURL, UPNP_GetStatusInfo(const char * controlURL,
const char * servicetype, const char * servicetype,
char * status, char * status,
@ -159,7 +159,7 @@ UPNP_GetStatusInfo(const char * controlURL,
if(up) if(up)
sscanf(up,"%u",uptime); sscanf(up,"%u",uptime);
else else
uptime = 0; *uptime = 0;
} }
if(lastconnerror) { if(lastconnerror) {
@ -181,7 +181,7 @@ UPNP_GetStatusInfo(const char * controlURL,
/* UPNP_GetConnectionTypeInfo() call the corresponding UPNP method /* UPNP_GetConnectionTypeInfo() call the corresponding UPNP method
* returns the connection type */ * returns the connection type */
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetConnectionTypeInfo(const char * controlURL, UPNP_GetConnectionTypeInfo(const char * controlURL,
const char * servicetype, const char * servicetype,
char * connectionType) char * connectionType)
@ -224,7 +224,7 @@ UPNP_GetConnectionTypeInfo(const char * controlURL,
* One of the values can be null * One of the values can be null
* Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only * Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only
* We can use the GetCommonLinkProperties from WANCommonInterfaceConfig:1 */ * We can use the GetCommonLinkProperties from WANCommonInterfaceConfig:1 */
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetLinkLayerMaxBitRates(const char * controlURL, UPNP_GetLinkLayerMaxBitRates(const char * controlURL,
const char * servicetype, const char * servicetype,
unsigned int * bitrateDown, unsigned int * bitrateDown,
@ -293,7 +293,7 @@ UPNP_GetLinkLayerMaxBitRates(const char * controlURL,
* 402 Invalid Args - 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. * 501 Action Failed - See UPnP Device Architecture section on Control.
*/ */
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetExternalIPAddress(const char * controlURL, UPNP_GetExternalIPAddress(const char * controlURL,
const char * servicetype, const char * servicetype,
char * extIpAdd) char * extIpAdd)
@ -333,15 +333,15 @@ UPNP_GetExternalIPAddress(const char * controlURL,
return ret; return ret;
} }
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_AddPortMapping(const char * controlURL, const char * servicetype, UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
const char * extPort, const char * extPort,
const char * inPort, const char * inPort,
const char * inClient, const char * inClient,
const char * desc, const char * desc,
const char * proto, const char * proto,
const char * remoteHost, const char * remoteHost,
const char * leaseDuration) const char * leaseDuration)
{ {
struct UPNParg * AddPortMappingArgs; struct UPNParg * AddPortMappingArgs;
char * buffer; char * buffer;
@ -354,6 +354,8 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
return UPNPCOMMAND_INVALID_ARGS; return UPNPCOMMAND_INVALID_ARGS;
AddPortMappingArgs = calloc(9, sizeof(struct UPNParg)); AddPortMappingArgs = calloc(9, sizeof(struct UPNParg));
if(AddPortMappingArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
AddPortMappingArgs[0].elt = "NewRemoteHost"; AddPortMappingArgs[0].elt = "NewRemoteHost";
AddPortMappingArgs[0].val = remoteHost; AddPortMappingArgs[0].val = remoteHost;
AddPortMappingArgs[1].elt = "NewExternalPort"; AddPortMappingArgs[1].elt = "NewExternalPort";
@ -394,7 +396,76 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
return ret; return ret;
} }
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype,
const char * extPort,
const char * inPort,
const char * inClient,
const char * desc,
const char * proto,
const char * remoteHost,
const char * leaseDuration,
char * reservedPort)
{
struct UPNParg * AddPortMappingArgs;
char * buffer;
int bufsize;
struct NameValueParserData pdata;
const char * resVal;
int ret;
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";
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"AddAnyPortMapping", AddPortMappingArgs,
&bufsize))) {
free(AddPortMappingArgs);
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal) {
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(resVal, "%d", &ret);
} else {
char *p;
p = GetValueFromNameValueList(&pdata, "NewReservedPort");
if(p) {
strncpy(reservedPort, p, 6);
reservedPort[5] = '\0';
ret = UPNPCOMMAND_SUCCESS;
} else {
ret = UPNPCOMMAND_INVALID_RESPONSE;
}
}
ClearNameValueList(&pdata);
free(AddPortMappingArgs);
return ret;
}
MINIUPNP_LIBSPEC int
UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
const char * extPort, const char * proto, const char * extPort, const char * proto,
const char * remoteHost) const char * remoteHost)
@ -411,6 +482,8 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
return UPNPCOMMAND_INVALID_ARGS; return UPNPCOMMAND_INVALID_ARGS;
DeletePortMappingArgs = calloc(4, sizeof(struct UPNParg)); DeletePortMappingArgs = calloc(4, sizeof(struct UPNParg));
if(DeletePortMappingArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
DeletePortMappingArgs[0].elt = "NewRemoteHost"; DeletePortMappingArgs[0].elt = "NewRemoteHost";
DeletePortMappingArgs[0].val = remoteHost; DeletePortMappingArgs[0].val = remoteHost;
DeletePortMappingArgs[1].elt = "NewExternalPort"; DeletePortMappingArgs[1].elt = "NewExternalPort";
@ -438,7 +511,55 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
return ret; return ret;
} }
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype,
const char * extPortStart, const char * extPortEnd,
const char * proto,
const char * manage)
{
struct UPNParg * DeletePortMappingArgs;
char * buffer;
int bufsize;
struct NameValueParserData pdata;
const char * resVal;
int ret;
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;
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"DeletePortMappingRange",
DeletePortMappingArgs, &bufsize))) {
free(DeletePortMappingArgs);
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal) {
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(resVal, "%d", &ret);
} else {
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
free(DeletePortMappingArgs);
return ret;
}
MINIUPNP_LIBSPEC int
UPNP_GetGenericPortMappingEntry(const char * controlURL, UPNP_GetGenericPortMappingEntry(const char * controlURL,
const char * servicetype, const char * servicetype,
const char * index, const char * index,
@ -462,6 +583,8 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL,
intClient[0] = '\0'; intClient[0] = '\0';
intPort[0] = '\0'; intPort[0] = '\0';
GetPortMappingArgs = calloc(2, sizeof(struct UPNParg)); GetPortMappingArgs = calloc(2, sizeof(struct UPNParg));
if(GetPortMappingArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
GetPortMappingArgs[0].elt = "NewPortMappingIndex"; GetPortMappingArgs[0].elt = "NewPortMappingIndex";
GetPortMappingArgs[0].val = index; GetPortMappingArgs[0].val = index;
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
@ -533,7 +656,7 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL,
return r; return r;
} }
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetPortMappingNumberOfEntries(const char * controlURL, UPNP_GetPortMappingNumberOfEntries(const char * controlURL,
const char * servicetype, const char * servicetype,
unsigned int * numEntries) unsigned int * numEntries)
@ -574,11 +697,12 @@ UPNP_GetPortMappingNumberOfEntries(const char * controlURL,
/* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping /* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping
* the result is returned in the intClient and intPort strings * the result is returned in the intClient and intPort strings
* please provide 16 and 6 bytes of data */ * please provide 16 and 6 bytes of data */
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetSpecificPortMappingEntry(const char * controlURL, UPNP_GetSpecificPortMappingEntry(const char * controlURL,
const char * servicetype, const char * servicetype,
const char * extPort, const char * extPort,
const char * proto, const char * proto,
const char * remoteHost,
char * intClient, char * intClient,
char * intPort, char * intPort,
char * desc, char * desc,
@ -596,8 +720,10 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
return UPNPCOMMAND_INVALID_ARGS; return UPNPCOMMAND_INVALID_ARGS;
GetPortMappingArgs = calloc(4, sizeof(struct UPNParg)); GetPortMappingArgs = calloc(4, sizeof(struct UPNParg));
if(GetPortMappingArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
GetPortMappingArgs[0].elt = "NewRemoteHost"; GetPortMappingArgs[0].elt = "NewRemoteHost";
/* TODO : add remote host ? */ GetPortMappingArgs[0].val = remoteHost;
GetPortMappingArgs[1].elt = "NewExternalPort"; GetPortMappingArgs[1].elt = "NewExternalPort";
GetPortMappingArgs[1].val = extPort; GetPortMappingArgs[1].val = extPort;
GetPortMappingArgs[2].elt = "NewProtocol"; GetPortMappingArgs[2].elt = "NewProtocol";
@ -665,7 +791,7 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
* 733 InconsistantParameters - NewStartPort and NewEndPort values are not * 733 InconsistantParameters - NewStartPort and NewEndPort values are not
* consistent. * consistent.
*/ */
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetListOfPortMappings(const char * controlURL, UPNP_GetListOfPortMappings(const char * controlURL,
const char * servicetype, const char * servicetype,
const char * startPort, const char * startPort,
@ -685,6 +811,8 @@ UPNP_GetListOfPortMappings(const char * controlURL,
return UPNPCOMMAND_INVALID_ARGS; return UPNPCOMMAND_INVALID_ARGS;
GetListOfPortMappingsArgs = calloc(6, sizeof(struct UPNParg)); GetListOfPortMappingsArgs = calloc(6, sizeof(struct UPNParg));
if(GetListOfPortMappingsArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
GetListOfPortMappingsArgs[0].elt = "NewStartPort"; GetListOfPortMappingsArgs[0].elt = "NewStartPort";
GetListOfPortMappingsArgs[0].val = startPort; GetListOfPortMappingsArgs[0].val = startPort;
GetListOfPortMappingsArgs[1].elt = "NewEndPort"; GetListOfPortMappingsArgs[1].elt = "NewEndPort";
@ -747,7 +875,7 @@ UPNP_GetListOfPortMappings(const char * controlURL,
} }
/* IGD:2, functions for service WANIPv6FirewallControl:1 */ /* IGD:2, functions for service WANIPv6FirewallControl:1 */
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetFirewallStatus(const char * controlURL, UPNP_GetFirewallStatus(const char * controlURL,
const char * servicetype, const char * servicetype,
int * firewallEnabled, int * firewallEnabled,
@ -759,7 +887,7 @@ UPNP_GetFirewallStatus(const char * controlURL,
char * fe, *ipa, *p; char * fe, *ipa, *p;
int ret = UPNPCOMMAND_UNKNOWN_ERROR; int ret = UPNPCOMMAND_UNKNOWN_ERROR;
if(!firewallEnabled && !inboundPinholeAllowed) if(!firewallEnabled || !inboundPinholeAllowed)
return UPNPCOMMAND_INVALID_ARGS; return UPNPCOMMAND_INVALID_ARGS;
buffer = simpleUPnPcommand(-1, controlURL, servicetype, buffer = simpleUPnPcommand(-1, controlURL, servicetype,
@ -791,7 +919,7 @@ UPNP_GetFirewallStatus(const char * controlURL,
return ret; return ret;
} }
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype, UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype,
const char * remoteHost, const char * remoteHost,
const char * remotePort, const char * remotePort,
@ -812,6 +940,8 @@ UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype
return UPNPCOMMAND_INVALID_ARGS; return UPNPCOMMAND_INVALID_ARGS;
GetOutboundPinholeTimeoutArgs = calloc(6, sizeof(struct UPNParg)); GetOutboundPinholeTimeoutArgs = calloc(6, sizeof(struct UPNParg));
if(GetOutboundPinholeTimeoutArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
GetOutboundPinholeTimeoutArgs[0].elt = "RemoteHost"; GetOutboundPinholeTimeoutArgs[0].elt = "RemoteHost";
GetOutboundPinholeTimeoutArgs[0].val = remoteHost; GetOutboundPinholeTimeoutArgs[0].val = remoteHost;
GetOutboundPinholeTimeoutArgs[1].elt = "RemotePort"; GetOutboundPinholeTimeoutArgs[1].elt = "RemotePort";
@ -846,7 +976,7 @@ UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype
return ret; return ret;
} }
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_AddPinhole(const char * controlURL, const char * servicetype, UPNP_AddPinhole(const char * controlURL, const char * servicetype,
const char * remoteHost, const char * remoteHost,
const char * remotePort, const char * remotePort,
@ -868,6 +998,8 @@ UPNP_AddPinhole(const char * controlURL, const char * servicetype,
return UPNPCOMMAND_INVALID_ARGS; return UPNPCOMMAND_INVALID_ARGS;
AddPinholeArgs = calloc(7, sizeof(struct UPNParg)); AddPinholeArgs = calloc(7, sizeof(struct UPNParg));
if(AddPinholeArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
/* RemoteHost can be wilcarded */ /* RemoteHost can be wilcarded */
if(strncmp(remoteHost, "empty", 5)==0) if(strncmp(remoteHost, "empty", 5)==0)
{ {
@ -925,7 +1057,7 @@ UPNP_AddPinhole(const char * controlURL, const char * servicetype,
return ret; return ret;
} }
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_UpdatePinhole(const char * controlURL, const char * servicetype, UPNP_UpdatePinhole(const char * controlURL, const char * servicetype,
const char * uniqueID, const char * uniqueID,
const char * leaseTime) const char * leaseTime)
@ -941,6 +1073,8 @@ UPNP_UpdatePinhole(const char * controlURL, const char * servicetype,
return UPNPCOMMAND_INVALID_ARGS; return UPNPCOMMAND_INVALID_ARGS;
UpdatePinholeArgs = calloc(3, sizeof(struct UPNParg)); UpdatePinholeArgs = calloc(3, sizeof(struct UPNParg));
if(UpdatePinholeArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
UpdatePinholeArgs[0].elt = "UniqueID"; UpdatePinholeArgs[0].elt = "UniqueID";
UpdatePinholeArgs[0].val = uniqueID; UpdatePinholeArgs[0].val = uniqueID;
UpdatePinholeArgs[1].elt = "NewLeaseTime"; UpdatePinholeArgs[1].elt = "NewLeaseTime";
@ -967,7 +1101,7 @@ UPNP_UpdatePinhole(const char * controlURL, const char * servicetype,
return ret; return ret;
} }
LIBSPEC int 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)
{ {
/*struct NameValueParserData pdata;*/ /*struct NameValueParserData pdata;*/
@ -982,6 +1116,8 @@ UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char
return UPNPCOMMAND_INVALID_ARGS; return UPNPCOMMAND_INVALID_ARGS;
DeletePinholeArgs = calloc(2, sizeof(struct UPNParg)); DeletePinholeArgs = calloc(2, sizeof(struct UPNParg));
if(DeletePinholeArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
DeletePinholeArgs[0].elt = "UniqueID"; DeletePinholeArgs[0].elt = "UniqueID";
DeletePinholeArgs[0].val = uniqueID; DeletePinholeArgs[0].val = uniqueID;
buffer = simpleUPnPcommand(-1, controlURL, servicetype, buffer = simpleUPnPcommand(-1, controlURL, servicetype,
@ -1006,7 +1142,7 @@ UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char
return ret; return ret;
} }
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype, UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype,
const char * uniqueID, int * isWorking) const char * uniqueID, int * isWorking)
{ {
@ -1021,6 +1157,8 @@ UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype,
return UPNPCOMMAND_INVALID_ARGS; return UPNPCOMMAND_INVALID_ARGS;
CheckPinholeWorkingArgs = calloc(4, sizeof(struct UPNParg)); CheckPinholeWorkingArgs = calloc(4, sizeof(struct UPNParg));
if(CheckPinholeWorkingArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
CheckPinholeWorkingArgs[0].elt = "UniqueID"; CheckPinholeWorkingArgs[0].elt = "UniqueID";
CheckPinholeWorkingArgs[0].val = uniqueID; CheckPinholeWorkingArgs[0].val = uniqueID;
buffer = simpleUPnPcommand(-1, controlURL, servicetype, buffer = simpleUPnPcommand(-1, controlURL, servicetype,
@ -1051,7 +1189,7 @@ UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype,
return ret; return ret;
} }
LIBSPEC int MINIUPNP_LIBSPEC int
UPNP_GetPinholePackets(const char * controlURL, const char * servicetype, UPNP_GetPinholePackets(const char * controlURL, const char * servicetype,
const char * uniqueID, int * packets) const char * uniqueID, int * packets)
{ {
@ -1066,6 +1204,8 @@ UPNP_GetPinholePackets(const char * controlURL, const char * servicetype,
return UPNPCOMMAND_INVALID_ARGS; return UPNPCOMMAND_INVALID_ARGS;
GetPinholePacketsArgs = calloc(4, sizeof(struct UPNParg)); GetPinholePacketsArgs = calloc(4, sizeof(struct UPNParg));
if(GetPinholePacketsArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
GetPinholePacketsArgs[0].elt = "UniqueID"; GetPinholePacketsArgs[0].elt = "UniqueID";
GetPinholePacketsArgs[0].val = uniqueID; GetPinholePacketsArgs[0].val = uniqueID;
buffer = simpleUPnPcommand(-1, controlURL, servicetype, buffer = simpleUPnPcommand(-1, controlURL, servicetype,

View File

@ -0,0 +1,23 @@
/* $Id: upnpdev.c,v 1.1 2015/08/28 12:14:19 nanard Exp $ */
/* Project : miniupnp
* Web : http://miniupnp.free.fr/
* Author : Thomas BERNARD
* copyright (c) 2005-2015 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENSE file. */
#include <stdlib.h>
#include "upnpdev.h"
/* freeUPNPDevlist() should be used to
* free the chained list returned by upnpDiscover() */
void freeUPNPDevlist(struct UPNPDev * devlist)
{
struct UPNPDev * next;
while(devlist)
{
next = devlist->pNext;
free(devlist);
devlist = next;
}
}

View File

@ -1,4 +1,4 @@
/* $Id: upnperrors.c,v 1.6 2012/03/15 01:02:03 nanard Exp $ */ /* $Id: upnperrors.c,v 1.8 2014/06/10 09:41:48 nanard Exp $ */
/* Project : miniupnp /* Project : miniupnp
* Author : Thomas BERNARD * Author : Thomas BERNARD
* copyright (c) 2007 Thomas Bernard * copyright (c) 2007 Thomas Bernard
@ -24,6 +24,9 @@ const char * strupnperror(int err)
case UPNPCOMMAND_INVALID_ARGS: case UPNPCOMMAND_INVALID_ARGS:
s = "Miniupnpc Invalid Arguments"; s = "Miniupnpc Invalid Arguments";
break; break;
case UPNPCOMMAND_INVALID_RESPONSE:
s = "Miniupnpc Invalid response";
break;
case UPNPDISCOVER_SOCKET_ERROR: case UPNPDISCOVER_SOCKET_ERROR:
s = "Miniupnpc Socket error"; s = "Miniupnpc Socket error";
break; break;

View File

@ -1,7 +1,7 @@
/* $Id: upnpreplyparse.c,v 1.12 2012/03/05 19:42:48 nanard Exp $ */ /* $Id: upnpreplyparse.c,v 1.19 2015/07/15 10:29:11 nanard Exp $ */
/* MiniUPnP project /* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2011 Thomas Bernard * (c) 2006-2015 Thomas Bernard
* This software is subject to the conditions detailed * This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */ * in the LICENCE file provided within the distribution */
@ -15,18 +15,65 @@
static void static void
NameValueParserStartElt(void * d, const char * name, int l) NameValueParserStartElt(void * d, const char * name, int l)
{ {
struct NameValueParserData * data = (struct NameValueParserData *)d; struct NameValueParserData * data = (struct NameValueParserData *)d;
data->topelt = 1;
if(l>63) if(l>63)
l = 63; l = 63;
memcpy(data->curelt, name, l); memcpy(data->curelt, name, l);
data->curelt[l] = '\0'; data->curelt[l] = '\0';
data->cdata = NULL;
data->cdatalen = 0;
}
static void
NameValueParserEndElt(void * d, const char * name, int l)
{
struct NameValueParserData * data = (struct NameValueParserData *)d;
struct NameValue * nv;
(void)name;
(void)l;
if(!data->topelt)
return;
if(strcmp(data->curelt, "NewPortListing") != 0)
{
int l;
/* standard case. Limited to n chars strings */
l = data->cdatalen;
nv = malloc(sizeof(struct NameValue));
if(nv == NULL)
{
/* malloc error */
#ifdef DEBUG
fprintf(stderr, "%s: error allocating memory",
"NameValueParserEndElt");
#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)
{
memcpy(nv->value, data->cdata, l);
nv->value[l] = '\0';
}
else
{
nv->value[0] = '\0';
}
nv->l_next = data->l_head; /* insert in list */
data->l_head = nv;
}
data->cdata = NULL;
data->cdatalen = 0;
data->topelt = 0;
} }
static void static void
NameValueParserGetData(void * d, const char * datas, int l) NameValueParserGetData(void * d, const char * datas, int l)
{ {
struct NameValueParserData * data = (struct NameValueParserData *)d; struct NameValueParserData * data = (struct NameValueParserData *)d;
struct NameValue * nv;
if(strcmp(data->curelt, "NewPortListing") == 0) if(strcmp(data->curelt, "NewPortListing") == 0)
{ {
/* specific case for NewPortListing which is a XML Document */ /* specific case for NewPortListing which is a XML Document */
@ -34,6 +81,10 @@ NameValueParserGetData(void * d, const char * datas, int l)
if(!data->portListing) if(!data->portListing)
{ {
/* malloc error */ /* malloc error */
#ifdef DEBUG
fprintf(stderr, "%s: error allocating memory",
"NameValueParserGetData");
#endif /* DEBUG */
return; return;
} }
memcpy(data->portListing, datas, l); memcpy(data->portListing, datas, l);
@ -42,15 +93,9 @@ NameValueParserGetData(void * d, const char * datas, int l)
} }
else else
{ {
/* standard case. Limited to 63 chars strings */ /* standard case. */
nv = malloc(sizeof(struct NameValue)); data->cdata = datas;
if(l>63) data->cdatalen = l;
l = 63;
strncpy(nv->name, data->curelt, 64);
nv->name[63] = '\0';
memcpy(nv->value, datas, l);
nv->value[l] = '\0';
LIST_INSERT_HEAD( &(data->head), nv, entries);
} }
} }
@ -58,19 +103,19 @@ void
ParseNameValue(const char * buffer, int bufsize, ParseNameValue(const char * buffer, int bufsize,
struct NameValueParserData * data) struct NameValueParserData * data)
{ {
struct xmlparser parser; struct xmlparser parser;
LIST_INIT(&(data->head)); data->l_head = NULL;
data->portListing = NULL; data->portListing = NULL;
data->portListingLength = 0; data->portListingLength = 0;
/* init xmlparser object */ /* init xmlparser object */
parser.xmlstart = buffer; parser.xmlstart = buffer;
parser.xmlsize = bufsize; parser.xmlsize = bufsize;
parser.data = data; parser.data = data;
parser.starteltfunc = NameValueParserStartElt; parser.starteltfunc = NameValueParserStartElt;
parser.endeltfunc = 0; parser.endeltfunc = NameValueParserEndElt;
parser.datafunc = NameValueParserGetData; parser.datafunc = NameValueParserGetData;
parser.attfunc = 0; parser.attfunc = 0;
parsexml(&parser); parsexml(&parser);
} }
void void
@ -83,9 +128,9 @@ ClearNameValueList(struct NameValueParserData * pdata)
pdata->portListing = NULL; pdata->portListing = NULL;
pdata->portListingLength = 0; pdata->portListingLength = 0;
} }
while((nv = pdata->head.lh_first) != NULL) while((nv = pdata->l_head) != NULL)
{ {
LIST_REMOVE(nv, entries); pdata->l_head = nv->l_next;
free(nv); free(nv);
} }
} }
@ -96,9 +141,9 @@ GetValueFromNameValueList(struct NameValueParserData * pdata,
{ {
struct NameValue * nv; struct NameValue * nv;
char * p = NULL; char * p = NULL;
for(nv = pdata->head.lh_first; for(nv = pdata->l_head;
(nv != NULL) && (p == NULL); (nv != NULL) && (p == NULL);
nv = nv->entries.le_next) nv = nv->l_next)
{ {
if(strcmp(nv->name, Name) == 0) if(strcmp(nv->name, Name) == 0)
p = nv->value; p = nv->value;
@ -140,13 +185,13 @@ DisplayNameValueList(char * buffer, int bufsize)
struct NameValueParserData pdata; struct NameValueParserData pdata;
struct NameValue * nv; struct NameValue * nv;
ParseNameValue(buffer, bufsize, &pdata); ParseNameValue(buffer, bufsize, &pdata);
for(nv = pdata.head.lh_first; for(nv = pdata.l_head;
nv != NULL; nv != NULL;
nv = nv->entries.le_next) nv = nv->l_next)
{ {
printf("%s = %s\n", nv->name, nv->value); printf("%s = %s\n", nv->name, nv->value);
} }
ClearNameValueList(&pdata); ClearNameValueList(&pdata);
} }
#endif #endif /* DEBUG */

View File

@ -2566,8 +2566,12 @@ int UPNP_Tools::upnp_init(void *param) {
int upnp_error = 0; int upnp_error = 0;
#ifndef MINIUPNPC_VERSION_PRE1_6 #ifndef MINIUPNPC_VERSION_PRE1_6
#if !defined(MINIUPNPC_API_VERSION) || MINIUPNPC_API_VERSION < 14
devlist = upnpDiscover(upnp_delay, upnp_multicastif, upnp_minissdpdsock, upnp_sameport, upnp_ipv6, &upnp_error); devlist = upnpDiscover(upnp_delay, upnp_multicastif, upnp_minissdpdsock, upnp_sameport, upnp_ipv6, &upnp_error);
#else
// miniupnpc 1.9.20150730
devlist = upnpDiscover(upnp_delay, upnp_multicastif, upnp_minissdpdsock, upnp_sameport, upnp_ipv6, 2, &upnp_error);
#endif
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"UPnP discover returned upnp_error = %d.\n",upnp_error); if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"UPnP discover returned upnp_error = %d.\n",upnp_error);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("UPnP discover returned upnp_error = %d.\n",upnp_error); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("UPnP discover returned upnp_error = %d.\n",upnp_error);