Skip to content

Instantly share code, notes, and snippets.

@laanwj
Created October 9, 2015 11:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save laanwj/6caebd77a1c253a486e4 to your computer and use it in GitHub Desktop.
Save laanwj/6caebd77a1c253a486e4 to your computer and use it in GitHub Desktop.
Difference between miniupnp 1.9.20150730 and 1.9.20151008
diff -duN miniupnpc-1.9.20150730/apiversions.txt miniupnpc-1.9.20151008/apiversions.txt
--- miniupnpc-1.9.20150730/apiversions.txt 2015-07-30 00:05:55.000000000 +0200
+++ miniupnpc-1.9.20151008/apiversions.txt 2015-10-08 18:16:03.000000000 +0200
@@ -1,7 +1,15 @@
-$Id: apiversions.txt,v 1.7 2015/07/23 20:40:08 nanard Exp $
+$Id: apiversions.txt,v 1.8 2015/10/08 16:15:47 nanard Exp $
Differences in API between miniUPnPc versions
+API version 15
+ changed "sameport" argument of upnpDiscover() upnpDiscoverAll() upnpDiscoverDevice()
+ to "localport". When 0 or 1, behaviour is not changed, but it can take
+ any other value between 2 and 65535
+ Existing programs should be compatible
+ updated macro :
+ #define MINIUPNPC_API_VERSION 15
+
API version 14
miniupnpc.h
add ttl argument to upnpDiscover() upnpDiscoverAll() upnpDiscoverDevice()
@@ -9,6 +17,8 @@
getDevicesFromMiniSSDPD() :
connectToMiniSSDPD() / disconnectFromMiniSSDPD()
requestDevicesFromMiniSSDPD() / receiveDevicesFromMiniSSDPD()
+ updated macro :
+ #define MINIUPNPC_API_VERSION 14
API version 13
miniupnpc.h:
diff -duN miniupnpc-1.9.20150730/Changelog.txt miniupnpc-1.9.20151008/Changelog.txt
--- miniupnpc-1.9.20150730/Changelog.txt 2015-07-30 00:05:55.000000000 +0200
+++ miniupnpc-1.9.20151008/Changelog.txt 2015-10-08 18:16:03.000000000 +0200
@@ -1,6 +1,24 @@
-$Id: Changelog.txt,v 1.212 2015/07/23 20:41:50 nanard Exp $
+$Id: Changelog.txt,v 1.216 2015/10/08 16:15:45 nanard Exp $
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
diff -duN miniupnpc-1.9.20150730/CMakeLists.txt miniupnpc-1.9.20151008/CMakeLists.txt
--- miniupnpc-1.9.20150730/CMakeLists.txt 2015-07-30 00:05:55.000000000 +0200
+++ miniupnpc-1.9.20151008/CMakeLists.txt 2015-10-08 18:16:03.000000000 +0200
@@ -2,7 +2,7 @@
project (miniupnpc C)
set (MINIUPNPC_VERSION 1.9)
-set (MINIUPNPC_API_VERSION 14)
+set (MINIUPNPC_API_VERSION 15)
if (NOT CMAKE_BUILD_TYPE)
if (WIN32)
@@ -70,9 +70,11 @@
miniupnpc.c
minixml.c
minisoap.c
+ minissdpc.c
miniwget.c
upnpc.c
upnpcommands.c
+ upnpdev.c
upnpreplyparse.c
upnperrors.c
connecthostport.c
@@ -164,9 +166,10 @@
igd_desc_parse.h
upnpreplyparse.h
upnperrors.h
+ upnpdev.h
miniupnpctypes.h
portlistingparse.h
- declspec.h
+ miniupnpc_declspec.h
DESTINATION include/miniupnpc
)
diff -duN miniupnpc-1.9.20150730/connecthostport.c miniupnpc-1.9.20151008/connecthostport.c
--- miniupnpc-1.9.20150730/connecthostport.c 2014-03-31 14:41:45.000000000 +0200
+++ miniupnpc-1.9.20151008/connecthostport.c 2015-10-02 19:02:48.000000000 +0200
@@ -1,7 +1,7 @@
-/* $Id: connecthostport.c,v 1.13 2014/03/31 12:36:36 nanard Exp $ */
+/* $Id: connecthostport.c,v 1.14 2015/10/02 11:08:34 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
- * Copyright (c) 2010-2014 Thomas Bernard
+ * Copyright (c) 2010-2015 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
@@ -23,6 +23,10 @@
#define socklen_t int
#else /* #ifdef _WIN32 */
#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/select.h>
#include <errno.h>
@@ -33,7 +37,6 @@
* 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 */
diff -duN miniupnpc-1.9.20150730/igd_desc_parse.c miniupnpc-1.9.20151008/igd_desc_parse.c
--- miniupnpc-1.9.20150730/igd_desc_parse.c 2014-11-26 11:42:59.000000000 +0100
+++ miniupnpc-1.9.20151008/igd_desc_parse.c 2015-09-17 15:05:25.000000000 +0200
@@ -1,8 +1,8 @@
-/* $Id: igd_desc_parse.c,v 1.16 2014/11/17 17:19:13 nanard Exp $ */
+/* $Id: igd_desc_parse.c,v 1.17 2015/09/15 13:30:04 nanard Exp $ */
/* Project : miniupnp
* http://miniupnp.free.fr/
* Author : Thomas Bernard
- * Copyright (c) 2005-2014 Thomas Bernard
+ * Copyright (c) 2005-2015 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
@@ -15,7 +15,9 @@
void IGDstartelt(void * d, const char * name, int l)
{
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->level++;
if( (l==7) && !memcmp(name, "service", l) ) {
Common subdirectories: miniupnpc-1.9.20150730/java and miniupnpc-1.9.20151008/java
diff -duN miniupnpc-1.9.20150730/listdevices.c miniupnpc-1.9.20151008/listdevices.c
--- miniupnpc-1.9.20150730/listdevices.c 2015-07-30 00:05:55.000000000 +0200
+++ miniupnpc-1.9.20151008/listdevices.c 2015-10-08 18:16:03.000000000 +0200
@@ -1,4 +1,4 @@
-/* $Id: listdevices.c,v 1.6 2015/07/23 20:40:08 nanard Exp $ */
+/* $Id: listdevices.c,v 1.7 2015/10/08 16:15:47 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2013-2015 Thomas Bernard
@@ -81,18 +81,18 @@
printf("searching UPnP device type %s\n", searched_device);
devlist = upnpDiscoverDevice(searched_device,
2000, multicastif, minissdpdpath,
- 0/*sameport*/, ipv6, ttl, &error);
+ 0/*localport*/, ipv6, ttl, &error);
} else if(searched_devices) {
printf("searching UPnP device types :\n");
for(i = 0; searched_devices[i]; i++)
printf("\t%s\n", searched_devices[i]);
devlist = upnpDiscoverDevices(searched_devices,
2000, multicastif, minissdpdpath,
- 0/*sameport*/, ipv6, ttl, &error, 1);
+ 0/*localport*/, ipv6, ttl, &error, 1);
} else {
printf("searching all UPnP devices\n");
devlist = upnpDiscoverAll(2000, multicastif, minissdpdpath,
- 0/*sameport*/, ipv6, ttl, &error);
+ 0/*localport*/, ipv6, ttl, &error);
}
if(devlist) {
for(dev = devlist, i = 1; dev != NULL; dev = dev->pNext, i++) {
diff -duN miniupnpc-1.9.20150730/Makefile miniupnpc-1.9.20151008/Makefile
--- miniupnpc-1.9.20150730/Makefile 2015-07-30 00:05:55.000000000 +0200
+++ miniupnpc-1.9.20151008/Makefile 2015-10-08 18:16:03.000000000 +0200
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.125 2015/07/29 22:05:23 nanard Exp $
+# $Id: Makefile,v 1.131 2015/10/08 16:15:46 nanard Exp $
# MiniUPnP Project
# http://miniupnp.free.fr/
# http://miniupnp.tuxfamily.org/
@@ -35,8 +35,15 @@
CFLAGS += -fno-common
CFLAGS += -DMINIUPNPC_SET_SOCKET_TIMEOUT
CFLAGS += -DMINIUPNPC_GET_SRC_ADDR
-CFLAGS += -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200112L
-CFLAGS += -ansi
+CFLAGS += -D_BSD_SOURCE
+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
INSTALL = install
SH = /bin/sh
@@ -46,29 +53,32 @@
#JNAERATOR = jnaerator-0.9.8-shaded.jar
#JNAERATORARGS = -library miniupnpc
#JNAERATOR = jnaerator-0.10-shaded.jar
-JNAERATOR = jnaerator-0.11-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 = 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 = 14
+APIVERSION = 15
SRCS = igd_desc_parse.c miniupnpc.c minixml.c minisoap.c miniwget.c \
upnpc.c upnpcommands.c upnpreplyparse.c testminixml.c \
minixmlvalid.c testupnpreplyparse.c minissdpc.c \
upnperrors.c testigddescparse.c testminiwget.c \
connecthostport.c portlistingparse.c receivedata.c \
- testportlistingparse.c miniupnpcmodule.c \
+ upnpdev.c testportlistingparse.c miniupnpcmodule.c \
minihttptestserver.c \
listdevices.c
LIBOBJS = miniwget.o minixml.o igd_desc_parse.o minisoap.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)
CFLAGS := -fPIC $(CFLAGS)
@@ -81,6 +91,7 @@
HEADERS = miniupnpc.h miniwget.h upnpcommands.h igd_desc_parse.h \
upnpreplyparse.h upnperrors.h miniupnpctypes.h \
portlistingparse.h \
+ upnpdev.h \
miniupnpc_declspec.h
# library names
@@ -325,39 +336,40 @@
# DO NOT DELETE THIS LINE -- make depend depends on it.
igd_desc_parse.o: igd_desc_parse.h
-miniupnpc.o: miniupnpc.h miniupnpc_declspec.h igd_desc_parse.h minissdpc.h
-miniupnpc.o: miniwget.h minisoap.h minixml.h upnpcommands.h upnpreplyparse.h
-miniupnpc.o: portlistingparse.h miniupnpctypes.h connecthostport.h
-miniupnpc.o: receivedata.h
+miniupnpc.o: miniupnpc.h miniupnpc_declspec.h igd_desc_parse.h upnpdev.h
+miniupnpc.o: minissdpc.h miniwget.h minisoap.h minixml.h upnpcommands.h
+miniupnpc.o: upnpreplyparse.h portlistingparse.h miniupnpctypes.h
+miniupnpc.o: connecthostport.h
minixml.o: minixml.h
minisoap.o: minisoap.h miniupnpcstrings.h
miniwget.o: miniupnpcstrings.h miniwget.h miniupnpc_declspec.h
miniwget.o: connecthostport.h receivedata.h
upnpc.o: miniwget.h miniupnpc_declspec.h miniupnpc.h igd_desc_parse.h
-upnpc.o: upnpcommands.h upnpreplyparse.h portlistingparse.h miniupnpctypes.h
-upnpc.o: upnperrors.h miniupnpcstrings.h
+upnpc.o: upnpdev.h upnpcommands.h upnpreplyparse.h portlistingparse.h
+upnpc.o: miniupnpctypes.h upnperrors.h miniupnpcstrings.h
upnpcommands.o: upnpcommands.h upnpreplyparse.h portlistingparse.h
upnpcommands.o: miniupnpc_declspec.h miniupnpctypes.h miniupnpc.h
-upnpcommands.o: igd_desc_parse.h
+upnpcommands.o: igd_desc_parse.h upnpdev.h
upnpreplyparse.o: upnpreplyparse.h minixml.h
testminixml.o: minixml.h igd_desc_parse.h
minixmlvalid.o: minixml.h
testupnpreplyparse.o: upnpreplyparse.h
-minissdpc.o: minissdpc.h miniupnpc.h miniupnpc_declspec.h igd_desc_parse.h
-minissdpc.o: codelength.h
+minissdpc.o: minissdpc.h miniupnpc_declspec.h upnpdev.h miniupnpc.h
+minissdpc.o: igd_desc_parse.h receivedata.h codelength.h
upnperrors.o: upnperrors.h miniupnpc_declspec.h upnpcommands.h
upnperrors.o: upnpreplyparse.h portlistingparse.h miniupnpctypes.h
-upnperrors.o: miniupnpc.h igd_desc_parse.h
+upnperrors.o: miniupnpc.h igd_desc_parse.h upnpdev.h
testigddescparse.o: igd_desc_parse.h minixml.h miniupnpc.h
-testigddescparse.o: miniupnpc_declspec.h
+testigddescparse.o: miniupnpc_declspec.h upnpdev.h
testminiwget.o: miniwget.h miniupnpc_declspec.h
connecthostport.o: connecthostport.h
portlistingparse.o: portlistingparse.h miniupnpc_declspec.h miniupnpctypes.h
portlistingparse.o: minixml.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: upnpcommands.h upnpreplyparse.h portlistingparse.h
-miniupnpcmodule.o: miniupnpctypes.h upnperrors.h
-listdevices.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
diff -duN miniupnpc-1.9.20150730/Makefile.mingw miniupnpc-1.9.20151008/Makefile.mingw
--- miniupnpc-1.9.20150730/Makefile.mingw 2014-06-10 12:02:51.000000000 +0200
+++ miniupnpc-1.9.20151008/Makefile.mingw 2015-09-22 11:59:25.000000000 +0200
@@ -1,7 +1,7 @@
-# $Id: Makefile.mingw,v 1.19 2014/06/10 09:48:11 nanard Exp $
+# $Id: Makefile.mingw,v 1.21 2015/09/18 12:45:16 nanard Exp $
# Miniupnp project.
# http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
-# (c) 2005-2014 Thomas Bernard
+# (c) 2005-2015 Thomas Bernard
# This Makefile is made for MinGW
#
CC = gcc
@@ -12,8 +12,10 @@
# -liphlpapi is needed for GetBestRoute() and GetIpAddrTable()
PYTHON=\utils\python25\python
OBJS=miniwget.o minixml.o igd_desc_parse.o minisoap.o \
+ minissdpc.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))
all: init upnpc-static upnpc-shared testminixml libminiupnpc.a miniupnpc.dll
@@ -71,9 +73,10 @@
miniupnpcstrings.h: miniupnpcstrings.h.in 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
@@ -89,3 +92,7 @@
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
+
Common subdirectories: miniupnpc-1.9.20150730/man3 and miniupnpc-1.9.20151008/man3
diff -duN miniupnpc-1.9.20150730/minissdpc.c miniupnpc-1.9.20151008/minissdpc.c
--- miniupnpc-1.9.20150730/minissdpc.c 2015-07-30 00:05:55.000000000 +0200
+++ miniupnpc-1.9.20151008/minissdpc.c 2015-10-08 18:16:03.000000000 +0200
@@ -1,4 +1,4 @@
-/* $Id: minissdpc.c,v 1.22 2015/07/23 17:15:01 nanard Exp $ */
+/* $Id: minissdpc.c,v 1.29 2015/10/08 16:15:47 nanard Exp $ */
/* Project : miniupnp
* Web : http://miniupnp.free.fr/
* Author : Thomas BERNARD
@@ -9,42 +9,92 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <unistd.h>
#include <sys/types.h>
#if defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
+#include <iphlpapi.h>
#include <winsock.h>
+#define snprintf _snprintf
+#if !defined(_MSC_VER)
#include <stdint.h>
-#endif
+#else /* !defined(_MSC_VER) */
+typedef unsigned short uint16_t;
+#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__)
#include <sys/socket.h>
-#endif
+#endif /* defined(__amigaos__) || defined(__amigaos4__) */
#if defined(__amigaos__)
#define uint16_t unsigned short
-#endif
+#endif /* defined(__amigaos__) */
/* Hack */
#define UNIX_PATH_LEN 108
struct sockaddr_un {
uint16_t sun_family;
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/param.h>
+#include <sys/time.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
#include "minissdpc.h"
#include "miniupnpc.h"
+#include "receivedata.h"
+
+#if !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__))
#include "codelength.h"
struct UPNPDev *
getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath, int * error)
{
- struct UPNPDev * devlist;
+ struct UPNPDev * devlist = NULL;
int s;
int res;
@@ -58,16 +108,16 @@
if (res < 0) {
if (error)
*error = res;
- return NULL;
+ } else {
+ devlist = receiveDevicesFromMiniSSDPD(s, error);
}
- devlist = receiveDevicesFromMiniSSDPD(s, error);
disconnectFromMiniSSDPD(s);
return devlist;
}
/* macros used to read from unix socket */
#define READ_BYTE_BUFFER(c) \
- if(bufferindex >= n) { \
+ if((int)bufferindex >= n) { \
n = read(s, buffer, sizeof(buffer)); \
if(n<=0) break; \
bufferindex = 0; \
@@ -81,7 +131,7 @@
#define READ_COPY_BUFFER(dst, len) \
for(l = len, p = (unsigned char *)dst; l > 0; ) { \
unsigned int lcopy; \
- if(bufferindex >= n) { \
+ if((int)bufferindex >= n) { \
n = read(s, buffer, sizeof(buffer)); \
if(n<=0) break; \
bufferindex = 0; \
@@ -145,6 +195,7 @@
if(connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0)
{
/*syslog(LOG_WARNING, "connect(\"%s\"): %m", socketpath);*/
+ close(s);
return MINISSDPC_SOCKET_ERROR;
}
return s;
@@ -316,3 +367,478 @@
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;
+}
+
diff -duN miniupnpc-1.9.20150730/minissdpc.h miniupnpc-1.9.20151008/minissdpc.h
--- miniupnpc-1.9.20150730/minissdpc.h 2015-07-30 00:05:55.000000000 +0200
+++ miniupnpc-1.9.20151008/minissdpc.h 2015-10-08 18:16:03.000000000 +0200
@@ -1,4 +1,4 @@
-/* $Id: minissdpc.h,v 1.4 2015/07/23 20:40:08 nanard Exp $ */
+/* $Id: minissdpc.h,v 1.7 2015/10/08 16:15:47 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author: Thomas Bernard
@@ -9,9 +9,11 @@
#define MINISSDPC_H_INCLUDED
#include "miniupnpc_declspec.h"
+#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)
@@ -21,6 +23,8 @@
extern "C" {
#endif
+#if !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__))
+
MINIUPNP_LIBSPEC struct UPNPDev *
getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath, int * error);
@@ -36,6 +40,16 @@
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
diff -duN miniupnpc-1.9.20150730/miniupnpc.c miniupnpc-1.9.20151008/miniupnpc.c
--- miniupnpc-1.9.20150730/miniupnpc.c 2015-07-30 00:05:55.000000000 +0200
+++ miniupnpc-1.9.20151008/miniupnpc.c 2015-10-08 18:16:03.000000000 +0200
@@ -1,26 +1,10 @@
-/* $Id: miniupnpc.c,v 1.135 2015/07/23 20:40:08 nanard Exp $ */
+/* $Id: miniupnpc.c,v 1.140 2015/10/08 16:15:47 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. */
-#define __EXTENSIONS__ 1
-#if !defined(__APPLE__) && !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(__APPLE__) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__sun) && !defined(__GNU__) && !defined(__FreeBSD_kernel__)
-#define HAS_IP_MREQN
-#endif
-
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -63,26 +47,11 @@
#include <errno.h>
#define closesocket close
#endif /* #else _WIN32 */
-#if defined(__amigaos__) || defined(__amigaos4__)
-/* Amiga OS specific stuff */
-#define TIMEVAL struct timeval
-#endif
#ifdef __GNU__
#define MAXHOSTNAMELEN 64
#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"
@@ -90,17 +59,10 @@
#include "minixml.h"
#include "upnpcommands.h"
#include "connecthostport.h"
-#include "receivedata.h"
/* compare the begining of a string with a constant string */
#define COMPARE(str, cstr) (0==memcmp(str, cstr, sizeof(cstr) - 1))
-#ifdef _WIN32
-#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
-#else
-#define PRINT_SOCKET_ERROR(x) perror(x)
-#endif
-
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
@@ -264,82 +226,6 @@
return buf;
}
-/* 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 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 */
-
/* upnpDiscoverDevices() :
* return a chained list of all devices found or NULL if
* no devices was found.
@@ -351,38 +237,16 @@
MINIUPNP_LIBSPEC struct UPNPDev *
upnpDiscoverDevices(const char * const deviceTypes[],
int delay, const char * multicastif,
- const char * minissdpdsock, int sameport,
+ const char * minissdpdsock, 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(PORT) "\r\n"
- "ST: %s\r\n"
- "MAN: \"ssdp:discover\"\r\n"
- "MX: %u\r\n"
- "\r\n";
+#if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__)
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;
-#endif
- int linklocal = 1;
+#endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
if(error)
*error = UPNPDISCOVER_UNKNOWN_ERROR;
@@ -427,349 +291,24 @@
#endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
/* direct discovery if minissdpd responses are not sufficient */
-#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(pIPAddrTable) {
- 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 /* _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 = UPNPDISCOVER_SOCKET_ERROR;
- PRINT_SOCKET_ERROR("setsockopt(SO_REUSEADDR,...)");
- return NULL;
- }
-
- if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
- {
- /* 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 = 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;
- 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(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
- * 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 = UPNPDISCOVER_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 = UPNPDISCOVER_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 = UPNPDISCOVER_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;
- }
+ 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;
}
}
-error:
- closesocket(sudp);
return devlist;
}
/* upnpDiscover() Discover IGD device */
MINIUPNP_LIBSPEC struct UPNPDev *
upnpDiscover(int delay, const char * multicastif,
- const char * minissdpdsock, int sameport,
+ const char * minissdpdsock, int localport,
int ipv6, unsigned char ttl,
int * error)
{
@@ -786,14 +325,14 @@
0
};
return upnpDiscoverDevices(deviceList,
- delay, multicastif, minissdpdsock, sameport,
+ delay, multicastif, minissdpdsock, localport,
ipv6, ttl, error, 0);
}
/* upnpDiscoverAll() Discover all UPnP devices */
MINIUPNP_LIBSPEC struct UPNPDev *
upnpDiscoverAll(int delay, const char * multicastif,
- const char * minissdpdsock, int sameport,
+ const char * minissdpdsock, int localport,
int ipv6, unsigned char ttl,
int * error)
{
@@ -803,14 +342,14 @@
0
};
return upnpDiscoverDevices(deviceList,
- delay, multicastif, minissdpdsock, sameport,
+ delay, multicastif, minissdpdsock, localport,
ipv6, ttl, error, 0);
}
/* upnpDiscoverDevice() Discover a specific device */
MINIUPNP_LIBSPEC struct UPNPDev *
upnpDiscoverDevice(const char * device, int delay, const char * multicastif,
- const char * minissdpdsock, int sameport,
+ const char * minissdpdsock, int localport,
int ipv6, unsigned char ttl,
int * error)
{
@@ -819,23 +358,10 @@
0
};
return upnpDiscoverDevices(deviceList,
- delay, multicastif, minissdpdsock, sameport,
+ delay, multicastif, minissdpdsock, localport,
ipv6, ttl, error, 0);
}
-/* freeUPNPDevlist() should be used to
- * free the chained list returned by upnpDiscover() */
-MINIUPNP_LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist)
-{
- struct UPNPDev * next;
- while(devlist)
- {
- next = devlist->pNext;
- free(devlist);
- devlist = next;
- }
-}
-
static char *
build_absolute_url(const char * baseurl, const char * descURL,
const char * url, unsigned int scope_id)
@@ -961,9 +487,9 @@
UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype,
status, &uptime, NULL);
if(0 == strcmp("Connected", status))
- {
return 1;
- }
+ else if(0 == strcmp("Up", status)) /* Also accept "Up" */
+ return 1;
else
return 0;
}
diff -duN miniupnpc-1.9.20150730/miniupnpc.h miniupnpc-1.9.20151008/miniupnpc.h
--- miniupnpc-1.9.20150730/miniupnpc.h 2015-07-30 00:09:48.000000000 +0200
+++ miniupnpc-1.9.20151008/miniupnpc.h 2015-10-08 18:22:17.000000000 +0200
@@ -1,4 +1,4 @@
-/* $Id: miniupnpc.h,v 1.44 2015/07/23 20:40:10 nanard Exp $ */
+/* $Id: miniupnpc.h,v 1.48 2015/10/08 16:19:40 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/
* Author: Thomas Bernard
@@ -10,6 +10,7 @@
#include "miniupnpc_declspec.h"
#include "igd_desc_parse.h"
+#include "upnpdev.h"
/* error codes : */
#define UPNPDISCOVER_SUCCESS (0)
@@ -18,8 +19,14 @@
#define UPNPDISCOVER_MEMORY_ERROR (-102)
/* versions : */
-#define MINIUPNPC_VERSION "1.9.20150730"
-#define MINIUPNPC_API_VERSION 14
+#define MINIUPNPC_VERSION "1.9.20151008"
+#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
extern "C" {
@@ -33,15 +40,6 @@
const char *, struct UPNParg *,
int *);
-struct UPNPDev {
- struct UPNPDev * pNext;
- char * descURL;
- char * st;
- unsigned int scope_id;
- char * usn;
- char buffer[3];
-};
-
/* upnpDiscover()
* discover UPnP devices on the network.
* The discovered devices are returned as a chained list.
@@ -53,41 +51,39 @@
* is NULL.
* If multicastif is not NULL, it will be used instead of the default
* multicast interface for sending SSDP discover packets.
- * If sameport is not null, SSDP packets will be sent from the source port
- * 1900 (same as destination port) otherwise system assign a source port.
+ * If localport is set to UPNP_LOCAL_PORT_SAME(1) SSDP packets will be sent
+ * from the source port 1900 (same as destination port), if set to
+ * UPNP_LOCAL_PORT_ANY(0) system assign a source port, any other value will
+ * be attempted as the source port.
* "searchalltypes" parameter is useful when searching several types,
* if 0, the discovery will stop with the first type returning results.
* TTL should default to 2. */
MINIUPNP_LIBSPEC struct UPNPDev *
upnpDiscover(int delay, const char * multicastif,
- const char * minissdpdsock, int sameport,
+ const char * minissdpdsock, int localport,
int ipv6, unsigned char ttl,
int * error);
MINIUPNP_LIBSPEC struct UPNPDev *
upnpDiscoverAll(int delay, const char * multicastif,
- const char * minissdpdsock, int sameport,
+ 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 sameport,
+ 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 sameport,
+ const char * minissdpdsock, int localport,
int ipv6, unsigned char ttl,
int * error,
int searchalltypes);
-/* freeUPNPDevlist()
- * free list returned by upnpDiscover() */
-MINIUPNP_LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist);
-
/* parserootdesc() :
* parse root XML description of a UPnP device and fill the IGDdatas
* structure. */
diff -duN miniupnpc-1.9.20150730/miniupnpcmodule.c miniupnpc-1.9.20151008/miniupnpcmodule.c
--- miniupnpc-1.9.20150730/miniupnpcmodule.c 2015-05-22 12:58:32.000000000 +0200
+++ miniupnpc-1.9.20151008/miniupnpcmodule.c 2015-10-08 18:16:06.000000000 +0200
@@ -1,4 +1,4 @@
-/* $Id: miniupnpcmodule.c,v 1.26 2015/05/22 10:29:08 nanard Exp $*/
+/* $Id: miniupnpcmodule.c,v 1.28 2015/10/08 16:15:48 nanard Exp $*/
/* Project : miniupnp
* Author : Thomas BERNARD
* website : http://miniupnp.tuxfamily.org/
@@ -42,6 +42,7 @@
struct UPNPUrls urls;
struct IGDdatas data;
unsigned int discoverdelay; /* value passed to upnpDiscover() */
+ unsigned int localport; /* value passed to upnpDiscover() */
char lanaddr[40]; /* our ip address on the LAN */
char * multicastif;
char * minissdpdsocket;
@@ -54,6 +55,15 @@
{"discoverdelay", T_UINT, offsetof(UPnPObject, discoverdelay),
0/*READWRITE*/, "value in ms used to wait for SSDP responses"
},
+ {"localport", T_UINT, offsetof(UPnPObject, localport),
+ 0/*READWRITE*/,
+ "If localport is set to UPNP_LOCAL_PORT_SAME(1) "
+ "SSDP packets will be sent from the source port "
+ "1900 (same as destination port), if set to "
+ "UPNP_LOCAL_PORT_ANY(0) system assign a source "
+ "port, any other value will be attempted as the "
+ "source port"
+ },
/* T_STRING is allways readonly :( */
{"multicastif", T_STRING, offsetof(UPnPObject, multicastif),
0, "IP of the network interface to be used for multicast operations"
@@ -70,15 +80,22 @@
char* multicastif = NULL;
char* minissdpdsocket = NULL;
static char *kwlist[] = {
- "multicastif", "minissdpdsocket", "discoverdelay", NULL
+ "multicastif", "minissdpdsocket", "discoverdelay",
+ "localport", NULL
};
- if(!PyArg_ParseTupleAndKeywords(args, kwds, "|zzI", kwlist,
+ if(!PyArg_ParseTupleAndKeywords(args, kwds, "|zzII", kwlist,
&multicastif,
&minissdpdsocket,
- &self->discoverdelay))
- return -1;
+ &self->discoverdelay,
+ &self->localport))
+ return -1;
+ if(self->localport>1 &&
+ (self->localport>65534||self->localport<1024)) {
+ PyErr_SetString(PyExc_Exception, "Invalid localport value");
+ return -1;
+ }
if(multicastif)
self->multicastif = strdup(multicastif);
if(minissdpdsocket)
@@ -112,8 +129,9 @@
self->devlist = upnpDiscover((int)self->discoverdelay/*timeout in ms*/,
self->multicastif,
self->minissdpdsocket,
- 0/*sameport flag*/,
+ (int)self->localport,
0/*ip v6*/,
+ 2/* TTL */,
0/*error */);
Py_END_ALLOW_THREADS
/* Py_RETURN_NONE ??? */
diff -duN miniupnpc-1.9.20150730/miniwget.c miniupnpc-1.9.20151008/miniwget.c
--- miniupnpc-1.9.20150730/miniwget.c 2015-07-15 18:14:01.000000000 +0200
+++ miniupnpc-1.9.20151008/miniwget.c 2015-08-06 15:36:25.000000000 +0200
@@ -1,4 +1,4 @@
-/* $Id: miniwget.c,v 1.70 2015/07/15 12:41:13 nanard Exp $ */
+/* $Id: miniwget.c,v 1.71 2015/08/06 09:54:20 nanard Exp $ */
/* Project : miniupnp
* Website : http://miniupnp.free.fr/
* Author : Thomas Bernard
@@ -94,7 +94,7 @@
return NULL;
}
content_buf = malloc(content_buf_len);
- if(header_buf == NULL)
+ if(content_buf == NULL)
{
free(header_buf);
#ifdef DEBUG
Common subdirectories: miniupnpc-1.9.20150730/msvc and miniupnpc-1.9.20151008/msvc
diff -duN miniupnpc-1.9.20150730/pymoduletest.py miniupnpc-1.9.20151008/pymoduletest.py
--- miniupnpc-1.9.20150730/pymoduletest.py 2015-05-22 12:58:32.000000000 +0200
+++ miniupnpc-1.9.20151008/pymoduletest.py 2015-10-08 18:16:06.000000000 +0200
@@ -14,6 +14,7 @@
parser.add_argument('-m', '--multicastif')
parser.add_argument('-p', '--minissdpdsocket')
parser.add_argument('-d', '--discoverdelay', type=int, default=200)
+parser.add_argument('-z', '--localport', type=int, default=0)
# create the object
u = miniupnpc.UPnP(**vars(parser.parse_args()))
Common subdirectories: miniupnpc-1.9.20150730/testdesc and miniupnpc-1.9.20151008/testdesc
diff -duN miniupnpc-1.9.20150730/testigddescparse.c miniupnpc-1.9.20151008/testigddescparse.c
--- miniupnpc-1.9.20150730/testigddescparse.c 2015-07-21 15:24:16.000000000 +0200
+++ miniupnpc-1.9.20151008/testigddescparse.c 2015-08-06 15:36:25.000000000 +0200
@@ -1,4 +1,4 @@
-/* $Id: testigddescparse.c,v 1.9 2015/07/21 13:17:50 nanard Exp $ */
+/* $Id: testigddescparse.c,v 1.10 2015/08/06 09:55:24 nanard Exp $ */
/* Project : miniupnp
* http://miniupnp.free.fr/
* Author : Thomas Bernard
@@ -165,6 +165,7 @@
fprintf(stderr, "Failed to read file %s. %d out of %d bytes.\n",
argv[1], r, len);
fclose(f);
+ free(buffer);
return 1;
}
fclose(f);
diff -duN miniupnpc-1.9.20150730/testminiwget.sh miniupnpc-1.9.20151008/testminiwget.sh
--- miniupnpc-1.9.20150730/testminiwget.sh 2015-07-21 15:24:16.000000000 +0200
+++ miniupnpc-1.9.20151008/testminiwget.sh 2015-09-17 15:05:27.000000000 +0200
@@ -1,5 +1,5 @@
#!/bin/sh
-# $Id: testminiwget.sh,v 1.12 2015/07/16 15:13:49 nanard Exp $
+# $Id: testminiwget.sh,v 1.13 2015/09/03 17:57:44 nanard Exp $
# project miniupnp : http://miniupnp.free.fr/
# (c) 2011-2015 Thomas Bernard
#
@@ -15,7 +15,7 @@
# The script was tested and works with ksh, bash
# it should now also run with dash
-TMPD=`mktemp -t -d miniwgetXXXXXXXXXX`
+TMPD=`mktemp -d -t miniwgetXXXXXXXXXX`
HTTPSERVEROUT="${TMPD}/httpserverout"
EXPECTEDFILE="${TMPD}/expectedfile"
DOWNLOADEDFILE="${TMPD}/downloadedfile"
Common subdirectories: miniupnpc-1.9.20150730/testreplyparse and miniupnpc-1.9.20151008/testreplyparse
diff -duN miniupnpc-1.9.20150730/upnpc.c miniupnpc-1.9.20151008/upnpc.c
--- miniupnpc-1.9.20150730/upnpc.c 2015-07-30 00:05:57.000000000 +0200
+++ miniupnpc-1.9.20151008/upnpc.c 2015-10-08 18:16:06.000000000 +0200
@@ -1,4 +1,4 @@
-/* $Id: upnpc.c,v 1.111 2015/07/23 20:40:10 nanard Exp $ */
+/* $Id: upnpc.c,v 1.112 2015/10/08 16:15:48 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005-2015 Thomas Bernard
@@ -543,6 +543,7 @@
const char * rootdescurl = 0;
const char * multicastif = 0;
const char * minissdpdpath = 0;
+ int localport = UPNP_LOCAL_PORT_ANY;
int retcode = 0;
int error = 0;
int ipv6 = 0;
@@ -559,7 +560,7 @@
}
#endif
printf("upnpc : miniupnpc library test client, version %s.\n", MINIUPNPC_VERSION_STRING);
- printf(" (c) 2005-2014 Thomas Bernard.\n");
+ printf(" (c) 2005-2015 Thomas Bernard.\n");
printf("Go to http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/\n"
"for more information.\n");
/* command line processing */
@@ -576,6 +577,18 @@
rootdescurl = argv[++i];
else if(argv[i][1] == 'm')
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')
minissdpdpath = argv[++i];
else if(argv[i][1] == '6')
@@ -629,6 +642,7 @@
fprintf(stderr, " -6 : use ip v6 instead of ip v4.\n");
fprintf(stderr, " -u url : bypass discovery process by providing the XML root description url.\n");
fprintf(stderr, " -m address/interface : provide ip address (ip v4) or interface name (ip v4 or v6) to use for sending SSDP multicast packets.\n");
+ fprintf(stderr, " -z localport : SSDP packets local (source) port (1024-65535).\n");
fprintf(stderr, " -p path : use this path for MiniSSDPd socket.\n");
fprintf(stderr, " -t ttl : set multicast TTL. Default value is 2.\n");
return 1;
@@ -636,7 +650,7 @@
if( rootdescurl
|| (devlist = upnpDiscover(2000, multicastif, minissdpdpath,
- 0/*sameport*/, ipv6, ttl, &error)))
+ localport, ipv6, ttl, &error)))
{
struct UPNPDev * device;
struct UPNPUrls urls;
diff -duN miniupnpc-1.9.20150730/upnpdev.c miniupnpc-1.9.20151008/upnpdev.c
--- miniupnpc-1.9.20150730/upnpdev.c 1970-01-01 01:00:00.000000000 +0100
+++ miniupnpc-1.9.20151008/upnpdev.c 2015-08-28 14:14:19.000000000 +0200
@@ -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;
+ }
+}
+
diff -duN miniupnpc-1.9.20150730/upnpdev.h miniupnpc-1.9.20151008/upnpdev.h
--- miniupnpc-1.9.20150730/upnpdev.h 1970-01-01 01:00:00.000000000 +0100
+++ miniupnpc-1.9.20151008/upnpdev.h 2015-08-28 14:14:19.000000000 +0200
@@ -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 */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment