upgrade miniupnp version to 1.9. update autoconf script to detect the API version; update upnp.c's #ifdefs to use the API version.

This commit is contained in:
Jordan Lee 2014-04-27 19:31:10 +00:00
parent 2be080f48e
commit a7137b7bb9
27 changed files with 775 additions and 240 deletions

View File

@ -243,41 +243,47 @@ dnl
dnl look for preinstalled miniupnpc...
dnl
AC_MSG_CHECKING([supported miniupnp library])
upnp_version="none"
ac_save_LIBS="$LIBS"
LIBS="-lminiupnpc"
# See if the OS has its miniupnp 1.5 installed
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <stdlib.h>
#include <miniupnpc/miniupnpc.h>
#include <miniupnpc/upnpcommands.h>
]], [[
struct UPNPDev * devlist;
struct UPNPUrls urls;
struct IGDdatas data;
char lanaddr[16];
char portStr[8];
char intPort[8];
char intClient[16];
upnpDiscover( 2000, NULL, NULL, 0 );
UPNP_GetValidIGD( devlist, &urls, &data, lanaddr, sizeof( lanaddr ) );
UPNP_GetSpecificPortMappingEntry( urls.controlURL, data.first.servicetype,
portStr, "TCP", intClient, intPort );
]])],[
AC_DEFINE(HAVE_MINIUPNP_15, 1, [Define to 1 if you have miniupnpc version 1.5])
upnp_version="1.5"],[])
AC_MSG_CHECKING([system miniupnpc library])
# See if the OS has its miniupnp 1.6 installed
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
dnl See if ANY version of miniupnpc is installed
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([#include <miniupnpc/miniupnpc.h>],
[struct UPNPDev dev;])],
[upnp_version="unknown"],
[upnp_version="none"]
)
dnl Let's hope it's 1.7 or higher, since it provides
dnl MINIUPNPC_API_VERSION and we won't have to figure
dnl it out on our own
if test "x$upnp_version" = "xunknown" ; then
AC_RUN_IFELSE(
[AC_LANG_PROGRAM(
[#include <stdlib.h>
#include <miniupnpc/miniupnpc.h>],
[#ifdef MINIUPNPC_API_VERSION
return EXIT_SUCCESS;
#else
return EXIT_FAILURE;
#endif]
)],
[upnp_version=">= 1.7"]
)
fi
dnl Or maybe it's miniupnp 1.6
if test "x$upnp_version" = "xunknown" ; then
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <stdlib.h>
#include <errno.h>
#include <miniupnpc/miniupnpc.h>
#include <miniupnpc/upnpcommands.h>
]], [[
]], [[
struct UPNPDev * devlist;
struct UPNPUrls urls;
struct IGDdatas data;
struct UPNPUrls urls;
struct IGDdatas data;
char lanaddr[16];
char portStr[8];
char intPort[8];
@ -286,9 +292,33 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
UPNP_GetValidIGD( devlist, &urls, &data, lanaddr, sizeof( lanaddr ) );
UPNP_GetSpecificPortMappingEntry( urls.controlURL, data.first.servicetype,
portStr, "TCP", intClient, intPort, NULL, NULL, NULL );
]])],[
AC_DEFINE(HAVE_MINIUPNP_16, 1, [Define to 1 if you have miniupnpc version 1.6])
upnp_version="1.6"],[])
]])],[
AC_DEFINE(MINIUPNPC_API_VERSION, 8, [miniupnpc 1.6's API version is 8])
upnp_version="1.6"])
fi
dnl Or maybe it's miniupnp 1.5
if test "x$upnp_version" = "xunknown" ; then
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <stdlib.h>
#include <miniupnpc/miniupnpc.h>
#include <miniupnpc/upnpcommands.h>
]], [[
struct UPNPDev * devlist;
struct UPNPUrls urls;
struct IGDdatas data;
char lanaddr[16];
char portStr[8];
char intPort[8];
char intClient[16];
upnpDiscover( 2000, NULL, NULL, 0 );
UPNP_GetValidIGD( devlist, &urls, &data, lanaddr, sizeof( lanaddr ) );
UPNP_GetSpecificPortMappingEntry( urls.controlURL, data.first.servicetype,
portStr, "TCP", intClient, intPort );
]])],[
AC_DEFINE(MINIUPNPC_API_VERSION, 5, [miniupnpc 1.5's API version is 5])
upnp_version="1.5"])
fi
# ... and the results of our tests
LIBS="$ac_save_LIBS"
@ -298,8 +328,6 @@ if test "x$upnp_version" = "xnone" ; then
LIBUPNP_CFLAGS="-I\$(top_srcdir)/third-party/"
LIBUPNP_LIBS="\$(top_builddir)/third-party/miniupnp/libminiupnp.a"
LIBUPNP_LIBS_QT="\$\${TRANSMISSION_TOP}/third-party/miniupnp/libminiupnp.a"
dnl because this is the version that we bundle...
AC_DEFINE(HAVE_MINIUPNP_16, 1, [Define to 1 if you have miniupnpc version 1.6])
else
AC_DEFINE([SYSTEM_MINIUPNP])
LIBUPNP_CFLAGS=""

View File

@ -18,10 +18,6 @@
#include <miniupnp/upnpcommands.h>
#endif
#ifdef SYS_DARWIN
#define HAVE_MINIUPNP_16 1
#endif
#include "transmission.h"
#include "log.h"
#include "port-forwarding.h"
@ -87,20 +83,22 @@ tr_upnpClose (tr_upnp * handle)
static struct UPNPDev *
tr_upnpDiscover (int msec)
{
struct UPNPDev * ret = NULL;
struct UPNPDev * ret;
bool have_err;
#if defined (HAVE_MINIUPNP_16)
int err = UPNPDISCOVER_SUCCESS;
ret = upnpDiscover (msec, NULL, NULL, 0, 0, &err);
if (err != UPNPDISCOVER_SUCCESS)
#elif defined (HAVE_MINIUPNP_15)
ret = upnpDiscover (msec, NULL, NULL, 0);
if (ret == NULL)
#if (MINIUPNPC_API_VERSION >= 8) /* adds ipv6 and error args */
int err = UPNPDISCOVER_SUCCESS;
ret = upnpDiscover (msec, NULL, NULL, 0, 0, &err);
have_err = err != UPNPDISCOVER_SUCCESS;
#else
ret = upnpDiscover (msec, NULL, NULL, 0);
have_err = ret == NULL;
#endif
tr_logAddNamedDbg (getKey (), "upnpDiscover failed (errno %d - %s)", errno, tr_strerror (errno));
if (have_err)
tr_logAddNamedDbg (getKey (), "upnpDiscover failed (errno %d - %s)", errno, tr_strerror (errno));
return ret;
return ret;
}
static int
@ -114,14 +112,42 @@ tr_upnpGetSpecificPortMappingEntry (tr_upnp * handle, const char * proto)
*intClient = '\0';
*intPort = '\0';
tr_snprintf (portStr, sizeof (portStr), "%d", (int)handle->port);
tr_snprintf (portStr, sizeof(portStr), "%d", (int)handle->port);
#if (MINIUPNPC_API_VERSION >= 10) /* adds remoteHost arg */
err = UPNP_GetSpecificPortMappingEntry (handle->urls.controlURL,
handle->data.first.servicetype,
portStr,
proto,
NULL /*remoteHost*/,
intClient,
intPort,
NULL /*desc*/,
NULL /*enabled*/,
NULL /*duration*/);
#elif (MINIUPNPC_API_VERSION >= 8) /* adds desc, enabled and leaseDuration args */
err = UPNP_GetSpecificPortMappingEntry (handle->urls.controlURL,
handle->data.first.servicetype,
portStr,
proto,
intClient,
intPort,
NULL /*desc*/,
NULL /*enabled*/,
NULL /*duration*/);
#if defined (HAVE_MINIUPNP_16)
err = UPNP_GetSpecificPortMappingEntry (handle->urls.controlURL, handle->data.first.servicetype, portStr, proto, intClient, intPort, NULL, NULL, NULL);
#elif defined (HAVE_MINIUPNP_15)
err = UPNP_GetSpecificPortMappingEntry (handle->urls.controlURL, handle->data.first.servicetype, portStr, proto, intClient, intPort);
#else
err = UPNPCOMMAND_UNKNOWN_ERROR;
err = UPNP_GetSpecificPortMappingEntry (handle->urls.controlURL,
handle->data.first.servicetype,
portStr,
proto,
intClient,
intPort);
#endif
return err;
@ -137,12 +163,10 @@ tr_upnpAddPortMapping (const tr_upnp * handle, const char * proto, tr_port port,
tr_snprintf (portStr, sizeof (portStr), "%d", (int)port);
#if defined (HAVE_MINIUPNP_16)
#if (MINIUPNPC_API_VERSION >= 8)
err = UPNP_AddPortMapping (handle->urls.controlURL, handle->data.first.servicetype, portStr, portStr, handle->lanaddr, desc, proto, NULL, NULL);
#elif defined (HAVE_MINIUPNP_15)
err = UPNP_AddPortMapping (handle->urls.controlURL, handle->data.first.servicetype, portStr, portStr, handle->lanaddr, desc, proto, NULL);
#else
err = UPNPCOMMAND_UNKNOWN_ERROR;
err = UPNP_AddPortMapping (handle->urls.controlURL, handle->data.first.servicetype, portStr, portStr, handle->lanaddr, desc, proto, NULL);
#endif
if (err)

View File

@ -1,6 +1,89 @@
$Id: Changelog.txt,v 1.169 2012/05/24 18:08:49 nanard Exp $
$Id: Changelog.txt,v 1.193 2014/02/05 17:26:45 nanard Exp $
miniUPnP client Changelog.
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:
Python 3 support (thanks to Christopher Foo)
2012/08/11:
Fix a memory link in UPNP_GetValidIGD()
Try to handle scope id in link local IPv6 URL under MS Windows
2012/07/20:
Disable HAS_IP_MREQN on DragonFly BSD
2012/06/28:
GetUPNPUrls() now inserts scope into link-local IPv6 addresses
2012/06/23:
More error return checks in upnpc.c
#define MINIUPNPC_GET_SRC_ADDR enables receivedata() to get scope_id
parseURL() now parses IPv6 addresses scope
new parameter for miniwget() : IPv6 address scope
increment API_VERSION to 9
2012/06/20:
fixed CMakeLists.txt
2012/05/29
Improvements in testminiwget.sh
VERSION 1.7 : released 2012/05/24
2012/05/01:

127
third-party/miniupnp/apiversions.txt vendored Normal file
View File

@ -0,0 +1,127 @@
$Id: apiversions.txt,v 1.3 2014/01/31 13:14:32 nanard Exp $
Differences in API between miniUPnPc versions
====================== miniUPnPc version 1.9 ======================
API version 10
upnpcommands.h:
added argument remoteHost to UPNP_GetSpecificPortMappingEntry()
miniupnpc.h:
updated macros :
#define MINIUPNPC_VERSION "1.9"
#define MINIUPNPC_API_VERSION 10
====================== miniUPnPc version 1.8 ======================
API version 9
miniupnpc.h:
updated macros :
#define MINIUPNPC_VERSION "1.8"
#define MINIUPNPC_API_VERSION 9
added "unsigned int scope_id;" to struct UPNPDev
added scope_id argument to GetUPNPUrls()
====================== miniUPnPc version 1.7 ======================
API version 8
miniupnpc.h :
add new macros :
#define MINIUPNPC_VERSION "1.7"
#define MINIUPNPC_API_VERSION 8
add rootdescURL to struct UPNPUrls
====================== miniUPnPc version 1.6 ======================
API version 8
Adding support for IPv6.
igd_desc_parse.h :
struct IGDdatas_service :
add char presentationurl[MINIUPNPC_URL_MAXSIZE];
struct IGDdatas :
add struct IGDdatas_service IPv6FC;
miniupnpc.h :
new macros :
#define UPNPDISCOVER_SUCCESS (0)
#define UPNPDISCOVER_UNKNOWN_ERROR (-1)
#define UPNPDISCOVER_SOCKET_ERROR (-101)
#define UPNPDISCOVER_MEMORY_ERROR (-102)
simpleUPnPcommand() prototype changed (but is normaly not used by API users)
add arguments ipv6 and error to upnpDiscover() :
struct UPNPDev *
upnpDiscover(int delay, const char * multicastif,
const char * minissdpdsock, int sameport,
int ipv6,
int * error);
add controlURL_6FC member to struct UPNPUrls :
struct UPNPUrls {
char * controlURL;
char * ipcondescURL;
char * controlURL_CIF;
char * controlURL_6FC;
};
upnpcommands.h :
add leaseDuration argument to UPNP_AddPortMapping()
add desc, enabled and leaseDuration arguments to UPNP_GetSpecificPortMappingEntry()
add UPNP_GetListOfPortMappings() function (IGDv2)
add IGDv2 IPv6 related functions :
UPNP_GetFirewallStatus()
UPNP_GetOutboundPinholeTimeout()
UPNP_AddPinhole()
UPNP_UpdatePinhole()
UPNP_DeletePinhole()
UPNP_CheckPinholeWorking()
UPNP_GetPinholePackets()
====================== miniUPnPc version 1.5 ======================
API version 5
new function :
int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *);
new macro in upnpcommands.h :
#define UPNPCOMMAND_HTTP_ERROR
====================== miniUPnPc version 1.4 ======================
Same API as version 1.3
====================== miniUPnPc version 1.3 ======================
API version 4
Use UNSIGNED_INTEGER type for
UPNP_GetTotalBytesSent(), UPNP_GetTotalBytesReceived(),
UPNP_GetTotalPacketsSent(), UPNP_GetTotalPacketsReceived()
Add remoteHost argument to UPNP_AddPortMapping() and UPNP_DeletePortMapping()
====================== miniUPnPc version 1.2 ======================
API version 3
added sameport argument to upnpDiscover()
struct UPNPDev *
upnpDiscover(int delay, const char * multicastif,
const char * minissdpdsock, int sameport);
====================== miniUPnPc Version 1.1 ======================
Same API as 1.0
====================== miniUPnPc Version 1.0 ======================
API version 2
struct UPNPDev {
struct UPNPDev * pNext;
char * descURL;
char * st;
char buffer[2];
};
struct UPNPDev * upnpDiscover(int delay, const char * multicastif,
const char * minissdpdsock);

View File

@ -1,11 +1,11 @@
/* $Id: codelength.h,v 1.3 2011/07/30 13:10:05 nanard Exp $ */
/* $Id: codelength.h,v 1.4 2012/09/27 15:40:29 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas BERNARD
* copyright (c) 2005-2011 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENCE file. */
#ifndef __CODELENGTH_H__
#define __CODELENGTH_H__
#ifndef CODELENGTH_H_INCLUDED
#define CODELENGTH_H_INCLUDED
/* Encode length by using 7bit per Byte :
* Most significant bit of each byte specifies that the

View File

@ -1,7 +1,7 @@
/* $Id: connecthostport.c,v 1.7 2012/03/05 19:42:46 nanard Exp $ */
/* $Id: connecthostport.c,v 1.13 2014/03/31 12:36:36 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2010-2012 Thomas Bernard
* Copyright (c) 2010-2014 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
@ -24,15 +24,18 @@
#else /* #ifdef _WIN32 */
#include <unistd.h>
#include <sys/param.h>
#include <sys/select.h>
#include <errno.h>
#define closesocket close
#include <netdb.h>
#include <netinet/in.h>
/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions
* during the connect() call */
#define MINIUPNPC_IGNORE_EINTR
#ifndef USE_GETHOSTBYNAME
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#endif /* #ifndef USE_GETHOSTBYNAME */
#endif /* #else _WIN32 */
@ -49,10 +52,15 @@
#include "connecthostport.h"
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
/* connecthostport()
* return a socket connected (TCP) to the host and port
* or -1 in case of error */
int connecthostport(const char * host, unsigned short port)
int connecthostport(const char * host, unsigned short port,
unsigned int scope_id)
{
int s, n;
#ifdef USE_GETHOSTBYNAME
@ -102,7 +110,10 @@ int connecthostport(const char * host, unsigned short port)
dest.sin_port = htons(port);
n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in));
#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;
fd_set wset;
@ -145,10 +156,12 @@ int connecthostport(const char * host, unsigned short port)
if(host[0] == '[')
{
/* literal ip v6 address */
int i;
for(i = 0; host[i+1] && (host[i+1] != ']') && i < MAXHOSTNAMELEN; i++)
int i, j;
for(i = 0, j = 1; host[j] && (host[j] != ']') && i < MAXHOSTNAMELEN; i++, j++)
{
tmp_host[i] = host[i+1];
tmp_host[i] = host[j];
if(0 == memcmp(host+j, "%25", 3)) /* %25 is just url encoding for '%' */
j+=2; /* skip "25" */
}
tmp_host[i] = '\0';
}
@ -173,6 +186,10 @@ int connecthostport(const char * host, unsigned short port)
s = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if(s < 0)
continue;
if(p->ai_addr->sa_family == AF_INET6 && scope_id > 0) {
struct sockaddr_in6 * addr6 = (struct sockaddr_in6 *)p->ai_addr;
addr6->sin6_scope_id = scope_id;
}
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
/* setting a 3 seconds timeout for the connect() call */
timeout.tv_sec = 3;
@ -190,7 +207,10 @@ int connecthostport(const char * host, unsigned short port)
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
n = connect(s, p->ai_addr, p->ai_addrlen);
#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;
fd_set wset;

View File

@ -1,17 +1,18 @@
/* $Id: connecthostport.h,v 1.1 2010/04/04 23:21:03 nanard Exp $ */
/* $Id: connecthostport.h,v 1.3 2012/09/27 15:42:10 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/
* Author: Thomas Bernard
* Copyright (c) 2010 Thomas Bernard
* Copyright (c) 2010-2012 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef __CONNECTHOSTPORT_H__
#define __CONNECTHOSTPORT_H__
#ifndef CONNECTHOSTPORT_H_INCLUDED
#define CONNECTHOSTPORT_H_INCLUDED
/* connecthostport()
* return a socket connected (TCP) to the host and port
* or -1 in case of error */
int connecthostport(const char * host, unsigned short port);
int connecthostport(const char * host, unsigned short port,
unsigned int scope_id);
#endif

View File

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

View File

@ -1,4 +1,4 @@
/* $Id: igd_desc_parse.h,v 1.10 2011/04/11 09:19:24 nanard Exp $ */
/* $Id: igd_desc_parse.h,v 1.11 2012/10/16 16:49:02 nanard Exp $ */
/* Project : miniupnp
* http://miniupnp.free.fr/
* Author : Thomas Bernard
@ -6,8 +6,8 @@
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
#ifndef __IGD_DESC_PARSE_H__
#define __IGD_DESC_PARSE_H__
#ifndef IGD_DESC_PARSE_H_INCLUDED
#define IGD_DESC_PARSE_H_INCLUDED
/* Structure to store the result of the parsing of UPnP
* descriptions of Internet Gateway Devices */

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
* Author : Thomas Bernard
* Copyright (c) 2005 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
#ifndef __MINISOAP_H__
#define __MINISOAP_H__
#ifndef MINISOAP_H_INCLUDED
#define MINISOAP_H_INCLUDED
/*int httpWrite(int, const char *, int, const char *);*/
int soapPostSubmit(int, const char *, const char *, unsigned short,

View File

@ -1,12 +1,12 @@
/* $Id: minissdpc.h,v 1.1 2007/08/31 15:15:33 nanard Exp $ */
/* $Id: minissdpc.h,v 1.2 2012/09/27 15:42:10 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author: Thomas Bernard
* Copyright (c) 2005-2007 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef __MINISSDPC_H__
#define __MINISSDPC_H__
#ifndef MINISSDPC_H_INCLUDED
#define MINISSDPC_H_INCLUDED
struct UPNPDev *
getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath);

View File

@ -1,8 +1,8 @@
/* $Id: miniupnpc.c,v 1.106 2012/06/11 16:08:17 nanard Exp $ */
/* $Id: miniupnpc.c,v 1.117 2014/01/31 14:19:13 nanard Exp $ */
/* Project : miniupnp
* Web : http://miniupnp.free.fr/
* Author : Thomas BERNARD
* copyright (c) 2005-2012 Thomas Bernard
* copyright (c) 2005-2014 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENSE file. */
#define __EXTENSIONS__ 1
@ -17,7 +17,7 @@
#endif
#endif
#if !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(MACOSX) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__sun)
#if !defined(__DragonFly__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(MACOSX) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__sun)
#define HAS_IP_MREQN
#endif
@ -31,6 +31,7 @@
#include <io.h>
#include <iphlpapi.h>
#define snprintf _snprintf
#define strdup _strdup
#ifndef strncasecmp
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
#define strncasecmp _memicmp
@ -70,6 +71,17 @@
#define TIMEVAL struct timeval
#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
#include "miniupnpc.h"
#include "minissdpc.h"
#include "miniwget.h"
@ -85,6 +97,10 @@
#define PRINT_SOCKET_ERROR(x) perror(x)
#endif
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
#define SOAPPREFIX "s"
#define SERVICEPREFIX "u"
#define SERVICEPREFIX2 'u'
@ -112,9 +128,9 @@ LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * d
* return values :
* pointer - OK
* NULL - error */
char * simpleUPnPcommand2(int s, const char * url, const char * service,
const char * action, struct UPNParg * args,
int * bufsize, const char * httpversion)
static char * simpleUPnPcommand2(int s, const char * url, const char * service,
const char * action, struct UPNParg * args,
int * bufsize, const char * httpversion)
{
char hostname[MAXHOSTNAMELEN+1];
unsigned short port = 0;
@ -189,12 +205,11 @@ char * simpleUPnPcommand2(int s, const char * url, const char * service,
strncpy(p, "></" SOAPPREFIX ":Body></" SOAPPREFIX ":Envelope>\r\n",
soapbody + sizeof(soapbody) - p);
}
if(!parseURL(url, hostname, &port, &path)) return NULL;
if(s<0)
{
s = connecthostport(hostname, port);
if(s < 0)
{
if(!parseURL(url, hostname, &port, &path, NULL)) return NULL;
if(s < 0) {
s = connecthostport(hostname, port, 0);
if(s < 0) {
/* failed to connect */
return NULL;
}
}
@ -230,8 +245,9 @@ char * simpleUPnPcommand(int s, const char * url, const char * service,
{
char * buf;
#if 1
buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.1");
/*
#else
buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.0");
if (!buf || *bufsize == 0)
{
@ -240,7 +256,7 @@ char * simpleUPnPcommand(int s, const char * url, const char * service,
#endif
buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.1");
}
*/
#endif
return buf;
}
@ -327,6 +343,7 @@ upnpDiscover(int delay, const char * multicastif,
{
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"
@ -528,7 +545,8 @@ upnpDiscover(int delay, const char * multicastif,
}
}
/* Avant d'envoyer le paquet on bind pour recevoir la reponse */
/* 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)
{
@ -543,6 +561,10 @@ upnpDiscover(int delay, const char * multicastif,
*error = UPNPDISCOVER_SUCCESS;
/* Calculating maximum response time in seconds */
mx = ((unsigned int)delay) / 1000u;
if(mx == 0) {
mx = 1;
delay = 1000;
}
/* receiving SSDP response packet */
for(n = 0; deviceList[deviceIndex]; deviceIndex++)
{
@ -625,7 +647,7 @@ upnpDiscover(int delay, const char * multicastif,
#endif /* #ifdef NO_GETADDRINFO */
}
/* Waiting for SSDP REPLY packet to M-SEARCH */
n = receivedata(sudp, bufr, sizeof(bufr), delay);
n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id);
if (n < 0) {
/* error */
if(error)
@ -685,6 +707,7 @@ upnpDiscover(int delay, const char * multicastif,
tmp->buffer[urlsize] = '\0';
memcpy(tmp->buffer + urlsize + 1, st, stsize);
tmp->buffer[urlsize+1+stsize] = '\0';
tmp->scope_id = scope_id;
devlist = tmp;
}
}
@ -731,15 +754,31 @@ url_cpy_or_cat(char * dst, const char * src, int n)
/* Prepare the Urls for usage...
*/
LIBSPEC void GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data,
const char * descURL)
LIBSPEC void
GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data,
const char * descURL, unsigned int scope_id)
{
char * p;
int n1, n2, n3, n4;
#ifdef IF_NAMESIZE
char ifname[IF_NAMESIZE];
#else
char scope_str[8];
#endif
n1 = strlen(data->urlbase);
if(n1==0)
n1 = strlen(descURL);
if(scope_id != 0) {
#ifdef IF_NAMESIZE
if(if_indextoname(scope_id, ifname)) {
n1 += 3 + strlen(ifname); /* 3 == strlen(%25) */
}
#else
/* under windows, scope is numerical */
snprintf(scope_str, sizeof(scope_str), "%u", scope_id);
#endif
}
n1 += 2; /* 1 byte more for Null terminator, 1 byte for '/' if needed */
n2 = n1; n3 = n1; n4 = n1;
n1 += strlen(data->first.scpdurl);
@ -763,6 +802,24 @@ LIBSPEC void GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data,
strncpy(urls->ipcondescURL, descURL, n1);
p = strchr(urls->ipcondescURL+7, '/');
if(p) p[0] = '\0';
if(scope_id != 0) {
if(0 == memcmp(urls->ipcondescURL, "http://[fe80:", 13)) {
/* this is a linklocal IPv6 address */
p = strchr(urls->ipcondescURL, ']');
if(p) {
/* insert %25<scope> into URL */
#ifdef IF_NAMESIZE
memmove(p + 3 + strlen(ifname), p, strlen(p) + 1);
memcpy(p, "%25", 3);
memcpy(p + 3, ifname, strlen(ifname));
#else
memmove(p + 3 + strlen(scope_str), p, strlen(p) + 1);
memcpy(p, "%25", 3);
memcpy(p + 3, scope_str, strlen(scope_str));
#endif
}
}
}
strncpy(urls->controlURL, urls->ipcondescURL, n2);
strncpy(urls->controlURL_CIF, urls->ipcondescURL, n3);
strncpy(urls->controlURL_6FC, urls->ipcondescURL, n4);
@ -830,7 +887,7 @@ UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data)
* not connected
* 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
* free allocated memory.
*/
@ -843,11 +900,14 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
struct xml_desc {
char * xml;
int size;
int is_igd;
} * desc = NULL;
struct UPNPDev * dev;
int ndev = 0;
int i;
int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */
int n_igd = 0;
char extIpAddr[16];
if(!devlist)
{
#ifdef DEBUG
@ -855,6 +915,7 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
#endif
return 0;
}
/* counting total number of devices in the list */
for(dev = devlist; dev; dev = dev->pNext)
ndev++;
if(ndev > 0)
@ -863,40 +924,58 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
if(!desc)
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(0==strcmp(data->CIF.servicetype,
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"))
{
desc[i].is_igd = 1;
n_igd++;
}
}
}
/* iterate the list to find a device depending on state */
for(state = 1; state <= 3; state++)
{
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);
#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(0==strcmp(data->CIF.servicetype,
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")
|| state >= 3 )
if(desc[i].is_igd || state >= 3 )
{
GetUPNPUrls(urls, data, dev->descURL);
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
printf("UPNPIGD_IsConnected(%s) = %d\n",
urls->controlURL,
UPNPIGD_IsConnected(urls, data));
#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;
FreeUPNPUrls(urls);
if(data->second.servicetype[0] != '\0') {
@ -908,13 +987,14 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
memcpy(&data->tmp, &data->first, sizeof(struct IGDdatas_service));
memcpy(&data->first, &data->second, sizeof(struct IGDdatas_service));
memcpy(&data->second, &data->tmp, sizeof(struct IGDdatas_service));
GetUPNPUrls(urls, data, dev->descURL);
GetUPNPUrls(urls, data, dev->descURL, dev->scope_id);
#ifdef DEBUG
printf("UPNPIGD_IsConnected(%s) = %d\n",
urls->controlURL,
UPNPIGD_IsConnected(urls, data));
#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;
FreeUPNPUrls(urls);
}
@ -925,7 +1005,14 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
}
state = 0;
free_and_return:
free(desc);
if(desc) {
for(i = 0; i < ndev; i++) {
if(desc[i].xml) {
free(desc[i].xml);
}
}
free(desc);
}
return state;
}
@ -943,14 +1030,14 @@ UPNP_GetIGDFromUrl(const char * rootdescurl,
char * descXML;
int descXMLsize = 0;
descXML = miniwget_getaddr(rootdescurl, &descXMLsize,
lanaddr, lanaddrlen);
lanaddr, lanaddrlen, 0);
if(descXML) {
memset(data, 0, sizeof(struct IGDdatas));
memset(urls, 0, sizeof(struct UPNPUrls));
parserootdesc(descXML, descXMLsize, data);
free(descXML);
descXML = NULL;
GetUPNPUrls(urls, data, rootdescurl);
GetUPNPUrls(urls, data, rootdescurl, 0);
return 1;
} else {
return 0;

View File

@ -1,12 +1,12 @@
/* $Id: miniupnpc.h,v 1.25 2011/10/09 16:17:29 nanard Exp $ */
/* $Id: miniupnpc.h,v 1.35 2014/01/31 13:26:34 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/
* Author: Thomas Bernard
* Copyright (c) 2005-2011 Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef __MINIUPNPC_H__
#define __MINIUPNPC_H__
#ifndef MINIUPNPC_H_INCLUDED
#define MINIUPNPC_H_INCLUDED
#include "declspec.h"
#include "igd_desc_parse.h"
@ -18,8 +18,8 @@
#define UPNPDISCOVER_MEMORY_ERROR (-102)
/* versions : */
#define MINIUPNPC_VERSION "1.7"
#define MINIUPNPC_API_VERSION 8
#define MINIUPNPC_VERSION "1.9.20140401"
#define MINIUPNPC_API_VERSION 10
#ifdef __cplusplus
extern "C" {
@ -37,6 +37,7 @@ struct UPNPDev {
struct UPNPDev * pNext;
char * descURL;
char * st;
unsigned int scope_id;
char buffer[2];
};
@ -110,9 +111,12 @@ UPNP_GetIGDFromUrl(const char * rootdescurl,
struct IGDdatas * data,
char * lanaddr, int lanaddrlen);
LIBSPEC void GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, const char *);
LIBSPEC void
GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *,
const char *, unsigned int);
LIBSPEC void FreeUPNPUrls(struct UPNPUrls *);
LIBSPEC void
FreeUPNPUrls(struct UPNPUrls *);
/* return 0 or 1 */
LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *);

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
* Author : Thomas Bernard
* Copyright (c) 2011 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided within this distribution */
#ifndef __MINIUPNPCTYPES_H__
#define __MINIUPNPCTYPES_H__
#ifndef MINIUPNPCTYPES_H_INCLUDED
#define MINIUPNPCTYPES_H_INCLUDED
#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
#define UNSIGNED_INTEGER unsigned long long

View File

@ -1,8 +1,8 @@
/* $Id: miniwget.c,v 1.56 2012/05/01 16:16:08 nanard Exp $ */
/* $Id: miniwget.c,v 1.61 2014/02/05 17:27:48 nanard Exp $ */
/* Project : miniupnp
* Website : http://miniupnp.free.fr/
* 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
* LICENCE file provided in this distribution. */
@ -36,11 +36,9 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netdb.h>
#define closesocket close
/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions
* during the connect() call */
#define MINIUPNPC_IGNORE_EINTR
#endif /* #else _WIN32 */
#if defined(__sun) || defined(sun)
#define MIN(x,y) (((x)<(y))?(x):(y))
@ -51,6 +49,10 @@
#include "connecthostport.h"
#include "receivedata.h"
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
/*
* Read a HTTP response from a socket.
* Process Content-Length and Transfer-encoding headers.
@ -82,7 +84,7 @@ getHTTPResponse(int s, int * size)
chunksize_buf[0] = '\0';
chunksize_buf_index = 0;
while((n = receivedata(s, buf, 2048, 5000)) > 0)
while((n = receivedata(s, buf, 2048, 5000, NULL)) > 0)
{
if(endofheaders == 0)
{
@ -157,7 +159,7 @@ getHTTPResponse(int s, int * size)
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++;
linestart = i;
colon = linestart;
@ -289,7 +291,7 @@ static void *
miniwget3(const char * host,
unsigned short port, const char * path,
int * size, char * addr_str, int addr_str_len,
const char * httpversion)
const char * httpversion, unsigned int scope_id)
{
char buf[2048];
int s;
@ -299,7 +301,7 @@ miniwget3(const char * host,
void * content;
*size = 0;
s = connecthostport(host, port);
s = connecthostport(host, port, scope_id);
if(s < 0)
return NULL;
@ -392,22 +394,27 @@ miniwget3(const char * host,
static void *
miniwget2(const char * host,
unsigned short port, const char * path,
int * size, char * addr_str, int addr_str_len)
int * size, char * addr_str, int addr_str_len,
unsigned int scope_id)
{
char * respbuffer;
respbuffer = miniwget3(host, port, path, size, addr_str, addr_str_len, "1.1");
/*
respbuffer = miniwget3(host, port, path, size, addr_str, addr_str_len, "1.0");
#if 1
respbuffer = miniwget3(host, port, path, size,
addr_str, addr_str_len, "1.1", scope_id);
#else
respbuffer = miniwget3(host, port, path, size,
addr_str, addr_str_len, "1.0", scope_id);
if (*size == 0)
{
#ifdef DEBUG
printf("Retrying with HTTP/1.1\n");
#endif
free(respbuffer);
respbuffer = miniwget3(host, port, path, size, addr_str, addr_str_len, "1.1");
respbuffer = miniwget3(host, port, path, size,
addr_str, addr_str_len, "1.1", scope_id);
}
*/
#endif
return respbuffer;
}
@ -424,7 +431,10 @@ miniwget2(const char * host,
* Return values :
* 0 - Failure
* 1 - Success */
int parseURL(const char * url, char * hostname, unsigned short * port, char * * path)
int
parseURL(const char * url,
char * hostname, unsigned short * port,
char * * path, unsigned int * scope_id)
{
char * p1, *p2, *p3;
if(!url)
@ -440,7 +450,43 @@ int parseURL(const char * url, char * hostname, unsigned short * port, char * *
if(*p1 == '[')
{
/* IP v6 : http://[2a00:1450:8002::6a]/path/abc */
char * scope;
scope = strchr(p1, '%');
p2 = strchr(p1, ']');
if(p2 && scope && scope < p2 && scope_id) {
/* parse scope */
#ifdef IF_NAMESIZE
char tmp[IF_NAMESIZE];
int l;
scope++;
/* "%25" is just '%' in URL encoding */
if(scope[0] == '2' && scope[1] == '5')
scope += 2; /* skip "25" */
l = p2 - scope;
if(l >= IF_NAMESIZE)
l = IF_NAMESIZE - 1;
memcpy(tmp, scope, l);
tmp[l] = '\0';
*scope_id = if_nametoindex(tmp);
if(*scope_id == 0) {
*scope_id = (unsigned int)strtoul(tmp, NULL, 10);
}
#else
/* under windows, scope is numerical */
char tmp[8];
int l;
scope++;
/* "%25" is just '%' in URL encoding */
if(scope[0] == '2' && scope[1] == '5')
scope += 2; /* skip "25" */
l = p2 - scope;
if(l >= sizeof(tmp))
l = sizeof(tmp) - 1;
memcpy(tmp, scope, l);
tmp[l] = '\0';
*scope_id = (unsigned int)strtoul(tmp, NULL, 10);
#endif
}
p3 = strchr(p1, '/');
if(p2 && p3)
{
@ -490,22 +536,26 @@ int parseURL(const char * url, char * hostname, unsigned short * port, char * *
return 1;
}
void * miniwget(const char * url, int * size)
void *
miniwget(const char * url, int * size, unsigned int scope_id)
{
unsigned short port;
char * path;
/* protocol://host:port/chemin */
char hostname[MAXHOSTNAMELEN+1];
*size = 0;
if(!parseURL(url, hostname, &port, &path))
if(!parseURL(url, hostname, &port, &path, &scope_id))
return NULL;
#ifdef DEBUG
printf("parsed url : hostname='%s' port=%hu path='%s'\n", hostname, port, path);
printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
hostname, port, path, scope_id);
#endif
return miniwget2(hostname, port, path, size, 0, 0);
return miniwget2(hostname, port, path, size, 0, 0, scope_id);
}
void * miniwget_getaddr(const char * url, int * size, char * addr, int addrlen)
void *
miniwget_getaddr(const char * url, int * size,
char * addr, int addrlen, unsigned int scope_id)
{
unsigned short port;
char * path;
@ -514,11 +564,12 @@ void * miniwget_getaddr(const char * url, int * size, char * addr, int addrlen)
*size = 0;
if(addr)
addr[0] = '\0';
if(!parseURL(url, hostname, &port, &path))
if(!parseURL(url, hostname, &port, &path, &scope_id))
return NULL;
#ifdef DEBUG
printf("parsed url : hostname='%s' port=%hu path='%s'\n", hostname, port, path);
printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
hostname, port, path, scope_id);
#endif
return miniwget2(hostname, port, path, size, addr, addrlen);
return miniwget2(hostname, port, path, size, addr, addrlen, scope_id);
}

View File

@ -1,12 +1,12 @@
/* $Id: miniwget.h,v 1.6 2010/12/09 16:11:33 nanard Exp $ */
/* $Id: miniwget.h,v 1.8 2012/09/27 15:42:10 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005 Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
#ifndef __MINIWGET_H__
#define __MINIWGET_H__
#ifndef MINIWGET_H_INCLUDED
#define MINIWGET_H_INCLUDED
#include "declspec.h"
@ -16,11 +16,11 @@ extern "C" {
LIBSPEC void * getHTTPResponse(int s, int * size);
LIBSPEC void * miniwget(const char *, int *);
LIBSPEC void * miniwget(const char *, int *, unsigned int);
LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int);
LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int, unsigned int);
int parseURL(const char *, char *, unsigned short *, char * *);
int parseURL(const char *, char *, unsigned short *, char * *, unsigned int *);
#ifdef __cplusplus
}

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 ! */
/* Project : miniupnp
* webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author : Thomas Bernard
Copyright (c) 2005-2011, Thomas BERNARD
Copyright (c) 2005-2014, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -113,7 +113,20 @@ static void parseelt(struct xmlparser * p)
const char * elementname;
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;
while( !IS_WHITE_SPACE(*p->xml)

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
*
* Project : miniupnp
@ -8,8 +8,8 @@
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
#ifndef __MINIXML_H__
#define __MINIXML_H__
#ifndef MINIXML_H_INCLUDED
#define MINIXML_H_INCLUDED
#define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n'))
/* if a callback function pointer is set to NULL,

View File

@ -1,4 +1,4 @@
/* $Id: portlistingparse.c,v 1.5 2012/03/05 19:42:47 nanard Exp $ */
/* $Id: portlistingparse.c,v 1.6 2012/05/29 10:26:51 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2011 Thomas Bernard
@ -71,6 +71,8 @@ static void
endelt(void * d, const char * name, int l)
{
struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;
(void)name;
(void)l;
pdata->curelt = PortMappingEltNone;
}

View File

@ -1,11 +1,11 @@
/* $Id: portlistingparse.h,v 1.6 2012/03/05 19:42:47 nanard Exp $ */
/* $Id: portlistingparse.h,v 1.7 2012/09/27 15:42:10 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2011-2012 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#ifndef __PORTLISTINGPARSE_H__
#define __PORTLISTINGPARSE_H__
#ifndef PORTLISTINGPARSE_H_INCLUDED
#define PORTLISTINGPARSE_H_INCLUDED
#include "declspec.h"
/* for the definition of UNSIGNED_INTEGER */

View File

@ -1,4 +1,4 @@
/* $Id: receivedata.c,v 1.3 2012/03/05 19:42:47 nanard Exp $ */
/* $Id: receivedata.c,v 1.5 2013/10/07 09:48:36 nanard Exp $ */
/* Project : miniupnp
* Website : http://miniupnp.free.fr/
* Author : Thomas Bernard
@ -18,6 +18,7 @@
#include <sys/select.h>
#endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */
#include <sys/socket.h>
#include <netinet/in.h>
#if !defined(__amigaos__) && !defined(__amigaos4__)
#include <poll.h>
#endif
@ -34,8 +35,19 @@
#include "receivedata.h"
int
receivedata(int socket, char * data, int length, int timeout)
receivedata(int socket,
char * data, int length,
int timeout, unsigned int * scope_id)
{
#ifdef MINIUPNPC_GET_SRC_ADDR
#ifdef DEBUG
/* to shut up valgrind about uninit value */
struct sockaddr_storage src_addr = {0};
#else
struct sockaddr_storage src_addr;
#endif
socklen_t src_addr_len = sizeof(src_addr);
#endif
int n;
#if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__)
/* using poll */
@ -72,10 +84,25 @@ receivedata(int socket, char * data, int length, int timeout)
return 0;
}
#endif
#ifdef MINIUPNPC_GET_SRC_ADDR
n = recvfrom(socket, data, length, 0,
(struct sockaddr *)&src_addr, &src_addr_len);
#else
n = recv(socket, data, length, 0);
#endif
if(n<0) {
PRINT_SOCKET_ERROR("recv");
}
#ifdef MINIUPNPC_GET_SRC_ADDR
if (src_addr.ss_family == AF_INET6) {
const struct sockaddr_in6 * src_addr6 = (struct sockaddr_in6 *)&src_addr;
#ifdef DEBUG
printf("scope_id=%u\n", src_addr6->sin6_scope_id);
#endif
if(scope_id)
*scope_id = src_addr6->sin6_scope_id;
}
#endif
return n;
}

View File

@ -1,17 +1,19 @@
/* $Id: receivedata.h,v 1.2 2012/03/05 19:42:47 nanard Exp $ */
/* $Id: receivedata.h,v 1.4 2012/09/27 15:42:10 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author: Thomas Bernard
* Copyright (c) 2011 Thomas Bernard
* Copyright (c) 2011-2012 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef __RECEIVEDATA_H__
#define __RECEIVEDATA_H__
#ifndef RECEIVEDATA_H_INCLUDED
#define RECEIVEDATA_H_INCLUDED
/* Reads data from the specified socket.
* Returns the number of bytes read if successful, zero if no bytes were
* read or if we timed out. Returns negative if there was an error. */
int receivedata(int socket, char * data, int length, int timeout);
int receivedata(int socket,
char * data, int length,
int timeout, unsigned int * scope_id);
#endif

View File

@ -1,52 +1,53 @@
#! /bin/sh
# $Id: updateminiupnpcstrings.sh,v 1.4 2009/07/29 08:34:01 nanard Exp $
# $Id: updateminiupnpcstrings.sh,v 1.7 2011/01/04 11:41:53 nanard Exp $
# project miniupnp : http://miniupnp.free.fr/
# (c) 2009 Thomas Bernard
VERSION_FILE=$1
TEMPLATE_FILE=$2
FILE=$3
TMPFILE=$3.tmp
FILE=miniupnpcstrings.h
TMPFILE=miniupnpcstrings.h.tmp
TEMPLATE_FILE=${FILE}.in
# detecting the OS name and version
OS_NAME=`uname -s`
OS_VERSION=`uname -r`
if [ -f /etc/debian_version ]; then
OS_NAME=Debian
OS_VERSION=`cat /etc/debian_version`
OS_NAME=Debian
OS_VERSION=`cat /etc/debian_version`
fi
# use lsb_release (Linux Standard Base) when available
LSB_RELEASE=`which lsb_release`
if [ 0 -eq $? -a -x "${LSB_RELEASE}" ]; then
OS_NAME=`${LSB_RELEASE} -i -s`
OS_VERSION=`${LSB_RELEASE} -r -s`
case $OS_NAME in
Debian)
#OS_VERSION=`${LSB_RELEASE} -c -s`
;;
Ubuntu)
#OS_VERSION=`${LSB_RELEASE} -c -s`
;;
esac
OS_NAME=`${LSB_RELEASE} -i -s`
OS_VERSION=`${LSB_RELEASE} -r -s`
case $OS_NAME in
Debian)
#OS_VERSION=`${LSB_RELEASE} -c -s`
;;
Ubuntu)
#OS_VERSION=`${LSB_RELEASE} -c -s`
;;
esac
fi
# on AmigaOS 3, uname -r returns "unknown", so we use uname -v
if [ "$OS_NAME" = "AmigaOS" ]; then
if [ "$OS_VERSION" = "unknown" ]; then
OS_VERSION=`uname -v`
fi
if [ "$OS_VERSION" = "unknown" ]; then
OS_VERSION=`uname -v`
fi
fi
echo "Detected OS [$OS_NAME] version [$OS_VERSION]"
MINIUPNPC_VERSION=`cat "$VERSION_FILE"`
MINIUPNPC_VERSION=`cat VERSION`
echo "MiniUPnPc version [${MINIUPNPC_VERSION}]"
EXPR="s|OS_STRING \".*\"|OS_STRING \"${OS_NAME}/${OS_VERSION}\"|"
#echo $EXPR
test -f ${FILE}.in
echo "setting OS_STRING macro value to ${OS_NAME}/${OS_VERSION} in $FILE."
sed -e "$EXPR" < "$TEMPLATE_FILE" > "$TMPFILE"
sed -e "$EXPR" < $TEMPLATE_FILE > $TMPFILE
EXPR="s|MINIUPNPC_VERSION_STRING \".*\"|MINIUPNPC_VERSION_STRING \"${MINIUPNPC_VERSION}\"|"
echo "setting MINIUPNPC_VERSION_STRING macro value to ${MINIUPNPC_VERSION} in $FILE."
sed -e "$EXPR" < "$TMPFILE" > "$FILE"
rm "$TMPFILE"
sed -e "$EXPR" < $TMPFILE > $FILE
rm $TMPFILE

View File

@ -1,7 +1,7 @@
/* $Id: upnpcommands.c,v 1.39 2012/04/09 12:49:27 nanard Exp $ */
/* $Id: upnpcommands.c,v 1.42 2014/01/31 13:18:25 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005-2011 Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
@ -578,7 +578,8 @@ LIBSPEC int
UPNP_GetSpecificPortMappingEntry(const char * controlURL,
const char * servicetype,
const char * extPort,
const char * proto,
const char * proto,
const char * remoteHost,
char * intClient,
char * intPort,
char * desc,
@ -597,7 +598,7 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
GetPortMappingArgs = calloc(4, sizeof(struct UPNParg));
GetPortMappingArgs[0].elt = "NewRemoteHost";
/* TODO : add remote host ? */
GetPortMappingArgs[0].val = remoteHost;
GetPortMappingArgs[1].elt = "NewExternalPort";
GetPortMappingArgs[1].val = extPort;
GetPortMappingArgs[2].elt = "NewProtocol";
@ -759,7 +760,7 @@ UPNP_GetFirewallStatus(const char * controlURL,
char * fe, *ipa, *p;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
if(!firewallEnabled && !inboundPinholeAllowed)
if(!firewallEnabled || !inboundPinholeAllowed)
return UPNPCOMMAND_INVALID_ARGS;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,

View File

@ -1,11 +1,11 @@
/* $Id: upnpcommands.h,v 1.24 2012/03/05 19:42:47 nanard Exp $ */
/* $Id: upnpcommands.h,v 1.27 2014/02/17 15:38:26 nanard Exp $ */
/* Miniupnp project : http://miniupnp.free.fr/
* Author : Thomas Bernard
* Copyright (c) 2005-2011 Thomas Bernard
* Copyright (c) 2005-2014 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided within this distribution */
#ifndef __UPNPCOMMANDS_H__
#define __UPNPCOMMANDS_H__
#ifndef UPNPCOMMANDS_H_INCLUDED
#define UPNPCOMMANDS_H_INCLUDED
#include "upnpreplyparse.h"
#include "portlistingparse.h"
@ -100,6 +100,8 @@ UPNP_GetLinkLayerMaxBitRates(const char* controlURL,
* 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
@ -112,7 +114,13 @@ UPNP_GetLinkLayerMaxBitRates(const char* controlURL,
* 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard
* and cannot be a specific IP address or DNS name
* 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and
* cannot be a specific port value */
* cannot be a specific port value
* 728 NoPortMapsAvailable - There are not enough free ports available to
* complete port mapping.
* 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed
* due to conflict with other mechanisms.
* 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded
*/
LIBSPEC int
UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
const char * extPort,
@ -132,6 +140,8 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
*
* List of possible UPnP errors for DeletePortMapping :
* 402 Invalid Args - See UPnP Device Architecture section on Control.
* 606 Action not authorized - The action requested REQUIRES authorization
* and the sender was not authorized.
* 714 NoSuchEntryInArray - The specified value does not exist in the array */
LIBSPEC int
UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
@ -150,6 +160,7 @@ UPNP_GetPortMappingNumberOfEntries(const char* controlURL,
* params :
* in extPort
* in proto
* in remoteHost
* out intClient (16 bytes)
* out intPort (6 bytes)
* out desc (80 bytes)
@ -158,12 +169,21 @@ UPNP_GetPortMappingNumberOfEntries(const char* controlURL,
*
* return value :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
* or a UPnP Error Code. */
* or a UPnP Error Code.
*
* 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.
*/
LIBSPEC int
UPNP_GetSpecificPortMappingEntry(const char * controlURL,
const char * servicetype,
const char * extPort,
const char * proto,
const char * remoteHost,
char * intClient,
char * intPort,
char * desc,
@ -188,6 +208,8 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
*
* Possible UPNP Error codes :
* 402 Invalid Args - See UPnP Device Architecture section on Control.
* 606 Action not authorized - The action requested REQUIRES authorization
* and the sender was not authorized.
* 713 SpecifiedArrayIndexInvalid - The specified array index is out of bounds
*/
LIBSPEC int

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.15 2013/06/06 21:36:40 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2011 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -15,18 +15,55 @@
static void
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)
l = 63;
memcpy(data->curelt, name, l);
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(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';
}
LIST_INSERT_HEAD( &(data->head), nv, entries);
}
data->cdata = NULL;
data->cdatalen = 0;
data->topelt = 0;
}
static void
NameValueParserGetData(void * d, const char * datas, int l)
{
struct NameValueParserData * data = (struct NameValueParserData *)d;
struct NameValue * nv;
if(strcmp(data->curelt, "NewPortListing") == 0)
{
/* specific case for NewPortListing which is a XML Document */
@ -42,15 +79,9 @@ NameValueParserGetData(void * d, const char * datas, int l)
}
else
{
/* standard case. Limited to 63 chars strings */
nv = malloc(sizeof(struct NameValue));
if(l>63)
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);
/* standard case. */
data->cdata = datas;
data->cdatalen = l;
}
}
@ -67,7 +98,7 @@ ParseNameValue(const char * buffer, int bufsize,
parser.xmlsize = bufsize;
parser.data = data;
parser.starteltfunc = NameValueParserStartElt;
parser.endeltfunc = 0;
parser.endeltfunc = NameValueParserEndElt;
parser.datafunc = NameValueParserGetData;
parser.attfunc = 0;
parsexml(&parser);

View File

@ -1,12 +1,12 @@
/* $Id: upnpreplyparse.h,v 1.13 2012/03/05 19:42:48 nanard Exp $ */
/* $Id: upnpreplyparse.h,v 1.17 2013/06/06 21:36:40 nanard Exp $ */
/* MiniUPnP project
* 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
* in the LICENCE file provided within the distribution */
#ifndef __UPNPREPLYPARSE_H__
#define __UPNPREPLYPARSE_H__
#ifndef UPNPREPLYPARSE_H_INCLUDED
#define UPNPREPLYPARSE_H_INCLUDED
#if defined(NO_SYS_QUEUE_H) || defined(_WIN32) || defined(__HAIKU__)
#include "bsdqueue.h"
@ -21,7 +21,7 @@ extern "C" {
struct NameValue {
LIST_ENTRY(NameValue) entries;
char name[64];
char value[64];
char value[128];
};
struct NameValueParserData {
@ -29,6 +29,9 @@ struct NameValueParserData {
char curelt[64];
char * portListing;
int portListingLength;
int topelt;
const char * cdata;
int cdatalen;
};
/* ParseNameValue() */
@ -45,10 +48,12 @@ char *
GetValueFromNameValueList(struct NameValueParserData * pdata,
const char * Name);
#if 0
/* GetValueFromNameValueListIgnoreNS() */
char *
GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
const char * Name);
#endif
/* DisplayNameValueList() */
#ifdef DEBUG