Merge branch 'next' into delfile2

This commit is contained in:
Lactozilla 2024-01-13 04:00:31 -03:00
commit e0afa3cfa1
247 changed files with 15973 additions and 7586 deletions

View file

@ -5,13 +5,8 @@ jobs:
docker:
- image: cimg/base:current
environment:
CC: ccache gcc -m32
PKG_CONFIG_LIBDIR: /usr/lib/i386-linux-gnu/pkgconfig
LIBGME_CFLAGS: -I/usr/include
LIBGME_LDFLAGS: -lgme
CC: ccache gcc
CCACHE_COMPRESS: true
WFLAGS: -Wno-unsuffixed-float-constants
GCC81: true
#- image: ubuntu:trusty
# environment:
# CC: ccache gcc -m32
@ -23,16 +18,11 @@ jobs:
# GCC48: true
resource_class: large
steps:
- run:
name: Add i386 arch
command: sudo dpkg --add-architecture i386
- run:
name: Add STJr PPA
command: |
sudo apt-get -qq update
sudo apt-get -qq -y install dirmngr
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 0B1702D71499D9C25F986507F240F4449D3B0EC6
echo "deb http://ppa.launchpad.net/stjr/srb2/ubuntu trusty main" | sudo tee -a /etc/apt/sources.list
sudo apt-get -qq install apt-utils
- run:
name: Make APT cache folder
command: mkdir -p /home/circleci/.cache/apt/archives/partial
@ -49,11 +39,8 @@ jobs:
keys:
- v1-SRB2-APT
- run:
name: Uninstall amd64 SDK
command: sudo apt-get -o Dir::Cache="/home/circleci/.cache/apt" -qq -y --no-install-recommends remove libcurl4-openssl-dev:amd64
- run:
name: Install i386 SDK
command: sudo apt-get -o Dir::Cache="/home/circleci/.cache/apt" -qq -y --no-install-recommends install git build-essential libpng-dev:i386 libsdl2-mixer-dev:i386 libgme-dev:i386 libcurl4-openssl-dev:i386 libopenmpt-dev:i386 gettext ccache wget gcc-multilib upx openssh-client
name: Install SDK
command: sudo apt-get -o Dir::Cache="/home/circleci/.cache/apt" -qq -y --no-install-recommends install git build-essential libpng-dev libsdl2-mixer-dev libgme-dev libcurl4-openssl-dev libopenmpt-dev libminiupnpc-dev gettext ccache wget gcc-multilib upx openssh-client
- run:
name: make md5sum
command: sudo find /home/circleci/.cache/apt/archives -type f -print0 | sort -z | sudo xargs -r0 md5sum > /home/circleci/.cache/apt_archives.md5
@ -62,28 +49,19 @@ jobs:
paths:
- /home/circleci/.cache/apt
- checkout
- run:
name: Compile without network support
command: make -C src LINUX=1 ERRORMODE=1 -k NONET=1 -j4
- run:
name: wipe build
command: make -C src LINUX=1 cleandep
- run:
name: rebuild depend
command: make -C src LINUX=1 clean
- run:
name: make master depend file
command: find make/linux/SDL/deps/ -type f -print0 | sort -z | xargs -r0 cat > make/linux/SDL.deps
command: find make/linux64/SDL/deps/ -type f -print0 | sort -z | xargs -r0 cat > make/linux64/SDL.deps
- restore_cache:
keys:
- v1-SRB2-{{ .Branch }}-{{ checksum "make/linux/SDL.deps" }}
- v1-SRB2-{{ .Branch }}-{{ checksum "make/linux64/SDL.deps" }}
- run:
name: Compile
command: make -C src LINUX=1 ERRORMODE=1 -k -j4
command: make -C src LINUX64=1 ERRORMODE=1 -k -j4
- store_artifacts:
path: /home/circleci/SRB2/bin/
destination: bin
- save_cache:
key: v1-SRB2-{{ .Branch }}-{{ checksum "make/linux/SDL.deps" }}
key: v1-SRB2-{{ .Branch }}-{{ checksum "make/linux64/SDL.deps" }}
paths:
- /home/circleci/.ccache

1
.gitattributes vendored
View file

@ -10,6 +10,7 @@
/src/Make*.cfg text=auto
/src/CMakeLists.txt text=auto
*.mk -whitespace text=auto
/comptime.sh text eol=lf
# Windows EOL
*.cs -crlf -whitespace
*.bat -crlf -whitespace

View file

@ -3,7 +3,7 @@ variables:
GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/$CI_PROJECT_PATH
default:
image: debian:stable-slim
image: git.do.srb2.org:5050/stjr/srb2ci/srb2ci:stable
cache:
- key: ccache-$CI_PROJECT_PATH_SLUG-$CI_JOB_NAME_SLUG
@ -19,6 +19,11 @@ default:
- apt-cache
unprotect: true
- key: apk-$CI_JOB_IMAGE
paths:
- apk-cache
unprotect: true
before_script:
- - |
# debconf
@ -167,6 +172,10 @@ Debian testing GCC:
allow_failure: true
artifacts:
paths:
- "bin/"
- "src/comptime.h"
expose_as: "testing-gcc"
name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-testing-gcc"
variables:
@ -185,7 +194,7 @@ Debian testing GCC:
- - |
# apt_development
echo -e "\e[0Ksection_start:`date +%s`:apt_development[collapsed=true]\r\e[0KInstalling development packages"
- apt-get install libsdl2-mixer-dev libpng-dev libcurl4-openssl-dev libgme-dev libopenmpt-dev
- apt-get install libsdl2-mixer-dev libpng-dev libcurl4-openssl-dev libgme-dev libopenmpt-dev libminiupnpc-dev
- |
# apt_development
echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K"
@ -261,7 +270,7 @@ Debian stable:amd64:
- - |
# apt_development
echo -e "\e[0Ksection_start:`date +%s`:apt_development[collapsed=true]\r\e[0KInstalling development packages"
- apt-get install libsdl2-mixer-dev:amd64 libpng-dev:amd64 libcurl4-openssl-dev:amd64 libgme-dev:amd64 libopenmpt-dev:amd64
- apt-get install libsdl2-mixer-dev:amd64 libpng-dev:amd64 libcurl4-openssl-dev:amd64 libgme-dev:amd64 libopenmpt-dev:amd64 libminiupnpc-dev:amd64
- |
# apt_development
echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K"
@ -304,7 +313,7 @@ Debian stable:i386:
- - |
# apt_development
echo -e "\e[0Ksection_start:`date +%s`:apt_development[collapsed=true]\r\e[0KInstalling development packages"
- apt-get install libsdl2-mixer-dev:i386 libpng-dev:i386 libcurl4-openssl-dev:i386 libgme-dev:i386 libopenmpt-dev:i386
- apt-get install libsdl2-mixer-dev:i386 libpng-dev:i386 libcurl4-openssl-dev:i386 libgme-dev:i386 libopenmpt-dev:i386 libminiupnpc-dev:i386
- |
# apt_development
echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K"
@ -348,7 +357,7 @@ Debian stable:arm64:
- - |
# apt_development
echo -e "\e[0Ksection_start:`date +%s`:apt_development[collapsed=true]\r\e[0KInstalling development packages"
- apt-get install libsdl2-mixer-dev:arm64 libpng-dev:arm64 libcurl4-openssl-dev:arm64 libgme-dev:arm64 libopenmpt-dev:arm64
- apt-get install libsdl2-mixer-dev:arm64 libpng-dev:arm64 libcurl4-openssl-dev:arm64 libgme-dev:arm64 libopenmpt-dev:arm64 libminiupnpc-dev:arm64
- |
# apt_development
echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K"
@ -401,6 +410,10 @@ Debian stable Clang:
allow_failure: true
artifacts:
paths:
- "bin/"
- "src/comptime.h"
expose_as: "clang"
name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-clang"
variables:
@ -421,7 +434,7 @@ Debian stable Clang:
- - |
# apt_development
echo -e "\e[0Ksection_start:`date +%s`:apt_development[collapsed=true]\r\e[0KInstalling development packages"
- apt-get install libsdl2-mixer-dev libpng-dev libcurl4-openssl-dev libgme-dev libopenmpt-dev
- apt-get install libsdl2-mixer-dev libpng-dev libcurl4-openssl-dev libgme-dev libopenmpt-dev libminiupnpc-dev
- |
# apt_development
echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K"
@ -434,45 +447,6 @@ Debian stable Clang:
# make
echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K"
Debian stable musl:
stage: build
when: manual
allow_failure: true
artifacts:
name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-musl"
variables:
CC: musl-gcc
LDD: musl-ldd
script:
- - |
# apt_toolchain
echo -e "\e[0Ksection_start:`date +%s`:apt_toolchain[collapsed=true]\r\e[0KInstalling toolchain packages"
- apt-get install gcc
- |
# apt_toolchain
echo -e "\e[0Ksection_end:`date +%s`:apt_toolchain\r\e[0K"
- - |
# apt_development
echo -e "\e[0Ksection_start:`date +%s`:apt_development[collapsed=true]\r\e[0KInstalling development packages"
- apt-get install musl-tools
- |
# apt_development
echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K"
- - |
# make
echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2"
- make --directory=src --keep-going CCACHE=1 ERRORMODE=1 NONX86=1 SDL=0 NOHW=1 NOZLIB=1 NOCURL=1 NOGME=1 NOOPENMPT=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 NONX86=1 SDL=0 NOHW=1 NOZLIB=1 NOCURL=1 NOGME=1 NOOPENMPT=1
- |
# make
echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K"
Debian testing Clang:
extends: Debian stable Clang
@ -481,6 +455,10 @@ Debian testing Clang:
image: debian:testing-slim
artifacts:
paths:
- "bin/"
- "src/comptime.h"
expose_as: "testing-clang"
name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-testing-clang"
variables:
@ -489,17 +467,132 @@ Debian testing Clang:
CFLAGS: -Wno-cast-align -Wno-deprecated-non-prototype
LDFLAGS: -Wl,-fuse-ld=gold
Debian testing musl:
extends: Debian stable musl
Alpine 3 GCC:
stage: build
when: manual
when: on_success
image: debian:testing-slim
image: alpine:3
allow_failure: true
artifacts:
name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-testing-musl"
paths:
- "bin/"
- "src/comptime.h"
expose_as: "Apline-3"
name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-Apline-3"
variables:
CC: musl-gcc
LDD: musl-ldd
LDFLAGS: -Wl,-fuse-ld=gold
before_script:
- - |
# apk_cache
echo -e "\e[0Ksection_start:`date +%s`:apk_cache[collapsed=true]\r\e[0KUpdating APK listing"
- export APK_CACHE_DIR=`pwd`/apk-cache
- mkdir --parents --verbose $APK_CACHE_DIR/
- ln -sf /etc/apk/cache $APK_CACHE_DIR
- |
# apk_cache
echo -e "\e[0Ksection_end:`date +%s`:apk_cache\r\e[0K"
- - |
# apk_update
echo -e "\e[0Ksection_start:`date +%s`:apk_update[collapsed=true]\r\e[0KUpdating APK listing"
- apk update
- |
# apk_update
echo -e "\e[0Ksection_end:`date +%s`:apk_update\r\e[0K"
- - |
# apk_upgrade
echo -e "\e[0Ksection_start:`date +%s`:apk_upgrade[collapsed=true]\r\e[0KUpdating existing packages"
- apk upgrade
- |
# apk_update
echo -e "\e[0Ksection_end:`date +%s`:apk_upgrade\r\e[0K"
- - |
# apk_common
echo -e "\e[0Ksection_start:`date +%s`:apk_common[collapsed=true]\r\e[0KInstalling common packages"
- apk add make git ccache nasm
- |
# apk_common
echo -e "\e[0Ksection_end:`date +%s`:apk_common\r\e[0K"
- - |
# ccache_config
echo -e "\e[0Ksection_start:`date +%s`:ccache_config[collapsed=true]\r\e[0KSetting up ccache config"
- mkdir --parents --verbose ~/.ccache/
- touch ~/.ccache/ccache.conf
- |
# cache.conf
echo Adding ccache configution option
- |
# base_dir
echo base_dir = $PWD | tee -a ~/.ccache/ccache.conf
- |
# cache_dir
echo cache_dir = $PWD/ccache | tee -a ~/.ccache/ccache.conf
- |
# compiler_check
echo compiler_check = content | tee -a ~/.ccache/ccache.conf
- |
# stats_log
echo stats_log = $PWD/ccache_statslog | tee -a ~/.ccache/ccache.conf
- |
# max_size
echo max_size = 50M | tee -a ~/.ccache/ccache.conf
- |
# ccache_config
echo -e "\e[0Ksection_end:`date +%s`:ccache_config\r\e[0K"
- - |
# cache_reset
echo -e "\e[0Ksection_start:`date +%s`:ccache_reset[collapsed=true]\r\e[0KResetting ccache statistics"
- ccache --zero-stats
- ccache --show-stats
- |
# ccache_reset
echo -e "\e[0Ksection_end:`date +%s`:ccache_reset\r\e[0K"
script:
- - |
# apk_toolchain
echo -e "\e[0Ksection_start:`date +%s`:apk_toolchain[collapsed=true]\r\e[0KInstalling toolchain packages"
- apk add gcc
- |
# apk_toolchain
echo -e "\e[0Ksection_end:`date +%s`:apk_toolchain\r\e[0K"
- - |
# apk_development
echo -e "\e[0Ksection_start:`date +%s`:apk_development[collapsed=true]\r\e[0KInstalling development packages"
- apk add musl-dev sdl2_mixer-dev libpng-dev curl-dev libgme-dev libopenmpt-dev miniupnpc-dev
- |
# apk_development
echo -e "\e[0Ksection_end:`date +%s`:apk_development\r\e[0K"
- - |
# make
echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2"
- make --directory=src --keep-going CCACHE=1 ERRORMODE=1 NONX86=1 NOEXECINFO=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 NONX86=1 NOEXECINFO=1
- |
# make
echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K"
after_script:
- - |
# apk_clean
echo -e "\e[0Ksection_start:`date +%s`:apk_clean[collapsed=true]\r\e[0KCleaning of unneeded APK packages"
- apk cache clean
- |
# apk_clean
echo -e "\e[0Ksection_end:`date +%s`:apk_clean\r\e[0K"
- - |
# ccache_stats
echo -e "\e[0Ksection_start:`date +%s`:ccache_stats[collapsed=true]\r\e[0Kccache statistics:"
- ccache --show-stats --verbose
- ccache --show-log-stats --verbose
- |
# ccahe_stats
echo -e "\e[0Ksection_end:`date +%s`:ccache_stats\r\e[0K"

View file

@ -75,6 +75,7 @@ option(SRB2_CONFIG_ERRORMODE "Compile C code with warnings treated as errors." O
option(SRB2_CONFIG_DEBUGMODE "Compile with PARANOIA, ZDEBUG, RANGECHECK and PACKETDROP defined." OFF)
option(SRB2_CONFIG_MOBJCONSISTANCY "Compile with MOBJCONSISTANCY defined." OFF)
option(SRB2_CONFIG_PACKETDROP "Compile with PACKETDROP defined." OFF)
option(SRB2_CONFIG_EXECINFO "Enable stack trace dump support." ON)
option(SRB2_CONFIG_ZDEBUG "Compile with ZDEBUG defined." OFF)
# SRB2_CONFIG_PROFILEMODE is probably superceded by some CMake setting.
option(SRB2_CONFIG_PROFILEMODE "Compile for profiling (GCC only)." OFF)

View file

@ -1,6 +1,7 @@
@echo off
set BRA=Unknown
set REV=illegal
set GL1=Dummy
copy nul: /b +%1\comptime.c tmp.$$$ > nul
move tmp.$$$ %1\comptime.c > nul
@ -13,8 +14,9 @@ goto filwri
:gitrev
set GIT=%2
if "%GIT%"=="" set GIT=git
for /f "usebackq" %%s in (`%GIT% rev-parse --abbrev-ref HEAD`) do @set BRA=%%s
for /f "usebackq" %%s in (`%GIT% rev-parse HEAD`) do @set REV=%%s
for /f "tokens=* usebackq" %%s in (`%GIT% rev-parse --abbrev-ref HEAD`) do @set BRA=%%s
for /f "tokens=* usebackq" %%s in (`%GIT% rev-parse HEAD`) do @set REV=%%s
for /f "tokens=* usebackq" %%s in (`%GIT% log -1 --format^=%%f`) do @set GL1=%%s
set REV=%REV:~0,8%
goto filwri
@ -30,3 +32,4 @@ echo // by the %0 batch file >> %1\comptime.h
echo // >> %1\comptime.h
echo const char* compbranch = "%BRA%"; >> %1\comptime.h
echo const char* comprevision = "%REV%"; >> %1\comptime.h
echo const char* compnote = "%GL1%"; >> %1\comptime.h

View file

@ -12,24 +12,26 @@ version() {
//
const char* compbranch = "$1";
const char* comprevision = "$2";
const char* compnote = "$3";
EOF
}
versiongit() {
gitbranch="$(git rev-parse --abbrev-ref HEAD)"
gitversion="$(git rev-parse HEAD | cut -c -8)"
version "$gitbranch" "$gitversion";
gitsubject="$(git log -1 --format=%f)"
version "$gitbranch" "$gitversion" "$gitsubject";
exit 0
}
versionsvn() {
svnrevision="$(svnversion -n "$1")"
version "Subversion" "r$svnrevision";
version "Subversion" "r$svnrevision" "dummy";
exit 0
}
versionfake() {
version "Unknown" "illegal";
version "Unknown" "illegal" "dummy";
}
compversion() {

View file

@ -10,6 +10,45 @@ udmf
prefix = "(0)";
}
6
{
title = "Sector Set Portal";
prefix = "(6)";
arg0
{
title = "Target sector tag";
type = 13;
}
arg1
{
title = "Portal type";
type = 11;
enum
{
0 = "Link to portal with same tag";
1 = "Copy portal from second tag";
2 = "Skybox portal";
3 = "Plane portal";
4 = "Horizon portal";
5 = "Copy portal to line";
6 = "Interactive portal (unimplemented)";
7 = "Link to sector with second tag";
8 = "Link to object with second tag";
}
}
arg2
{
title = "Affected planes";
type = 11;
enum = "floorceiling";
}
arg3
{
title = "Misc";
tooltip = "For type 0 portal: specifies whether the line belongs to the sector viewed\nthrough the portal (1) or the sector in which the portal is seen (0).\nFor type 1 portal: specifies the sector tag of the portal to copy.\nFor type 7 portal: specifies the sector tag to make a portal to.\nFor type 8 portal: specifies the object tag to make a portal to.";
}
}
7
{
title = "Sector Flat Alignment";

26
libs/miniupnpc/.gitattributes vendored Normal file
View file

@ -0,0 +1,26 @@
/*.cmake text=auto
/*.py text=auto
/*.rc -crlf -whitespace
/*.sh text eol=lf
/*.txt text=auto
/CMakeLists.txt text=auto
/LICENSE text=auto
/Makefile text=auto
/Makefile.mingw text=auto
/include/*.h text=auto
/java/*.bat -crlf -whitespace
/java/*.java text=auto
/java/*.sh text eol=lf
/man3/miniupnpc.3 eol=lf
/msvc/*.sln -crlf -whitespace
/msvc/*.vbs -crlf -whitespace
/msvc/*.vcproj -crlf -whitespace
/msvc/*.vcxproj* -crlf -whitespace
/src/*.c text=auto
/src/*.h text=auto
/testdesc/*.values text=auto
/testdesc/*.xml text=auto
/testreplyparse/*.namevalue text=auto
/testreplyparse/*.txt text=auto
/testreplyparse/*.xml text=auto
MANIFEST.in eol=lf

View file

@ -1,172 +1,308 @@
cmake_minimum_required (VERSION 2.6)
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
project (miniupnpc C)
set (MINIUPNPC_VERSION 1.5)
set (MINIUPNPC_API_VERSION 8)
project (miniupnpc
VERSION 2.2.5
DESCRIPTION "UPnP IGD client lightweight library"
HOMEPAGE_URL https://miniupnp.tuxfamily.org/
LANGUAGES C)
if (NOT CMAKE_BUILD_TYPE)
if (WIN32)
set (DEFAULT_BUILD_TYPE MinSizeRel)
else (WIN32)
set (DEFAULT_BUILD_TYPE RelWithDebInfo)
endif(WIN32)
set (CMAKE_BUILD_TYPE ${DEFAULT_BUILD_TYPE} CACHE STRING
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
FORCE)
endif()
set (MINIUPNPC_API_VERSION 17)
option (UPNPC_BUILD_STATIC "Build static library" TRUE)
option (UPNPC_BUILD_SHARED "Build shared library" TRUE)
if (NOT WIN32)
option (UPNPC_BUILD_TESTS "Build test executables" TRUE)
endif (NOT WIN32)
option (UPNPC_BUILD_TESTS "Build test executables" TRUE)
option (UPNPC_BUILD_SAMPLE "Build sample executables" TRUE)
option (NO_GETADDRINFO "Define NO_GETADDRINFO" FALSE)
mark_as_advanced (NO_GETADDRINFO)
if (NO_GETADDRINFO)
add_definitions (-DNO_GETADDRINFO)
endif (NO_GETADDRINFO)
if (NOT WIN32)
add_definitions (-DMINIUPNPC_SET_SOCKET_TIMEOUT)
else (NOT WIN32)
add_definitions (-D_WIN32_WINNT=0x0501) # XP or higher for getnameinfo and friends
endif (NOT WIN32)
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
add_definitions (-DMACOSX -D_DARWIN_C_SOURCE)
endif ()
# Set compiler specific build flags
if (CMAKE_COMPILER_IS_GNUC)
# Set our own default flags at first run.
if (NOT CONFIGURED)
if (NOT CMAKE_SYSTEM_NAME STREQUAL "AmigaOS")
set (_PIC -fPIC)
endif (CMAKE_SYSTEM_NAME STREQUAL "AmigaOS")
set (CMAKE_C_FLAGS "${_PIC} -Wall $ENV{CFLAGS}" # CMAKE_C_FLAGS gets appended to the other C flags
CACHE STRING "Flags used by the C compiler during normal builds." FORCE)
set (CMAKE_C_FLAGS_DEBUG "-g -DDDEBUG"
CACHE STRING "Flags used by the C compiler during debug builds." FORCE)
set (CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG"
CACHE STRING "Flags used by the C compiler during release builds." FORCE)
set (CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g -DNDEBUG"
CACHE STRING "Flags used by the C compiler during release builds." FORCE)
set (CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG"
CACHE STRING "Flags used by the C compiler during release builds." FORCE)
endif (NOT CONFIGURED)
endif ()
configure_file (${CMAKE_SOURCE_DIR}/miniupnpcstrings.h.cmake ${CMAKE_BINARY_DIR}/miniupnpcstrings.h)
include_directories (${CMAKE_BINARY_DIR})
set (MINIUPNPC_SOURCES
igd_desc_parse.c
miniupnpc.c
minixml.c
minisoap.c
miniwget.c
upnpc.c
upnpcommands.c
upnpreplyparse.c
upnperrors.c
connecthostport.c
portlistingparse.c
)
if (NOT WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL "AmigaOS")
set (MINIUPNPC_SOURCES ${MINIUPNPC_SOURCES} minissdpc.c)
endif (NOT WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL "AmigaOS")
if (WIN32)
set_source_files_properties (${MINIUPNPC_SOURCES} PROPERTIES
COMPILE_DEFINITIONS STATICLIB
COMPILE_DEFINITIONS MINIUPNP_EXPORTS
)
endif (WIN32)
if (WIN32)
find_library (WINSOCK2_LIBRARY NAMES ws2_32 WS2_32 Ws2_32)
find_library (IPHLPAPI_LIBRARY NAMES iphlpapi)
set (LDLIBS ${WINSOCK2_LIBRARY} ${IPHLPAPI_LIBRARY} ${LDLIBS})
#elseif (CMAKE_SYSTEM_NAME STREQUAL "Solaris")
# find_library (SOCKET_LIBRARY NAMES socket)
# find_library (NSL_LIBRARY NAMES nsl)
# find_library (RESOLV_LIBRARY NAMES resolv)
# set (LDLIBS ${SOCKET_LIBRARY} ${NSL_LIBRARY} ${RESOLV_LIBRARY} ${LDLIBS})
endif (WIN32)
option (UPNPC_NO_INSTALL "Disable installation" FALSE)
if (NOT UPNPC_BUILD_STATIC AND NOT UPNPC_BUILD_SHARED)
message (FATAL "Both shared and static libraries are disabled!")
endif (NOT UPNPC_BUILD_STATIC AND NOT UPNPC_BUILD_SHARED)
endif ()
include(GNUInstallDirs)
# Interface library for compile definitions, flags and option
add_library(miniupnpc-private INTERFACE)
if (NO_GETADDRINFO)
target_compile_definitions(miniupnpc-private INTERFACE NO_GETADDRINFO)
endif ()
if (NOT WIN32)
target_compile_definitions(miniupnpc-private INTERFACE
MINIUPNPC_SET_SOCKET_TIMEOUT
_BSD_SOURCE _DEFAULT_SOURCE)
if (NOT APPLE AND NOT CMAKE_SYSTEM_NAME MATCHES ".*BSD" AND NOT CMAKE_SYSTEM_NAME STREQUAL "SunOS")
# add_definitions (-D_POSIX_C_SOURCE=200112L)
target_compile_definitions(miniupnpc-private INTERFACE _XOPEN_SOURCE=600)
endif ()
if (CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
target_compile_definitions(miniupnpc-private INTERFACE _NETBSD_SOURCE)
endif ()
else ()
target_compile_definitions(miniupnpc-private INTERFACE _WIN32_WINNT=0x0501) # XP or higher for getnameinfo and friends
endif ()
if (APPLE)
target_compile_definitions(miniupnpc-private INTERFACE _DARWIN_C_SOURCE)
endif ()
# Set compiler specific build flags
if (CMAKE_COMPILER_IS_GNUCC AND NOT CMAKE_SYSTEM_NAME STREQUAL "AmigaOS")
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
target_compile_options(miniupnpc-private INTERFACE -Wall)
endif ()
# Suppress noise warnings
if (MSVC)
target_compile_definitions(miniupnpc-private INTERFACE _CRT_SECURE_NO_WARNINGS _WINSOCK_DEPRECATED_NO_WARNINGS)
endif()
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/miniupnpcstrings.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/miniupnpcstrings.h)
target_include_directories(miniupnpc-private INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
set (MINIUPNPC_SOURCES
src/igd_desc_parse.c
src/miniupnpc.c
src/minixml.c
src/minisoap.c
src/minissdpc.c
src/miniwget.c
src/upnpcommands.c
src/upnpdev.c
src/upnpreplyparse.c
src/upnperrors.c
src/connecthostport.c
src/portlistingparse.c
src/receivedata.c
src/addr_is_reserved.c
${CMAKE_CURRENT_BINARY_DIR}/miniupnpcstrings.h
)
if (WIN32)
target_link_libraries(miniupnpc-private INTERFACE ws2_32 iphlpapi)
elseif (CMAKE_SYSTEM_NAME STREQUAL "SunOS")
target_link_libraries(miniupnpc-private INTERFACE socket nsl resolv)
find_library (SOCKET_LIBRARY NAMES socket)
find_library (NSL_LIBRARY NAMES nsl)
find_library (RESOLV_LIBRARY NAMES resolv)
set (LDLIBS ${SOCKET_LIBRARY} ${NSL_LIBRARY} ${RESOLV_LIBRARY} ${LDLIBS})
elseif (HAIKU)
target_link_libraries(miniupnpc-private INTERFACE network)
find_library (SOCKET_LIBRARY NAMES network)
find_library (NSL_LIBRARY NAMES network)
find_library (RESOLV_LIBRARY NAMES network)
set (LDLIBS ${SOCKET_LIBRARY} ${NSL_LIBRARY} ${RESOLV_LIBRARY} ${LDLIBS})
endif ()
if (UPNPC_BUILD_STATIC)
add_library (upnpc-static STATIC ${MINIUPNPC_SOURCES})
set_target_properties (upnpc-static PROPERTIES OUTPUT_NAME "miniupnpc")
target_link_libraries (upnpc-static ${LDLIBS})
set (UPNPC_INSTALL_TARGETS ${UPNPC_INSTALL_TARGETS} upnpc-static)
set (UPNPC_LIBRARY_TARGET upnpc-static)
endif (UPNPC_BUILD_STATIC)
add_library (libminiupnpc-static STATIC ${MINIUPNPC_SOURCES})
target_include_directories (libminiupnpc-static PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include/miniupnpc>)
if (NOT UPNPC_BUILD_SHARED)
add_library (miniupnpc::miniupnpc ALIAS libminiupnpc-static)
endif()
set_target_properties (libminiupnpc-static PROPERTIES EXPORT_NAME miniupnpc)
if (WIN32 AND NOT MINGW)
set_target_properties (libminiupnpc-static PROPERTIES OUTPUT_NAME "libminiupnpc")
else()
set_target_properties (libminiupnpc-static PROPERTIES OUTPUT_NAME "miniupnpc")
endif()
target_link_libraries (libminiupnpc-static PRIVATE miniupnpc-private)
target_include_directories(libminiupnpc-static INTERFACE $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
target_compile_definitions(libminiupnpc-static PUBLIC MINIUPNP_STATICLIB)
if (NOT UPNPC_NO_INSTALL)
install (TARGETS miniupnpc-private EXPORT miniupnpc-private)
install (EXPORT miniupnpc-private
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/miniupnpc"
NAMESPACE miniupnpc::)
install (TARGETS libminiupnpc-static
EXPORT libminiupnpc-static
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
install (EXPORT libminiupnpc-static
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/miniupnpc"
NAMESPACE miniupnpc::)
endif()
if (UPNPC_BUILD_SAMPLE)
add_executable (upnpc-static src/upnpc.c)
target_link_libraries (upnpc-static PRIVATE libminiupnpc-static)
target_include_directories(upnpc-static PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
if (NOT UPNPC_NO_INSTALL)
install (TARGETS upnpc-static
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
endif ()
endif ()
if (UPNPC_BUILD_SHARED)
add_library (upnpc-shared SHARED ${MINIUPNPC_SOURCES})
set_target_properties (upnpc-shared PROPERTIES OUTPUT_NAME "miniupnpc")
set_target_properties (upnpc-shared PROPERTIES VERSION ${MINIUPNPC_VERSION})
set_target_properties (upnpc-shared PROPERTIES SOVERSION ${MINIUPNPC_API_VERSION})
target_link_libraries (upnpc-shared ${LDLIBS})
set (UPNPC_INSTALL_TARGETS ${UPNPC_INSTALL_TARGETS} upnpc-shared)
set (UPNPC_LIBRARY_TARGET upnpc-shared)
endif (UPNPC_BUILD_SHARED)
add_library (libminiupnpc-shared SHARED ${MINIUPNPC_SOURCES})
target_include_directories (libminiupnpc-shared PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include/miniupnpc>)
add_library (miniupnpc::miniupnpc ALIAS libminiupnpc-shared)
set_target_properties (libminiupnpc-shared PROPERTIES EXPORT_NAME miniupnpc)
set_target_properties (libminiupnpc-shared PROPERTIES OUTPUT_NAME "miniupnpc")
set_target_properties (libminiupnpc-shared PROPERTIES VERSION ${PROJECT_VERSION})
set_target_properties (libminiupnpc-shared PROPERTIES SOVERSION ${MINIUPNPC_API_VERSION})
target_link_libraries (libminiupnpc-shared PRIVATE miniupnpc-private)
target_compile_definitions(libminiupnpc-shared PRIVATE MINIUPNP_EXPORTS)
target_include_directories(libminiupnpc-shared INTERFACE $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
if (WIN32)
target_link_libraries(libminiupnpc-shared INTERFACE ws2_32 iphlpapi)
endif()
if (NOT UPNPC_NO_INSTALL)
install (TARGETS libminiupnpc-shared
EXPORT libminiupnpc-shared
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
install (EXPORT libminiupnpc-shared
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/miniupnpc"
NAMESPACE miniupnpc::)
endif()
if (UPNPC_BUILD_SAMPLE)
add_executable (upnpc-shared src/upnpc.c)
target_link_libraries (upnpc-shared PRIVATE libminiupnpc-shared)
target_include_directories(upnpc-shared PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
if (NOT UPNPC_NO_INSTALL)
install (TARGETS upnpc-shared
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
endif ()
add_executable (listdevices src/listdevices.c)
target_link_libraries (listdevices PRIVATE libminiupnpc-shared)
target_include_directories(listdevices PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
if (NOT UPNPC_NO_INSTALL)
install (TARGETS listdevices
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
endif ()
if (UPNPC_BUILD_TESTS)
add_executable (testminixml testminixml.c minixml.c igd_desc_parse.c)
target_link_libraries (testminixml ${LDLIBS})
add_library(miniupnpc-tests INTERFACE)
target_link_libraries(miniupnpc-tests INTERFACE miniupnpc-private)
target_compile_definitions(miniupnpc-tests INTERFACE MINIUPNP_STATICLIB)
add_executable (minixmlvalid minixmlvalid.c minixml.c)
target_link_libraries (minixmlvalid ${LDLIBS})
add_executable (testminixml src/testminixml.c src/minixml.c src/igd_desc_parse.c)
target_include_directories (testminixml PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
target_link_libraries (testminixml PRIVATE miniupnpc-tests)
add_executable (testupnpreplyparse testupnpreplyparse.c
minixml.c upnpreplyparse.c)
target_link_libraries (testupnpreplyparse ${LDLIBS})
add_executable (minixmlvalid src/minixmlvalid.c src/minixml.c)
target_link_libraries (minixmlvalid PRIVATE miniupnpc-tests)
add_executable (testigddescparse testigddescparse.c
igd_desc_parse.c minixml.c miniupnpc.c miniwget.c minissdpc.c
upnpcommands.c upnpreplyparse.c minisoap.c connecthostport.c
portlistingparse.c
add_executable (testupnpreplyparse src/testupnpreplyparse.c
src/minixml.c src/upnpreplyparse.c)
target_include_directories (testupnpreplyparse PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
target_link_libraries (testupnpreplyparse PRIVATE miniupnpc-tests)
add_executable (testigddescparse src/testigddescparse.c
src/igd_desc_parse.c src/minixml.c src/miniupnpc.c src/miniwget.c src/minissdpc.c
src/upnpcommands.c src/upnpreplyparse.c src/minisoap.c src/connecthostport.c
src/portlistingparse.c src/receivedata.c src/addr_is_reserved.c
)
target_link_libraries (testigddescparse ${LDLIBS})
target_include_directories (testigddescparse PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
target_link_libraries (testigddescparse PRIVATE miniupnpc-tests)
add_executable (testminiwget testminiwget.c
miniwget.c miniupnpc.c minisoap.c upnpcommands.c minissdpc.c
upnpreplyparse.c minixml.c igd_desc_parse.c connecthostport.c
portlistingparse.c
add_executable (testminiwget src/testminiwget.c
src/miniwget.c src/miniupnpc.c src/minisoap.c src/upnpcommands.c src/minissdpc.c
src/upnpreplyparse.c src/minixml.c src/igd_desc_parse.c src/connecthostport.c
src/portlistingparse.c src/receivedata.c src/addr_is_reserved.c
)
target_link_libraries (testminiwget ${LDLIBS})
target_include_directories (testminiwget PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
target_link_libraries (testminiwget PRIVATE miniupnpc-tests)
add_executable (testaddr_is_reserved src/testaddr_is_reserved.c
src/addr_is_reserved.c
)
target_link_libraries (testaddr_is_reserved PRIVATE miniupnpc-tests)
add_executable (testportlistingparse src/testportlistingparse.c
src/minixml.c src/portlistingparse.c)
target_include_directories (testportlistingparse PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
target_link_libraries (testportlistingparse PRIVATE miniupnpc-tests)
add_executable (minihttptestserver src/minihttptestserver.c)
# set (UPNPC_INSTALL_TARGETS ${UPNPC_INSTALL_TARGETS} testminixml minixmlvalid testupnpreplyparse testigddescparse testminiwget)
endif (UPNPC_BUILD_TESTS)
include(CTest)
add_test(NAME validateminixml
COMMAND minixmlvalid)
add_test(NAME validateminiwget
COMMAND ${CMAKE_SOURCE_DIR}/testminiwget.sh)
set_property(TEST validateminiwget
PROPERTY ENVIRONMENT
TESTSERVER=${CMAKE_BINARY_DIR}/minihttptestserver
TESTMINIWGET=${CMAKE_BINARY_DIR}/testminiwget)
add_test(NAME validateupnpreplyparse
COMMAND ${CMAKE_SOURCE_DIR}/testupnpreplyparse.sh
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
set_property(TEST validateupnpreplyparse
PROPERTY ENVIRONMENT
TESTUPNPREPLYPARSE=${CMAKE_BINARY_DIR}/testupnpreplyparse)
add_test(NAME validateportlistingparse
COMMAND testportlistingparse)
add_test(NAME validateigddescparse1
COMMAND testigddescparse new_LiveBox_desc.xml new_LiveBox_desc.values
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/testdesc)
add_test(NAME validateigddescparse2
COMMAND testigddescparse linksys_WAG200G_desc.xml linksys_WAG200G_desc.values
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/testdesc)
add_test(NAME validateaddr_is_reserved
COMMAND testaddr_is_reserved)
endif ()
install (TARGETS ${UPNPC_INSTALL_TARGETS}
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib${LIB_SUFFIX}
ARCHIVE DESTINATION lib${LIB_SUFFIX}
)
install (FILES
miniupnpc.h
miniwget.h
upnpcommands.h
igd_desc_parse.h
upnpreplyparse.h
upnperrors.h
declspec.h
DESTINATION include/miniupnpc
)
configure_file(miniupnpc.pc.in miniupnpc.pc @ONLY)
set (CONFIGURED YES CACHE INTERNAL "")
if (NOT UPNPC_NO_INSTALL)
install (FILES
include/miniupnpc.h
include/miniwget.h
include/upnpcommands.h
include/igd_desc_parse.h
include/upnpreplyparse.h
include/upnperrors.h
include/upnpdev.h
include/miniupnpctypes.h
include/portlistingparse.h
include/miniupnpc_declspec.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/miniupnpc
)
# vim: ts=2:sw=2
install(FILES miniupnpc-config.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/miniupnpc
)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/miniupnpc.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
)
install(FILES man3/miniupnpc.3
DESTINATION ${CMAKE_INSTALL_MANDIR}/man3
)
install(FILES external-ip.sh
TYPE BIN
)
endif()
# vim: ts=2:sw=2:expandtab

View file

@ -1,6 +1,343 @@
$Id: Changelog.txt,v 1.152 2011/07/25 18:02:11 nanard Exp $
$Id: Changelog.txt,v 1.256 2023/06/11 23:23:29 nanard Exp $
miniUPnP client Changelog.
2023/06/05:
GetListOfPortMappings NewStartPort 0 => 1
2023/05/30:
CheckPinholeWorking is optional
add 60x errors from UPnP Device Architecture
2023/01/04:
cmake: install binaries, man pages and external-ip.sh
VERSION 2.2.4 : released 2022/10/21
2022/02/20:
upnpc: use of @ to replace local lan address
2021/11/09:
python module : Allow to specify the root description url
VERSION 2.2.3 : released 2021/09/28
2021/08/13:
Change directory structure : include/ and src/ directories.
VERSION 2.2.2 : released 2021/03/03
2021/01/15:
miniupnpcmodule.c: throw an exception in UPnP_discover()
2020/12/30:
Fix usage of IP_MULTICAST_IF with struct ip_mreqn
VERSION 2.2.1 : released 2020/12/20
2020/11/30:
Add miniupnpc.rc for .dll description
VERSION 2.2.0 : released 2020/11/09
2020/09/24:
Check properly for reserved IP addresses
2020/09/23:
prevent infinite loop in upnpDiscover()
2020/02/16:
Add Haiku support
2019/10/22:
testminiwget.sh can use either "ip addr" or "ifconfig -a
2019/10/13:
fix UPNP_GetValidIGD() when several devices are found
which are reachable from != local address
2019/08/24:
Allow Remote Host on upnpc command line
fix error 708 description in strupnperror()
2019/04/05:
Fix memory leak in upnpreplyparse.c with NewPortListing element
2019/03/10:
connecthostport.c: Code simplification, error trace fix
2019/01/23:
set timeout for select() in connecthostport()
2018/10/31:
miniupnpcmodule.c: check return of WSAStartup()
2018/07/14:
Fix and improve MSVC project :
Add Dll configurations
improve genminiupnpcstrings.vbs
2018/06/18:
Fixes for windows 64-bits.
VERSION 2.1 : released 2018/05/07
2018/05/07:
CMake Modernize and cleanup CMakeLists.txt
Update MS Visual Studio projects
2018/04/30:
listdevices: show devices sorted by XML desc URL
2018/04/26:
Small fix in miniupnpcmodule.c (python module)
Support cross compiling in Makefile.mingw
2018/04/06:
Use SOCKET type instead of int (for Win64 compilation)
Increments API_VERSION to 17
2018/02/22:
Disable usage of MiniSSDPd when using -m option
2017/12/11:
Fix buffer over run in minixml.c
Fix uninitialized variable access in upnpreplyparse.c
2017/05/05:
Fix CVE-2017-8798 Thanks to tin/Team OSTStrom
2016/11/11:
check strlen before memcmp in XML parsing portlistingparse.c
fix build under SOLARIS and CYGWIN
2016/10/11:
Add python 3 compatibility to IGD test
VERSION 2.0 : released 2016/04/19
2016/01/24:
change miniwget to return HTTP status code
increments API_VERSION to 16
2016/01/22:
Improve UPNPIGD_IsConnected() to check if WAN address is not private.
parse HTTP response status line in miniwget.c
2015/10/26:
snprintf() overflow check. check overflow in simpleUPnPcommand2()
2015/10/25:
fix compilation with old macs
fix compilation with mingw32 (for Appveyor)
fix python module for python <= 2.3
2015/10/08:
Change sameport to localport
see https://github.com/miniupnp/miniupnp/pull/120
increments API_VERSION to 15
2015/09/15:
Fix buffer overflow in igd_desc_parse.c/IGDstartelt()
Discovered by Aleksandar Nikolic of Cisco Talos
2015/08/28:
move ssdpDiscoverDevices() to minissdpc.c
2015/08/27:
avoid unix socket leak in getDevicesFromMiniSSDPD()
2015/08/16:
Also accept "Up" as ConnectionStatus value
2015/07/23:
split getDevicesFromMiniSSDPD
add ttl argument to upnpDiscover() functions
increments API_VERSION to 14
2015/07/22:
Read USN from SSDP messages.
2015/07/15:
Check malloc/calloc
2015/06/16:
update getDevicesFromMiniSSDPD() to process longer minissdpd
responses
2015/05/22:
add searchalltypes param to upnpDiscoverDevices()
increments API_VERSION to 13
2015/04/30:
upnpc: output version on the terminal
2015/04/27:
_BSD_SOURCE is deprecated in favor of _DEFAULT_SOURCE
fix CMakeLists.txt COMPILE_DEFINITIONS
fix getDevicesFromMiniSSDPD() not setting scope_id
improve -r command of upnpc command line tool
2014/11/17:
search all :
upnpDiscoverDevices() / upnpDiscoverAll() functions
listdevices executable
increment API_VERSION to 12
validate igd_desc_parse
2014/11/13:
increment API_VERSION to 11
2014/11/05:
simplified function GetUPNPUrls()
2014/09/11:
use remoteHost arg of DeletePortMapping
2014/09/06:
Fix python3 build
2014/07/01:
Fix parsing of IGD2 root descriptions
2014/06/10:
rename LIBSPEC to MINIUPNP_LIBSPEC
2014/05/15:
Add support for IGD2 AddAnyPortMapping and DeletePortMappingRange
2014/02/05:
handle EINPROGRESS after connect()
2014/02/03:
minixml now handle XML comments
VERSION 1.9 : released 2014/01/31
2014/01/31:
added argument remoteHost to UPNP_GetSpecificPortMappingEntry()
increment API_VERSION to 10
2013/12/09:
--help and -h arguments in upnpc.c
2013/10/07:
fixed potential buffer overrun in miniwget.c
Modified UPNP_GetValidIGD() to check for ExternalIpAddress
2013/08/01:
define MAXHOSTNAMELEN if not already done
2013/06/06:
update upnpreplyparse to allow larger values (128 chars instead of 64)
2013/05/14:
Update upnpreplyparse to take into account "empty" elements
validate upnpreplyparse.c code with "make check"
2013/05/03:
Fix Solaris build thanks to Maciej Małecki
2013/04/27:
Fix testminiwget.sh for BSD
2013/03/23:
Fixed Makefile for *BSD
2013/03/11:
Update Makefile to use JNAerator version 0.11
2013/02/11:
Fix testminiwget.sh for use with dash
Use $(DESTDIR) in Makefile
VERSION 1.8 : released 2013/02/06
2012/10/16:
fix testminiwget with no IPv6 support
2012/09/27:
Rename all include guards to not clash with C99
(7.1.3 Reserved identifiers).
2012/08/30:
Added -e option to upnpc program (set description for port mappings)
2012/08/29:
Python 3 support (thanks to Christopher Foo)
2012/08/11:
Fix a memory link in UPNP_GetValidIGD()
Try to handle scope id in link local IPv6 URL under MS Windows
2012/07/20:
Disable HAS_IP_MREQN on DragonFly BSD
2012/06/28:
GetUPNPUrls() now inserts scope into link-local IPv6 addresses
2012/06/23:
More error return checks in upnpc.c
#define MINIUPNPC_GET_SRC_ADDR enables receivedata() to get scope_id
parseURL() now parses IPv6 addresses scope
new parameter for miniwget() : IPv6 address scope
increment API_VERSION to 9
2012/06/20:
fixed CMakeLists.txt
2012/05/29
Improvements in testminiwget.sh
VERSION 1.7 : released 2012/05/24
2012/05/01:
Cleanup settings of CFLAGS in Makefile
Fix signed/unsigned integer comparaisons
2012/04/20:
Allow to specify protocol with TCP or UDP for -A option
2012/04/09:
Only try to fetch XML description once in UPNP_GetValidIGD()
Added -ansi flag to compilation, and fixed C++ comments to ANSI C comments.
2012/04/05:
minor improvements to minihttptestserver.c
2012/03/15:
upnperrors.c returns valid error string for unrecognized error codes
2012/03/08:
make minihttptestserver listen on loopback interface instead of 0.0.0.0
2012/01/25:
Maven installation thanks to Alexey Kuznetsov
2012/01/21:
Replace WIN32 macro by _WIN32
2012/01/19:
Fixes in java wrappers thanks to Alexey Kuznetsov :
https://github.com/axet/miniupnp/tree/fix-javatest/miniupnpc
Make and install .deb packages (python) thanks to Alexey Kuznetsov :
https://github.com/axet/miniupnp/tree/feature-debbuild/miniupnpc
2012/01/07:
The multicast interface can now be specified by name with IPv4.
2012/01/02:
Install man page
2011/11/25:
added header to Port Mappings list in upnpc.c
2011/10/09:
Makefile : make clean now removes jnaerator generated files.
MINIUPNPC_VERSION in miniupnpc.h (updated by make)
2011/09/12:
added rootdescURL to UPNPUrls structure.
VERSION 1.6 : released 2011/07/25
2011/07/25:
@ -236,7 +573,7 @@ VERSION 1.2 :
small modif to make Clang happy :)
2008/07/17:
#define SOAPPREFIX "s" in miniupnpc.c in order to remove SOAP-ENV...
#define SOAPPREFIX "s" in miniupnpc.c in order to remove SOAP-ENV...
2008/07/14:
include declspec.h in installation (to /usr/include/miniupnpc)
@ -258,7 +595,7 @@ VERSION 1.1 :
improved python module error/exception reporting.
2008/04/23:
Completely rewrite igd_desc_parse.c in order to be compatible with
Completely rewrite igd_desc_parse.c in order to be compatible with
Linksys WAG200G
Added testigddescparse
updated python module
@ -281,7 +618,7 @@ VERSION 1.0 :
improved make install :)
2007/12/22:
Adding upnperrors.c/h to provide a strupnperror() function
Adding upnperrors.c/h to provide a strupnperror() function
used to translate UPnP error codes to string.
2007/12/19:
@ -363,7 +700,7 @@ VERSION 1.0 :
upnpc now displays external ip address with -s or -l
2007/04/11:
changed MINIUPNPC_URL_MAXSIZE to 128 to accomodate the "BT Voyager 210"
changed MINIUPNPC_URL_MAXSIZE to 128 to accommodate the "BT Voyager 210"
2007/03/19:
cleanup in miniwget.c

View file

@ -1,27 +1,29 @@
MiniUPnPc
Copyright (c) 2005-2011, Thomas BERNARD
BSD 3-Clause License
Copyright (c) 2005-2023, 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.
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. 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.
3. Neither the name of the copyright holder nor the names of its
contributors may 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.
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.

View file

@ -1,5 +1,10 @@
include README
include miniupnpcmodule.c
include VERSION
include LICENSE
include src/miniupnpcmodule.c
include setup.py
include *.h
include libminiupnpc.a
include Makefile
include src/*.[ch]
include include/*.h
include *.h.in
include *.sh

View file

@ -1,214 +1,396 @@
# $Id: Makefile,v 1.81 2011/06/21 15:24:14 nanard Exp $
# $Id: Makefile,v 1.148 2022/10/19 22:46:06 nanard Exp $
# MiniUPnP Project
# http://miniupnp.free.fr/
# (c) 2005-2011 Thomas Bernard
# https://miniupnp.tuxfamily.org/
# https://github.com/miniupnp/miniupnp
# (c) 2005-2022 Thomas Bernard
# to install use :
# $ PREFIX=/tmp/dummylocation make install
# $ make DESTDIR=/tmp/dummylocation install
# or
# $ INSTALLPREFIX=/usr/local make install
# or
# make install (will go to /usr/bin, /usr/lib, etc...)
OS = $(shell uname -s)
# 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 -Wall -g -DDEBUG
CFLAGS ?= -O -Wall -DNDEBUG -DMINIUPNPC_SET_SOCKET_TIMEOUT -Wstrict-prototypes
# -DNO_GETADDRINFO
#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.3.jar
#following libs are needed on Solaris
#LDLIBS=-lsocket -lnsl -lresolv
#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 = 8
APIVERSION = 17
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 portlistringparse.c receivedata.c
SRCS = $(wildcard $(SRCDIR)/*.c)
LIBOBJS = miniwget.o minixml.o igd_desc_parse.o minisoap.o \
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
connecthostport.o portlistingparse.o receivedata.o upnpdev.o \
addr_is_reserved.o)
ifneq ($(OS), AmigaOS)
CFLAGS := -fPIC $(CFLAGS)
LIBOBJS := $(LIBOBJS) minissdpc.o
endif
BUILDINCLUDES = $(addprefix $(BUILD)/, miniupnpcstrings.h)
OBJS = $(patsubst %.c,%.o,$(SRCS))
OBJS = $(patsubst $(SRCDIR)/%.c,$(BUILD)/%.o,$(SRCS))
DEPS = $(patsubst $(SRCDIR)/%.c,$(BUILD)/%.d,$(SRCS))
# HEADERS to install
HEADERS = miniupnpc.h miniwget.h upnpcommands.h igd_desc_parse.h \
upnpreplyparse.h upnperrors.h miniupnpctypes.h \
portlistingparse.h \
declspec.h
CPPFLAGS += -I$(INCDIR)
HEADERS = $(wildcard $(INCDIR)/*.h)
# library names
LIBRARY = libminiupnpc.a
ifeq ($(OS), Darwin)
SHAREDLIBRARY = libminiupnpc.dylib
SONAME = $(basename $(SHAREDLIBRARY)).$(APIVERSION).dylib
CFLAGS := -DMACOSX -D_DARWIN_C_SOURCE $(CFLAGS)
else
SHAREDLIBRARY = libminiupnpc.so
SONAME = $(SHAREDLIBRARY).$(APIVERSION)
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 = upnpc-static
EXECUTABLES_ADDTESTS = testminixml minixmlvalid testupnpreplyparse \
testigddescparse testminiwget
EXECUTABLES = $(addprefix $(BUILD)/, upnpc-static listdevices)
EXECUTABLES_ADDTESTS = $(addprefix $(BUILD)/, testminixml minixmlvalid \
testupnpreplyparse testigddescparse testminiwget testportlistingparse)
TESTMINIXMLOBJS = minixml.o igd_desc_parse.o testminixml.o
TESTMINIXMLOBJS = $(addprefix $(BUILD)/, minixml.o igd_desc_parse.o testminixml.o)
TESTMINIWGETOBJS = miniwget.o testminiwget.o connecthostport.o receivedata.o
TESTMINIWGETOBJS = $(addprefix $(BUILD)/, miniwget.o testminiwget.o connecthostport.o receivedata.o)
TESTUPNPREPLYPARSE = testupnpreplyparse.o minixml.o upnpreplyparse.o
TESTUPNPREPLYPARSE = $(addprefix $(BUILD)/, testupnpreplyparse.o minixml.o upnpreplyparse.o)
TESTIGDDESCPARSE = testigddescparse.o igd_desc_parse.o minixml.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
portlistingparse.o addr_is_reserved.o)
ifneq ($(OS), AmigaOS)
EXECUTABLES := $(EXECUTABLES) upnpc-shared
TESTMINIWGETOBJS := $(TESTMINIWGETOBJS) minissdpc.o
TESTIGDDESCPARSE := $(TESTIGDDESCPARSE) minissdpc.o
ifeq (, $(findstring amiga, $(OS)))
ifeq (, $(findstring mingw, $(OS))$(findstring cygwin, $(OS))$(findstring msys, $(OS)))
CFLAGS += -fPIC
endif
EXECUTABLES += $(BUILD)/upnpc-shared
TESTMINIWGETOBJS += $(BUILD)/minissdpc.o
TESTIGDDESCPARSE += $(BUILD)/minissdpc.o
LIBOBJS += $(BUILD)/minissdpc.o
endif
LIBDIR ?= lib
# install directories
INSTALLPREFIX ?= $(PREFIX)/usr
ifeq ($(strip $(PREFIX)),)
INSTALLPREFIX ?= /usr
else
INSTALLPREFIX ?= $(PREFIX)
endif
INSTALLDIRINC = $(INSTALLPREFIX)/include/miniupnpc
INSTALLDIRLIB = $(INSTALLPREFIX)/lib
INSTALLDIRLIB = $(INSTALLPREFIX)/$(LIBDIR)
INSTALLDIRBIN = $(INSTALLPREFIX)/bin
INSTALLDIRMAN = $(INSTALLPREFIX)/share/man
PKGCONFIGDIR = $(INSTALLDIRLIB)/pkgconfig
FILESTOINSTALL = $(LIBRARY) $(EXECUTABLES)
ifneq ($(OS), AmigaOS)
FILESTOINSTALL := $(FILESTOINSTALL) $(SHAREDLIBRARY)
ifeq (, $(findstring amiga, $(OS)))
FILESTOINSTALL += $(SHAREDLIBRARY) $(BUILD)/miniupnpc.pc
endif
.PHONY: install clean depend all check everything \
installpythonmodule
# validateminixml validateminiwget
.PHONY: install clean depend all check test everything \
installpythonmodule updateversion
all: $(LIBRARY) $(EXECUTABLES)
check: validateminixml validateminiwget
test: check
check: validateminixml validateminiwget validateupnpreplyparse \
validateportlistingparse validateigddescparse validateaddr_is_reserved
everything: all $(EXECUTABLES_ADDTESTS)
pythonmodule: $(LIBRARY) miniupnpcmodule.c setup.py
python setup.py build
pythonmodule: $(LIBRARY) $(SRCDIR)/miniupnpcmodule.c setup.py
MAKE=$(MAKE) python setup.py build
touch $@
installpythonmodule: pythonmodule
python setup.py install
MAKE=$(MAKE) python setup.py install
validateminixml: minixmlvalid
@echo "minixml validation test"
./minixmlvalid
pythonmodule3: $(LIBRARY) $(SRCDIR)/miniupnpcmodule.c setup.py
MAKE=$(MAKE) python3 setup.py build
touch $@
validateminiwget: testminiwget minihttptestserver testminiwget.sh
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"
./testminiwget.sh
./$<
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) miniupnpcstrings.h
$(RM) $(LIBRARY) $(SHAREDLIBRARY) $(EXECUTABLES) $(OBJS) $(BUILDINCLUDES)
$(RM) $(EXECUTABLES_ADDTESTS)
# clean python stuff
$(RM) pythonmodule validateminixml
$(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
install: $(FILESTOINSTALL)
$(INSTALL) -d $(INSTALLDIRINC)
$(INSTALL) -m 644 $(HEADERS) $(INSTALLDIRINC)
$(INSTALL) -d $(INSTALLDIRLIB)
$(INSTALL) -m 644 $(LIBRARY) $(INSTALLDIRLIB)
ifneq ($(OS), AmigaOS)
$(INSTALL) -m 644 $(SHAREDLIBRARY) $(INSTALLDIRLIB)/$(SONAME)
ln -fs $(SONAME) $(INSTALLDIRLIB)/$(SHAREDLIBRARY)
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 $(INSTALLDIRBIN)
ifeq ($(OS), AmigaOS)
$(INSTALL) -m 755 upnpc-static $(INSTALLDIRBIN)/upnpc
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRBIN)
ifneq (, $(findstring amiga, $(OS)))
$(INSTALL) -m 755 $(BUILD)/upnpc-static $(DESTDIR)$(INSTALLDIRBIN)/upnpc
else
$(INSTALL) -m 755 upnpc-shared $(INSTALLDIRBIN)/upnpc
$(INSTALL) -m 755 $(BUILD)/upnpc-shared $(DESTDIR)$(INSTALLDIRBIN)/upnpc
endif
$(INSTALL) -m 755 external-ip.sh $(INSTALLDIRBIN)/external-ip
$(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 $(INSTALLDIRINC)
$(RM) $(INSTALLDIRLIB)/$(LIBRARY)
$(RM) $(INSTALLDIRLIB)/$(SHAREDLIBRARY)
$(RM) -r $(DESTDIR)$(INSTALLDIRINC)
$(RM) $(DESTDIR)$(INSTALLDIRLIB)/$(LIBRARY)
$(RM) $(DESTDIR)$(INSTALLDIRLIB)/$(SHAREDLIBRARY)
depend:
makedepend -Y -- $(CFLAGS) -- $(SRCS) 2>/dev/null
$(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)
ifeq ($(OS), Darwin)
$(CC) -dynamiclib $(LDFLAGS) -Wl,-install_name,$(SONAME) -o $@ $^
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
upnpc-static: upnpc.o $(LIBRARY) $(LDLIBS)
$(CC) $(LDFLAGS) -o $@ $^
$(BUILD)/%.o: $(SRCDIR)/%.c $(BUILD)/%.d
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
upnpc-shared: upnpc.o $(SHAREDLIBRARY) $(LDLIBS)
$(CC) $(LDFLAGS) -o $@ $^
$(DEPS): $(BUILDINCLUDES)
testminixml: $(TESTMINIXMLOBJS)
$(BUILD)/%.d: $(SRCDIR)/%.c
@$(MKDIR) $(@D)
$(CC) $(CPPFLAGS) $(DEPFLAGS) -MT $@ -o $@ $<
testminiwget: $(TESTMINIWGETOBJS)
$(BUILD)/upnpc-static: $(BUILD)/upnpc.o $(LIBRARY)
$(CC) $(LDFLAGS) -o $@ $^ $(LOADLIBES) $(LDLIBS)
minixmlvalid: minixml.o minixmlvalid.o
$(BUILD)/upnpc-shared: $(BUILD)/upnpc.o $(SHAREDLIBRARY)
$(CC) $(LDFLAGS) -o $@ $^ $(LOADLIBES) $(LDLIBS)
testupnpreplyparse: $(TESTUPNPREPLYPARSE)
$(BUILD)/listdevices: $(BUILD)/listdevices.o $(LIBRARY)
testigddescparse: $(TESTIGDDESCPARSE)
$(BUILD)/testminixml: $(TESTMINIXMLOBJS)
miniupnpcstrings.h: miniupnpcstrings.h.in updateminiupnpcstrings.sh
$(SH) updateminiupnpcstrings.sh
$(BUILD)/testminiwget: $(TESTMINIWGETOBJS)
jar: $(SHAREDLIBRARY)
$(JAVA) -jar $(JNAERATOR) -library miniupnpc miniupnpc.h declspec.h upnpcommands.h upnpreplyparse.h igd_desc_parse.h miniwget.h upnperrors.h $(SHAREDLIBRARY) -package fr.free.miniupnp -o . -jar java/miniupnpc_$(OS).jar -v
$(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
# DO NOT DELETE THIS LINE -- make depend depends on it.
print-%:
@echo "$* = $($*)"
igd_desc_parse.o: igd_desc_parse.h
miniupnpc.o: miniupnpc.h declspec.h igd_desc_parse.h minissdpc.h miniwget.h
miniupnpc.o: minisoap.h minixml.h upnpcommands.h upnpreplyparse.h
miniupnpc.o: portlistingparse.h miniupnpctypes.h connecthostport.h
miniupnpc.o: receivedata.h
minixml.o: minixml.h
minisoap.o: minisoap.h miniupnpcstrings.h
miniwget.o: miniupnpcstrings.h miniwget.h declspec.h connecthostport.h
miniwget.o: receivedata.h
upnpc.o: miniwget.h declspec.h miniupnpc.h igd_desc_parse.h upnpcommands.h
upnpc.o: upnpreplyparse.h portlistingparse.h miniupnpctypes.h upnperrors.h
upnpcommands.o: upnpcommands.h upnpreplyparse.h portlistingparse.h declspec.h
upnpcommands.o: miniupnpctypes.h miniupnpc.h igd_desc_parse.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 declspec.h igd_desc_parse.h codelength.h
upnperrors.o: upnperrors.h declspec.h upnpcommands.h upnpreplyparse.h
upnperrors.o: portlistingparse.h miniupnpctypes.h miniupnpc.h
upnperrors.o: igd_desc_parse.h
testigddescparse.o: igd_desc_parse.h minixml.h miniupnpc.h declspec.h
testminiwget.o: miniwget.h declspec.h
connecthostport.o: connecthostport.h
receivedata.o: receivedata.h
ifneq ($(MAKECMDGOALS),clean)
-include $(DEPS)
endif

View file

@ -1,93 +1,181 @@
# $Id: Makefile.mingw,v 1.16 2011/04/18 17:39:31 nanard Exp $
# $Id: Makefile.mingw,v 1.35 2022/10/16 05:28:15 nanard Exp $
# Miniupnp project.
# http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
# (c) 2005-2011 Thomas Bernard
# http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
# (c) 2005-2020 Thomas Bernard
# This Makefile is made for MinGW
#
CC = gcc
# To cross compile on a *nix machine :
# make -f Makefile.mingw DLLWRAP=mingw32-dllwrap CC=mingw32-gcc AR=mingw32-ar WINDRES=mingw32-windres
#
SRCDIR = src
INCDIR = include
CC ?= gcc
SETUP_COMPILER_FLAG?=
DLLWRAP = dllwrap
#CFLAGS = -Wall -g -DDEBUG -D_WIN32_WINNT=0X501
CFLAGS = -Wall -Os -DNDEBUG -D_WIN32_WINNT=0X501
LDLIBS = -lws2_32 -liphlpapi
WINDRES = windres
SH = /bin/sh
# -lwsock32
# -liphlpapi is used for GetBestRoute()
ZIP = zip
ifeq ($(OS),Windows_NT)
RM = del
else
RM = rm -f
endif
CFLAGS ?= -Os
CFLAGS += -Wall
CFLAGS += -W -Wstrict-prototypes
CPPFLAGS += -DNDEBUG -D_WIN32_WINNT=0x501
CPPFLAGS += -Iinclude
CPPFLAGS += -I.
# -liphlpapi is needed for GetBestRoute() and GetIpAddrTable()
LDLIBS = -lws2_32 -liphlpapi
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
OBJSDLL=$(addprefix dll/, $(OBJS))
connecthostport.o portlistingparse.o receivedata.o \
upnpdev.o addr_is_reserved.o
OBJSDLL=$(addprefix dll-, $(OBJS)) winres.o
BINARIES=upnpc-static.exe upnpc-shared.exe \
listdevices-static.exe listdevices-shared.exe \
miniupnpc.dll libminiupnpc.a \
testminixml.exe
ifneq ($(GITHUB_SHA),)
COMMITREF=$(GITHUB_SHA)
else
ifneq ($(CI_COMMIT_SHORT_SHA),)
COMMITREF=$(CI_COMMIT_SHORT_SHA)
else
COMMITREF=$(shell git rev-parse --short HEAD)
endif
endif
DISTFILE:=$(shell echo "miniupnpc-bin-win32-`cat VERSION`-$(COMMITREF).zip")
all: init upnpc-static upnpc-shared testminixml libminiupnpc.a miniupnpc.dll
LIBDIR ?= lib
# install directories
ifeq ($(strip $(PREFIX)),)
INSTALLPREFIX ?= /usr
else
INSTALLPREFIX ?= $(PREFIX)
endif
init:
mkdir dll
echo init > init
.PHONY: all dist clean
all: $(BINARIES)
dist: $(DISTFILE)
clean:
$(RM) upnpc testminixml *.o
$(RM) dll\*.o
$(RM) miniupnpcstrings.h
$(RM) *.o
$(RM) *.exe
$(RM) miniupnpc.dll
$(RM) miniupnpc.dll miniupnpc.lib miniupnpc.dll.def
$(RM) libminiupnpc.a
$(RM) $(DISTFILE)
$(DISTFILE): $(BINARIES)
$(ZIP) $@ *.exe *.dll *.lib *.def *.a LICENSE README Changelog.txt
libminiupnpc.a: $(OBJS)
$(AR) cr $@ $?
pythonmodule: libminiupnpc.a
$(PYTHON) setupmingw32.py build --compiler=mingw32
$(PYTHON) setupmingw32.py build $(SETUP_COMPILER_FLAG)
$(PYTHON) setupmingw32.py install --skip-build
$(PYTHON) setupmingw32.py bdist_wheel --skip-build
miniupnpc.dll: libminiupnpc.a $(OBJSDLL)
$(DLLWRAP) -k --driver-name "$(CC)" \
miniupnpc.dll: miniupnpc.def $(OBJSDLL)
$(DLLWRAP) -k --driver-name $(CC) \
--def miniupnpc.def \
--output-def miniupnpc.dll.def \
--implib miniupnpc.lib -o $@ \
$(OBJSDLL) $(LDLIBS)
miniupnpc.lib: miniupnpc.dll
echo $@ generated with $<
dll/upnpc.o: upnpc.o
echo $@ generated with $<
%.o: $(SRCDIR)/%.c
$(CC) $(CFLAGS) $(CPPFLAGS) -DMINIUPNP_STATICLIB -c -o $@ $<
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -DSTATICLIB -c -o $@ $<
$(CC) $(CFLAGS) $(CPPFLAGS) -DMINIUPNP_EXPORTS -c -o dll/$@ $<
dll-%.o: $(SRCDIR)/%.c
$(CC) $(CFLAGS) $(CPPFLAGS) -DMINIUPNP_EXPORTS -c -o $@ $<
upnpc.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -DSTATICLIB -c -o $@ $<
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o dll/$@ $<
%-shared.o: $(SRCDIR)/%.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
upnpc-static: upnpc.o libminiupnpc.a
# --enable-stdcall-fixup
%-static.exe: %.o libminiupnpc.a
$(CC) -static -o $@ $^ $(LDLIBS)
%-shared.exe: %-shared.o miniupnpc.lib
$(CC) -o $@ $^ $(LDLIBS)
upnpc-shared: dll/upnpc.o miniupnpc.lib
$(CC) -o $@ $^ $(LDLIBS)
# To make miniupnpcstrings.h from miniupnpcstrings.h.in we either
# use a custom executable (if running make under windows) or use
# sed (if cross compiling from another platform).
ifeq ($(OS),Windows_NT)
wingenminiupnpcstrings.exe: wingenminiupnpcstrings.c
$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $^
wingenminiupnpcstrings: wingenminiupnpcstrings.o
miniupnpcstrings.h: miniupnpcstrings.h.in wingenminiupnpcstrings.exe VERSION
.\wingenminiupnpcstrings.exe $< $@ rc_version.h
wingenminiupnpcstrings.o: wingenminiupnpcstrings.c
rc_version.h: miniupnpcstrings.h
else
miniupnpcstrings.h: miniupnpcstrings.h.in VERSION
sed 's|OS_STRING ".*"|OS_STRING "Windows/Mingw32"|' $< | \
sed 's|MINIUPNPC_VERSION_STRING ".*"|MINIUPNPC_VERSION_STRING "$(shell cat VERSION)"|' > $@
miniupnpcstrings.h: miniupnpcstrings.h.in wingenminiupnpcstrings
-$(SH) updateminiupnpcstrings.sh
-wingenminiupnpcstrings $< $@
rc_version.h: VERSION
echo "#define LIBMINIUPNPC_DOTTED_VERSION \"$(shell cat VERSION)\"" > $@.tmp
echo "#define LIBMINIUPNPC_MAJOR_VERSION $(shell cat VERSION|cut -d. -f1)" >> $@.tmp
echo "#define LIBMINIUPNPC_MINOR_VERSION $(shell cat VERSION|cut -d. -f2)" >> $@.tmp
echo "#define LIBMINIUPNPC_MICRO_VERSION $(shell cat VERSION|cut -d. -f3)" >> $@.tmp
mv $@.tmp $@
endif
minixml.o: minixml.c minixml.h miniupnpcstrings.h
miniupnpc.pc: VERSION
$(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 "Version: $(shell cat VERSION)" >> $@
echo "Libs: -L\$${libdir} -lminiupnpc" >> $@
echo "Cflags: -I\$${includedir}" >> $@
upnpc.o: upnpc.c miniwget.h minisoap.h miniupnpc.h igd_desc_parse.h upnpreplyparse.h upnpcommands.h upnperrors.h
winres.o: miniupnpc.rc rc_version.h
$(WINDRES) -D INTERNAL_NAME=\\\"miniupnpc.dll\\0\\\" -i $< -o $@
miniwget.o: miniwget.c miniwget.h miniupnpcstrings.h connecthostport.h
testminixml.exe: testminixml.o minixml.o igd_desc_parse.o
$(CC) -static -o $@ $^
minisoap.o: minisoap.c minisoap.h miniupnpcstrings.h
minixml.o: $(SRCDIR)/minixml.c $(SRCDIR)/minixml.h
miniupnpc.o: miniupnpc.c miniupnpc.h minisoap.h miniwget.h minixml.h
upnpc.o: include/miniwget.h $(SRCDIR)/minisoap.h include/miniupnpc.h include/igd_desc_parse.h
upnpc.o: include/upnpreplyparse.h include/upnpcommands.h include/upnperrors.h miniupnpcstrings.h
igd_desc_parse.o: igd_desc_parse.c igd_desc_parse.h
miniwget.o: $(SRCDIR)/miniwget.c include/miniwget.h miniupnpcstrings.h $(SRCDIR)/connecthostport.h
testminixml: minixml.o igd_desc_parse.o testminixml.c
minisoap.o: $(SRCDIR)/minisoap.c $(SRCDIR)/minisoap.h miniupnpcstrings.h
upnpreplyparse.o: upnpreplyparse.c upnpreplyparse.h minixml.h
miniupnpc.o: $(SRCDIR)/miniupnpc.c include/miniupnpc.h $(SRCDIR)/minisoap.h \
include/miniwget.h $(SRCDIR)/minixml.h $(SRCDIR)/addr_is_reserved.h
upnpcommands.o: upnpcommands.c upnpcommands.h upnpreplyparse.h miniupnpc.h portlistingparse.h
igd_desc_parse.o: $(SRCDIR)/igd_desc_parse.c include/igd_desc_parse.h
upnpreplyparse.o: $(SRCDIR)/upnpreplyparse.c include/upnpreplyparse.h $(SRCDIR)/minixml.h
upnpcommands.o: $(SRCDIR)/upnpcommands.c include/upnpcommands.h include/upnpreplyparse.h \
include/miniupnpc.h include/portlistingparse.h
minissdpc.o: $(SRCDIR)/minissdpc.c $(SRCDIR)/minissdpc.h $(SRCDIR)/receivedata.h
upnpdev.o: $(SRCDIR)/upnpdev.c include/upnpdev.h

View file

@ -1,18 +1,20 @@
Project: miniupnp
Project web page: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
Project web page: http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
github: https://github.com/miniupnp/miniupnp
Author: Thomas Bernard
Copyright (c) 2005-2011 Thomas Bernard
Copyright (c) 2005-2023 Thomas Bernard
This software is subject to the conditions detailed in the
LICENSE file provided within this distribution.
For the comfort of Win32 users, bsdqueue.h is included in the distribution.
Its licence is included in the header of the file.
bsdqueue.h is a copy of the sys/queue.h of an OpenBSD system.
* miniupnp Client *
* miniUPnP Client - miniUPnPc *
To compile, simply run 'gmake' (could be 'make' on your system).
Under win32, to compile with MinGW, type "mingw32make.bat".
MS Visual C solution and project files are supplied in the msvc/ subdirectory.
The miniupnpc library is available as a static library or as a DLL :
define MINIUPNP_STATICLIB if you want to link against the static library.
The compilation is known to work under linux, FreeBSD,
OpenBSD, MacOS X, AmigaOS and cygwin.
The official AmigaOS4.1 SDK was used for AmigaOS4 and GeekGadgets for AmigaOS3.
@ -23,7 +25,7 @@ To install the library and headers on the system use :
> make install
> exit
alternatively, to install in a specific location, use :
alternatively, to install into a specific location, use :
> INSTALLPREFIX=/usr/local make install
upnpc.c is a sample client using the libminiupnpc.
@ -31,6 +33,7 @@ To use the libminiupnpc in your application, link it with
libminiupnpc.a (or .so) and use the following functions found in miniupnpc.h,
upnpcommands.h and miniwget.h :
- upnpDiscover()
- UPNP_GetValidIGD()
- miniwget()
- parserootdesc()
- GetUPNPUrls()
@ -41,9 +44,10 @@ and -lminiupnpc for the link
Discovery process is speeded up when MiniSSDPd is running on the machine.
* Python module *
you can build a python module with 'make pythonmodule'
you can build a python module with 'make pythonmodule'
and install it with 'make installpythonmodule'.
setup.py (and setupmingw32.py) are included in the distribution.
@ -55,5 +59,34 @@ If you are using libminiupnpc in your application, please
send me an email !
For any question, you can use the web forum :
http://miniupnp.tuxfamily.org/forum/
https://miniupnp.tuxfamily.org/forum/
Bugs should be reported on GitHub :
https://github.com/miniupnp/miniupnp/issues
* Linux firewall configuration for UPnP clients *
Due to how UPnP protocol is designed, unicast responses to UPnP multicast client
requests are not tracked by Linux netfilter. And therefore netfilter executes
default action for them (which is in most cases DROP response packet).
To workaround this limitation, custom ipset hash table can be used. It is
supported since Linux kernel >= 2.6.39.
Rules for IPv4:
$ ipset create upnp hash:ip,port timeout 3
$ iptables -A OUTPUT -d 239.255.255.250/32 -p udp -m udp --dport 1900 -j SET --add-set upnp src,src --exist
$ iptables -A INPUT -p udp -m set --match-set upnp dst,dst -j ACCEPT
$ iptables -A INPUT -d 239.255.255.250/32 -p udp -m udp --dport 1900 -j ACCEPT
Rules for IPv6:
$ ipset create upnp6 hash:ip,port timeout 3 family inet6
$ ip6tables -A OUTPUT -d ff02::c/128 -p udp -m udp --dport 1900 -j SET --add-set upnp6 src,src --exist
$ ip6tables -A OUTPUT -d ff05::c/128 -p udp -m udp --dport 1900 -j SET --add-set upnp6 src,src --exist
$ ip6tables -A INPUT -p udp -m set --match-set upnp6 dst,dst -j ACCEPT
$ ip6tables -A INPUT -d ff02::c/128 -p udp -m udp --dport 1900 -j ACCEPT
$ ip6tables -A INPUT -d ff05::c/128 -p udp -m udp --dport 1900 -j ACCEPT
Detailed description is available on:
https://serverfault.com/a/911286
https://unix.stackexchange.com/a/444804

View file

@ -1 +1 @@
1.6
2.2.5

View file

@ -0,0 +1,178 @@
$Id: apiversions.txt,v 1.10 2018/04/06 10:53:13 nanard Exp $
Differences in API between miniUPnPc versions
API version 17
change struct UPNPDev
move getHTTPResponse() to miniwget_private.h
updated macro :
#define MINIUPNPC_API_VERSION 17
API version 16
added "status_code" argument to getHTTPResponse(), miniwget() and miniwget_getaddr()
updated macro :
#define MINIUPNPC_API_VERSION 16
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()
upnpDiscoverDevices()
getDevicesFromMiniSSDPD() :
connectToMiniSSDPD() / disconnectFromMiniSSDPD()
requestDevicesFromMiniSSDPD() / receiveDevicesFromMiniSSDPD()
updated macro :
#define MINIUPNPC_API_VERSION 14
API version 13
miniupnpc.h:
add searchalltype param to upnpDiscoverDevices() function
updated macro :
#define MINIUPNPC_API_VERSION 13
API version 12
miniupnpc.h :
add upnpDiscoverAll() / upnpDiscoverDevice() / upnpDiscoverDevices()
functions
updated macros :
#define MINIUPNPC_API_VERSION 12
API version 11
upnpreplyparse.h / portlistingparse.h :
removed usage of sys/queue.h / bsdqueue.h
miniupnpc.h:
updated macros :
#define MINIUPNPC_API_VERSION 11
====================== miniUPnPc version 1.9 ======================
API version 10
upnpcommands.h:
added argument remoteHost to UPNP_GetSpecificPortMappingEntry()
miniupnpc.h:
updated macros :
#define MINIUPNPC_VERSION "1.9"
#define MINIUPNPC_API_VERSION 10
====================== miniUPnPc version 1.8 ======================
API version 9
miniupnpc.h:
updated macros :
#define MINIUPNPC_VERSION "1.8"
#define MINIUPNPC_API_VERSION 9
added "unsigned int scope_id;" to struct UPNPDev
added scope_id argument to GetUPNPUrls()
====================== miniUPnPc version 1.7 ======================
API version 8
miniupnpc.h :
add new macros :
#define MINIUPNPC_VERSION "1.7"
#define MINIUPNPC_API_VERSION 8
add rootdescURL to struct UPNPUrls
====================== miniUPnPc version 1.6 ======================
API version 8
Adding support for IPv6.
igd_desc_parse.h :
struct IGDdatas_service :
add char presentationurl[MINIUPNPC_URL_MAXSIZE];
struct IGDdatas :
add struct IGDdatas_service IPv6FC;
miniupnpc.h :
new macros :
#define UPNPDISCOVER_SUCCESS (0)
#define UPNPDISCOVER_UNKNOWN_ERROR (-1)
#define UPNPDISCOVER_SOCKET_ERROR (-101)
#define UPNPDISCOVER_MEMORY_ERROR (-102)
simpleUPnPcommand() prototype changed (but is normaly not used by API users)
add arguments ipv6 and error to upnpDiscover() :
struct UPNPDev *
upnpDiscover(int delay, const char * multicastif,
const char * minissdpdsock, int sameport,
int ipv6,
int * error);
add controlURL_6FC member to struct UPNPUrls :
struct UPNPUrls {
char * controlURL;
char * ipcondescURL;
char * controlURL_CIF;
char * controlURL_6FC;
};
upnpcommands.h :
add leaseDuration argument to UPNP_AddPortMapping()
add desc, enabled and leaseDuration arguments to UPNP_GetSpecificPortMappingEntry()
add UPNP_GetListOfPortMappings() function (IGDv2)
add IGDv2 IPv6 related functions :
UPNP_GetFirewallStatus()
UPNP_GetOutboundPinholeTimeout()
UPNP_AddPinhole()
UPNP_UpdatePinhole()
UPNP_DeletePinhole()
UPNP_CheckPinholeWorking()
UPNP_GetPinholePackets()
====================== miniUPnPc version 1.5 ======================
API version 5
new function :
int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *);
new macro in upnpcommands.h :
#define UPNPCOMMAND_HTTP_ERROR
====================== miniUPnPc version 1.4 ======================
Same API as version 1.3
====================== miniUPnPc version 1.3 ======================
API version 4
Use UNSIGNED_INTEGER type for
UPNP_GetTotalBytesSent(), UPNP_GetTotalBytesReceived(),
UPNP_GetTotalPacketsSent(), UPNP_GetTotalPacketsReceived()
Add remoteHost argument to UPNP_AddPortMapping() and UPNP_DeletePortMapping()
====================== miniUPnPc version 1.2 ======================
API version 3
added sameport argument to upnpDiscover()
struct UPNPDev *
upnpDiscover(int delay, const char * multicastif,
const char * minissdpdsock, int sameport);
====================== miniUPnPc Version 1.1 ======================
Same API as 1.0
====================== miniUPnPc Version 1.0 ======================
API version 2
struct UPNPDev {
struct UPNPDev * pNext;
char * descURL;
char * st;
char buffer[2];
};
struct UPNPDev * upnpDiscover(int delay, const char * multicastif,
const char * minissdpdsock);

View file

@ -1,531 +0,0 @@
/* $OpenBSD: queue.h,v 1.31 2005/11/25 08:06:25 otto Exp $ */
/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
/*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)queue.h 8.5 (Berkeley) 8/20/94
*/
#ifndef _SYS_QUEUE_H_
#define _SYS_QUEUE_H_
/*
* This file defines five types of data structures: singly-linked lists,
* lists, simple queues, tail queues, and circular queues.
*
*
* A singly-linked list is headed by a single forward pointer. The elements
* are singly linked for minimum space and pointer manipulation overhead at
* the expense of O(n) removal for arbitrary elements. New elements can be
* added to the list after an existing element or at the head of the list.
* Elements being removed from the head of the list should use the explicit
* macro for this purpose for optimum efficiency. A singly-linked list may
* only be traversed in the forward direction. Singly-linked lists are ideal
* for applications with large datasets and few or no removals or for
* implementing a LIFO queue.
*
* A list is headed by a single forward pointer (or an array of forward
* pointers for a hash table header). The elements are doubly linked
* so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before
* or after an existing element or at the head of the list. A list
* may only be traversed in the forward direction.
*
* A simple queue is headed by a pair of pointers, one the head of the
* list and the other to the tail of the list. The elements are singly
* linked to save space, so elements can only be removed from the
* head of the list. New elements can be added to the list before or after
* an existing element, at the head of the list, or at the end of the
* list. A simple queue may only be traversed in the forward direction.
*
* A tail queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or
* after an existing element, at the head of the list, or at the end of
* the list. A tail queue may be traversed in either direction.
*
* A circle queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or after
* an existing element, at the head of the list, or at the end of the list.
* A circle queue may be traversed in either direction, but has a more
* complex end of list detection.
*
* For details on the use of these macros, see the queue(3) manual page.
*/
#ifdef QUEUE_MACRO_DEBUG
#define _Q_INVALIDATE(a) (a) = ((void *)-1)
#else
#define _Q_INVALIDATE(a)
#endif
/*
* Singly-linked List definitions.
*/
#define SLIST_HEAD(name, type) \
struct name { \
struct type *slh_first; /* first element */ \
}
#define SLIST_HEAD_INITIALIZER(head) \
{ NULL }
#ifdef SLIST_ENTRY
#undef SLIST_ENTRY
#endif
#define SLIST_ENTRY(type) \
struct { \
struct type *sle_next; /* next element */ \
}
/*
* Singly-linked List access methods.
*/
#define SLIST_FIRST(head) ((head)->slh_first)
#define SLIST_END(head) NULL
#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
#define SLIST_FOREACH(var, head, field) \
for((var) = SLIST_FIRST(head); \
(var) != SLIST_END(head); \
(var) = SLIST_NEXT(var, field))
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
for ((varp) = &SLIST_FIRST((head)); \
((var) = *(varp)) != SLIST_END(head); \
(varp) = &SLIST_NEXT((var), field))
/*
* Singly-linked List functions.
*/
#define SLIST_INIT(head) { \
SLIST_FIRST(head) = SLIST_END(head); \
}
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
(elm)->field.sle_next = (slistelm)->field.sle_next; \
(slistelm)->field.sle_next = (elm); \
} while (0)
#define SLIST_INSERT_HEAD(head, elm, field) do { \
(elm)->field.sle_next = (head)->slh_first; \
(head)->slh_first = (elm); \
} while (0)
#define SLIST_REMOVE_NEXT(head, elm, field) do { \
(elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \
} while (0)
#define SLIST_REMOVE_HEAD(head, field) do { \
(head)->slh_first = (head)->slh_first->field.sle_next; \
} while (0)
#define SLIST_REMOVE(head, elm, type, field) do { \
if ((head)->slh_first == (elm)) { \
SLIST_REMOVE_HEAD((head), field); \
} else { \
struct type *curelm = (head)->slh_first; \
\
while (curelm->field.sle_next != (elm)) \
curelm = curelm->field.sle_next; \
curelm->field.sle_next = \
curelm->field.sle_next->field.sle_next; \
_Q_INVALIDATE((elm)->field.sle_next); \
} \
} while (0)
/*
* List definitions.
*/
#define LIST_HEAD(name, type) \
struct name { \
struct type *lh_first; /* first element */ \
}
#define LIST_HEAD_INITIALIZER(head) \
{ NULL }
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
/*
* List access methods
*/
#define LIST_FIRST(head) ((head)->lh_first)
#define LIST_END(head) NULL
#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
#define LIST_FOREACH(var, head, field) \
for((var) = LIST_FIRST(head); \
(var)!= LIST_END(head); \
(var) = LIST_NEXT(var, field))
/*
* List functions.
*/
#define LIST_INIT(head) do { \
LIST_FIRST(head) = LIST_END(head); \
} while (0)
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
(listelm)->field.le_next->field.le_prev = \
&(elm)->field.le_next; \
(listelm)->field.le_next = (elm); \
(elm)->field.le_prev = &(listelm)->field.le_next; \
} while (0)
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.le_prev = (listelm)->field.le_prev; \
(elm)->field.le_next = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &(elm)->field.le_next; \
} while (0)
#define LIST_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.le_next = (head)->lh_first) != NULL) \
(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
(head)->lh_first = (elm); \
(elm)->field.le_prev = &(head)->lh_first; \
} while (0)
#define LIST_REMOVE(elm, field) do { \
if ((elm)->field.le_next != NULL) \
(elm)->field.le_next->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = (elm)->field.le_next; \
_Q_INVALIDATE((elm)->field.le_prev); \
_Q_INVALIDATE((elm)->field.le_next); \
} while (0)
#define LIST_REPLACE(elm, elm2, field) do { \
if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
(elm2)->field.le_next->field.le_prev = \
&(elm2)->field.le_next; \
(elm2)->field.le_prev = (elm)->field.le_prev; \
*(elm2)->field.le_prev = (elm2); \
_Q_INVALIDATE((elm)->field.le_prev); \
_Q_INVALIDATE((elm)->field.le_next); \
} while (0)
/*
* Simple queue definitions.
*/
#define SIMPLEQ_HEAD(name, type) \
struct name { \
struct type *sqh_first; /* first element */ \
struct type **sqh_last; /* addr of last next element */ \
}
#define SIMPLEQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).sqh_first }
#define SIMPLEQ_ENTRY(type) \
struct { \
struct type *sqe_next; /* next element */ \
}
/*
* Simple queue access methods.
*/
#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
#define SIMPLEQ_END(head) NULL
#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
#define SIMPLEQ_FOREACH(var, head, field) \
for((var) = SIMPLEQ_FIRST(head); \
(var) != SIMPLEQ_END(head); \
(var) = SIMPLEQ_NEXT(var, field))
/*
* Simple queue functions.
*/
#define SIMPLEQ_INIT(head) do { \
(head)->sqh_first = NULL; \
(head)->sqh_last = &(head)->sqh_first; \
} while (0)
#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
(head)->sqh_last = &(elm)->field.sqe_next; \
(head)->sqh_first = (elm); \
} while (0)
#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.sqe_next = NULL; \
*(head)->sqh_last = (elm); \
(head)->sqh_last = &(elm)->field.sqe_next; \
} while (0)
#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
(head)->sqh_last = &(elm)->field.sqe_next; \
(listelm)->field.sqe_next = (elm); \
} while (0)
#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
(head)->sqh_last = &(head)->sqh_first; \
} while (0)
/*
* Tail queue definitions.
*/
#define TAILQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
}
#define TAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first }
#define TAILQ_ENTRY(type) \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
}
/*
* tail queue access methods
*/
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_END(head) NULL
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
/* XXX */
#define TAILQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#define TAILQ_EMPTY(head) \
(TAILQ_FIRST(head) == TAILQ_END(head))
#define TAILQ_FOREACH(var, head, field) \
for((var) = TAILQ_FIRST(head); \
(var) != TAILQ_END(head); \
(var) = TAILQ_NEXT(var, field))
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for((var) = TAILQ_LAST(head, headname); \
(var) != TAILQ_END(head); \
(var) = TAILQ_PREV(var, headname, field))
/*
* Tail queue functions.
*/
#define TAILQ_INIT(head) do { \
(head)->tqh_first = NULL; \
(head)->tqh_last = &(head)->tqh_first; \
} while (0)
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
(head)->tqh_first->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(head)->tqh_first = (elm); \
(elm)->field.tqe_prev = &(head)->tqh_first; \
} while (0)
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.tqe_next = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &(elm)->field.tqe_next; \
} while (0)
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
(elm)->field.tqe_next->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(listelm)->field.tqe_next = (elm); \
(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
} while (0)
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
(elm)->field.tqe_next = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
} while (0)
#define TAILQ_REMOVE(head, elm, field) do { \
if (((elm)->field.tqe_next) != NULL) \
(elm)->field.tqe_next->field.tqe_prev = \
(elm)->field.tqe_prev; \
else \
(head)->tqh_last = (elm)->field.tqe_prev; \
*(elm)->field.tqe_prev = (elm)->field.tqe_next; \
_Q_INVALIDATE((elm)->field.tqe_prev); \
_Q_INVALIDATE((elm)->field.tqe_next); \
} while (0)
#define TAILQ_REPLACE(head, elm, elm2, field) do { \
if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
(elm2)->field.tqe_next->field.tqe_prev = \
&(elm2)->field.tqe_next; \
else \
(head)->tqh_last = &(elm2)->field.tqe_next; \
(elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
*(elm2)->field.tqe_prev = (elm2); \
_Q_INVALIDATE((elm)->field.tqe_prev); \
_Q_INVALIDATE((elm)->field.tqe_next); \
} while (0)
/*
* Circular queue definitions.
*/
#define CIRCLEQ_HEAD(name, type) \
struct name { \
struct type *cqh_first; /* first element */ \
struct type *cqh_last; /* last element */ \
}
#define CIRCLEQ_HEAD_INITIALIZER(head) \
{ CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
#define CIRCLEQ_ENTRY(type) \
struct { \
struct type *cqe_next; /* next element */ \
struct type *cqe_prev; /* previous element */ \
}
/*
* Circular queue access methods
*/
#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
#define CIRCLEQ_LAST(head) ((head)->cqh_last)
#define CIRCLEQ_END(head) ((void *)(head))
#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
#define CIRCLEQ_EMPTY(head) \
(CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))
#define CIRCLEQ_FOREACH(var, head, field) \
for((var) = CIRCLEQ_FIRST(head); \
(var) != CIRCLEQ_END(head); \
(var) = CIRCLEQ_NEXT(var, field))
#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
for((var) = CIRCLEQ_LAST(head); \
(var) != CIRCLEQ_END(head); \
(var) = CIRCLEQ_PREV(var, field))
/*
* Circular queue functions.
*/
#define CIRCLEQ_INIT(head) do { \
(head)->cqh_first = CIRCLEQ_END(head); \
(head)->cqh_last = CIRCLEQ_END(head); \
} while (0)
#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
(elm)->field.cqe_next = (listelm)->field.cqe_next; \
(elm)->field.cqe_prev = (listelm); \
if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \
(head)->cqh_last = (elm); \
else \
(listelm)->field.cqe_next->field.cqe_prev = (elm); \
(listelm)->field.cqe_next = (elm); \
} while (0)
#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
(elm)->field.cqe_next = (listelm); \
(elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \
(head)->cqh_first = (elm); \
else \
(listelm)->field.cqe_prev->field.cqe_next = (elm); \
(listelm)->field.cqe_prev = (elm); \
} while (0)
#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
(elm)->field.cqe_next = (head)->cqh_first; \
(elm)->field.cqe_prev = CIRCLEQ_END(head); \
if ((head)->cqh_last == CIRCLEQ_END(head)) \
(head)->cqh_last = (elm); \
else \
(head)->cqh_first->field.cqe_prev = (elm); \
(head)->cqh_first = (elm); \
} while (0)
#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.cqe_next = CIRCLEQ_END(head); \
(elm)->field.cqe_prev = (head)->cqh_last; \
if ((head)->cqh_first == CIRCLEQ_END(head)) \
(head)->cqh_first = (elm); \
else \
(head)->cqh_last->field.cqe_next = (elm); \
(head)->cqh_last = (elm); \
} while (0)
#define CIRCLEQ_REMOVE(head, elm, field) do { \
if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \
(head)->cqh_last = (elm)->field.cqe_prev; \
else \
(elm)->field.cqe_next->field.cqe_prev = \
(elm)->field.cqe_prev; \
if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \
(head)->cqh_first = (elm)->field.cqe_next; \
else \
(elm)->field.cqe_prev->field.cqe_next = \
(elm)->field.cqe_next; \
_Q_INVALIDATE((elm)->field.cqe_prev); \
_Q_INVALIDATE((elm)->field.cqe_next); \
} while (0)
#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \
if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \
CIRCLEQ_END(head)) \
(head).cqh_last = (elm2); \
else \
(elm2)->field.cqe_next->field.cqe_prev = (elm2); \
if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \
CIRCLEQ_END(head)) \
(head).cqh_first = (elm2); \
else \
(elm2)->field.cqe_prev->field.cqe_next = (elm2); \
_Q_INVALIDATE((elm)->field.cqe_prev); \
_Q_INVALIDATE((elm)->field.cqe_next); \
} while (0)
#endif /* !_SYS_QUEUE_H_ */

View file

@ -1,24 +0,0 @@
/* $Id: codelength.h,v 1.1 2008/10/06 22:04:06 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas BERNARD
* copyright (c) 2005-2008 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENCE file. */
#ifndef __CODELENGTH_H__
#define __CODELENGTH_H__
/* Encode length by using 7bit per Byte :
* Most significant bit of each byte specifies that the
* following byte is part of the code */
#define DECODELENGTH(n, p) n = 0; \
do { n = (n << 7) | (*p & 0x7f); } \
while(*(p++)&0x80);
#define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \
if(n>=2097152) *(p++) = (n >> 21) | 0x80; \
if(n>=16384) *(p++) = (n >> 14) | 0x80; \
if(n>=128) *(p++) = (n >> 7) | 0x80; \
*(p++) = n & 0x7f;
#endif

View file

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

View file

@ -1,15 +0,0 @@
#ifndef __DECLSPEC_H__
#define __DECLSPEC_H__
#if defined(WIN32) && !defined(STATICLIB)
#ifdef MINIUPNP_EXPORTS
#define LIBSPEC __declspec(dllexport)
#else
#define LIBSPEC __declspec(dllimport)
#endif
#else
#define LIBSPEC
#endif
#endif

View file

@ -1,4 +1,4 @@
#!/bin/sh
# $Id: external-ip.sh,v 1.1 2010/08/05 12:57:41 nanard Exp $
# $Id: external-ip.sh,v 1.2 2017/11/02 15:33:09 nanard Exp $
# (c) 2010 Reuben Hawkins
upnpc -s | grep ExternalIPAddress | sed 's/[^0-9\.]//g'
upnpc -s | sed -n -e 's/^ExternalIPAddress = \([0-9.]*\)$/\1/p'

View file

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

View file

@ -1,15 +1,17 @@
/* $Id: miniupnpc.h,v 1.23 2011/04/11 08:21:46 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/
/* $Id: miniupnpc.h,v 1.61 2022/10/21 21:15:02 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-2011 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__
#define __MINIUPNPC_H__
#ifndef MINIUPNPC_H_INCLUDED
#define MINIUPNPC_H_INCLUDED
#include "declspec.h"
#include "miniupnpc_declspec.h"
#include "igd_desc_parse.h"
#include "upnpdev.h"
/* error codes : */
#define UPNPDISCOVER_SUCCESS (0)
@ -17,6 +19,16 @@
#define UPNPDISCOVER_SOCKET_ERROR (-101)
#define UPNPDISCOVER_MEMORY_ERROR (-102)
/* versions : */
#define MINIUPNPC_VERSION "2.2.5"
#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
@ -29,13 +41,6 @@ simpleUPnPcommand(int, const char *, const char *,
const char *, struct UPNParg *,
int *);
struct UPNPDev {
struct UPNPDev * pNext;
char * descURL;
char * st;
char buffer[2];
};
/* upnpDiscover()
* discover UPnP devices on the network.
* The discovered devices are returned as a chained list.
@ -47,21 +52,43 @@ struct UPNPDev {
* 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. */
LIBSPEC struct UPNPDev *
* 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,
int ipv6,
const char * minissdpdsock, int localport,
int ipv6, unsigned char ttl,
int * error);
/* freeUPNPDevlist()
* free list returned by upnpDiscover() */
LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist);
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. */
LIBSPEC void parserootdesc(const char *, int, struct IGDdatas *);
MINIUPNP_LIBSPEC void parserootdesc(const char *, int, struct IGDdatas *);
/* structure used to get fast access to urls
* controlURL: controlURL of the WANIPConnection
@ -74,6 +101,7 @@ struct UPNPUrls {
char * ipcondescURL;
char * controlURL_CIF;
char * controlURL_6FC;
char * rootdescURL;
};
/* UPNP_GetValidIGD() :
@ -88,7 +116,7 @@ struct UPNPUrls {
* passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
* free allocated memory.
*/
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_GetValidIGD(struct UPNPDev * devlist,
struct UPNPUrls * urls,
struct IGDdatas * data,
@ -96,21 +124,25 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
/* UPNP_GetIGDFromUrl()
* Used when skipping the discovery process.
* When succeding, urls, data, and lanaddr arguments are set.
* return value :
* 0 - Not ok
* 1 - OK */
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_GetIGDFromUrl(const char * rootdescurl,
struct UPNPUrls * urls,
struct IGDdatas * data,
char * lanaddr, int lanaddrlen);
LIBSPEC void GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, const char *);
MINIUPNP_LIBSPEC void
GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *,
const char *, unsigned int);
LIBSPEC void FreeUPNPUrls(struct UPNPUrls *);
MINIUPNP_LIBSPEC void
FreeUPNPUrls(struct UPNPUrls *);
/* return 0 or 1 */
LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *);
MINIUPNP_LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *);
#ifdef __cplusplus

View file

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

View file

@ -1,13 +1,15 @@
/* $Id: miniupnpctypes.h,v 1.1 2011/02/15 11:10:40 nanard Exp $ */
/* $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) 2011 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__
#define __MINIUPNPCTYPES_H__
#ifndef MINIUPNPCTYPES_H_INCLUDED
#define MINIUPNPCTYPES_H_INCLUDED
#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
/* 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

View file

@ -0,0 +1,27 @@
/* $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

View file

@ -1,22 +1,16 @@
/* $Id: portlistingparse.h,v 1.4 2011/02/15 23:03:56 nanard Exp $ */
/* $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 Thomas Bernard
* (c) 2011-2015 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#ifndef __PORTLISTINGPARSE_H__
#define __PORTLISTINGPARSE_H__
#ifndef PORTLISTINGPARSE_H_INCLUDED
#define PORTLISTINGPARSE_H_INCLUDED
#include "declspec.h"
#include "miniupnpc_declspec.h"
/* for the definition of UNSIGNED_INTEGER */
#include "miniupnpctypes.h"
#if defined(NO_SYS_QUEUE_H) || defined(WIN32) || defined(__HAIKU__)
#include "bsdqueue.h"
#else
#include <sys/queue.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -37,11 +31,11 @@ typedef enum { PortMappingEltNone,
PortMappingEntry, NewRemoteHost,
NewExternalPort, NewProtocol,
NewInternalPort, NewInternalClient,
NewEnabled, NewDescription,
NewEnabled, NewDescription,
NewLeaseTime } portMappingElt;
struct PortMapping {
LIST_ENTRY(PortMapping) entries;
struct PortMapping * l_next; /* list next element */
UNSIGNED_INTEGER leaseTime;
unsigned short externalPort;
unsigned short internalPort;
@ -53,15 +47,15 @@ struct PortMapping {
};
struct PortMappingParserData {
LIST_HEAD(portmappinglisthead, PortMapping) head;
struct PortMapping * l_head; /* list head */
portMappingElt curelt;
};
LIBSPEC void
MINIUPNP_LIBSPEC void
ParsePortListing(const char * buffer, int bufsize,
struct PortMappingParserData * pdata);
LIBSPEC void
MINIUPNP_LIBSPEC void
FreePortListing(struct PortMappingParserData * pdata);
#ifdef __cplusplus

View file

@ -1,15 +1,13 @@
/* $Id: upnpcommands.h,v 1.23 2011/04/11 09:14:00 nanard Exp $ */
/* $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-2011 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__
#define __UPNPCOMMANDS_H__
#ifndef UPNPCOMMANDS_H_INCLUDED
#define UPNPCOMMANDS_H_INCLUDED
#include "upnpreplyparse.h"
#include "portlistingparse.h"
#include "declspec.h"
#include "miniupnpc_declspec.h"
#include "miniupnpctypes.h"
/* MiniUPnPc return codes : */
@ -17,24 +15,28 @@
#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
LIBSPEC UNSIGNED_INTEGER
struct PortMappingParserData;
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalBytesSent(const char * controlURL,
const char * servicetype);
LIBSPEC UNSIGNED_INTEGER
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalBytesReceived(const char * controlURL,
const char * servicetype);
LIBSPEC UNSIGNED_INTEGER
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalPacketsSent(const char * controlURL,
const char * servicetype);
LIBSPEC UNSIGNED_INTEGER
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalPacketsReceived(const char * controlURL,
const char * servicetype);
@ -43,7 +45,7 @@ UPNP_GetTotalPacketsReceived(const char * controlURL,
* Return values :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
* or a UPnP Error code */
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_GetStatusInfo(const char * controlURL,
const char * servicetype,
char * status,
@ -55,23 +57,23 @@ UPNP_GetStatusInfo(const char * controlURL,
* Return Values :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
* or a UPnP Error code */
LIBSPEC int
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
* 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. */
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_GetExternalIPAddress(const char * controlURL,
const char * servicetype,
char * extIpAdd);
@ -82,7 +84,7 @@ UPNP_GetExternalIPAddress(const char * controlURL,
* return values :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
* or a UPnP Error Code. */
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_GetLinkLayerMaxBitRates(const char* controlURL,
const char* servicetype,
unsigned int * bitrateDown,
@ -95,33 +97,75 @@ UPNP_GetLinkLayerMaxBitRates(const char* controlURL,
* 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
* 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 */
LIBSPEC int
* 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);
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().
@ -132,24 +176,46 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
*
* List of possible UPnP errors for DeletePortMapping :
* 402 Invalid Args - See UPnP Device Architecture section on Control.
* 606 Action not authorized - The action requested REQUIRES authorization
* and the sender was not authorized.
* 714 NoSuchEntryInArray - The specified value does not exist in the array */
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
const char * extPort, const char * proto,
const char * remoteHost);
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 */
LIBSPEC int
UPNP_GetPortMappingNumberOfEntries(const char* controlURL,
const char* servicetype,
unsigned int * num);
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)
@ -158,12 +224,21 @@ UPNP_GetPortMappingNumberOfEntries(const char* controlURL,
*
* return value :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
* or a UPnP Error Code. */
LIBSPEC int
* 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,
@ -188,9 +263,11 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
*
* Possible UPNP Error codes :
* 402 Invalid Args - See UPnP Device Architecture section on Control.
* 606 Action not authorized - The action requested REQUIRES authorization
* and the sender was not authorized.
* 713 SpecifiedArrayIndexInvalid - The specified array index is out of bounds
*/
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_GetGenericPortMappingEntry(const char * controlURL,
const char * servicetype,
const char * index,
@ -212,7 +289,7 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL,
* 733 InconsistantParameters - NewStartPort and NewEndPort values are not
* consistent.
*/
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_GetListOfPortMappings(const char * controlURL,
const char * servicetype,
const char * startPort,
@ -221,14 +298,14 @@ UPNP_GetListOfPortMappings(const char * controlURL,
const char * numberOfPorts,
struct PortMappingParserData * data);
/* IGD:2, functions for service WANIPv6FirewallControl:1 */
LIBSPEC int
/* IGD:2, functions for service WANIPv6FirewallControl:1 */
MINIUPNP_LIBSPEC int
UPNP_GetFirewallStatus(const char * controlURL,
const char * servicetype,
int * firewallEnabled,
int * firewallEnabled,
int * inboundPinholeAllowed);
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype,
const char * remoteHost,
const char * remotePort,
@ -237,7 +314,7 @@ UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype
const char * proto,
int * opTimeout);
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_AddPinhole(const char * controlURL, const char * servicetype,
const char * remoteHost,
const char * remotePort,
@ -247,19 +324,19 @@ UPNP_AddPinhole(const char * controlURL, const char * servicetype,
const char * leaseTime,
char * uniqueID);
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_UpdatePinhole(const char * controlURL, const char * servicetype,
const char * uniqueID,
const char * leaseTime);
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID);
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype,
const char * uniqueID, int * isWorking);
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_GetPinholePackets(const char * controlURL, const char * servicetype,
const char * uniqueID, int * packets);

View file

@ -0,0 +1,44 @@
/* $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 */

View file

@ -1,23 +1,23 @@
/* $Id: upnperrors.h,v 1.2 2008/07/02 23:31:15 nanard Exp $ */
/* (c) 2007 Thomas Bernard
/* $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__
#define __UPNPERRORS_H__
#ifndef UPNPERRORS_H_INCLUDED
#define UPNPERRORS_H_INCLUDED
#include "declspec.h"
#include "miniupnpc_declspec.h"
#ifdef __cplusplus
extern "C" {
#endif
/* strupnperror()
* Return a string description of the UPnP error code
* Return a string description of the UPnP error code
* or NULL for undefinded errors */
LIBSPEC const char * strupnperror(int err);
MINIUPNP_LIBSPEC const char * strupnperror(int err);
#ifdef __cplusplus
}

View file

@ -1,34 +1,31 @@
/* $Id: upnpreplyparse.h,v 1.11 2011/02/07 16:17:06 nanard Exp $ */
/* $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-2011 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#ifndef __UPNPREPLYPARSE_H__
#define __UPNPREPLYPARSE_H__
#if defined(NO_SYS_QUEUE_H) || defined(WIN32) || defined(__HAIKU__)
#include "bsdqueue.h"
#else
#include <sys/queue.h>
#endif
#ifndef UPNPREPLYPARSE_H_INCLUDED
#define UPNPREPLYPARSE_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
struct NameValue {
LIST_ENTRY(NameValue) entries;
char name[64];
char value[64];
struct NameValue * l_next;
char name[64];
char value[128];
};
struct NameValueParserData {
LIST_HEAD(listhead, NameValue) head;
char curelt[64];
struct NameValue * l_head;
char curelt[64];
char * portListing;
int portListingLength;
int topelt;
const char * cdata;
int cdatalen;
};
/* ParseNameValue() */
@ -45,10 +42,12 @@ char *
GetValueFromNameValueList(struct NameValueParserData * pdata,
const char * Name);
#if 0
/* GetValueFromNameValueListIgnoreNS() */
char *
GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
const char * Name);
#endif
/* DisplayNameValueList() */
#ifdef DEBUG

View file

@ -1,4 +1,6 @@
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import fr.free.miniupnp.*;
/**
@ -27,7 +29,7 @@ public class JavaBridgeTest {
return;
}
devlist = miniupnpc.upnpDiscover(UPNP_DELAY, (String) null, (String) null, 0, null);
devlist = miniupnpc.upnpDiscover(UPNP_DELAY, (String) null, (String) null, 0, 0, (byte)2, IntBuffer.allocate(1));
if (devlist != null) {
System.out.println("List of UPNP devices found on the network :");
for (UPNPDev device = devlist; device != null; device = device.pNext) {
@ -70,12 +72,12 @@ public class JavaBridgeTest {
System.out.println("AddPortMapping() failed with code " + ret);
ret = miniupnpc.UPNP_GetSpecificPortMappingEntry(
urls.controlURL.getString(0), new String(data.first.servicetype),
args[0], args[1], intClient, intPort,
args[0], args[1], null, intClient, intPort,
desc, enabled, leaseDuration);
if (ret != MiniupnpcLibrary.UPNPCOMMAND_SUCCESS)
System.out.println("GetSpecificPortMappingEntry() failed with code " + ret);
System.out.println("InternalIP:Port = " +
new String(intClient.array()) + ":" + new String(intPort.array()) +
new String(intClient.array()) + ":" + new String(intPort.array()) +
" (" + new String(desc.array()) + ")");
ret = miniupnpc.UPNP_DeletePortMapping(
urls.controlURL.getString(0),

View file

@ -0,0 +1,8 @@
@echo off
set JAVA=java
set JAVAC=javac
REM notice the semicolon for Windows. Write once, run ... oh nevermind
set CP=miniupnpc_win32.jar;.
%JAVAC% -cp "%CP%" JavaBridgeTest.java || exit 1
%JAVA% -cp "%CP%" JavaBridgeTest 12345 UDP || exit 1

View file

@ -1,8 +1,8 @@
#! /bin/sh
#!/bin/bash
JAVA=java
JAVAC=javac
CP=$(for i in *.jar; do echo -n $i:; done).
$JAVAC -cp miniupnpc_Linux.jar JavaBridgeTest.java
$JAVA -cp miniupnpc_Linux.jar:. JavaBridgeTest 12345 UDP
$JAVAC -cp $CP JavaBridgeTest.java || exit 1
$JAVA -cp $CP JavaBridgeTest 12345 UDP || exit 1

View file

@ -1,5 +1,4 @@
\" $Id: miniupnpc.3,v 1.3 2011/07/25 18:02:11 nanard Exp $
.TH miniupnpc 3
.TH MINIUPNPC 3
.SH NAME
miniupnpc \- UPnP client library
.SH SYNOPSIS
@ -26,25 +25,28 @@ through the miniupnpc API. The name of the C functions are matching
the UPnP methods names. ie: GetGenericPortMappingEntry is
UPNP_GetGenericPortMappingEntry.
.SH "API FUNCTIONS"
.IP "struct UPNPDev * upnpDiscover(int delay, const char * multicastif, const char * minissdpdsock, int sameport, int ipv6, int * error);"
.IP "struct UPNPDev * upnpDiscover(int delay, const char * multicastif, const char * minissdpdsock, int localport, int ipv6, int * error);"
execute the discovery process.
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 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.
If ipv6 is not 0, IPv6 is used instead of IPv4 for the discovery process.
.IP "void freeUPNPDevlist(struct UPNPDev * devlist);"
free the list returned by upnpDiscover().
.IP "int UPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen);"
browse the list of device returned by upnpDiscover(), find
a live UPnP internet gateway device and fill structures passed as arguments
with data used for UPNP methods invokation.
with data used for UPNP methods invocation.
.IP "int UPNP_GetIGDFromUrl(const char * rootdescurl, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen);"
permit to bypass the upnpDiscover() call if the xml root description
permit one to bypass the upnpDiscover() call if the xml root description
URL of the UPnP IGD is known.
Fill structures passed as arguments
with data used for UPNP methods invokation.
with data used for UPNP methods invocation.
.IP "void GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, const char *);"
.IP "void FreeUPNPUrls(struct UPNPUrls *);"

View file

@ -1,132 +0,0 @@
/* $Id: minissdpc.c,v 1.14 2010/11/25 09:57:25 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas BERNARD
* copyright (c) 2005-2009 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENCE file. */
/*#include <syslog.h>*/
#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 <winsock.h>
#include <stdint.h>
#endif
#if defined(__amigaos__) || defined(__amigaos4__)
#include <sys/socket.h>
#endif
#if defined(__amigaos__)
#define uint16_t unsigned short
#endif
/* Hack */
#define UNIX_PATH_LEN 108
struct sockaddr_un {
uint16_t sun_family;
char sun_path[UNIX_PATH_LEN];
};
#else
#include <sys/socket.h>
#include <sys/un.h>
#endif
#include "minissdpc.h"
#include "miniupnpc.h"
#include "codelength.h"
struct UPNPDev *
getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath)
{
struct UPNPDev * tmp;
struct UPNPDev * devlist = NULL;
unsigned char buffer[2048];
ssize_t n;
unsigned char * p;
unsigned char * url;
unsigned int i;
unsigned int urlsize, stsize, usnsize, l;
int s;
struct sockaddr_un addr;
s = socket(AF_UNIX, SOCK_STREAM, 0);
if(s < 0)
{
/*syslog(LOG_ERR, "socket(unix): %m");*/
perror("socket(unix)");
return NULL;
}
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socketpath, sizeof(addr.sun_path));
/* TODO : check if we need to handle the EINTR */
if(connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0)
{
/*syslog(LOG_WARNING, "connect(\"%s\"): %m", socketpath);*/
close(s);
return NULL;
}
stsize = strlen(devtype);
buffer[0] = 1; /* request type 1 : request devices/services by type */
p = buffer + 1;
l = stsize; CODELENGTH(l, p);
if(p + stsize > buffer + sizeof(buffer))
{
/* devtype is too long ! */
close(s);
return NULL;
}
memcpy(p, devtype, stsize);
p += stsize;
if(write(s, buffer, p - buffer) < 0)
{
/*syslog(LOG_ERR, "write(): %m");*/
perror("minissdpc.c: write()");
close(s);
return NULL;
}
n = read(s, buffer, sizeof(buffer));
if(n<=0)
{
perror("minissdpc.c: read()");
close(s);
return NULL;
}
p = buffer + 1;
for(i = 0; i < buffer[0]; i++)
{
if(p+2>=buffer+sizeof(buffer))
break;
DECODELENGTH(urlsize, p);
if(p+urlsize+2>=buffer+sizeof(buffer))
break;
url = p;
p += urlsize;
DECODELENGTH(stsize, p);
if(p+stsize+2>=buffer+sizeof(buffer))
break;
tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize);
tmp->pNext = devlist;
tmp->descURL = tmp->buffer;
tmp->st = tmp->buffer + 1 + urlsize;
memcpy(tmp->buffer, url, urlsize);
tmp->buffer[urlsize] = '\0';
memcpy(tmp->buffer + urlsize + 1, p, stsize);
p += stsize;
tmp->buffer[urlsize+1+stsize] = '\0';
devlist = tmp;
/* added for compatibility with recent versions of MiniSSDPd
* >= 2007/12/19 */
DECODELENGTH(usnsize, p);
p += usnsize;
if(p>buffer + sizeof(buffer))
break;
}
close(s);
return devlist;
}

View file

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

View file

@ -0,0 +1,6 @@
if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/libminiupnpc-shared.cmake" OR MINIUPNPC_USE_STATIC_LIBS)
include("${CMAKE_CURRENT_LIST_DIR}/miniupnpc-private.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/libminiupnpc-static.cmake")
else()
include("${CMAKE_CURRENT_LIST_DIR}/libminiupnpc-shared.cmake")
endif()

View file

@ -1,943 +0,0 @@
/* $Id: miniupnpc.c,v 1.95 2011/05/15 21:42:26 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas BERNARD
* copyright (c) 2005-2011 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENSE file. */
#define __EXTENSIONS__ 1
#if !defined(MACOSX) && !defined(__sun)
#if !defined(_XOPEN_SOURCE) && !defined(__OpenBSD__) && !defined(__NetBSD__)
#ifndef __cplusplus
#define _XOPEN_SOURCE 600
#endif
#endif
#ifndef __BSD_VISIBLE
#define __BSD_VISIBLE 1
#endif
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef WIN32
/* Win32 Specific includes and defines */
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
#include <iphlpapi.h>
#define snprintf _snprintf
#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 */
#define MAXHOSTNAMELEN 64
#else /* #ifdef WIN32 */
/* Standard POSIX includes */
#include <unistd.h>
#if defined(__amigaos__) && !defined(__amigaos4__)
/* Amiga OS 3 specific stuff */
#define socklen_t int
#else
#include <sys/select.h>
#endif
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <net/if.h>
#if !defined(__amigaos__) && !defined(__amigaos4__)
#include <poll.h>
#endif
#include <strings.h>
#include <errno.h>
#define closesocket close
#endif /* #else WIN32 */
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
#include <sys/time.h>
#endif
#if defined(__amigaos__) || defined(__amigaos4__)
/* Amiga OS specific stuff */
#define TIMEVAL struct timeval
#endif
#include "miniupnpc.h"
#include "minissdpc.h"
#include "miniwget.h"
#include "minisoap.h"
#include "minixml.h"
#include "upnpcommands.h"
#include "connecthostport.h"
#include "receivedata.h"
#ifdef WIN32
#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
#else
#define PRINT_SOCKET_ERROR(x) perror(x)
#endif
#define SOAPPREFIX "s"
#define SERVICEPREFIX "u"
#define SERVICEPREFIX2 'u'
/* root description parsing */
LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data)
{
struct xmlparser parser;
/* xmlparser object */
parser.xmlstart = buffer;
parser.xmlsize = bufsize;
parser.data = data;
parser.starteltfunc = IGDstartelt;
parser.endeltfunc = IGDendelt;
parser.datafunc = IGDdata;
parser.attfunc = 0;
parsexml(&parser);
#ifdef DEBUG
printIGD(data);
#endif
}
/* simpleUPnPcommand2 :
* not so simple !
* return values :
* pointer - OK
* NULL - error */
char * simpleUPnPcommand2(int s, const char * url, const char * service,
const char * action, struct UPNParg * args,
int * bufsize, const char * httpversion)
{
char hostname[MAXHOSTNAMELEN+1];
unsigned short port = 0;
char * path;
char soapact[128];
char soapbody[2048];
char * buf;
int n;
*bufsize = 0;
snprintf(soapact, sizeof(soapact), "%s#%s", service, action);
if(args==NULL)
{
/*soapbodylen = */snprintf(soapbody, sizeof(soapbody),
"<?xml version=\"1.0\"?>\r\n"
"<" SOAPPREFIX ":Envelope "
"xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" "
SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
"<" SOAPPREFIX ":Body>"
"<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">"
"</" SERVICEPREFIX ":%s>"
"</" SOAPPREFIX ":Body></" SOAPPREFIX ":Envelope>"
"\r\n", action, service, action);
}
else
{
char * p;
const char * pe, * pv;
int soapbodylen;
soapbodylen = snprintf(soapbody, sizeof(soapbody),
"<?xml version=\"1.0\"?>\r\n"
"<" SOAPPREFIX ":Envelope "
"xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" "
SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
"<" SOAPPREFIX ":Body>"
"<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">",
action, service);
p = soapbody + soapbodylen;
while(args->elt)
{
/* check that we are never overflowing the string... */
if(soapbody + sizeof(soapbody) <= p + 100)
{
/* we keep a margin of at least 100 bytes */
return NULL;
}
*(p++) = '<';
pe = args->elt;
while(*pe)
*(p++) = *(pe++);
*(p++) = '>';
if((pv = args->val))
{
while(*pv)
*(p++) = *(pv++);
}
*(p++) = '<';
*(p++) = '/';
pe = args->elt;
while(*pe)
*(p++) = *(pe++);
*(p++) = '>';
args++;
}
*(p++) = '<';
*(p++) = '/';
*(p++) = SERVICEPREFIX2;
*(p++) = ':';
pe = action;
while(*pe)
*(p++) = *(pe++);
strncpy(p, "></" SOAPPREFIX ":Body></" SOAPPREFIX ":Envelope>\r\n",
soapbody + sizeof(soapbody) - p);
}
if(!parseURL(url, hostname, &port, &path)) return NULL;
if(s<0)
{
s = connecthostport(hostname, port);
if(s < 0)
{
return NULL;
}
}
n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, httpversion);
if(n<=0) {
#ifdef DEBUG
printf("Error sending SOAP request\n");
#endif
closesocket(s);
return NULL;
}
buf = getHTTPResponse(s, bufsize);
#ifdef DEBUG
if(*bufsize > 0 && buf)
{
printf("SOAP Response :\n%.*s\n", *bufsize, buf);
}
#endif
closesocket(s);
return buf;
}
/* simpleUPnPcommand :
* not so simple !
* return values :
* pointer - OK
* NULL - error */
char * simpleUPnPcommand(int s, const char * url, const char * service,
const char * action, struct UPNParg * args,
int * bufsize)
{
char * buf;
buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.1");
/*
buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.0");
if (!buf || *bufsize == 0)
{
#if DEBUG
printf("Error or no result from SOAP request; retrying with HTTP/1.1\n");
#endif
buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.1");
}
*/
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)
{
int a, b, i;
i = 0;
a = i; /* start of the line */
b = 0; /* end of the "header" (position of the colon) */
while(i<size)
{
switch(reply[i])
{
case ':':
if(b==0)
{
b = i; /* end of the "header" */
/*for(j=a; j<b; j++)
{
putchar(reply[j]);
}
*/
}
break;
case '\x0a':
case '\x0d':
if(b!=0)
{
/*for(j=b+1; j<i; j++)
{
putchar(reply[j]);
}
putchar('\n');*/
/* skip the colon and white spaces */
do { b++; } while(reply[b]==' ');
if(0==strncasecmp(reply+a, "location", 8))
{
*location = reply+b;
*locationsize = i-b;
}
else if(0==strncasecmp(reply+a, "st", 2))
{
*st = reply+b;
*stsize = i-b;
}
b = 0;
}
a = i+1;
break;
default:
break;
}
i++;
}
}
/* port upnp discover : SSDP protocol */
#define PORT 1900
#define XSTR(s) STR(s)
#define STR(s) #s
#define UPNP_MCAST_ADDR "239.255.255.250"
/* for IPv6 */
#define UPNP_MCAST_LL_ADDR "FF02::C" /* link-local */
#define UPNP_MCAST_SL_ADDR "FF05::C" /* site-local */
#if defined (WIN32) && defined (NO_GETADDRINFO)
static int inet_pton(int af, const char* src, void* dst)
{
int address_length;
struct sockaddr_storage sa;
struct sockaddr_in *sin = (struct sockaddr_in *)&sa;
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa;
switch (af) {
case AF_INET:
address_length = sizeof (struct sockaddr_in);
break;
case AF_INET6:
address_length = sizeof (struct sockaddr_in6);
break;
default:
return -1;
}
if (WSAStringToAddress ((LPTSTR) src, af, NULL, (LPSOCKADDR) &sa, &address_length) == 0) {
switch (af)
{
case AF_INET:
memcpy (dst, &sin->sin_addr, sizeof (struct in_addr));
break;
case AF_INET6:
memcpy (dst, &sin6->sin6_addr, sizeof (struct in6_addr));
break;
}
return 1;
}
return 0;
}
#endif
/* upnpDiscover() :
* 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) */
LIBSPEC struct UPNPDev *
upnpDiscover(int delay, const char * multicastif,
const char * minissdpdsock, int sameport,
int ipv6,
int * error)
{
struct UPNPDev * tmp;
struct UPNPDev * devlist = 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";
static const char * const deviceList[] = {
#if 0
"urn:schemas-upnp-org:device:InternetGatewayDevice:2",
"urn:schemas-upnp-org:service:WANIPConnection:2",
#endif
"urn:schemas-upnp-org:device:InternetGatewayDevice:1",
"urn:schemas-upnp-org:service:WANIPConnection:1",
"urn:schemas-upnp-org:service:WANPPPConnection:1",
"upnp:rootdevice",
0
};
int deviceIndex = 0;
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;
if(error)
*error = UPNPDISCOVER_UNKNOWN_ERROR;
#if !defined(WIN32) && !defined(__amigaos__) && !defined(__amigaos4__)
/* first try to get infos from minissdpd ! */
if(!minissdpdsock)
minissdpdsock = "/var/run/minissdpd.sock";
while(!devlist && deviceList[deviceIndex]) {
devlist = getDevicesFromMiniSSDPD(deviceList[deviceIndex],
minissdpdsock);
/* We return what we have found if it was not only a rootdevice */
if(devlist && !strstr(deviceList[deviceIndex], "rootdevice")) {
if(error)
*error = UPNPDISCOVER_SUCCESS;
return devlist;
}
deviceIndex++;
}
deviceIndex = 0;
#endif
/* fallback to direct discovery */
#ifdef WIN32
sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP);
#else
sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, 0);
#endif
if(sudp < 0)
{
if(error)
*error = UPNPDISCOVER_SOCKET_ERROR;
PRINT_SOCKET_ERROR("socket");
return NULL;
}
/* reception */
memset(&sockudp_r, 0, sizeof(struct sockaddr_storage));
if(ipv6) {
struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_r;
p->sin6_family = AF_INET6;
if(sameport)
p->sin6_port = htons(PORT);
p->sin6_addr = in6addr_any; /* in6addr_any is not available with MinGW32 3.4.2 */
} else {
struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_r;
p->sin_family = AF_INET;
if(sameport)
p->sin_port = htons(PORT);
p->sin_addr.s_addr = INADDR_ANY;
}
#ifdef WIN32
/* This code could help us to use the right Network interface for
* SSDP multicast traffic */
/* Get IP associated with the index given in the ip_forward struct
* in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */
if(!ipv6
&& (GetBestRoute(inet_addr("223.255.255.255"), 0, &ip_forward) == NO_ERROR)) {
DWORD dwRetVal = 0;
PMIB_IPADDRTABLE pIPAddrTable;
DWORD dwSize = 0;
#ifdef DEBUG
IN_ADDR IPAddr;
#endif
int i;
#ifdef DEBUG
printf("ifIndex=%lu nextHop=%lx \n", ip_forward.dwForwardIfIndex, ip_forward.dwForwardNextHop);
#endif
pIPAddrTable = (MIB_IPADDRTABLE *) malloc(sizeof (MIB_IPADDRTABLE));
if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) {
free(pIPAddrTable);
pIPAddrTable = (MIB_IPADDRTABLE *) malloc(dwSize);
}
if(pIPAddrTable) {
dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 );
#ifdef DEBUG
printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries);
#endif
for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) {
#ifdef DEBUG
printf("\n\tInterface Index[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwIndex);
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr;
printf("\tIP Address[%d]: \t%s\n", i, inet_ntoa(IPAddr) );
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask;
printf("\tSubnet Mask[%d]: \t%s\n", i, inet_ntoa(IPAddr) );
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr;
printf("\tBroadCast[%d]: \t%s (%ld)\n", i, inet_ntoa(IPAddr), pIPAddrTable->table[i].dwBCastAddr);
printf("\tReassembly size[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwReasmSize);
printf("\tType and State[%d]:", i);
printf("\n");
#endif
if (pIPAddrTable->table[i].dwIndex == ip_forward.dwForwardIfIndex) {
/* Set the address of this interface to be used */
struct in_addr mc_if;
memset(&mc_if, 0, sizeof(mc_if));
mc_if.s_addr = pIPAddrTable->table[i].dwAddr;
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) {
PRINT_SOCKET_ERROR("setsockopt");
}
((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = pIPAddrTable->table[i].dwAddr;
#ifndef DEBUG
break;
#endif
}
}
free(pIPAddrTable);
pIPAddrTable = NULL;
}
}
#endif
#ifdef WIN32
if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0)
#else
if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0)
#endif
{
if(error)
*error = UPNPDISCOVER_SOCKET_ERROR;
PRINT_SOCKET_ERROR("setsockopt");
return NULL;
}
if(multicastif)
{
if(ipv6) {
#if !defined(WIN32)
/* according to MSDN, if_nametoindex() is supported since
* MS Windows Vista and MS Windows Server 2008.
* http://msdn.microsoft.com/en-us/library/bb408409%28v=vs.85%29.aspx */
unsigned int ifindex = if_nametoindex(multicastif); /* eth0, etc. */
if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(&ifindex)) < 0)
{
PRINT_SOCKET_ERROR("setsockopt");
}
#else
#ifdef DEBUG
printf("Setting of multicast interface not supported in IPv6 under Windows.\n");
#endif
#endif
} else {
struct in_addr mc_if;
mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */
((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");
}
}
}
/* Avant d'envoyer le paquet on bind pour recevoir la reponse */
if (bind(sudp, (const struct sockaddr *)&sockudp_r,
ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) != 0)
{
if(error)
*error = UPNPDISCOVER_SOCKET_ERROR;
PRINT_SOCKET_ERROR("bind");
closesocket(sudp);
return NULL;
}
if(error)
*error = UPNPDISCOVER_SUCCESS;
/* Calculating maximum response time in seconds */
mx = ((unsigned int)delay) / 1000u;
/* receiving SSDP response packet */
for(n = 0; deviceList[deviceIndex]; deviceIndex++)
{
if(n == 0)
{
/* sending the SSDP M-SEARCH packet */
n = snprintf(bufr, sizeof(bufr),
MSearchMsgFmt,
ipv6 ?
(linklocal ? "[" UPNP_MCAST_LL_ADDR "]" : "[" UPNP_MCAST_SL_ADDR "]")
: UPNP_MCAST_ADDR,
deviceList[deviceIndex], mx);
#ifdef DEBUG
printf("Sending %s", bufr);
#endif
#ifdef NO_GETADDRINFO
/* the following code is not using getaddrinfo */
/* emission */
memset(&sockudp_w, 0, sizeof(struct sockaddr_storage));
if(ipv6) {
struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_w;
p->sin6_family = AF_INET6;
p->sin6_port = htons(PORT);
inet_pton(AF_INET6,
linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR,
&(p->sin6_addr));
} else {
struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_w;
p->sin_family = AF_INET;
p->sin_port = htons(PORT);
p->sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);
}
n = sendto(sudp, bufr, n, 0,
(const void *)&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) {
PRINT_SOCKET_ERROR("sendto");
continue;
}
}
freeaddrinfo(servinfo);
if(n < 0) {
if(error)
*error = UPNPDISCOVER_SOCKET_ERROR;
break;
}
#endif /* #ifdef NO_GETADDRINFO */
}
/* Waiting for SSDP REPLY packet to M-SEARCH */
n = receivedata(sudp, bufr, sizeof(bufr), delay);
if (n < 0) {
/* error */
if(error)
*error = UPNPDISCOVER_SOCKET_ERROR;
break;
} else if (n == 0) {
/* no data or Time Out */
if (devlist) {
/* no more device type to look for... */
if(error)
*error = UPNPDISCOVER_SUCCESS;
break;
}
if(ipv6) {
if(linklocal) {
linklocal = 0;
--deviceIndex;
} else {
linklocal = 1;
}
}
} else {
const char * descURL=NULL;
int urlsize=0;
const char * st=NULL;
int stsize=0;
/*printf("%d byte(s) :\n%s\n", n, bufr);*/ /* affichage du message */
parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize);
if(st&&descURL)
{
#ifdef DEBUG
printf("M-SEARCH Reply:\nST: %.*s\nLocation: %.*s\n",
stsize, st, urlsize, descURL);
#endif
for(tmp=devlist; tmp; tmp = tmp->pNext) {
if(memcmp(tmp->descURL, descURL, urlsize) == 0 &&
tmp->descURL[urlsize] == '\0' &&
memcmp(tmp->st, st, stsize) == 0 &&
tmp->st[stsize] == '\0')
break;
}
/* at the exit of the loop above, tmp is null if
* no duplicate device was found */
if(tmp)
continue;
tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize);
if(!tmp) {
/* memory allocation error */
if(error)
*error = UPNPDISCOVER_MEMORY_ERROR;
break;
}
tmp->pNext = devlist;
tmp->descURL = tmp->buffer;
tmp->st = tmp->buffer + 1 + urlsize;
memcpy(tmp->buffer, descURL, urlsize);
tmp->buffer[urlsize] = '\0';
memcpy(tmp->buffer + urlsize + 1, st, stsize);
tmp->buffer[urlsize+1+stsize] = '\0';
devlist = tmp;
}
}
}
closesocket(sudp);
return devlist;
}
/* freeUPNPDevlist() should be used to
* free the chained list returned by upnpDiscover() */
LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist)
{
struct UPNPDev * next;
while(devlist)
{
next = devlist->pNext;
free(devlist);
devlist = next;
}
}
static void
url_cpy_or_cat(char * dst, const char * src, int n)
{
if( (src[0] == 'h')
&&(src[1] == 't')
&&(src[2] == 't')
&&(src[3] == 'p')
&&(src[4] == ':')
&&(src[5] == '/')
&&(src[6] == '/'))
{
strncpy(dst, src, n);
}
else
{
int l = strlen(dst);
if(src[0] != '/')
dst[l++] = '/';
if(l<=n)
strncpy(dst + l, src, n - l);
}
}
/* Prepare the Urls for usage...
*/
LIBSPEC void GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data,
const char * descURL)
{
char * p;
int n1, n2, n3, n4;
n1 = strlen(data->urlbase);
if(n1==0)
n1 = strlen(descURL);
n1 += 2; /* 1 byte more for Null terminator, 1 byte for '/' if needed */
n2 = n1; n3 = n1; n4 = n1;
n1 += strlen(data->first.scpdurl);
n2 += strlen(data->first.controlurl);
n3 += strlen(data->CIF.controlurl);
n4 += strlen(data->IPv6FC.controlurl);
urls->ipcondescURL = (char *)malloc(n1);
urls->controlURL = (char *)malloc(n2);
urls->controlURL_CIF = (char *)malloc(n3);
urls->controlURL_6FC = (char *)malloc(n4);
/* maintenant on chope la desc du WANIPConnection */
if(data->urlbase[0] != '\0')
strncpy(urls->ipcondescURL, data->urlbase, n1);
else
strncpy(urls->ipcondescURL, descURL, n1);
p = strchr(urls->ipcondescURL+7, '/');
if(p) p[0] = '\0';
strncpy(urls->controlURL, urls->ipcondescURL, n2);
strncpy(urls->controlURL_CIF, urls->ipcondescURL, n3);
strncpy(urls->controlURL_6FC, urls->ipcondescURL, n4);
url_cpy_or_cat(urls->ipcondescURL, data->first.scpdurl, n1);
url_cpy_or_cat(urls->controlURL, data->first.controlurl, n2);
url_cpy_or_cat(urls->controlURL_CIF, data->CIF.controlurl, n3);
url_cpy_or_cat(urls->controlURL_6FC, data->IPv6FC.controlurl, n4);
#ifdef DEBUG
printf("urls->ipcondescURL='%s' %u n1=%d\n", urls->ipcondescURL,
(unsigned)strlen(urls->ipcondescURL), n1);
printf("urls->controlURL='%s' %u n2=%d\n", urls->controlURL,
(unsigned)strlen(urls->controlURL), n2);
printf("urls->controlURL_CIF='%s' %u n3=%d\n", urls->controlURL_CIF,
(unsigned)strlen(urls->controlURL_CIF), n3);
printf("urls->controlURL_6FC='%s' %u n4=%d\n", urls->controlURL_6FC,
(unsigned)strlen(urls->controlURL_6FC), n4);
#endif
}
LIBSPEC void
FreeUPNPUrls(struct UPNPUrls * urls)
{
if(!urls)
return;
free(urls->controlURL);
urls->controlURL = 0;
free(urls->ipcondescURL);
urls->ipcondescURL = 0;
free(urls->controlURL_CIF);
urls->controlURL_CIF = 0;
free(urls->controlURL_6FC);
urls->controlURL_6FC = 0;
}
int
UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data)
{
char status[64];
unsigned int uptime;
status[0] = '\0';
UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype,
status, &uptime, NULL);
if(0 == strcmp("Connected", status))
{
return 1;
}
else
return 0;
}
/* 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.
*/
LIBSPEC int
UPNP_GetValidIGD(struct UPNPDev * devlist,
struct UPNPUrls * urls,
struct IGDdatas * data,
char * lanaddr, int lanaddrlen)
{
char * descXML;
int descXMLsize = 0;
struct UPNPDev * dev;
int ndev = 0;
int state; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */
if(!devlist)
{
#ifdef DEBUG
printf("Empty devlist\n");
#endif
return 0;
}
for(state = 1; state <= 3; state++)
{
for(dev = devlist; dev; dev = dev->pNext)
{
/* we should choose an internet gateway device.
* with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */
descXML = miniwget_getaddr(dev->descURL, &descXMLsize,
lanaddr, lanaddrlen);
if(descXML)
{
ndev++;
memset(data, 0, sizeof(struct IGDdatas));
memset(urls, 0, sizeof(struct UPNPUrls));
parserootdesc(descXML, descXMLsize, data);
free(descXML);
descXML = NULL;
if(0==strcmp(data->CIF.servicetype,
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")
|| state >= 3 )
{
GetUPNPUrls(urls, data, dev->descURL);
#ifdef DEBUG
printf("UPNPIGD_IsConnected(%s) = %d\n",
urls->controlURL,
UPNPIGD_IsConnected(urls, data));
#endif
if((state >= 2) || UPNPIGD_IsConnected(urls, data))
return state;
FreeUPNPUrls(urls);
if(data->second.servicetype[0] != '\0') {
#ifdef DEBUG
printf("We tried %s, now we try %s !\n",
data->first.servicetype, data->second.servicetype);
#endif
/* swaping WANPPPConnection and WANIPConnection ! */
memcpy(&data->tmp, &data->first, sizeof(struct IGDdatas_service));
memcpy(&data->first, &data->second, sizeof(struct IGDdatas_service));
memcpy(&data->second, &data->tmp, sizeof(struct IGDdatas_service));
GetUPNPUrls(urls, data, dev->descURL);
#ifdef DEBUG
printf("UPNPIGD_IsConnected(%s) = %d\n",
urls->controlURL,
UPNPIGD_IsConnected(urls, data));
#endif
if((state >= 2) || UPNPIGD_IsConnected(urls, data))
return state;
FreeUPNPUrls(urls);
}
}
memset(data, 0, sizeof(struct IGDdatas));
}
#ifdef DEBUG
else
{
printf("error getting XML description %s\n", dev->descURL);
}
#endif
}
}
return 0;
}
/* UPNP_GetIGDFromUrl()
* Used when skipping the discovery process.
* return value :
* 0 - Not ok
* 1 - OK */
int
UPNP_GetIGDFromUrl(const char * rootdescurl,
struct UPNPUrls * urls,
struct IGDdatas * data,
char * lanaddr, int lanaddrlen)
{
char * descXML;
int descXMLsize = 0;
descXML = miniwget_getaddr(rootdescurl, &descXMLsize,
lanaddr, lanaddrlen);
if(descXML) {
memset(data, 0, sizeof(struct IGDdatas));
memset(urls, 0, sizeof(struct UPNPUrls));
parserootdesc(descXML, descXMLsize, data);
free(descXML);
descXML = NULL;
GetUPNPUrls(urls, data, rootdescurl);
return 1;
} else {
return 0;
}
}

View file

@ -1,9 +1,13 @@
LIBRARY
; miniupnpc library
miniupnpc
EXPORTS
; miniupnpc
upnpDiscover
upnpDiscoverDevice
upnpDiscoverDevices
upnpDiscoverAll
freeUPNPDevlist
parserootdesc
UPNP_GetValidIGD
@ -23,7 +27,9 @@ EXPORTS
UPNP_GetExternalIPAddress
UPNP_GetLinkLayerMaxBitRates
UPNP_AddPortMapping
UPNP_AddAnyPortMapping
UPNP_DeletePortMapping
UPNP_DeletePortMappingRange
UPNP_GetPortMappingNumberOfEntries
UPNP_GetSpecificPortMappingEntry
UPNP_GetGenericPortMappingEntry

View file

@ -0,0 +1,18 @@
# this template is filled-in by CMake `configure_file(... @ONLY)`
# the `@....@` are filled in by CMake configure_file(),
# from variables set in your CMakeLists.txt or by CMake itself
#
# Good tutoral for understanding .pc files:
# https://people.freedesktop.org/~dbn/pkg-config-guide.html
prefix="@CMAKE_INSTALL_PREFIX@"
exec_prefix="${prefix}"
libdir="${prefix}/lib"
includedir="${prefix}/include"
Name: @PROJECT_NAME@
Description: @PROJECT_DESCRIPTION@
URL: @PROJECT_HOMEPAGE_URL@
Version: @PROJECT_VERSION@
Libs: -L"${libdir}" -lminiupnpc
Cflags: -I"${includedir}"

View file

@ -0,0 +1,36 @@
#include <winver.h>
#include "rc_version.h"
VS_VERSION_INFO VERSIONINFO
FILEVERSION LIBMINIUPNPC_MAJOR_VERSION,LIBMINIUPNPC_MINOR_VERSION,LIBMINIUPNPC_MICRO_VERSION,0
PRODUCTVERSION LIBMINIUPNPC_MAJOR_VERSION,LIBMINIUPNPC_MINOR_VERSION,LIBMINIUPNPC_MICRO_VERSION,0
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG
#else
FILEFLAGS 0
#endif
FILEOS VOS__WINDOWS32
FILETYPE VFT_DLL
FILESUBTYPE VFT2_UNKNOWN // not used
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "04090000" /* Lang = US English, Charset = ASCII */
BEGIN
VALUE "FileDescription", "MiniUPnPc library\0"
VALUE "FileVersion", LIBMINIUPNPC_DOTTED_VERSION "\0"
VALUE "InternalName", INTERNAL_NAME
VALUE "LegalCopyright", "Copyright (C) Thomas Bernard\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", INTERNAL_NAME
VALUE "ProductName", "MiniUPnPc\0"
VALUE "ProductVersion", LIBMINIUPNPC_DOTTED_VERSION "\0"
VALUE "Comments", "For more information visit https://miniupnp.tuxfamil.org/\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0409, 0 /* US English, ASCII */
END
END

View file

@ -1,7 +1,15 @@
#ifndef __MINIUPNPCSTRINGS_H__
#define __MINIUPNPCSTRINGS_H__
#ifndef MINIUPNPCSTRINGS_H_INCLUDED
#define MINIUPNPCSTRINGS_H_INCLUDED
#define OS_STRING "${CMAKE_SYSTEM_NAME}"
#define MINIUPNPC_VERSION_STRING "${MINIUPNPC_VERSION}"
#if 0
/* according to "UPnP Device Architecture 1.0" */
#define UPNP_VERSION_STRING "UPnP/1.0"
#else
/* according to "UPnP Device Architecture 1.1" */
#define UPNP_VERSION_STRING "UPnP/1.1"
#endif
#endif

View file

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

View file

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

View file

@ -0,0 +1,112 @@
' VBScript to generate miniupnpcstrings.h
' Copyright 2018 Thomas Bernard
'Set WshShell = CreateObject("WScript.Shell")
Set FSO = CreateObject("Scripting.FileSystemObject")
versionfile = "..\version"
infile = "..\miniupnpcstrings.h.in"
outfile = "..\miniupnpcstrings.h"
outfilerc = "..\rc_version.h"
On Error Resume Next
'Wscript.Echo revision
Err.Clear
Set f = FSO.OpenTextFile(versionfile, 1, False) ' 1 = Read
If Err.Number = 0 Then
version = f.ReadLine
f.Close
Else
' Exit error
WScript.Quit 1
End If
os_version = "0.0.0"
strComputer = "."
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colOperatingSystems = objWMIService.ExecQuery ("Select * from Win32_OperatingSystem")
For Each objOperatingSystem in colOperatingSystems
'Wscript.Echo objOperatingSystem.Caption & " -- "
os_version = objOperatingSystem.Version
Next
'Wscript.Echo os_version
Dim array
needWrite = True
' First Check if the file already contains the right versions
Err.Clear
Set f_in = FSO.OpenTextFile(outfile, 1, False)
If Err.Number = 0 Then
old_version = ""
old_os_version = ""
Do Until f_in.AtEndOfStream
line = f_in.ReadLine
If Len(line) > 0 Then
array = Split(line, " ")
If UBound(array) >= 2 And array(0) = "#define" Then
If array(1) = "OS_STRING" Then
old_os_version = Replace(array(2), Chr(34), "")
ElseIf array(1) = "MINIUPNPC_VERSION_STRING" Then
old_version = Replace(array(2), Chr(34), "")
End if
End if
End If
Loop
f_in.Close
If old_version = version And old_os_version = "MSWindows/" & os_version Then
needWrite = False
Else
needWrite = True
End If
End If
If Not needWrite Then
' check files dates
Set fIn1 = FSO.GetFile(versionfile)
Set fIn2 = FSO.GetFile(infile)
Set fOut = FSO.GetFile(outfile)
If DateDiff("s", fIn1.DateLastModified, fOut.DateLastModified) < 0 Then
needWrite = True
End If
If DateDiff("s", fIn2.DateLastModified, fOut.DateLastModified) < 0 Then
needWrite = True
End If
End If
If Not needWrite Then
' nothing to do
WScript.Quit 0
End if
' generate the file
Err.Clear
Set f_in = FSO.OpenTextFile(infile, 1, False)
If Err.Number = 0 Then
Set f_out = FSO.OpenTextFile(outfile, 2, True) ' 2 = Write
Do Until f_in.AtEndOfStream
line = f_in.ReadLine
If Len(line) > 0 Then
array = Split(line, " ")
If UBound(array) >= 2 And array(0) = "#define" Then
If array(1) = "OS_STRING" Then
line = "#define OS_STRING " & Chr(34) & "MSWindows/" & os_version & Chr(34)
ElseIf array(1) = "MINIUPNPC_VERSION_STRING" Then
line = "#define MINIUPNPC_VERSION_STRING " & Chr(34) & version & Chr(34)
End if
End if
End If
f_out.WriteLine line
Loop
f_in.Close
f_out.Close
End If
Set f_out = FSO.OpenTextFile(outfilerc, 2, True) ' 2 = Write
f_out.WriteLine "#define LIBMINIUPNPC_DOTTED_VERSION " & Chr(34) & version & Chr(34)
ver = Split(version, ".")
f_out.WriteLine "#define LIBMINIUPNPC_MAJOR_VERSION " & ver(0)
f_out.WriteLine "#define LIBMINIUPNPC_MINOR_VERSION " & ver(1)
f_out.WriteLine "#define LIBMINIUPNPC_MICRO_VERSION " & ver(2)
f_out.Close

View file

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

View file

@ -0,0 +1,215 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug Dll|Win32">
<Configuration>Debug Dll</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release Dll|Win32">
<Configuration>Release Dll</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{D28CE435-CB33-4BAE-8A52-C6EF915956F5}</ProjectGuid>
<RootNamespace>miniupnpc</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>14.0.25123.0</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
<IntDir>$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'">
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
<IntDir>$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
<IntDir>$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'">
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
<IntDir>$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MINIUPNP_STATICLIB;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader />
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<AdditionalIncludeDirectories>..;..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<PreBuildEvent>
<Command>genminiupnpcstrings.vbs</Command>
</PreBuildEvent>
<ResourceCompile>
<PreprocessorDefinitions>INTERNAL_NAME="\"miniupnpc.dll\0\"";%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MINIUPNP_EXPORTS;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<AdditionalIncludeDirectories>..;..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<PreBuildEvent>
<Command>genminiupnpcstrings.vbs</Command>
</PreBuildEvent>
<Link>
<AdditionalDependencies>ws2_32.lib;IPHlpApi.Lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>INTERNAL_NAME="\"miniupnpc.dll\0\"";%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MINIUPNP_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader />
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>..;..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<PreBuildEvent>
<Command>genminiupnpcstrings.vbs</Command>
</PreBuildEvent>
<ResourceCompile>
<PreprocessorDefinitions>INTERNAL_NAME="\"miniupnpc.dll\0\"";%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MINIUPNP_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>..;..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<PreBuildEvent>
<Command>genminiupnpcstrings.vbs</Command>
</PreBuildEvent>
<Link>
<AdditionalDependencies>ws2_32.lib;IPHlpApi.Lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>INTERNAL_NAME="\"miniupnpc.dll\0\"";%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\src\addr_is_reserved.c" />
<ClCompile Include="..\src\connecthostport.c" />
<ClCompile Include="..\src\igd_desc_parse.c" />
<ClCompile Include="..\src\minisoap.c" />
<ClCompile Include="..\src\minissdpc.c" />
<ClCompile Include="..\src\miniupnpc.c" />
<ClCompile Include="..\src\miniwget.c" />
<ClCompile Include="..\src\minixml.c" />
<ClCompile Include="..\src\portlistingparse.c" />
<ClCompile Include="..\src\receivedata.c" />
<ClCompile Include="..\src\upnpcommands.c" />
<ClCompile Include="..\src\upnpdev.c" />
<ClCompile Include="..\src\upnperrors.c" />
<ClCompile Include="..\src\upnpreplyparse.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\addr_is_reserved.h" />
<ClInclude Include="..\src\connecthostport.h" />
<ClInclude Include="..\include\igd_desc_parse.h" />
<ClInclude Include="..\src\minisoap.h" />
<ClInclude Include="..\src\minissdpc.h" />
<ClInclude Include="..\include\miniupnpc.h" />
<ClInclude Include="..\miniupnpcstrings.h" />
<ClInclude Include="..\include\miniupnpctypes.h" />
<ClInclude Include="..\include\miniupnpc_declspec.h" />
<ClInclude Include="..\include\miniwget.h" />
<ClInclude Include="..\src\miniwget_private.h" />
<ClInclude Include="..\src\minixml.h" />
<ClInclude Include="..\include\portlistingparse.h" />
<ClInclude Include="..\src\receivedata.h" />
<ClInclude Include="..\include\upnpcommands.h" />
<ClInclude Include="..\include\upnpdev.h" />
<ClInclude Include="..\include\upnperrors.h" />
<ClInclude Include="..\include\upnpreplyparse.h" />
<ClInclude Include="..\src\win32_snprintf.h" />
<ClInclude Include="..\rc_version.h" />
</ItemGroup>
<ItemGroup>
<None Include="genminiupnpcstrings.vbs" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="../miniupnpc.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,133 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Fichiers sources">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Fichiers d%27en-tête">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Fichiers de ressources">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
<Filter Include="scripts">
<UniqueIdentifier>{508da401-2f8e-4fdb-9a43-95baa95a91e7}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\addr_is_reserved.c">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="..\src\connecthostport.c">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="..\src\igd_desc_parse.c">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="..\src\minisoap.c">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="..\src\minissdpc.c">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="..\src\miniupnpc.c">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="..\src\miniwget.c">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="..\src\minixml.c">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="..\src\portlistingparse.c">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="..\src\receivedata.c">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="..\src\upnpcommands.c">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="..\src\upnpdev.c">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="..\src\upnperrors.c">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="..\src\upnpreplyparse.c">
<Filter>Fichiers sources</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\rc_version.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="..\src\addr_is_reserved.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="..\src\connecthostport.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="..\include\igd_desc_parse.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="..\src\minisoap.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="..\src\minissdpc.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="..\include\miniupnpc.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="..\include\miniupnpcstrings.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="..\include\miniupnpctypes.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="..\include\miniupnpc_declspec.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="..\include\miniwget.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="..\src\minixml.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="..\include\portlistingparse.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="..\include\receivedata.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="..\include\upnpcommands.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="..\include\upnpdev.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="..\include\upnperrors.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="..\include\upnpreplyparse.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="..\src\win32_snprintf.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="genminiupnpcstrings.vbs">
<Filter>scripts</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="../miniupnpc.rc">
<Filter>Fichiers de ressources</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View file

@ -0,0 +1,36 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual C++ Express 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniupnpc_vs2010", "miniupnpc_vs2010.vcxproj", "{D28CE435-CB33-4BAE-8A52-C6EF915956F5}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "upnpc-static_vs2010", "upnpc-static_vs2010.vcxproj", "{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug Dll|Win32 = Debug Dll|Win32
Debug|Win32 = Debug|Win32
Release Dll|Win32 = Release Dll|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug Dll|Win32.ActiveCfg = Debug Dll|Win32
{D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug Dll|Win32.Build.0 = Debug Dll|Win32
{D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug|Win32.ActiveCfg = Debug|Win32
{D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug|Win32.Build.0 = Debug|Win32
{D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release Dll|Win32.ActiveCfg = Release Dll|Win32
{D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release Dll|Win32.Build.0 = Release Dll|Win32
{D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release|Win32.ActiveCfg = Release|Win32
{D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release|Win32.Build.0 = Release|Win32
{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug Dll|Win32.ActiveCfg = Debug Dll|Win32
{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug Dll|Win32.Build.0 = Debug Dll|Win32
{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug|Win32.ActiveCfg = Debug|Win32
{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug|Win32.Build.0 = Debug|Win32
{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release Dll|Win32.ActiveCfg = Release Dll|Win32
{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release Dll|Win32.Build.0 = Release Dll|Win32
{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release|Win32.ActiveCfg = Release|Win32
{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,209 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug Dll|Win32">
<Configuration>Debug Dll</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release Dll|Win32">
<Configuration>Release Dll</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{D28CE435-CB33-4BAE-8A52-C6EF915956F5}</ProjectGuid>
<RootNamespace>miniupnpc</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'">$(Configuration)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'">$(Configuration)\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">miniupnpc</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'">miniupnpc</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">miniupnpc</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'">miniupnpc</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MINIUPNP_STATICLIB;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<AdditionalIncludeDirectories>..;..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<PreBuildEvent>
<Command>genminiupnpcstrings.vbs</Command>
</PreBuildEvent>
<ResourceCompile>
<PreprocessorDefinitions>INTERNAL_NAME="\"miniupnpc.dll\0\"";%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MINIUPNP_EXPORTS;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<AdditionalIncludeDirectories>..;..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<PreBuildEvent>
<Command>genminiupnpcstrings.vbs</Command>
</PreBuildEvent>
<Link>
<AdditionalDependencies>ws2_32.lib;IPHlpApi.Lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>INTERNAL_NAME="\"miniupnpc.dll\0\"";%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MINIUPNP_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>..;..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<PreBuildEvent>
<Command>genminiupnpcstrings.vbs</Command>
</PreBuildEvent>
<ResourceCompile>
<PreprocessorDefinitions>INTERNAL_NAME="\"miniupnpc.dll\0\"";%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MINIUPNP_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>..;..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<PreBuildEvent>
<Command>genminiupnpcstrings.vbs</Command>
</PreBuildEvent>
<Link>
<AdditionalDependencies>ws2_32.lib;IPHlpApi.Lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>INTERNAL_NAME="\"miniupnpc.dll\0\"";%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\src\addr_is_reserved.c" />
<ClCompile Include="..\src\connecthostport.c" />
<ClCompile Include="..\src\igd_desc_parse.c" />
<ClCompile Include="..\src\minisoap.c" />
<ClCompile Include="..\src\minissdpc.c" />
<ClCompile Include="..\src\miniupnpc.c" />
<ClCompile Include="..\src\miniwget.c" />
<ClCompile Include="..\src\minixml.c" />
<ClCompile Include="..\src\portlistingparse.c" />
<ClCompile Include="..\src\receivedata.c" />
<ClCompile Include="..\src\upnpcommands.c" />
<ClCompile Include="..\src\upnpdev.c" />
<ClCompile Include="..\src\upnperrors.c" />
<ClCompile Include="..\src\upnpreplyparse.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\addr_is_reserved.h" />
<ClInclude Include="..\src\connecthostport.h" />
<ClInclude Include="..\include\igd_desc_parse.h" />
<ClInclude Include="..\src\minisoap.h" />
<ClInclude Include="..\src\minissdpc.h" />
<ClInclude Include="..\include\miniupnpc.h" />
<ClInclude Include="..\miniupnpcstrings.h" />
<ClInclude Include="..\include\miniupnpctypes.h" />
<ClInclude Include="..\include\miniupnpc_declspec.h" />
<ClInclude Include="..\include\miniwget.h" />
<ClInclude Include="..\src\miniwget_private.h" />
<ClInclude Include="..\src\minixml.h" />
<ClInclude Include="..\include\portlistingparse.h" />
<ClInclude Include="..\src\receivedata.h" />
<ClInclude Include="..\include\upnpcommands.h" />
<ClInclude Include="..\include\upnpdev.h" />
<ClInclude Include="..\include\upnperrors.h" />
<ClInclude Include="..\include\upnpreplyparse.h" />
<ClInclude Include="..\src\win32_snprintf.h" />
<ClInclude Include="..\rc_version.h" />
</ItemGroup>
<ItemGroup>
<None Include="genminiupnpcstrings.vbs" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="../miniupnpc.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,133 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="..\connecthostport.c">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\upnpreplyparse.c">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\igd_desc_parse.c">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\minisoap.c">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\minissdpc.c">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\miniupnpc.c">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\miniwget.c">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\minixml.c">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\portlistingparse.c">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\receivedata.c">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\upnpcommands.c">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\upnpdev.c">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\upnperrors.c">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\addr_is_reserved.c">
<Filter>sources</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\connecthostport.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\igd_desc_parse.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\minisoap.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\minissdpc.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\miniupnpc.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\miniupnpcstrings.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\miniupnpctypes.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\miniwget.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\minixml.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\portlistingparse.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\receivedata.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\upnpcommands.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\upnpdev.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\upnperrors.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\upnpreplyparse.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\miniupnpc_socketdef.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\miniupnpc_declspec.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\miniwget_private.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\addr_is_reserved.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\win32_snprintf.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="..\rc_version.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="sources">
<UniqueIdentifier>{f2cbd46b-f63f-412e-80e5-b7c9048a1add}</UniqueIdentifier>
</Filter>
<Filter Include="headers">
<UniqueIdentifier>{2b3996de-1bc4-418b-8a83-a5f34fdf0df5}</UniqueIdentifier>
</Filter>
<Filter Include="scripts">
<UniqueIdentifier>{45dbc39d-c3ca-4a75-adf0-76070e20415a}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="genminiupnpcstrings.vbs">
<Filter>scripts</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="../miniupnpc.rc">
<Filter>Fichiers de ressources</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View file

@ -0,0 +1,38 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25123.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniupnpc", "miniupnpc.vcxproj", "{D28CE435-CB33-4BAE-8A52-C6EF915956F5}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "upnpc-static", "upnpc-static.vcxproj", "{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug Dll|Win32 = Debug Dll|Win32
Debug|Win32 = Debug|Win32
Release Dll|Win32 = Release Dll|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug Dll|Win32.ActiveCfg = Debug Dll|Win32
{D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug Dll|Win32.Build.0 = Debug Dll|Win32
{D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug|Win32.ActiveCfg = Debug|Win32
{D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug|Win32.Build.0 = Debug|Win32
{D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release Dll|Win32.ActiveCfg = Release Dll|Win32
{D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release Dll|Win32.Build.0 = Release Dll|Win32
{D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release|Win32.ActiveCfg = Release|Win32
{D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release|Win32.Build.0 = Release|Win32
{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug Dll|Win32.ActiveCfg = Debug Dll|Win32
{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug Dll|Win32.Build.0 = Debug Dll|Win32
{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug|Win32.ActiveCfg = Debug|Win32
{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug|Win32.Build.0 = Debug|Win32
{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release Dll|Win32.ActiveCfg = Release Dll|Win32
{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release Dll|Win32.Build.0 = Release Dll|Win32
{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release|Win32.ActiveCfg = Release|Win32
{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

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

View file

@ -0,0 +1,184 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug Dll|Win32">
<Configuration>Debug Dll</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release Dll|Win32">
<Configuration>Release Dll</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}</ProjectGuid>
<RootNamespace>upnpcstatic</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>14.0.25123.0</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
<IntDir>$(Configuration)\</IntDir>
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'">
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
<IntDir>$(Configuration)\</IntDir>
<LinkIncremental>true</LinkIncremental>
<TargetName>upnpc-shared</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
<IntDir>$(Configuration)\</IntDir>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'">
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
<IntDir>$(Configuration)\</IntDir>
<LinkIncremental>false</LinkIncremental>
<TargetName>upnpc-shared</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;MINIUPNP_STATICLIB;DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader />
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<AdditionalIncludeDirectories>..;..\include</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;$(Configuration)\miniupnpc.lib;IPHlpApi.Lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;MINIUPNP_STATICLIB;DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<AdditionalIncludeDirectories>..;..\include</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;$(Configuration)\miniupnpc.lib;$(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;MINIUPNP_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader />
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>..;..\include</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;$(Configuration)\miniupnpc.lib;IPHlpApi.Lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>..;..\include</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;$(Configuration)\miniupnpc.lib;IPHlpApi.Lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\src\upnpc.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="miniupnpc.vcxproj">
<Project>{d28ce435-cb33-4bae-8a52-c6ef915956f5}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Fichiers sources">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Fichiers d%27en-tête">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Fichiers de ressources">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\upnpc.c">
<Filter>Fichiers sources</Filter>
</ClCompile>
</ItemGroup>
</Project>

View file

@ -0,0 +1,176 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug Dll|Win32">
<Configuration>Debug Dll</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release Dll|Win32">
<Configuration>Release Dll</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}</ProjectGuid>
<RootNamespace>upnpcstatic</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'">false</LinkIncremental>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">upnpc-static</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'">upnpc-static</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">upnpc-static</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'">upnpc-static</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;MINIUPNP_STATICLIB;DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<AdditionalIncludeDirectories>..;..\include</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;IPHlpApi.Lib;$(Configuration)\miniupnpc.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<AdditionalIncludeDirectories>..;..\include</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;$(Configuration)\miniupnpc.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;MINIUPNP_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>..;..\include</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;IPHlpApi.Lib;$(Configuration)\miniupnpc.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>..;..\include</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;$(Configuration)\miniupnpc.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\src\upnpc.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="miniupnpc_vs2010.vcxproj">
<Project>{d28ce435-cb33-4bae-8a52-c6ef915956f5}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -1,35 +1,70 @@
#! /usr/bin/python
#! /usr/bin/env python
# vim: tabstop=2 shiftwidth=2 expandtab
# MiniUPnP project
# Author : Thomas Bernard
# Python 3
# This Sample code is public domain.
# website : http://miniupnp.tuxfamily.org/
# website : https://miniupnp.tuxfamily.org/
# import the python miniupnpc module
import miniupnpc
import sys
# create the object
u = miniupnpc.UPnP()
print 'inital(default) values :'
print ' discoverdelay', u.discoverdelay
print ' lanaddr', u.lanaddr
print ' multicastif', u.multicastif
print ' minissdpdsocket', u.minissdpdsocket
u.discoverdelay = 200;
try:
import argparse
parser = argparse.ArgumentParser()
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()))
except:
print('argparse not available')
i = 1
multicastif = None
minissdpdsocket = None
discoverdelay = 200
localport = 0
while i < len(sys.argv):
print(sys.argv[i])
if sys.argv[i] == '-m' or sys.argv[i] == '--multicastif':
multicastif = sys.argv[i+1]
elif sys.argv[i] == '-p' or sys.argv[i] == '--minissdpdsocket':
minissdpdsocket = sys.argv[i+1]
elif sys.argv[i] == '-d' or sys.argv[i] == '--discoverdelay':
discoverdelay = int(sys.argv[i+1])
elif sys.argv[i] == '-z' or sys.argv[i] == '--localport':
localport = int(sys.argv[i+1])
else:
raise Exception('invalid argument %s' % sys.argv[i])
i += 2
# create the object
u = miniupnpc.UPnP(multicastif, minissdpdsocket, discoverdelay, localport)
print('inital(default) values :')
print(' discoverdelay', u.discoverdelay)
print(' lanaddr', u.lanaddr)
print(' multicastif', u.multicastif)
print(' minissdpdsocket', u.minissdpdsocket)
#u.minissdpdsocket = '../minissdpd/minissdpd.sock'
# discovery process, it usualy takes several seconds (2 seconds or more)
print 'Discovering... delay=%ums' % u.discoverdelay
print u.discover(), 'device(s) detected'
# discovery process, it usually takes several seconds (2 seconds or more)
print('Discovering... delay=%ums' % u.discoverdelay)
print('%d device(s) detected' % u.discover())
# select an igd
try:
u.selectigd()
except Exception, e:
print 'Exception :', e
except Exception as e:
print('Exception :', e)
sys.exit(1)
# it is also possible to pass the root description URL to u.selectigd() :
# u.selectigd('http://192.168.1.254:5678/desc/root')
# display information about the IGD and the internet connection
print 'local ip address :', u.lanaddr
print 'external ip address :', u.externalipaddress()
print u.statusinfo(), u.connectiontype()
print('local ip address :', u.lanaddr)
print('external ip address :', u.externalipaddress())
print( u.statusinfo(), u.connectiontype())
print('total bytes : sent', u.totalbytesent(), 'received', u.totalbytereceived())
print('total packets : sent', u.totalpacketsent(), 'received', u.totalpacketreceived())
#print u.addportmapping(64000, 'TCP',
# '192.168.1.166', 63000, 'port mapping test', '')
@ -43,10 +78,14 @@ while True:
p = u.getgenericportmapping(i)
if p==None:
break
print i, p
print(i, p)
(port, proto, (ihost,iport), desc, c, d, e) = p
#print port, desc
i = i + 1
print u.getspecificportmapping(port, proto)
print(u.getspecificportmapping(port, proto))
try:
print(u.getportmappingnumberofentries())
except Exception as e:
print('GetPortMappingNumberOfEntries() is not supported :', e)

View file

@ -1,81 +0,0 @@
/* $Id: receivedata.c,v 1.1 2011/04/11 08:21:47 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2011 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
#include <stdio.h>
#ifdef WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <unistd.h>
#if defined(__amigaos__) && !defined(__amigaos4__)
#define socklen_t int
#else /* #if defined(__amigaos__) && !defined(__amigaos4__) */
#include <sys/select.h>
#endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */
#include <sys/socket.h>
#if !defined(__amigaos__) && !defined(__amigaos4__)
#include <poll.h>
#endif
#include <errno.h>
#define MINIUPNPC_IGNORE_EINTR
#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
#include "receivedata.h"
int
receivedata(int socket, char * data, int length, int timeout)
{
int n;
#if !defined(WIN32) && !defined(__amigaos__) && !defined(__amigaos4__)
/* using poll */
struct pollfd fds[1]; /* for the poll */
#ifdef MINIUPNPC_IGNORE_EINTR
do {
#endif
fds[0].fd = socket;
fds[0].events = POLLIN;
n = poll(fds, 1, timeout);
#ifdef MINIUPNPC_IGNORE_EINTR
} while(n < 0 && errno == EINTR);
#endif
if(n < 0) {
PRINT_SOCKET_ERROR("poll");
return -1;
} else if(n == 0) {
/* timeout */
return 0;
}
#else /* !defined(WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
/* using select under WIN32 and amigaos */
fd_set socketSet;
TIMEVAL timeval;
FD_ZERO(&socketSet);
FD_SET(socket, &socketSet);
timeval.tv_sec = timeout / 1000;
timeval.tv_usec = (timeout % 1000) * 1000;
n = select(FD_SETSIZE, &socketSet, NULL, NULL, &timeval);
if(n < 0) {
PRINT_SOCKET_ERROR("select");
return -1;
} else if(n == 0) {
return 0;
}
#endif
n = recv(socket, data, length, 0);
if(n<0) {
PRINT_SOCKET_ERROR("recv");
}
return n;
}

View file

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

View file

@ -1,15 +1,35 @@
#! /usr/bin/python
# $Id: setup.py,v 1.6 2011/01/04 09:46:08 nanard Exp $
# the MiniUPnP Project (c) 2007-2011 Thomas Bernard
# http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/
#! /usr/bin/env python
# vim: tabstop=8 shiftwidth=8 expandtab
# $Id: setup.py,v 1.15 2021/09/28 21:10:11 nanard Exp $
# the MiniUPnP Project (c) 2007-2021 Thomas Bernard
# https://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/
#
# python script to build the miniupnpc module under unix
#
# replace libminiupnpc.a by libminiupnpc.so for shared library usage
from distutils.core import setup, Extension
setup(name="miniupnpc", version="1.5",
ext_modules=[
Extension(name="miniupnpc", sources=["miniupnpcmodule.c"],
extra_objects=["libminiupnpc.a"])
])
# Uses MAKE environment variable (defaulting to 'make')
from setuptools import setup, Extension
from setuptools.command import build_ext
import subprocess
import os
EXT = ['build/libminiupnpc.a']
class make_then_build_ext(build_ext.build_ext):
def run(self):
subprocess.check_call([os.environ.get('MAKE', 'make')] + EXT)
build_ext.build_ext.run(self)
setup(name="miniupnpc",
version=open('VERSION').read().strip(),
author='Thomas BERNARD',
author_email='miniupnp@free.fr',
license=open('LICENSE').read(),
url='http://miniupnp.free.fr/',
description='miniUPnP client',
cmdclass={'build_ext': make_then_build_ext},
ext_modules=[
Extension(name="miniupnpc", sources=["src/miniupnpcmodule.c"],
include_dirs=['include'], extra_objects=EXT)
])

View file

@ -1,15 +1,35 @@
#! /usr/bin/python
# $Id: setupmingw32.py,v 1.5 2011/05/15 21:18:43 nanard Exp $
# the MiniUPnP Project (c) 2007-2011 Thomas Bernard
# http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/
#! /usr/bin/env python
# vim: tabstop=8 shiftwidth=8 expandtab
# $Id: setupmingw32.py,v 1.14 2021/09/28 21:10:11 nanard Exp $
# the MiniUPnP Project (c) 2007-2021 Thomas Bernard
# https://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/
#
# python script to build the miniupnpc module under windows (using mingw32)
#
from distutils.core import setup, Extension
setup(name="miniupnpc", version="1.5",
ext_modules=[
Extension(name="miniupnpc", sources=["miniupnpcmodule.c"],
libraries=["ws2_32", "iphlpapi"],
extra_objects=["libminiupnpc.a"])
])
import sys
if (sys.version_info.major * 10 + sys.version_info.minor) >= 35:
compat_lib = ["legacy_stdio_definitions"]
else:
compat_lib = []
try:
from setuptools import setup, Extension
except ImportError:
from distutils.core import setup, Extension
from distutils import sysconfig
sysconfig.get_config_vars()["OPT"] = ''
sysconfig.get_config_vars()["CFLAGS"] = ''
setup(name="miniupnpc",
version=open('VERSION').read().strip(),
author='Thomas BERNARD',
author_email='miniupnp@free.fr',
license=open('LICENSE').read(),
url='http://miniupnp.free.fr/',
description='miniUPnP client',
ext_modules=[
Extension(name="miniupnpc", sources=["src/miniupnpcmodule.c"],
libraries=["ws2_32", "iphlpapi"] + compat_lib,
include_dirs=['include'], extra_objects=["miniupnpc.lib"])
])

View file

@ -0,0 +1,79 @@
/* $Id: addr_is_reserved.c,v 1.5 2021/05/10 20:53:02 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* Project : miniupnp
* Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
* Author : Thomas BERNARD
* copyright (c) 2005-2021 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENSE file. */
#ifdef _WIN32
/* Win32 Specific includes and defines */
#include <winsock2.h>
#include <ws2tcpip.h>
#if !defined(_MSC_VER)
#include <stdint.h>
#else /* !defined(_MSC_VER) */
typedef unsigned long uint32_t;
#endif /* !defined(_MSC_VER) */
#else /* _WIN32 */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif /* _WIN32 */
/* List of IP address blocks which are private / reserved and therefore not suitable for public external IP addresses */
#define IP(a, b, c, d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d))
#define MSK(m) (32-(m))
static const struct { uint32_t address; uint32_t rmask; } reserved[] = {
{ IP( 0, 0, 0, 0), MSK( 8) }, /* RFC1122 "This host on this network" */
{ IP( 10, 0, 0, 0), MSK( 8) }, /* RFC1918 Private-Use */
{ IP(100, 64, 0, 0), MSK(10) }, /* RFC6598 Shared Address Space */
{ IP(127, 0, 0, 0), MSK( 8) }, /* RFC1122 Loopback */
{ IP(169, 254, 0, 0), MSK(16) }, /* RFC3927 Link-Local */
{ IP(172, 16, 0, 0), MSK(12) }, /* RFC1918 Private-Use */
{ IP(192, 0, 0, 0), MSK(24) }, /* RFC6890 IETF Protocol Assignments */
{ IP(192, 0, 2, 0), MSK(24) }, /* RFC5737 Documentation (TEST-NET-1) */
{ IP(192, 31, 196, 0), MSK(24) }, /* RFC7535 AS112-v4 */
{ IP(192, 52, 193, 0), MSK(24) }, /* RFC7450 AMT */
{ IP(192, 88, 99, 0), MSK(24) }, /* RFC7526 6to4 Relay Anycast */
{ IP(192, 168, 0, 0), MSK(16) }, /* RFC1918 Private-Use */
{ IP(192, 175, 48, 0), MSK(24) }, /* RFC7534 Direct Delegation AS112 Service */
{ IP(198, 18, 0, 0), MSK(15) }, /* RFC2544 Benchmarking */
{ IP(198, 51, 100, 0), MSK(24) }, /* RFC5737 Documentation (TEST-NET-2) */
{ IP(203, 0, 113, 0), MSK(24) }, /* RFC5737 Documentation (TEST-NET-3) */
{ IP(224, 0, 0, 0), MSK( 4) }, /* RFC1112 Multicast */
{ IP(240, 0, 0, 0), MSK( 4) }, /* RFC1112 Reserved for Future Use + RFC919 Limited Broadcast */
};
#undef IP
#undef MSK
/**
* @return 1 or 0
*/
int addr_is_reserved(const char * addr_str)
{
uint32_t addr_n, address;
size_t i;
#if defined(_WIN32) && _WIN32_WINNT < 0x0600 // _WIN32_WINNT_VISTA
addr_n = inet_addr(addr_str);
if (addr_n == INADDR_NONE)
return 1;
#else
/* was : addr_n = inet_addr(addr_str); */
if (inet_pton(AF_INET, addr_str, &addr_n) <= 0) {
/* error */
return 1;
}
#endif
address = ntohl(addr_n);
for (i = 0; i < sizeof(reserved)/sizeof(reserved[0]); ++i) {
if ((address >> reserved[i].rmask) == (reserved[i].address >> reserved[i].rmask))
return 1;
}
return 0;
}

View file

@ -0,0 +1,14 @@
/* $Id: addr_is_reserved.h,v 1.1 2020/09/28 21:11:19 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-2020 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef ADDR_IS_RESERVED_H_INCLUDED
#define ADDR_IS_RESERVED_H_INCLUDED
int addr_is_reserved(const char * addr_str);
#endif /* ADDR_IS_RESERVED_H_INCLUDED */

View file

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

View file

@ -1,7 +1,8 @@
/* $Id: connecthostport.c,v 1.5 2011/04/09 08:49:50 nanard Exp $ */
/* Project : miniupnp
/* $Id: connecthostport.c,v 1.24 2020/11/09 19:26:53 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2010-2011 Thomas Bernard
* Copyright (c) 2010-2020 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
@ -13,35 +14,32 @@
#include <string.h>
#include <stdio.h>
#ifdef WIN32
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
#define MAXHOSTNAMELEN 64
#define snprintf _snprintf
#include "win32_snprintf.h"
#define herror
#define socklen_t int
#else /* #ifdef WIN32 */
#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>
#define closesocket close
#include <netdb.h>
#include <netinet/in.h>
/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions
* during the connect() call */
#define MINIUPNPC_IGNORE_EINTR
#ifndef USE_GETHOSTBYNAME
#include <sys/types.h>
#include <sys/socket.h>
#endif /* #ifndef USE_GETHOSTBYNAME */
#endif /* #else WIN32 */
/* definition of PRINT_SOCKET_ERROR */
#ifdef WIN32
#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
#else
#define PRINT_SOCKET_ERROR(x) perror(x)
#endif
#include <sys/select.h>
#endif /* #else _WIN32 */
#if defined(__amigaos__) || defined(__amigaos4__)
#define herror(A) printf("%s\n", A)
@ -49,12 +47,18 @@
#include "connecthostport.h"
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
/* connecthostport()
* return a socket connected (TCP) to the host and port
* or -1 in case of error */
int connecthostport(const char * host, unsigned short port)
SOCKET connecthostport(const char * host, unsigned short port,
unsigned int scope_id)
{
int s, n;
SOCKET s;
int n;
#ifdef USE_GETHOSTBYNAME
struct sockaddr_in dest;
struct hostent *hp;
@ -67,21 +71,21 @@ int connecthostport(const char * host, unsigned short port)
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
struct timeval timeout;
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
#ifdef USE_GETHOSTBYNAME
hp = gethostbyname(host);
if(hp == NULL)
{
herror(host);
return -1;
return INVALID_SOCKET;
}
memcpy(&dest.sin_addr, hp->h_addr, sizeof(dest.sin_addr));
memset(dest.sin_zero, 0, sizeof(dest.sin_zero));
s = socket(PF_INET, SOCK_STREAM, 0);
if(s < 0)
if(ISINVALID(s))
{
PRINT_SOCKET_ERROR("socket");
return -1;
return INVALID_SOCKET;
}
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
/* setting a 3 seconds timeout for the connect() call */
@ -89,35 +93,52 @@ int connecthostport(const char * host, unsigned short port)
timeout.tv_usec = 0;
if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0)
{
PRINT_SOCKET_ERROR("setsockopt");
PRINT_SOCKET_ERROR("setsockopt SO_RCVTIMEO");
}
timeout.tv_sec = 3;
timeout.tv_usec = 0;
if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0)
{
PRINT_SOCKET_ERROR("setsockopt");
PRINT_SOCKET_ERROR("setsockopt SO_SNDTIMEO");
}
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
dest.sin_family = AF_INET;
dest.sin_port = htons(port);
n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in));
#ifdef MINIUPNPC_IGNORE_EINTR
while(n < 0 && errno == EINTR)
/* EINTR The system call was interrupted by a signal that was caught
* EINPROGRESS The socket is nonblocking and the connection cannot
* be completed immediately. */
while(n < 0 && (errno == EINTR || errno == EINPROGRESS))
{
socklen_t len;
fd_set wset;
int err;
FD_ZERO(&wset);
FD_SET(s, &wset);
if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR)
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
timeout.tv_sec = 3;
timeout.tv_usec = 0;
n = select(s + 1, NULL, &wset, NULL, &timeout);
#else
n = select(s + 1, NULL, &wset, NULL, NULL);
#endif
if(n == -1 && errno == EINTR)
continue;
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
if(n == 0) {
errno = ETIMEDOUT;
n = -1;
break;
}
#endif
/*len = 0;*/
/*n = getpeername(s, NULL, &len);*/
len = sizeof(err);
if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {
PRINT_SOCKET_ERROR("getsockopt");
closesocket(s);
return -1;
return INVALID_SOCKET;
}
if(err != 0) {
errno = err;
@ -129,7 +150,7 @@ int connecthostport(const char * host, unsigned short port)
{
PRINT_SOCKET_ERROR("connect");
closesocket(s);
return -1;
return INVALID_SOCKET;
}
#else /* #ifdef USE_GETHOSTBYNAME */
/* use getaddrinfo() instead of gethostbyname() */
@ -145,10 +166,12 @@ int connecthostport(const char * host, unsigned short port)
if(host[0] == '[')
{
/* literal ip v6 address */
int i;
for(i = 0; host[i+1] && (host[i+1] != ']') && i < MAXHOSTNAMELEN; i++)
int i, j;
for(i = 0, j = 1; host[j] && (host[j] != ']') && i < MAXHOSTNAMELEN; i++, j++)
{
tmp_host[i] = host[i+1];
tmp_host[i] = host[j];
if(0 == strncmp(host+j, "%25", 3)) /* %25 is just url encoding for '%' */
j+=2; /* skip "25" */
}
tmp_host[i] = '\0';
}
@ -160,19 +183,29 @@ int connecthostport(const char * host, unsigned short port)
n = getaddrinfo(tmp_host, port_str, &hints, &ai);
if(n != 0)
{
#ifdef WIN32
#ifdef _WIN32
fprintf(stderr, "getaddrinfo() error : %d\n", n);
#else
fprintf(stderr, "getaddrinfo() error : %s\n", gai_strerror(n));
#endif
return -1;
return INVALID_SOCKET;
}
s = -1;
s = INVALID_SOCKET;
for(p = ai; p; p = p->ai_next)
{
if(!ISINVALID(s))
closesocket(s);
#ifdef DEBUG
printf("ai_family=%d ai_socktype=%d ai_protocol=%d (PF_INET=%d, PF_INET6=%d)\n",
p->ai_family, p->ai_socktype, p->ai_protocol, PF_INET, PF_INET6);
#endif
s = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if(s < 0)
if(ISINVALID(s))
continue;
if(p->ai_addr->sa_family == AF_INET6 && scope_id > 0) {
struct sockaddr_in6 * addr6 = (struct sockaddr_in6 *)p->ai_addr;
addr6->sin6_scope_id = scope_id;
}
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
/* setting a 3 seconds timeout for the connect() call */
timeout.tv_sec = 3;
@ -188,17 +221,34 @@ int connecthostport(const char * host, unsigned short port)
PRINT_SOCKET_ERROR("setsockopt");
}
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
n = connect(s, p->ai_addr, p->ai_addrlen);
n = connect(s, p->ai_addr, MSC_CAST_INT p->ai_addrlen);
#ifdef MINIUPNPC_IGNORE_EINTR
while(n < 0 && errno == EINTR)
/* EINTR The system call was interrupted by a signal that was caught
* EINPROGRESS The socket is nonblocking and the connection cannot
* be completed immediately. */
while(n < 0 && (errno == EINTR || errno == EINPROGRESS))
{
socklen_t len;
fd_set wset;
int err;
FD_ZERO(&wset);
FD_SET(s, &wset);
if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR)
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
timeout.tv_sec = 3;
timeout.tv_usec = 0;
n = select(s + 1, NULL, &wset, NULL, &timeout);
#else
n = select(s + 1, NULL, &wset, NULL, NULL);
#endif
if(n == -1 && errno == EINTR)
continue;
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
if(n == 0) {
errno = ETIMEDOUT;
n = -1;
break;
}
#endif
/*len = 0;*/
/*n = getpeername(s, NULL, &len);*/
len = sizeof(err);
@ -206,7 +256,7 @@ int connecthostport(const char * host, unsigned short port)
PRINT_SOCKET_ERROR("getsockopt");
closesocket(s);
freeaddrinfo(ai);
return -1;
return INVALID_SOCKET;
}
if(err != 0) {
errno = err;
@ -214,28 +264,21 @@ int connecthostport(const char * host, unsigned short port)
}
}
#endif /* #ifdef MINIUPNPC_IGNORE_EINTR */
if(n < 0)
{
closesocket(s);
continue;
}
else
{
if(n >= 0) /* connect() was successful */
break;
}
}
freeaddrinfo(ai);
if(s < 0)
if(ISINVALID(s))
{
PRINT_SOCKET_ERROR("socket");
return -1;
return INVALID_SOCKET;
}
if(n < 0)
{
PRINT_SOCKET_ERROR("connect");
return -1;
closesocket(s);
return INVALID_SOCKET;
}
#endif /* #ifdef USE_GETHOSTBYNAME */
return s;
}

View file

@ -0,0 +1,20 @@
/* $Id: connecthostport.h,v 1.4 2018/04/06 10:53:13 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/
* Author: Thomas Bernard
* Copyright (c) 2010-2018 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef CONNECTHOSTPORT_H_INCLUDED
#define CONNECTHOSTPORT_H_INCLUDED
#include "miniupnpc_socketdef.h"
/* connecthostport()
* return a socket connected (TCP) to the host and port
* or INVALID_SOCKET in case of error */
SOCKET connecthostport(const char * host, unsigned short port,
unsigned int scope_id);
#endif

View file

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

View file

@ -0,0 +1,197 @@
/* $Id: listdevices.c,v 1.8 2018/05/03 08:16:44 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2013-2015 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef _WIN32
#include <winsock2.h>
#endif /* _WIN32 */
#include "miniupnpc.h"
struct upnp_dev_list {
struct upnp_dev_list * next;
char * descURL;
struct UPNPDev * * array;
size_t count;
size_t allocated_count;
};
#define ADD_DEVICE_COUNT_STEP 16
void add_device(struct upnp_dev_list * * list_head, struct UPNPDev * dev)
{
struct upnp_dev_list * elt;
size_t i;
if(dev == NULL)
return;
for(elt = *list_head; elt != NULL; elt = elt->next) {
if(strcmp(elt->descURL, dev->descURL) == 0) {
for(i = 0; i < elt->count; i++) {
if (strcmp(elt->array[i]->st, dev->st) == 0 && strcmp(elt->array[i]->usn, dev->usn) == 0) {
return; /* already found */
}
}
if(elt->count >= elt->allocated_count) {
struct UPNPDev * * tmp;
elt->allocated_count += ADD_DEVICE_COUNT_STEP;
tmp = realloc(elt->array, elt->allocated_count * sizeof(struct UPNPDev *));
if(tmp == NULL) {
fprintf(stderr, "Failed to realloc(%p, %lu)\n", elt->array, (unsigned long)(elt->allocated_count * sizeof(struct UPNPDev *)));
return;
}
elt->array = tmp;
}
elt->array[elt->count++] = dev;
return;
}
}
elt = malloc(sizeof(struct upnp_dev_list));
if(elt == NULL) {
fprintf(stderr, "Failed to malloc(%lu)\n", (unsigned long)sizeof(struct upnp_dev_list));
return;
}
elt->next = *list_head;
elt->descURL = strdup(dev->descURL);
if(elt->descURL == NULL) {
fprintf(stderr, "Failed to strdup(%s)\n", dev->descURL);
free(elt);
return;
}
elt->allocated_count = ADD_DEVICE_COUNT_STEP;
elt->array = malloc(ADD_DEVICE_COUNT_STEP * sizeof(struct UPNPDev *));
if(elt->array == NULL) {
fprintf(stderr, "Failed to malloc(%lu)\n", (unsigned long)(ADD_DEVICE_COUNT_STEP * sizeof(struct UPNPDev *)));
free(elt->descURL);
free(elt);
return;
}
elt->array[0] = dev;
elt->count = 1;
*list_head = elt;
}
void free_device(struct upnp_dev_list * elt)
{
free(elt->descURL);
free(elt->array);
free(elt);
}
int main(int argc, char * * argv)
{
const char * searched_device = NULL;
const char * * searched_devices = NULL;
const char * multicastif = 0;
const char * minissdpdpath = 0;
int ipv6 = 0;
unsigned char ttl = 2;
int error = 0;
struct UPNPDev * devlist = 0;
struct UPNPDev * dev;
struct upnp_dev_list * sorted_list = NULL;
struct upnp_dev_list * dev_array;
int i;
#ifdef _WIN32
WSADATA wsaData;
int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if(nResult != NO_ERROR)
{
fprintf(stderr, "WSAStartup() failed.\n");
return -1;
}
#endif
for(i = 1; i < argc; i++) {
if(strcmp(argv[i], "-6") == 0)
ipv6 = 1;
else if(strcmp(argv[i], "-d") == 0) {
if(++i >= argc) {
fprintf(stderr, "%s option needs one argument\n", "-d");
return 1;
}
searched_device = argv[i];
} else if(strcmp(argv[i], "-t") == 0) {
if(++i >= argc) {
fprintf(stderr, "%s option needs one argument\n", "-t");
return 1;
}
ttl = (unsigned char)atoi(argv[i]);
} else if(strcmp(argv[i], "-l") == 0) {
if(++i >= argc) {
fprintf(stderr, "-l option needs at least one argument\n");
return 1;
}
searched_devices = (const char * *)(argv + i);
break;
} else if(strcmp(argv[i], "-m") == 0) {
if(++i >= argc) {
fprintf(stderr, "-m option needs one argument\n");
return 1;
}
multicastif = argv[i];
} else {
printf("usage : %s [options] [-l <device1> <device2> ...]\n", argv[0]);
printf("options :\n");
printf(" -6 : use IPv6\n");
printf(" -m address/ifname : network interface to use for multicast\n");
printf(" -d <device string> : search only for this type of device\n");
printf(" -l <device1> <device2> ... : search only for theses types of device\n");
printf(" -t ttl : set multicast TTL. Default value is 2.\n");
printf(" -h : this help\n");
return 1;
}
}
if(searched_device) {
printf("searching UPnP device type %s\n", searched_device);
devlist = upnpDiscoverDevice(searched_device,
2000, multicastif, minissdpdpath,
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/*localport*/, ipv6, ttl, &error, 1);
} else {
printf("searching all UPnP devices\n");
devlist = upnpDiscoverAll(2000, multicastif, minissdpdpath,
0/*localport*/, ipv6, ttl, &error);
}
if(devlist) {
for(dev = devlist, i = 1; dev != NULL; dev = dev->pNext, i++) {
printf("%3d: %-48s\n", i, dev->st);
printf(" %s\n", dev->descURL);
printf(" %s\n", dev->usn);
add_device(&sorted_list, dev);
}
putchar('\n');
for (dev_array = sorted_list; dev_array != NULL ; dev_array = dev_array->next) {
printf("%s :\n", dev_array->descURL);
for(i = 0; (unsigned)i < dev_array->count; i++) {
printf("%2d: %s\n", i+1, dev_array->array[i]->st);
printf(" %s\n", dev_array->array[i]->usn);
}
putchar('\n');
}
freeUPNPDevlist(devlist);
while(sorted_list != NULL) {
dev_array = sorted_list;
sorted_list = sorted_list->next;
free_device(dev_array);
}
} else {
printf("no device found.\n");
}
return 0;
}

View file

@ -1,7 +1,7 @@
/* $Id: minihttptestserver.c,v 1.6 2011/05/09 08:53:15 nanard Exp $ */
/* $Id: minihttptestserver.c,v 1.25 2020/05/29 21:14:22 nanard Exp $ */
/* Project : miniUPnP
* Author : Thomas Bernard
* Copyright (c) 2011 Thomas Bernard
* Copyright (c) 2011-2018 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
@ -16,36 +16,43 @@
#include <netinet/in.h>
#include <signal.h>
#include <time.h>
#include <errno.h>
#ifndef INADDR_LOOPBACK
#define INADDR_LOOPBACK 0x7f000001
#endif
#define CRAP_LENGTH (2048)
volatile int quit = 0;
volatile int child_to_wait_for = 0;
static int server(unsigned short port, const char * expected_file_name, int ipv6);
volatile sig_atomic_t quit = 0;
volatile sig_atomic_t child_to_wait_for = 0;
/**
* signal handler for SIGCHLD (child status has changed)
*/
void handle_signal_chld(int sig)
{
printf("handle_signal_chld(%d)\n", sig);
(void)sig;
/* printf("handle_signal_chld(%d)\n", sig); */
++child_to_wait_for;
}
/**
* signal handler for SIGINT (CRTL C)
*/
#if 0
void handle_signal_int(int sig)
{
printf("handle_signal_int(%d)\n", sig);
(void)sig;
/* printf("handle_signal_int(%d)\n", sig); */
quit = 1;
}
#endif
/**
* build a text/plain content of the specified length
*/
void build_content(char * p, int n)
void build_content(char * p, size_t n)
{
char line_buffer[80];
int k;
@ -74,10 +81,10 @@ void build_content(char * p, int n)
/**
* build crappy content
*/
void build_crap(char * p, int n)
void build_crap(char * p, size_t n)
{
static const char crap[] = "_CRAP_\r\n";
int i;
size_t i;
while(n > 0) {
i = sizeof(crap) - 1;
@ -93,15 +100,19 @@ void build_crap(char * p, int n)
* build chunked response.
* return a malloc'ed buffer
*/
char * build_chunked_response(int content_length, int * response_len) {
char * build_chunked_response(size_t content_length, size_t * response_len)
{
char * response_buffer;
char * content_buffer;
int buffer_length;
int i, n;
size_t buffer_length;
size_t i;
unsigned int n;
/* allocate to have some margin */
buffer_length = 256 + content_length + (content_length >> 4);
response_buffer = malloc(buffer_length);
if(response_buffer == NULL)
return NULL;
*response_len = snprintf(response_buffer, buffer_length,
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/plain\r\n"
@ -110,6 +121,10 @@ char * build_chunked_response(int content_length, int * response_len) {
/* build the content */
content_buffer = malloc(content_length);
if(content_buffer == NULL) {
free(response_buffer);
return NULL;
}
build_content(content_buffer, content_length);
/* chunk it */
@ -129,16 +144,126 @@ char * build_chunked_response(int content_length, int * response_len) {
response_buffer[(*response_len)++] = '\r';
response_buffer[(*response_len)++] = '\n';
}
memcpy(response_buffer + *response_len, "0\r\n", 3);
*response_len += 3;
/* the last chunk : "0\r\n" a empty body and then
* the final "\r\n" */
memcpy(response_buffer + *response_len, "0\r\n\r\n", 5);
*response_len += 5;
free(content_buffer);
printf("resp_length=%d buffer_length=%d content_length=%d\n",
printf("resp_length=%lu buffer_length=%lu content_length=%lu\n",
*response_len, buffer_length, content_length);
return response_buffer;
}
enum modes { MODE_INVALID, MODE_CHUNKED, MODE_ADDCRAP, MODE_NORMAL };
/* favicon.ico generator */
#ifdef OLD_HEADER
#define FAVICON_LENGTH (6 + 16 + 12 + 8 + 32 * 4)
#else
#define FAVICON_LENGTH (6 + 16 + 40 + 8 + 32 * 4)
#endif
void build_favicon_content(unsigned char * p, size_t n)
{
int i;
if(n < FAVICON_LENGTH)
return;
/* header : 6 bytes */
*p++ = 0;
*p++ = 0;
*p++ = 1; /* type : ICO */
*p++ = 0;
*p++ = 1; /* number of images in file */
*p++ = 0;
/* image directory (1 entry) : 16 bytes */
*p++ = 16; /* width */
*p++ = 16; /* height */
*p++ = 2; /* number of colors in the palette. 0 = no palette */
*p++ = 0; /* reserved */
*p++ = 1; /* color planes */
*p++ = 0; /* " */
*p++ = 1; /* bpp */
*p++ = 0; /* " */
#ifdef OLD_HEADER
*p++ = 12 + 8 + 32 * 4; /* bmp size */
#else
*p++ = 40 + 8 + 32 * 4; /* bmp size */
#endif
*p++ = 0; /* " */
*p++ = 0; /* " */
*p++ = 0; /* " */
*p++ = 6 + 16; /* bmp offset */
*p++ = 0; /* " */
*p++ = 0; /* " */
*p++ = 0; /* " */
/* BMP */
#ifdef OLD_HEADER
/* BITMAPCOREHEADER */
*p++ = 12; /* size of this header */
*p++ = 0; /* " */
*p++ = 0; /* " */
*p++ = 0; /* " */
*p++ = 16; /* width */
*p++ = 0; /* " */
*p++ = 16 * 2; /* height x 2 ! */
*p++ = 0; /* " */
*p++ = 1; /* color planes */
*p++ = 0; /* " */
*p++ = 1; /* bpp */
*p++ = 0; /* " */
#else
/* BITMAPINFOHEADER */
*p++ = 40; /* size of this header */
*p++ = 0; /* " */
*p++ = 0; /* " */
*p++ = 0; /* " */
*p++ = 16; /* width */
*p++ = 0; /* " */
*p++ = 0; /* " */
*p++ = 0; /* " */
*p++ = 16 * 2; /* height x 2 ! */
*p++ = 0; /* " */
*p++ = 0; /* " */
*p++ = 0; /* " */
*p++ = 1; /* color planes */
*p++ = 0; /* " */
*p++ = 1; /* bpp */
*p++ = 0; /* " */
/* compression method, image size, ppm x, ppm y */
/* colors in the palette ? */
/* important colors */
for(i = 4 * 6; i > 0; --i)
*p++ = 0;
#endif
/* palette */
*p++ = 0; /* b */
*p++ = 0; /* g */
*p++ = 0; /* r */
*p++ = 0; /* reserved */
*p++ = 255; /* b */
*p++ = 255; /* g */
*p++ = 255; /* r */
*p++ = 0; /* reserved */
/* pixel data */
for(i = 16; i > 0; --i) {
if(i & 1) {
*p++ = 0125;
*p++ = 0125;
} else {
*p++ = 0252;
*p++ = 0252;
}
*p++ = 0;
*p++ = 0;
}
/* Opacity MASK */
for(i = 16 * 4; i > 0; --i) {
*p++ = 0;
}
}
enum modes {
MODE_INVALID, MODE_CHUNKED, MODE_ADDCRAP, MODE_NORMAL, MODE_FAVICON, MODE_MALFORMED
};
const struct {
const enum modes mode;
const char * text;
@ -146,28 +271,33 @@ const struct {
{MODE_CHUNKED, "chunked"},
{MODE_ADDCRAP, "addcrap"},
{MODE_NORMAL, "normal"},
{MODE_FAVICON, "favicon.ico"},
{MODE_MALFORMED, "malformed"},
{MODE_INVALID, NULL}
};
/**
* write the response with random behaviour !
*/
void send_response(int c, const char * buffer, int len)
void send_response(int c, const char * buffer, size_t len)
{
int n;
ssize_t n;
while(len > 0) {
n = (rand() % 99) + 1;
if(n > len)
if((size_t)n > len)
n = len;
n = write(c, buffer, n);
if(n < 0) {
perror("write");
return;
if(errno != EINTR) {
perror("write");
return;
}
/* if errno == EINTR, try again */
} else {
len -= n;
buffer += n;
usleep(10000); /* 10ms */
}
usleep(10000); /* 10ms */
}
}
@ -177,17 +307,18 @@ void send_response(int c, const char * buffer, int len)
void handle_http_connection(int c)
{
char request_buffer[2048];
int request_len = 0;
size_t request_len = 0;
int headers_found = 0;
int n, i;
ssize_t n, m;
size_t i;
char request_method[16];
char request_uri[256];
char http_version[16];
char * p;
char * response_buffer;
int response_len;
size_t response_len;
enum modes mode;
int content_length = 16*1024;
size_t content_length = 16*1024;
/* read the request */
while(request_len < sizeof(request_buffer) && !headers_found) {
@ -195,6 +326,8 @@ void handle_http_connection(int c)
request_buffer + request_len,
sizeof(request_buffer) - request_len);
if(n < 0) {
if(errno == EINTR)
continue;
perror("read");
return;
} else if(n==0) {
@ -213,9 +346,10 @@ void handle_http_connection(int c)
}
if(!headers_found) {
/* error */
printf("no HTTP header found in the request\n");
return;
}
printf("headers :\n%.*s", request_len, request_buffer);
printf("headers :\n%.*s", (int)request_len, request_buffer);
/* the request have been received, now parse the request line */
p = request_buffer;
for(i = 0; i < sizeof(request_method) - 1; i++) {
@ -227,7 +361,7 @@ void handle_http_connection(int c)
request_method[i] = '\0';
while(*p == ' ')
p++;
for(i = 0; i < sizeof(request_uri) - 1; i++) {
for(i = 0; i < (int)sizeof(request_uri) - 1; i++) {
if(*p == ' ' || *p == '\r')
break;
request_uri[i] = *p;
@ -236,7 +370,7 @@ void handle_http_connection(int c)
request_uri[i] = '\0';
while(*p == ' ')
p++;
for(i = 0; i < sizeof(http_version) - 1; i++) {
for(i = 0; i < (int)sizeof(http_version) - 1; i++) {
if(*p == ' ' || *p == '\r')
break;
http_version[i] = *p;
@ -249,10 +383,24 @@ void handle_http_connection(int c)
if(0 != strcmp(request_method, "GET")) {
const char response405[] = "HTTP/1.1 405 Method Not Allowed\r\n"
"Allow: GET\r\n\r\n";
const char * pc;
/* 405 Method Not Allowed */
/* The response MUST include an Allow header containing a list
* of valid methods for the requested resource. */
write(c, response405, sizeof(response405) - 1);
n = sizeof(response405) - 1;
pc = response405;
while(n > 0) {
m = write(c, pc, n);
if(m<0) {
if(errno != EINTR) {
perror("write");
return;
}
} else {
n -= m;
pc += m;
}
}
return;
}
@ -266,33 +414,81 @@ void handle_http_connection(int c)
}
switch(mode) {
case MODE_MALFORMED:
response_len = 2048;
response_buffer = malloc(response_len);
if(!response_buffer)
break;
n = snprintf(response_buffer, response_len,
"HTTP/1.1 \r\n"
"\r\n"
/*"0000\r\n"*/);
for (i = n; i < response_len; i++) {
response_buffer[i] = ' ';
}
response_len = n;
break;
case MODE_CHUNKED:
response_buffer = build_chunked_response(content_length, &response_len);
break;
case MODE_ADDCRAP:
response_len = content_length+256;
response_buffer = malloc(response_len);
if(!response_buffer)
break;
n = snprintf(response_buffer, response_len,
"HTTP/1.1 200 OK\r\n"
"Server: minihttptestserver\r\n"
"Content-Type: text/plain\r\n"
"Content-Length: %d\r\n"
"Content-Length: %lu\r\n"
"\r\n", content_length);
response_len = content_length+n+CRAP_LENGTH;
response_buffer = realloc(response_buffer, response_len);
p = realloc(response_buffer, response_len);
if(p == NULL) {
/* error 500 */
free(response_buffer);
response_buffer = NULL;
break;
}
response_buffer = p;
build_content(response_buffer + n, content_length);
build_crap(response_buffer + n + content_length, CRAP_LENGTH);
break;
case MODE_FAVICON:
content_length = FAVICON_LENGTH;
response_len = content_length + 256;
response_buffer = malloc(response_len);
if(!response_buffer)
break;
n = snprintf(response_buffer, response_len,
"HTTP/1.1 200 OK\r\n"
"Server: minihttptestserver\r\n"
"Content-Type: image/vnd.microsoft.icon\r\n"
"Content-Length: %lu\r\n"
"\r\n", content_length);
/* image/x-icon */
build_favicon_content((unsigned char *)(response_buffer + n), content_length);
response_len = content_length + n;
break;
default:
response_len = content_length+256;
response_buffer = malloc(response_len);
if(!response_buffer)
break;
n = snprintf(response_buffer, response_len,
"HTTP/1.1 200 OK\r\n"
"Server: minihttptestserver\r\n"
"Content-Type: text/plain\r\n"
"\r\n");
response_len = content_length+n;
response_buffer = realloc(response_buffer, response_len);
p = realloc(response_buffer, response_len);
if(p == NULL) {
/* Error 500 */
free(response_buffer);
response_buffer = NULL;
break;
}
response_buffer = p;
build_content(response_buffer + n, response_len - n);
}
@ -308,15 +504,8 @@ void handle_http_connection(int c)
*/
int main(int argc, char * * argv) {
int ipv6 = 0;
int s, c, i;
int r, i;
unsigned short port = 0;
struct sockaddr_storage server_addr;
socklen_t server_addrlen;
struct sockaddr_storage client_addr;
socklen_t client_addrlen;
pid_t pid;
int child = 0;
int status;
const char * expected_file_name = NULL;
for(i = 1; i < argc; i++) {
@ -339,15 +528,46 @@ int main(int argc, char * * argv) {
fprintf(stderr, "unknown command line switch '%s'\n", argv[i]);
}
} else {
fprintf(stderr, "unkown command line argument '%s'\n", argv[i]);
fprintf(stderr, "unknown command line argument '%s'\n", argv[i]);
}
}
srand(time(NULL));
signal(SIGCHLD, handle_signal_chld);
#if 0
signal(SIGINT, handle_signal_int);
#endif
r = server(port, expected_file_name, ipv6);
if(r != 0) {
printf("*** ERROR ***\n");
}
return r;
}
static int server(unsigned short port, const char * expected_file_name, int ipv6)
{
int s, c;
int i;
struct sockaddr_storage server_addr;
socklen_t server_addrlen;
struct sockaddr_storage client_addr;
socklen_t client_addrlen;
pid_t pid;
int child = 0;
int status;
struct sigaction sa;
memset(&sa, 0, sizeof(struct sigaction));
/*signal(SIGCHLD, handle_signal_chld);*/
sa.sa_handler = handle_signal_chld;
if(sigaction(SIGCHLD, &sa, NULL) < 0) {
perror("sigaction");
return 1;
}
/*signal(SIGINT, handle_signal_int);*/
sa.sa_handler = handle_signal_int;
if(sigaction(SIGINT, &sa, NULL) < 0) {
perror("sigaction");
return 1;
}
s = socket(ipv6 ? AF_INET6 : AF_INET, SOCK_STREAM, 0);
if(s < 0) {
@ -360,12 +580,12 @@ int main(int argc, char * * argv) {
struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&server_addr;
addr->sin6_family = AF_INET6;
addr->sin6_port = htons(port);
addr->sin6_addr = in6addr_any;
addr->sin6_addr = in6addr_loopback;
} else {
struct sockaddr_in * addr = (struct sockaddr_in *)&server_addr;
addr->sin_family = AF_INET;
addr->sin_port = htons(port);
addr->sin_addr.s_addr = htonl(INADDR_ANY);
addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
}
if(bind(s, (struct sockaddr *)&server_addr,
ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) < 0) {
@ -399,10 +619,19 @@ int main(int argc, char * * argv) {
if(f) {
char * buffer;
buffer = malloc(16*1024);
build_content(buffer, 16*1024);
fwrite(buffer, 1, 16*1024, f);
free(buffer);
if(buffer == NULL) {
fprintf(stderr, "memory allocation error\n");
} else {
build_content(buffer, 16*1024);
i = fwrite(buffer, 1, 16*1024, f);
if(i != 16*1024) {
fprintf(stderr, "error writing to file %s : %dbytes written (out of %d)\n", expected_file_name, i, 16*1024);
}
free(buffer);
}
fclose(f);
} else {
fprintf(stderr, "error opening file %s for writing\n", expected_file_name);
}
}
@ -413,16 +642,16 @@ int main(int argc, char * * argv) {
if(pid < 0) {
perror("wait");
} else {
printf("child(%d) terminated with status %d\n", pid, status);
printf("child(%d) terminated with status %d\n", (int)pid, status);
}
--child_to_wait_for;
}
/* TODO : add a select() call in order to handle the case
* when a signal is caught */
client_addrlen = sizeof(struct sockaddr_storage);
c = accept(s, (struct sockaddr *)&client_addr,
&client_addrlen);
if(c < 0) {
if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
continue;
perror("accept");
return 1;
}
@ -450,7 +679,7 @@ int main(int argc, char * * argv) {
if(pid < 0) {
perror("wait");
} else {
printf("child(%d) terminated with status %d\n", pid, status);
printf("child(%d) terminated with status %d\n", (int)pid, status);
}
--child_to_wait_for;
}

View file

@ -1,7 +1,8 @@
/* $Id: minisoap.c,v 1.21 2011/03/22 19:15:35 nanard Exp $ */
/* Project : miniupnp
/* $Id: minisoap.c,v 1.30 2020/11/09 19:27:42 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005-2009 Thomas Bernard
* Copyright (c) 2005-2020 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
*
@ -9,10 +10,10 @@
*/
#include <stdio.h>
#include <string.h>
#ifdef WIN32
#ifdef _WIN32
#include <io.h>
#include <winsock2.h>
#define snprintf _snprintf
#include "win32_snprintf.h"
#else
#include <unistd.h>
#include <sys/types.h>
@ -24,16 +25,10 @@
/* only for malloc */
#include <stdlib.h>
#ifdef WIN32
#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
#else
#define PRINT_SOCKET_ERROR(x) perror(x)
#endif
/* httpWrite sends the headers and the body to the socket
* and returns the number of bytes sent */
static int
httpWrite(int fd, const char * body, int bodysize,
httpWrite(SOCKET fd, const char * body, int bodysize,
const char * headers, int headerssize)
{
int n = 0;
@ -43,10 +38,10 @@ httpWrite(int fd, const char * body, int bodysize,
/* Note : my old linksys router only took into account
* soap request that are sent into only one packet */
char * p;
/* TODO: AVOID MALLOC */
/* TODO: AVOID MALLOC, we could use writev() for that */
p = malloc(headerssize+bodysize);
if(!p)
return 0;
return -1;
memcpy(p, headers, headerssize);
memcpy(p+headerssize, body, bodysize);
/*n = write(fd, p, headerssize+bodysize);*/
@ -55,9 +50,9 @@ httpWrite(int fd, const char * body, int bodysize,
PRINT_SOCKET_ERROR("send");
}
/* disable send on the socket */
/* draytek routers dont seems to like that... */
/* draytek routers don't seem to like that... */
#if 0
#ifdef WIN32
#ifdef _WIN32
if(shutdown(fd, SD_SEND)<0) {
#else
if(shutdown(fd, SHUT_WR)<0) { /*SD_SEND*/
@ -70,7 +65,7 @@ httpWrite(int fd, const char * body, int bodysize,
}
/* self explanatory */
int soapPostSubmit(int fd,
int soapPostSubmit(SOCKET fd,
const char * url,
const char * host,
unsigned short port,
@ -78,11 +73,10 @@ int soapPostSubmit(int fd,
const char * body,
const char * httpversion)
{
int bodysize;
char headerbuf[512];
int headerssize;
char portstr[8];
bodysize = (int)strlen(body);
int bodysize = (int)strlen(body);
/* We are not using keep-alive HTTP connections.
* HTTP/1.1 needs the header Connection: close to do that.
* This is the default with HTTP/1.0
@ -96,7 +90,7 @@ int soapPostSubmit(int fd,
headerssize = snprintf(headerbuf, sizeof(headerbuf),
"POST %s HTTP/%s\r\n"
"Host: %s%s\r\n"
"User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
"User-Agent: " OS_STRING ", " UPNP_VERSION_STRING ", MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
"Content-Length: %d\r\n"
"Content-Type: text/xml\r\n"
"SOAPAction: \"%s\"\r\n"
@ -105,6 +99,8 @@ int soapPostSubmit(int fd,
"Pragma: no-cache\r\n"
"\r\n",
url, httpversion, host, portstr, bodysize, action);
if ((unsigned int)headerssize >= sizeof(headerbuf))
return -1;
#ifdef DEBUG
/*printf("SOAP request : headersize=%d bodysize=%d\n",
headerssize, bodysize);

View file

@ -1,14 +1,16 @@
/* $Id: minisoap.h,v 1.4 2010/04/12 20:39:41 nanard Exp $ */
/* $Id: minisoap.h,v 1.6 2018/04/06 10:53:13 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005 Thomas Bernard
* Copyright (c) 2005-2018 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
#ifndef __MINISOAP_H__
#define __MINISOAP_H__
#ifndef MINISOAP_H_INCLUDED
#define MINISOAP_H_INCLUDED
#include "miniupnpc_socketdef.h"
/*int httpWrite(int, const char *, int, const char *);*/
int soapPostSubmit(int, const char *, const char *, unsigned short,
int soapPostSubmit(SOCKET, const char *, const char *, unsigned short,
const char *, const char *, const char *);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,58 @@
/* $Id: minissdpc.h,v 1.8 2019/02/10 12:29:23 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author: Thomas Bernard
* Copyright (c) 2005-2015 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef MINISSDPC_H_INCLUDED
#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)
#define MINISSDPC_INVALID_SERVER_REPLY (-104)
#ifdef __cplusplus
extern "C" {
#endif
#if !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__))
MINIUPNP_LIBSPEC struct UPNPDev *
getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath, int * error);
MINIUPNP_LIBSPEC int
connectToMiniSSDPD(const char * socketpath);
MINIUPNP_LIBSPEC int
disconnectFromMiniSSDPD(int s);
MINIUPNP_LIBSPEC int
requestDevicesFromMiniSSDPD(int s, const char * devtype);
MINIUPNP_LIBSPEC struct UPNPDev *
receiveDevicesFromMiniSSDPD(int s, int * error);
#endif /* !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)) */
MINIUPNP_LIBSPEC struct UPNPDev *
ssdpDiscoverDevices(const char * const deviceTypes[],
int delay, const char * multicastif,
int localport,
int ipv6, unsigned char ttl,
int * error,
int searchalltypes);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,698 @@
/* $Id: miniupnpc.c,v 1.159 2021/03/02 23:36:32 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* Project : miniupnp
* Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
* Author : Thomas BERNARD
* copyright (c) 2005-2021 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENSE file. */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef _WIN32
/* Win32 Specific includes and defines */
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
#include <iphlpapi.h>
#include "win32_snprintf.h"
#define strdup _strdup
#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 */
#define MAXHOSTNAMELEN 64
#else /* #ifdef _WIN32 */
/* Standard POSIX includes */
#include <unistd.h>
#if defined(__amigaos__) && !defined(__amigaos4__)
/* Amiga OS 3 specific stuff */
#define socklen_t int
#else
#include <sys/select.h>
#endif
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <net/if.h>
#if !defined(__amigaos__) && !defined(__amigaos4__)
#include <poll.h>
#endif
#include <strings.h>
#include <errno.h>
#define closesocket close
#endif /* #else _WIN32 */
#ifdef __GNU__
#define MAXHOSTNAMELEN 64
#endif
#include "miniupnpc.h"
#include "minissdpc.h"
#include "miniwget.h"
#include "miniwget_private.h"
#include "minisoap.h"
#include "minixml.h"
#include "upnpcommands.h"
#include "connecthostport.h"
#include "addr_is_reserved.h"
/* compare the beginning of a string with a constant string */
#define COMPARE(str, cstr) (0==strncmp(str, cstr, sizeof(cstr) - 1))
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
#define SOAPPREFIX "s"
#define SERVICEPREFIX "u"
#define SERVICEPREFIX2 'u'
/* root description parsing */
MINIUPNP_LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data)
{
struct xmlparser parser;
/* xmlparser object */
parser.xmlstart = buffer;
parser.xmlsize = bufsize;
parser.data = data;
parser.starteltfunc = IGDstartelt;
parser.endeltfunc = IGDendelt;
parser.datafunc = IGDdata;
parser.attfunc = 0;
parsexml(&parser);
#ifdef DEBUG
printIGD(data);
#endif
}
/* simpleUPnPcommand2 :
* not so simple !
* return values :
* pointer - OK
* NULL - error */
static char *
simpleUPnPcommand2(SOCKET s, const char * url, const char * service,
const char * action, struct UPNParg * args,
int * bufsize, const char * httpversion)
{
char hostname[MAXHOSTNAMELEN+1];
unsigned short port = 0;
char * path;
char soapact[128];
char soapbody[2048];
int soapbodylen;
char * buf;
int n;
int status_code;
*bufsize = 0;
snprintf(soapact, sizeof(soapact), "%s#%s", service, action);
if(args==NULL)
{
soapbodylen = snprintf(soapbody, sizeof(soapbody),
"<?xml version=\"1.0\"?>\r\n"
"<" SOAPPREFIX ":Envelope "
"xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" "
SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
"<" SOAPPREFIX ":Body>"
"<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">"
"</" SERVICEPREFIX ":%s>"
"</" SOAPPREFIX ":Body></" SOAPPREFIX ":Envelope>"
"\r\n", action, service, action);
if ((unsigned int)soapbodylen >= sizeof(soapbody))
return NULL;
}
else
{
char * p;
const char * pe, * pv;
const char * const pend = soapbody + sizeof(soapbody);
soapbodylen = snprintf(soapbody, sizeof(soapbody),
"<?xml version=\"1.0\"?>\r\n"
"<" SOAPPREFIX ":Envelope "
"xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" "
SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
"<" SOAPPREFIX ":Body>"
"<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">",
action, service);
if ((unsigned int)soapbodylen >= sizeof(soapbody))
return NULL;
p = soapbody + soapbodylen;
while(args->elt)
{
if(p >= pend) /* check for space to write next byte */
return NULL;
*(p++) = '<';
pe = args->elt;
while(p < pend && *pe)
*(p++) = *(pe++);
if(p >= pend) /* check for space to write next byte */
return NULL;
*(p++) = '>';
if((pv = args->val))
{
while(p < pend && *pv)
*(p++) = *(pv++);
}
if((p+2) > pend) /* check for space to write next 2 bytes */
return NULL;
*(p++) = '<';
*(p++) = '/';
pe = args->elt;
while(p < pend && *pe)
*(p++) = *(pe++);
if(p >= pend) /* check for space to write next byte */
return NULL;
*(p++) = '>';
args++;
}
if((p+4) > pend) /* check for space to write next 4 bytes */
return NULL;
*(p++) = '<';
*(p++) = '/';
*(p++) = SERVICEPREFIX2;
*(p++) = ':';
pe = action;
while(p < pend && *pe)
*(p++) = *(pe++);
strncpy(p, "></" SOAPPREFIX ":Body></" SOAPPREFIX ":Envelope>\r\n",
pend - p);
if(soapbody[sizeof(soapbody)-1]) /* strncpy pads buffer with 0s, so if it doesn't end in 0, could not fit full string */
return NULL;
}
if(!parseURL(url, hostname, &port, &path, NULL)) return NULL;
if(ISINVALID(s)) {
s = connecthostport(hostname, port, 0);
if(ISINVALID(s)) {
/* failed to connect */
return NULL;
}
}
n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, httpversion);
if(n<=0) {
#ifdef DEBUG
printf("Error sending SOAP request\n");
#endif
closesocket(s);
return NULL;
}
buf = getHTTPResponse(s, bufsize, &status_code);
#ifdef DEBUG
if(*bufsize > 0 && buf)
{
printf("HTTP %d SOAP Response :\n%.*s\n", status_code, *bufsize, buf);
}
else
{
printf("HTTP %d, empty SOAP response. size=%d\n", status_code, *bufsize);
}
#endif
closesocket(s);
return buf;
}
/* simpleUPnPcommand :
* not so simple !
* return values :
* pointer - OK
* NULL - error */
char *
simpleUPnPcommand(int s, const char * url, const char * service,
const char * action, struct UPNParg * args,
int * bufsize)
{
char * buf;
#if 1
buf = simpleUPnPcommand2((SOCKET)s, url, service, action, args, bufsize, "1.1");
#else
buf = simpleUPnPcommand2((SOCKET)s, url, service, action, args, bufsize, "1.0");
if (!buf || *bufsize == 0)
{
#if DEBUG
printf("Error or no result from SOAP request; retrying with HTTP/1.1\n");
#endif
buf = simpleUPnPcommand2((SOCKET)s, url, service, action, args, bufsize, "1.1");
}
#endif
return buf;
}
/* upnpDiscoverDevices() :
* 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. */
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)
{
struct UPNPDev * tmp;
struct UPNPDev * devlist = 0;
#if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__)
int deviceIndex;
#endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
if(error)
*error = UPNPDISCOVER_UNKNOWN_ERROR;
#if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__)
/* first try to get infos from minissdpd ! */
if(!minissdpdsock)
minissdpdsock = "/var/run/minissdpd.sock";
if(minissdpdsock[0] != '\0') {
for(deviceIndex = 0; deviceTypes[deviceIndex]; deviceIndex++) {
struct UPNPDev * minissdpd_devlist;
int only_rootdevice = 1;
minissdpd_devlist = getDevicesFromMiniSSDPD(deviceTypes[deviceIndex],
minissdpdsock, 0);
if(minissdpd_devlist) {
#ifdef DEBUG
printf("returned by MiniSSDPD: %s\t%s\n",
minissdpd_devlist->st, minissdpd_devlist->descURL);
#endif /* DEBUG */
if(!strstr(minissdpd_devlist->st, "rootdevice"))
only_rootdevice = 0;
for(tmp = minissdpd_devlist; tmp->pNext != NULL; tmp = tmp->pNext) {
#ifdef DEBUG
printf("returned by MiniSSDPD: %s\t%s\n",
tmp->pNext->st, tmp->pNext->descURL);
#endif /* DEBUG */
if(!strstr(tmp->st, "rootdevice"))
only_rootdevice = 0;
}
tmp->pNext = devlist;
devlist = minissdpd_devlist;
if(!searchalltypes && !only_rootdevice)
break;
}
}
}
for(tmp = devlist; tmp != NULL; tmp = tmp->pNext) {
/* We return what we have found if it was not only a rootdevice */
if(!strstr(tmp->st, "rootdevice")) {
if(error)
*error = UPNPDISCOVER_SUCCESS;
return devlist;
}
}
#else /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
(void)minissdpdsock; /* unused */
#endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
/* direct discovery if minissdpd responses are not sufficient */
{
struct UPNPDev * discovered_devlist;
discovered_devlist = ssdpDiscoverDevices(deviceTypes, delay, multicastif, localport,
ipv6, ttl, error, searchalltypes);
if(devlist == NULL)
devlist = discovered_devlist;
else {
for(tmp = devlist; tmp->pNext != NULL; tmp = tmp->pNext);
tmp->pNext = discovered_devlist;
}
}
return devlist;
}
/* upnpDiscover() Discover IGD device */
MINIUPNP_LIBSPEC struct UPNPDev *
upnpDiscover(int delay, const char * multicastif,
const char * minissdpdsock, int localport,
int ipv6, unsigned char ttl,
int * error)
{
static const char * const deviceList[] = {
#if 0
"urn:schemas-upnp-org:device:InternetGatewayDevice:2",
"urn:schemas-upnp-org:service:WANIPConnection:2",
#endif
"urn:schemas-upnp-org:device:InternetGatewayDevice:1",
"urn:schemas-upnp-org:service:WANIPConnection:1",
"urn:schemas-upnp-org:service:WANPPPConnection:1",
"upnp:rootdevice",
/*"ssdp:all",*/
0
};
return upnpDiscoverDevices(deviceList,
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 localport,
int ipv6, unsigned char ttl,
int * error)
{
static const char * const deviceList[] = {
/*"upnp:rootdevice",*/
"ssdp:all",
0
};
return upnpDiscoverDevices(deviceList,
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 localport,
int ipv6, unsigned char ttl,
int * error)
{
const char * const deviceList[] = {
device,
0
};
return upnpDiscoverDevices(deviceList,
delay, multicastif, minissdpdsock, localport,
ipv6, ttl, error, 0);
}
static char *
build_absolute_url(const char * baseurl, const char * descURL,
const char * url, unsigned int scope_id)
{
size_t l, n;
char * s;
const char * base;
char * p;
#if defined(IF_NAMESIZE) && !defined(_WIN32)
char ifname[IF_NAMESIZE];
#else /* defined(IF_NAMESIZE) && !defined(_WIN32) */
char scope_str[8];
#endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */
if( (url[0] == 'h')
&&(url[1] == 't')
&&(url[2] == 't')
&&(url[3] == 'p')
&&(url[4] == ':')
&&(url[5] == '/')
&&(url[6] == '/'))
return strdup(url);
base = (baseurl[0] == '\0') ? descURL : baseurl;
n = strlen(base);
if(n > 7) {
p = strchr(base + 7, '/');
if(p)
n = p - base;
}
l = n + strlen(url) + 1;
if(url[0] != '/')
l++;
if(scope_id != 0) {
#if defined(IF_NAMESIZE) && !defined(_WIN32)
if(if_indextoname(scope_id, ifname)) {
l += 3 + strlen(ifname); /* 3 == strlen(%25) */
}
#else /* defined(IF_NAMESIZE) && !defined(_WIN32) */
/* under windows, scope is numerical */
l += 3 + snprintf(scope_str, sizeof(scope_str), "%u", scope_id);
#endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */
}
s = malloc(l);
if(s == NULL) return NULL;
memcpy(s, base, n);
if(scope_id != 0) {
s[n] = '\0';
if(n > 13 && 0 == memcmp(s, "http://[fe80:", 13)) {
/* this is a linklocal IPv6 address */
p = strchr(s, ']');
if(p) {
/* insert %25<scope> into URL */
#if defined(IF_NAMESIZE) && !defined(_WIN32)
memmove(p + 3 + strlen(ifname), p, strlen(p) + 1);
memcpy(p, "%25", 3);
memcpy(p + 3, ifname, strlen(ifname));
n += 3 + strlen(ifname);
#else /* defined(IF_NAMESIZE) && !defined(_WIN32) */
memmove(p + 3 + strlen(scope_str), p, strlen(p) + 1);
memcpy(p, "%25", 3);
memcpy(p + 3, scope_str, strlen(scope_str));
n += 3 + strlen(scope_str);
#endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */
}
}
}
if(url[0] != '/')
s[n++] = '/';
memcpy(s + n, url, l - n);
return s;
}
/* Prepare the Urls for usage...
*/
MINIUPNP_LIBSPEC void
GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data,
const char * descURL, unsigned int scope_id)
{
/* strdup descURL */
urls->rootdescURL = strdup(descURL);
/* get description of WANIPConnection */
urls->ipcondescURL = build_absolute_url(data->urlbase, descURL,
data->first.scpdurl, scope_id);
urls->controlURL = build_absolute_url(data->urlbase, descURL,
data->first.controlurl, scope_id);
urls->controlURL_CIF = build_absolute_url(data->urlbase, descURL,
data->CIF.controlurl, scope_id);
urls->controlURL_6FC = build_absolute_url(data->urlbase, descURL,
data->IPv6FC.controlurl, scope_id);
#ifdef DEBUG
printf("urls->ipcondescURL='%s'\n", urls->ipcondescURL);
printf("urls->controlURL='%s'\n", urls->controlURL);
printf("urls->controlURL_CIF='%s'\n", urls->controlURL_CIF);
printf("urls->controlURL_6FC='%s'\n", urls->controlURL_6FC);
#endif
}
MINIUPNP_LIBSPEC void
FreeUPNPUrls(struct UPNPUrls * urls)
{
if(!urls)
return;
free(urls->controlURL);
urls->controlURL = 0;
free(urls->ipcondescURL);
urls->ipcondescURL = 0;
free(urls->controlURL_CIF);
urls->controlURL_CIF = 0;
free(urls->controlURL_6FC);
urls->controlURL_6FC = 0;
free(urls->rootdescURL);
urls->rootdescURL = 0;
}
int
UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data)
{
char status[64];
unsigned int uptime;
status[0] = '\0';
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;
}
/* UPNP_GetValidIGD() :
* return values :
* -1 = Internal error
* 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 positive non zero return case, the urls and data structures
* passed as parameters are set. Don't 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)
{
struct xml_desc {
char lanaddr[40];
char * xml;
int size;
int is_igd;
} * desc = NULL;
struct UPNPDev * dev;
int ndev = 0;
int i;
int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */
char extIpAddr[16];
int status_code = -1;
if(!devlist)
{
#ifdef DEBUG
printf("Empty devlist\n");
#endif
return 0;
}
/* counting total number of devices in the list */
for(dev = devlist; dev; dev = dev->pNext)
ndev++;
/* ndev is always > 0 */
desc = calloc(ndev, sizeof(struct xml_desc));
if(!desc)
return -1; /* memory allocation error */
/* Step 1 : downloading descriptions and testing type */
for(dev = devlist, i = 0; dev; dev = dev->pNext, i++)
{
/* we should choose an internet gateway device.
* with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */
desc[i].xml = miniwget_getaddr(dev->descURL, &(desc[i].size),
desc[i].lanaddr, sizeof(desc[i].lanaddr),
dev->scope_id, &status_code);
#ifdef DEBUG
if(!desc[i].xml)
{
printf("error getting XML description %s\n", dev->descURL);
}
#endif
if(desc[i].xml)
{
memset(data, 0, sizeof(struct IGDdatas));
memset(urls, 0, sizeof(struct UPNPUrls));
parserootdesc(desc[i].xml, desc[i].size, data);
if(COMPARE(data->CIF.servicetype,
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:"))
{
desc[i].is_igd = 1;
}
}
}
/* iterate the list to find a device depending on state */
for(state = 1; state <= 3; state++)
{
for(dev = devlist, i = 0; dev; dev = dev->pNext, i++)
{
if(desc[i].xml)
{
memset(data, 0, sizeof(struct IGDdatas));
memset(urls, 0, sizeof(struct UPNPUrls));
parserootdesc(desc[i].xml, desc[i].size, data);
if(desc[i].is_igd || state >= 3 )
{
int is_connected;
GetUPNPUrls(urls, data, dev->descURL, dev->scope_id);
/* in state 2 and 3 we don't test if device is connected ! */
if(state >= 2)
goto free_and_return;
is_connected = UPNPIGD_IsConnected(urls, data);
#ifdef DEBUG
printf("UPNPIGD_IsConnected(%s) = %d\n",
urls->controlURL, is_connected);
#endif
/* checks that status is connected AND there is a external IP address assigned */
if(is_connected &&
(UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) {
if(!addr_is_reserved(extIpAddr))
goto free_and_return;
}
FreeUPNPUrls(urls);
if(data->second.servicetype[0] != '\0') {
#ifdef DEBUG
printf("We tried %s, now we try %s !\n",
data->first.servicetype, data->second.servicetype);
#endif
/* swaping WANPPPConnection and WANIPConnection ! */
memcpy(&data->tmp, &data->first, sizeof(struct IGDdatas_service));
memcpy(&data->first, &data->second, sizeof(struct IGDdatas_service));
memcpy(&data->second, &data->tmp, sizeof(struct IGDdatas_service));
GetUPNPUrls(urls, data, dev->descURL, dev->scope_id);
is_connected = UPNPIGD_IsConnected(urls, data);
#ifdef DEBUG
printf("UPNPIGD_IsConnected(%s) = %d\n",
urls->controlURL, is_connected);
#endif
if(is_connected &&
(UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) {
if(!addr_is_reserved(extIpAddr))
goto free_and_return;
}
FreeUPNPUrls(urls);
}
}
memset(data, 0, sizeof(struct IGDdatas));
}
}
}
state = 0;
free_and_return:
if (lanaddr != NULL && state >= 1 && state <= 3 && i < ndev)
strncpy(lanaddr, desc[i].lanaddr, lanaddrlen);
for(i = 0; i < ndev; i++)
free(desc[i].xml);
free(desc);
return state;
}
/* UPNP_GetIGDFromUrl()
* Used when skipping the discovery process.
* return value :
* 0 - Not ok
* 1 - OK */
int
UPNP_GetIGDFromUrl(const char * rootdescurl,
struct UPNPUrls * urls,
struct IGDdatas * data,
char * lanaddr, int lanaddrlen)
{
char * descXML;
int descXMLsize = 0;
descXML = miniwget_getaddr(rootdescurl, &descXMLsize,
lanaddr, lanaddrlen, 0, NULL);
if(descXML) {
memset(data, 0, sizeof(struct IGDdatas));
memset(urls, 0, sizeof(struct UPNPUrls));
parserootdesc(descXML, descXMLsize, data);
free(descXML);
GetUPNPUrls(urls, data, rootdescurl, 0);
return 1;
} else {
return 0;
}
}

View file

@ -0,0 +1,44 @@
/* $Id: miniupnpc_socketdef.h,v 1.4 2021/03/02 23:35:29 nanard Exp $ */
/* Miniupnp project : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
* Author : Thomas Bernard
* Copyright (c) 2018 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided within this distribution */
#ifndef MINIUPNPC_SOCKETDEF_H_INCLUDED
#define MINIUPNPC_SOCKETDEF_H_INCLUDED
#ifdef _WIN32
#define ISINVALID(s) (INVALID_SOCKET==(s))
#else
#ifndef SOCKET
#define SOCKET int
#endif
#ifndef SSIZE_T
#define SSIZE_T ssize_t
#endif
#ifndef INVALID_SOCKET
#define INVALID_SOCKET (-1)
#endif
#ifndef ISINVALID
#define ISINVALID(s) ((s)<0)
#endif
#endif
#ifdef _MSC_VER
#define MSC_CAST_INT (int)
#else
#define MSC_CAST_INT
#endif
/* definition of PRINT_SOCKET_ERROR */
#ifdef _WIN32
#define PRINT_SOCKET_ERROR(x) fprintf(stderr, "Socket error: %s, %d\n", x, WSAGetLastError());
#else
#define PRINT_SOCKET_ERROR(x) perror(x)
#endif
#endif /* MINIUPNPC_SOCKETDEF_H_INCLUDED */

View file

@ -1,17 +1,22 @@
/* $Id: miniupnpcmodule.c,v 1.18 2011/04/10 11:21:23 nanard Exp $*/
/* Project : miniupnp
/* $Id: miniupnpcmodule.c,v 1.38 2021/11/09 18:46:49 nanard Exp $*/
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* Project : miniupnp
* Author : Thomas BERNARD
* website : http://miniupnp.tuxfamily.org/
* copyright (c) 2007-2009 Thomas Bernard
* website : https://miniupnp.tuxfamily.org/
* copyright (c) 2007-2021 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENCE file. */
#include <Python.h>
#define STATICLIB
#include "structmember.h"
#define MINIUPNP_STATICLIB
#include <structmember.h>
#include "miniupnpc.h"
#include "upnpcommands.h"
#include "upnperrors.h"
#ifdef _WIN32
#include <winsock2.h>
#endif
/* for compatibility with Python < 2.4 */
#ifndef Py_RETURN_NONE
#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
@ -25,6 +30,16 @@
#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
#endif
/* for compatibility with Python < 3.0 */
#ifndef PyVarObject_HEAD_INIT
#define PyVarObject_HEAD_INIT(type, size) \
PyObject_HEAD_INIT(type) size,
#endif
#ifndef Py_TYPE
#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
#endif
typedef struct {
PyObject_HEAD
/* Type-specific fields go here. */
@ -32,6 +47,7 @@ typedef struct {
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;
@ -44,57 +60,115 @@ static PyMemberDef UPnP_members[] = {
{"discoverdelay", T_UINT, offsetof(UPnPObject, discoverdelay),
0/*READWRITE*/, "value in ms used to wait for SSDP responses"
},
/* T_STRING is allways readonly :( */
{"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 always readonly :( */
{"multicastif", T_STRING, offsetof(UPnPObject, multicastif),
0, "IP of the network interface to be used for multicast operations"
},
{"minissdpdsocket", T_STRING, offsetof(UPnPObject, multicastif),
{"minissdpdsocket", T_STRING, offsetof(UPnPObject, minissdpdsocket),
0, "path of the MiniSSDPd unix socket"
},
{NULL}
};
static int UPnP_init(UPnPObject *self, PyObject *args, PyObject *kwds)
{
char* multicastif = NULL;
char* minissdpdsocket = NULL;
static char *kwlist[] = {
"multicastif", "minissdpdsocket", "discoverdelay",
"localport", NULL
};
if(!PyArg_ParseTupleAndKeywords(args, kwds, "|zzII", kwlist,
&multicastif,
&minissdpdsocket,
&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)
self->minissdpdsocket = strdup(minissdpdsocket);
return 0;
}
static void
UPnPObject_dealloc(UPnPObject *self)
{
freeUPNPDevlist(self->devlist);
FreeUPNPUrls(&self->urls);
self->ob_type->tp_free((PyObject*)self);
free(self->multicastif);
free(self->minissdpdsocket);
Py_TYPE(self)->tp_free((PyObject*)self);
}
static PyObject *
UPnP_discover(UPnPObject *self)
{
struct UPNPDev * dev;
int i;
int error = 0;
PyObject *res = NULL;
if(self->devlist)
{
freeUPNPDevlist(self->devlist);
self->devlist = 0;
}
}
Py_BEGIN_ALLOW_THREADS
self->devlist = upnpDiscover((int)self->discoverdelay/*timeout in ms*/,
0/* multicast if*/,
0/*minissdpd socket*/,
0/*sameport flag*/,
self->multicastif,
self->minissdpdsocket,
(int)self->localport,
0/*ip v6*/,
0/*error */);
2/* TTL */,
&error);
Py_END_ALLOW_THREADS
/* Py_RETURN_NONE ??? */
for(dev = self->devlist, i = 0; dev; dev = dev->pNext)
i++;
res = Py_BuildValue("i", i);
return res;
if (self->devlist != NULL) {
struct UPNPDev * dev;
int i = 0;
for(dev = self->devlist; dev; dev = dev->pNext)
i++;
res = Py_BuildValue("i", i);
return res;
} else {
PyErr_SetString(PyExc_Exception, strupnperror(error));
return NULL;
}
}
static PyObject *
UPnP_selectigd(UPnPObject *self)
UPnP_selectigd(UPnPObject *self, PyObject *args)
{
const char * rootDescUrl = NULL;
int r;
if(!PyArg_ParseTuple(args, "|z", &rootDescUrl))
return NULL;
Py_BEGIN_ALLOW_THREADS
r = UPNP_GetValidIGD(self->devlist, &self->urls, &self->data,
self->lanaddr, sizeof(self->lanaddr));
if (rootDescUrl == NULL) {
r = UPNP_GetValidIGD(self->devlist, &self->urls, &self->data,
self->lanaddr, sizeof(self->lanaddr));
} else {
r = UPNP_GetIGDFromUrl(rootDescUrl, &self->urls, &self->data,
self->lanaddr, sizeof(self->lanaddr));
}
Py_END_ALLOW_THREADS
if(r)
{
@ -116,7 +190,11 @@ Py_BEGIN_ALLOW_THREADS
i = UPNP_GetTotalBytesSent(self->urls.controlURL_CIF,
self->data.CIF.servicetype);
Py_END_ALLOW_THREADS
#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
return Py_BuildValue("I", i);
#else
return Py_BuildValue("i", (int)i);
#endif
}
static PyObject *
@ -127,7 +205,11 @@ Py_BEGIN_ALLOW_THREADS
i = UPNP_GetTotalBytesReceived(self->urls.controlURL_CIF,
self->data.CIF.servicetype);
Py_END_ALLOW_THREADS
#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
return Py_BuildValue("I", i);
#else
return Py_BuildValue("i", (int)i);
#endif
}
static PyObject *
@ -138,7 +220,11 @@ Py_BEGIN_ALLOW_THREADS
i = UPNP_GetTotalPacketsSent(self->urls.controlURL_CIF,
self->data.CIF.servicetype);
Py_END_ALLOW_THREADS
#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
return Py_BuildValue("I", i);
#else
return Py_BuildValue("i", (int)i);
#endif
}
static PyObject *
@ -149,7 +235,11 @@ Py_BEGIN_ALLOW_THREADS
i = UPNP_GetTotalPacketsReceived(self->urls.controlURL_CIF,
self->data.CIF.servicetype);
Py_END_ALLOW_THREADS
#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
return Py_BuildValue("I", i);
#else
return Py_BuildValue("i", (int)i);
#endif
}
static PyObject *
@ -166,7 +256,11 @@ Py_BEGIN_ALLOW_THREADS
status, &uptime, lastconnerror);
Py_END_ALLOW_THREADS
if(r==UPNPCOMMAND_SUCCESS) {
#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
return Py_BuildValue("(s,I,s)", status, uptime, lastconnerror);
#else
return Py_BuildValue("(s,i,s)", status, (int)uptime, lastconnerror);
#endif
} else {
/* TODO: have our own exception type ! */
PyErr_SetString(PyExc_Exception, strupnperror(r));
@ -215,7 +309,7 @@ Py_END_ALLOW_THREADS
}
/* AddPortMapping(externalPort, protocol, internalHost, internalPort, desc,
* remoteHost)
* remoteHost, leaseDuration)
* protocol is 'UDP' or 'TCP' */
static PyObject *
UPnP_addportmapping(UPnPObject *self, PyObject *args)
@ -228,17 +322,24 @@ UPnP_addportmapping(UPnPObject *self, PyObject *args)
const char * host;
const char * desc;
const char * remoteHost;
const char * leaseDuration = "0";
unsigned int intLeaseDuration = 0;
char strLeaseDuration[12];
int r;
if (!PyArg_ParseTuple(args, "HssHss", &ePort, &proto,
&host, &iPort, &desc, &remoteHost))
#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
if (!PyArg_ParseTuple(args, "HssHzz|I", &ePort, &proto,
&host, &iPort, &desc, &remoteHost, &intLeaseDuration))
#else
if (!PyArg_ParseTuple(args, "HssHzz|i", &ePort, &proto,
&host, &iPort, &desc, &remoteHost, (int *)&intLeaseDuration))
#endif
return NULL;
Py_BEGIN_ALLOW_THREADS
sprintf(extPort, "%hu", ePort);
sprintf(inPort, "%hu", iPort);
sprintf(strLeaseDuration, "%u", intLeaseDuration);
r = UPNP_AddPortMapping(self->urls.controlURL, self->data.first.servicetype,
extPort, inPort, host, desc, proto,
remoteHost, leaseDuration);
remoteHost, strLeaseDuration);
Py_END_ALLOW_THREADS
if(r==UPNPCOMMAND_SUCCESS)
{
@ -255,6 +356,42 @@ Py_END_ALLOW_THREADS
}
}
/* AddAnyPortMapping(externalPort, protocol, internalHost, internalPort, desc,
* remoteHost)
* protocol is 'UDP' or 'TCP' */
static PyObject *
UPnP_addanyportmapping(UPnPObject *self, PyObject *args)
{
char extPort[6];
unsigned short ePort;
char inPort[6];
unsigned short iPort;
char reservedPort[6];
const char * proto;
const char * host;
const char * desc;
const char * remoteHost;
const char * leaseDuration = "0";
int r;
if (!PyArg_ParseTuple(args, "HssHzz", &ePort, &proto, &host, &iPort, &desc, &remoteHost))
return NULL;
Py_BEGIN_ALLOW_THREADS
sprintf(extPort, "%hu", ePort);
sprintf(inPort, "%hu", iPort);
r = UPNP_AddAnyPortMapping(self->urls.controlURL, self->data.first.servicetype,
extPort, inPort, host, desc, proto,
remoteHost, leaseDuration, reservedPort);
Py_END_ALLOW_THREADS
if(r==UPNPCOMMAND_SUCCESS) {
return Py_BuildValue("i", atoi(reservedPort));
} else {
/* TODO: have our own exception type ! */
PyErr_SetString(PyExc_Exception, strupnperror(r));
return NULL;
}
}
/* DeletePortMapping(extPort, proto, removeHost='')
* proto = 'UDP', 'TCP' */
static PyObject *
@ -281,6 +418,37 @@ Py_END_ALLOW_THREADS
}
}
/* DeletePortMappingRange(extPort, proto, removeHost='')
* proto = 'UDP', 'TCP' */
static PyObject *
UPnP_deleteportmappingrange(UPnPObject *self, PyObject *args)
{
char extPortStart[6];
unsigned short ePortStart;
char extPortEnd[6];
unsigned short ePortEnd;
const char * proto;
unsigned char manage;
char manageStr[6];
int r;
if(!PyArg_ParseTuple(args, "HHsb", &ePortStart, &ePortEnd, &proto, &manage))
return NULL;
Py_BEGIN_ALLOW_THREADS
sprintf(extPortStart, "%hu", ePortStart);
sprintf(extPortEnd, "%hu", ePortEnd);
sprintf(manageStr, "%hu", (unsigned short)manage);
r = UPNP_DeletePortMappingRange(self->urls.controlURL, self->data.first.servicetype,
extPortStart, extPortEnd, proto, manageStr);
Py_END_ALLOW_THREADS
if(r==UPNPCOMMAND_SUCCESS) {
Py_RETURN_TRUE;
} else {
/* TODO: have our own exception type ! */
PyErr_SetString(PyExc_Exception, strupnperror(r));
return NULL;
}
}
static PyObject *
UPnP_getportmappingnumberofentries(UPnPObject *self)
{
@ -292,7 +460,11 @@ Py_BEGIN_ALLOW_THREADS
&n);
Py_END_ALLOW_THREADS
if(r==UPNPCOMMAND_SUCCESS) {
#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
return Py_BuildValue("I", n);
#else
return Py_BuildValue("i", (int)n);
#endif
} else {
/* TODO: have our own exception type ! */
PyErr_SetString(PyExc_Exception, strupnperror(r));
@ -300,7 +472,7 @@ Py_END_ALLOW_THREADS
}
}
/* GetSpecificPortMapping(ePort, proto)
/* GetSpecificPortMapping(ePort, proto, remoteHost='')
* proto = 'UDP' or 'TCP' */
static PyObject *
UPnP_getspecificportmapping(UPnPObject *self, PyObject *args)
@ -308,13 +480,14 @@ UPnP_getspecificportmapping(UPnPObject *self, PyObject *args)
char extPort[6];
unsigned short ePort;
const char * proto;
const char * remoteHost = "";
char intClient[40];
char intPort[6];
unsigned short iPort;
char desc[80];
char enabled[4];
char leaseDuration[16];
if(!PyArg_ParseTuple(args, "Hs", &ePort, &proto))
if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost))
return NULL;
extPort[0] = '\0'; intClient[0] = '\0'; intPort[0] = '\0';
desc[0] = '\0'; enabled[0] = '\0'; leaseDuration[0] = '\0';
@ -322,7 +495,7 @@ Py_BEGIN_ALLOW_THREADS
sprintf(extPort, "%hu", ePort);
UPNP_GetSpecificPortMappingEntry(self->urls.controlURL,
self->data.first.servicetype,
extPort, proto,
extPort, proto, remoteHost,
intClient, intPort,
desc, enabled, leaseDuration);
Py_END_ALLOW_THREADS
@ -376,9 +549,15 @@ Py_END_ALLOW_THREADS
ePort = (unsigned short)atoi(extPort);
iPort = (unsigned short)atoi(intPort);
dur = (unsigned int)strtoul(duration, 0, 0);
#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
return Py_BuildValue("(H,s,(s,H),s,s,s,I)",
ePort, protocol, intClient, iPort,
desc, enabled, rHost, dur);
#else
return Py_BuildValue("(i,s,(s,i),s,s,s,i)",
(int)ePort, protocol, intClient, (int)iPort,
desc, enabled, rHost, (int)dur);
#endif
}
else
{
@ -391,7 +570,7 @@ static PyMethodDef UPnP_methods[] = {
{"discover", (PyCFunction)UPnP_discover, METH_NOARGS,
"discover UPnP IGD devices on the network"
},
{"selectigd", (PyCFunction)UPnP_selectigd, METH_NOARGS,
{"selectigd", (PyCFunction)UPnP_selectigd, METH_VARARGS,
"select a valid UPnP IGD among discovered devices"
},
{"totalbytesent", (PyCFunction)UPnP_totalbytesent, METH_NOARGS,
@ -418,9 +597,15 @@ static PyMethodDef UPnP_methods[] = {
{"addportmapping", (PyCFunction)UPnP_addportmapping, METH_VARARGS,
"add a port mapping"
},
{"addanyportmapping", (PyCFunction)UPnP_addanyportmapping, METH_VARARGS,
"add a port mapping, IGD to select alternative if necessary"
},
{"deleteportmapping", (PyCFunction)UPnP_deleteportmapping, METH_VARARGS,
"delete a port mapping"
},
{"deleteportmappingrange", (PyCFunction)UPnP_deleteportmappingrange, METH_VARARGS,
"delete a range of port mappings"
},
{"getportmappingnumberofentries", (PyCFunction)UPnP_getportmappingnumberofentries, METH_NOARGS,
"-- non standard --"
},
@ -434,8 +619,8 @@ static PyMethodDef UPnP_methods[] = {
};
static PyTypeObject UPnPType = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
PyVarObject_HEAD_INIT(NULL,
0) /*ob_size*/
"miniupnpc.UPnP", /*tp_name*/
sizeof(UPnPObject), /*tp_basicsize*/
0, /*tp_itemsize*/
@ -470,13 +655,14 @@ static PyTypeObject UPnPType = {
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0,/*(initproc)UPnP_init,*/ /* tp_init */
(initproc)UPnP_init, /* tp_init */
0, /* tp_alloc */
#ifndef WIN32
#ifndef _WIN32
PyType_GenericNew,/*UPnP_new,*/ /* tp_new */
#else
0,
0, /* tp_new */
#endif
0, /* tp_free */
};
/* module methods */
@ -484,24 +670,69 @@ static PyMethodDef miniupnpc_methods[] = {
{NULL} /* Sentinel */
};
#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"miniupnpc", /* m_name */
"miniupnpc module.", /* m_doc */
-1, /* m_size */
miniupnpc_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
};
#endif
#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC
initminiupnpc(void)
#if PY_MAJOR_VERSION >= 3
PyInit_miniupnpc(void)
#else
initminiupnpc(void)
#endif
{
PyObject* m;
#ifdef WIN32
#ifdef _WIN32
/* initialize Winsock. */
WSADATA wsaData;
int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (nResult != 0)
{
/* error code could be WSASYSNOTREADY WSASYSNOTREADY
* WSASYSNOTREADY WSASYSNOTREADY WSASYSNOTREADY */
#if PY_MAJOR_VERSION >= 3
return 0;
#else
return;
#endif
}
UPnPType.tp_new = PyType_GenericNew;
#endif
if (PyType_Ready(&UPnPType) < 0)
#if PY_MAJOR_VERSION >= 3
return 0;
#else
return;
#endif
#if PY_MAJOR_VERSION >= 3
m = PyModule_Create(&moduledef);
#else
m = Py_InitModule3("miniupnpc", miniupnpc_methods,
"miniupnpc module.");
#endif
Py_INCREF(&UPnPType);
PyModule_AddObject(m, "UPnP", (PyObject *)&UPnPType);
#if PY_MAJOR_VERSION >= 3
return m;
#endif
}

View file

@ -1,21 +1,21 @@
/* $Id: miniwget.c,v 1.52 2011/06/17 22:59:42 nanard Exp $ */
/* $Id: miniwget.c,v 1.84 2020/11/09 19:41:18 nanard Exp $ */
/* Project : miniupnp
* Website : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
* Author : Thomas Bernard
* Copyright (c) 2005-2011 Thomas Bernard
* Copyright (c) 2005-2020 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifdef WIN32
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
#define MAXHOSTNAMELEN 64
#define MIN(x,y) (((x)<(y))?(x):(y))
#define snprintf _snprintf
#include "win32_snprintf.h"
#define socklen_t int
#ifndef strncasecmp
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
@ -24,7 +24,7 @@
#define strncasecmp memicmp
#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
#endif /* #ifndef strncasecmp */
#else /* #ifdef WIN32 */
#else /* #ifdef _WIN32 */
#include <unistd.h>
#include <sys/param.h>
#if defined(__amigaos__) && !defined(__amigaos4__)
@ -33,22 +33,31 @@
#include <sys/select.h>
#endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netdb.h>
#define closesocket close
/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions
* during the connect() call */
#define MINIUPNPC_IGNORE_EINTR
#endif /* #else WIN32 */
#if defined(__sun) || defined(sun)
#include <strings.h>
#endif /* #else _WIN32 */
#ifdef __GNU__
#define MAXHOSTNAMELEN 64
#endif /* __GNU__ */
#ifndef MIN
#define MIN(x,y) (((x)<(y))?(x):(y))
#endif
#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.
@ -56,7 +65,7 @@
* to the length parameter.
*/
void *
getHTTPResponse(int s, int * size)
getHTTPResponse(SOCKET s, int * size, int * status_code)
{
char buf[2048];
int n;
@ -67,20 +76,42 @@ getHTTPResponse(int s, int * size)
unsigned int bytestocopy = 0;
/* buffers : */
char * header_buf;
int header_buf_len = 2048;
int header_buf_used = 0;
unsigned int header_buf_len = 2048;
unsigned int header_buf_used = 0;
char * content_buf;
int content_buf_len = 2048;
int content_buf_used = 0;
unsigned int content_buf_len = 2048;
unsigned int content_buf_used = 0;
char chunksize_buf[32];
int chunksize_buf_index;
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, 2048, 5000)) > 0)
while((n = receivedata(s, buf, sizeof(buf), 5000, NULL)) > 0)
{
if(endofheaders == 0)
{
@ -89,7 +120,15 @@ getHTTPResponse(int s, int * size)
int colon=0;
int valuestart=0;
if(header_buf_used + n > header_buf_len) {
header_buf = realloc(header_buf, header_buf_used + n);
char * tmp = realloc(header_buf, header_buf_used + n);
if(tmp == NULL) {
/* memory allocation error */
free(header_buf);
free(content_buf);
*size = -1;
return NULL;
}
header_buf = tmp;
header_buf_len = header_buf_used + n;
}
memcpy(header_buf + header_buf_used, buf, n);
@ -97,14 +136,14 @@ getHTTPResponse(int s, int * size)
/* search for CR LF CR LF (end of headers)
* recognize also LF LF */
i = 0;
while(i < (header_buf_used-1) && (endofheaders == 0)) {
while(i < ((int)header_buf_used-1) && (endofheaders == 0)) {
if(header_buf[i] == '\r') {
i++;
if(header_buf[i] == '\n') {
i++;
if(i < header_buf_used && header_buf[i] == '\r') {
if(i < (int)header_buf_used && header_buf[i] == '\r') {
i++;
if(i < header_buf_used && header_buf[i] == '\n') {
if(i < (int)header_buf_used && header_buf[i] == '\n') {
endofheaders = i+1;
}
}
@ -121,7 +160,7 @@ getHTTPResponse(int s, int * size)
continue;
/* parse header lines */
for(i = 0; i < endofheaders - 1; i++) {
if(colon <= linestart && header_buf[i]==':')
if(linestart > 0 && colon <= linestart && header_buf[i]==':')
{
colon = i;
while(i < (endofheaders-1)
@ -132,7 +171,34 @@ getHTTPResponse(int s, int * size)
/* detecting end of line */
else if(header_buf[i]=='\r' || header_buf[i]=='\n')
{
if(colon > linestart && valuestart > colon)
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",
@ -155,113 +221,130 @@ getHTTPResponse(int s, int * size)
chunked = 1;
}
}
while(header_buf[i]=='\r' || header_buf[i] == '\n')
while((i < (int)header_buf_used) && (header_buf[i]=='\r' || header_buf[i] == '\n'))
i++;
linestart = i;
colon = linestart;
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(endofheaders)
/* if we get there, endofheaders != 0.
* In the other case, there was a continue above */
/* content */
if(chunked)
{
/* content */
if(chunked)
int i = 0;
while(i < n)
{
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<n && buf[i] == '\n') i++;
}
while(i<n && isxdigit(buf[i])
&& chunksize_buf_index < (sizeof(chunksize_buf)-1))
{
chunksize_buf[chunksize_buf_index++] = buf[i];
chunksize_buf[chunksize_buf_index] = '\0';
i++;
}
while(i<n && buf[i] != '\r' && buf[i] != '\n')
i++; /* discarding chunk-extension */
if(i<n && buf[i] == '\r') i++;
if(i<n && buf[i] == '\n') {
unsigned int j;
for(j = 0; j < chunksize_buf_index; j++) {
if(chunksize_buf[j] >= '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)
{
/* reading chunk size */
if(chunksize_buf_index == 0) {
/* skipping any leading CR LF */
if(i<n && buf[i] == '\r') i++;
if(i<n && buf[i] == '\n') i++;
}
while(i<n && isxdigit(buf[i])
&& chunksize_buf_index < (sizeof(chunksize_buf)-1))
{
chunksize_buf[chunksize_buf_index++] = buf[i];
chunksize_buf[chunksize_buf_index] = '\0';
i++;
}
while(i<n && buf[i] != '\r' && buf[i] != '\n')
i++; /* discarding chunk-extension */
if(i<n && buf[i] == '\r') i++;
if(i<n && buf[i] == '\n') {
int j;
for(j = 0; j < chunksize_buf_index; j++) {
if(chunksize_buf[j] >= '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);
printf("end of HTTP content - %d %d\n", i, n);
/*printf("'%.*s'\n", n-i, buf+i);*/
#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;
}
goto end_of_stream;
}
bytestocopy = ((int)chunksize < n - i)?chunksize:(n - i);
if((int)(content_buf_used + bytestocopy) > content_buf_len)
{
if(content_length >= content_buf_used + (int)bytestocopy) {
content_buf_len = content_length;
} else {
content_buf_len = content_buf_used + (int)bytestocopy;
}
content_buf = (char *)realloc((void *)content_buf,
content_buf_len);
}
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) > content_length) {
/* skipping additional bytes */
n = content_length - content_buf_used;
}
if(content_buf_used + n > content_buf_len)
/* 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)
{
if(content_length >= content_buf_used + n) {
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 + n;
content_buf_len = content_buf_used + bytestocopy;
}
content_buf = (char *)realloc((void *)content_buf,
content_buf_len);
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;
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 >= content_length)
if(content_length > 0 && content_buf_used >= (unsigned int)content_length)
{
#ifdef DEBUG
printf("End of HTTP content\n");
@ -270,7 +353,7 @@ getHTTPResponse(int s, int * size)
}
}
end_of_stream:
free(header_buf); header_buf = NULL;
free(header_buf);
*size = content_buf_used;
if(content_buf_used == 0)
{
@ -284,21 +367,22 @@ end_of_stream:
* do all the work.
* Return NULL if something failed. */
static void *
miniwget3(const char * url, const char * host,
miniwget3(const char * host,
unsigned short port, const char * path,
int * size, char * addr_str, int addr_str_len,
const char * httpversion)
const char * httpversion, unsigned int scope_id,
int * status_code)
{
char buf[2048];
int s;
int n = -1;
SOCKET s;
int n;
int len;
int sent;
void * content;
*size = 0;
s = connecthostport(host, port);
if(s < 0)
s = connecthostport(host, port, scope_id);
if(ISINVALID(s))
return NULL;
/* get address for caller ! */
@ -336,16 +420,14 @@ miniwget3(const char * url, const char * host,
addr_str, addr_str_len);
}
#endif
#ifndef NO_GETADDRINFO
/* 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);
#endif
if(n != 0) {
#ifdef WIN32
#ifdef _WIN32
fprintf(stderr, "getnameinfo() failed : %d\n", n);
#else
fprintf(stderr, "getnameinfo() failed : %s\n", gai_strerror(n));
@ -362,10 +444,15 @@ miniwget3(const char * url, const char * host,
"GET %s HTTP/%s\r\n"
"Host: %s:%d\r\n"
"Connection: Close\r\n"
"User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
"User-Agent: " OS_STRING ", " UPNP_VERSION_STRING ", MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
"\r\n",
path, httpversion, host, port);
if ((unsigned int)len >= sizeof(buf))
{
closesocket(s);
return NULL;
}
sent = 0;
/* sending the HTTP request */
while(sent < len)
@ -382,7 +469,7 @@ miniwget3(const char * url, const char * host,
sent += n;
}
}
content = getHTTPResponse(s, size);
content = getHTTPResponse(s, size, status_code);
closesocket(s);
return content;
}
@ -390,24 +477,32 @@ miniwget3(const char * url, const char * host,
/* miniwget2() :
* Call miniwget3(); retry with HTTP/1.1 if 1.0 fails. */
static void *
miniwget2(const char * url, const char * host,
unsigned short port, const char * path,
int * size, char * addr_str, int addr_str_len)
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;
respbuffer = miniwget3(url, host, port, path, size, addr_str, addr_str_len, "1.1");
/*
respbuffer = miniwget3(url, host, port, path, size, addr_str, addr_str_len, "1.0");
#if 1
respbuffer = miniwget3(host, port, path, size,
addr_str, addr_str_len, "1.1",
scope_id, 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(url, host, port, path, size, addr_str, addr_str_len, "1.1");
respbuffer = miniwget3(host, port, path, size,
addr_str, addr_str_len, "1.1",
scope_id, status_code);
}
*/
#endif
return respbuffer;
}
@ -419,12 +514,15 @@ miniwget2(const char * url, const char * host,
* 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
* 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)
int
parseURL(const char * url,
char * hostname, unsigned short * port,
char * * path, unsigned int * scope_id)
{
char * p1, *p2, *p3;
if(!url)
@ -440,7 +538,43 @@ int parseURL(const char * url, char * hostname, unsigned short * port, char * *
if(*p1 == '[')
{
/* IP v6 : http://[2a00:1450:8002::6a]/path/abc */
char * scope;
scope = strchr(p1, '%');
p2 = strchr(p1, ']');
if(p2 && scope && scope < p2 && scope_id) {
/* parse scope */
#ifdef IF_NAMESIZE
char tmp[IF_NAMESIZE];
int l;
scope++;
/* "%25" is just '%' in URL encoding */
if(scope[0] == '2' && scope[1] == '5')
scope += 2; /* skip "25" */
l = p2 - scope;
if(l >= IF_NAMESIZE)
l = IF_NAMESIZE - 1;
memcpy(tmp, scope, l);
tmp[l] = '\0';
*scope_id = if_nametoindex(tmp);
if(*scope_id == 0) {
*scope_id = (unsigned int)strtoul(tmp, NULL, 10);
}
#else
/* under windows, scope is numerical */
char tmp[8];
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)
{
@ -490,35 +624,41 @@ int parseURL(const char * url, char * hostname, unsigned short * port, char * *
return 1;
}
void * miniwget(const char * url, int * size)
void *
miniwget(const char * url, int * size,
unsigned int scope_id, int * status_code)
{
unsigned short port;
char * path;
/* protocol://host:port/chemin */
char hostname[MAXHOSTNAMELEN+1];
*size = 0;
if(!parseURL(url, hostname, &port, &path))
if(!parseURL(url, hostname, &port, &path, &scope_id))
return NULL;
#ifdef DEBUG
printf("parsed url : hostname='%s' port=%hu path='%s'\n", hostname, port, path);
printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
hostname, port, path, scope_id);
#endif
return miniwget2(url, hostname, port, path, size, 0, 0);
return miniwget2(hostname, port, path, size, 0, 0, scope_id, status_code);
}
void * miniwget_getaddr(const char * url, int * size, char * addr, int addrlen)
void *
miniwget_getaddr(const char * url, int * size,
char * addr, int addrlen, unsigned int scope_id,
int * status_code)
{
unsigned short port;
char * path;
/* protocol://host:port/chemin */
/* protocol://host:port/path */
char hostname[MAXHOSTNAMELEN+1];
*size = 0;
if(addr)
addr[0] = '\0';
if(!parseURL(url, hostname, &port, &path))
if(!parseURL(url, hostname, &port, &path, &scope_id))
return NULL;
#ifdef DEBUG
printf("parsed url : hostname='%s' port=%hu path='%s'\n", hostname, port, path);
printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
hostname, port, path, scope_id);
#endif
return miniwget2(url, hostname, port, path, size, addr, addrlen);
return miniwget2(hostname, port, path, size, addr, addrlen, scope_id, status_code);
}

View file

@ -0,0 +1,15 @@
/* $Id: miniwget_private.h,v 1.1 2018/04/06 10:17:58 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2018 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
#ifndef MINIWGET_INTERNAL_H_INCLUDED
#define MINIWGET_INTERNAL_H_INCLUDED
#include "miniupnpc_socketdef.h"
void * getHTTPResponse(SOCKET s, int * size, int * status_code);
#endif

View file

@ -1,10 +1,11 @@
/* $Id: minixml.c,v 1.9 2011/02/07 13:44:57 nanard Exp $ */
/* minixml.c : the minimum size a xml parser can be ! */
/* $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-2011, Thomas BERNARD
Copyright (c) 2005-2017, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -113,7 +114,20 @@ static void parseelt(struct xmlparser * p)
const char * elementname;
while(p->xml < (p->xmlend - 1))
{
if((p->xml)[0]=='<' && (p->xml)[1]!='?')
if((p->xml + 4) <= p->xmlend && (0 == memcmp(p->xml, "<!--", 4)))
{
p->xml += 3;
/* ignore comments */
do
{
p->xml++;
if ((p->xml + 3) >= p->xmlend)
return;
}
while(memcmp(p->xml, "-->", 3) != 0);
p->xml += 3;
}
else if((p->xml)[0]=='<' && (p->xml)[1]!='?')
{
i = 0; elementname = ++p->xml;
while( !IS_WHITE_SPACE(*p->xml)
@ -148,8 +162,9 @@ static void parseelt(struct xmlparser * p)
if (p->xml >= p->xmlend)
return;
}
if(memcmp(p->xml, "<![CDATA[", 9) == 0)
{
/* CDATA are at least 9 + 3 characters long : <![CDATA[ ]]> */
if((p->xmlend >= (p->xml + (9 + 3))) && (memcmp(p->xml, "<![CDATA[", 9) == 0))
{
/* CDATA handling */
p->xml += 9;
data = p->xml;

View file

@ -1,4 +1,4 @@
/* $Id: minixml.h,v 1.6 2006/11/30 11:47:21 nanard Exp $ */
/* $Id: minixml.h,v 1.8 2019/02/10 12:29:25 nanard Exp $ */
/* minimal xml parser
*
* Project : miniupnp
@ -8,9 +8,9 @@
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
#ifndef __MINIXML_H__
#define __MINIXML_H__
#define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n'))
#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 */

View file

@ -1,4 +1,4 @@
/* $Id: minixmlvalid.c,v 1.4 2011/02/07 13:44:57 nanard Exp $ */
/* $Id: minixmlvalid.c,v 1.7 2015/07/15 12:41:15 nanard Exp $ */
/* MiniUPnP Project
* http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/
* minixmlvalid.c :
@ -32,7 +32,7 @@ int evtlistcmp(struct eventlist * a, struct eventlist * b)
if(a->n != b->n)
{
printf("event number not matching : %d != %d\n", a->n, b->n);
//return 1;
/*return 1;*/
}
for(i=0; i<a->n; i++)
{
@ -82,7 +82,7 @@ static const struct event evtref[] =
{ELTEND, "elt2b", 5},
{ELTEND, "elt2a", 5},
{ELTEND, "xmlroot", 7}
};
};
void startelt(void * data, const char * p, int l)
{
@ -128,6 +128,11 @@ int testxmlparser(const char * xml, int size)
struct xmlparser parser;
evtlist.n = 0;
evtlist.events = malloc(sizeof(struct event)*100);
if(evtlist.events == NULL)
{
fprintf(stderr, "Memory allocation error.\n");
return -1;
}
memset(&parser, 0, sizeof(parser));
parser.xmlstart = xml;
parser.xmlsize = size;
@ -148,6 +153,8 @@ int testxmlparser(const char * xml, int size)
int main(int argc, char * * argv)
{
int r;
(void)argc; (void)argv;
r = testxmlparser(xmldata, sizeof(xmldata)-1);
if(r)
printf("minixml validation test failed\n");

View file

@ -1,14 +1,22 @@
/* $Id: portlistingparse.c,v 1.4 2011/03/18 11:02:17 nanard Exp $ */
/* $Id: portlistingparse.c,v 1.11 2020/03/22 22:43:44 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2011 Thomas Bernard
* (c) 2011-2020 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include <string.h>
#include <stdlib.h>
#ifdef DEBUG
#include <stdio.h>
#endif /* DEBUG */
#include "portlistingparse.h"
#include "minixml.h"
#if defined(__HAIKU__)
/* rename our private function because Haiku already defines a atoui() function */
#define atoui atoui2
#endif
/* list of the elements */
static const struct {
const portMappingElt code;
@ -52,7 +60,7 @@ startelt(void * d, const char * name, int l)
pdata->curelt = PortMappingEltNone;
for(i = 0; elements[i].str; i++)
{
if(memcmp(name, elements[i].str, l) == 0)
if(strlen(elements[i].str) == (size_t)l && memcmp(name, elements[i].str, l) == 0)
{
pdata->curelt = elements[i].code;
break;
@ -62,7 +70,17 @@ startelt(void * d, const char * name, int l)
{
struct PortMapping * pm;
pm = calloc(1, sizeof(struct PortMapping));
LIST_INSERT_HEAD( &(pdata->head), pm, entries);
if(pm == NULL)
{
/* malloc error */
#ifdef DEBUG
fprintf(stderr, "%s: error allocating memory",
"startelt");
#endif /* DEBUG */
return;
}
pm->l_next = pdata->l_head; /* insert in list */
pdata->l_head = pm;
}
}
@ -71,6 +89,8 @@ static void
endelt(void * d, const char * name, int l)
{
struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;
(void)name;
(void)l;
pdata->curelt = PortMappingEltNone;
}
@ -80,7 +100,7 @@ data(void * d, const char * data, int l)
{
struct PortMapping * pm;
struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;
pm = pdata->head.lh_first;
pm = pdata->l_head;
if(!pm)
return;
if(l > 63)
@ -132,7 +152,6 @@ ParsePortListing(const char * buffer, int bufsize,
struct xmlparser parser;
memset(pdata, 0, sizeof(struct PortMappingParserData));
LIST_INIT(&(pdata->head));
/* init xmlparser */
parser.xmlstart = buffer;
parser.xmlsize = bufsize;
@ -148,9 +167,10 @@ void
FreePortListing(struct PortMappingParserData * pdata)
{
struct PortMapping * pm;
while((pm = pdata->head.lh_first) != NULL)
while((pm = pdata->l_head) != NULL)
{
LIST_REMOVE(pm, entries);
/* remove from list */
pdata->l_head = pm->l_next;
free(pm);
}
}

View file

@ -0,0 +1,105 @@
/* $Id: receivedata.c,v 1.10 2021/03/02 23:33:07 nanard Exp $ */
/* Project : miniupnp
* Website : http://miniupnp.free.fr/
* Author : Thomas Bernard
* Copyright (c) 2011-2021 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
#include <stdio.h>
#include <string.h>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else /* _WIN32 */
#include <unistd.h>
#if defined(__amigaos__) && !defined(__amigaos4__)
#define socklen_t int
#else /* #if defined(__amigaos__) && !defined(__amigaos4__) */
#include <sys/select.h>
#endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */
#include <sys/socket.h>
#include <netinet/in.h>
#if !defined(__amigaos__) && !defined(__amigaos4__)
#include <poll.h>
#endif /* !defined(__amigaos__) && !defined(__amigaos4__) */
#include <errno.h>
#define MINIUPNPC_IGNORE_EINTR
#endif /* _WIN32 */
#include "receivedata.h"
int
receivedata(SOCKET socket,
char * data, int length,
int timeout, unsigned int * scope_id)
{
#ifdef MINIUPNPC_GET_SRC_ADDR
struct sockaddr_storage src_addr;
socklen_t src_addr_len = sizeof(src_addr);
#endif /* MINIUPNPC_GET_SRC_ADDR */
int n;
#if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__)
/* using poll */
struct pollfd fds[1]; /* for the poll */
#ifdef MINIUPNPC_IGNORE_EINTR
do {
#endif /* MINIUPNPC_IGNORE_EINTR */
fds[0].fd = socket;
fds[0].events = POLLIN;
n = poll(fds, 1, timeout);
#ifdef MINIUPNPC_IGNORE_EINTR
} while(n < 0 && errno == EINTR);
#endif /* MINIUPNPC_IGNORE_EINTR */
if(n < 0) {
PRINT_SOCKET_ERROR("poll");
return -1;
} else if(n == 0) {
/* timeout */
return 0;
}
#else /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
/* using select under _WIN32 and amigaos */
fd_set socketSet;
TIMEVAL timeval;
FD_ZERO(&socketSet);
FD_SET(socket, &socketSet);
timeval.tv_sec = timeout / 1000;
timeval.tv_usec = (timeout % 1000) * 1000;
n = select(FD_SETSIZE, &socketSet, NULL, NULL, &timeval);
if(n < 0) {
PRINT_SOCKET_ERROR("select");
return -1;
} else if(n == 0) {
return 0;
}
#endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
#ifdef MINIUPNPC_GET_SRC_ADDR
memset(&src_addr, 0, sizeof(src_addr));
n = recvfrom(socket, data, length, 0,
(struct sockaddr *)&src_addr, &src_addr_len);
#else /* MINIUPNPC_GET_SRC_ADDR */
n = recv(socket, data, length, 0);
#endif /* MINIUPNPC_GET_SRC_ADDR */
if(n<0) {
PRINT_SOCKET_ERROR("recv");
}
#ifdef MINIUPNPC_GET_SRC_ADDR
if (src_addr.ss_family == AF_INET6) {
const struct sockaddr_in6 * src_addr6 = (struct sockaddr_in6 *)&src_addr;
#ifdef DEBUG
printf("scope_id=%u\n", src_addr6->sin6_scope_id);
#endif /* DEBUG */
if(scope_id)
*scope_id = src_addr6->sin6_scope_id;
} else {
if(scope_id)
*scope_id = 0;
}
#else /* MINIUPNPC_GET_SRC_ADDR */
if(scope_id)
*scope_id = 0;
#endif /* MINIUPNPC_GET_SRC_ADDR */
return n;
}

View file

@ -0,0 +1,21 @@
/* $Id: receivedata.h,v 1.5 2018/04/06 10:53:15 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author: Thomas Bernard
* Copyright (c) 2011-2018 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef RECEIVEDATA_H_INCLUDED
#define RECEIVEDATA_H_INCLUDED
#include "miniupnpc_socketdef.h"
/* Reads data from the specified socket.
* Returns the number of bytes read if successful, zero if no bytes were
* read or if we timed out. Returns negative if there was an error. */
int receivedata(SOCKET socket,
char * data, int length,
int timeout, unsigned int * scope_id);
#endif

View file

@ -0,0 +1,46 @@
/* $Id: testaddr_is_reserved.c,v 1.1 2020/10/15 22:12:51 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* Project : miniupnp
* Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
* Author : Thomas BERNARD
* copyright (c) 2005-2020 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENSE file. */
#include <stdio.h>
#include "addr_is_reserved.h"
static const struct {
const char * str;
int expected_result;
} tests[] = {
{ "0.0.0.0", 1 },
{ "8.8.8.8", 0 },
{ "192.168.1.1", 1 },
{ "10.250.42.12", 1 },
{ "11.250.42.12", 0 },
{ "172.31.1.1", 1 },
{ "172.32.1.1", 0 },
{ "169.254.42.42", 1 },
{ "192.0.0.11", 1 },
{ "198.0.0.11", 0 },
{ "198.18.0.11", 1 },
{ "100.64.1.1", 1 },
{ "100.127.1.1", 1 },
{ "100.128.1.1", 0 },
{ NULL, 0 }
};
int main(int argc, char * * argv) {
int i, result;
(void)argc; (void)argv;
for (i = 0; tests[i].str != NULL; i++) {
result = addr_is_reserved(tests[i].str);
printf("testing %s %d %d\n", tests[i].str, tests[i].expected_result, result);
if (result != tests[i].expected_result) {
fprintf(stderr, "*** FAILURE ***\n");
return 1; /* Failure */
}
}
return 0; /* success */
}

View file

@ -0,0 +1,187 @@
/* $Id: testigddescparse.c,v 1.11 2019/02/10 12:33:32 nanard Exp $ */
/* Project : miniupnp
* http://miniupnp.free.fr/
* Author : Thomas Bernard
* Copyright (c) 2008-2015 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "igd_desc_parse.h"
#include "minixml.h"
#include "miniupnpc.h"
/* count number of differences */
int compare_service(struct IGDdatas_service * s, FILE * f)
{
int n = 0;
char line[1024];
while(fgets(line, sizeof(line), f)) {
char * value;
char * equal;
char * name;
char * parsedvalue;
int l;
l = strlen(line);
while((l > 0) && ((line[l-1] == '\r') || (line[l-1] == '\n') || (line[l-1] == ' ')))
line[--l] = '\0';
if(l == 0)
break; /* end on blank line */
if(line[0] == '#')
continue; /* skip comments */
equal = strchr(line, '=');
if(equal == NULL) {
fprintf(stderr, "Warning, line does not contain '=' : %s\n", line);
continue;
}
*equal = '\0';
name = line;
while(*name == ' ' || *name == '\t')
name++;
l = strlen(name);
while((l > 0) && (name[l-1] == ' ' || name[l-1] == '\t'))
name[--l] = '\0';
value = equal + 1;
while(*value == ' ' || *value == '\t')
value++;
if(strcmp(name, "controlurl") == 0)
parsedvalue = s->controlurl;
else if(strcmp(name, "eventsuburl") == 0)
parsedvalue = s->eventsuburl;
else if(strcmp(name, "scpdurl") == 0)
parsedvalue = s->scpdurl;
else if(strcmp(name, "servicetype") == 0)
parsedvalue = s->servicetype;
else {
fprintf(stderr, "unknown field '%s'\n", name);
continue;
}
if(0 != strcmp(parsedvalue, value)) {
fprintf(stderr, "difference : '%s' != '%s'\n", parsedvalue, value);
n++;
}
}
return n;
}
int compare_igd(struct IGDdatas * p, FILE * f)
{
int n = 0;
char line[1024];
struct IGDdatas_service * s;
while(fgets(line, sizeof(line), f)) {
char * colon;
int l = (int)strlen(line);
while((l > 0) && (line[l-1] == '\r' || (line[l-1] == '\n')))
line[--l] = '\0';
if(l == 0 || line[0] == '#')
continue; /* skip blank lines and comments */
colon = strchr(line, ':');
if(colon == NULL) {
fprintf(stderr, "Warning, no ':' : %s\n", line);
continue;
}
s = NULL;
*colon = '\0';
if(strcmp(line, "CIF") == 0)
s = &p->CIF;
else if(strcmp(line, "first") == 0)
s = &p->first;
else if(strcmp(line, "second") == 0)
s = &p->second;
else if(strcmp(line, "IPv6FC") == 0)
s = &p->IPv6FC;
else {
s = NULL;
fprintf(stderr, "*** unknown service '%s' ***\n", line);
n++;
continue;
}
n += compare_service(s, f);
}
if(n > 0)
fprintf(stderr, "*** %d difference%s ***\n", n, (n > 1) ? "s" : "");
return n;
}
int test_igd_desc_parse(char * buffer, int len, FILE * f)
{
int n;
struct IGDdatas igd;
struct xmlparser parser;
struct UPNPUrls urls;
memset(&igd, 0, sizeof(struct IGDdatas));
memset(&parser, 0, sizeof(struct xmlparser));
parser.xmlstart = buffer;
parser.xmlsize = len;
parser.data = &igd;
parser.starteltfunc = IGDstartelt;
parser.endeltfunc = IGDendelt;
parser.datafunc = IGDdata;
parsexml(&parser);
#ifdef DEBUG
printIGD(&igd);
#endif /* DEBUG */
GetUPNPUrls(&urls, &igd, "http://fake/desc/url/file.xml", 0);
printf("ipcondescURL='%s'\n", urls.ipcondescURL);
printf("controlURL='%s'\n", urls.controlURL);
printf("controlURL_CIF='%s'\n", urls.controlURL_CIF);
n = f ? compare_igd(&igd, f) : 0;
FreeUPNPUrls(&urls);
return n;
}
int main(int argc, char * * argv)
{
FILE * f;
char * buffer;
int len;
int r;
if(argc<2) {
fprintf(stderr, "Usage: %s file.xml [file.values]\n", argv[0]);
return 1;
}
f = fopen(argv[1], "rb");
if(!f) {
fprintf(stderr, "Cannot open %s for reading.\n", argv[1]);
return 1;
}
fseek(f, 0, SEEK_END);
len = ftell(f);
fseek(f, 0, SEEK_SET);
buffer = malloc(len);
if(!buffer) {
fprintf(stderr, "Memory allocation error.\n");
fclose(f);
return 1;
}
r = (int)fread(buffer, 1, len, f);
if(r != len) {
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);
f = NULL;
if(argc > 2) {
f = fopen(argv[2], "rb");
if(!f) {
fprintf(stderr, "Cannot open %s for reading.\n", argv[2]);
free(buffer);
return 1;
}
}
r = test_igd_desc_parse(buffer, len, f);
free(buffer);
if(f)
fclose(f);
return r;
}

View file

@ -1,7 +1,8 @@
/* $Id: testminiwget.c,v 1.3 2011/05/06 16:33:53 nanard Exp $ */
/* Project : miniupnp
/* $Id: testminiwget.c,v 1.7 2018/01/16 01:01:05 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005-2011 Thomas Bernard
* Copyright (c) 2005-2018 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
@ -11,7 +12,7 @@
/**
* This program uses the miniwget / miniwget_getaddr function
* from miniwget.c in order to retreive a web ressource using
* from miniwget.c in order to retrieve a web ressource using
* a GET HTTP method, and store it in a file.
*/
int main(int argc, char * * argv)
@ -20,15 +21,17 @@ int main(int argc, char * * argv)
int size, writtensize;
FILE *f;
char addr[64];
int status_code = -1;
if(argc < 3) {
fprintf(stderr, "Usage:\t%s url file\n", argv[0]);
fprintf(stderr, "Example:\t%s http://www.google.com/ out.html\n", argv[0]);
return 1;
}
/*data = miniwget(argv[1], &size);*/
data = miniwget_getaddr(argv[1], &size, addr, sizeof(addr));
if(!data) {
fprintf(stderr, "Error fetching %s\n", argv[1]);
data = miniwget_getaddr(argv[1], &size, addr, sizeof(addr), 0, &status_code);
if(!data || (status_code != 200)) {
if(data) free(data);
fprintf(stderr, "Error %d fetching %s\n", status_code, argv[1]);
return 1;
}
printf("local address : %s\n", addr);

View file

@ -1,7 +1,11 @@
/* $Id: testminixml.c,v 1.6 2006/11/19 22:32:35 nanard Exp $
/* $Id: testminixml.c,v 1.10 2014/11/17 17:19:13 nanard Exp $
* MiniUPnP project
* Website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author : Thomas Bernard.
* Copyright (c) 2005-2014 Thomas Bernard
*
* testminixml.c
* test program for the "minixml" functions.
* Author : Thomas Bernard.
*/
#include <stdlib.h>
#include <stdio.h>
@ -9,18 +13,11 @@
#include "minixml.h"
#include "igd_desc_parse.h"
#ifdef WIN32
#define NO_BZERO
#endif
#ifdef NO_BZERO
#define bzero(p, n) memset(p, 0, n)
#endif
/* ---------------------------------------------------------------------- */
void printeltname1(void * d, const char * name, int l)
{
int i;
(void)d;
printf("element ");
for(i=0;i<l;i++)
putchar(name[i]);
@ -28,6 +25,7 @@ void printeltname1(void * d, const char * name, int l)
void printeltname2(void * d, const char * name, int l)
{
int i;
(void)d;
putchar('/');
for(i=0;i<l;i++)
putchar(name[i]);
@ -36,6 +34,7 @@ void printeltname2(void * d, const char * name, int l)
void printdata(void *d, const char * data, int l)
{
int i;
(void)d;
printf("data : ");
for(i=0;i<l;i++)
putchar(data[i]);
@ -47,7 +46,7 @@ void burptest(const char * buffer, int bufsize)
struct IGDdatas data;
struct xmlparser parser;
/*objet IGDdatas */
bzero(&data, sizeof(struct IGDdatas));
memset(&data, 0, sizeof(struct IGDdatas));
/* objet xmlparser */
parser.xmlstart = buffer;
parser.xmlsize = bufsize;
@ -57,9 +56,11 @@ void burptest(const char * buffer, int bufsize)
parser.datafunc = printdata; */
parser.starteltfunc = IGDstartelt;
parser.endeltfunc = IGDendelt;
parser.datafunc = IGDdata;
parser.datafunc = IGDdata;
parsexml(&parser);
#ifdef DEBUG
printIGD(&data);
#endif /* DEBUG */
}
/* ----- main ---- */

View file

@ -0,0 +1,151 @@
/* $Id: testportlistingparse.c,v 1.2 2014/11/01 10:37:32 nanard Exp $ */
/* Project : miniupnp
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author : Thomas Bernard
* Copyright (c) 2014 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
#include <string.h>
#include <stdio.h>
#include "portlistingparse.h"
struct port_mapping {
unsigned int leasetime;
unsigned short externalport;
unsigned short internalport;
const char * remotehost;
const char * client;
const char * proto;
const char * desc;
unsigned char enabled;
};
/* return the number of differences */
int test(const char * portListingXml, int portListingXmlLen,
const struct port_mapping * ref, int count)
{
int i;
int r = 0;
struct PortMappingParserData data;
struct PortMapping * pm;
memset(&data, 0, sizeof(data));
ParsePortListing(portListingXml, portListingXmlLen, &data);
for(i = 0, pm = data.l_head;
(pm != NULL) && (i < count);
i++, 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);
if(0 != strcmp(pm->protocol, ref[i].proto)) {
printf("protocol : '%s' != '%s'\n", pm->protocol, ref[i].proto);
r++;
}
if(pm->externalPort != ref[i].externalport) {
printf("externalPort : %hu != %hu\n",
pm->externalPort, ref[i].externalport);
r++;
}
if(0 != strcmp(pm->internalClient, ref[i].client)) {
printf("client : '%s' != '%s'\n",
pm->internalClient, ref[i].client);
r++;
}
if(pm->internalPort != ref[i].internalport) {
printf("internalPort : %hu != %hu\n",
pm->internalPort, ref[i].internalport);
r++;
}
if(0 != strcmp(pm->description, ref[i].desc)) {
printf("description : '%s' != '%s'\n",
pm->description, ref[i].desc);
r++;
}
if(0 != strcmp(pm->remoteHost, ref[i].remotehost)) {
printf("remoteHost : '%s' != '%s'\n",
pm->remoteHost, ref[i].remotehost);
r++;
}
if((unsigned)pm->leaseTime != ref[i].leasetime) {
printf("leaseTime : %u != %u\n",
(unsigned)pm->leaseTime, ref[i].leasetime);
r++;
}
if(pm->enabled != ref[i].enabled) {
printf("enabled : %d != %d\n",
(int)pm->enabled, (int)ref[i].enabled);
r++;
}
}
if((i != count) || (pm != NULL)) {
printf("count mismatch : i=%d count=%d pm=%p\n", i, count, pm);
r++;
}
FreePortListing(&data);
return r;
}
const char test_document[] =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<p:PortMappingList xmlns:p=\"urn:schemas-upnp-org:gw:WANIPConnection\"\n"
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n"
"xsi:schemaLocation=\"urn:schemas-upnp-org:gw:WANIPConnection "
"http://www.upnp.org/schemas/gw/WANIPConnection-v2.xsd\">\n"
" <p:PortMappingEntry>\n"
" <p:NewRemoteHost></p:NewRemoteHost>\n"
" <p:NewExternalPort>5002</p:NewExternalPort>\n"
" <p:NewProtocol>UDP</p:NewProtocol>\n"
" <p:NewInternalPort>4001</p:NewInternalPort>\n"
" <p:NewInternalClient>192.168.1.123</p:NewInternalClient>\n"
" <p:NewEnabled>1</p:NewEnabled>\n"
" <p:NewDescription>xxx</p:NewDescription>\n"
" <p:NewLeaseTime>0</p:NewLeaseTime>\n"
" </p:PortMappingEntry>\n"
" <p:PortMappingEntry>\n"
" <p:NewRemoteHost>202.233.2.1</p:NewRemoteHost>\n"
" <p:NewExternalPort>2345</p:NewExternalPort>\n"
" <p:NewProtocol>TCP</p:NewProtocol>\n"
" <p:NewInternalPort>2349</p:NewInternalPort>\n"
" <p:NewInternalClient>192.168.1.137</p:NewInternalClient>\n"
" <p:NewEnabled>1</p:NewEnabled>\n"
" <p:NewDescription>dooom</p:NewDescription>\n"
" <p:NewLeaseTime>346</p:NewLeaseTime>\n"
" </p:PortMappingEntry>\n"
" <p:PortMappingEntry>\n"
" <p:NewRemoteHost>134.231.2.11</p:NewRemoteHost>\n"
" <p:NewExternalPort>12345</p:NewExternalPort>\n"
" <p:NewProtocol>TCP</p:NewProtocol>\n"
" <p:NewInternalPort>12345</p:NewInternalPort>\n"
" <p:NewInternalClient>192.168.1.137</p:NewInternalClient>\n"
" <p:NewEnabled>1</p:NewEnabled>\n"
" <p:NewDescription>dooom A</p:NewDescription>\n"
" <p:NewLeaseTime>347</p:NewLeaseTime>\n"
" </p:PortMappingEntry>\n"
"</p:PortMappingList>";
#define PORT_MAPPINGS_COUNT 3
const struct port_mapping port_mappings[PORT_MAPPINGS_COUNT] = {
{347, 12345, 12345, "134.231.2.11", "192.168.1.137", "TCP", "dooom A", 1},
{346, 2345, 2349, "202.233.2.1", "192.168.1.137", "TCP", "dooom", 1},
{0, 5002, 4001, "", "192.168.1.123", "UDP", "xxx", 1}
};
/* --- main --- */
int main(void)
{
int r;
r = test(test_document, sizeof(test_document) - 1,
port_mappings, PORT_MAPPINGS_COUNT);
if(r == 0) {
printf("test of portlistingparse OK\n");
return 0;
} else {
printf("test FAILED (%d differences counted)\n", r);
return 1;
}
}

View file

@ -0,0 +1,115 @@
/* $Id: testupnpreplyparse.c,v 1.5 2017/12/12 11:18:46 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2017 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "upnpreplyparse.h"
int
test_parsing(const char * buf, int len, FILE * f)
{
char line[1024];
struct NameValueParserData pdata;
int ok = 1;
ParseNameValue(buf, len, &pdata);
/* check result */
if(f != NULL)
{
while(fgets(line, sizeof(line), f))
{
char * value;
char * equal;
char * parsedvalue;
int l;
l = strlen(line);
while((l > 0) && ((line[l-1] == '\r') || (line[l-1] == '\n')))
line[--l] = '\0';
/* skip empty lines */
if(l == 0)
continue;
equal = strchr(line, '=');
if(equal == NULL)
{
fprintf(stderr, "Warning, line does not contain '=' : %s\n", line);
continue;
}
*equal = '\0';
value = equal + 1;
parsedvalue = GetValueFromNameValueList(&pdata, line);
if((parsedvalue == NULL) || (strcmp(parsedvalue, value) != 0))
{
fprintf(stderr, "Element <%s> : expecting value '%s', got '%s'\n",
line, value, parsedvalue ? parsedvalue : "<null string>");
ok = 0;
}
}
}
ClearNameValueList(&pdata);
return ok;
}
int main(int argc, char * * argv)
{
FILE * f;
char * buffer;
long l;
int ok;
if(argc<2)
{
fprintf(stderr, "Usage: %s file.xml [file.namevalues]\n", argv[0]);
return 1;
}
f = fopen(argv[1], "r");
if(!f)
{
fprintf(stderr, "Error : can not open file %s\n", argv[1]);
return 2;
}
if(fseek(f, 0, SEEK_END) < 0) {
perror("fseek");
return 1;
}
l = (int)ftell(f);
if(l < 0) {
perror("ftell");
return 1;
}
if(fseek(f, 0, SEEK_SET) < 0) {
perror("fseek");
return 1;
}
buffer = malloc(l + 1);
if(buffer == NULL) {
fprintf(stderr, "Error: failed to allocate %ld bytes\n", l+1);
return 1;
}
l = fread(buffer, 1, l, f);
fclose(f);
f = NULL;
buffer[l] = '\0';
if(argc > 2)
{
f = fopen(argv[2], "r");
if(!f)
{
fprintf(stderr, "Error : can not open file %s\n", argv[2]);
return 2;
}
}
#ifdef DEBUG
DisplayNameValueList(buffer, l);
#endif
ok = test_parsing(buffer, l, f);
if(f)
{
fclose(f);
}
free(buffer);
return ok ? 0 : 3;
}

View file

@ -1,7 +1,7 @@
/* $Id: upnpc.c,v 1.88 2011/06/17 23:31:01 nanard Exp $ */
/* $Id: upnpc.c,v 1.134 2023/06/11 23:23:10 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005-2011 Thomas Bernard
* Copyright (c) 2005-2023 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
@ -9,16 +9,22 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef WIN32
#ifdef _WIN32
#include <winsock2.h>
#define snprintf _snprintf
#include "win32_snprintf.h"
#else
/* for IPPROTO_TCP / IPPROTO_UDP */
#include <netinet/in.h>
#endif
#include <ctype.h>
#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"
/* protofix() checks if protocol is "UDP" or "TCP"
* returns NULL if not */
const char * protofix(const char * proto)
{
@ -26,7 +32,7 @@ const char * protofix(const char * proto)
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])
b = b && ( (proto[i] == proto_tcp[i])
|| (proto[i] == (proto_tcp[i] | 32)) );
if(b)
return proto_tcp;
@ -38,6 +44,22 @@ const char * protofix(const char * proto)
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)
{
@ -45,48 +67,55 @@ static void DisplayInfos(struct UPNPUrls * urls,
char connectionType[64];
char status[64];
char lastconnerr[64];
unsigned int uptime;
unsigned int uptime = 0;
unsigned int brUp, brDown;
time_t timenow, timestarted;
int r;
UPNP_GetConnectionTypeInfo(urls->controlURL,
data->first.servicetype,
connectionType);
if(connectionType[0])
printf("Connection Type : %s\n", connectionType);
else
if(UPNP_GetConnectionTypeInfo(urls->controlURL,
data->first.servicetype,
connectionType) != UPNPCOMMAND_SUCCESS)
printf("GetConnectionTypeInfo failed.\n");
UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype,
status, &uptime, lastconnerr);
printf("Status : %s, uptime=%us, LastConnectionError : %s\n",
status, uptime, lastconnerr);
timenow = time(NULL);
timestarted = timenow - uptime;
printf(" Time started : %s", ctime(&timestarted));
UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, data->CIF.servicetype,
&brDown, &brUp);
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);
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(&timestarted));
}
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);
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");
}
printf("\n");
r = UPNP_GetExternalIPAddress(urls->controlURL,
data->first.servicetype,
externalIPAddress);
if(r != UPNPCOMMAND_SUCCESS)
printf("GetExternalIPAddress() returned %d\n", r);
if(externalIPAddress[0])
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);
else
printf("GetExternalIPAddress failed.\n");
}
}
static void GetConnectionStatus(struct UPNPUrls * urls,
@ -106,7 +135,7 @@ static void ListRedirections(struct UPNPUrls * urls,
struct IGDdatas * data)
{
int r;
int i = 0;
unsigned short i = 0;
char index[6];
char intClient[40];
char intPort[6];
@ -119,8 +148,9 @@ static void ListRedirections(struct UPNPUrls * urls,
/*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, "%d", i);
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';
@ -132,20 +162,19 @@ static void ListRedirections(struct UPNPUrls * urls,
rHost, duration);
if(r==0)
/*
printf("%02d - %s %s->%s:%s\tenabled=%s leaseDuration=%s\n"
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("%2d %s %5s->%s:%-5s '%s' '%s' %s\n",
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));
i++;
} while(r==0);
} while(r == 0 && i++ < 65535);
}
static void NewListRedirections(struct UPNPUrls * urls,
@ -159,14 +188,15 @@ static void NewListRedirections(struct UPNPUrls * urls,
memset(&pdata, 0, sizeof(struct PortMappingParserData));
r = UPNP_GetListOfPortMappings(urls->controlURL,
data->first.servicetype,
"0",
"1",
"65535",
"TCP",
"1000",
&pdata);
if(r == UPNPCOMMAND_SUCCESS)
{
for(pm = pdata.head.lh_first; pm != NULL; pm = pm->entries.le_next)
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,
@ -184,14 +214,14 @@ static void NewListRedirections(struct UPNPUrls * urls,
}
r = UPNP_GetListOfPortMappings(urls->controlURL,
data->first.servicetype,
"0",
"1",
"65535",
"UDP",
"1000",
&pdata);
if(r == UPNPCOMMAND_SUCCESS)
{
for(pm = pdata.head.lh_first; pm != NULL; pm = pm->entries.le_next)
for(pm = pdata.l_head; pm != NULL; pm = pm->l_next)
{
printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n",
i, pm->protocol, pm->externalPort, pm->internalClient,
@ -209,87 +239,145 @@ static void NewListRedirections(struct UPNPUrls * urls,
}
}
/* Test function
/* Test function
* 1 - get connection type
* 2 - get extenal ip address
* 3 - Add port mapping
* 4 - get this port mapping from the IGD */
static void SetRedirectAndTest(struct UPNPUrls * urls,
struct IGDdatas * data,
const char * iaddr,
const char * iport,
const char * eport,
const char * proto,
const char * leaseDuration)
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;
return -1;
}
proto = protofix(proto);
if(!proto)
{
fprintf(stderr, "invalid protocol\n");
return;
return -1;
}
UPNP_GetExternalIPAddress(urls->controlURL,
data->first.servicetype,
externalIPAddress);
if(externalIPAddress[0])
printf("ExternalIPAddress = %s\n", externalIPAddress);
else
printf("GetExternalIPAddress failed.\n");
r = UPNP_AddPortMapping(urls->controlURL, data->first.servicetype,
eport, iport, iaddr, 0, proto, 0, leaseDuration);
r = UPNP_GetExternalIPAddress(urls->controlURL,
data->first.servicetype,
externalIPAddress);
if(r!=UPNPCOMMAND_SUCCESS)
printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
eport, iport, iaddr, r, strupnperror(r));
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,
intClient, intPort, NULL/*desc*/,
NULL/*enabled*/, duration);
if(r!=UPNPCOMMAND_SUCCESS)
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));
if(intClient[0]) {
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 void
static int
RemoveRedirect(struct UPNPUrls * urls,
struct IGDdatas * data,
const char * eport,
const char * proto)
const char * eport,
const char * proto,
const char * remoteHost)
{
int r;
if(!proto || !eport)
{
fprintf(stderr, "invalid arguments\n");
return;
return -1;
}
proto = protofix(proto);
if(!proto)
{
fprintf(stderr, "protocol invalid\n");
return;
return -1;
}
r = UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, 0);
printf("UPNP_DeletePortMapping() returned : %d\n", r);
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 */
@ -301,7 +389,7 @@ static void GetFirewallStatus(struct UPNPUrls * urls, struct IGDdatas * data)
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);
@ -310,7 +398,7 @@ static void GetFirewallStatus(struct UPNPUrls * urls, struct IGDdatas * data)
printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived);
}
/* Test function
/* Test function
* 1 - Add pinhole
* 2 - Check if pinhole is working from the IGD side */
static void SetPinholeAndTest(struct UPNPUrls * urls, struct IGDdatas * data,
@ -319,27 +407,43 @@ static void SetPinholeAndTest(struct UPNPUrls * urls, struct IGDdatas * data,
const char * proto, const char * lease_time)
{
char uniqueID[8];
//int isWorking = 0;
/*int isWorking = 0;*/
int r;
char proto_tmp[8];
if(!intaddr || !remoteaddr || !iport || !eport || !proto || !lease_time)
{
fprintf(stderr, "Wrong arguments\n");
return;
}
/*proto = protofix(proto);
if(!proto)
if(atoi(proto) == 0)
{
fprintf(stderr, "invalid protocol\n");
return;
}*/
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",
intaddr, iport, remoteaddr, eport, r, strupnperror(r));
remoteaddr, eport, intaddr, iport, r, strupnperror(r));
else
{
printf("AddPinhole: ([%s]:%s -> [%s]:%s) / Pinhole ID = %s\n", intaddr, iport, remoteaddr, eport, uniqueID);
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));
@ -361,11 +465,20 @@ static void GetPinholeAndUpdate(struct UPNPUrls * urls, struct IGDdatas * data,
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);
printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");
if(r!=UPNPCOMMAND_SUCCESS)
printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r));
if(isWorking || r==709)
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);
@ -374,7 +487,7 @@ static void GetPinholeAndUpdate(struct UPNPUrls * urls, struct IGDdatas * data,
}
}
/* Test function
/* Test function
* Get pinhole timeout
*/
static void GetPinholeOutboundTimeout(struct UPNPUrls * urls, struct IGDdatas * data,
@ -455,16 +568,20 @@ int main(int argc, char ** argv)
char ** commandargv = 0;
int commandargc = 0;
struct UPNPDev * devlist = 0;
char lanaddr[64]; /* my ip address on the LAN */
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
#ifdef _WIN32
WSADATA wsaData;
int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if(nResult != NO_ERROR)
@ -473,22 +590,49 @@ int main(int argc, char ** argv)
return -1;
}
#endif
printf("upnpc : miniupnpc library test client. (c) 2006-2011 Thomas Bernard\n");
printf("Go to http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/\n"
printf("upnpc : miniupnpc library test client, version %s.\n", MINIUPNPC_VERSION_STRING);
printf(" (c) 2005-2023 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; i<argc; i++)
{
if(0 == strcmp(argv[i], "--help") || 0 == strcmp(argv[i], "-h"))
{
command = 0;
break;
}
if(argv[i][0] == '-')
{
if(argv[i][1] == 'u')
rootdescurl = argv[++i];
else if(argv[i][1] == 'm')
{
multicastif = argv[++i];
minissdpdpath = ""; /* Disable usage of minissdpd */
}
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')
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];
@ -504,19 +648,22 @@ int main(int argc, char ** argv)
}
}
if(!command || (command == 'a' && commandargc<4)
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]\n\t\tAdd port redirection\n", argv[0]);
fprintf(stderr, " \t%s [options] -d external_port protocol [port2 protocol2] [...]\n\t\tDelete port redirection\n", argv[0]);
fprintf(stderr, "Usage :\t%s [options] -a ip port external_port protocol [duration] [remote host]\n\t\tAdd port redirection\n", argv[0]);
fprintf(stderr, " \t%s [options] -d external_port protocol [remote host]\n\t\tDelete port redirection\n", argv[0]);
fprintf(stderr, " \t%s [options] -s\n\t\tGet Connection status\n", argv[0]);
fprintf(stderr, " \t%s [options] -l\n\t\tList redirections\n", argv[0]);
fprintf(stderr, " \t%s [options] -L\n\t\tList redirections (using GetListOfPortMappings, IGD v2)\n", argv[0]);
fprintf(stderr, " \t%s [options] -r port1 protocol1 [port2 protocol2] [...]\n\t\tAdd all redirections to the current host\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 redirection allowing IGD to use alternative external_port (for IGD:2 only)\n", argv[0]);
fprintf(stderr, " \t%s [options] -N external_port_start external_port_end protocol [manage]\n\t\tDelete range of port redirections (for IGD:2 only)\n", argv[0]);
fprintf(stderr, " \t%s [options] -r port1 [external_port1] protocol1 [port2 [external_port2] protocol2] [...]\n\t\tAdd all redirections to the current host\n", argv[0]);
fprintf(stderr, " \t%s [options] -A remote_ip remote_port internal_ip internal_port protocol lease_time\n\t\tAdd Pinhole (for IGD:2 only)\n", argv[0]);
fprintf(stderr, " \t%s [options] -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]);
@ -526,17 +673,22 @@ int main(int argc, char ** argv)
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 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 v6) to use for sending SSDP multicast packets.\n");
fprintf(stderr, " -m address/interface : provide ip address (ip v4) or interface name (ip v4 or v6) to use for sending SSDP multicast packets.\n");
fprintf(stderr, " -z localport : SSDP packets local (source) port (1024-65535).\n");
fprintf(stderr, " -p path : use this path for MiniSSDPd socket.\n");
fprintf(stderr, " -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,
0/*sameport*/, ipv6, &error)))
localport, ipv6, ttl, &error)))
{
struct UPNPDev * device;
struct UPNPUrls urls;
@ -550,7 +702,7 @@ int main(int argc, char ** argv)
device->descURL, device->st);
}
}
else
else if(!rootdescurl)
{
printf("upnpDiscover() error code=%d\n", error);
}
@ -564,16 +716,18 @@ int main(int argc, char ** argv)
break;
case 2:
printf("Found a (not connected?) IGD : %s\n", urls.controlURL);
printf("Trying to continue anyway\n");
if (ignore) printf("Trying to continue anyway\n");
break;
case 3:
printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL);
printf("Trying to continue anyway\n");
if (ignore) printf("Trying to continue anyway\n");
break;
default:
printf("Found device (igd ?) : %s\n", urls.controlURL);
printf("Trying to continue anyway\n");
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);
@ -585,6 +739,12 @@ int main(int argc, char ** argv)
}
#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':
@ -595,27 +755,65 @@ int main(int argc, char ** argv)
NewListRedirections(&urls, &data);
break;
case 'a':
SetRedirectAndTest(&urls, &data,
commandargv[0], commandargv[1],
commandargv[2], commandargv[3],
(commandargc > 4)?commandargv[4]:"0");
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':
for(i=0; i<commandargc; i+=2)
{
RemoveRedirect(&urls, &data, commandargv[i], commandargv[i+1]);
}
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':
for(i=0; i<commandargc; i+=2)
i = 0;
while(i<commandargc)
{
/*printf("port %s protocol %s\n", argv[i], argv[i+1]);*/
SetRedirectAndTest(&urls, &data,
lanaddr, commandargv[i],
commandargv[i], commandargv[i+1], "0");
if(!is_int(commandargv[i])) {
/* 1st parameter not an integer : error */
fprintf(stderr, "command -r : %s is not an port number\n", commandargv[i]);
retcode = 1;
break;
} else if(is_int(commandargv[i+1])){
/* 2nd parameter is an integer : <port> <external_port> <protocol> */
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 : <port> <protocol> */
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':
@ -664,6 +862,10 @@ int main(int argc, char ** argv)
retcode = 1;
}
} else {
fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n");
retcode = 1;
}
FreeUPNPUrls(&urls);
}
else
@ -678,6 +880,12 @@ int main(int argc, char ** argv)
fprintf(stderr, "No IGD UPnP Device found on the network !\n");
retcode = 1;
}
#ifdef _WIN32
nResult = WSACleanup();
if(nResult != NO_ERROR) {
fprintf(stderr, "WSACleanup() failed.\n");
}
#endif /* _WIN32 */
return retcode;
}

View file

@ -1,7 +1,8 @@
/* $Id: upnpcommands.c,v 1.37 2011/06/04 15:56:23 nanard Exp $ */
/* Project : miniupnp
/* $Id: upnpcommands.c,v 1.51 2019/04/23 11:45:15 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005-2011 Thomas Bernard
* Copyright (c) 2005-2018 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
@ -11,6 +12,7 @@
#include "upnpcommands.h"
#include "miniupnpc.h"
#include "portlistingparse.h"
#include "upnpreplyparse.h"
static UNSIGNED_INTEGER
my_atoui(const char * s)
@ -20,7 +22,7 @@ my_atoui(const char * s)
/*
* */
LIBSPEC UNSIGNED_INTEGER
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalBytesSent(const char * controlURL,
const char * servicetype)
{
@ -31,11 +33,11 @@ UPNP_GetTotalBytesSent(const char * controlURL,
char * p;
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetTotalBytesSent", 0, &bufsize))) {
return UPNPCOMMAND_HTTP_ERROR;
return (UNSIGNED_INTEGER)UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
/*DisplayNameValueList(buffer, bufsize);*/
free(buffer); buffer = NULL;
free(buffer);
p = GetValueFromNameValueList(&pdata, "NewTotalBytesSent");
r = my_atoui(p);
ClearNameValueList(&pdata);
@ -44,7 +46,7 @@ UPNP_GetTotalBytesSent(const char * controlURL,
/*
* */
LIBSPEC UNSIGNED_INTEGER
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalBytesReceived(const char * controlURL,
const char * servicetype)
{
@ -55,11 +57,11 @@ UPNP_GetTotalBytesReceived(const char * controlURL,
char * p;
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetTotalBytesReceived", 0, &bufsize))) {
return UPNPCOMMAND_HTTP_ERROR;
return (UNSIGNED_INTEGER)UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
/*DisplayNameValueList(buffer, bufsize);*/
free(buffer); buffer = NULL;
free(buffer);
p = GetValueFromNameValueList(&pdata, "NewTotalBytesReceived");
r = my_atoui(p);
ClearNameValueList(&pdata);
@ -68,7 +70,7 @@ UPNP_GetTotalBytesReceived(const char * controlURL,
/*
* */
LIBSPEC UNSIGNED_INTEGER
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalPacketsSent(const char * controlURL,
const char * servicetype)
{
@ -79,11 +81,11 @@ UPNP_GetTotalPacketsSent(const char * controlURL,
char * p;
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetTotalPacketsSent", 0, &bufsize))) {
return UPNPCOMMAND_HTTP_ERROR;
return (UNSIGNED_INTEGER)UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
/*DisplayNameValueList(buffer, bufsize);*/
free(buffer); buffer = NULL;
free(buffer);
p = GetValueFromNameValueList(&pdata, "NewTotalPacketsSent");
r = my_atoui(p);
ClearNameValueList(&pdata);
@ -92,7 +94,7 @@ UPNP_GetTotalPacketsSent(const char * controlURL,
/*
* */
LIBSPEC UNSIGNED_INTEGER
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalPacketsReceived(const char * controlURL,
const char * servicetype)
{
@ -103,11 +105,11 @@ UPNP_GetTotalPacketsReceived(const char * controlURL,
char * p;
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetTotalPacketsReceived", 0, &bufsize))) {
return UPNPCOMMAND_HTTP_ERROR;
return (UNSIGNED_INTEGER)UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
/*DisplayNameValueList(buffer, bufsize);*/
free(buffer); buffer = NULL;
free(buffer);
p = GetValueFromNameValueList(&pdata, "NewTotalPacketsReceived");
r = my_atoui(p);
ClearNameValueList(&pdata);
@ -116,10 +118,10 @@ UPNP_GetTotalPacketsReceived(const char * controlURL,
/* UPNP_GetStatusInfo() call the corresponding UPNP method
* returns the current status and uptime */
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_GetStatusInfo(const char * controlURL,
const char * servicetype,
char * status,
char * status,
unsigned int * uptime,
char * lastconnerror)
{
@ -140,7 +142,7 @@ UPNP_GetStatusInfo(const char * controlURL,
}
ParseNameValue(buffer, bufsize, &pdata);
/*DisplayNameValueList(buffer, bufsize);*/
free(buffer); buffer = NULL;
free(buffer);
up = GetValueFromNameValueList(&pdata, "NewUptime");
p = GetValueFromNameValueList(&pdata, "NewConnectionStatus");
err = GetValueFromNameValueList(&pdata, "NewLastConnectionError");
@ -159,7 +161,7 @@ UPNP_GetStatusInfo(const char * controlURL,
if(up)
sscanf(up,"%u",uptime);
else
uptime = 0;
*uptime = 0;
}
if(lastconnerror) {
@ -181,7 +183,7 @@ UPNP_GetStatusInfo(const char * controlURL,
/* UPNP_GetConnectionTypeInfo() call the corresponding UPNP method
* returns the connection type */
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_GetConnectionTypeInfo(const char * controlURL,
const char * servicetype,
char * connectionType)
@ -200,7 +202,7 @@ UPNP_GetConnectionTypeInfo(const char * controlURL,
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
free(buffer);
p = GetValueFromNameValueList(&pdata, "NewConnectionType");
/*p = GetValueFromNameValueList(&pdata, "NewPossibleConnectionTypes");*/
/* PossibleConnectionTypes will have several values.... */
@ -221,10 +223,10 @@ UPNP_GetConnectionTypeInfo(const char * controlURL,
/* UPNP_GetLinkLayerMaxBitRate() call the corresponding UPNP method.
* Returns 2 values: Downloadlink bandwidth and Uplink bandwidth.
* One of the values can be null
* Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only
* One of the values can be null
* Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only
* We can use the GetCommonLinkProperties from WANCommonInterfaceConfig:1 */
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_GetLinkLayerMaxBitRates(const char * controlURL,
const char * servicetype,
unsigned int * bitrateDown,
@ -249,7 +251,7 @@ UPNP_GetLinkLayerMaxBitRates(const char * controlURL,
}
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
free(buffer);
/*down = GetValueFromNameValueList(&pdata, "NewDownstreamMaxBitRate");*/
/*up = GetValueFromNameValueList(&pdata, "NewUpstreamMaxBitRate");*/
down = GetValueFromNameValueList(&pdata, "NewLayer1DownstreamMaxBitRate");
@ -285,7 +287,7 @@ UPNP_GetLinkLayerMaxBitRates(const char * controlURL,
/* 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.
@ -293,7 +295,7 @@ UPNP_GetLinkLayerMaxBitRates(const char * controlURL,
* 402 Invalid Args - See UPnP Device Architecture section on Control.
* 501 Action Failed - See UPnP Device Architecture section on Control.
*/
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_GetExternalIPAddress(const char * controlURL,
const char * servicetype,
char * extIpAdd)
@ -313,7 +315,7 @@ UPNP_GetExternalIPAddress(const char * controlURL,
}
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
free(buffer);
/*printf("external ip = %s\n", GetValueFromNameValueList(&pdata, "NewExternalIPAddress") );*/
p = GetValueFromNameValueList(&pdata, "NewExternalIPAddress");
if(p) {
@ -333,15 +335,15 @@ UPNP_GetExternalIPAddress(const char * controlURL,
return ret;
}
LIBSPEC int
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)
const char * extPort,
const char * inPort,
const char * inClient,
const char * desc,
const char * proto,
const char * remoteHost,
const char * leaseDuration)
{
struct UPNParg * AddPortMappingArgs;
char * buffer;
@ -354,6 +356,8 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
return UPNPCOMMAND_INVALID_ARGS;
AddPortMappingArgs = calloc(9, sizeof(struct UPNParg));
if(AddPortMappingArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
AddPortMappingArgs[0].elt = "NewRemoteHost";
AddPortMappingArgs[0].val = remoteHost;
AddPortMappingArgs[1].elt = "NewExternalPort";
@ -370,17 +374,18 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
AddPortMappingArgs[6].val = desc?desc:"libminiupnpc";
AddPortMappingArgs[7].elt = "NewLeaseDuration";
AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0";
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"AddPortMapping", AddPortMappingArgs,
&bufsize))) {
free(AddPortMappingArgs);
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"AddPortMapping", AddPortMappingArgs,
&bufsize);
free(AddPortMappingArgs);
if(!buffer) {
return UPNPCOMMAND_HTTP_ERROR;
}
/*DisplayNameValueList(buffer, bufsize);*/
/*buffer[bufsize] = '\0';*/
/*puts(buffer);*/
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
free(buffer);
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal) {
/*printf("AddPortMapping errorCode = '%s'\n", resVal); */
@ -390,11 +395,79 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
free(AddPortMappingArgs);
return ret;
}
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype,
const char * extPort,
const char * inPort,
const char * inClient,
const char * desc,
const char * proto,
const char * remoteHost,
const char * leaseDuration,
char * reservedPort)
{
struct UPNParg * AddPortMappingArgs;
char * buffer;
int bufsize;
struct NameValueParserData pdata;
const char * resVal;
int ret;
if(!inPort || !inClient || !proto || !extPort)
return UPNPCOMMAND_INVALID_ARGS;
AddPortMappingArgs = calloc(9, sizeof(struct UPNParg));
if(AddPortMappingArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
AddPortMappingArgs[0].elt = "NewRemoteHost";
AddPortMappingArgs[0].val = remoteHost;
AddPortMappingArgs[1].elt = "NewExternalPort";
AddPortMappingArgs[1].val = extPort;
AddPortMappingArgs[2].elt = "NewProtocol";
AddPortMappingArgs[2].val = proto;
AddPortMappingArgs[3].elt = "NewInternalPort";
AddPortMappingArgs[3].val = inPort;
AddPortMappingArgs[4].elt = "NewInternalClient";
AddPortMappingArgs[4].val = inClient;
AddPortMappingArgs[5].elt = "NewEnabled";
AddPortMappingArgs[5].val = "1";
AddPortMappingArgs[6].elt = "NewPortMappingDescription";
AddPortMappingArgs[6].val = desc?desc:"libminiupnpc";
AddPortMappingArgs[7].elt = "NewLeaseDuration";
AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0";
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"AddAnyPortMapping", AddPortMappingArgs,
&bufsize);
free(AddPortMappingArgs);
if(!buffer) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
free(buffer);
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal) {
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(resVal, "%d", &ret);
} else {
char *p;
p = GetValueFromNameValueList(&pdata, "NewReservedPort");
if(p) {
strncpy(reservedPort, p, 6);
reservedPort[5] = '\0';
ret = UPNPCOMMAND_SUCCESS;
} else {
ret = UPNPCOMMAND_INVALID_RESPONSE;
}
}
ClearNameValueList(&pdata);
return ret;
}
MINIUPNP_LIBSPEC int
UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
const char * extPort, const char * proto,
const char * remoteHost)
@ -411,21 +484,24 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
return UPNPCOMMAND_INVALID_ARGS;
DeletePortMappingArgs = calloc(4, sizeof(struct UPNParg));
if(DeletePortMappingArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
DeletePortMappingArgs[0].elt = "NewRemoteHost";
DeletePortMappingArgs[0].val = remoteHost;
DeletePortMappingArgs[1].elt = "NewExternalPort";
DeletePortMappingArgs[1].val = extPort;
DeletePortMappingArgs[2].elt = "NewProtocol";
DeletePortMappingArgs[2].val = proto;
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"DeletePortMapping",
DeletePortMappingArgs, &bufsize))) {
free(DeletePortMappingArgs);
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"DeletePortMapping",
DeletePortMappingArgs, &bufsize);
free(DeletePortMappingArgs);
if(!buffer) {
return UPNPCOMMAND_HTTP_ERROR;
}
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
free(buffer);
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal) {
ret = UPNPCOMMAND_UNKNOWN_ERROR;
@ -434,11 +510,58 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
free(DeletePortMappingArgs);
return ret;
}
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype,
const char * extPortStart, const char * extPortEnd,
const char * proto,
const char * manage)
{
struct UPNParg * DeletePortMappingArgs;
char * buffer;
int bufsize;
struct NameValueParserData pdata;
const char * resVal;
int ret;
if(!extPortStart || !extPortEnd || !proto || !manage)
return UPNPCOMMAND_INVALID_ARGS;
DeletePortMappingArgs = calloc(5, sizeof(struct UPNParg));
if(DeletePortMappingArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
DeletePortMappingArgs[0].elt = "NewStartPort";
DeletePortMappingArgs[0].val = extPortStart;
DeletePortMappingArgs[1].elt = "NewEndPort";
DeletePortMappingArgs[1].val = extPortEnd;
DeletePortMappingArgs[2].elt = "NewProtocol";
DeletePortMappingArgs[2].val = proto;
DeletePortMappingArgs[3].elt = "NewManage";
DeletePortMappingArgs[3].val = manage;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"DeletePortMappingRange",
DeletePortMappingArgs, &bufsize);
free(DeletePortMappingArgs);
if(!buffer) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
free(buffer);
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal) {
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(resVal, "%d", &ret);
} else {
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
return ret;
}
MINIUPNP_LIBSPEC int
UPNP_GetGenericPortMappingEntry(const char * controlURL,
const char * servicetype,
const char * index,
@ -462,16 +585,19 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL,
intClient[0] = '\0';
intPort[0] = '\0';
GetPortMappingArgs = calloc(2, sizeof(struct UPNParg));
if(GetPortMappingArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
GetPortMappingArgs[0].elt = "NewPortMappingIndex";
GetPortMappingArgs[0].val = index;
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetGenericPortMappingEntry",
GetPortMappingArgs, &bufsize))) {
free(GetPortMappingArgs);
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetGenericPortMappingEntry",
GetPortMappingArgs, &bufsize);
free(GetPortMappingArgs);
if(!buffer) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
free(buffer);
p = GetValueFromNameValueList(&pdata, "NewRemoteHost");
if(p && rHost)
@ -493,14 +619,14 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL,
protocol[3] = '\0';
}
p = GetValueFromNameValueList(&pdata, "NewInternalClient");
if(p && intClient)
if(p)
{
strncpy(intClient, p, 16);
intClient[15] = '\0';
r = 0;
}
p = GetValueFromNameValueList(&pdata, "NewInternalPort");
if(p && intPort)
if(p)
{
strncpy(intPort, p, 6);
intPort[5] = '\0';
@ -529,11 +655,10 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL,
sscanf(p, "%d", &r);
}
ClearNameValueList(&pdata);
free(GetPortMappingArgs);
return r;
}
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_GetPortMappingNumberOfEntries(const char * controlURL,
const char * servicetype,
unsigned int * numEntries)
@ -552,7 +677,7 @@ UPNP_GetPortMappingNumberOfEntries(const char * controlURL,
DisplayNameValueList(buffer, bufsize);
#endif
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
free(buffer);
p = GetValueFromNameValueList(&pdata, "NewPortMappingNumberOfEntries");
if(numEntries && p) {
@ -574,11 +699,12 @@ UPNP_GetPortMappingNumberOfEntries(const char * controlURL,
/* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping
* the result is returned in the intClient and intPort strings
* please provide 16 and 6 bytes of data */
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_GetSpecificPortMappingEntry(const char * controlURL,
const char * servicetype,
const char * extPort,
const char * proto,
const char * proto,
const char * remoteHost,
char * intClient,
char * intPort,
char * desc,
@ -596,21 +722,24 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
return UPNPCOMMAND_INVALID_ARGS;
GetPortMappingArgs = calloc(4, sizeof(struct UPNParg));
if(GetPortMappingArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
GetPortMappingArgs[0].elt = "NewRemoteHost";
/* TODO : add remote host ? */
GetPortMappingArgs[0].val = remoteHost;
GetPortMappingArgs[1].elt = "NewExternalPort";
GetPortMappingArgs[1].val = extPort;
GetPortMappingArgs[2].elt = "NewProtocol";
GetPortMappingArgs[2].val = proto;
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetSpecificPortMappingEntry",
GetPortMappingArgs, &bufsize))) {
free(GetPortMappingArgs);
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetSpecificPortMappingEntry",
GetPortMappingArgs, &bufsize);
free(GetPortMappingArgs);
if(!buffer) {
return UPNPCOMMAND_HTTP_ERROR;
}
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
free(buffer);
p = GetValueFromNameValueList(&pdata, "NewInternalClient");
if(p) {
@ -653,7 +782,6 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
}
ClearNameValueList(&pdata);
free(GetPortMappingArgs);
return ret;
}
@ -665,7 +793,7 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
* 733 InconsistantParameters - NewStartPort and NewEndPort values are not
* consistent.
*/
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_GetListOfPortMappings(const char * controlURL,
const char * servicetype,
const char * startPort,
@ -685,6 +813,8 @@ UPNP_GetListOfPortMappings(const char * controlURL,
return UPNPCOMMAND_INVALID_ARGS;
GetListOfPortMappingsArgs = calloc(6, sizeof(struct UPNParg));
if(GetListOfPortMappingsArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
GetListOfPortMappingsArgs[0].elt = "NewStartPort";
GetListOfPortMappingsArgs[0].val = startPort;
GetListOfPortMappingsArgs[1].elt = "NewEndPort";
@ -696,17 +826,17 @@ UPNP_GetListOfPortMappings(const char * controlURL,
GetListOfPortMappingsArgs[4].elt = "NewNumberOfPorts";
GetListOfPortMappingsArgs[4].val = numberOfPorts?numberOfPorts:"1000";
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetListOfPortMappings",
GetListOfPortMappingsArgs, &bufsize))) {
free(GetListOfPortMappingsArgs);
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetListOfPortMappings",
GetListOfPortMappingsArgs, &bufsize);
free(GetListOfPortMappingsArgs);
if(!buffer) {
return UPNPCOMMAND_HTTP_ERROR;
}
free(GetListOfPortMappingsArgs);
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
free(buffer);
/*p = GetValueFromNameValueList(&pdata, "NewPortListing");*/
/*if(p) {
@ -741,16 +871,16 @@ UPNP_GetListOfPortMappings(const char * controlURL,
}
ClearNameValueList(&pdata);
//printf("%.*s", bufsize, buffer);
/*printf("%.*s", bufsize, buffer);*/
return ret;
}
/* IGD:2, functions for service WANIPv6FirewallControl:1 */
LIBSPEC int
/* IGD:2, functions for service WANIPv6FirewallControl:1 */
MINIUPNP_LIBSPEC int
UPNP_GetFirewallStatus(const char * controlURL,
const char * servicetype,
int * firewallEnabled,
int * firewallEnabled,
int * inboundPinholeAllowed)
{
struct NameValueParserData pdata;
@ -759,7 +889,7 @@ UPNP_GetFirewallStatus(const char * controlURL,
char * fe, *ipa, *p;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
if(!firewallEnabled && !inboundPinholeAllowed)
if(!firewallEnabled || !inboundPinholeAllowed)
return UPNPCOMMAND_INVALID_ARGS;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
@ -768,7 +898,7 @@ UPNP_GetFirewallStatus(const char * controlURL,
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
free(buffer);
fe = GetValueFromNameValueList(&pdata, "FirewallEnabled");
ipa = GetValueFromNameValueList(&pdata, "InboundPinholeAllowed");
if(ipa && fe)
@ -791,7 +921,7 @@ UPNP_GetFirewallStatus(const char * controlURL,
return ret;
}
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype,
const char * remoteHost,
const char * remotePort,
@ -805,13 +935,14 @@ UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype
int bufsize;
struct NameValueParserData pdata;
const char * resVal;
char * p;
int ret;
if(!intPort || !intClient || !proto || !remotePort || !remoteHost)
return UPNPCOMMAND_INVALID_ARGS;
GetOutboundPinholeTimeoutArgs = calloc(6, sizeof(struct UPNParg));
if(GetOutboundPinholeTimeoutArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
GetOutboundPinholeTimeoutArgs[0].elt = "RemoteHost";
GetOutboundPinholeTimeoutArgs[0].val = remoteHost;
GetOutboundPinholeTimeoutArgs[1].elt = "RemotePort";
@ -824,10 +955,11 @@ UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype
GetOutboundPinholeTimeoutArgs[4].val = intClient;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetOutboundPinholeTimeout", GetOutboundPinholeTimeoutArgs, &bufsize);
free(GetOutboundPinholeTimeoutArgs);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
free(buffer);
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal)
{
@ -836,17 +968,16 @@ UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype
}
else
{
ret = UPNPCOMMAND_SUCCESS;
p = GetValueFromNameValueList(&pdata, "OutboundPinholeTimeout");
const char * p = GetValueFromNameValueList(&pdata, "OutboundPinholeTimeout");
if(p)
*opTimeout = my_atoui(p);
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
free(GetOutboundPinholeTimeoutArgs);
return ret;
}
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_AddPinhole(const char * controlURL, const char * servicetype,
const char * remoteHost,
const char * remotePort,
@ -868,7 +999,9 @@ UPNP_AddPinhole(const char * controlURL, const char * servicetype,
return UPNPCOMMAND_INVALID_ARGS;
AddPinholeArgs = calloc(7, sizeof(struct UPNParg));
// RemoteHost can be wilcarded
if(AddPinholeArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
/* RemoteHost can be wilcarded */
if(strncmp(remoteHost, "empty", 5)==0)
{
AddPinholeArgs[0].elt = "RemoteHost";
@ -899,10 +1032,11 @@ UPNP_AddPinhole(const char * controlURL, const char * servicetype,
AddPinholeArgs[5].val = leaseTime;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"AddPinhole", AddPinholeArgs, &bufsize);
free(AddPinholeArgs);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
free(buffer);
p = GetValueFromNameValueList(&pdata, "UniqueID");
if(p)
{
@ -912,7 +1046,7 @@ UPNP_AddPinhole(const char * controlURL, const char * servicetype,
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal)
{
//printf("AddPortMapping errorCode = '%s'\n", resVal);
/*printf("AddPortMapping errorCode = '%s'\n", resVal);*/
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(resVal, "%d", &ret);
}
@ -921,11 +1055,10 @@ UPNP_AddPinhole(const char * controlURL, const char * servicetype,
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
free(AddPinholeArgs);
return ret;
}
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_UpdatePinhole(const char * controlURL, const char * servicetype,
const char * uniqueID,
const char * leaseTime)
@ -941,16 +1074,19 @@ UPNP_UpdatePinhole(const char * controlURL, const char * servicetype,
return UPNPCOMMAND_INVALID_ARGS;
UpdatePinholeArgs = calloc(3, sizeof(struct UPNParg));
if(UpdatePinholeArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
UpdatePinholeArgs[0].elt = "UniqueID";
UpdatePinholeArgs[0].val = uniqueID;
UpdatePinholeArgs[1].elt = "NewLeaseTime";
UpdatePinholeArgs[1].val = leaseTime;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"UpdatePinhole", UpdatePinholeArgs, &bufsize);
free(UpdatePinholeArgs);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
free(buffer);
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal)
{
@ -963,11 +1099,10 @@ UPNP_UpdatePinhole(const char * controlURL, const char * servicetype,
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
free(UpdatePinholeArgs);
return ret;
}
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID)
{
/*struct NameValueParserData pdata;*/
@ -982,15 +1117,18 @@ UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char
return UPNPCOMMAND_INVALID_ARGS;
DeletePinholeArgs = calloc(2, sizeof(struct UPNParg));
if(DeletePinholeArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
DeletePinholeArgs[0].elt = "UniqueID";
DeletePinholeArgs[0].val = uniqueID;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"DeletePinhole", DeletePinholeArgs, &bufsize);
free(DeletePinholeArgs);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
free(buffer);
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal)
{
@ -1002,11 +1140,10 @@ UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
free(DeletePinholeArgs);
return ret;
}
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype,
const char * uniqueID, int * isWorking)
{
@ -1021,14 +1158,19 @@ UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype,
return UPNPCOMMAND_INVALID_ARGS;
CheckPinholeWorkingArgs = calloc(4, sizeof(struct UPNParg));
if(CheckPinholeWorkingArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
CheckPinholeWorkingArgs[0].elt = "UniqueID";
CheckPinholeWorkingArgs[0].val = uniqueID;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"CheckPinholeWorking", CheckPinholeWorkingArgs, &bufsize);
free(CheckPinholeWorkingArgs);
if(!buffer)
{
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
free(buffer);
p = GetValueFromNameValueList(&pdata, "IsWorking");
if(p)
@ -1047,11 +1189,10 @@ UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype,
}
ClearNameValueList(&pdata);
free(CheckPinholeWorkingArgs);
return ret;
}
LIBSPEC int
MINIUPNP_LIBSPEC int
UPNP_GetPinholePackets(const char * controlURL, const char * servicetype,
const char * uniqueID, int * packets)
{
@ -1066,14 +1207,17 @@ UPNP_GetPinholePackets(const char * controlURL, const char * servicetype,
return UPNPCOMMAND_INVALID_ARGS;
GetPinholePacketsArgs = calloc(4, sizeof(struct UPNParg));
if(GetPinholePacketsArgs == NULL)
return UPNPCOMMAND_MEM_ALLOC_ERROR;
GetPinholePacketsArgs[0].elt = "UniqueID";
GetPinholePacketsArgs[0].val = uniqueID;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetPinholePackets", GetPinholePacketsArgs, &bufsize);
free(GetPinholePacketsArgs);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
free(buffer);
p = GetValueFromNameValueList(&pdata, "PinholePackets");
if(p)
@ -1090,8 +1234,5 @@ UPNP_GetPinholePackets(const char * controlURL, const char * servicetype,
}
ClearNameValueList(&pdata);
free(GetPinholePacketsArgs);
return ret;
}

View file

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

View file

@ -1,9 +1,10 @@
/* $Id: upnperrors.c,v 1.5 2011/04/10 11:19:36 nanard Exp $ */
/* Project : miniupnp
/* $Id: upnperrors.c,v 1.11 2023/05/29 21:59:15 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* Project : miniupnp
* Author : Thomas BERNARD
* copyright (c) 2007 Thomas Bernard
* copyright (c) 2007-2023 Thomas Bernard
* All Right reserved.
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
* This software is subjet to the conditions detailed in the
* provided LICENCE file. */
#include <string.h>
@ -24,10 +25,17 @@ const char * strupnperror(int err)
case UPNPCOMMAND_INVALID_ARGS:
s = "Miniupnpc Invalid Arguments";
break;
case UPNPCOMMAND_INVALID_RESPONSE:
s = "Miniupnpc Invalid response";
break;
case UPNPCOMMAND_HTTP_ERROR:
s = "Miniupnpc HTTP error";
break;
case UPNPDISCOVER_SOCKET_ERROR:
s = "Miniupnpc Socket error";
break;
case UPNPDISCOVER_MEMORY_ERROR:
case UPNPCOMMAND_MEM_ALLOC_ERROR:
s = "Miniupnpc Memory allocation error";
break;
case 401:
@ -39,6 +47,24 @@ const char * strupnperror(int err)
case 501:
s = "Action Failed";
break;
case 600:
s = "Argument Value Invalid";
break;
case 601:
s = "Argument Value Out of Range";
break;
case 602:
s = "Optional Action Not Implemented";
break;
case 603:
s = "Out of Memory";
break;
case 604:
s = "Human Intervention Required";
break;
case 605:
s = "String Argument Too Long";
break;
case 606:
s = "Action not authorized";
break;
@ -64,7 +90,7 @@ const char * strupnperror(int err)
s = "ProtocolWildcardingNotAllowed";
break;
case 708:
s = "WildcardNotPermittedInSrcIP";
s = "InvalidLayer2Address";
break;
case 709:
s = "NoPacketSent";
@ -97,7 +123,8 @@ const char * strupnperror(int err)
s = "ExternalPortOnlySupportsWildcard";
break;
default:
s = NULL;
s = "UnknownError";
break;
}
return s;
}

View file

@ -1,7 +1,8 @@
/* $Id: upnpreplyparse.c,v 1.11 2011/02/07 16:17:06 nanard Exp $ */
/* MiniUPnP project
/* $Id: upnpreplyparse.c,v 1.21 2019/04/08 13:30:51 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2011 Thomas Bernard
* (c) 2006-2019 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -15,25 +16,77 @@
static void
NameValueParserStartElt(void * d, const char * name, int l)
{
struct NameValueParserData * data = (struct NameValueParserData *)d;
struct NameValueParserData * data = (struct NameValueParserData *)d;
data->topelt = 1;
if(l>63)
l = 63;
memcpy(data->curelt, name, l);
data->curelt[l] = '\0';
data->cdata = NULL;
data->cdatalen = 0;
}
static void
NameValueParserEndElt(void * d, const char * name, int namelen)
{
struct NameValueParserData * data = (struct NameValueParserData *)d;
struct NameValue * nv;
(void)name;
(void)namelen;
if(!data->topelt)
return;
if(strcmp(data->curelt, "NewPortListing") != 0)
{
int l;
/* standard case. Limited to n chars strings */
l = data->cdatalen;
nv = malloc(sizeof(struct NameValue));
if(nv == NULL)
{
/* malloc error */
#ifdef DEBUG
fprintf(stderr, "%s: error allocating memory",
"NameValueParserEndElt");
#endif /* DEBUG */
return;
}
if(l>=(int)sizeof(nv->value))
l = sizeof(nv->value) - 1;
strncpy(nv->name, data->curelt, 64);
nv->name[63] = '\0';
if(data->cdata != NULL)
{
memcpy(nv->value, data->cdata, l);
nv->value[l] = '\0';
}
else
{
nv->value[0] = '\0';
}
nv->l_next = data->l_head; /* insert in list */
data->l_head = nv;
}
data->cdata = NULL;
data->cdatalen = 0;
data->topelt = 0;
}
static void
NameValueParserGetData(void * d, const char * datas, int l)
{
struct NameValueParserData * data = (struct NameValueParserData *)d;
struct NameValue * nv;
if(strcmp(data->curelt, "NewPortListing") == 0)
{
/* specific case for NewPortListing which is a XML Document */
free(data->portListing);
data->portListing = malloc(l + 1);
if(!data->portListing)
{
/* malloc error */
#ifdef DEBUG
fprintf(stderr, "%s: error allocating memory",
"NameValueParserGetData");
#endif /* DEBUG */
return;
}
memcpy(data->portListing, datas, l);
@ -42,15 +95,9 @@ NameValueParserGetData(void * d, const char * datas, int l)
}
else
{
/* standard case. Limited to 63 chars strings */
nv = malloc(sizeof(struct NameValue));
if(l>63)
l = 63;
strncpy(nv->name, data->curelt, 64);
nv->name[63] = '\0';
memcpy(nv->value, datas, l);
nv->value[l] = '\0';
LIST_INSERT_HEAD( &(data->head), nv, entries);
/* standard case. */
data->cdata = datas;
data->cdatalen = l;
}
}
@ -58,19 +105,17 @@ void
ParseNameValue(const char * buffer, int bufsize,
struct NameValueParserData * data)
{
struct xmlparser parser;
LIST_INIT(&(data->head));
data->portListing = NULL;
data->portListingLength = 0;
/* init xmlparser object */
parser.xmlstart = buffer;
parser.xmlsize = bufsize;
parser.data = data;
parser.starteltfunc = NameValueParserStartElt;
parser.endeltfunc = 0;
parser.datafunc = NameValueParserGetData;
struct xmlparser parser;
memset(data, 0, sizeof(struct NameValueParserData));
/* init xmlparser object */
parser.xmlstart = buffer;
parser.xmlsize = bufsize;
parser.data = data;
parser.starteltfunc = NameValueParserStartElt;
parser.endeltfunc = NameValueParserEndElt;
parser.datafunc = NameValueParserGetData;
parser.attfunc = 0;
parsexml(&parser);
parsexml(&parser);
}
void
@ -83,22 +128,22 @@ ClearNameValueList(struct NameValueParserData * pdata)
pdata->portListing = NULL;
pdata->portListingLength = 0;
}
while((nv = pdata->head.lh_first) != NULL)
while((nv = pdata->l_head) != NULL)
{
LIST_REMOVE(nv, entries);
pdata->l_head = nv->l_next;
free(nv);
}
}
char *
char *
GetValueFromNameValueList(struct NameValueParserData * pdata,
const char * Name)
{
struct NameValue * nv;
char * p = NULL;
for(nv = pdata->head.lh_first;
for(nv = pdata->l_head;
(nv != NULL) && (p == NULL);
nv = nv->entries.le_next)
nv = nv->l_next)
{
if(strcmp(nv->name, Name) == 0)
p = nv->value;
@ -131,7 +176,7 @@ GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
}
#endif
/* debug all-in-one function
/* debug all-in-one function
* do parsing then display to stdout */
#ifdef DEBUG
void
@ -140,13 +185,13 @@ DisplayNameValueList(char * buffer, int bufsize)
struct NameValueParserData pdata;
struct NameValue * nv;
ParseNameValue(buffer, bufsize, &pdata);
for(nv = pdata.head.lh_first;
for(nv = pdata.l_head;
nv != NULL;
nv = nv->entries.le_next)
nv = nv->l_next)
{
printf("%s = %s\n", nv->name, nv->value);
}
ClearNameValueList(&pdata);
}
#endif
#endif /* DEBUG */

View file

@ -0,0 +1,71 @@
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* MiniUPnP project
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
* (c) 2020 Pali Rohár
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#ifndef WIN32_SNPRINTF_H
#define WIN32_SNPRINTF_H
#ifdef _WIN32
#include <stdio.h>
/* snprintf is supported by:
* - Visual Studio 2015 or new
* - mingw32 with iso c ext
* - mingw-w64 with ansi stdio
* - mingw-w64 6.0.0 or new with ucrt
* - mingw-w64 8.0.0 or new with iso c ext
*/
#if ( \
(defined(_MSC_VER) && _MSC_VER < 1900) /* Visual Studio older than 2015 */ || \
(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) && defined(__NO_ISOCEXT)) /* mingw32 without iso c ext */ || \
(defined(__MINGW64_VERSION_MAJOR) && /* mingw-w64 not ... */ !( \
(defined (__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO != 0)) /* ... with ansi stdio */ || \
(__MINGW64_VERSION_MAJOR >= 6 && defined(_UCRT)) /* ... at least 6.0.0 with ucrt */ || \
(__MINGW64_VERSION_MAJOR >= 8 && !defined(__NO_ISOCEXT)) /* ... at least 8.0.0 with iso c ext */ || \
0) || \
0)
/* _scprintf is supported by:
* - Visual Studio 2002 or new
* - msvcr70.dll or new
* - msvcrt.dll on Windows XP or new
*/
#if ( \
(defined(_MSC_VER) && _MSC_VER < 1300) /* Visual Studio older than 2002 */ || \
(defined(__MSVCRT_VERSION__) && __MSVCRT_VERSION__ < 0x700) /* msvcrt older than 7.0 */ || \
0)
#define CHECK_SCPRINTF 0
#define IF_SCPRINTF(expr) 0
#define ELSE_SCPRINTF(expr) expr
#else
#define CHECK_SCPRINTF 1
#define IF_SCPRINTF(expr) expr
#define ELSE_SCPRINTF(expr) 0
#endif
/* Emulation of snprintf for win32 */
#define snprintf(buf, size, fmt, ...) ( \
(((size) != 0 && (buf) != NULL) ? ( /* _snprintf does not work with NULL buffer */ \
_snprintf((buf), (size), (fmt), __VA_ARGS__), /* _snprintf returns -1 on overflow, so ignore its value */ \
(((char *)buf)[(size_t)(size)-1] = 0), /* _snprintf does not fill nul byte on overflow */ \
0) : 0), \
(CHECK_SCPRINTF ? IF_SCPRINTF( \
_scprintf((fmt), __VA_ARGS__) /* calculate return value for snprintf via _scprintf */ \
) : ELSE_SCPRINTF( \
((size) != 0 && (buf) != NULL) ? \
strlen((buf)) /* return just length of buffer */ \
: \
1 /* no buffer, impossible to calculate, return just non-zero number */ \
) \
) \
)
#endif
#endif /* _WIN32 */
#endif /* WIN32_SNPRINTF_H */

Some files were not shown because too many files have changed in this diff Show more