miniupnpc-2.2.6/Makefile 0100644 0001750 0000024 00000030231 14545377501 0014357 0 ustar 00nanard staff # $Id: Makefile,v 1.150 2023/06/15 22:55:24 nanard Exp $
# MiniUPnP Project
# http://miniupnp.free.fr/
# https://miniupnp.tuxfamily.org/
# https://github.com/miniupnp/miniupnp
# (c) 2005-2023 Thomas Bernard
# to install use :
# $ make DESTDIR=/tmp/dummylocation install
# or
# $ INSTALLPREFIX=/usr/local make install
# or
# $ make install (default INSTALLPREFIX is /usr)
OS = $(shell $(CC) -dumpmachine)
VERSION = $(shell cat VERSION)
ifneq (, $(findstring darwin, $(OS)))
JARSUFFIX=mac
LIBTOOL ?= $(shell which libtool)
endif
ifneq (, $(findstring linux, $(OS)))
JARSUFFIX=linux
endif
ifneq (, $(findstring mingw, $(OS))$(findstring cygwin, $(OS))$(findstring msys, $(OS)))
JARSUFFIX=win32
endif
HAVE_IPV6 ?= yes
export HAVE_IPV6
# directories
INCDIR = include
SRCDIR = src
BUILD = build
CC ?= gcc
#AR = gar
#CFLAGS = -O -g
# to debug :
ASANFLAGS = -fsanitize=address -fsanitize=undefined -fsanitize=leak
#CFLAGS = -g -ggdb -O0 $(ASANFLAGS) -fno-omit-frame-pointer
#CPPFLAGS += -DDEBUG
#LDFLAGS += $(ASANFLAGS)
CFLAGS ?= -O
CFLAGS += -Wall
CFLAGS += -W -Wstrict-prototypes
CFLAGS += -fno-common
CPPFLAGS += -I$(BUILD)
CPPFLAGS += -DMINIUPNPC_SET_SOCKET_TIMEOUT
CPPFLAGS += -DMINIUPNPC_GET_SRC_ADDR
CPPFLAGS += -D_BSD_SOURCE
CPPFLAGS += -D_DEFAULT_SOURCE
ifneq (, $(findstring netbsd, $(OS)))
CPPFLAGS += -D_NETBSD_SOURCE
endif
ifeq (, $(findstring freebsd, $(OS))$(findstring darwin, $(OS)))
#CPPFLAGS += -D_POSIX_C_SOURCE=200112L
CPPFLAGS += -D_XOPEN_SOURCE=600
endif
#CFLAGS += -ansi
#CPPFLAGS += -DNO_GETADDRINFO
DEPFLAGS = -MM -MG
MKDIR = mkdir -p
INSTALL = install
SH = /bin/sh
JAVA = java
# see http://code.google.com/p/jnaerator/
#JNAERATOR = jnaerator-0.9.7.jar
#JNAERATOR = jnaerator-0.9.8-shaded.jar
#JNAERATORARGS = -library miniupnpc
#JNAERATOR = jnaerator-0.10-shaded.jar
#JNAERATOR = jnaerator-0.11-shaded.jar
# https://repo1.maven.org/maven2/com/nativelibs4java/jnaerator/0.12/jnaerator-0.12-shaded.jar
JNAERATOR = jnaerator-0.12-shaded.jar
JNAERATORARGS = -mode StandaloneJar -runtime JNAerator -library miniupnpc
#JNAERATORBASEURL = http://jnaerator.googlecode.com/files/
JNAERATORBASEURL = https://repo1.maven.org/maven2/com/nativelibs4java/jnaerator/0.12
ifneq (, $(findstring sun, $(OS))$(findstring solaris, $(OS)))
LDLIBS=-lsocket -lnsl -lresolv
CPPFLAGS += -D__EXTENSIONS__
CFLAGS += -std=c99
endif
# APIVERSION is used to build SONAME
APIVERSION = 17
SRCS = $(wildcard $(SRCDIR)/*.c)
LIBOBJS = $(addprefix $(BUILD)/,miniwget.o minixml.o igd_desc_parse.o minisoap.o \
miniupnpc.o upnpreplyparse.o upnpcommands.o upnperrors.o \
connecthostport.o portlistingparse.o receivedata.o upnpdev.o \
addr_is_reserved.o)
BUILDINCLUDES = $(addprefix $(BUILD)/, miniupnpcstrings.h)
OBJS = $(patsubst $(SRCDIR)/%.c,$(BUILD)/%.o,$(SRCS))
DEPS = $(patsubst $(SRCDIR)/%.c,$(BUILD)/%.d,$(SRCS))
# HEADERS to install
CPPFLAGS += -I$(INCDIR)
HEADERS = $(wildcard $(INCDIR)/*.h)
# library names
LIBRARY = $(BUILD)/libminiupnpc.a
ifneq (, $(findstring darwin, $(OS)))
SHAREDLIBRARY = $(BUILD)/libminiupnpc.dylib
SONAME = $(notdir $(basename $(SHAREDLIBRARY))).$(APIVERSION).dylib
CPPFLAGS += -D_DARWIN_C_SOURCE
else
ifeq ($(JARSUFFIX), win32)
SHAREDLIBRARY = $(BUILD)/miniupnpc.dll
else
# Linux/BSD/etc.
SHAREDLIBRARY = $(BUILD)/libminiupnpc.so
SONAME = $(notdir $(SHAREDLIBRARY)).$(APIVERSION)
endif
endif
EXECUTABLES = $(addprefix $(BUILD)/, upnpc-static upnp-listdevices-static)
EXECUTABLES_ADDTESTS = $(addprefix $(BUILD)/, testminixml minixmlvalid \
testupnpreplyparse testigddescparse testminiwget testportlistingparse)
TESTMINIXMLOBJS = $(addprefix $(BUILD)/, minixml.o igd_desc_parse.o testminixml.o)
TESTMINIWGETOBJS = $(addprefix $(BUILD)/, miniwget.o testminiwget.o connecthostport.o receivedata.o)
TESTUPNPREPLYPARSE = $(addprefix $(BUILD)/, testupnpreplyparse.o minixml.o upnpreplyparse.o)
TESTPORTLISTINGPARSE = $(addprefix $(BUILD)/, testportlistingparse.o minixml.o portlistingparse.o)
TESTADDR_IS_RESERVED = $(addprefix $(BUILD)/, testaddr_is_reserved.o addr_is_reserved.o)
TESTIGDDESCPARSE = $(addprefix $(BUILD)/, testigddescparse.o igd_desc_parse.o minixml.o \
miniupnpc.o miniwget.o upnpcommands.o upnpreplyparse.o \
minisoap.o connecthostport.o receivedata.o \
portlistingparse.o addr_is_reserved.o)
ifeq (, $(findstring amiga, $(OS)))
ifeq (, $(findstring mingw, $(OS))$(findstring cygwin, $(OS))$(findstring msys, $(OS)))
CFLAGS += -fPIC
endif
EXECUTABLES += $(BUILD)/upnpc-shared $(BUILD)/upnp-listdevices-shared
TESTMINIWGETOBJS += $(BUILD)/minissdpc.o
TESTIGDDESCPARSE += $(BUILD)/minissdpc.o
LIBOBJS += $(BUILD)/minissdpc.o
endif
LIBDIR ?= lib
# install directories
ifeq ($(strip $(PREFIX)),)
INSTALLPREFIX ?= /usr
else
INSTALLPREFIX ?= $(PREFIX)
endif
INSTALLDIRINC = $(INSTALLPREFIX)/include/miniupnpc
INSTALLDIRLIB = $(INSTALLPREFIX)/$(LIBDIR)
INSTALLDIRBIN = $(INSTALLPREFIX)/bin
INSTALLDIRMAN = $(INSTALLPREFIX)/share/man
PKGCONFIGDIR = $(INSTALLDIRLIB)/pkgconfig
FILESTOINSTALL = $(LIBRARY) $(EXECUTABLES)
ifeq (, $(findstring amiga, $(OS)))
FILESTOINSTALL += $(SHAREDLIBRARY) $(BUILD)/miniupnpc.pc
endif
.PHONY: install clean depend all check test everything \
installpythonmodule updateversion
all: $(LIBRARY) $(EXECUTABLES)
test: check
check: validateminixml validateminiwget validateupnpreplyparse \
validateportlistingparse validateigddescparse validateaddr_is_reserved
everything: all $(EXECUTABLES_ADDTESTS)
pythonmodule: $(LIBRARY) $(SRCDIR)/miniupnpcmodule.c setup.py
MAKE=$(MAKE) python setup.py build
touch $@
installpythonmodule: pythonmodule
MAKE=$(MAKE) python setup.py install
pythonmodule3: $(LIBRARY) $(SRCDIR)/miniupnpcmodule.c setup.py
MAKE=$(MAKE) python3 setup.py build
touch $@
installpythonmodule3: pythonmodule3
MAKE=$(MAKE) python3 setup.py install
validateminixml: $(BUILD)/minixmlvalid
@echo "minixml validation test"
./$<
touch $@
validateminiwget: testminiwget.sh $(BUILD)/testminiwget $(BUILD)/minihttptestserver
@echo "miniwget validation test"
./$<
touch $@
validateupnpreplyparse: testupnpreplyparse.sh $(BUILD)/testupnpreplyparse
@echo "upnpreplyparse validation test"
./$<
touch $@
validateportlistingparse: $(BUILD)/testportlistingparse
@echo "portlistingparse validation test"
./$<
touch $@
validateigddescparse: $(BUILD)/testigddescparse
@echo "igd desc parse validation test"
./$< testdesc/new_LiveBox_desc.xml testdesc/new_LiveBox_desc.values
./$< testdesc/linksys_WAG200G_desc.xml testdesc/linksys_WAG200G_desc.values
touch $@
validateaddr_is_reserved: $(BUILD)/testaddr_is_reserved
@echo "addr_is_reserved() validation test"
./$<
touch $@
clean:
$(RM) $(LIBRARY) $(SHAREDLIBRARY) $(EXECUTABLES) $(OBJS) $(BUILDINCLUDES)
$(RM) $(EXECUTABLES_ADDTESTS)
# clean python stuff
$(RM) pythonmodule pythonmodule3
$(RM) validateminixml validateminiwget validateupnpreplyparse
$(RM) validateigddescparse
$(RM) minihttptestserver
$(RM) testaddr_is_reserved
$(RM) -r build/ dist/
#python setup.py clean
# clean jnaerator stuff
$(RM) _jnaerator.* java/miniupnpc_$(OS).jar
distclean: clean
$(RM) $(JNAERATOR) java/*.jar java/*.class out.errors.txt
updateversion: include/miniupnpc.h
cp $< $<.bak
sed 's/\(.*MINIUPNPC_API_VERSION\s\+\)[0-9]\+/\1$(APIVERSION)/' < $<.bak > $<
install: updateversion $(FILESTOINSTALL)
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRINC)
$(INSTALL) -m 644 $(HEADERS) $(DESTDIR)$(INSTALLDIRINC)
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRLIB)
$(INSTALL) -m 644 $(LIBRARY) $(DESTDIR)$(INSTALLDIRLIB)
ifeq (, $(findstring amiga, $(OS)))
$(INSTALL) -m 644 $(SHAREDLIBRARY) $(DESTDIR)$(INSTALLDIRLIB)/$(SONAME)
ln -fs $(SONAME) $(DESTDIR)$(INSTALLDIRLIB)/$(notdir $(SHAREDLIBRARY))
$(INSTALL) -d $(DESTDIR)$(PKGCONFIGDIR)
$(INSTALL) -m 644 $(BUILD)/miniupnpc.pc $(DESTDIR)$(PKGCONFIGDIR)
endif
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRBIN)
ifneq (, $(findstring amiga, $(OS)))
$(INSTALL) -m 755 $(BUILD)/upnpc-static $(DESTDIR)$(INSTALLDIRBIN)/upnpc
$(INSTALL) -m 755 $(BUILD)/upnp-listdevices-static $(DESTDIR)$(INSTALLDIRBIN)/upnp-listdevices
else
$(INSTALL) -m 755 $(BUILD)/upnpc-shared $(DESTDIR)$(INSTALLDIRBIN)/upnpc
$(INSTALL) -m 755 $(BUILD)/upnp-listdevices-shared $(DESTDIR)$(INSTALLDIRBIN)/upnp-listdevices
endif
$(INSTALL) -m 755 external-ip.sh $(DESTDIR)$(INSTALLDIRBIN)/external-ip
ifeq (, $(findstring amiga, $(OS)))
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRMAN)/man3
$(INSTALL) -m 644 man3/miniupnpc.3 $(DESTDIR)$(INSTALLDIRMAN)/man3/miniupnpc.3
ifneq (, $(findstring linux, $(OS)))
gzip -f $(DESTDIR)$(INSTALLDIRMAN)/man3/miniupnpc.3
endif
endif
install-static: updateversion $(FILESTOINSTALL)
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRINC)
$(INSTALL) -m 644 $(HEADERS) $(DESTDIR)$(INSTALLDIRINC)
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRLIB)
$(INSTALL) -m 644 $(LIBRARY) $(DESTDIR)$(INSTALLDIRLIB)
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRBIN)
$(INSTALL) -m 755 external-ip.sh $(DESTDIR)$(INSTALLDIRBIN)/external-ip
cleaninstall:
$(RM) -r $(DESTDIR)$(INSTALLDIRINC)
$(RM) $(DESTDIR)$(INSTALLDIRLIB)/$(LIBRARY)
$(RM) $(DESTDIR)$(INSTALLDIRLIB)/$(SHAREDLIBRARY)
$(BUILD)/miniupnpc.pc: VERSION
@$(MKDIR) $(@D)
$(RM) $@
echo "prefix=$(INSTALLPREFIX)" >> $@
echo "exec_prefix=\$${prefix}" >> $@
echo "libdir=\$${exec_prefix}/$(LIBDIR)" >> $@
echo "includedir=\$${prefix}/include" >> $@
echo "" >> $@
echo "Name: miniUPnPc" >> $@
echo "Description: UPnP IGD client lightweight library" >> $@
echo "URL: https://miniupnp.tuxfamily.org/" >> $@
echo "Version: $(VERSION)" >> $@
echo "Libs: -L\$${libdir} -lminiupnpc" >> $@
echo "Cflags: -I\$${includedir}" >> $@
depend: $(DEPS)
$(LIBRARY): $(LIBOBJS)
ifneq (, $(findstring darwin, $(OS)))
$(LIBTOOL) -static -o $@ $?
else
$(AR) crs $@ $?
endif
$(SHAREDLIBRARY): $(LIBOBJS)
ifneq (, $(findstring darwin, $(OS)))
# $(CC) -dynamiclib $(LDFLAGS) -Wl,-install_name,$(SONAME) -o $@ $^
$(CC) -dynamiclib $(LDFLAGS) -Wl,-install_name,$(INSTALLDIRLIB)/$(SONAME) -o $@ $^
else
$(CC) -shared $(LDFLAGS) -Wl,-soname,$(SONAME) -o $@ $^
endif
$(BUILD)/%.o: $(SRCDIR)/%.c $(BUILD)/%.d
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
$(DEPS): $(BUILDINCLUDES)
$(BUILD)/%.d: $(SRCDIR)/%.c
@$(MKDIR) $(@D)
$(CC) $(CPPFLAGS) $(DEPFLAGS) -MT $@ -o $@ $<
$(BUILD)/upnpc-static: $(BUILD)/upnpc.o $(LIBRARY)
$(CC) $(LDFLAGS) -o $@ $^ $(LOADLIBES) $(LDLIBS)
$(BUILD)/upnpc-shared: $(BUILD)/upnpc.o $(SHAREDLIBRARY)
$(CC) $(LDFLAGS) -o $@ $^ $(LOADLIBES) $(LDLIBS)
$(BUILD)/upnp-listdevices-static: $(BUILD)/listdevices.o $(LIBRARY)
$(CC) $(LDFLAGS) -o $@ $^ $(LOADLIBES) $(LDLIBS)
$(BUILD)/upnp-listdevices-shared: $(BUILD)/listdevices.o $(SHAREDLIBRARY)
$(CC) $(LDFLAGS) -o $@ $^ $(LOADLIBES) $(LDLIBS)
$(BUILD)/testminixml: $(TESTMINIXMLOBJS)
$(BUILD)/testminiwget: $(TESTMINIWGETOBJS)
$(BUILD)/minixmlvalid: $(addprefix $(BUILD)/, minixml.o minixmlvalid.o)
$(BUILD)/testupnpreplyparse: $(TESTUPNPREPLYPARSE)
$(BUILD)/testigddescparse: $(TESTIGDDESCPARSE)
$(BUILD)/testportlistingparse: $(TESTPORTLISTINGPARSE)
$(BUILD)/testaddr_is_reserved: $(TESTADDR_IS_RESERVED)
$(BUILD)/miniupnpcstrings.h: miniupnpcstrings.h.in updateminiupnpcstrings.sh VERSION
@$(MKDIR) $(@D)
$(SH) updateminiupnpcstrings.sh $@ $<
# ftp tool supplied with OpenBSD can download files from http.
jnaerator-%.jar:
wget $(JNAERATORBASEURL)/$@ || \
curl -o $@ $(JNAERATORBASEURL)/$@ || \
ftp $(JNAERATORBASEURL)/$@
jar: $(SHAREDLIBRARY) $(JNAERATOR)
$(JAVA) -jar $(JNAERATOR) $(JNAERATORARGS) \
miniupnpc.h miniupnpc_declspec.h upnpcommands.h upnpreplyparse.h \
igd_desc_parse.h miniwget.h upnperrors.h $(SHAREDLIBRARY) \
-package fr.free.miniupnp -o . -jar java/miniupnpc_$(JARSUFFIX).jar -v
mvn_install:
mvn install:install-file -Dfile=java/miniupnpc_$(JARSUFFIX).jar \
-DgroupId=com.github \
-DartifactId=miniupnp \
-Dversion=$(VERSION) \
-Dpackaging=jar \
-Dclassifier=$(JARSUFFIX) \
-DgeneratePom=true \
-DcreateChecksum=true
# make .deb packages
deb: /usr/share/pyshared/stdeb all
(python setup.py --command-packages=stdeb.command bdist_deb)
# install .deb packages
ideb:
(sudo dpkg -i deb_dist/*.deb)
/usr/share/pyshared/stdeb: /usr/share/doc/python-all-dev
(sudo apt-get install python-stdeb)
/usr/share/doc/python-all-dev:
(sudo apt-get install python-all-dev)
minihttptestserver: minihttptestserver.o
print-%:
@echo "$* = $($*)"
ifneq ($(MAKECMDGOALS),clean)
-include $(DEPS)
endif
miniupnpc-2.2.6/include/igd_desc_parse.h 0100644 0001750 0000024 00000003135 12435327263 0017445 0 ustar 00nanard staff /* $Id: igd_desc_parse.h,v 1.12 2014/11/17 17:19:13 nanard Exp $ */
/* Project : miniupnp
* http://miniupnp.free.fr/
* Author : Thomas Bernard
* Copyright (c) 2005-2014 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
#ifndef IGD_DESC_PARSE_H_INCLUDED
#define IGD_DESC_PARSE_H_INCLUDED
/* Structure to store the result of the parsing of UPnP
* descriptions of Internet Gateway Devices */
#define MINIUPNPC_URL_MAXSIZE (128)
struct IGDdatas_service {
char controlurl[MINIUPNPC_URL_MAXSIZE];
char eventsuburl[MINIUPNPC_URL_MAXSIZE];
char scpdurl[MINIUPNPC_URL_MAXSIZE];
char servicetype[MINIUPNPC_URL_MAXSIZE];
/*char devicetype[MINIUPNPC_URL_MAXSIZE];*/
};
struct IGDdatas {
char cureltname[MINIUPNPC_URL_MAXSIZE];
char urlbase[MINIUPNPC_URL_MAXSIZE];
char presentationurl[MINIUPNPC_URL_MAXSIZE];
int level;
/*int state;*/
/* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */
struct IGDdatas_service CIF;
/* "urn:schemas-upnp-org:service:WANIPConnection:1"
* "urn:schemas-upnp-org:service:WANPPPConnection:1" */
struct IGDdatas_service first;
/* if both WANIPConnection and WANPPPConnection are present */
struct IGDdatas_service second;
/* "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1" */
struct IGDdatas_service IPv6FC;
/* tmp */
struct IGDdatas_service tmp;
};
void IGDstartelt(void *, const char *, int);
void IGDendelt(void *, const char *, int);
void IGDdata(void *, const char *, int);
#ifdef DEBUG
void printIGD(struct IGDdatas *);
#endif /* DEBUG */
#endif /* IGD_DESC_PARSE_H_INCLUDED */
miniupnpc-2.2.6/include/miniupnpc.h 0100644 0001750 0000024 00000012032 14545377536 0016524 0 ustar 00nanard staff /* $Id: miniupnpc.h,v 1.62 2023/06/11 23:25:46 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* Project: miniupnp
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
* Author: Thomas Bernard
* Copyright (c) 2005-2022 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef MINIUPNPC_H_INCLUDED
#define MINIUPNPC_H_INCLUDED
#include "miniupnpc_declspec.h"
#include "igd_desc_parse.h"
#include "upnpdev.h"
/* error codes : */
#define UPNPDISCOVER_SUCCESS (0)
#define UPNPDISCOVER_UNKNOWN_ERROR (-1)
#define UPNPDISCOVER_SOCKET_ERROR (-101)
#define UPNPDISCOVER_MEMORY_ERROR (-102)
/* versions : */
#define MINIUPNPC_VERSION "2.2.6"
#define MINIUPNPC_API_VERSION 17
/* Source port:
Using "1" as an alias for 1900 for backwards compatibility
(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" {
#endif
/* Structures definitions : */
struct UPNParg { const char * elt; const char * val; };
char *
simpleUPnPcommand(int, const char *, const char *,
const char *, struct UPNParg *,
int *);
/* upnpDiscover()
* discover UPnP devices on the network.
* The discovered devices are returned as a chained list.
* It is up to the caller to free the list with freeUPNPDevlist().
* delay (in millisecond) is the maximum time for waiting any device
* response.
* If available, device list will be obtained from MiniSSDPd.
* Default path for minissdpd socket will be used if minissdpdsock argument
* is NULL.
* If multicastif is not NULL, it will be used instead of the default
* multicast interface for sending SSDP discover packets.
* If localport is set to UPNP_LOCAL_PORT_SAME(1) SSDP packets will be sent
* from the source port 1900 (same as destination port), if set to
* UPNP_LOCAL_PORT_ANY(0) system assign a source port, any other value will
* be attempted as the source port.
* "searchalltypes" parameter is useful when searching several types,
* if 0, the discovery will stop with the first type returning results.
* TTL should default to 2. */
MINIUPNP_LIBSPEC struct UPNPDev *
upnpDiscover(int delay, const char * multicastif,
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 localport,
int ipv6, unsigned char ttl,
int * error);
MINIUPNP_LIBSPEC struct UPNPDev *
upnpDiscoverDevice(const char * device, int delay, const char * multicastif,
const char * minissdpdsock, int localport,
int ipv6, unsigned char ttl,
int * error);
MINIUPNP_LIBSPEC struct UPNPDev *
upnpDiscoverDevices(const char * const deviceTypes[],
int delay, const char * multicastif,
const char * minissdpdsock, int localport,
int ipv6, unsigned char ttl,
int * error,
int searchalltypes);
/* parserootdesc() :
* parse root XML description of a UPnP device and fill the IGDdatas
* structure. */
MINIUPNP_LIBSPEC void parserootdesc(const char *, int, struct IGDdatas *);
/* structure used to get fast access to urls
* controlURL: controlURL of the WANIPConnection
* ipcondescURL: url of the description of the WANIPConnection
* controlURL_CIF: controlURL of the WANCommonInterfaceConfig
* controlURL_6FC: controlURL of the WANIPv6FirewallControl
*/
struct UPNPUrls {
char * controlURL;
char * ipcondescURL;
char * controlURL_CIF;
char * controlURL_6FC;
char * rootdescURL;
};
/* UPNP_GetValidIGD() :
* return values :
* 0 = NO IGD found
* 1 = A valid connected IGD has been found
* 2 = A valid IGD has been found but it reported as
* 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
* passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
* free allocated memory.
*/
MINIUPNP_LIBSPEC int
UPNP_GetValidIGD(struct UPNPDev * devlist,
struct UPNPUrls * urls,
struct IGDdatas * data,
char * lanaddr, int lanaddrlen);
/* UPNP_GetIGDFromUrl()
* Used when skipping the discovery process.
* When succeding, urls, data, and lanaddr arguments are set.
* return value :
* 0 - Not ok
* 1 - OK */
MINIUPNP_LIBSPEC int
UPNP_GetIGDFromUrl(const char * rootdescurl,
struct UPNPUrls * urls,
struct IGDdatas * data,
char * lanaddr, int lanaddrlen);
MINIUPNP_LIBSPEC void
GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *,
const char *, unsigned int);
MINIUPNP_LIBSPEC void
FreeUPNPUrls(struct UPNPUrls *);
/* return 0 or 1 */
MINIUPNP_LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *);
#ifdef __cplusplus
}
#endif
#endif
miniupnpc-2.2.6/include/miniupnpc_declspec.h 0100644 0001750 0000024 00000001060 12553442422 0020345 0 ustar 00nanard staff #ifndef MINIUPNPC_DECLSPEC_H_INCLUDED
#define MINIUPNPC_DECLSPEC_H_INCLUDED
#if defined(_WIN32) && !defined(MINIUPNP_STATICLIB)
/* for windows dll */
#ifdef MINIUPNP_EXPORTS
#define MINIUPNP_LIBSPEC __declspec(dllexport)
#else
#define MINIUPNP_LIBSPEC __declspec(dllimport)
#endif
#else
#if defined(__GNUC__) && __GNUC__ >= 4
/* fix dynlib for OS X 10.9.2 and Apple LLVM version 5.0 */
#define MINIUPNP_LIBSPEC __attribute__ ((visibility ("default")))
#else
#define MINIUPNP_LIBSPEC
#endif
#endif
#endif /* MINIUPNPC_DECLSPEC_H_INCLUDED */
miniupnpc-2.2.6/include/miniupnpctypes.h 0100644 0001750 0000024 00000001242 14124702403 0017564 0 ustar 00nanard staff /* $Id: miniupnpctypes.h,v 1.3 2021/08/21 09:50:00 nanard Exp $ */
/* Miniupnp project : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org
* Author : Thomas Bernard
* Copyright (c) 2021 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided within this distribution */
#ifndef MINIUPNPCTYPES_H_INCLUDED
#define MINIUPNPCTYPES_H_INCLUDED
/* Use unsigned long long when available :
* strtoull is C99 */
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#define UNSIGNED_INTEGER unsigned long long
#define STRTOUI strtoull
#else
#define UNSIGNED_INTEGER unsigned int
#define STRTOUI strtoul
#endif
#endif
miniupnpc-2.2.6/include/miniwget.h 0100644 0001750 0000024 00000001262 13261650652 0016333 0 ustar 00nanard staff /* $Id: miniwget.h,v 1.13 2018/04/06 10:53:15 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005-2016 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
#ifndef MINIWGET_H_INCLUDED
#define MINIWGET_H_INCLUDED
#include "miniupnpc_declspec.h"
#ifdef __cplusplus
extern "C" {
#endif
MINIUPNP_LIBSPEC void * miniwget(const char *, int *, unsigned int, int *);
MINIUPNP_LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int, unsigned int, int *);
int parseURL(const char *, char *, unsigned short *, char * *, unsigned int *);
#ifdef __cplusplus
}
#endif
#endif
miniupnpc-2.2.6/include/portlistingparse.h 0100644 0001750 0000024 00000003446 12553444000 0020116 0 ustar 00nanard staff /* $Id: portlistingparse.h,v 1.11 2015/07/21 13:16:55 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2011-2015 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#ifndef PORTLISTINGPARSE_H_INCLUDED
#define PORTLISTINGPARSE_H_INCLUDED
#include "miniupnpc_declspec.h"
/* for the definition of UNSIGNED_INTEGER */
#include "miniupnpctypes.h"
#ifdef __cplusplus
extern "C" {
#endif
/* sample of PortMappingEntry :
202.233.2.1
2345
TCP
2345
192.168.1.137
1
dooom
345
*/
typedef enum { PortMappingEltNone,
PortMappingEntry, NewRemoteHost,
NewExternalPort, NewProtocol,
NewInternalPort, NewInternalClient,
NewEnabled, NewDescription,
NewLeaseTime } portMappingElt;
struct PortMapping {
struct PortMapping * l_next; /* list next element */
UNSIGNED_INTEGER leaseTime;
unsigned short externalPort;
unsigned short internalPort;
char remoteHost[64];
char internalClient[64];
char description[64];
char protocol[4];
unsigned char enabled;
};
struct PortMappingParserData {
struct PortMapping * l_head; /* list head */
portMappingElt curelt;
};
MINIUPNP_LIBSPEC void
ParsePortListing(const char * buffer, int bufsize,
struct PortMappingParserData * pdata);
MINIUPNP_LIBSPEC void
FreePortListing(struct PortMappingParserData * pdata);
#ifdef __cplusplus
}
#endif
#endif
miniupnpc-2.2.6/include/upnpcommands.h 0100644 0001750 0000024 00000032416 13430014533 0017207 0 ustar 00nanard staff /* $Id: upnpcommands.h,v 1.33 2019/02/10 12:29:25 nanard Exp $ */
/* Miniupnp project : http://miniupnp.free.fr/
* Author : Thomas Bernard
* Copyright (c) 2005-2018 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided within this distribution */
#ifndef UPNPCOMMANDS_H_INCLUDED
#define UPNPCOMMANDS_H_INCLUDED
#include "miniupnpc_declspec.h"
#include "miniupnpctypes.h"
/* MiniUPnPc return codes : */
#define UPNPCOMMAND_SUCCESS (0)
#define UPNPCOMMAND_UNKNOWN_ERROR (-1)
#define UPNPCOMMAND_INVALID_ARGS (-2)
#define UPNPCOMMAND_HTTP_ERROR (-3)
#define UPNPCOMMAND_INVALID_RESPONSE (-4)
#define UPNPCOMMAND_MEM_ALLOC_ERROR (-5)
#ifdef __cplusplus
extern "C" {
#endif
struct PortMappingParserData;
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalBytesSent(const char * controlURL,
const char * servicetype);
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalBytesReceived(const char * controlURL,
const char * servicetype);
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalPacketsSent(const char * controlURL,
const char * servicetype);
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalPacketsReceived(const char * controlURL,
const char * servicetype);
/* UPNP_GetStatusInfo()
* status and lastconnerror are 64 byte buffers
* Return values :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
* or a UPnP Error code */
MINIUPNP_LIBSPEC int
UPNP_GetStatusInfo(const char * controlURL,
const char * servicetype,
char * status,
unsigned int * uptime,
char * lastconnerror);
/* UPNP_GetConnectionTypeInfo()
* argument connectionType is a 64 character buffer
* Return Values :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
* or a UPnP Error code */
MINIUPNP_LIBSPEC int
UPNP_GetConnectionTypeInfo(const char * controlURL,
const char * servicetype,
char * connectionType);
/* UPNP_GetExternalIPAddress() call the corresponding UPNP method.
* if the third arg is not null the value is copied to it.
* at least 16 bytes must be available
*
* Return values :
* 0 : SUCCESS
* NON ZERO : ERROR Either an UPnP error code or an unknown error.
*
* possible UPnP Errors :
* 402 Invalid Args - See UPnP Device Architecture section on Control.
* 501 Action Failed - See UPnP Device Architecture section on Control. */
MINIUPNP_LIBSPEC int
UPNP_GetExternalIPAddress(const char * controlURL,
const char * servicetype,
char * extIpAdd);
/* UPNP_GetLinkLayerMaxBitRates()
* call WANCommonInterfaceConfig:1#GetCommonLinkProperties
*
* return values :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
* or a UPnP Error Code. */
MINIUPNP_LIBSPEC int
UPNP_GetLinkLayerMaxBitRates(const char* controlURL,
const char* servicetype,
unsigned int * bitrateDown,
unsigned int * bitrateUp);
/* UPNP_AddPortMapping()
* if desc is NULL, it will be defaulted to "libminiupnpc"
* remoteHost is usually NULL because IGD don't support it.
*
* Return values :
* 0 : SUCCESS
* NON ZERO : ERROR. Either an UPnP error code or an unknown error.
*
* List of possible UPnP errors for AddPortMapping :
* errorCode errorDescription (short) - Description (long)
* 402 Invalid Args - See UPnP Device Architecture section on Control.
* 501 Action Failed - See UPnP Device Architecture section on Control.
* 606 Action not authorized - The action requested REQUIRES authorization and
* the sender was not authorized.
* 715 WildCardNotPermittedInSrcIP - The source IP address cannot be
* wild-carded
* 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded
* 718 ConflictInMappingEntry - The port mapping entry specified conflicts
* with a mapping assigned previously to another client
* 724 SamePortValuesRequired - Internal and External port values
* must be the same
* 725 OnlyPermanentLeasesSupported - The NAT implementation only supports
* permanent lease times on port mappings
* 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard
* and cannot be a specific IP address or DNS name
* 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and
* cannot be a specific port value
* 728 NoPortMapsAvailable - There are not enough free ports available to
* complete port mapping.
* 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed
* due to conflict with other mechanisms.
* 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded
*/
MINIUPNP_LIBSPEC int
UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
const char * extPort,
const char * inPort,
const char * inClient,
const char * desc,
const char * proto,
const char * remoteHost,
const char * leaseDuration);
/* UPNP_AddAnyPortMapping()
* if desc is NULL, it will be defaulted to "libminiupnpc"
* remoteHost is usually NULL because IGD don't support it.
*
* Return values :
* 0 : SUCCESS
* NON ZERO : ERROR. Either an UPnP error code or an unknown error.
*
* List of possible UPnP errors for AddPortMapping :
* errorCode errorDescription (short) - Description (long)
* 402 Invalid Args - See UPnP Device Architecture section on Control.
* 501 Action Failed - See UPnP Device Architecture section on Control.
* 606 Action not authorized - The action requested REQUIRES authorization and
* the sender was not authorized.
* 715 WildCardNotPermittedInSrcIP - The source IP address cannot be
* wild-carded
* 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded
* 728 NoPortMapsAvailable - There are not enough free ports available to
* complete port mapping.
* 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed
* due to conflict with other mechanisms.
* 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded
*/
MINIUPNP_LIBSPEC int
UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype,
const char * extPort,
const char * inPort,
const char * inClient,
const char * desc,
const char * proto,
const char * remoteHost,
const char * leaseDuration,
char * reservedPort);
/* UPNP_DeletePortMapping()
* Use same argument values as what was used for AddPortMapping().
* remoteHost is usually NULL because IGD don't support it.
* Return Values :
* 0 : SUCCESS
* NON ZERO : error. Either an UPnP error code or an undefined error.
*
* List of possible UPnP errors for DeletePortMapping :
* 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 */
MINIUPNP_LIBSPEC int
UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
const char * extPort, const char * proto,
const char * remoteHost);
/* UPNP_DeletePortRangeMapping()
* Use same argument values as what was used for AddPortMapping().
* remoteHost is usually NULL because IGD don't support it.
* Return Values :
* 0 : SUCCESS
* NON ZERO : error. Either an UPnP error code or an undefined error.
*
* List of possible UPnP errors for DeletePortMapping :
* 606 Action not authorized - The action requested REQUIRES authorization
* and the sender was not authorized.
* 730 PortMappingNotFound - This error message is returned if no port
* mapping is found in the specified range.
* 733 InconsistentParameters - NewStartPort and NewEndPort values are not consistent. */
MINIUPNP_LIBSPEC int
UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype,
const char * extPortStart, const char * extPortEnd,
const char * proto,
const char * manage);
/* UPNP_GetPortMappingNumberOfEntries()
* not supported by all routers */
MINIUPNP_LIBSPEC int
UPNP_GetPortMappingNumberOfEntries(const char * controlURL,
const char * servicetype,
unsigned int * numEntries);
/* UPNP_GetSpecificPortMappingEntry()
* retrieves an existing port mapping
* params :
* in extPort
* in proto
* in remoteHost
* out intClient (16 bytes)
* out intPort (6 bytes)
* out desc (80 bytes)
* out enabled (4 bytes)
* out leaseDuration (16 bytes)
*
* return value :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
* 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.
*/
MINIUPNP_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,
char * enabled,
char * leaseDuration);
/* UPNP_GetGenericPortMappingEntry()
* params :
* in index
* out extPort (6 bytes)
* out intClient (16 bytes)
* out intPort (6 bytes)
* out protocol (4 bytes)
* out desc (80 bytes)
* out enabled (4 bytes)
* out rHost (64 bytes)
* out duration (16 bytes)
*
* return value :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
* or a UPnP Error Code.
*
* 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
*/
MINIUPNP_LIBSPEC int
UPNP_GetGenericPortMappingEntry(const char * controlURL,
const char * servicetype,
const char * index,
char * extPort,
char * intClient,
char * intPort,
char * protocol,
char * desc,
char * enabled,
char * rHost,
char * duration);
/* UPNP_GetListOfPortMappings() Available in IGD v2
*
*
* Possible UPNP Error codes :
* 606 Action not Authorized
* 730 PortMappingNotFound - no port mapping is found in the specified range.
* 733 InconsistantParameters - NewStartPort and NewEndPort values are not
* consistent.
*/
MINIUPNP_LIBSPEC int
UPNP_GetListOfPortMappings(const char * controlURL,
const char * servicetype,
const char * startPort,
const char * endPort,
const char * protocol,
const char * numberOfPorts,
struct PortMappingParserData * data);
/* IGD:2, functions for service WANIPv6FirewallControl:1 */
MINIUPNP_LIBSPEC int
UPNP_GetFirewallStatus(const char * controlURL,
const char * servicetype,
int * firewallEnabled,
int * inboundPinholeAllowed);
MINIUPNP_LIBSPEC int
UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype,
const char * remoteHost,
const char * remotePort,
const char * intClient,
const char * intPort,
const char * proto,
int * opTimeout);
MINIUPNP_LIBSPEC int
UPNP_AddPinhole(const char * controlURL, const char * servicetype,
const char * remoteHost,
const char * remotePort,
const char * intClient,
const char * intPort,
const char * proto,
const char * leaseTime,
char * uniqueID);
MINIUPNP_LIBSPEC int
UPNP_UpdatePinhole(const char * controlURL, const char * servicetype,
const char * uniqueID,
const char * leaseTime);
MINIUPNP_LIBSPEC int
UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID);
MINIUPNP_LIBSPEC int
UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype,
const char * uniqueID, int * isWorking);
MINIUPNP_LIBSPEC int
UPNP_GetPinholePackets(const char * controlURL, const char * servicetype,
const char * uniqueID, int * packets);
#ifdef __cplusplus
}
#endif
#endif
miniupnpc-2.2.6/include/upnpdev.h 0100644 0001750 0000024 00000001666 14124702404 0016171 0 ustar 00nanard staff /* $Id: upnpdev.h,v 1.4 2021/08/21 09:45:01 nanard Exp $ */
/* Project : miniupnp
* Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
* Author : Thomas BERNARD
* copyright (c) 2005-2021 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENSE file. */
#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;
char * usn;
unsigned int scope_id;
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* C99 flexible array member */
char buffer[];
#elif defined(__GNUC__)
char buffer[0];
#else
/* Fallback to a hack */
char buffer[1];
#endif
};
/* freeUPNPDevlist()
* free list returned by upnpDiscover() */
MINIUPNP_LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist);
#ifdef __cplusplus
}
#endif
#endif /* UPNPDEV_H_INCLUDED */
miniupnpc-2.2.6/include/upnperrors.h 0100644 0001750 0000024 00000001160 12553444000 0016713 0 ustar 00nanard staff /* $Id: upnperrors.h,v 1.6 2015/07/21 13:16:55 nanard Exp $ */
/* (c) 2007-2015 Thomas Bernard
* All rights reserved.
* MiniUPnP Project.
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* This software is subjet to the conditions detailed in the
* provided LICENCE file. */
#ifndef UPNPERRORS_H_INCLUDED
#define UPNPERRORS_H_INCLUDED
#include "miniupnpc_declspec.h"
#ifdef __cplusplus
extern "C" {
#endif
/* strupnperror()
* Return a string description of the UPnP error code
* or NULL for undefinded errors */
MINIUPNP_LIBSPEC const char * strupnperror(int err);
#ifdef __cplusplus
}
#endif
#endif
miniupnpc-2.2.6/include/upnpreplyparse.h 0100644 0001750 0000024 00000002521 12423472602 0017574 0 ustar 00nanard staff /* $Id: upnpreplyparse.h,v 1.19 2014/10/27 16:33:19 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#ifndef UPNPREPLYPARSE_H_INCLUDED
#define UPNPREPLYPARSE_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
struct NameValue {
struct NameValue * l_next;
char name[64];
char value[128];
};
struct NameValueParserData {
struct NameValue * l_head;
char curelt[64];
char * portListing;
int portListingLength;
int topelt;
const char * cdata;
int cdatalen;
};
/* ParseNameValue() */
void
ParseNameValue(const char * buffer, int bufsize,
struct NameValueParserData * data);
/* ClearNameValueList() */
void
ClearNameValueList(struct NameValueParserData * pdata);
/* GetValueFromNameValueList() */
char *
GetValueFromNameValueList(struct NameValueParserData * pdata,
const char * Name);
#if 0
/* GetValueFromNameValueListIgnoreNS() */
char *
GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
const char * Name);
#endif
/* DisplayNameValueList() */
#ifdef DEBUG
void
DisplayNameValueList(char * buffer, int bufsize);
#endif
#ifdef __cplusplus
}
#endif
#endif
miniupnpc-2.2.6/src/igd_desc_parse.c 0100644 0001750 0000024 00000011016 12576535225 0016606 0 ustar 00nanard staff /* $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-2015 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
#include "igd_desc_parse.h"
#include
#include
/* Start element handler :
* update nesting level counter and copy element name */
void IGDstartelt(void * d, const char * name, int l)
{
struct IGDdatas * datas = (struct IGDdatas *)d;
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) ) {
datas->tmp.controlurl[0] = '\0';
datas->tmp.eventsuburl[0] = '\0';
datas->tmp.scpdurl[0] = '\0';
datas->tmp.servicetype[0] = '\0';
}
}
#define COMPARE(str, cstr) (0==memcmp(str, cstr, sizeof(cstr) - 1))
/* End element handler :
* update nesting level counter and update parser state if
* service element is parsed */
void IGDendelt(void * d, const char * name, int l)
{
struct IGDdatas * datas = (struct IGDdatas *)d;
datas->level--;
/*printf("endelt %2d %.*s\n", datas->level, l, name);*/
if( (l==7) && !memcmp(name, "service", l) )
{
if(COMPARE(datas->tmp.servicetype,
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:")) {
memcpy(&datas->CIF, &datas->tmp, sizeof(struct IGDdatas_service));
} else if(COMPARE(datas->tmp.servicetype,
"urn:schemas-upnp-org:service:WANIPv6FirewallControl:")) {
memcpy(&datas->IPv6FC, &datas->tmp, sizeof(struct IGDdatas_service));
} else if(COMPARE(datas->tmp.servicetype,
"urn:schemas-upnp-org:service:WANIPConnection:")
|| COMPARE(datas->tmp.servicetype,
"urn:schemas-upnp-org:service:WANPPPConnection:") ) {
if(datas->first.servicetype[0] == '\0') {
memcpy(&datas->first, &datas->tmp, sizeof(struct IGDdatas_service));
} else {
memcpy(&datas->second, &datas->tmp, sizeof(struct IGDdatas_service));
}
}
}
}
/* Data handler :
* copy data depending on the current element name and state */
void IGDdata(void * d, const char * data, int l)
{
struct IGDdatas * datas = (struct IGDdatas *)d;
char * dstmember = 0;
/*printf("%2d %s : %.*s\n",
datas->level, datas->cureltname, l, data); */
if( !strcmp(datas->cureltname, "URLBase") )
dstmember = datas->urlbase;
else if( !strcmp(datas->cureltname, "presentationURL") )
dstmember = datas->presentationurl;
else if( !strcmp(datas->cureltname, "serviceType") )
dstmember = datas->tmp.servicetype;
else if( !strcmp(datas->cureltname, "controlURL") )
dstmember = datas->tmp.controlurl;
else if( !strcmp(datas->cureltname, "eventSubURL") )
dstmember = datas->tmp.eventsuburl;
else if( !strcmp(datas->cureltname, "SCPDURL") )
dstmember = datas->tmp.scpdurl;
/* else if( !strcmp(datas->cureltname, "deviceType") )
dstmember = datas->devicetype_tmp;*/
if(dstmember)
{
if(l>=MINIUPNPC_URL_MAXSIZE)
l = MINIUPNPC_URL_MAXSIZE-1;
memcpy(dstmember, data, l);
dstmember[l] = '\0';
}
}
#ifdef DEBUG
void printIGD(struct IGDdatas * d)
{
printf("urlbase = '%s'\n", d->urlbase);
printf("WAN Device (Common interface config) :\n");
/*printf(" deviceType = '%s'\n", d->CIF.devicetype);*/
printf(" serviceType = '%s'\n", d->CIF.servicetype);
printf(" controlURL = '%s'\n", d->CIF.controlurl);
printf(" eventSubURL = '%s'\n", d->CIF.eventsuburl);
printf(" SCPDURL = '%s'\n", d->CIF.scpdurl);
printf("primary WAN Connection Device (IP or PPP Connection):\n");
/*printf(" deviceType = '%s'\n", d->first.devicetype);*/
printf(" servicetype = '%s'\n", d->first.servicetype);
printf(" controlURL = '%s'\n", d->first.controlurl);
printf(" eventSubURL = '%s'\n", d->first.eventsuburl);
printf(" SCPDURL = '%s'\n", d->first.scpdurl);
printf("secondary WAN Connection Device (IP or PPP Connection):\n");
/*printf(" deviceType = '%s'\n", d->second.devicetype);*/
printf(" servicetype = '%s'\n", d->second.servicetype);
printf(" controlURL = '%s'\n", d->second.controlurl);
printf(" eventSubURL = '%s'\n", d->second.eventsuburl);
printf(" SCPDURL = '%s'\n", d->second.scpdurl);
printf("WAN IPv6 Firewall Control :\n");
/*printf(" deviceType = '%s'\n", d->IPv6FC.devicetype);*/
printf(" servicetype = '%s'\n", d->IPv6FC.servicetype);
printf(" controlURL = '%s'\n", d->IPv6FC.controlurl);
printf(" eventSubURL = '%s'\n", d->IPv6FC.eventsuburl);
printf(" SCPDURL = '%s'\n", d->IPv6FC.scpdurl);
}
#endif /* DEBUG */
miniupnpc-2.2.6/src/miniwget.c 0100644 0001750 0000024 00000040762 14545377501 0015507 0 ustar 00nanard staff /* $Id: miniwget.c,v 1.85 2023/06/15 21:47:50 nanard Exp $ */
/* Project : miniupnp
* Website : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
* Author : Thomas Bernard
* Copyright (c) 2005-2023 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
#include
#include
#include
#include
#ifdef _WIN32
#include
#include
#include
#define MAXHOSTNAMELEN 64
#include "win32_snprintf.h"
#define socklen_t int
#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 */
#else /* #ifdef _WIN32 */
#include
#include
#if defined(__amigaos__) && !defined(__amigaos4__)
#define socklen_t int
#else /* #if defined(__amigaos__) && !defined(__amigaos4__) */
#include
#endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */
#include
#include
#include
#include
#include
#define closesocket close
#include
#endif /* #else _WIN32 */
#ifdef __GNU__
#define MAXHOSTNAMELEN 64
#endif /* __GNU__ */
#ifndef MIN
#define MIN(x,y) (((x)<(y))?(x):(y))
#endif /* MIN */
#include "miniupnpcstrings.h"
#include "miniwget.h"
#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.
* return a pointer to the content buffer, which length is saved
* to the length parameter.
*/
void *
getHTTPResponse(SOCKET s, int * size, int * status_code)
{
char buf[2048];
int n;
int endofheaders = 0;
int chunked = 0;
int content_length = -1;
unsigned int chunksize = 0;
unsigned int bytestocopy = 0;
/* buffers : */
char * header_buf;
unsigned int header_buf_len = 2048;
unsigned int header_buf_used = 0;
char * content_buf;
unsigned int content_buf_len = 2048;
unsigned int content_buf_used = 0;
char chunksize_buf[32];
unsigned int chunksize_buf_index;
#ifdef DEBUG
char * reason_phrase = NULL;
int reason_phrase_len = 0;
#endif
if(status_code) *status_code = -1;
header_buf = malloc(header_buf_len);
if(header_buf == NULL)
{
#ifdef DEBUG
fprintf(stderr, "%s: Memory allocation error\n", "getHTTPResponse");
#endif /* DEBUG */
*size = -1;
return NULL;
}
content_buf = malloc(content_buf_len);
if(content_buf == NULL)
{
free(header_buf);
#ifdef DEBUG
fprintf(stderr, "%s: Memory allocation error\n", "getHTTPResponse");
#endif /* DEBUG */
*size = -1;
return NULL;
}
chunksize_buf[0] = '\0';
chunksize_buf_index = 0;
while((n = receivedata(s, buf, sizeof(buf), 5000, NULL)) > 0)
{
if(endofheaders == 0)
{
int i;
int linestart=0;
int colon=0;
int valuestart=0;
if(header_buf_used + n > header_buf_len) {
char * tmp = realloc(header_buf, header_buf_used + n);
if(tmp == NULL) {
/* memory allocation error */
free(header_buf);
free(content_buf);
*size = -1;
return NULL;
}
header_buf = tmp;
header_buf_len = header_buf_used + n;
}
memcpy(header_buf + header_buf_used, buf, n);
header_buf_used += n;
/* search for CR LF CR LF (end of headers)
* recognize also LF LF */
i = 0;
while(i < ((int)header_buf_used-1) && (endofheaders == 0)) {
if(header_buf[i] == '\r') {
i++;
if(header_buf[i] == '\n') {
i++;
if(i < (int)header_buf_used && header_buf[i] == '\r') {
i++;
if(i < (int)header_buf_used && header_buf[i] == '\n') {
endofheaders = i+1;
}
}
}
} else if(header_buf[i] == '\n') {
i++;
if(header_buf[i] == '\n') {
endofheaders = i+1;
}
}
i++;
}
if(endofheaders == 0)
continue;
/* parse header lines */
for(i = 0; i < endofheaders - 1; i++) {
if(linestart > 0 && colon <= linestart && header_buf[i]==':')
{
colon = i;
while(i < (endofheaders-1)
&& (header_buf[i+1] == ' ' || header_buf[i+1] == '\t'))
i++;
valuestart = i + 1;
}
/* detecting end of line */
else if(header_buf[i]=='\r' || header_buf[i]=='\n')
{
if(linestart == 0 && status_code)
{
/* Status line
* HTTP-Version SP Status-Code SP Reason-Phrase CRLF */
int sp;
for(sp = 0; sp < i - 1; sp++)
if(header_buf[sp] == ' ')
{
if(*status_code < 0)
{
if (header_buf[sp+1] >= '1' && header_buf[sp+1] <= '9')
*status_code = atoi(header_buf + sp + 1);
}
else
{
#ifdef DEBUG
reason_phrase = header_buf + sp + 1;
reason_phrase_len = i - sp - 1;
#endif
break;
}
}
#ifdef DEBUG
printf("HTTP status code = %d, Reason phrase = %.*s\n",
*status_code, reason_phrase_len, reason_phrase);
#endif
}
else if(colon > linestart && valuestart > colon)
{
#ifdef DEBUG
printf("header='%.*s', value='%.*s'\n",
colon-linestart, header_buf+linestart,
i-valuestart, header_buf+valuestart);
#endif
if(0==strncasecmp(header_buf+linestart, "content-length", colon-linestart))
{
content_length = atoi(header_buf+valuestart);
#ifdef DEBUG
printf("Content-Length: %d\n", content_length);
#endif
}
else if(0==strncasecmp(header_buf+linestart, "transfer-encoding", colon-linestart)
&& 0==strncasecmp(header_buf+valuestart, "chunked", 7))
{
#ifdef DEBUG
printf("chunked transfer-encoding!\n");
#endif
chunked = 1;
}
}
while((i < (int)header_buf_used) && (header_buf[i]=='\r' || header_buf[i] == '\n'))
i++;
linestart = i;
colon = linestart;
valuestart = 0;
}
}
/* copy the remaining of the received data back to buf */
n = header_buf_used - endofheaders;
memcpy(buf, header_buf + endofheaders, n);
/* if(headers) */
}
/* if we get there, endofheaders != 0.
* In the other case, there was a continue above */
/* content */
if(chunked)
{
int i = 0;
while(i < n)
{
if(chunksize == 0)
{
/* reading chunk size */
if(chunksize_buf_index == 0) {
/* skipping any leading CR LF */
if(buf[i] == '\r') i++;
if(i= '0'
&& chunksize_buf[j] <= '9')
chunksize = (chunksize << 4) + (chunksize_buf[j] - '0');
else
chunksize = (chunksize << 4) + ((chunksize_buf[j] | 32) - 'a' + 10);
}
chunksize_buf[0] = '\0';
chunksize_buf_index = 0;
i++;
} else {
/* not finished to get chunksize */
continue;
}
#ifdef DEBUG
printf("chunksize = %u (%x)\n", chunksize, chunksize);
#endif
if(chunksize == 0)
{
#ifdef DEBUG
printf("end of HTTP content - %d %d\n", i, n);
/*printf("'%.*s'\n", n-i, buf+i);*/
#endif
goto end_of_stream;
}
}
/* it is guaranteed that (n >= i) */
bytestocopy = (chunksize < (unsigned int)(n - i))?chunksize:(unsigned int)(n - i);
if((content_buf_used + bytestocopy) > content_buf_len)
{
char * tmp;
if((content_length >= 0) && ((unsigned int)content_length >= (content_buf_used + bytestocopy))) {
content_buf_len = content_length;
} else {
content_buf_len = content_buf_used + bytestocopy;
}
tmp = realloc(content_buf, content_buf_len);
if(tmp == NULL) {
/* memory allocation error */
free(content_buf);
free(header_buf);
*size = -1;
return NULL;
}
content_buf = tmp;
}
memcpy(content_buf + content_buf_used, buf + i, bytestocopy);
content_buf_used += bytestocopy;
i += bytestocopy;
chunksize -= bytestocopy;
}
}
else
{
/* not chunked */
if(content_length > 0
&& (content_buf_used + n) > (unsigned int)content_length) {
/* skipping additional bytes */
n = content_length - content_buf_used;
}
if(content_buf_used + n > content_buf_len)
{
char * tmp;
if(content_length >= 0
&& (unsigned int)content_length >= (content_buf_used + n)) {
content_buf_len = content_length;
} else {
content_buf_len = content_buf_used + n;
}
tmp = realloc(content_buf, content_buf_len);
if(tmp == NULL) {
/* memory allocation error */
free(content_buf);
free(header_buf);
*size = -1;
return NULL;
}
content_buf = tmp;
}
memcpy(content_buf + content_buf_used, buf, n);
content_buf_used += n;
}
/* use the Content-Length header value if available */
if(content_length > 0 && content_buf_used >= (unsigned int)content_length)
{
#ifdef DEBUG
printf("End of HTTP content\n");
#endif
break;
}
}
end_of_stream:
free(header_buf);
*size = content_buf_used;
if(content_buf_used == 0)
{
free(content_buf);
content_buf = NULL;
}
return content_buf;
}
/* miniwget3() :
* do all the work.
* Return NULL if something failed. */
static void *
miniwget3(const char * host,
unsigned short port, const char * path,
int * size, char * addr_str, int addr_str_len,
const char * httpversion, unsigned int scope_id,
int * status_code)
{
char buf[2048];
SOCKET s;
int n;
int len;
int sent;
void * content;
*size = 0;
s = connecthostport(host, port, scope_id);
if(ISINVALID(s))
return NULL;
/* get address for caller ! */
if(addr_str)
{
struct sockaddr_storage saddr;
socklen_t saddrlen;
saddrlen = sizeof(saddr);
if(getsockname(s, (struct sockaddr *)&saddr, &saddrlen) < 0)
{
perror("getsockname");
}
else
{
#if defined(__amigaos__) && !defined(__amigaos4__)
/* using INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD);
* But his function make a string with the port : nn.nn.nn.nn:port */
/* if(WSAAddressToStringA((SOCKADDR *)&saddr, sizeof(saddr),
NULL, addr_str, (DWORD *)&addr_str_len))
{
printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError());
}*/
/* the following code is only compatible with ip v4 addresses */
strncpy(addr_str, inet_ntoa(((struct sockaddr_in *)&saddr)->sin_addr), addr_str_len);
#else
#if 0
if(saddr.sa_family == AF_INET6) {
inet_ntop(AF_INET6,
&(((struct sockaddr_in6 *)&saddr)->sin6_addr),
addr_str, addr_str_len);
} else {
inet_ntop(AF_INET,
&(((struct sockaddr_in *)&saddr)->sin_addr),
addr_str, addr_str_len);
}
#endif
/* getnameinfo return ip v6 address with the scope identifier
* such as : 2a01:e35:8b2b:7330::%4281128194 */
n = getnameinfo((const struct sockaddr *)&saddr, saddrlen,
addr_str, addr_str_len,
NULL, 0,
NI_NUMERICHOST | NI_NUMERICSERV);
if(n != 0) {
#ifdef _WIN32
fprintf(stderr, "getnameinfo() failed : %d\n", n);
#else
fprintf(stderr, "getnameinfo() failed : %s\n", gai_strerror(n));
#endif
}
#endif
}
#ifdef DEBUG
printf("address miniwget : %s\n", addr_str);
#endif
}
len = snprintf(buf, sizeof(buf),
"GET %s HTTP/%s\r\n"
"Host: %s:%d\r\n"
"Connection: Close\r\n"
"User-Agent: " OS_STRING " " UPNP_VERSION_STRING " MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
"\r\n",
path, httpversion, host, port);
if ((unsigned int)len >= sizeof(buf))
{
closesocket(s);
return NULL;
}
sent = 0;
/* sending the HTTP request */
while(sent < len)
{
n = send(s, buf+sent, len-sent, 0);
if(n < 0)
{
perror("send");
closesocket(s);
return NULL;
}
else
{
sent += n;
}
}
content = getHTTPResponse(s, size, status_code);
closesocket(s);
return content;
}
/* miniwget2() :
* Call miniwget3(); retry with HTTP/1.1 if 1.0 fails. */
static void *
miniwget2(const char * host,
unsigned short port, const char * path,
int * size, char * addr_str, int addr_str_len,
unsigned int scope_id, int * status_code)
{
char * respbuffer;
#if 1
respbuffer = miniwget3(host, port, path, size,
addr_str, addr_str_len, "1.1",
scope_id, status_code);
#else
respbuffer = miniwget3(host, port, path, size,
addr_str, addr_str_len, "1.0",
scope_id, status_code);
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",
scope_id, status_code);
}
#endif
return respbuffer;
}
/* parseURL()
* arguments :
* url : source string not modified
* hostname : hostname destination string (size of MAXHOSTNAMELEN+1)
* port : port (destination)
* path : pointer to the path part of the URL
*
* Return values :
* 0 - Failure
* 1 - Success */
int
parseURL(const char * url,
char * hostname, unsigned short * port,
char * * path, unsigned int * scope_id)
{
char * p1, *p2, *p3;
if(!url)
return 0;
p1 = strstr(url, "://");
if(!p1)
return 0;
p1 += 3;
if( (url[0]!='h') || (url[1]!='t')
||(url[2]!='t') || (url[3]!='p'))
return 0;
memset(hostname, 0, MAXHOSTNAMELEN + 1);
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];
size_t 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)
{
p2++;
strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1)));
if(*p2 == ':')
{
*port = 0;
p2++;
while( (*p2 >= '0') && (*p2 <= '9'))
{
*port *= 10;
*port += (unsigned short)(*p2 - '0');
p2++;
}
}
else
{
*port = 80;
}
*path = p3;
return 1;
}
}
p2 = strchr(p1, ':');
p3 = strchr(p1, '/');
if(!p3)
return 0;
if(!p2 || (p2>p3))
{
strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p3-p1)));
*port = 80;
}
else
{
strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1)));
*port = 0;
p2++;
while( (*p2 >= '0') && (*p2 <= '9'))
{
*port *= 10;
*port += (unsigned short)(*p2 - '0');
p2++;
}
}
*path = p3;
return 1;
}
void *
miniwget(const char * url, int * size,
unsigned int scope_id, int * status_code)
{
unsigned short port;
char * path;
/* protocol://host:port/chemin */
char hostname[MAXHOSTNAMELEN+1];
*size = 0;
if(!parseURL(url, hostname, &port, &path, &scope_id))
return NULL;
#ifdef DEBUG
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, scope_id, status_code);
}
void *
miniwget_getaddr(const char * url, int * size,
char * addr, int addrlen, unsigned int scope_id,
int * status_code)
{
unsigned short port;
char * path;
/* protocol://host:port/path */
char hostname[MAXHOSTNAMELEN+1];
*size = 0;
if(addr)
addr[0] = '\0';
if(!parseURL(url, hostname, &port, &path, &scope_id))
return NULL;
#ifdef DEBUG
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, scope_id, status_code);
}
miniupnpc-2.2.6/src/minixml.c 0100644 0001750 0000024 00000013232 13213741334 0015317 0 ustar 00nanard staff /* $Id: minixml.c,v 1.12 2017/12/12 11:17:40 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* 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-2017, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include
#include "minixml.h"
/* parseatt : used to parse the argument list
* return 0 (false) in case of success and -1 (true) if the end
* of the xmlbuffer is reached. */
static int parseatt(struct xmlparser * p)
{
const char * attname;
int attnamelen;
const char * attvalue;
int attvaluelen;
while(p->xml < p->xmlend)
{
if(*p->xml=='/' || *p->xml=='>')
return 0;
if( !IS_WHITE_SPACE(*p->xml) )
{
char sep;
attname = p->xml;
attnamelen = 0;
while(*p->xml!='=' && !IS_WHITE_SPACE(*p->xml) )
{
attnamelen++; p->xml++;
if(p->xml >= p->xmlend)
return -1;
}
while(*(p->xml++) != '=')
{
if(p->xml >= p->xmlend)
return -1;
}
while(IS_WHITE_SPACE(*p->xml))
{
p->xml++;
if(p->xml >= p->xmlend)
return -1;
}
sep = *p->xml;
if(sep=='\'' || sep=='\"')
{
p->xml++;
if(p->xml >= p->xmlend)
return -1;
attvalue = p->xml;
attvaluelen = 0;
while(*p->xml != sep)
{
attvaluelen++; p->xml++;
if(p->xml >= p->xmlend)
return -1;
}
}
else
{
attvalue = p->xml;
attvaluelen = 0;
while( !IS_WHITE_SPACE(*p->xml)
&& *p->xml != '>' && *p->xml != '/')
{
attvaluelen++; p->xml++;
if(p->xml >= p->xmlend)
return -1;
}
}
/*printf("%.*s='%.*s'\n",
attnamelen, attname, attvaluelen, attvalue);*/
if(p->attfunc)
p->attfunc(p->data, attname, attnamelen, attvalue, attvaluelen);
}
p->xml++;
}
return -1;
}
/* parseelt parse the xml stream and
* call the callback functions when needed... */
static void parseelt(struct xmlparser * p)
{
int i;
const char * elementname;
while(p->xml < (p->xmlend - 1))
{
if((p->xml + 4) <= p->xmlend && (0 == 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)
&& (*p->xml!='>') && (*p->xml!='/')
)
{
i++; p->xml++;
if (p->xml >= p->xmlend)
return;
/* to ignore namespace : */
if(*p->xml==':')
{
i = 0;
elementname = ++p->xml;
}
}
if(i>0)
{
if(p->starteltfunc)
p->starteltfunc(p->data, elementname, i);
if(parseatt(p))
return;
if(*p->xml!='/')
{
const char * data;
i = 0; data = ++p->xml;
if (p->xml >= p->xmlend)
return;
while( IS_WHITE_SPACE(*p->xml) )
{
i++; p->xml++;
if (p->xml >= p->xmlend)
return;
}
/* CDATA are at least 9 + 3 characters long : */
if((p->xmlend >= (p->xml + (9 + 3))) && (memcmp(p->xml, "xml += 9;
data = p->xml;
i = 0;
while(memcmp(p->xml, "]]>", 3) != 0)
{
i++; p->xml++;
if ((p->xml + 3) >= p->xmlend)
return;
}
if(i>0 && p->datafunc)
p->datafunc(p->data, data, i);
while(*p->xml!='<')
{
p->xml++;
if (p->xml >= p->xmlend)
return;
}
}
else
{
while(*p->xml!='<')
{
i++; p->xml++;
if ((p->xml + 1) >= p->xmlend)
return;
}
if(i>0 && p->datafunc && *(p->xml + 1) == '/')
p->datafunc(p->data, data, i);
}
}
}
else if(*p->xml == '/')
{
i = 0; elementname = ++p->xml;
if (p->xml >= p->xmlend)
return;
while((*p->xml != '>'))
{
i++; p->xml++;
if (p->xml >= p->xmlend)
return;
}
if(p->endeltfunc)
p->endeltfunc(p->data, elementname, i);
p->xml++;
}
}
else
{
p->xml++;
}
}
}
/* the parser must be initialized before calling this function */
void parsexml(struct xmlparser * parser)
{
parser->xml = parser->xmlstart;
parser->xmlend = parser->xmlstart + parser->xmlsize;
parseelt(parser);
}
miniupnpc-2.2.6/src/minixml.h 0100644 0001750 0000024 00000002233 13430014533 0015316 0 ustar 00nanard staff /* $Id: minixml.h,v 1.8 2019/02/10 12:29:25 nanard Exp $ */
/* minimal xml parser
*
* Project : miniupnp
* Website : http://miniupnp.free.fr/
* 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 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,
* the function is not called */
struct xmlparser {
const char *xmlstart;
const char *xmlend;
const char *xml; /* pointer to current character */
int xmlsize;
void * data;
void (*starteltfunc) (void *, const char *, int);
void (*endeltfunc) (void *, const char *, int);
void (*datafunc) (void *, const char *, int);
void (*attfunc) (void *, const char *, int, const char *, int);
};
/* parsexml()
* the xmlparser structure must be initialized before the call
* the following structure members have to be initialized :
* xmlstart, xmlsize, data, *func
* xml is for internal usage, xmlend is computed automatically */
void parsexml(struct xmlparser *);
#endif
miniupnpc-2.2.6/src/upnpc.c 0100644 0001750 0000024 00000071066 14545377501 0015012 0 ustar 00nanard staff /* $Id: upnpc.c,v 1.137 2024/01/04 00:42:50 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005-2024 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
#include
#include
#include
#include
#ifdef _WIN32
#include
#include "win32_snprintf.h"
#else
/* for IPPROTO_TCP / IPPROTO_UDP */
#include
#endif
#include
#include "miniwget.h"
#include "miniupnpc.h"
#include "upnpcommands.h"
#include "portlistingparse.h"
#include "upnperrors.h"
#include "miniupnpcstrings.h"
/* protofix() checks if protocol is "UDP" or "TCP"
* returns NULL if not */
const char * protofix(const char * proto)
{
static const char proto_tcp[4] = { 'T', 'C', 'P', 0};
static const char proto_udp[4] = { 'U', 'D', 'P', 0};
int i, b;
for(i=0, b=1; i<4; i++)
b = b && ( (proto[i] == proto_tcp[i])
|| (proto[i] == (proto_tcp[i] | 32)) );
if(b)
return proto_tcp;
for(i=0, b=1; i<4; i++)
b = b && ( (proto[i] == proto_udp[i])
|| (proto[i] == (proto_udp[i] | 32)) );
if(b)
return proto_udp;
return 0;
}
/* is_int() checks if parameter is an integer or not
* 1 for integer
* 0 for not an integer */
int is_int(char const* s)
{
if(s == NULL)
return 0;
while(*s) {
/* #define isdigit(c) ((c) >= '0' && (c) <= '9') */
if(!isdigit(*s))
return 0;
s++;
}
return 1;
}
static void DisplayInfos(struct UPNPUrls * urls,
struct IGDdatas * data)
{
char externalIPAddress[40];
char connectionType[64];
char status[64];
char lastconnerr[64];
unsigned int uptime = 0;
unsigned int brUp, brDown;
time_t timenow, timestarted;
int r;
if(UPNP_GetConnectionTypeInfo(urls->controlURL,
data->first.servicetype,
connectionType) != UPNPCOMMAND_SUCCESS)
printf("GetConnectionTypeInfo failed.\n");
else
printf("Connection Type : %s\n", connectionType);
if(UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype,
status, &uptime, lastconnerr) != UPNPCOMMAND_SUCCESS)
printf("GetStatusInfo failed.\n");
else
printf("Status : %s, uptime=%us, LastConnectionError : %s\n",
status, uptime, lastconnerr);
if(uptime > 0) {
timenow = time(NULL);
timestarted = timenow - uptime;
printf(" Time started : %s", ctime(×tarted));
}
if(UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, data->CIF.servicetype,
&brDown, &brUp) != UPNPCOMMAND_SUCCESS) {
printf("GetLinkLayerMaxBitRates failed.\n");
} else {
printf("MaxBitRateDown : %u bps", brDown);
if(brDown >= 1000000) {
printf(" (%u.%u Mbps)", brDown / 1000000, (brDown / 100000) % 10);
} else if(brDown >= 1000) {
printf(" (%u Kbps)", brDown / 1000);
}
printf(" MaxBitRateUp %u bps", brUp);
if(brUp >= 1000000) {
printf(" (%u.%u Mbps)", brUp / 1000000, (brUp / 100000) % 10);
} else if(brUp >= 1000) {
printf(" (%u Kbps)", brUp / 1000);
}
printf("\n");
}
r = UPNP_GetExternalIPAddress(urls->controlURL,
data->first.servicetype,
externalIPAddress);
if(r != UPNPCOMMAND_SUCCESS) {
printf("GetExternalIPAddress failed. (errorcode=%d)\n", r);
} else if(!externalIPAddress[0]) {
printf("GetExternalIPAddress failed. (empty string)\n");
} else {
printf("ExternalIPAddress = %s\n", externalIPAddress);
}
}
static void GetConnectionStatus(struct UPNPUrls * urls,
struct IGDdatas * data)
{
unsigned int bytessent, bytesreceived, packetsreceived, packetssent;
DisplayInfos(urls, data);
bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype);
bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype);
packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype);
packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype);
printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived);
printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived);
}
static void ListRedirections(struct UPNPUrls * urls,
struct IGDdatas * data)
{
int r;
unsigned short i = 0;
char index[6];
char intClient[40];
char intPort[6];
char extPort[6];
char protocol[4];
char desc[80];
char enabled[6];
char rHost[64];
char duration[16];
/*unsigned int num=0;
UPNP_GetPortMappingNumberOfEntries(urls->controlURL, data->servicetype, &num);
printf("PortMappingNumberOfEntries : %u\n", num);*/
printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n");
do {
snprintf(index, 6, "%hu", i);
rHost[0] = '\0'; enabled[0] = '\0';
duration[0] = '\0'; desc[0] = '\0';
extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0';
r = UPNP_GetGenericPortMappingEntry(urls->controlURL,
data->first.servicetype,
index,
extPort, intClient, intPort,
protocol, desc, enabled,
rHost, duration);
if(r==0)
/*
printf("%02hu - %s %s->%s:%s\tenabled=%s leaseDuration=%s\n"
" desc='%s' rHost='%s'\n",
i, protocol, extPort, intClient, intPort,
enabled, duration,
desc, rHost);
*/
printf("%2hu %s %5s->%s:%-5s '%s' '%s' %s\n",
i, protocol, extPort, intClient, intPort,
desc, rHost, duration);
else
printf("GetGenericPortMappingEntry() returned %d (%s)\n",
r, strupnperror(r));
} while(r == 0 && i++ < 65535);
}
static void NewListRedirections(struct UPNPUrls * urls,
struct IGDdatas * data)
{
int r;
int i = 0;
struct PortMappingParserData pdata;
struct PortMapping * pm;
memset(&pdata, 0, sizeof(struct PortMappingParserData));
r = UPNP_GetListOfPortMappings(urls->controlURL,
data->first.servicetype,
"1",
"65535",
"TCP",
"1000",
&pdata);
if(r == UPNPCOMMAND_SUCCESS)
{
printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n");
for(pm = pdata.l_head; pm != NULL; pm = pm->l_next)
{
printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n",
i, pm->protocol, pm->externalPort, pm->internalClient,
pm->internalPort,
pm->description, pm->remoteHost,
(unsigned)pm->leaseTime);
i++;
}
FreePortListing(&pdata);
}
else
{
printf("GetListOfPortMappings() returned %d (%s)\n",
r, strupnperror(r));
}
r = UPNP_GetListOfPortMappings(urls->controlURL,
data->first.servicetype,
"1",
"65535",
"UDP",
"1000",
&pdata);
if(r == UPNPCOMMAND_SUCCESS)
{
for(pm = pdata.l_head; pm != NULL; pm = pm->l_next)
{
printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n",
i, pm->protocol, pm->externalPort, pm->internalClient,
pm->internalPort,
pm->description, pm->remoteHost,
(unsigned)pm->leaseTime);
i++;
}
FreePortListing(&pdata);
}
else
{
printf("GetListOfPortMappings() returned %d (%s)\n",
r, strupnperror(r));
}
}
/* Test function
* 1 - get connection type
* 2 - get extenal ip address
* 3 - Add port mapping
* 4 - get this port mapping from the IGD */
static int SetRedirectAndTest(struct UPNPUrls * urls,
struct IGDdatas * data,
const char * iaddr,
const char * iport,
const char * eport,
const char * proto,
const char * leaseDuration,
const char * remoteHost,
const char * description,
int addAny)
{
char externalIPAddress[40];
char intClient[40];
char intPort[6];
char reservedPort[6];
char duration[16];
int r;
if(!iaddr || !iport || !eport || !proto)
{
fprintf(stderr, "Wrong arguments\n");
return -1;
}
proto = protofix(proto);
if(!proto)
{
fprintf(stderr, "invalid protocol\n");
return -1;
}
r = UPNP_GetExternalIPAddress(urls->controlURL,
data->first.servicetype,
externalIPAddress);
if(r!=UPNPCOMMAND_SUCCESS)
printf("GetExternalIPAddress failed.\n");
else
printf("ExternalIPAddress = %s\n", externalIPAddress);
if (addAny) {
r = UPNP_AddAnyPortMapping(urls->controlURL, data->first.servicetype,
eport, iport, iaddr, description,
proto, remoteHost, leaseDuration, reservedPort);
if(r==UPNPCOMMAND_SUCCESS)
eport = reservedPort;
else
printf("AddAnyPortMapping(%s, %s, %s) failed with code %d (%s)\n",
eport, iport, iaddr, r, strupnperror(r));
} else {
r = UPNP_AddPortMapping(urls->controlURL, data->first.servicetype,
eport, iport, iaddr, description,
proto, remoteHost, leaseDuration);
if(r!=UPNPCOMMAND_SUCCESS) {
printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
eport, iport, iaddr, r, strupnperror(r));
return -2;
}
}
r = UPNP_GetSpecificPortMappingEntry(urls->controlURL,
data->first.servicetype,
eport, proto, remoteHost,
intClient, intPort, NULL/*desc*/,
NULL/*enabled*/, duration);
if(r!=UPNPCOMMAND_SUCCESS) {
printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n",
r, strupnperror(r));
return -2;
} else {
printf("InternalIP:Port = %s:%s\n", intClient, intPort);
printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n",
externalIPAddress, eport, proto, intClient, intPort, duration);
}
return 0;
}
static int
RemoveRedirect(struct UPNPUrls * urls,
struct IGDdatas * data,
const char * eport,
const char * proto,
const char * remoteHost)
{
int r;
if(!proto || !eport)
{
fprintf(stderr, "invalid arguments\n");
return -1;
}
proto = protofix(proto);
if(!proto)
{
fprintf(stderr, "protocol invalid\n");
return -1;
}
r = UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, remoteHost);
if(r!=UPNPCOMMAND_SUCCESS) {
printf("UPNP_DeletePortMapping() failed with code : %d\n", r);
return -2;
}else {
printf("UPNP_DeletePortMapping() returned : %d\n", r);
}
return 0;
}
static int
RemoveRedirectRange(struct UPNPUrls * urls,
struct IGDdatas * data,
const char * ePortStart, char const * ePortEnd,
const char * proto, const char * manage)
{
int r;
if (!manage)
manage = "0";
if(!proto || !ePortStart || !ePortEnd)
{
fprintf(stderr, "invalid arguments\n");
return -1;
}
proto = protofix(proto);
if(!proto)
{
fprintf(stderr, "protocol invalid\n");
return -1;
}
r = UPNP_DeletePortMappingRange(urls->controlURL, data->first.servicetype, ePortStart, ePortEnd, proto, manage);
if(r!=UPNPCOMMAND_SUCCESS) {
printf("UPNP_DeletePortMappingRange() failed with code : %d\n", r);
return -2;
}else {
printf("UPNP_DeletePortMappingRange() returned : %d\n", r);
}
return 0;
}
/* IGD:2, functions for service WANIPv6FirewallControl:1 */
static void GetFirewallStatus(struct UPNPUrls * urls, struct IGDdatas * data)
{
unsigned int bytessent, bytesreceived, packetsreceived, packetssent;
int firewallEnabled = 0, inboundPinholeAllowed = 0;
UPNP_GetFirewallStatus(urls->controlURL_6FC, data->IPv6FC.servicetype, &firewallEnabled, &inboundPinholeAllowed);
printf("FirewallEnabled: %d & Inbound Pinhole Allowed: %d\n", firewallEnabled, inboundPinholeAllowed);
printf("GetFirewallStatus:\n Firewall Enabled: %s\n Inbound Pinhole Allowed: %s\n", (firewallEnabled)? "Yes":"No", (inboundPinholeAllowed)? "Yes":"No");
bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype);
bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype);
packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype);
packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype);
printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived);
printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived);
}
/* Test function
* 1 - Add pinhole
* 2 - Check if pinhole is working from the IGD side */
static void SetPinholeAndTest(struct UPNPUrls * urls, struct IGDdatas * data,
const char * remoteaddr, const char * eport,
const char * intaddr, const char * iport,
const char * proto, const char * lease_time)
{
char uniqueID[8];
/*int isWorking = 0;*/
int r;
char proto_tmp[8];
if(!intaddr || !remoteaddr || !iport || !eport || !proto || !lease_time)
{
fprintf(stderr, "Wrong arguments\n");
return;
}
if(atoi(proto) == 0)
{
const char * protocol;
protocol = protofix(proto);
if(protocol && (strcmp("TCP", protocol) == 0))
{
snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_TCP);
proto = proto_tmp;
}
else if(protocol && (strcmp("UDP", protocol) == 0))
{
snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_UDP);
proto = proto_tmp;
}
else
{
fprintf(stderr, "invalid protocol\n");
return;
}
}
r = UPNP_AddPinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, lease_time, uniqueID);
if(r!=UPNPCOMMAND_SUCCESS)
printf("AddPinhole([%s]:%s -> [%s]:%s) failed with code %d (%s)\n",
remoteaddr, eport, intaddr, iport, r, strupnperror(r));
else
{
printf("AddPinhole: ([%s]:%s -> [%s]:%s) / Pinhole ID = %s\n",
remoteaddr, eport, intaddr, iport, uniqueID);
/*r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->servicetype_6FC, uniqueID, &isWorking);
if(r!=UPNPCOMMAND_SUCCESS)
printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r));
printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");*/
}
}
/* Test function
* 1 - Check if pinhole is working from the IGD side
* 2 - Update pinhole */
static void GetPinholeAndUpdate(struct UPNPUrls * urls, struct IGDdatas * data,
const char * uniqueID, const char * lease_time)
{
int isWorking = 0;
int r;
if(!uniqueID || !lease_time)
{
fprintf(stderr, "Wrong arguments\n");
return;
}
/* CheckPinholeWorking is an Optional Action, error 602 should be
* returned if it is not implemented */
r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking);
if(r==UPNPCOMMAND_SUCCESS)
printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");
else
printf("CheckPinholeWorking(%s) failed with code %d (%s)\n", uniqueID, r, strupnperror(r));
/* 702 FirewallDisabled Firewall is disabled and this action is disabled
* 703 InboundPinholeNotAllowed Creation of inbound pinholes by UPnP CPs
* are not allowed and this action is disabled
* 704 NoSuchEntry There is no pinhole with the specified UniqueID.
* 709 NoTrafficReceived No traffic corresponding to this pinhole has
* been received by the gateway. */
if(isWorking || (r!=702 && r!=703 && r!=704))
{
r = UPNP_UpdatePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, lease_time);
printf("UpdatePinhole: Pinhole ID = %s with Lease Time: %s\n", uniqueID, lease_time);
if(r!=UPNPCOMMAND_SUCCESS)
printf("UpdatePinhole: ID (%s) failed with code %d (%s)\n", uniqueID, r, strupnperror(r));
}
}
/* Test function
* Get pinhole timeout
*/
static void GetPinholeOutboundTimeout(struct UPNPUrls * urls, struct IGDdatas * data,
const char * remoteaddr, const char * eport,
const char * intaddr, const char * iport,
const char * proto)
{
int timeout = 0;
int r;
if(!intaddr || !remoteaddr || !iport || !eport || !proto)
{
fprintf(stderr, "Wrong arguments\n");
return;
}
r = UPNP_GetOutboundPinholeTimeout(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, &timeout);
if(r!=UPNPCOMMAND_SUCCESS)
printf("GetOutboundPinholeTimeout([%s]:%s -> [%s]:%s) failed with code %d (%s)\n",
intaddr, iport, remoteaddr, eport, r, strupnperror(r));
else
printf("GetOutboundPinholeTimeout: ([%s]:%s -> [%s]:%s) / Timeout = %d\n", intaddr, iport, remoteaddr, eport, timeout);
}
static void
GetPinholePackets(struct UPNPUrls * urls,
struct IGDdatas * data, const char * uniqueID)
{
int r, pinholePackets = 0;
if(!uniqueID)
{
fprintf(stderr, "invalid arguments\n");
return;
}
r = UPNP_GetPinholePackets(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &pinholePackets);
if(r!=UPNPCOMMAND_SUCCESS)
printf("GetPinholePackets() failed with code %d (%s)\n", r, strupnperror(r));
else
printf("GetPinholePackets: Pinhole ID = %s / PinholePackets = %d\n", uniqueID, pinholePackets);
}
static void
CheckPinhole(struct UPNPUrls * urls,
struct IGDdatas * data, const char * uniqueID)
{
int r, isWorking = 0;
if(!uniqueID)
{
fprintf(stderr, "invalid arguments\n");
return;
}
r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking);
if(r!=UPNPCOMMAND_SUCCESS)
printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r));
else
printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");
}
static void
RemovePinhole(struct UPNPUrls * urls,
struct IGDdatas * data, const char * uniqueID)
{
int r;
if(!uniqueID)
{
fprintf(stderr, "invalid arguments\n");
return;
}
r = UPNP_DeletePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID);
printf("UPNP_DeletePinhole() returned : %d\n", r);
}
/* sample upnp client program */
int main(int argc, char ** argv)
{
char command = 0;
char ** commandargv = 0;
int commandargc = 0;
struct UPNPDev * devlist = 0;
char lanaddr[64] = "unset"; /* my ip address on the LAN */
int i;
const char * rootdescurl = 0;
const char * multicastif = 0;
const char * minissdpdpath = 0;
int localport = UPNP_LOCAL_PORT_ANY;
int retcode = 0;
int error = 0;
int ipv6 = 0;
int ignore = 0;
unsigned char ttl = 2; /* defaulting to 2 */
const char * description = 0;
#ifdef _WIN32
WSADATA wsaData;
int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if(nResult != NO_ERROR)
{
fprintf(stderr, "WSAStartup() failed.\n");
return -1;
}
#endif
printf("upnpc : miniupnpc library test client, version %s.\n", MINIUPNPC_VERSION_STRING);
printf(" (c) 2005-2024 Thomas Bernard.\n");
printf("Go to http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/\n"
"for more information.\n");
/* command line processing */
for(i=1; i65535 ||
(localport >1 && localport < 1024))
{
fprintf(stderr, "Invalid localport '%s'\n", argv[i]);
localport = UPNP_LOCAL_PORT_ANY;
break;
}
}
else if(argv[i][1] == 'p')
minissdpdpath = argv[++i];
else if(argv[i][1] == '6')
ipv6 = 1;
else if(argv[i][1] == 'e')
description = argv[++i];
else if(argv[i][1] == 't')
ttl = (unsigned char)atoi(argv[++i]);
else if(argv[i][1] == 'i')
ignore = 1;
else
{
command = argv[i][1];
i++;
commandargv = argv + i;
commandargc = argc - i;
break;
}
}
else
{
fprintf(stderr, "option '%s' invalid\n", argv[i]);
}
}
if(!command
|| (command == 'a' && commandargc<4)
|| (command == 'd' && argc<2)
|| (command == 'r' && argc<2)
|| (command == 'A' && commandargc<6)
|| (command == 'U' && commandargc<2)
|| (command == 'D' && commandargc<1))
{
fprintf(stderr, "Usage :\t%s [options] -a ip port external_port protocol [duration] [remote host]\n\t\tAdd port mapping\n", argv[0]);
fprintf(stderr, " \t%s [options] -r port1 [external_port1] protocol1 [port2 [external_port2] protocol2] [...]\n\t\tAdd multiple port mappings to the current host\n", argv[0]);
fprintf(stderr, " \t%s [options] -d external_port protocol [remote host]\n\t\tDelete port redirection\n", argv[0]);
fprintf(stderr, " \t%s [options] -s\n\t\tGet Connection status\n", argv[0]);
fprintf(stderr, " \t%s [options] -l\n\t\tList redirections\n", argv[0]);
fprintf(stderr, " \t%s [options] -L\n\t\tList redirections (using GetListOfPortMappings (for IGD:2 only)\n", argv[0]);
fprintf(stderr, " \t%s [options] -n ip port external_port protocol [duration] [remote host]\n\t\tAdd (any) port mapping allowing IGD to use alternative external_port (for IGD:2 only)\n", argv[0]);
fprintf(stderr, " \t%s [options] -N external_port_start external_port_end protocol [manage]\n\t\tDelete range of port mappings (for IGD:2 only)\n", argv[0]);
fprintf(stderr, " \t%s [options] -A remote_ip remote_port internal_ip internal_port protocol lease_time\n\t\tAdd Pinhole (for IGD:2 only)\n", argv[0]);
fprintf(stderr, " \t%s [options] -U uniqueID new_lease_time\n\t\tUpdate Pinhole (for IGD:2 only)\n", argv[0]);
fprintf(stderr, " \t%s [options] -C uniqueID\n\t\tCheck if Pinhole is Working (for IGD:2 only)\n", argv[0]);
fprintf(stderr, " \t%s [options] -K uniqueID\n\t\tGet Number of packets going through the rule (for IGD:2 only)\n", argv[0]);
fprintf(stderr, " \t%s [options] -D uniqueID\n\t\tDelete Pinhole (for IGD:2 only)\n", argv[0]);
fprintf(stderr, " \t%s [options] -S\n\t\tGet Firewall status (for IGD:2 only)\n", argv[0]);
fprintf(stderr, " \t%s [options] -G remote_ip remote_port internal_ip internal_port protocol\n\t\tGet Outbound Pinhole Timeout (for IGD:2 only)\n", argv[0]);
fprintf(stderr, " \t%s [options] -P\n\t\tGet Presentation URL\n", argv[0]);
fprintf(stderr, "\nprotocol is UDP or TCP\n");
fprintf(stderr, "@ can be used in option -a, -n, -A and -G to represent local LAN address.\n");
fprintf(stderr, "Options:\n");
fprintf(stderr, " -e description : set description for port mapping.\n");
fprintf(stderr, " -6 : use IPv6 instead of IPv4.\n");
fprintf(stderr, " -u URL : bypass discovery process by providing the XML root description URL.\n");
fprintf(stderr, " -m address/interface : provide IPv4 address or interface name (IPv4 or IPv6) 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");
fprintf(stderr, " -i : ignore errors and try to use also disconnected IGD or non-IGD device.\n");
return 1;
}
if( rootdescurl
|| (devlist = upnpDiscover(2000, multicastif, minissdpdpath,
localport, ipv6, ttl, &error)))
{
struct UPNPDev * device;
struct UPNPUrls urls;
struct IGDdatas data;
if(devlist)
{
printf("List of UPNP devices found on the network :\n");
for(device = devlist; device; device = device->pNext)
{
printf(" desc: %s\n st: %s\n\n",
device->descURL, device->st);
}
}
else if(!rootdescurl)
{
printf("upnpDiscover() error code=%d\n", error);
}
i = 1;
if( (rootdescurl && UPNP_GetIGDFromUrl(rootdescurl, &urls, &data, lanaddr, sizeof(lanaddr)))
|| (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr))))
{
switch(i) {
case 1:
printf("Found valid IGD : %s\n", urls.controlURL);
break;
case 2:
printf("Found a (not connected?) IGD : %s\n", urls.controlURL);
if (ignore) printf("Trying to continue anyway\n");
break;
case 3:
printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL);
if (ignore) printf("Trying to continue anyway\n");
break;
default:
printf("Found device (igd ?) : %s\n", urls.controlURL);
if (ignore) printf("Trying to continue anyway\n");
}
if(i==1 || ignore) {
printf("Local LAN ip address : %s\n", lanaddr);
#if 0
printf("getting \"%s\"\n", urls.ipcondescURL);
descXML = miniwget(urls.ipcondescURL, &descXMLsize);
if(descXML)
{
/*fwrite(descXML, 1, descXMLsize, stdout);*/
free(descXML); descXML = NULL;
}
#endif
/* replace '@' with the local LAN ip address */
if ((command == 'a' || command == 'n') && 0 == strcmp(commandargv[0], "@"))
commandargv[0] = lanaddr;
else if ((command == 'A' || command == 'G') && 0 == strcmp(commandargv[2], "@"))
commandargv[2] = lanaddr;
switch(command)
{
case 'l':
DisplayInfos(&urls, &data);
ListRedirections(&urls, &data);
break;
case 'L':
NewListRedirections(&urls, &data);
break;
case 'a':
if (SetRedirectAndTest(&urls, &data,
commandargv[0], commandargv[1],
commandargv[2], commandargv[3],
(commandargc > 4) && is_int(commandargv[4]) ? commandargv[4] : "0",
(commandargc > 4) && !is_int(commandargv[4]) ? commandargv[4] : (commandargc > 5) ? commandargv[5] : NULL,
description, 0) < 0)
retcode = 2;
break;
case 'd':
if (RemoveRedirect(&urls, &data, commandargv[0], commandargv[1],
commandargc > 2 ? commandargv[2] : NULL) < 0)
retcode = 2;
break;
case 'n': /* aNy */
if (SetRedirectAndTest(&urls, &data,
commandargv[0], commandargv[1],
commandargv[2], commandargv[3],
(commandargc > 4) && is_int(commandargv[4]) ? commandargv[4] : "0",
(commandargc > 4) && !is_int(commandargv[4]) ? commandargv[4] : (commandargc > 5) ? commandargv[5] : NULL,
description, 1) < 0)
retcode = 2;
break;
case 'N':
if (commandargc < 3)
fprintf(stderr, "too few arguments\n");
if (RemoveRedirectRange(&urls, &data, commandargv[0], commandargv[1], commandargv[2],
commandargc > 3 ? commandargv[3] : NULL) < 0)
retcode = 2;
break;
case 's':
GetConnectionStatus(&urls, &data);
break;
case 'r':
i = 0;
while(i */
if (SetRedirectAndTest(&urls, &data,
lanaddr, commandargv[i],
commandargv[i+1], commandargv[i+2], "0", NULL,
description, 0) < 0)
retcode = 2;
i+=3; /* 3 parameters parsed */
} else {
/* 2nd parameter not an integer : */
if (SetRedirectAndTest(&urls, &data,
lanaddr, commandargv[i],
commandargv[i], commandargv[i+1], "0", NULL,
description, 0) < 0)
retcode = 2;
i+=2; /* 2 parameters parsed */
}
}
break;
case 'A':
SetPinholeAndTest(&urls, &data,
commandargv[0], commandargv[1],
commandargv[2], commandargv[3],
commandargv[4], commandargv[5]);
break;
case 'U':
GetPinholeAndUpdate(&urls, &data,
commandargv[0], commandargv[1]);
break;
case 'C':
for(i=0; i