mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-04-24 14:24:54 +00:00
Merge 946de7679c
into 879a8889aa
This commit is contained in:
commit
dfefb23afe
53 changed files with 6440 additions and 1347 deletions
345
Externals/miniupnpc/CMakeLists.txt
vendored
345
Externals/miniupnpc/CMakeLists.txt
vendored
|
@ -1,39 +1,318 @@
|
|||
cmake_minimum_required(VERSION 2.8.12)
|
||||
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
|
||||
|
||||
project(miniupnpc C)
|
||||
set(MINIUPNPC_VERSION 1.9)
|
||||
set(MINIUPNPC_API_VERSION 14)
|
||||
project (miniupnpc
|
||||
VERSION 2.3.2
|
||||
DESCRIPTION "UPnP IGD client lightweight library"
|
||||
HOMEPAGE_URL https://miniupnp.tuxfamily.org/
|
||||
LANGUAGES C)
|
||||
|
||||
if(UNIX)
|
||||
add_definitions(-DMINIUPNPC_SET_SOCKET_TIMEOUT)
|
||||
add_definitions(-D_BSD_SOURCE -D_POSIX_C_SOURCE=1)
|
||||
elseif(WIN32)
|
||||
add_definitions(-D_WIN32_WINNT=0x0501)
|
||||
find_library(WINSOCK2_LIBRARY NAMES ws2_32 WS2_32 Ws2_32)
|
||||
find_library(IPHLPAPI_LIBRARY NAMES iphlpapi)
|
||||
set(LDLIBS ${WINSOCK2_LIBRARY} ${IPHLPAPI_LIBRARY} ${LDLIBS})
|
||||
set (MINIUPNPC_API_VERSION 20)
|
||||
|
||||
option (UPNPC_BUILD_STATIC "Build static library" TRUE)
|
||||
option (UPNPC_BUILD_SHARED "Build shared library" FALSE)
|
||||
option (UPNPC_BUILD_TESTS "Build test executables" FALSE)
|
||||
option (UPNPC_BUILD_SAMPLE "Build sample executables" FALSE)
|
||||
option (NO_GETADDRINFO "Define NO_GETADDRINFO" FALSE)
|
||||
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 ()
|
||||
|
||||
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
|
||||
MINIUPNPC_GET_SRC_ADDR
|
||||
_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 ()
|
||||
set (MINIUPNPC_TARGET_WINDOWS_VERSION "0x0501" CACHE STRING "Minimum target Windows version as hex string") # XP or higher for getnameinfo and friends
|
||||
if (MINIUPNPC_TARGET_WINDOWS_VERSION)
|
||||
target_compile_definitions(miniupnpc-private INTERFACE _WIN32_WINNT=${MINIUPNPC_TARGET_WINDOWS_VERSION})
|
||||
endif ()
|
||||
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()
|
||||
|
||||
if(APPLE)
|
||||
add_definitions(-DMACOSX -D_DARWIN_C_SOURCE)
|
||||
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 (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})
|
||||
|
||||
add_executable (upnp-listdevices-static src/listdevices.c)
|
||||
target_link_libraries (upnp-listdevices-static PRIVATE libminiupnpc-static)
|
||||
target_include_directories(upnp-listdevices-static PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
if (NOT UPNPC_NO_INSTALL)
|
||||
install (TARGETS upnpc-static upnp-listdevices-static
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
endif()
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (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})
|
||||
|
||||
add_executable (upnp-listdevices-shared src/listdevices.c)
|
||||
target_link_libraries (upnp-listdevices-shared PRIVATE libminiupnpc-shared)
|
||||
target_include_directories(upnp-listdevices-shared PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
if (NOT UPNPC_NO_INSTALL)
|
||||
install (TARGETS upnpc-shared upnp-listdevices-shared
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
endif()
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (UPNPC_BUILD_TESTS)
|
||||
add_library(miniupnpc-tests INTERFACE)
|
||||
target_link_libraries(miniupnpc-tests INTERFACE miniupnpc-private)
|
||||
target_compile_definitions(miniupnpc-tests INTERFACE MINIUPNP_STATICLIB)
|
||||
|
||||
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 (minixmlvalid src/minixmlvalid.c src/minixml.c)
|
||||
target_link_libraries (minixmlvalid PRIVATE miniupnpc-tests)
|
||||
|
||||
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_include_directories (testigddescparse PRIVATE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
|
||||
target_link_libraries (testigddescparse PRIVATE miniupnpc-tests)
|
||||
|
||||
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_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)
|
||||
|
||||
if (NOT WIN32)
|
||||
add_executable (minihttptestserver src/minihttptestserver.c)
|
||||
endif()
|
||||
|
||||
# set (UPNPC_INSTALL_TARGETS ${UPNPC_INSTALL_TARGETS} testminixml minixmlvalid testupnpreplyparse testigddescparse testminiwget)
|
||||
include(CTest)
|
||||
add_test(NAME validateminixml
|
||||
COMMAND minixmlvalid)
|
||||
add_test(NAME validateminiwget
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/testminiwget.sh)
|
||||
if (NOT WIN32)
|
||||
set_property(TEST validateminiwget
|
||||
PROPERTY ENVIRONMENT
|
||||
TESTSERVER=${CMAKE_BINARY_DIR}/minihttptestserver
|
||||
TESTMINIWGET=${CMAKE_BINARY_DIR}/testminiwget)
|
||||
endif()
|
||||
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 ()
|
||||
|
||||
configure_file(miniupnpc.pc.in miniupnpc.pc @ONLY)
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
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()
|
||||
|
||||
set(SRCS 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)
|
||||
|
||||
add_library(miniupnpc STATIC ${SRCS})
|
||||
dolphin_disable_warnings(miniupnpc)
|
||||
target_include_directories(miniupnpc PUBLIC src)
|
||||
|
||||
add_library(Miniupnpc::miniupnpc ALIAS miniupnpc)
|
||||
# vim: ts=2:sw=2:expandtab
|
||||
|
|
195
Externals/miniupnpc/Changelog.txt
vendored
195
Externals/miniupnpc/Changelog.txt
vendored
|
@ -1,6 +1,197 @@
|
|||
$Id: Changelog.txt,v 1.215 2015/10/01 09:26:11 nanard Exp $
|
||||
$Id: Changelog.txt,v 1.276 2025/03/05 10:29:50 nanard Exp $
|
||||
miniUPnP client Changelog.
|
||||
|
||||
VERSION 2.3.2 : released 2025/03/05
|
||||
|
||||
2025/02/24:
|
||||
remove STRTOUI from public headers
|
||||
remove parseURL() from public headers
|
||||
remove struct NameValue from upnpreplyparse.h and use flexible array member
|
||||
Increments API_VERSION to 20
|
||||
|
||||
VERSION 2.3.1 : released 2025/02/23
|
||||
|
||||
2025/02/23:
|
||||
allocate argument arrays on stack instead of heap in upnpcommand.c
|
||||
|
||||
2025/02/09:
|
||||
doxygen documentation of the public headers
|
||||
|
||||
VERSION 2.3.0 : released 2025/01/11
|
||||
|
||||
2025/01/10:
|
||||
Change simpleUPnPcommand() prototype to remove unused first argument
|
||||
Increments API_VERSION to 19
|
||||
|
||||
2024/07/27:
|
||||
Add #define for UPNP_GetValidIGD() return values
|
||||
|
||||
VERSION 2.2.8 : released 2024/06/09
|
||||
|
||||
2024/05/16:
|
||||
IPv6: try site-local before link-local
|
||||
|
||||
2024/05/08:
|
||||
upnpc.c: Add -f option to upnpc program (delete multiple port redirections)
|
||||
UPNP_GetValidIGD(): distinguish between not connected and connected to a
|
||||
"private" network (with a reserved IP address).
|
||||
Increments API_VERSION to 18
|
||||
|
||||
VERSION 2.2.7 : released 2024/03/20
|
||||
|
||||
2024/01/15:
|
||||
listdevices.c: exit with status code 1 if no UPNP device is found
|
||||
|
||||
2024/01/07:
|
||||
upnpc.c: reformat Usage
|
||||
|
||||
VERSION 2.2.6 : released 2024/01/04
|
||||
|
||||
2024/01/04:
|
||||
includes charset="utf-8" in Content-Type
|
||||
fix memory allocation error in minissdpc.c
|
||||
|
||||
2023/06/15:
|
||||
Make User-Agent compliant.
|
||||
listdevices => upnp-listdevices
|
||||
|
||||
VERSION 2.2.5 : released 2023/06/12
|
||||
|
||||
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
|
||||
|
@ -565,7 +756,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
|
||||
|
|
28
Externals/miniupnpc/LICENSE
vendored
28
Externals/miniupnpc/LICENSE
vendored
|
@ -1,27 +1 @@
|
|||
MiniUPnPc
|
||||
Copyright (c) 2005-2015, Thomas BERNARD
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
../LICENSE
|
44
Externals/miniupnpc/README
vendored
44
Externals/miniupnpc/README
vendored
|
@ -1,23 +1,19 @@
|
|||
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
|
||||
freecode: http://freecode.com/projects/miniupnp
|
||||
Author: Thomas Bernard
|
||||
Copyright (c) 2005-2012 Thomas Bernard
|
||||
Copyright (c) 2005-2025 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 - 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.
|
||||
|
@ -37,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()
|
||||
|
@ -62,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
|
||||
|
|
2
Externals/miniupnpc/VERSION
vendored
2
Externals/miniupnpc/VERSION
vendored
|
@ -1 +1 @@
|
|||
1.9
|
||||
2.3.2
|
||||
|
|
42
Externals/miniupnpc/apiversions.txt
vendored
42
Externals/miniupnpc/apiversions.txt
vendored
|
@ -1,7 +1,45 @@
|
|||
$Id: apiversions.txt,v 1.7 2015/07/23 20:40:08 nanard Exp $
|
||||
$Id: apiversions.txt,v 1.14 2025/03/05 10:29:51 nanard Exp $
|
||||
|
||||
Differences in API between miniUPnPc versions
|
||||
|
||||
API version 20
|
||||
cleanup : remove STRTOUI and parseURL() from public headers
|
||||
remove struct NameValue from upnpreplyparse.h
|
||||
updated macro :
|
||||
#define MINIUPNPC_API_VERSION 20
|
||||
This more a cleanup than a real API change. Things that were removed
|
||||
from public headers were not supposed to be used and/or not
|
||||
exposed in the dll export list.
|
||||
|
||||
API version 19
|
||||
change simpleUPnPcommand() prototype
|
||||
updated macro :
|
||||
#define MINIUPNPC_API_VERSION 19
|
||||
|
||||
API version 18
|
||||
change UPNP_GetValidIGD() prototype and return values
|
||||
updated macro :
|
||||
#define MINIUPNPC_API_VERSION 18
|
||||
|
||||
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()
|
||||
|
@ -9,6 +47,8 @@ miniupnpc.h
|
|||
getDevicesFromMiniSSDPD() :
|
||||
connectToMiniSSDPD() / disconnectFromMiniSSDPD()
|
||||
requestDevicesFromMiniSSDPD() / receiveDevicesFromMiniSSDPD()
|
||||
updated macro :
|
||||
#define MINIUPNPC_API_VERSION 14
|
||||
|
||||
API version 13
|
||||
miniupnpc.h:
|
||||
|
|
75
Externals/miniupnpc/include/igd_desc_parse.h
vendored
Normal file
75
Externals/miniupnpc/include/igd_desc_parse.h
vendored
Normal file
|
@ -0,0 +1,75 @@
|
|||
/* $Id: igd_desc_parse.h,v 1.14 2025/02/08 23:15:16 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005-2025 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution.
|
||||
* */
|
||||
#ifndef IGD_DESC_PARSE_H_INCLUDED
|
||||
#define IGD_DESC_PARSE_H_INCLUDED
|
||||
|
||||
/*! \file igd_desc_parse.h
|
||||
* \brief API to parse UPNP device description XML
|
||||
* \todo should not be exposed in the public API
|
||||
*/
|
||||
|
||||
/*! \brief maximum lenght of URLs */
|
||||
#define MINIUPNPC_URL_MAXSIZE (128)
|
||||
|
||||
/*! \brief Structure to store the result of the parsing of UPnP
|
||||
* descriptions of Internet Gateway Devices services */
|
||||
struct IGDdatas_service {
|
||||
/*! \brief controlURL for the service */
|
||||
char controlurl[MINIUPNPC_URL_MAXSIZE];
|
||||
/*! \brief eventSubURL for the service */
|
||||
char eventsuburl[MINIUPNPC_URL_MAXSIZE];
|
||||
/*! \brief SCPDURL for the service */
|
||||
char scpdurl[MINIUPNPC_URL_MAXSIZE];
|
||||
/*! \brief serviceType */
|
||||
char servicetype[MINIUPNPC_URL_MAXSIZE];
|
||||
/*char devicetype[MINIUPNPC_URL_MAXSIZE];*/
|
||||
};
|
||||
|
||||
/*! \brief Structure to store the result of the parsing of UPnP
|
||||
* descriptions of Internet Gateway Devices */
|
||||
struct IGDdatas {
|
||||
/*! \brief current element name */
|
||||
char cureltname[MINIUPNPC_URL_MAXSIZE];
|
||||
/*! \brief URLBase */
|
||||
char urlbase[MINIUPNPC_URL_MAXSIZE];
|
||||
/*! \brief presentationURL */
|
||||
char presentationurl[MINIUPNPC_URL_MAXSIZE];
|
||||
/*! \brief depth into the XML tree */
|
||||
int level;
|
||||
/*! \brief "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */
|
||||
struct IGDdatas_service CIF;
|
||||
/*! \brief first of "urn:schemas-upnp-org:service:WANIPConnection:1"
|
||||
* or "urn:schemas-upnp-org:service:WANPPPConnection:1" */
|
||||
struct IGDdatas_service first;
|
||||
/*! \brief second of "urn:schemas-upnp-org:service:WANIPConnection:1"
|
||||
* or "urn:schemas-upnp-org:service:WANPPPConnection:1" */
|
||||
struct IGDdatas_service second;
|
||||
/*! \brief "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1" */
|
||||
struct IGDdatas_service IPv6FC;
|
||||
/*! \brief currently parsed service */
|
||||
struct IGDdatas_service tmp;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief XML start element handler
|
||||
*/
|
||||
void IGDstartelt(void *, const char *, int);
|
||||
/*!
|
||||
* \brief XML end element handler
|
||||
*/
|
||||
void IGDendelt(void *, const char *, int);
|
||||
/*!
|
||||
* \brief XML characted data handler
|
||||
*/
|
||||
void IGDdata(void *, const char *, int);
|
||||
#ifdef DEBUG
|
||||
void printIGD(struct IGDdatas *);
|
||||
#endif /* DEBUG */
|
||||
|
||||
#endif /* IGD_DESC_PARSE_H_INCLUDED */
|
303
Externals/miniupnpc/include/miniupnpc.h
vendored
Normal file
303
Externals/miniupnpc/include/miniupnpc.h
vendored
Normal file
|
@ -0,0 +1,303 @@
|
|||
/* $Id: miniupnpc.h,v 1.76 2025/03/05 10:35:57 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-2025 Thomas Bernard
|
||||
* This software is subjects to the conditions detailed
|
||||
* in the LICENCE file provided within this distribution */
|
||||
#ifndef MINIUPNPC_H_INCLUDED
|
||||
#define MINIUPNPC_H_INCLUDED
|
||||
|
||||
/*! \file miniupnpc.h
|
||||
* \brief Main C API for MiniUPnPc
|
||||
*
|
||||
* Contains functions to discover devices and check for device validity
|
||||
* or connectivity.
|
||||
*
|
||||
* \mainpage MiniUPnPc API documentation
|
||||
* MiniUPnPc (MiniUPnP client) is a library implementing a UPnP
|
||||
* Internet Gateway Device (IGD) control point.
|
||||
*
|
||||
* It should be used by applications that needs to listen to incoming
|
||||
* traffic from the internet which are running on a LAN where a
|
||||
* UPnP IGD is running on the router (or gateway).
|
||||
*
|
||||
* See more documentation on the website http://miniupnp.free.fr
|
||||
* or https://miniupnp.tuxfamily.org/ or GitHub :
|
||||
* https://github.com/miniupnp/miniupnp/tree/master/miniupnpc
|
||||
*/
|
||||
#include "miniupnpc_declspec.h"
|
||||
#include "igd_desc_parse.h"
|
||||
#include "upnpdev.h"
|
||||
|
||||
/* error codes : */
|
||||
/*! \brief value for success */
|
||||
#define UPNPDISCOVER_SUCCESS (0)
|
||||
/*! \brief value for unknown error */
|
||||
#define UPNPDISCOVER_UNKNOWN_ERROR (-1)
|
||||
/*! \brief value for a socket error */
|
||||
#define UPNPDISCOVER_SOCKET_ERROR (-101)
|
||||
/*! \brief value for a memory allocation error */
|
||||
#define UPNPDISCOVER_MEMORY_ERROR (-102)
|
||||
|
||||
/*! \brief software version */
|
||||
#define MINIUPNPC_VERSION "2.3.2"
|
||||
/*! \brief C API version */
|
||||
#define MINIUPNPC_API_VERSION 20
|
||||
|
||||
/*! \brief any (ie system chosen) port */
|
||||
#define UPNP_LOCAL_PORT_ANY 0
|
||||
/*! \brief Use as an alias for 1900 for backwards compatibility */
|
||||
#define UPNP_LOCAL_PORT_SAME 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Structures definitions : */
|
||||
|
||||
/*!
|
||||
* \brief UPnP method argument
|
||||
*/
|
||||
struct UPNParg {
|
||||
const char * elt; /*!< \brief UPnP argument name */
|
||||
const char * val; /*!< \brief UPnP argument value */
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief execute a UPnP method (SOAP action)
|
||||
*
|
||||
* \param[in] url Control URL for the service
|
||||
* \param[in] service service to use
|
||||
* \param[in] action action to call
|
||||
* \param[in] args action arguments
|
||||
* \param[out] bufsize the size of the returned buffer
|
||||
* \return NULL in case of error or the raw XML response
|
||||
*/
|
||||
char *
|
||||
simpleUPnPcommand(const char * url, const char * service,
|
||||
const char * action, const struct UPNParg * args,
|
||||
int * bufsize);
|
||||
|
||||
/*!
|
||||
* \brief Discover UPnP IGD on the network.
|
||||
*
|
||||
* The discovered devices are returned as a chained list.
|
||||
* It is up to the caller to free the list with freeUPNPDevlist().
|
||||
* If available, device list will be obtained from MiniSSDPd.
|
||||
*
|
||||
* \param[in] delay (in millisecond) maximum time for waiting any device
|
||||
* response
|
||||
* \param[in] multicastif If not NULL, used instead of the default
|
||||
* multicast interface for sending SSDP discover packets
|
||||
* \param[in] minissdpdsock Path to minissdpd socket, default is used if
|
||||
* NULL
|
||||
* \param[in] localport Source port to send SSDP packets.
|
||||
* #UPNP_LOCAL_PORT_SAME for 1900 (same as destination port)
|
||||
* #UPNP_LOCAL_PORT_ANY to let system assign a source port
|
||||
* \param[in] ipv6 0 for IPv4, 1 of IPv6
|
||||
* \param[in] ttl should default to 2 as advised by UDA 1.1
|
||||
* \param[out] error error code when NULL is returned
|
||||
* \return NULL or a linked list
|
||||
*/
|
||||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
upnpDiscover(int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error);
|
||||
|
||||
/*!
|
||||
* \brief Discover all UPnP devices on the network
|
||||
*
|
||||
* search for "ssdp:all"
|
||||
* \param[in] delay (in millisecond) maximum time for waiting any device
|
||||
* response
|
||||
* \param[in] multicastif If not NULL, used instead of the default
|
||||
* multicast interface for sending SSDP discover packets
|
||||
* \param[in] minissdpdsock Path to minissdpd socket, default is used if
|
||||
* NULL
|
||||
* \param[in] localport Source port to send SSDP packets.
|
||||
* #UPNP_LOCAL_PORT_SAME for 1900 (same as destination port)
|
||||
* #UPNP_LOCAL_PORT_ANY to let system assign a source port
|
||||
* \param[in] ipv6 0 for IPv4, 1 of IPv6
|
||||
* \param[in] ttl should default to 2 as advised by UDA 1.1
|
||||
* \param[out] error error code when NULL is returned
|
||||
* \return NULL or a linked list
|
||||
*/
|
||||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
upnpDiscoverAll(int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error);
|
||||
|
||||
/*!
|
||||
* \brief Discover one type of UPnP devices
|
||||
*
|
||||
* \param[in] device device type to search
|
||||
* \param[in] delay (in millisecond) maximum time for waiting any device
|
||||
* response
|
||||
* \param[in] multicastif If not NULL, used instead of the default
|
||||
* multicast interface for sending SSDP discover packets
|
||||
* \param[in] minissdpdsock Path to minissdpd socket, default is used if
|
||||
* NULL
|
||||
* \param[in] localport Source port to send SSDP packets.
|
||||
* #UPNP_LOCAL_PORT_SAME for 1900 (same as destination port)
|
||||
* #UPNP_LOCAL_PORT_ANY to let system assign a source port
|
||||
* \param[in] ipv6 0 for IPv4, 1 of IPv6
|
||||
* \param[in] ttl should default to 2 as advised by UDA 1.1
|
||||
* \param[out] error error code when NULL is returned
|
||||
* \return NULL or a linked list
|
||||
*/
|
||||
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);
|
||||
|
||||
/*!
|
||||
* \brief Discover one or several type of UPnP devices
|
||||
*
|
||||
* \param[in] deviceTypes array of device types to search (ending with NULL)
|
||||
* \param[in] delay (in millisecond) maximum time for waiting any device
|
||||
* response
|
||||
* \param[in] multicastif If not NULL, used instead of the default
|
||||
* multicast interface for sending SSDP discover packets
|
||||
* \param[in] minissdpdsock Path to minissdpd socket, default is used if
|
||||
* NULL
|
||||
* \param[in] localport Source port to send SSDP packets.
|
||||
* #UPNP_LOCAL_PORT_SAME for 1900 (same as destination port)
|
||||
* #UPNP_LOCAL_PORT_ANY to let system assign a source port
|
||||
* \param[in] ipv6 0 for IPv4, 1 of IPv6
|
||||
* \param[in] ttl should default to 2 as advised by UDA 1.1
|
||||
* \param[out] error error code when NULL is returned
|
||||
* \param[in] searchalltypes 0 to stop with the first type returning results
|
||||
* \return NULL or a linked list
|
||||
*/
|
||||
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);
|
||||
|
||||
/*!
|
||||
* \brief parse root XML description of a UPnP device
|
||||
*
|
||||
* fill the IGDdatas structure.
|
||||
* \param[in] buffer character buffer containing the XML description
|
||||
* \param[in] bufsize size in bytes of the buffer
|
||||
* \param[out] data IGDdatas structure to fill
|
||||
*/
|
||||
MINIUPNP_LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data);
|
||||
|
||||
/*!
|
||||
* \brief structure used to get fast access to urls
|
||||
*/
|
||||
struct UPNPUrls {
|
||||
/*! \brief controlURL of the WANIPConnection */
|
||||
char * controlURL;
|
||||
/*! \brief url of the description of the WANIPConnection */
|
||||
char * ipcondescURL;
|
||||
/*! \brief controlURL of the WANCommonInterfaceConfig */
|
||||
char * controlURL_CIF;
|
||||
/*! \brief controlURL of the WANIPv6FirewallControl */
|
||||
char * controlURL_6FC;
|
||||
/*! \brief url of the root description */
|
||||
char * rootdescURL;
|
||||
};
|
||||
|
||||
/*! \brief NO IGD found */
|
||||
#define UPNP_NO_IGD (0)
|
||||
/*! \brief valid and connected IGD */
|
||||
#define UPNP_CONNECTED_IGD (1)
|
||||
/*! \brief valid and connected IGD but with a reserved address
|
||||
* (non routable) */
|
||||
#define UPNP_PRIVATEIP_IGD (2)
|
||||
/*! \brief valid but not connected IGD */
|
||||
#define UPNP_DISCONNECTED_IGD (3)
|
||||
/*! \brief UPnP device not recognized as an IGD */
|
||||
#define UPNP_UNKNOWN_DEVICE (4)
|
||||
|
||||
/*!
|
||||
* \brief look for a valid and possibly connected IGD in the list
|
||||
*
|
||||
* 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.
|
||||
* \param[in] devlist A device list obtained with upnpDiscover() /
|
||||
* upnpDiscoverAll() / upnpDiscoverDevice() / upnpDiscoverDevices()
|
||||
* \param[out] urls Urls for the IGD found
|
||||
* \param[out] data datas for the IGD found
|
||||
* \param[out] lanaddr buffer to copy the local address of the host to reach the IGD
|
||||
* \param[in] lanaddrlen size of the lanaddr buffer
|
||||
* \param[out] wanaddr buffer to copy the public address of the IGD
|
||||
* \param[in] wanaddrlen size of the wanaddr buffer
|
||||
* \return #UPNP_NO_IGD / #UPNP_CONNECTED_IGD / #UPNP_PRIVATEIP_IGD /
|
||||
* #UPNP_DISCONNECTED_IGD / #UPNP_UNKNOWN_DEVICE
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetValidIGD(struct UPNPDev * devlist,
|
||||
struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
char * lanaddr, int lanaddrlen,
|
||||
char * wanaddr, int wanaddrlen);
|
||||
|
||||
/*!
|
||||
* \brief Get IGD URLs and data for URL
|
||||
*
|
||||
* Used when skipping the discovery process.
|
||||
* \param[in] rootdescurl Root description URL of the device
|
||||
* \param[out] urls Urls for the IGD found
|
||||
* \param[out] data datas for the IGD found
|
||||
* \param[out] lanaddr buffer to copy the local address of the host to reach the IGD
|
||||
* \param[in] lanaddrlen size of the lanaddr buffer
|
||||
* \return 0 Not ok / 1 OK
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetIGDFromUrl(const char * rootdescurl,
|
||||
struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
char * lanaddr, int lanaddrlen);
|
||||
|
||||
/*!
|
||||
* \brief Prepare the URLs for usage
|
||||
*
|
||||
* build absolute URLs from the root description
|
||||
* \param[out] urls URL structure to initialize
|
||||
* \param[in] data datas for the IGD
|
||||
* \param[in] descURL root description URL for the IGD
|
||||
* \param[in] scope_id if not 0, add the scope to the linklocal IPv6
|
||||
* addresses in URLs
|
||||
*/
|
||||
MINIUPNP_LIBSPEC void
|
||||
GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data,
|
||||
const char * descURL, unsigned int scope_id);
|
||||
|
||||
/*!
|
||||
* \brief free the members of a UPNPUrls struct
|
||||
*
|
||||
* All URLs buffers are freed and zeroed
|
||||
* \param[out] urls
|
||||
*/
|
||||
MINIUPNP_LIBSPEC void
|
||||
FreeUPNPUrls(struct UPNPUrls * urls);
|
||||
|
||||
/*!
|
||||
* \brief check the current connection status of an IGD
|
||||
*
|
||||
* it uses UPNP_GetStatusInfo()
|
||||
* \param[in] urls IGD URLs
|
||||
* \param[in] data IGD data
|
||||
* \return 1 Connected / 0 Disconnected
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
22
Externals/miniupnpc/include/miniupnpc_declspec.h
vendored
Normal file
22
Externals/miniupnpc/include/miniupnpc_declspec.h
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
#ifndef MINIUPNPC_DECLSPEC_H_INCLUDED
|
||||
#define MINIUPNPC_DECLSPEC_H_INCLUDED
|
||||
|
||||
/*! \file miniupnpc_declspec.h
|
||||
* \brief define #MINIUPNP_LIBSPEC for dll exports and imports */
|
||||
#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 */
|
27
Externals/miniupnpc/include/miniupnpctypes.h
vendored
Normal file
27
Externals/miniupnpc/include/miniupnpctypes.h
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
/* $Id: miniupnpctypes.h,v 1.4 2025/02/08 23:15:16 nanard Exp $ */
|
||||
/* Project: miniupnp
|
||||
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org
|
||||
* Author: Thomas Bernard
|
||||
* Copyright (c) 2021-2025 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided within this distribution */
|
||||
#ifndef MINIUPNPCTYPES_H_INCLUDED
|
||||
#define MINIUPNPCTYPES_H_INCLUDED
|
||||
|
||||
/*! \file miniupnpctypes.h
|
||||
* \brief type definitions
|
||||
*
|
||||
* Use unsigned long long when available :
|
||||
* strtoull is C99
|
||||
*
|
||||
* \def UNSIGNED_INTEGER
|
||||
* \brief `unsigned long long` or `unsigned int`
|
||||
* \todo int can be 16 bits, so it should be `unsigned long`
|
||||
*/
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
#define UNSIGNED_INTEGER unsigned long long
|
||||
#else
|
||||
#define UNSIGNED_INTEGER unsigned int
|
||||
#endif
|
||||
|
||||
#endif
|
54
Externals/miniupnpc/include/miniwget.h
vendored
Normal file
54
Externals/miniupnpc/include/miniwget.h
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
/* $Id: miniwget.h,v 1.14 2025/02/08 23:15:17 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Author : Thomas Bernard
|
||||
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||
* Copyright (c) 2005-2025 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
|
||||
|
||||
/*! \file miniwget.h
|
||||
* \brief Lightweight HTTP client API
|
||||
*/
|
||||
#include "miniupnpc_declspec.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*! \brief perform HTTP GET on an URL
|
||||
*
|
||||
* \param[in] url HTTP URL to GET
|
||||
* \param[out] size length of the returned buffer. -1 in case of memory
|
||||
* allocation error
|
||||
* \param[in] scope_id interface id for IPv6 to use if not specified in the URL
|
||||
* \param[out] status_code HTTP response status code (200, 404, etc.)
|
||||
* \return the body of the HTTP response
|
||||
*/
|
||||
MINIUPNP_LIBSPEC void * miniwget(const char * url, int * size,
|
||||
unsigned int scope_id, int * status_code);
|
||||
|
||||
/*! \brief perform HTTP GET on an URL
|
||||
*
|
||||
* Also get the local address used to reach the HTTP server
|
||||
*
|
||||
* \param[in] url HTTP URL to GET
|
||||
* \param[out] size length of the returned buffer. -1 in case of memory
|
||||
* allocation error
|
||||
* \param[out] addr local address used to connect to the server
|
||||
* \param[in] addrlen size of the addr buffer
|
||||
* \param[in] scope_id interface id for IPv6 to use if not specified in the URL
|
||||
* \param[out] status_code HTTP response status code (200, 404, etc.)
|
||||
* \return the body of the HTTP response
|
||||
*/
|
||||
MINIUPNP_LIBSPEC void * miniwget_getaddr(const char * url, int * size,
|
||||
char * addr, int addrlen,
|
||||
unsigned int scope_id, int * status_code);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
91
Externals/miniupnpc/include/portlistingparse.h
vendored
Normal file
91
Externals/miniupnpc/include/portlistingparse.h
vendored
Normal file
|
@ -0,0 +1,91 @@
|
|||
/* $Id: portlistingparse.h,v 1.12 2025/02/08 23:15:17 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2011-2025 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
#ifndef PORTLISTINGPARSE_H_INCLUDED
|
||||
#define PORTLISTINGPARSE_H_INCLUDED
|
||||
|
||||
/*! \file portlistingparse.h
|
||||
* \brief Parsing of the list of port mappings
|
||||
*
|
||||
* As returned by GetListOfPortMappings.
|
||||
* Sample of PortMappingEntry :
|
||||
*
|
||||
* <p:PortMappingEntry>
|
||||
* <p:NewRemoteHost>202.233.2.1</p:NewRemoteHost>
|
||||
* <p:NewExternalPort>2345</p:NewExternalPort>
|
||||
* <p:NewProtocol>TCP</p:NewProtocol>
|
||||
* <p:NewInternalPort>2345</p:NewInternalPort>
|
||||
* <p:NewInternalClient>192.168.1.137</p:NewInternalClient>
|
||||
* <p:NewEnabled>1</p:NewEnabled>
|
||||
* <p:NewDescription>dooom</p:NewDescription>
|
||||
* <p:NewLeaseTime>345</p:NewLeaseTime>
|
||||
* </p:PortMappingEntry>
|
||||
*/
|
||||
#include "miniupnpc_declspec.h"
|
||||
/* for the definition of UNSIGNED_INTEGER */
|
||||
#include "miniupnpctypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief enum of all XML elements
|
||||
*/
|
||||
typedef enum { PortMappingEltNone,
|
||||
PortMappingEntry, NewRemoteHost,
|
||||
NewExternalPort, NewProtocol,
|
||||
NewInternalPort, NewInternalClient,
|
||||
NewEnabled, NewDescription,
|
||||
NewLeaseTime } portMappingElt;
|
||||
|
||||
/*!
|
||||
* \brief linked list of port mappings
|
||||
*/
|
||||
struct PortMapping {
|
||||
struct PortMapping * l_next; /*!< \brief next list element */
|
||||
UNSIGNED_INTEGER leaseTime; /*!< \brief in seconds */
|
||||
unsigned short externalPort; /*!< \brief external port */
|
||||
unsigned short internalPort; /*!< \brief internal port */
|
||||
char remoteHost[64]; /*!< \brief empty for wildcard */
|
||||
char internalClient[64]; /*!< \brief internal IP address */
|
||||
char description[64]; /*!< \brief description */
|
||||
char protocol[4]; /*!< \brief `TCP` or `UDP` */
|
||||
unsigned char enabled; /*!< \brief 0 (false) or 1 (true) */
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief structure for ParsePortListing()
|
||||
*/
|
||||
struct PortMappingParserData {
|
||||
struct PortMapping * l_head; /*!< \brief list head */
|
||||
portMappingElt curelt; /*!< \brief currently parsed element */
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief parse the NewPortListing part of GetListOfPortMappings response
|
||||
*
|
||||
* \param[in] buffer XML data
|
||||
* \param[in] bufsize length of XML data
|
||||
* \param[out] pdata Parsed data
|
||||
*/
|
||||
MINIUPNP_LIBSPEC void
|
||||
ParsePortListing(const char * buffer, int bufsize,
|
||||
struct PortMappingParserData * pdata);
|
||||
|
||||
/*!
|
||||
* \brief free parsed data structure
|
||||
*
|
||||
* \param[in] pdata Parsed data to free
|
||||
*/
|
||||
MINIUPNP_LIBSPEC void
|
||||
FreePortListing(struct PortMappingParserData * pdata);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
568
Externals/miniupnpc/include/upnpcommands.h
vendored
Normal file
568
Externals/miniupnpc/include/upnpcommands.h
vendored
Normal file
|
@ -0,0 +1,568 @@
|
|||
/* $Id: upnpcommands.h,v 1.34 2025/02/08 23:15:17 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-2025 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided within this distribution */
|
||||
#ifndef UPNPCOMMANDS_H_INCLUDED
|
||||
#define UPNPCOMMANDS_H_INCLUDED
|
||||
|
||||
/*! \file upnpcommands.h
|
||||
* \brief Internet Gateway Device methods
|
||||
*
|
||||
* See the documentation for both IGD v1 and IGD v2 :
|
||||
* - https://upnp.org/specs/gw/UPnP-gw-InternetGatewayDevice-v1-Device.pdf
|
||||
* - https://upnp.org/specs/gw/UPnP-gw-InternetGatewayDevice-v2-Device.pdf
|
||||
*
|
||||
* The methods are from WANIPConnection:1 or 2, WANCommonInterfaceConfig:1,
|
||||
* and WANIPv6FirewallControl:1
|
||||
*
|
||||
*/
|
||||
|
||||
#include "miniupnpc_declspec.h"
|
||||
#include "miniupnpctypes.h"
|
||||
|
||||
/* MiniUPnPc return codes : */
|
||||
/*! \brief value for success */
|
||||
#define UPNPCOMMAND_SUCCESS (0)
|
||||
/*! \brief value for unknown error */
|
||||
#define UPNPCOMMAND_UNKNOWN_ERROR (-1)
|
||||
/*! \brief error while checking the arguments */
|
||||
#define UPNPCOMMAND_INVALID_ARGS (-2)
|
||||
/*! \brief HTTP communication error */
|
||||
#define UPNPCOMMAND_HTTP_ERROR (-3)
|
||||
/*! \brief The response contains invalid values */
|
||||
#define UPNPCOMMAND_INVALID_RESPONSE (-4)
|
||||
/*! \brief Memory allocation error */
|
||||
#define UPNPCOMMAND_MEM_ALLOC_ERROR (-5)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct PortMappingParserData;
|
||||
|
||||
/*! \brief WANCommonInterfaceConfig:GetTotalBytesSent
|
||||
*
|
||||
* Note: this is a 32bits unsigned value and rolls over to 0 after reaching
|
||||
* the maximum value
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANCommonInterfaceConfig of
|
||||
* a WANDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
|
||||
*/
|
||||
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
|
||||
UPNP_GetTotalBytesSent(const char * controlURL,
|
||||
const char * servicetype);
|
||||
|
||||
/*! \brief WANCommonInterfaceConfig:GetTotalBytesReceived
|
||||
*
|
||||
* Note: this is a 32bits unsigned value and rolls over to 0 after reaching
|
||||
* the maximum value
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANCommonInterfaceConfig of a WANDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
|
||||
*/
|
||||
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
|
||||
UPNP_GetTotalBytesReceived(const char * controlURL,
|
||||
const char * servicetype);
|
||||
|
||||
/*! \brief WANCommonInterfaceConfig:GetTotalPacketsSent
|
||||
*
|
||||
* Note: this is a 32bits unsigned value and rolls over to 0 after reaching
|
||||
* the maximum value
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANCommonInterfaceConfig of a WANDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
|
||||
*/
|
||||
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
|
||||
UPNP_GetTotalPacketsSent(const char * controlURL,
|
||||
const char * servicetype);
|
||||
|
||||
/*! \brief WANCommonInterfaceConfig:GetTotalBytesReceived
|
||||
*
|
||||
* Note: this is a 32bits unsigned value and rolls over to 0 after reaching
|
||||
* the maximum value
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANCommonInterfaceConfig of a WANDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
|
||||
*/
|
||||
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
|
||||
UPNP_GetTotalPacketsReceived(const char * controlURL,
|
||||
const char * servicetype);
|
||||
|
||||
/*! \brief WANIPConnection:GetStatusInfo()
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1
|
||||
* \param[out] status 64 bytes buffer : `Unconfigured`, `Connecting`,
|
||||
* `Connected`, `PendingDisconnect`, `Disconnecting`, `Disconnected`
|
||||
* \param[out] uptime time in seconds
|
||||
* \param[out] lastconnerror 64 bytes buffer : `ERROR_NONE`,
|
||||
* `ERROR_COMMAND_ABORTED`, `ERROR_NOT_ENABLED_FOR_INTERNET`,
|
||||
* `ERROR_USER_DISCONNECT`, `ERROR_ISP_DISCONNECT`,
|
||||
* `ERROR_IDLE_DISCONNECT`, `ERROR_FORCED_DISCONNECT`,
|
||||
* `ERROR_NO_CARRIER`, `ERROR_IP_CONFIGURATION`, `ERROR_UNKNOWN`
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP Error code
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetStatusInfo(const char * controlURL,
|
||||
const char * servicetype,
|
||||
char * status,
|
||||
unsigned int * uptime,
|
||||
char * lastconnerror);
|
||||
|
||||
/*! \brief WANIPConnection:GetConnectionTypeInfo()
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1
|
||||
* \param[out] connectionType 64 characters buffer : `Unconfigured`,
|
||||
* `IP_Routed`, `IP_Bridged`
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP Error code
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetConnectionTypeInfo(const char * controlURL,
|
||||
const char * servicetype,
|
||||
char * connectionType);
|
||||
|
||||
/*! \brief WANIPConnection:GetExternalIPAddress()
|
||||
*
|
||||
* possible UPnP Errors :
|
||||
* - 402 Invalid Args - See UPnP Device Architecture section on Control.
|
||||
* - 501 Action Failed - See UPnP Device Architecture section on Control.
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1
|
||||
* \param[out] extIpAdd 16 bytes buffer
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_UNKNOWN_ERROR,
|
||||
* #UPNPCOMMAND_INVALID_ARGS, #UPNPCOMMAND_HTTP_ERROR or an
|
||||
* UPnP error code
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetExternalIPAddress(const char * controlURL,
|
||||
const char * servicetype,
|
||||
char * extIpAdd);
|
||||
|
||||
/*! \brief UPNP_GetLinkLayerMaxBitRates()
|
||||
* call `WANCommonInterfaceConfig:GetCommonLinkProperties`
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANCommonInterfaceConfig of a WANDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
|
||||
* \param[out] bitrateDown bits per second
|
||||
* \param[out] bitrateUp bits per second
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP Error Code.
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetLinkLayerMaxBitRates(const char* controlURL,
|
||||
const char* servicetype,
|
||||
unsigned int * bitrateDown,
|
||||
unsigned int * bitrateUp);
|
||||
|
||||
/*! \brief WANIPConnection:AddPortMapping()
|
||||
*
|
||||
* List of possible UPnP errors for AddPortMapping :
|
||||
* errorCode errorDescription (short) | Description (long)
|
||||
* ---------------------------------- | -----------------
|
||||
* 402 Invalid Args | See UPnP Device Architecture section on Control.
|
||||
* 501 Action Failed | See UPnP Device Architecture section on Control.
|
||||
* 606 Action not authorized | The action requested REQUIRES authorization and the sender was not authorized.
|
||||
* 715 WildCardNotPermittedInSrcIP | The source IP address cannot be wild-carded
|
||||
* 716 WildCardNotPermittedInExtPort | The external port cannot be wild-carded
|
||||
* 718 ConflictInMappingEntry | The port mapping entry specified conflicts with a mapping assigned previously to another client
|
||||
* 724 SamePortValuesRequired | Internal and External port values must be the same
|
||||
* 725 OnlyPermanentLeasesSupported | The NAT implementation only supports permanent lease times on port mappings
|
||||
* 726 RemoteHostOnlySupportsWildcard | RemoteHost must be a wildcard and cannot be a specific IP address or DNS name
|
||||
* 727 ExternalPortOnlySupportsWildcard | ExternalPort must be a wildcard and cannot be a specific port value
|
||||
* 728 NoPortMapsAvailable | There are not enough free ports available to complete port mapping.
|
||||
* 729 ConflictWithOtherMechanisms | Attempted port mapping is not allowed due to conflict with other mechanisms.
|
||||
* 732 WildCardNotPermittedInIntPort | The internal port cannot be wild-carded
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1
|
||||
* \param[in] extPort External port
|
||||
* \param[in] inPort Internal port
|
||||
* \param[in] inClient IP of Internal client.
|
||||
* \param[in] desc Port Mapping description. if NULL, defaults to
|
||||
* "libminiupnpc"
|
||||
* \param[in] proto `TCP` or `UDP`
|
||||
* \param[in] remoteHost IP or empty string for wildcard. Most IGD don't
|
||||
* support it
|
||||
* \param[in] leaseDuration between 0 and 604800
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_MEM_ALLOC_ERROR, #UPNPCOMMAND_HTTP_ERROR,
|
||||
* #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP error code.
|
||||
*/
|
||||
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);
|
||||
|
||||
/*! \brief WANIPConnection:AddAnyPortMapping()
|
||||
*
|
||||
* Only in WANIPConnection:2
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:2
|
||||
* \param[in] extPort External port
|
||||
* \param[in] inPort Internal port
|
||||
* \param[in] inClient IP of Internal client.
|
||||
* \param[in] desc Port Mapping description. if NULL, defaults to
|
||||
* "libminiupnpc"
|
||||
* \param[in] proto `TCP` or `UDP`
|
||||
* \param[in] remoteHost IP or empty string for wildcard. Most IGD don't
|
||||
* support it
|
||||
* \param[in] leaseDuration between 0 and 604800
|
||||
* \param[out] reservedPort 6 bytes buffer
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_MEM_ALLOC_ERROR, #UPNPCOMMAND_HTTP_ERROR,
|
||||
* #UPNPCOMMAND_INVALID_RESPONSE, #UPNPCOMMAND_UNKNOWN_ERROR
|
||||
* or a UPnP error code.
|
||||
*/
|
||||
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);
|
||||
|
||||
/*! \brief WANIPConnection:DeletePortMapping()
|
||||
*
|
||||
* Use same argument values as what was used for UPNP_AddPortMapping()
|
||||
*
|
||||
* List of possible UPnP errors for UPNP_DeletePortMapping() :
|
||||
* errorCode errorDescription (short) | Description (long)
|
||||
* ---------------------------------- | ------------------
|
||||
* 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
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1
|
||||
* \param[in] extPort External port
|
||||
* \param[in] proto `TCP` or `UDP`
|
||||
* \param[in] remoteHost IP or empty string for wildcard. Most IGD don't
|
||||
* support it
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_MEM_ALLOC_ERROR, #UPNPCOMMAND_HTTP_ERROR,
|
||||
* #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP error code.
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
|
||||
const char * extPort, const char * proto,
|
||||
const char * remoteHost);
|
||||
|
||||
/*! \brief WANIPConnection:DeletePortRangeMapping()
|
||||
*
|
||||
* Only in WANIPConnection:2
|
||||
* 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 :
|
||||
* errorCode errorDescription (short) | Description (long)
|
||||
* ---------------------------------- | ------------------
|
||||
* 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.
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:2
|
||||
* \param[in] extPortStart External port range start
|
||||
* \param[in] extPortEnd External port range end
|
||||
* \param[in] proto `TCP` or `UDP`
|
||||
* \param[in] manage `0` to remove only the port mappings of this IGD,
|
||||
* `1` to remove port mappings also for other clients
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_MEM_ALLOC_ERROR, #UPNPCOMMAND_HTTP_ERROR,
|
||||
* #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP error code.
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype,
|
||||
const char * extPortStart, const char * extPortEnd,
|
||||
const char * proto,
|
||||
const char * manage);
|
||||
|
||||
/*! \brief WANIPConnection:GetPortMappingNumberOfEntries()
|
||||
*
|
||||
* not supported by all routers
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1
|
||||
* \param[out] numEntries Port mappings count
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_HTTP_ERROR,
|
||||
* #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP error code.
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetPortMappingNumberOfEntries(const char * controlURL,
|
||||
const char * servicetype,
|
||||
unsigned int * numEntries);
|
||||
|
||||
/*! \brief retrieves an existing port mapping for a port:protocol
|
||||
*
|
||||
* List of possible UPnP errors for UPNP_GetSpecificPortMappingEntry() :
|
||||
* 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.
|
||||
* 714 NoSuchEntryInArray | The specified value does not exist in the array.
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1
|
||||
* \param[in] extPort External port
|
||||
* \param[in] proto `TCP` or `UDP`
|
||||
* \param[in] remoteHost IP or empty string for wildcard. Most IGD don't
|
||||
* support it
|
||||
* \param[out] intClient 16 bytes buffer
|
||||
* \param[out] intPort 6 bytes buffer
|
||||
* \param[out] desc 80 bytes buffer
|
||||
* \param[out] enabled 4 bytes buffer
|
||||
* \param[out] leaseDuration 16 bytes
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP Error Code.
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetSpecificPortMappingEntry(const char * controlURL,
|
||||
const char * servicetype,
|
||||
const char * extPort,
|
||||
const char * proto,
|
||||
const char * remoteHost,
|
||||
char * intClient,
|
||||
char * intPort,
|
||||
char * desc,
|
||||
char * enabled,
|
||||
char * leaseDuration);
|
||||
|
||||
/*! \brief WANIPConnection:GetGenericPortMappingEntry()
|
||||
*
|
||||
* errorCode errorDescription (short) | Description (long)
|
||||
* ---------------------------------- | ------------------
|
||||
* 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
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1
|
||||
* \param[in] index
|
||||
* \param[out] extPort 6 bytes buffer
|
||||
* \param[out] intClient 16 bytes buffer
|
||||
* \param[out] intPort 6 bytes buffer
|
||||
* \param[out] protocol 4 bytes buffer
|
||||
* \param[out] desc 80 bytes buffer
|
||||
* \param[out] enabled 4 bytes buffer
|
||||
* \param[out] rHost 64 bytes buffer
|
||||
* \param[out] duration 16 bytes buffer
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP Error Code.
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetGenericPortMappingEntry(const char * controlURL,
|
||||
const char * servicetype,
|
||||
const char * index,
|
||||
char * extPort,
|
||||
char * intClient,
|
||||
char * intPort,
|
||||
char * protocol,
|
||||
char * desc,
|
||||
char * enabled,
|
||||
char * rHost,
|
||||
char * duration);
|
||||
|
||||
/*! \brief retrieval of a list of existing port mappings
|
||||
*
|
||||
* Available in IGD v2 : WANIPConnection:GetListOfPortMappings()
|
||||
*
|
||||
* errorCode errorDescription (short) | Description (long)
|
||||
* ---------------------------------- | ------------------
|
||||
* 606 Action not authorized | The action requested REQUIRES authorization and the sender was not authorized.
|
||||
* 730 PortMappingNotFound | no port mapping is found in the specified range.
|
||||
* 733 InconsistantParameters | NewStartPort and NewEndPort values are not consistent.
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a
|
||||
* WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:2
|
||||
* \param[in] startPort port interval start
|
||||
* \param[in] endPort port interval end
|
||||
* \param[in] protocol `TCP` or `UDP`
|
||||
* \param[in] numberOfPorts size limit of the list returned. `0` to request
|
||||
* all port mappings
|
||||
* \param[out] data port mappings list
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetListOfPortMappings(const char * controlURL,
|
||||
const char * servicetype,
|
||||
const char * startPort,
|
||||
const char * endPort,
|
||||
const char * protocol,
|
||||
const char * numberOfPorts,
|
||||
struct PortMappingParserData * data);
|
||||
|
||||
/*! \brief GetFirewallStatus() retrieves whether the firewall is enabled
|
||||
* and pinhole can be created through UPnP
|
||||
*
|
||||
* IGD:2, functions for service WANIPv6FirewallControl:1
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPv6FirewallControl of a
|
||||
* WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
|
||||
* \param[out] firewallEnabled false (0) or true (1)
|
||||
* \param[out] inboundPinholeAllowed false (0) or true (1)
|
||||
* \return #UPNPCOMMAND_UNKNOWN_ERROR, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_HTTP_ERROR, #UPNPCOMMAND_SUCCESS or an UPnP error code
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetFirewallStatus(const char * controlURL,
|
||||
const char * servicetype,
|
||||
int * firewallEnabled,
|
||||
int * inboundPinholeAllowed);
|
||||
|
||||
/*! \brief retrieve default value after which automatically created pinholes
|
||||
* expire
|
||||
*
|
||||
* The returned value may be specific to the \p proto, \p remoteHost,
|
||||
* \p remotePort, \p intClient and \p intPort, but this behavior depends
|
||||
* on the implementation of the firewall.
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPv6FirewallControl of a
|
||||
* WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
|
||||
* \param[in] remoteHost
|
||||
* \param[in] remotePort
|
||||
* \param[in] intClient
|
||||
* \param[in] intPort
|
||||
* \param[in] proto `TCP` or `UDP`
|
||||
* \param[out] opTimeout lifetime in seconds of an inbound "automatic"
|
||||
* firewall pinhole created by an outbound traffic initiation.
|
||||
* \return #UPNPCOMMAND_UNKNOWN_ERROR, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_HTTP_ERROR, #UPNPCOMMAND_SUCCESS or an UPnP error code
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetOutboundPinholeTimeout(const char * controlURL,
|
||||
const char * servicetype,
|
||||
const char * remoteHost,
|
||||
const char * remotePort,
|
||||
const char * intClient,
|
||||
const char * intPort,
|
||||
const char * proto,
|
||||
int * opTimeout);
|
||||
|
||||
/*! \brief create a new pinhole that allows incoming traffic to pass
|
||||
* through the firewall
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPv6FirewallControl of a
|
||||
* WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
|
||||
* \param[in] remoteHost literal presentation of IPv6 address or domain name.
|
||||
* empty string for wildcard
|
||||
* \param[in] remotePort remote host port. Likely 0 (for wildcard)
|
||||
* \param[in] intClient IP address of internal client. cannot be wildcarded
|
||||
* \param[in] intPort client port. 0 for wildcard
|
||||
* \param[in] proto IP protocol integer (6 for TCP, 17 for UDP, etc.)
|
||||
* 65535 for wildcard.
|
||||
* \param[in] leaseTime in seconds
|
||||
* \param[out] uniqueID 8 bytes buffer
|
||||
* \return #UPNPCOMMAND_UNKNOWN_ERROR, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_HTTP_ERROR, #UPNPCOMMAND_SUCCESS or an UPnP error code
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_AddPinhole(const char * controlURL, const char * servicetype,
|
||||
const char * remoteHost,
|
||||
const char * remotePort,
|
||||
const char * intClient,
|
||||
const char * intPort,
|
||||
const char * proto,
|
||||
const char * leaseTime,
|
||||
char * uniqueID);
|
||||
|
||||
/*! \brief update a pinhole’s lease time
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPv6FirewallControl of a
|
||||
* WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
|
||||
* \param[in] uniqueID value obtained through UPNP_AddPinhole()
|
||||
* \param[in] leaseTime in seconds
|
||||
* \return #UPNPCOMMAND_UNKNOWN_ERROR, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_HTTP_ERROR, #UPNPCOMMAND_SUCCESS or an UPnP error code
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_UpdatePinhole(const char * controlURL, const char * servicetype,
|
||||
const char * uniqueID,
|
||||
const char * leaseTime);
|
||||
|
||||
/*! \brief remove a pinhole
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPv6FirewallControl of a
|
||||
* WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
|
||||
* \param[in] uniqueID value obtained through UPNP_AddPinhole()
|
||||
* \return #UPNPCOMMAND_UNKNOWN_ERROR, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_HTTP_ERROR, #UPNPCOMMAND_SUCCESS or an UPnP error code
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_DeletePinhole(const char * controlURL,
|
||||
const char * servicetype,
|
||||
const char * uniqueID);
|
||||
|
||||
/*! \brief checking if a certain pinhole allows traffic to pass through the firewall
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPv6FirewallControl of a
|
||||
* WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
|
||||
* \param[in] uniqueID value obtained through UPNP_AddPinhole()
|
||||
* \param[out] isWorking `0` for false, `1` for true
|
||||
* \return #UPNPCOMMAND_UNKNOWN_ERROR, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_HTTP_ERROR, #UPNPCOMMAND_SUCCESS or an UPnP error code
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype,
|
||||
const char * uniqueID, int * isWorking);
|
||||
|
||||
/*! \brief get the total number of IP packets which have been going through
|
||||
* the specified pinhole
|
||||
* \todo \p packets should be #UNSIGNED_INTEGER
|
||||
* \param[in] controlURL controlURL of the WANIPv6FirewallControl of a
|
||||
* WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
|
||||
* \param[in] uniqueID value obtained through UPNP_AddPinhole()
|
||||
* \param[out] packets how many IP packets have been going through the
|
||||
* specified pinhole
|
||||
* \return #UPNPCOMMAND_UNKNOWN_ERROR, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_HTTP_ERROR, #UPNPCOMMAND_SUCCESS or an UPnP error code
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetPinholePackets(const char * controlURL, const char * servicetype,
|
||||
const char * uniqueID, int * packets);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
58
Externals/miniupnpc/include/upnpdev.h
vendored
Normal file
58
Externals/miniupnpc/include/upnpdev.h
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* $Id: upnpdev.h,v 1.6 2025/02/08 23:15:17 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||
* Author : Thomas BERNARD
|
||||
* copyright (c) 2005-2025 Thomas Bernard
|
||||
* This software is subjet to the conditions detailed in the
|
||||
* provided LICENSE file. */
|
||||
#ifndef UPNPDEV_H_INCLUDED
|
||||
#define UPNPDEV_H_INCLUDED
|
||||
|
||||
/*! \file upnpdev.h
|
||||
* \brief UPNPDev device linked-list structure
|
||||
* \todo could be merged into miniupnpc.h
|
||||
*/
|
||||
#include "miniupnpc_declspec.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief UPnP device linked-list
|
||||
*/
|
||||
struct UPNPDev {
|
||||
/*! \brief pointer to the next element */
|
||||
struct UPNPDev * pNext;
|
||||
/*! \brief root description URL */
|
||||
char * descURL;
|
||||
/*! \brief ST: as advertised */
|
||||
char * st;
|
||||
/*! \brief USN: as advertised */
|
||||
char * usn;
|
||||
/*! \brief IPv6 scope id of the network interface */
|
||||
unsigned int scope_id;
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
/* C99 flexible array member */
|
||||
/*! \brief buffer for descURL, st and usn */
|
||||
char buffer[];
|
||||
#elif defined(__GNUC__)
|
||||
char buffer[0];
|
||||
#else
|
||||
/* Fallback to a hack */
|
||||
char buffer[1];
|
||||
#endif
|
||||
};
|
||||
|
||||
/*! \brief free list returned by upnpDiscover()
|
||||
* \param[in] devlist linked list to free
|
||||
*/
|
||||
MINIUPNP_LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* UPNPDEV_H_INCLUDED */
|
36
Externals/miniupnpc/include/upnperrors.h
vendored
Normal file
36
Externals/miniupnpc/include/upnperrors.h
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* $Id: upnperrors.h,v 1.8 2025/02/08 23:15:17 nanard Exp $ */
|
||||
/* (c) 2007-2025 Thomas Bernard
|
||||
* All rights reserved.
|
||||
* MiniUPnP Project.
|
||||
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||
* This software is subjet to the conditions detailed in the
|
||||
* provided LICENCE file. */
|
||||
#ifndef UPNPERRORS_H_INCLUDED
|
||||
#define UPNPERRORS_H_INCLUDED
|
||||
|
||||
/*! \file upnperrors.h
|
||||
* \brief code to string API for errors
|
||||
*/
|
||||
#include "miniupnpc_declspec.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief convert error code to string
|
||||
*
|
||||
* Work for both MiniUPnPc specific errors and UPnP standard defined
|
||||
* errors.
|
||||
*
|
||||
* \param[in] err numerical error code
|
||||
* \return a string description of the error code
|
||||
* or NULL for undefinded errors
|
||||
*/
|
||||
MINIUPNP_LIBSPEC const char * strupnperror(int err);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
82
Externals/miniupnpc/include/upnpreplyparse.h
vendored
Normal file
82
Externals/miniupnpc/include/upnpreplyparse.h
vendored
Normal file
|
@ -0,0 +1,82 @@
|
|||
/* $Id: upnpreplyparse.h,v 1.20 2025/02/08 23:15:17 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||
* (c) 2006-2025 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
|
||||
#ifndef UPNPREPLYPARSE_H_INCLUDED
|
||||
#define UPNPREPLYPARSE_H_INCLUDED
|
||||
|
||||
/*! \file upnpreplyparse.h
|
||||
* \brief Parsing of UPnP SOAP responses
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*! \brief Name/Value linked list
|
||||
* not exposed in the public API
|
||||
*/
|
||||
struct NameValue;
|
||||
|
||||
/*! \brief data structure for parsing */
|
||||
struct NameValueParserData {
|
||||
/*! \brief name/value linked list */
|
||||
struct NameValue * l_head;
|
||||
/*! \brief current element name */
|
||||
char curelt[64];
|
||||
/*! \brief port listing array */
|
||||
char * portListing;
|
||||
/*! \brief port listing array length */
|
||||
int portListingLength;
|
||||
/*! \brief flag indicating the current element is */
|
||||
int topelt;
|
||||
/*! \brief top element character data */
|
||||
const char * cdata;
|
||||
/*! \brief top element character data length */
|
||||
int cdatalen;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Parse XML and fill the structure
|
||||
*
|
||||
* \param[in] buffer XML data
|
||||
* \param[in] bufsize buffer length
|
||||
* \param[out] data structure to fill
|
||||
*/
|
||||
void
|
||||
ParseNameValue(const char * buffer, int bufsize,
|
||||
struct NameValueParserData * data);
|
||||
|
||||
/*!
|
||||
* \brief free memory
|
||||
*
|
||||
* \param[in,out] pdata data structure
|
||||
*/
|
||||
void
|
||||
ClearNameValueList(struct NameValueParserData * pdata);
|
||||
|
||||
/*!
|
||||
* \brief get a value from the parsed data
|
||||
*
|
||||
* \param[in] pdata data structure
|
||||
* \param[in] name name
|
||||
* \return the value or NULL if not found
|
||||
*/
|
||||
char *
|
||||
GetValueFromNameValueList(struct NameValueParserData * pdata,
|
||||
const char * name);
|
||||
|
||||
/* DisplayNameValueList() */
|
||||
#ifdef DEBUG
|
||||
void
|
||||
DisplayNameValueList(char * buffer, int bufsize);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
276
Externals/miniupnpc/miniupnpc.vcxproj
vendored
276
Externals/miniupnpc/miniupnpc.vcxproj
vendored
|
@ -1,63 +1,249 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project>
|
||||
<Import Project="..\..\Source\VSProps\Base.Macros.props" />
|
||||
<Import Project="$(VSPropsDir)Base.Targets.props" />
|
||||
<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>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{31643FDB-1BB8-4965-9DE7-000FC88D35AE}</ProjectGuid>
|
||||
<ProjectGuid>{D28CE435-CB33-4BAE-8A52-C6EF915956F5}</ProjectGuid>
|
||||
<RootNamespace>miniupnpc</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<Import Project="$(VSPropsDir)Configuration.StaticLibrary.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Dll|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Dll|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<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|x64'" 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" />
|
||||
<Import Project="$(VSPropsDir)Base.props" />
|
||||
<Import Project="$(VSPropsDir)ClDisableAllWarnings.props" />
|
||||
</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|x64'">
|
||||
<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|x64'">
|
||||
<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>
|
||||
<ClInclude Include="src\codelength.h" />
|
||||
<ClInclude Include="src\connecthostport.h" />
|
||||
<ClInclude Include="src\igd_desc_parse.h" />
|
||||
<ClInclude Include="src\minisoap.h" />
|
||||
<ClInclude Include="src\minissdpc.h" />
|
||||
<ClInclude Include="src\miniupnpc.h" />
|
||||
<ClInclude Include="src\miniupnpc_declspec.h" />
|
||||
<ClInclude Include="src\miniupnpcstrings.h" />
|
||||
<ClInclude Include="src\miniupnpctypes.h" />
|
||||
<ClInclude Include="src\miniwget.h" />
|
||||
<ClInclude Include="src\minixml.h" />
|
||||
<ClInclude Include="src\portlistingparse.h" />
|
||||
<ClInclude Include="src\receivedata.h" />
|
||||
<ClInclude Include="src\upnpcommands.h" />
|
||||
<ClInclude Include="src\upnpdev.h" />
|
||||
<ClInclude Include="src\upnperrors.h" />
|
||||
<ClInclude Include="src\upnpreplyparse.h" />
|
||||
<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>
|
||||
<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" />
|
||||
<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="LICENSE" />
|
||||
<None Include="README" />
|
||||
<None Include="VERSION" />
|
||||
<None Include="genminiupnpcstrings.vbs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="apiversions.txt" />
|
||||
<Text Include="Changelog.txt" />
|
||||
<Text Include="CMakeLists.txt" />
|
||||
<ResourceCompile Include="../miniupnpc.rc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
|
89
Externals/miniupnpc/src/addr_is_reserved.c
vendored
Normal file
89
Externals/miniupnpc/src/addr_is_reserved.c
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
/* $Id: addr_is_reserved.c,v 1.7 2025/01/12 15:47:17 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-2025 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) */
|
||||
#if !defined(_WIN32_WINNT_VISTA)
|
||||
#define _WIN32_WINNT_VISTA 0x0600
|
||||
#endif
|
||||
#else /* _WIN32 */
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif /* _WIN32 */
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
/* 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 < _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)) {
|
||||
#ifdef DEBUG
|
||||
printf("IP address %s is reserved\n", addr_str);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
14
Externals/miniupnpc/src/addr_is_reserved.h
vendored
Normal file
14
Externals/miniupnpc/src/addr_is_reserved.h
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
/* $Id: $ */
|
||||
/* 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 */
|
113
Externals/miniupnpc/src/connecthostport.c
vendored
113
Externals/miniupnpc/src/connecthostport.c
vendored
|
@ -1,7 +1,8 @@
|
|||
/* $Id: connecthostport.c,v 1.13 2014/03/31 12:36:36 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-2014 Thomas Bernard
|
||||
* Copyright (c) 2010-2020 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution. */
|
||||
|
||||
|
@ -18,11 +19,15 @@
|
|||
#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 */
|
||||
#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>
|
||||
|
@ -32,20 +37,10 @@
|
|||
/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions
|
||||
* during the connect() call */
|
||||
#define MINIUPNPC_IGNORE_EINTR
|
||||
#ifndef USE_GETHOSTBYNAME
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#endif /* #ifndef USE_GETHOSTBYNAME */
|
||||
#endif /* #else _WIN32 */
|
||||
|
||||
/* 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
|
||||
|
||||
#if defined(__amigaos__) || defined(__amigaos4__)
|
||||
#define herror(A) printf("%s\n", A)
|
||||
#endif
|
||||
|
@ -59,10 +54,11 @@
|
|||
/* 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,
|
||||
unsigned int scope_id)
|
||||
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;
|
||||
|
@ -81,15 +77,15 @@ int connecthostport(const char * host, unsigned short port,
|
|||
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 */
|
||||
|
@ -97,13 +93,13 @@ 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;
|
||||
|
@ -113,22 +109,36 @@ int connecthostport(const char * host, unsigned short port,
|
|||
/* 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))
|
||||
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;
|
||||
|
@ -140,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() */
|
||||
|
@ -160,7 +170,7 @@ int connecthostport(const char * host, unsigned short port,
|
|||
for(i = 0, j = 1; host[j] && (host[j] != ']') && i < MAXHOSTNAMELEN; i++, j++)
|
||||
{
|
||||
tmp_host[i] = host[j];
|
||||
if(0 == memcmp(host+j, "%25", 3)) /* %25 is just url encoding for '%' */
|
||||
if(0 == strncmp(host+j, "%25", 3)) /* %25 is just url encoding for '%' */
|
||||
j+=2; /* skip "25" */
|
||||
}
|
||||
tmp_host[i] = '\0';
|
||||
|
@ -178,13 +188,19 @@ int connecthostport(const char * host, unsigned short port,
|
|||
#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;
|
||||
|
@ -205,7 +221,7 @@ 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
|
||||
/* EINTR The system call was interrupted by a signal that was caught
|
||||
* EINPROGRESS The socket is nonblocking and the connection cannot
|
||||
|
@ -217,8 +233,22 @@ int connecthostport(const char * host, unsigned short port,
|
|||
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);
|
||||
|
@ -226,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;
|
||||
|
@ -234,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;
|
||||
}
|
||||
|
||||
|
|
10
Externals/miniupnpc/src/connecthostport.h
vendored
10
Externals/miniupnpc/src/connecthostport.h
vendored
|
@ -2,17 +2,19 @@
|
|||
/* Project: miniupnp
|
||||
* http://miniupnp.free.fr/
|
||||
* Author: Thomas Bernard
|
||||
* Copyright (c) 2010-2012 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 -1 in case of error */
|
||||
int connecthostport(const char * host, unsigned short port,
|
||||
unsigned int scope_id);
|
||||
* or INVALID_SOCKET in case of error */
|
||||
SOCKET connecthostport(const char * host, unsigned short port,
|
||||
unsigned int scope_id);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
50
Externals/miniupnpc/src/igd_desc_parse.h
vendored
50
Externals/miniupnpc/src/igd_desc_parse.h
vendored
|
@ -1,46 +1,72 @@
|
|||
/* $Id: igd_desc_parse.h,v 1.12 2014/11/17 17:19:13 nanard Exp $ */
|
||||
/* $Id: igd_desc_parse.h,v 1.14 2025/02/08 23:15:16 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* http://miniupnp.free.fr/
|
||||
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005-2014 Thomas Bernard
|
||||
* Copyright (c) 2005-2025 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution.
|
||||
* */
|
||||
#ifndef IGD_DESC_PARSE_H_INCLUDED
|
||||
#define IGD_DESC_PARSE_H_INCLUDED
|
||||
|
||||
/* Structure to store the result of the parsing of UPnP
|
||||
* descriptions of Internet Gateway Devices */
|
||||
/*! \file igd_desc_parse.h
|
||||
* \brief API to parse UPNP device description XML
|
||||
* \todo should not be exposed in the public API
|
||||
*/
|
||||
|
||||
/*! \brief maximum lenght of URLs */
|
||||
#define MINIUPNPC_URL_MAXSIZE (128)
|
||||
|
||||
/*! \brief Structure to store the result of the parsing of UPnP
|
||||
* descriptions of Internet Gateway Devices services */
|
||||
struct IGDdatas_service {
|
||||
/*! \brief controlURL for the service */
|
||||
char controlurl[MINIUPNPC_URL_MAXSIZE];
|
||||
/*! \brief eventSubURL for the service */
|
||||
char eventsuburl[MINIUPNPC_URL_MAXSIZE];
|
||||
/*! \brief SCPDURL for the service */
|
||||
char scpdurl[MINIUPNPC_URL_MAXSIZE];
|
||||
/*! \brief serviceType */
|
||||
char servicetype[MINIUPNPC_URL_MAXSIZE];
|
||||
/*char devicetype[MINIUPNPC_URL_MAXSIZE];*/
|
||||
};
|
||||
|
||||
/*! \brief Structure to store the result of the parsing of UPnP
|
||||
* descriptions of Internet Gateway Devices */
|
||||
struct IGDdatas {
|
||||
/*! \brief current element name */
|
||||
char cureltname[MINIUPNPC_URL_MAXSIZE];
|
||||
/*! \brief URLBase */
|
||||
char urlbase[MINIUPNPC_URL_MAXSIZE];
|
||||
/*! \brief presentationURL */
|
||||
char presentationurl[MINIUPNPC_URL_MAXSIZE];
|
||||
/*! \brief depth into the XML tree */
|
||||
int level;
|
||||
/*int state;*/
|
||||
/* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */
|
||||
/*! \brief "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */
|
||||
struct IGDdatas_service CIF;
|
||||
/* "urn:schemas-upnp-org:service:WANIPConnection:1"
|
||||
* "urn:schemas-upnp-org:service:WANPPPConnection:1" */
|
||||
/*! \brief first of "urn:schemas-upnp-org:service:WANIPConnection:1"
|
||||
* or "urn:schemas-upnp-org:service:WANPPPConnection:1" */
|
||||
struct IGDdatas_service first;
|
||||
/* if both WANIPConnection and WANPPPConnection are present */
|
||||
/*! \brief second of "urn:schemas-upnp-org:service:WANIPConnection:1"
|
||||
* or "urn:schemas-upnp-org:service:WANPPPConnection:1" */
|
||||
struct IGDdatas_service second;
|
||||
/* "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1" */
|
||||
/*! \brief "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1" */
|
||||
struct IGDdatas_service IPv6FC;
|
||||
/* tmp */
|
||||
/*! \brief currently parsed service */
|
||||
struct IGDdatas_service tmp;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief XML start element handler
|
||||
*/
|
||||
void IGDstartelt(void *, const char *, int);
|
||||
/*!
|
||||
* \brief XML end element handler
|
||||
*/
|
||||
void IGDendelt(void *, const char *, int);
|
||||
/*!
|
||||
* \brief XML characted data handler
|
||||
*/
|
||||
void IGDdata(void *, const char *, int);
|
||||
#ifdef DEBUG
|
||||
void printIGD(struct IGDdatas *);
|
||||
|
|
198
Externals/miniupnpc/src/listdevices.c
vendored
Normal file
198
Externals/miniupnpc/src/listdevices.c
vendored
Normal file
|
@ -0,0 +1,198 @@
|
|||
/* $Id: listdevices.c,v 1.6 2015/07/23 20:40:08 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 {
|
||||
fprintf(stderr,"No UPnP devices found\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
690
Externals/miniupnpc/src/minihttptestserver.c
vendored
Normal file
690
Externals/miniupnpc/src/minihttptestserver.c
vendored
Normal file
|
@ -0,0 +1,690 @@
|
|||
/* $Id: minihttptestserver.c,v 1.25 2020/05/29 21:14:22 nanard Exp $ */
|
||||
/* Project : miniUPnP
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2011-2018 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 <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <arpa/inet.h>
|
||||
#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)
|
||||
|
||||
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)
|
||||
{
|
||||
(void)sig;
|
||||
/* printf("handle_signal_chld(%d)\n", sig); */
|
||||
++child_to_wait_for;
|
||||
}
|
||||
|
||||
/**
|
||||
* signal handler for SIGINT (CRTL C)
|
||||
*/
|
||||
void handle_signal_int(int sig)
|
||||
{
|
||||
(void)sig;
|
||||
/* printf("handle_signal_int(%d)\n", sig); */
|
||||
quit = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* build a text/plain content of the specified length
|
||||
*/
|
||||
void build_content(char * p, size_t n)
|
||||
{
|
||||
char line_buffer[80];
|
||||
int k;
|
||||
int i = 0;
|
||||
|
||||
while(n > 0) {
|
||||
k = snprintf(line_buffer, sizeof(line_buffer),
|
||||
"%04d_ABCDEFGHIJKL_This_line_is_64_bytes_long_ABCDEFGHIJKL_%04d\r\n",
|
||||
i, i);
|
||||
if(k != 64) {
|
||||
fprintf(stderr, "snprintf() returned %d in build_content()\n", k);
|
||||
}
|
||||
++i;
|
||||
if(n >= 64) {
|
||||
memcpy(p, line_buffer, 64);
|
||||
p += 64;
|
||||
n -= 64;
|
||||
} else {
|
||||
memcpy(p, line_buffer, n);
|
||||
p += n;
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* build crappy content
|
||||
*/
|
||||
void build_crap(char * p, size_t n)
|
||||
{
|
||||
static const char crap[] = "_CRAP_\r\n";
|
||||
size_t i;
|
||||
|
||||
while(n > 0) {
|
||||
i = sizeof(crap) - 1;
|
||||
if(i > n)
|
||||
i = n;
|
||||
memcpy(p, crap, i);
|
||||
p += i;
|
||||
n -= i;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* build chunked response.
|
||||
* return a malloc'ed buffer
|
||||
*/
|
||||
char * build_chunked_response(size_t content_length, size_t * response_len)
|
||||
{
|
||||
char * response_buffer;
|
||||
char * content_buffer;
|
||||
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"
|
||||
"Transfer-Encoding: chunked\r\n"
|
||||
"\r\n");
|
||||
|
||||
/* 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 */
|
||||
i = 0;
|
||||
while(i < content_length) {
|
||||
n = (rand() % 199) + 1;
|
||||
if(i + n > content_length) {
|
||||
n = content_length - i;
|
||||
}
|
||||
/* TODO : check buffer size ! */
|
||||
*response_len += snprintf(response_buffer + *response_len,
|
||||
buffer_length - *response_len,
|
||||
"%x\r\n", n);
|
||||
memcpy(response_buffer + *response_len, content_buffer + i, n);
|
||||
*response_len += n;
|
||||
i += n;
|
||||
response_buffer[(*response_len)++] = '\r';
|
||||
response_buffer[(*response_len)++] = '\n';
|
||||
}
|
||||
/* 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=%lu buffer_length=%lu content_length=%lu\n",
|
||||
*response_len, buffer_length, content_length);
|
||||
return response_buffer;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
} modes_array[] = {
|
||||
{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, size_t len)
|
||||
{
|
||||
ssize_t n;
|
||||
while(len > 0) {
|
||||
n = (rand() % 99) + 1;
|
||||
if((size_t)n > len)
|
||||
n = len;
|
||||
n = write(c, buffer, n);
|
||||
if(n < 0) {
|
||||
if(errno != EINTR) {
|
||||
perror("write");
|
||||
return;
|
||||
}
|
||||
/* if errno == EINTR, try again */
|
||||
} else {
|
||||
len -= n;
|
||||
buffer += n;
|
||||
usleep(10000); /* 10ms */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* handle the HTTP connection
|
||||
*/
|
||||
void handle_http_connection(int c)
|
||||
{
|
||||
char request_buffer[2048];
|
||||
size_t request_len = 0;
|
||||
int headers_found = 0;
|
||||
ssize_t n, m;
|
||||
size_t i;
|
||||
char request_method[16];
|
||||
char request_uri[256];
|
||||
char http_version[16];
|
||||
char * p;
|
||||
char * response_buffer;
|
||||
size_t response_len;
|
||||
enum modes mode;
|
||||
size_t content_length = 16*1024;
|
||||
|
||||
/* read the request */
|
||||
while(request_len < sizeof(request_buffer) && !headers_found) {
|
||||
n = read(c,
|
||||
request_buffer + request_len,
|
||||
sizeof(request_buffer) - request_len);
|
||||
if(n < 0) {
|
||||
if(errno == EINTR)
|
||||
continue;
|
||||
perror("read");
|
||||
return;
|
||||
} else if(n==0) {
|
||||
/* remote host closed the connection */
|
||||
break;
|
||||
} else {
|
||||
request_len += n;
|
||||
for(i = 0; i < request_len - 3; i++) {
|
||||
if(0 == memcmp(request_buffer + i, "\r\n\r\n", 4)) {
|
||||
/* found the end of headers */
|
||||
headers_found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!headers_found) {
|
||||
/* error */
|
||||
printf("no HTTP header found in the request\n");
|
||||
return;
|
||||
}
|
||||
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++) {
|
||||
if(*p == ' ' || *p == '\r')
|
||||
break;
|
||||
request_method[i] = *p;
|
||||
++p;
|
||||
}
|
||||
request_method[i] = '\0';
|
||||
while(*p == ' ')
|
||||
p++;
|
||||
for(i = 0; i < (int)sizeof(request_uri) - 1; i++) {
|
||||
if(*p == ' ' || *p == '\r')
|
||||
break;
|
||||
request_uri[i] = *p;
|
||||
++p;
|
||||
}
|
||||
request_uri[i] = '\0';
|
||||
while(*p == ' ')
|
||||
p++;
|
||||
for(i = 0; i < (int)sizeof(http_version) - 1; i++) {
|
||||
if(*p == ' ' || *p == '\r')
|
||||
break;
|
||||
http_version[i] = *p;
|
||||
++p;
|
||||
}
|
||||
http_version[i] = '\0';
|
||||
printf("Method = %s, URI = %s, %s\n",
|
||||
request_method, request_uri, http_version);
|
||||
/* check if the request method is allowed */
|
||||
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. */
|
||||
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;
|
||||
}
|
||||
|
||||
mode = MODE_INVALID;
|
||||
/* use the request URI to know what to do */
|
||||
for(i = 0; modes_array[i].mode != MODE_INVALID; i++) {
|
||||
if(strstr(request_uri, modes_array[i].text)) {
|
||||
mode = modes_array[i].mode; /* found */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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: %lu\r\n"
|
||||
"\r\n", content_length);
|
||||
response_len = content_length+n+CRAP_LENGTH;
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
if(response_buffer) {
|
||||
send_response(c, response_buffer, response_len);
|
||||
free(response_buffer);
|
||||
} else {
|
||||
/* Error 500 */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
int main(int argc, char * * argv) {
|
||||
int ipv6 = 0;
|
||||
int r, i;
|
||||
unsigned short port = 0;
|
||||
const char * expected_file_name = NULL;
|
||||
|
||||
for(i = 1; i < argc; i++) {
|
||||
if(argv[i][0] == '-') {
|
||||
switch(argv[i][1]) {
|
||||
case '6':
|
||||
ipv6 = 1;
|
||||
break;
|
||||
case 'e':
|
||||
/* write expected file ! */
|
||||
expected_file_name = argv[++i];
|
||||
break;
|
||||
case 'p':
|
||||
/* port */
|
||||
if(++i < argc) {
|
||||
port = (unsigned short)atoi(argv[i]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown command line switch '%s'\n", argv[i]);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "unknown command line argument '%s'\n", argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
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) {
|
||||
perror("socket");
|
||||
return 1;
|
||||
}
|
||||
memset(&server_addr, 0, sizeof(struct sockaddr_storage));
|
||||
memset(&client_addr, 0, sizeof(struct sockaddr_storage));
|
||||
if(ipv6) {
|
||||
struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&server_addr;
|
||||
addr->sin6_family = AF_INET6;
|
||||
addr->sin6_port = htons(port);
|
||||
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_LOOPBACK);
|
||||
}
|
||||
if(bind(s, (struct sockaddr *)&server_addr,
|
||||
ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) < 0) {
|
||||
perror("bind");
|
||||
return 1;
|
||||
}
|
||||
if(listen(s, 5) < 0) {
|
||||
perror("listen");
|
||||
}
|
||||
if(port == 0) {
|
||||
server_addrlen = sizeof(struct sockaddr_storage);
|
||||
if(getsockname(s, (struct sockaddr *)&server_addr, &server_addrlen) < 0) {
|
||||
perror("getsockname");
|
||||
return 1;
|
||||
}
|
||||
if(ipv6) {
|
||||
struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&server_addr;
|
||||
port = ntohs(addr->sin6_port);
|
||||
} else {
|
||||
struct sockaddr_in * addr = (struct sockaddr_in *)&server_addr;
|
||||
port = ntohs(addr->sin_port);
|
||||
}
|
||||
printf("Listening on port %hu\n", port);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
/* write expected file */
|
||||
if(expected_file_name) {
|
||||
FILE * f;
|
||||
f = fopen(expected_file_name, "wb");
|
||||
if(f) {
|
||||
char * buffer;
|
||||
buffer = malloc(16*1024);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* fork() loop */
|
||||
while(!child && !quit) {
|
||||
while(child_to_wait_for > 0) {
|
||||
pid = wait(&status);
|
||||
if(pid < 0) {
|
||||
perror("wait");
|
||||
} else {
|
||||
printf("child(%d) terminated with status %d\n", (int)pid, status);
|
||||
}
|
||||
--child_to_wait_for;
|
||||
}
|
||||
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;
|
||||
}
|
||||
printf("accept...\n");
|
||||
pid = fork();
|
||||
if(pid < 0) {
|
||||
perror("fork");
|
||||
return 1;
|
||||
} else if(pid == 0) {
|
||||
/* child */
|
||||
child = 1;
|
||||
close(s);
|
||||
s = -1;
|
||||
handle_http_connection(c);
|
||||
}
|
||||
close(c);
|
||||
}
|
||||
if(s >= 0) {
|
||||
close(s);
|
||||
s = -1;
|
||||
}
|
||||
if(!child) {
|
||||
while(child_to_wait_for > 0) {
|
||||
pid = wait(&status);
|
||||
if(pid < 0) {
|
||||
perror("wait");
|
||||
} else {
|
||||
printf("child(%d) terminated with status %d\n", (int)pid, status);
|
||||
}
|
||||
--child_to_wait_for;
|
||||
}
|
||||
printf("Bye...\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
41
Externals/miniupnpc/src/minisoap.c
vendored
41
Externals/miniupnpc/src/minisoap.c
vendored
|
@ -1,7 +1,8 @@
|
|||
/* $Id: minisoap.c,v 1.23 2014/11/04 22:31:55 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
/* $Id: minisoap.c,v 1.32 2023/07/05 22:43:50 nanard Exp $ */
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* Project : miniupnp
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005-2014 Thomas Bernard
|
||||
* Copyright (c) 2005-2024 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution.
|
||||
*
|
||||
|
@ -12,7 +13,7 @@
|
|||
#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,7 +50,7 @@ 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
|
||||
if(shutdown(fd, SD_SEND)<0) {
|
||||
|
@ -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,33 +73,37 @@ 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
|
||||
* Using HTTP/1.1 means we need to support chunked transfer-encoding :
|
||||
* When using HTTP/1.1, the router "BiPAC 7404VNOX" always use chunked
|
||||
* transfer encoding. */
|
||||
/* Connection: Close is normally there only in HTTP/1.1 but who knows */
|
||||
/* Connection: close is normally there only in HTTP/1.1 but who knows */
|
||||
portstr[0] = '\0';
|
||||
if(port != 80)
|
||||
snprintf(portstr, sizeof(portstr), ":%hu", port);
|
||||
headerssize = snprintf(headerbuf, sizeof(headerbuf),
|
||||
"POST %s HTTP/%s\r\n"
|
||||
"Host: %s%s\r\n"
|
||||
"User-Agent: " OS_STRING ", " UPNP_VERSION_STRING ", MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
|
||||
"User-Agent: " OS_STRING " " UPNP_VERSION_STRING " MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
|
||||
"Content-Length: %d\r\n"
|
||||
#if (UPNP_VERSION_MAJOR == 1) && (UPNP_VERSION_MINOR == 0)
|
||||
"Content-Type: text/xml\r\n"
|
||||
#else
|
||||
"Content-Type: text/xml; charset=\"utf-8\"\r\n"
|
||||
#endif
|
||||
"SOAPAction: \"%s\"\r\n"
|
||||
"Connection: Close\r\n"
|
||||
"Connection: close\r\n"
|
||||
"Cache-Control: no-cache\r\n" /* ??? */
|
||||
"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);
|
||||
|
|
6
Externals/miniupnpc/src/minisoap.h
vendored
6
Externals/miniupnpc/src/minisoap.h
vendored
|
@ -1,14 +1,16 @@
|
|||
/* $Id: minisoap.h,v 1.4 2010/04/12 20:39:41 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_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
|
||||
|
|
509
Externals/miniupnpc/src/minissdpc.c
vendored
509
Externals/miniupnpc/src/minissdpc.c
vendored
|
@ -1,23 +1,26 @@
|
|||
/* $Id: minissdpc.c,v 1.28 2015/09/18 13:05:39 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Web : http://miniupnp.free.fr/
|
||||
/* $Id: minissdpc.c,v 1.52 2025/01/12 15:47:17 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-2015 Thomas Bernard
|
||||
* copyright (c) 2005-2025 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 <time.h>
|
||||
#include <sys/types.h>
|
||||
#if defined (__NetBSD__)
|
||||
#include <net/if.h>
|
||||
#endif
|
||||
#if defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <io.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <winsock.h>
|
||||
#define snprintf _snprintf
|
||||
#include "win32_snprintf.h"
|
||||
#if !defined(_MSC_VER)
|
||||
#include <stdint.h>
|
||||
#else /* !defined(_MSC_VER) */
|
||||
|
@ -30,6 +33,15 @@ typedef unsigned short uint16_t;
|
|||
#define strncasecmp memicmp
|
||||
#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
|
||||
#endif /* #ifndef strncasecmp */
|
||||
#if defined(WINAPI_FAMILY) && defined(WINAPI_FAMILY_PARTITION)
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP
|
||||
#define in6addr_any in6addr_any_init
|
||||
static const IN6_ADDR in6addr_any_init = {0};
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(_WIN32_WINNT_VISTA)
|
||||
#define _WIN32_WINNT_VISTA 0x0600
|
||||
#endif
|
||||
#endif /* _WIN32 */
|
||||
#if defined(__amigaos__) || defined(__amigaos4__)
|
||||
#include <sys/socket.h>
|
||||
|
@ -57,14 +69,17 @@ struct sockaddr_un {
|
|||
#define closesocket close
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
|
||||
#else
|
||||
#define PRINT_SOCKET_ERROR(x) perror(x)
|
||||
#include "miniupnpc_socketdef.h"
|
||||
|
||||
#if !defined(__DragonFly__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__APPLE__) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__sun) && !defined(__GNU__) && !defined(__FreeBSD_kernel__) && !defined(__HAIKU__)
|
||||
#define HAS_IP_MREQN
|
||||
#endif
|
||||
|
||||
#if !defined(__DragonFly__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__APPLE__) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__sun) && !defined(__GNU__) && !defined(__FreeBSD_kernel__)
|
||||
#define HAS_IP_MREQN
|
||||
#ifndef _WIN32
|
||||
#include <sys/ioctl.h>
|
||||
#if defined(__sun) || defined(__HAIKU__)
|
||||
#include <sys/sockio.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(HAS_IP_MREQN) && defined(NEED_STRUCT_IP_MREQN)
|
||||
|
@ -84,6 +99,7 @@ struct ip_mreqn
|
|||
#endif
|
||||
|
||||
#include "minissdpc.h"
|
||||
#include "miniupnpc.h"
|
||||
#include "receivedata.h"
|
||||
|
||||
#if !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__))
|
||||
|
@ -160,7 +176,7 @@ connectToMiniSSDPD(const char * socketpath)
|
|||
{
|
||||
int s;
|
||||
struct sockaddr_un addr;
|
||||
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
|
||||
#if defined(MINIUPNPC_SET_SOCKET_TIMEOUT) && !defined(__sun)
|
||||
struct timeval timeout;
|
||||
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
|
||||
|
||||
|
@ -171,23 +187,25 @@ connectToMiniSSDPD(const char * socketpath)
|
|||
perror("socket(unix)");
|
||||
return MINISSDPC_SOCKET_ERROR;
|
||||
}
|
||||
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
|
||||
#if defined(MINIUPNPC_SET_SOCKET_TIMEOUT) && !defined(__sun)
|
||||
/* setting a 3 seconds timeout */
|
||||
/* not supported for AF_UNIX sockets under Solaris */
|
||||
timeout.tv_sec = 3;
|
||||
timeout.tv_usec = 0;
|
||||
if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0)
|
||||
{
|
||||
perror("setsockopt");
|
||||
perror("setsockopt SO_RCVTIMEO unix");
|
||||
}
|
||||
timeout.tv_sec = 3;
|
||||
timeout.tv_usec = 0;
|
||||
if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0)
|
||||
{
|
||||
perror("setsockopt");
|
||||
perror("setsockopt SO_SNDTIMEO unix");
|
||||
}
|
||||
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
|
||||
if(!socketpath)
|
||||
socketpath = "/var/run/minissdpd.sock";
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, socketpath, sizeof(addr.sun_path));
|
||||
/* TODO : check if we need to handle the EINTR */
|
||||
|
@ -323,7 +341,7 @@ receiveDevicesFromMiniSSDPD(int s, int * error)
|
|||
#ifdef DEBUG
|
||||
printf(" usnsize=%u\n", usnsize);
|
||||
#endif /* DEBUG */
|
||||
tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize);
|
||||
tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize+3);
|
||||
if(tmp == NULL) {
|
||||
if (error)
|
||||
*error = MINISSDPC_MEMORY_ERROR;
|
||||
|
@ -372,6 +390,7 @@ free_tmp_and_return:
|
|||
* 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.
|
||||
* - usn/usnsize : "usn:" filed of the SSDP reply packet
|
||||
* The strings are NOT null terminated */
|
||||
static void
|
||||
parseMSEARCHReply(const char * reply, int size,
|
||||
|
@ -409,17 +428,17 @@ parseMSEARCHReply(const char * reply, int size,
|
|||
putchar('\n');*/
|
||||
/* skip the colon and white spaces */
|
||||
do { b++; } while(reply[b]==' ');
|
||||
if(0==strncasecmp(reply+a, "location", 8))
|
||||
if(0==strncasecmp(reply+a, "location:", 9))
|
||||
{
|
||||
*location = reply+b;
|
||||
*locationsize = i-b;
|
||||
}
|
||||
else if(0==strncasecmp(reply+a, "st", 2))
|
||||
else if(0==strncasecmp(reply+a, "st:", 3))
|
||||
{
|
||||
*st = reply+b;
|
||||
*stsize = i-b;
|
||||
}
|
||||
else if(0==strncasecmp(reply+a, "usn", 3))
|
||||
else if(0==strncasecmp(reply+a, "usn:", 4))
|
||||
{
|
||||
*usn = reply+b;
|
||||
*usnsize = i-b;
|
||||
|
@ -435,8 +454,53 @@ parseMSEARCHReply(const char * reply, int size,
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(CLOCK_MONOTONIC_FAST)
|
||||
#define UPNP_CLOCKID CLOCK_MONOTONIC_FAST
|
||||
#elif defined(CLOCK_MONOTONIC)
|
||||
#define UPNP_CLOCKID CLOCK_MONOTONIC
|
||||
#endif
|
||||
|
||||
static int upnp_gettimeofday(struct timeval * tv)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
ULONGLONG ts = GetTickCount64();
|
||||
#else
|
||||
DWORD ts = GetTickCount();
|
||||
#endif
|
||||
tv->tv_sec = (long)(ts / 1000);
|
||||
tv->tv_usec = (ts % 1000) * 1000;
|
||||
return 0; /* success */
|
||||
#elif defined(CLOCK_MONOTONIC_FAST) || defined(CLOCK_MONOTONIC)
|
||||
#if defined(__APPLE__)
|
||||
#if defined(__clang__)
|
||||
if (__builtin_available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)) {
|
||||
#else /* !defined(__clang__) */
|
||||
if (clock_gettime != NULL) {
|
||||
#endif /* defined(__clang__) */
|
||||
#endif /* defined(__APPLE__) */
|
||||
struct timespec ts;
|
||||
int ret_code = clock_gettime(UPNP_CLOCKID, &ts);
|
||||
if (ret_code == 0)
|
||||
{
|
||||
tv->tv_sec = ts.tv_sec;
|
||||
tv->tv_usec = ts.tv_nsec / 1000;
|
||||
}
|
||||
return ret_code;
|
||||
#if defined(__APPLE__)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* fall-back for earlier Apple platforms */
|
||||
return gettimeofday(tv, NULL);
|
||||
}
|
||||
#endif /* defined(__APPLE__) */
|
||||
#else
|
||||
return gettimeofday(tv, NULL);
|
||||
#endif
|
||||
}
|
||||
/* port upnp discover : SSDP protocol */
|
||||
#define PORT 1900
|
||||
#define SSDP_PORT 1900
|
||||
#define XSTR(s) STR(s)
|
||||
#define STR(s) #s
|
||||
#define UPNP_MCAST_ADDR "239.255.255.250"
|
||||
|
@ -456,25 +520,25 @@ parseMSEARCHReply(const char * reply, int size,
|
|||
struct UPNPDev *
|
||||
ssdpDiscoverDevices(const char * const deviceTypes[],
|
||||
int delay, const char * multicastif,
|
||||
int sameport,
|
||||
int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error,
|
||||
int searchalltypes)
|
||||
{
|
||||
struct UPNPDev * tmp;
|
||||
struct UPNPDev * devlist = 0;
|
||||
struct UPNPDev * devlist = NULL;
|
||||
unsigned int scope_id = 0;
|
||||
int opt = 1;
|
||||
static const char MSearchMsgFmt[] =
|
||||
"M-SEARCH * HTTP/1.1\r\n"
|
||||
"HOST: %s:" XSTR(PORT) "\r\n"
|
||||
"HOST: %s:" XSTR(SSDP_PORT) "\r\n"
|
||||
"ST: %s\r\n"
|
||||
"MAN: \"ssdp:discover\"\r\n"
|
||||
"MX: %u\r\n"
|
||||
"\r\n";
|
||||
int deviceIndex;
|
||||
char bufr[1536]; /* reception and emission buffer */
|
||||
int sudp;
|
||||
SOCKET sudp;
|
||||
int n;
|
||||
struct sockaddr_storage sockudp_r;
|
||||
unsigned int mx;
|
||||
|
@ -482,23 +546,26 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
|
|||
struct sockaddr_storage sockudp_w;
|
||||
#else
|
||||
int rv;
|
||||
struct addrinfo hints, *servinfo, *p;
|
||||
struct addrinfo hints, *servinfo;
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
MIB_IPFORWARDROW ip_forward;
|
||||
unsigned long _ttl = (unsigned long)ttl;
|
||||
#endif
|
||||
int linklocal = 1;
|
||||
int linklocal = 0; /* try first with site-local multicast */
|
||||
int sentok;
|
||||
|
||||
if(error)
|
||||
*error = MINISSDPC_UNKNOWN_ERROR;
|
||||
|
||||
if(localport==UPNP_LOCAL_PORT_SAME)
|
||||
localport = SSDP_PORT;
|
||||
|
||||
#ifdef _WIN32
|
||||
sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
#else
|
||||
sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, 0);
|
||||
#endif
|
||||
if(sudp < 0)
|
||||
if(ISINVALID(sudp))
|
||||
{
|
||||
if(error)
|
||||
*error = MINISSDPC_SOCKET_ERROR;
|
||||
|
@ -510,14 +577,14 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
|
|||
if(ipv6) {
|
||||
struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_r;
|
||||
p->sin6_family = AF_INET6;
|
||||
if(sameport)
|
||||
p->sin6_port = htons(PORT);
|
||||
if(localport > 0 && localport < 65536)
|
||||
p->sin6_port = htons((unsigned short)localport);
|
||||
p->sin6_addr = in6addr_any; /* in6addr_any is not available with MinGW32 3.4.2 */
|
||||
} else {
|
||||
struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_r;
|
||||
p->sin_family = AF_INET;
|
||||
if(sameport)
|
||||
p->sin_port = htons(PORT);
|
||||
if(localport > 0 && localport < 65536)
|
||||
p->sin_port = htons((unsigned short)localport);
|
||||
p->sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
|
@ -525,61 +592,98 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
|
|||
* 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;
|
||||
if(!ipv6) {
|
||||
DWORD ifbestidx;
|
||||
#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
// While we don't need IPv6 support, the IPv4 only function is not available in UWP apps.
|
||||
SOCKADDR_IN destAddr;
|
||||
memset(&destAddr, 0, sizeof(destAddr));
|
||||
destAddr.sin_family = AF_INET;
|
||||
destAddr.sin_addr.s_addr = inet_addr("223.255.255.255");
|
||||
destAddr.sin_port = 0;
|
||||
if (GetBestInterfaceEx((struct sockaddr *)&destAddr, &ifbestidx) == NO_ERROR) {
|
||||
#else
|
||||
if (GetBestInterface(inet_addr("223.255.255.255"), &ifbestidx) == NO_ERROR) {
|
||||
#endif
|
||||
int i;
|
||||
#ifdef DEBUG
|
||||
printf("ifIndex=%lu nextHop=%lx \n", ip_forward.dwForwardIfIndex, ip_forward.dwForwardNextHop);
|
||||
#endif
|
||||
pIPAddrTable = (MIB_IPADDRTABLE *) malloc(sizeof (MIB_IPADDRTABLE));
|
||||
if(pIPAddrTable) {
|
||||
if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) {
|
||||
free(pIPAddrTable);
|
||||
pIPAddrTable = (MIB_IPADDRTABLE *) malloc(dwSize);
|
||||
DWORD dwRetVal = NO_ERROR;
|
||||
PIP_ADAPTER_ADDRESSES pAddresses = NULL;
|
||||
ULONG outBufLen = 15360;
|
||||
int Iterations;
|
||||
PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
|
||||
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
|
||||
|
||||
for (Iterations = 0; Iterations < 3; Iterations++) {
|
||||
pAddresses = (IP_ADAPTER_ADDRESSES *) HeapAlloc(GetProcessHeap(), 0, outBufLen);
|
||||
if (pAddresses == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
dwRetVal = GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &outBufLen);
|
||||
|
||||
if (dwRetVal != ERROR_BUFFER_OVERFLOW) {
|
||||
break;
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, pAddresses);
|
||||
pAddresses = NULL;
|
||||
}
|
||||
}
|
||||
if(pIPAddrTable) {
|
||||
dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 );
|
||||
|
||||
if (dwRetVal == NO_ERROR) {
|
||||
pCurrAddresses = pAddresses;
|
||||
while (pCurrAddresses) {
|
||||
#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);
|
||||
int i;
|
||||
PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = NULL;
|
||||
PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = NULL;
|
||||
|
||||
printf("\tIfIndex (IPv4 interface): %u\n", pCurrAddresses->IfIndex);
|
||||
printf("\tAdapter name: %s\n", pCurrAddresses->AdapterName);
|
||||
pUnicast = pCurrAddresses->FirstUnicastAddress;
|
||||
if (pUnicast != NULL) {
|
||||
for (i = 0; pUnicast != NULL; i++) {
|
||||
printf("\tIP Address[%d]: \t%s\n", i, inet_ntoa(((PSOCKADDR_IN)pUnicast->Address.lpSockaddr)->sin_addr) );
|
||||
pUnicast = pUnicast->Next;
|
||||
}
|
||||
printf("\tNumber of Unicast Addresses: %d\n", i);
|
||||
}
|
||||
pAnycast = pCurrAddresses->FirstAnycastAddress;
|
||||
if (pAnycast) {
|
||||
for (i = 0; pAnycast != NULL; i++) {
|
||||
printf("\tAnycast Address[%d]: \t%s\n", i, inet_ntoa(((PSOCKADDR_IN)pAnycast->Address.lpSockaddr)->sin_addr) );
|
||||
pAnycast = pAnycast->Next;
|
||||
}
|
||||
printf("\tNumber of Anycast Addresses: %d\n", i);
|
||||
}
|
||||
pMulticast = pCurrAddresses->FirstMulticastAddress;
|
||||
if (pMulticast) {
|
||||
for (i = 0; pMulticast != NULL; i++) {
|
||||
printf("\tMulticast Address[%d]: \t%s\n", i, inet_ntoa(((PSOCKADDR_IN)pMulticast->Address.lpSockaddr)->sin_addr) );
|
||||
pMulticast = pMulticast->Next;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
if (pIPAddrTable->table[i].dwIndex == ip_forward.dwForwardIfIndex) {
|
||||
pUnicast = pCurrAddresses->FirstUnicastAddress;
|
||||
if (pCurrAddresses->IfIndex == ifbestidx && pUnicast != NULL) {
|
||||
SOCKADDR_IN *ipv4 = (SOCKADDR_IN *)(pUnicast->Address.lpSockaddr);
|
||||
/* 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;
|
||||
mc_if.s_addr = ipv4->sin_addr.s_addr;
|
||||
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;
|
||||
((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = ipv4->sin_addr.s_addr;
|
||||
#ifndef DEBUG
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
pCurrAddresses = pCurrAddresses->Next;
|
||||
}
|
||||
}
|
||||
free(pIPAddrTable);
|
||||
pIPAddrTable = NULL;
|
||||
if (pAddresses != NULL) {
|
||||
HeapFree(GetProcessHeap(), 0, pAddresses);
|
||||
pAddresses = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
@ -593,20 +697,33 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
|
|||
if(error)
|
||||
*error = MINISSDPC_SOCKET_ERROR;
|
||||
PRINT_SOCKET_ERROR("setsockopt(SO_REUSEADDR,...)");
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(ipv6) {
|
||||
#ifdef _WIN32
|
||||
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&_ttl, sizeof(_ttl)) < 0)
|
||||
DWORD mcastHops = ttl;
|
||||
if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const char *)&mcastHops, sizeof(mcastHops)) < 0)
|
||||
#else /* _WIN32 */
|
||||
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
|
||||
int mcastHops = ttl;
|
||||
if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &mcastHops, sizeof(mcastHops)) < 0)
|
||||
#endif /* _WIN32 */
|
||||
{
|
||||
/* not a fatal error */
|
||||
PRINT_SOCKET_ERROR("setsockopt(IP_MULTICAST_TTL,...)");
|
||||
{
|
||||
PRINT_SOCKET_ERROR("setsockopt(IPV6_MULTICAST_HOPS,...)");
|
||||
}
|
||||
} else {
|
||||
#ifdef _WIN32
|
||||
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&_ttl, sizeof(_ttl)) < 0)
|
||||
#else /* _WIN32 */
|
||||
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
|
||||
#endif /* _WIN32 */
|
||||
{
|
||||
/* not a fatal error */
|
||||
PRINT_SOCKET_ERROR("setsockopt(IP_MULTICAST_TTL,...)");
|
||||
}
|
||||
}
|
||||
|
||||
if(multicastif)
|
||||
if(multicastif && multicastif[0] != '\0')
|
||||
{
|
||||
if(ipv6) {
|
||||
#if !defined(_WIN32)
|
||||
|
@ -614,9 +731,16 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
|
|||
* 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(ifindex == 0)
|
||||
{
|
||||
if(error)
|
||||
*error = MINISSDPC_INVALID_INPUT;
|
||||
fprintf(stderr, "Invalid multicast interface name %s\n", multicastif);
|
||||
goto error;
|
||||
}
|
||||
if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) < 0)
|
||||
{
|
||||
PRINT_SOCKET_ERROR("setsockopt");
|
||||
PRINT_SOCKET_ERROR("setsockopt IPV6_MULTICAST_IF");
|
||||
}
|
||||
#else
|
||||
#ifdef DEBUG
|
||||
|
@ -625,29 +749,67 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
|
|||
#endif
|
||||
} else {
|
||||
struct in_addr mc_if;
|
||||
mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */
|
||||
#if defined(_WIN32)
|
||||
#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
InetPtonA(AF_INET, multicastif, &mc_if);
|
||||
#else
|
||||
mc_if.s_addr = inet_addr(multicastif); /* old Windows SDK do not support InetPtoA() */
|
||||
#endif
|
||||
#else
|
||||
/* was : mc_if.s_addr = inet_addr(multicastif); */ /* ex: 192.168.x.x */
|
||||
if (inet_pton(AF_INET, multicastif, &mc_if.s_addr) <= 0) {
|
||||
mc_if.s_addr = INADDR_NONE;
|
||||
}
|
||||
#endif
|
||||
if(mc_if.s_addr != INADDR_NONE)
|
||||
{
|
||||
((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr;
|
||||
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
|
||||
{
|
||||
PRINT_SOCKET_ERROR("setsockopt");
|
||||
PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
|
||||
}
|
||||
} else {
|
||||
#ifdef HAS_IP_MREQN
|
||||
/* was not an ip address, try with an interface name */
|
||||
#ifndef _WIN32
|
||||
#ifdef HAS_IP_MREQN
|
||||
struct ip_mreqn reqn; /* only defined with -D_BSD_SOURCE or -D_GNU_SOURCE */
|
||||
#endif
|
||||
struct ifreq ifr;
|
||||
int ifrlen = sizeof(ifr);
|
||||
strncpy(ifr.ifr_name, multicastif, IFNAMSIZ);
|
||||
ifr.ifr_name[IFNAMSIZ-1] = '\0';
|
||||
if(ioctl(sudp, SIOCGIFADDR, &ifr, &ifrlen) < 0)
|
||||
{
|
||||
PRINT_SOCKET_ERROR("ioctl(...SIOCGIFADDR...)");
|
||||
goto error;
|
||||
}
|
||||
mc_if.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
|
||||
#ifdef HAS_IP_MREQN
|
||||
memset(&reqn, 0, sizeof(struct ip_mreqn));
|
||||
reqn.imr_address.s_addr = mc_if.s_addr;
|
||||
reqn.imr_ifindex = if_nametoindex(multicastif);
|
||||
if(reqn.imr_ifindex == 0)
|
||||
{
|
||||
if(error)
|
||||
*error = MINISSDPC_INVALID_INPUT;
|
||||
fprintf(stderr, "Invalid multicast ip address / interface name %s\n", multicastif);
|
||||
goto error;
|
||||
}
|
||||
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0)
|
||||
{
|
||||
PRINT_SOCKET_ERROR("setsockopt");
|
||||
PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
|
||||
}
|
||||
#else
|
||||
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
|
||||
{
|
||||
PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
|
||||
}
|
||||
#endif
|
||||
#else /* _WIN32 */
|
||||
#ifdef DEBUG
|
||||
printf("Setting of multicast interface not supported with interface name.\n");
|
||||
#endif
|
||||
#endif
|
||||
#endif /* #ifdef HAS_IP_MREQN / !defined(_WIN32) */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -674,6 +836,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
|
|||
}
|
||||
/* receiving SSDP response packet */
|
||||
for(deviceIndex = 0; deviceTypes[deviceIndex]; deviceIndex++) {
|
||||
sentok = 0;
|
||||
/* sending the SSDP M-SEARCH packet */
|
||||
n = snprintf(bufr, sizeof(bufr),
|
||||
MSearchMsgFmt,
|
||||
|
@ -681,6 +844,11 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
|
|||
(linklocal ? "[" UPNP_MCAST_LL_ADDR "]" : "[" UPNP_MCAST_SL_ADDR "]")
|
||||
: UPNP_MCAST_ADDR,
|
||||
deviceTypes[deviceIndex], mx);
|
||||
if ((unsigned int)n >= sizeof(bufr)) {
|
||||
if(error)
|
||||
*error = MINISSDPC_MEMORY_ERROR;
|
||||
goto error;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
/*printf("Sending %s", bufr);*/
|
||||
printf("Sending M-SEARCH request to %s with ST: %s\n",
|
||||
|
@ -696,14 +864,14 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
|
|||
if(ipv6) {
|
||||
struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_w;
|
||||
p->sin6_family = AF_INET6;
|
||||
p->sin6_port = htons(PORT);
|
||||
p->sin6_port = htons(SSDP_PORT);
|
||||
inet_pton(AF_INET6,
|
||||
linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR,
|
||||
&(p->sin6_addr));
|
||||
} else {
|
||||
struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_w;
|
||||
p->sin_family = AF_INET;
|
||||
p->sin_port = htons(PORT);
|
||||
p->sin_port = htons(SSDP_PORT);
|
||||
p->sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);
|
||||
}
|
||||
n = sendto(sudp, bufr, n, 0, &sockudp_w,
|
||||
|
@ -712,7 +880,8 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
|
|||
if(error)
|
||||
*error = MINISSDPC_SOCKET_ERROR;
|
||||
PRINT_SOCKET_ERROR("sendto");
|
||||
break;
|
||||
} else {
|
||||
sentok = 1;
|
||||
}
|
||||
#else /* #ifdef NO_GETADDRINFO */
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
|
@ -722,7 +891,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
|
|||
if ((rv = getaddrinfo(ipv6
|
||||
? (linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR)
|
||||
: UPNP_MCAST_ADDR,
|
||||
XSTR(PORT), &hints, &servinfo)) != 0) {
|
||||
XSTR(SSDP_PORT), &hints, &servinfo)) != 0) {
|
||||
if(error)
|
||||
*error = MINISSDPC_SOCKET_ERROR;
|
||||
#ifdef _WIN32
|
||||
|
@ -731,105 +900,120 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
|
|||
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) {
|
||||
} else {
|
||||
struct addrinfo *p;
|
||||
for(p = servinfo; p; p = p->ai_next) {
|
||||
n = sendto(sudp, bufr, n, 0, p->ai_addr, MSC_CAST_INT p->ai_addrlen);
|
||||
if (n < 0) {
|
||||
#ifdef DEBUG
|
||||
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
|
||||
if (getnameinfo(p->ai_addr, p->ai_addrlen, hbuf, sizeof(hbuf), sbuf,
|
||||
sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
|
||||
fprintf(stderr, "host:%s port:%s\n", hbuf, sbuf);
|
||||
}
|
||||
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
|
||||
if (getnameinfo(p->ai_addr, (socklen_t)p->ai_addrlen, hbuf, sizeof(hbuf), sbuf,
|
||||
sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
|
||||
fprintf(stderr, "host:%s port:%s\n", hbuf, sbuf);
|
||||
}
|
||||
#endif
|
||||
PRINT_SOCKET_ERROR("sendto");
|
||||
continue;
|
||||
PRINT_SOCKET_ERROR("sendto");
|
||||
continue;
|
||||
} else {
|
||||
sentok = 1;
|
||||
}
|
||||
}
|
||||
freeaddrinfo(servinfo);
|
||||
}
|
||||
freeaddrinfo(servinfo);
|
||||
if(n < 0) {
|
||||
if(!sentok) {
|
||||
if(error)
|
||||
*error = MINISSDPC_SOCKET_ERROR;
|
||||
break;
|
||||
}
|
||||
#endif /* #ifdef NO_GETADDRINFO */
|
||||
/* Waiting for SSDP REPLY packet to M-SEARCH
|
||||
* if searchalltypes is set, enter the loop only
|
||||
* when the last deviceType is reached */
|
||||
if(!searchalltypes || !deviceTypes[deviceIndex + 1]) do {
|
||||
n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id);
|
||||
if (n < 0) {
|
||||
/* error */
|
||||
if(error)
|
||||
*error = MINISSDPC_SOCKET_ERROR;
|
||||
goto error;
|
||||
} else if (n == 0) {
|
||||
/* no data or Time Out */
|
||||
#ifdef DEBUG
|
||||
printf("NODATA or TIMEOUT\n");
|
||||
#endif /* DEBUG */
|
||||
if (devlist && !searchalltypes) {
|
||||
/* found some devices, stop now*/
|
||||
if((sentok && !searchalltypes) || !deviceTypes[deviceIndex + 1]) {
|
||||
struct timeval start = {0, 0}, current = {0, 0};
|
||||
upnp_gettimeofday(&start);
|
||||
do {
|
||||
n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id);
|
||||
if (n < 0) {
|
||||
/* error */
|
||||
if(error)
|
||||
*error = MINISSDPC_SUCCESS;
|
||||
*error = MINISSDPC_SOCKET_ERROR;
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
const char * descURL=NULL;
|
||||
int urlsize=0;
|
||||
const char * st=NULL;
|
||||
int stsize=0;
|
||||
const char * usn=NULL;
|
||||
int usnsize=0;
|
||||
parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize, &usn, &usnsize);
|
||||
if(st&&descURL) {
|
||||
} else if (n == 0) {
|
||||
/* no data or Time Out */
|
||||
#ifdef DEBUG
|
||||
printf("M-SEARCH Reply:\n ST: %.*s\n USN: %.*s\n Location: %.*s\n",
|
||||
stsize, st, usnsize, (usn?usn:""), urlsize, descURL);
|
||||
printf("NODATA or TIMEOUT\n");
|
||||
#endif /* DEBUG */
|
||||
for(tmp=devlist; tmp; tmp = tmp->pNext) {
|
||||
if(memcmp(tmp->descURL, descURL, urlsize) == 0 &&
|
||||
tmp->descURL[urlsize] == '\0' &&
|
||||
memcmp(tmp->st, st, stsize) == 0 &&
|
||||
tmp->st[stsize] == '\0' &&
|
||||
(usnsize == 0 || memcmp(tmp->usn, usn, usnsize) == 0) &&
|
||||
tmp->usn[usnsize] == '\0')
|
||||
break;
|
||||
}
|
||||
/* at the exit of the loop above, tmp is null if
|
||||
* no duplicate device was found */
|
||||
if(tmp)
|
||||
continue;
|
||||
tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize);
|
||||
if(!tmp) {
|
||||
/* memory allocation error */
|
||||
if (devlist && !searchalltypes) {
|
||||
/* found some devices, stop now*/
|
||||
if(error)
|
||||
*error = MINISSDPC_MEMORY_ERROR;
|
||||
*error = MINISSDPC_SUCCESS;
|
||||
goto error;
|
||||
}
|
||||
tmp->pNext = devlist;
|
||||
tmp->descURL = tmp->buffer;
|
||||
tmp->st = tmp->buffer + 1 + urlsize;
|
||||
tmp->usn = tmp->st + 1 + stsize;
|
||||
memcpy(tmp->buffer, descURL, urlsize);
|
||||
tmp->buffer[urlsize] = '\0';
|
||||
memcpy(tmp->st, st, stsize);
|
||||
tmp->buffer[urlsize+1+stsize] = '\0';
|
||||
if(usn != NULL)
|
||||
memcpy(tmp->usn, usn, usnsize);
|
||||
tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0';
|
||||
tmp->scope_id = scope_id;
|
||||
devlist = tmp;
|
||||
} else {
|
||||
const char * descURL=NULL;
|
||||
int urlsize=0;
|
||||
const char * st=NULL;
|
||||
int stsize=0;
|
||||
const char * usn=NULL;
|
||||
int usnsize=0;
|
||||
parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize, &usn, &usnsize);
|
||||
if(st&&descURL) {
|
||||
#ifdef DEBUG
|
||||
printf("M-SEARCH Reply:\n ST: %.*s\n USN: %.*s\n Location: %.*s\n",
|
||||
stsize, st, usnsize, (usn?usn:""), urlsize, descURL);
|
||||
#endif /* DEBUG */
|
||||
for(tmp=devlist; tmp; tmp = tmp->pNext) {
|
||||
if(strncmp(tmp->descURL, descURL, urlsize) == 0 &&
|
||||
tmp->descURL[urlsize] == '\0' &&
|
||||
strncmp(tmp->st, st, stsize) == 0 &&
|
||||
tmp->st[stsize] == '\0' &&
|
||||
(usnsize == 0 || strncmp(tmp->usn, usn, usnsize) == 0) &&
|
||||
tmp->usn[usnsize] == '\0')
|
||||
break;
|
||||
}
|
||||
/* at the exit of the loop above, tmp is null if
|
||||
* no duplicate device was found */
|
||||
if(tmp)
|
||||
continue;
|
||||
tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize+3);
|
||||
if(!tmp) {
|
||||
/* memory allocation error */
|
||||
if(error)
|
||||
*error = MINISSDPC_MEMORY_ERROR;
|
||||
goto error;
|
||||
}
|
||||
tmp->pNext = devlist;
|
||||
tmp->descURL = tmp->buffer;
|
||||
tmp->st = tmp->buffer + 1 + urlsize;
|
||||
tmp->usn = tmp->st + 1 + stsize;
|
||||
memcpy(tmp->buffer, descURL, urlsize);
|
||||
tmp->buffer[urlsize] = '\0';
|
||||
memcpy(tmp->st, st, stsize);
|
||||
tmp->buffer[urlsize+1+stsize] = '\0';
|
||||
if(usn != NULL)
|
||||
memcpy(tmp->usn, usn, usnsize);
|
||||
tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0';
|
||||
tmp->scope_id = scope_id;
|
||||
devlist = tmp;
|
||||
}
|
||||
if (upnp_gettimeofday(¤t) >= 0) {
|
||||
/* exit the loop if delay is reached */
|
||||
long interval = (current.tv_sec - start.tv_sec) * 1000;
|
||||
interval += (current.tv_usec - start.tv_usec) / 1000;
|
||||
if (interval > (long)delay)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(n > 0);
|
||||
} while(n > 0);
|
||||
}
|
||||
if(ipv6) {
|
||||
/* switch linklocal flag */
|
||||
if(linklocal) {
|
||||
linklocal = 0;
|
||||
--deviceIndex;
|
||||
} else {
|
||||
/* try again with linklocal multicast */
|
||||
linklocal = 1;
|
||||
--deviceIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -837,4 +1021,3 @@ error:
|
|||
closesocket(sudp);
|
||||
return devlist;
|
||||
}
|
||||
|
||||
|
|
8
Externals/miniupnpc/src/minissdpc.h
vendored
8
Externals/miniupnpc/src/minissdpc.h
vendored
|
@ -32,20 +32,20 @@ MINIUPNP_LIBSPEC int
|
|||
connectToMiniSSDPD(const char * socketpath);
|
||||
|
||||
MINIUPNP_LIBSPEC int
|
||||
disconnectFromMiniSSDPD(int fd);
|
||||
disconnectFromMiniSSDPD(int s);
|
||||
|
||||
MINIUPNP_LIBSPEC int
|
||||
requestDevicesFromMiniSSDPD(int fd, const char * devtype);
|
||||
requestDevicesFromMiniSSDPD(int s, const char * devtype);
|
||||
|
||||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
receiveDevicesFromMiniSSDPD(int fd, int * error);
|
||||
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 sameport,
|
||||
int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error,
|
||||
int searchalltypes);
|
||||
|
|
292
Externals/miniupnpc/src/miniupnpc.c
vendored
292
Externals/miniupnpc/src/miniupnpc.c
vendored
|
@ -1,8 +1,9 @@
|
|||
/* $Id: miniupnpc.c,v 1.135 2015/07/23 20:40:08 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Web : http://miniupnp.free.fr/
|
||||
/* $Id: miniupnpc.c,v 1.165 2025/01/10 22:57:21 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-2015 Thomas Bernard
|
||||
* copyright (c) 2005-2025 Thomas Bernard
|
||||
* This software is subjet to the conditions detailed in the
|
||||
* provided LICENSE file. */
|
||||
#include <stdlib.h>
|
||||
|
@ -14,7 +15,7 @@
|
|||
#include <ws2tcpip.h>
|
||||
#include <io.h>
|
||||
#include <iphlpapi.h>
|
||||
#define snprintf _snprintf
|
||||
#include "win32_snprintf.h"
|
||||
#define strdup _strdup
|
||||
#ifndef strncasecmp
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
|
@ -55,13 +56,15 @@
|
|||
#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 begining of a string with a constant string */
|
||||
#define COMPARE(str, cstr) (0==memcmp(str, cstr, sizeof(cstr) - 1))
|
||||
/* 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
|
||||
|
@ -89,98 +92,119 @@ MINIUPNP_LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGD
|
|||
#endif
|
||||
}
|
||||
|
||||
/* simpleUPnPcommand2 :
|
||||
/* simpleUPnPcommand :
|
||||
* 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 *
|
||||
simpleUPnPcommand(const char * url, const char * service,
|
||||
const char * action, const struct UPNParg * args,
|
||||
int * bufsize)
|
||||
{
|
||||
char hostname[MAXHOSTNAMELEN+1];
|
||||
unsigned short port = 0;
|
||||
char * path;
|
||||
char soapact[128];
|
||||
char soapbody[2048];
|
||||
int soapbodylen;
|
||||
char * buf;
|
||||
int n;
|
||||
int n;
|
||||
int status_code;
|
||||
SOCKET s;
|
||||
|
||||
*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 "
|
||||
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);
|
||||
"\r\n", action, service, action);
|
||||
if ((unsigned int)soapbodylen >= sizeof(soapbody))
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
char * p;
|
||||
const char * pe, * pv;
|
||||
int soapbodylen;
|
||||
const char * const pend = soapbody + sizeof(soapbody);
|
||||
soapbodylen = snprintf(soapbody, sizeof(soapbody),
|
||||
"<?xml version=\"1.0\"?>\r\n"
|
||||
"<" SOAPPREFIX ":Envelope "
|
||||
"<" 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)
|
||||
{
|
||||
/* check that we are never overflowing the string... */
|
||||
if(soapbody + sizeof(soapbody) <= p + 100)
|
||||
{
|
||||
/* we keep a margin of at least 100 bytes */
|
||||
if(p >= pend) /* check for space to write next byte */
|
||||
return NULL;
|
||||
}
|
||||
*(p++) = '<';
|
||||
|
||||
pe = args->elt;
|
||||
while(*pe)
|
||||
while(p < pend && *pe)
|
||||
*(p++) = *(pe++);
|
||||
|
||||
if(p >= pend) /* check for space to write next byte */
|
||||
return NULL;
|
||||
*(p++) = '>';
|
||||
|
||||
if((pv = args->val))
|
||||
{
|
||||
while(*pv)
|
||||
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(*pe)
|
||||
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(*pe)
|
||||
while(p < pend && *pe)
|
||||
*(p++) = *(pe++);
|
||||
|
||||
strncpy(p, "></" SOAPPREFIX ":Body></" SOAPPREFIX ":Envelope>\r\n",
|
||||
soapbody + sizeof(soapbody) - p);
|
||||
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(s < 0) {
|
||||
s = connecthostport(hostname, port, 0);
|
||||
if(s < 0) {
|
||||
/* failed to connect */
|
||||
return NULL;
|
||||
}
|
||||
s = connecthostport(hostname, port, 0);
|
||||
if(ISINVALID(s)) {
|
||||
/* failed to connect */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, httpversion);
|
||||
n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, "1.1");
|
||||
if(n<=0) {
|
||||
#ifdef DEBUG
|
||||
printf("Error sending SOAP request\n");
|
||||
|
@ -189,43 +213,21 @@ char * simpleUPnPcommand2(int s, const char * url, const char * service,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
buf = getHTTPResponse(s, bufsize);
|
||||
buf = getHTTPResponse(s, bufsize, &status_code);
|
||||
#ifdef DEBUG
|
||||
if(*bufsize > 0 && buf)
|
||||
{
|
||||
printf("SOAP Response :\n%.*s\n", *bufsize, 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(s, url, service, action, args, bufsize, "1.1");
|
||||
#else
|
||||
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");
|
||||
}
|
||||
#endif
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* upnpDiscoverDevices() :
|
||||
* return a chained list of all devices found or NULL if
|
||||
* no devices was found.
|
||||
|
@ -237,7 +239,7 @@ char * simpleUPnPcommand(int s, const char * url, const char * service,
|
|||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
upnpDiscoverDevices(const char * const deviceTypes[],
|
||||
int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int sameport,
|
||||
const char * minissdpdsock, int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error,
|
||||
int searchalltypes)
|
||||
|
@ -254,30 +256,32 @@ upnpDiscoverDevices(const char * const deviceTypes[],
|
|||
/* first try to get infos from minissdpd ! */
|
||||
if(!minissdpdsock)
|
||||
minissdpdsock = "/var/run/minissdpd.sock";
|
||||
for(deviceIndex = 0; deviceTypes[deviceIndex]; deviceIndex++) {
|
||||
struct UPNPDev * minissdpd_devlist;
|
||||
int only_rootdevice = 1;
|
||||
minissdpd_devlist = getDevicesFromMiniSSDPD(deviceTypes[deviceIndex],
|
||||
minissdpdsock, 0);
|
||||
if(minissdpd_devlist) {
|
||||
#ifdef DEBUG
|
||||
printf("returned by MiniSSDPD: %s\t%s\n",
|
||||
minissdpd_devlist->st, minissdpd_devlist->descURL);
|
||||
#endif /* DEBUG */
|
||||
if(!strstr(minissdpd_devlist->st, "rootdevice"))
|
||||
only_rootdevice = 0;
|
||||
for(tmp = minissdpd_devlist; tmp->pNext != NULL; tmp = tmp->pNext) {
|
||||
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",
|
||||
tmp->pNext->st, tmp->pNext->descURL);
|
||||
minissdpd_devlist->st, minissdpd_devlist->descURL);
|
||||
#endif /* DEBUG */
|
||||
if(!strstr(tmp->st, "rootdevice"))
|
||||
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;
|
||||
}
|
||||
tmp->pNext = devlist;
|
||||
devlist = minissdpd_devlist;
|
||||
if(!searchalltypes && !only_rootdevice)
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(tmp = devlist; tmp != NULL; tmp = tmp->pNext) {
|
||||
|
@ -288,12 +292,14 @@ upnpDiscoverDevices(const char * const deviceTypes[],
|
|||
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, sameport,
|
||||
discovered_devlist = ssdpDiscoverDevices(deviceTypes, delay, multicastif, localport,
|
||||
ipv6, ttl, error, searchalltypes);
|
||||
if(devlist == NULL)
|
||||
devlist = discovered_devlist;
|
||||
|
@ -308,7 +314,7 @@ upnpDiscoverDevices(const char * const deviceTypes[],
|
|||
/* upnpDiscover() Discover IGD device */
|
||||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
upnpDiscover(int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int sameport,
|
||||
const char * minissdpdsock, int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error)
|
||||
{
|
||||
|
@ -325,14 +331,14 @@ upnpDiscover(int delay, const char * multicastif,
|
|||
0
|
||||
};
|
||||
return upnpDiscoverDevices(deviceList,
|
||||
delay, multicastif, minissdpdsock, sameport,
|
||||
delay, multicastif, minissdpdsock, localport,
|
||||
ipv6, ttl, error, 0);
|
||||
}
|
||||
|
||||
/* upnpDiscoverAll() Discover all UPnP devices */
|
||||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
upnpDiscoverAll(int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int sameport,
|
||||
const char * minissdpdsock, int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error)
|
||||
{
|
||||
|
@ -342,14 +348,14 @@ upnpDiscoverAll(int delay, const char * multicastif,
|
|||
0
|
||||
};
|
||||
return upnpDiscoverDevices(deviceList,
|
||||
delay, multicastif, minissdpdsock, sameport,
|
||||
delay, multicastif, minissdpdsock, localport,
|
||||
ipv6, ttl, error, 0);
|
||||
}
|
||||
|
||||
/* upnpDiscoverDevice() Discover a specific device */
|
||||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
upnpDiscoverDevice(const char * device, int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int sameport,
|
||||
const char * minissdpdsock, int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error)
|
||||
{
|
||||
|
@ -358,7 +364,7 @@ upnpDiscoverDevice(const char * device, int delay, const char * multicastif,
|
|||
0
|
||||
};
|
||||
return upnpDiscoverDevices(deviceList,
|
||||
delay, multicastif, minissdpdsock, sameport,
|
||||
delay, multicastif, minissdpdsock, localport,
|
||||
ipv6, ttl, error, 0);
|
||||
}
|
||||
|
||||
|
@ -366,7 +372,7 @@ static char *
|
|||
build_absolute_url(const char * baseurl, const char * descURL,
|
||||
const char * url, unsigned int scope_id)
|
||||
{
|
||||
int l, n;
|
||||
size_t l, n;
|
||||
char * s;
|
||||
const char * base;
|
||||
char * p;
|
||||
|
@ -409,7 +415,7 @@ build_absolute_url(const char * baseurl, const char * descURL,
|
|||
memcpy(s, base, n);
|
||||
if(scope_id != 0) {
|
||||
s[n] = '\0';
|
||||
if(0 == memcmp(s, "http://[fe80:", 13)) {
|
||||
if(n > 13 && 0 == memcmp(s, "http://[fe80:", 13)) {
|
||||
/* this is a linklocal IPv6 address */
|
||||
p = strchr(s, ']');
|
||||
if(p) {
|
||||
|
@ -498,23 +504,29 @@ UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data)
|
|||
/* 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
|
||||
* 0 = NO IGD found (UPNP_NO_IGD)
|
||||
* 1 = A valid connected IGD has been found (UPNP_CONNECTED_IGD)
|
||||
* 2 = A valid connected IGD has been found but its
|
||||
* IP address is reserved (non routable) (UPNP_PRIVATEIP_IGD)
|
||||
* 3 = A valid IGD has been found but it reported as
|
||||
* not connected (UPNP_DISCONNECTED_IGD)
|
||||
* 4 = an UPnP device has been found but was not recognized as an IGD
|
||||
* (UPNP_UNKNOWN_DEVICE)
|
||||
*
|
||||
* In any positive non zero return case, the urls and data structures
|
||||
* passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
|
||||
* passed as parameters are set. 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 IGDdatas * data,
|
||||
char * lanaddr, int lanaddrlen,
|
||||
char * wanaddr, int wanaddrlen)
|
||||
{
|
||||
struct xml_desc {
|
||||
char lanaddr[40];
|
||||
char wanaddr[40];
|
||||
char * xml;
|
||||
int size;
|
||||
int is_igd;
|
||||
|
@ -522,9 +534,10 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
|
|||
struct UPNPDev * dev;
|
||||
int ndev = 0;
|
||||
int i;
|
||||
int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */
|
||||
int n_igd = 0;
|
||||
char extIpAddr[16];
|
||||
int state = -1; /* state 1 : IGD connected. State 2 : connected with reserved IP.
|
||||
* State 3 : IGD. State 4 : anything */
|
||||
int status_code = -1;
|
||||
|
||||
if(!devlist)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
|
@ -535,20 +548,18 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
|
|||
/* counting total number of devices in the list */
|
||||
for(dev = devlist; dev; dev = dev->pNext)
|
||||
ndev++;
|
||||
if(ndev > 0)
|
||||
{
|
||||
desc = calloc(ndev, sizeof(struct xml_desc));
|
||||
if(!desc)
|
||||
return -1; /* memory allocation error */
|
||||
}
|
||||
/* 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),
|
||||
lanaddr, lanaddrlen,
|
||||
dev->scope_id);
|
||||
desc[i].lanaddr, sizeof(desc[i].lanaddr),
|
||||
dev->scope_id, &status_code);
|
||||
#ifdef DEBUG
|
||||
if(!desc[i].xml)
|
||||
{
|
||||
|
@ -564,12 +575,11 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
|
|||
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:"))
|
||||
{
|
||||
desc[i].is_igd = 1;
|
||||
n_igd++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* iterate the list to find a device depending on state */
|
||||
for(state = 1; state <= 3; state++)
|
||||
for(state = 1; state <= 4; state++)
|
||||
{
|
||||
for(dev = devlist, i = 0; dev; dev = dev->pNext, i++)
|
||||
{
|
||||
|
@ -578,22 +588,28 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
|
|||
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 )
|
||||
if(desc[i].is_igd || state >= 4 )
|
||||
{
|
||||
int is_connected;
|
||||
|
||||
GetUPNPUrls(urls, data, dev->descURL, dev->scope_id);
|
||||
|
||||
/* in state 2 and 3 we dont test if device is connected ! */
|
||||
if(state >= 2)
|
||||
/* in state 3 and 4 we don't test if device is connected ! */
|
||||
if(state >= 3)
|
||||
goto free_and_return;
|
||||
is_connected = UPNPIGD_IsConnected(urls, data);
|
||||
#ifdef DEBUG
|
||||
printf("UPNPIGD_IsConnected(%s) = %d\n",
|
||||
urls->controlURL,
|
||||
UPNPIGD_IsConnected(urls, data));
|
||||
urls->controlURL, is_connected);
|
||||
#endif
|
||||
/* checks that status is connected AND there is a external IP address assigned */
|
||||
if(UPNPIGD_IsConnected(urls, data)
|
||||
&& (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0))
|
||||
goto free_and_return;
|
||||
if(is_connected) {
|
||||
if(state >= 2)
|
||||
goto free_and_return;
|
||||
if(UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, desc[i].wanaddr) == 0
|
||||
&& !addr_is_reserved(desc[i].wanaddr))
|
||||
goto free_and_return;
|
||||
}
|
||||
FreeUPNPUrls(urls);
|
||||
if(data->second.servicetype[0] != '\0') {
|
||||
#ifdef DEBUG
|
||||
|
@ -605,14 +621,18 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
|
|||
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,
|
||||
UPNPIGD_IsConnected(urls, data));
|
||||
urls->controlURL, is_connected);
|
||||
#endif
|
||||
if(UPNPIGD_IsConnected(urls, data)
|
||||
&& (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0))
|
||||
goto free_and_return;
|
||||
if(is_connected) {
|
||||
if(state >= 2)
|
||||
goto free_and_return;
|
||||
if(UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, desc[i].wanaddr) == 0
|
||||
&& !addr_is_reserved(desc[i].wanaddr))
|
||||
goto free_and_return;
|
||||
}
|
||||
FreeUPNPUrls(urls);
|
||||
}
|
||||
}
|
||||
|
@ -622,14 +642,15 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
|
|||
}
|
||||
state = 0;
|
||||
free_and_return:
|
||||
if(desc) {
|
||||
for(i = 0; i < ndev; i++) {
|
||||
if(desc[i].xml) {
|
||||
free(desc[i].xml);
|
||||
}
|
||||
}
|
||||
free(desc);
|
||||
if (state >= 1 && state <= 4 && i < ndev) {
|
||||
if (lanaddr != NULL)
|
||||
strncpy(lanaddr, desc[i].lanaddr, lanaddrlen);
|
||||
if (wanaddr != NULL)
|
||||
strncpy(wanaddr, desc[i].wanaddr, wanaddrlen);
|
||||
}
|
||||
for(i = 0; i < ndev; i++)
|
||||
free(desc[i].xml);
|
||||
free(desc);
|
||||
return state;
|
||||
}
|
||||
|
||||
|
@ -646,18 +667,17 @@ UPNP_GetIGDFromUrl(const char * rootdescurl,
|
|||
{
|
||||
char * descXML;
|
||||
int descXMLsize = 0;
|
||||
|
||||
descXML = miniwget_getaddr(rootdescurl, &descXMLsize,
|
||||
lanaddr, lanaddrlen, 0);
|
||||
lanaddr, lanaddrlen, 0, NULL);
|
||||
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, 0);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
271
Externals/miniupnpc/src/miniupnpc.h
vendored
271
Externals/miniupnpc/src/miniupnpc.h
vendored
|
@ -1,139 +1,298 @@
|
|||
/* $Id: miniupnpc.h,v 1.44 2015/07/23 20:40:10 nanard Exp $ */
|
||||
/* Project: miniupnp
|
||||
* http://miniupnp.free.fr/
|
||||
/* $Id: miniupnpc.h,v 1.76 2025/03/05 10:35:57 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-2015 Thomas Bernard
|
||||
* Copyright (c) 2005-2025 Thomas Bernard
|
||||
* This software is subjects to the conditions detailed
|
||||
* in the LICENCE file provided within this distribution */
|
||||
#ifndef MINIUPNPC_H_INCLUDED
|
||||
#define MINIUPNPC_H_INCLUDED
|
||||
|
||||
/*! \file miniupnpc.h
|
||||
* \brief Main C API for MiniUPnPc
|
||||
*
|
||||
* Contains functions to discover devices and check for device validity
|
||||
* or connectivity.
|
||||
*
|
||||
* \mainpage MiniUPnPc API documentation
|
||||
* MiniUPnPc (MiniUPnP client) is a library implementing a UPnP
|
||||
* Internet Gateway Device (IGD) control point.
|
||||
*
|
||||
* It should be used by applications that needs to listen to incoming
|
||||
* traffic from the internet which are running on a LAN where a
|
||||
* UPnP IGD is running on the router (or gateway).
|
||||
*
|
||||
* See more documentation on the website http://miniupnp.free.fr
|
||||
* or https://miniupnp.tuxfamily.org/ or GitHub :
|
||||
* https://github.com/miniupnp/miniupnp/tree/master/miniupnpc
|
||||
*/
|
||||
#include "miniupnpc_declspec.h"
|
||||
#include "igd_desc_parse.h"
|
||||
#include "upnpdev.h"
|
||||
|
||||
/* error codes : */
|
||||
/*! \brief value for success */
|
||||
#define UPNPDISCOVER_SUCCESS (0)
|
||||
/*! \brief value for unknown error */
|
||||
#define UPNPDISCOVER_UNKNOWN_ERROR (-1)
|
||||
/*! \brief value for a socket error */
|
||||
#define UPNPDISCOVER_SOCKET_ERROR (-101)
|
||||
/*! \brief value for a memory allocation error */
|
||||
#define UPNPDISCOVER_MEMORY_ERROR (-102)
|
||||
|
||||
/* versions : */
|
||||
#define MINIUPNPC_VERSION "1.9"
|
||||
#define MINIUPNPC_API_VERSION 14
|
||||
/*! \brief software version */
|
||||
#define MINIUPNPC_VERSION "2.3.2"
|
||||
/*! \brief C API version */
|
||||
#define MINIUPNPC_API_VERSION 20
|
||||
|
||||
/*! \brief any (ie system chosen) port */
|
||||
#define UPNP_LOCAL_PORT_ANY 0
|
||||
/*! \brief Use as an alias for 1900 for backwards compatibility */
|
||||
#define UPNP_LOCAL_PORT_SAME 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Structures definitions : */
|
||||
struct UPNParg { const char * elt; const char * val; };
|
||||
|
||||
/*!
|
||||
* \brief UPnP method argument
|
||||
*/
|
||||
struct UPNParg {
|
||||
const char * elt; /*!< \brief UPnP argument name */
|
||||
const char * val; /*!< \brief UPnP argument value */
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief execute a UPnP method (SOAP action)
|
||||
*
|
||||
* \param[in] url Control URL for the service
|
||||
* \param[in] service service to use
|
||||
* \param[in] action action to call
|
||||
* \param[in] args action arguments
|
||||
* \param[out] bufsize the size of the returned buffer
|
||||
* \return NULL in case of error or the raw XML response
|
||||
*/
|
||||
char *
|
||||
simpleUPnPcommand(int, const char *, const char *,
|
||||
const char *, struct UPNParg *,
|
||||
int *);
|
||||
simpleUPnPcommand(const char * url, const char * service,
|
||||
const char * action, const struct UPNParg * args,
|
||||
int * bufsize);
|
||||
|
||||
/* upnpDiscover()
|
||||
* discover UPnP devices on the network.
|
||||
/*!
|
||||
* \brief Discover UPnP IGD on the network.
|
||||
*
|
||||
* The discovered devices are returned as a chained list.
|
||||
* It is up to the caller to free the list with freeUPNPDevlist().
|
||||
* delay (in millisecond) is the maximum time for waiting any device
|
||||
* response.
|
||||
* If available, device list will be obtained from MiniSSDPd.
|
||||
* Default path for minissdpd socket will be used if minissdpdsock argument
|
||||
* is NULL.
|
||||
* If multicastif is not NULL, it will be used instead of the default
|
||||
* multicast interface for sending SSDP discover packets.
|
||||
* If sameport is not null, SSDP packets will be sent from the source port
|
||||
* 1900 (same as destination port) otherwise system assign a 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. */
|
||||
*
|
||||
* \param[in] delay (in millisecond) maximum time for waiting any device
|
||||
* response
|
||||
* \param[in] multicastif If not NULL, used instead of the default
|
||||
* multicast interface for sending SSDP discover packets
|
||||
* \param[in] minissdpdsock Path to minissdpd socket, default is used if
|
||||
* NULL
|
||||
* \param[in] localport Source port to send SSDP packets.
|
||||
* #UPNP_LOCAL_PORT_SAME for 1900 (same as destination port)
|
||||
* #UPNP_LOCAL_PORT_ANY to let system assign a source port
|
||||
* \param[in] ipv6 0 for IPv4, 1 of IPv6
|
||||
* \param[in] ttl should default to 2 as advised by UDA 1.1
|
||||
* \param[out] error error code when NULL is returned
|
||||
* \return NULL or a linked list
|
||||
*/
|
||||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
upnpDiscover(int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int sameport,
|
||||
const char * minissdpdsock, int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error);
|
||||
|
||||
/*!
|
||||
* \brief Discover all UPnP devices on the network
|
||||
*
|
||||
* search for "ssdp:all"
|
||||
* \param[in] delay (in millisecond) maximum time for waiting any device
|
||||
* response
|
||||
* \param[in] multicastif If not NULL, used instead of the default
|
||||
* multicast interface for sending SSDP discover packets
|
||||
* \param[in] minissdpdsock Path to minissdpd socket, default is used if
|
||||
* NULL
|
||||
* \param[in] localport Source port to send SSDP packets.
|
||||
* #UPNP_LOCAL_PORT_SAME for 1900 (same as destination port)
|
||||
* #UPNP_LOCAL_PORT_ANY to let system assign a source port
|
||||
* \param[in] ipv6 0 for IPv4, 1 of IPv6
|
||||
* \param[in] ttl should default to 2 as advised by UDA 1.1
|
||||
* \param[out] error error code when NULL is returned
|
||||
* \return NULL or a linked list
|
||||
*/
|
||||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
upnpDiscoverAll(int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int sameport,
|
||||
const char * minissdpdsock, int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error);
|
||||
|
||||
/*!
|
||||
* \brief Discover one type of UPnP devices
|
||||
*
|
||||
* \param[in] device device type to search
|
||||
* \param[in] delay (in millisecond) maximum time for waiting any device
|
||||
* response
|
||||
* \param[in] multicastif If not NULL, used instead of the default
|
||||
* multicast interface for sending SSDP discover packets
|
||||
* \param[in] minissdpdsock Path to minissdpd socket, default is used if
|
||||
* NULL
|
||||
* \param[in] localport Source port to send SSDP packets.
|
||||
* #UPNP_LOCAL_PORT_SAME for 1900 (same as destination port)
|
||||
* #UPNP_LOCAL_PORT_ANY to let system assign a source port
|
||||
* \param[in] ipv6 0 for IPv4, 1 of IPv6
|
||||
* \param[in] ttl should default to 2 as advised by UDA 1.1
|
||||
* \param[out] error error code when NULL is returned
|
||||
* \return NULL or a linked list
|
||||
*/
|
||||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
upnpDiscoverDevice(const char * device, int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int sameport,
|
||||
const char * minissdpdsock, int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error);
|
||||
|
||||
/*!
|
||||
* \brief Discover one or several type of UPnP devices
|
||||
*
|
||||
* \param[in] deviceTypes array of device types to search (ending with NULL)
|
||||
* \param[in] delay (in millisecond) maximum time for waiting any device
|
||||
* response
|
||||
* \param[in] multicastif If not NULL, used instead of the default
|
||||
* multicast interface for sending SSDP discover packets
|
||||
* \param[in] minissdpdsock Path to minissdpd socket, default is used if
|
||||
* NULL
|
||||
* \param[in] localport Source port to send SSDP packets.
|
||||
* #UPNP_LOCAL_PORT_SAME for 1900 (same as destination port)
|
||||
* #UPNP_LOCAL_PORT_ANY to let system assign a source port
|
||||
* \param[in] ipv6 0 for IPv4, 1 of IPv6
|
||||
* \param[in] ttl should default to 2 as advised by UDA 1.1
|
||||
* \param[out] error error code when NULL is returned
|
||||
* \param[in] searchalltypes 0 to stop with the first type returning results
|
||||
* \return NULL or a linked list
|
||||
*/
|
||||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
upnpDiscoverDevices(const char * const deviceTypes[],
|
||||
int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int sameport,
|
||||
const char * minissdpdsock, int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error,
|
||||
int searchalltypes);
|
||||
|
||||
/* parserootdesc() :
|
||||
* parse root XML description of a UPnP device and fill the IGDdatas
|
||||
* structure. */
|
||||
MINIUPNP_LIBSPEC void parserootdesc(const char *, int, struct IGDdatas *);
|
||||
/*!
|
||||
* \brief parse root XML description of a UPnP device
|
||||
*
|
||||
* fill the IGDdatas structure.
|
||||
* \param[in] buffer character buffer containing the XML description
|
||||
* \param[in] bufsize size in bytes of the buffer
|
||||
* \param[out] data IGDdatas structure to fill
|
||||
*/
|
||||
MINIUPNP_LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data);
|
||||
|
||||
/* structure used to get fast access to urls
|
||||
* controlURL: controlURL of the WANIPConnection
|
||||
* ipcondescURL: url of the description of the WANIPConnection
|
||||
* controlURL_CIF: controlURL of the WANCommonInterfaceConfig
|
||||
* controlURL_6FC: controlURL of the WANIPv6FirewallControl
|
||||
/*!
|
||||
* \brief structure used to get fast access to urls
|
||||
*/
|
||||
struct UPNPUrls {
|
||||
/*! \brief controlURL of the WANIPConnection */
|
||||
char * controlURL;
|
||||
/*! \brief url of the description of the WANIPConnection */
|
||||
char * ipcondescURL;
|
||||
/*! \brief controlURL of the WANCommonInterfaceConfig */
|
||||
char * controlURL_CIF;
|
||||
/*! \brief controlURL of the WANIPv6FirewallControl */
|
||||
char * controlURL_6FC;
|
||||
/*! \brief url of the root description */
|
||||
char * rootdescURL;
|
||||
};
|
||||
|
||||
/* UPNP_GetValidIGD() :
|
||||
* return values :
|
||||
* 0 = NO IGD found
|
||||
* 1 = A valid connected IGD has been found
|
||||
* 2 = A valid IGD has been found but it reported as
|
||||
* not connected
|
||||
* 3 = an UPnP device has been found but was not recognized as an IGD
|
||||
/*! \brief NO IGD found */
|
||||
#define UPNP_NO_IGD (0)
|
||||
/*! \brief valid and connected IGD */
|
||||
#define UPNP_CONNECTED_IGD (1)
|
||||
/*! \brief valid and connected IGD but with a reserved address
|
||||
* (non routable) */
|
||||
#define UPNP_PRIVATEIP_IGD (2)
|
||||
/*! \brief valid but not connected IGD */
|
||||
#define UPNP_DISCONNECTED_IGD (3)
|
||||
/*! \brief UPnP device not recognized as an IGD */
|
||||
#define UPNP_UNKNOWN_DEVICE (4)
|
||||
|
||||
/*!
|
||||
* \brief look for a valid and possibly connected IGD in the list
|
||||
*
|
||||
* 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.
|
||||
* \param[in] devlist A device list obtained with upnpDiscover() /
|
||||
* upnpDiscoverAll() / upnpDiscoverDevice() / upnpDiscoverDevices()
|
||||
* \param[out] urls Urls for the IGD found
|
||||
* \param[out] data datas for the IGD found
|
||||
* \param[out] lanaddr buffer to copy the local address of the host to reach the IGD
|
||||
* \param[in] lanaddrlen size of the lanaddr buffer
|
||||
* \param[out] wanaddr buffer to copy the public address of the IGD
|
||||
* \param[in] wanaddrlen size of the wanaddr buffer
|
||||
* \return #UPNP_NO_IGD / #UPNP_CONNECTED_IGD / #UPNP_PRIVATEIP_IGD /
|
||||
* #UPNP_DISCONNECTED_IGD / #UPNP_UNKNOWN_DEVICE
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetValidIGD(struct UPNPDev * devlist,
|
||||
struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
char * lanaddr, int lanaddrlen);
|
||||
struct IGDdatas * data,
|
||||
char * lanaddr, int lanaddrlen,
|
||||
char * wanaddr, int wanaddrlen);
|
||||
|
||||
/* UPNP_GetIGDFromUrl()
|
||||
/*!
|
||||
* \brief Get IGD URLs and data for URL
|
||||
*
|
||||
* Used when skipping the discovery process.
|
||||
* When succeding, urls, data, and lanaddr arguments are set.
|
||||
* return value :
|
||||
* 0 - Not ok
|
||||
* 1 - OK */
|
||||
* \param[in] rootdescurl Root description URL of the device
|
||||
* \param[out] urls Urls for the IGD found
|
||||
* \param[out] data datas for the IGD found
|
||||
* \param[out] lanaddr buffer to copy the local address of the host to reach the IGD
|
||||
* \param[in] lanaddrlen size of the lanaddr buffer
|
||||
* \return 0 Not ok / 1 OK
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetIGDFromUrl(const char * rootdescurl,
|
||||
struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
char * lanaddr, int lanaddrlen);
|
||||
|
||||
/*!
|
||||
* \brief Prepare the URLs for usage
|
||||
*
|
||||
* build absolute URLs from the root description
|
||||
* \param[out] urls URL structure to initialize
|
||||
* \param[in] data datas for the IGD
|
||||
* \param[in] descURL root description URL for the IGD
|
||||
* \param[in] scope_id if not 0, add the scope to the linklocal IPv6
|
||||
* addresses in URLs
|
||||
*/
|
||||
MINIUPNP_LIBSPEC void
|
||||
GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *,
|
||||
const char *, unsigned int);
|
||||
GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data,
|
||||
const char * descURL, unsigned int scope_id);
|
||||
|
||||
/*!
|
||||
* \brief free the members of a UPNPUrls struct
|
||||
*
|
||||
* All URLs buffers are freed and zeroed
|
||||
* \param[out] urls
|
||||
*/
|
||||
MINIUPNP_LIBSPEC void
|
||||
FreeUPNPUrls(struct UPNPUrls *);
|
||||
FreeUPNPUrls(struct UPNPUrls * urls);
|
||||
|
||||
/* return 0 or 1 */
|
||||
MINIUPNP_LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *);
|
||||
/*!
|
||||
* \brief check the current connection status of an IGD
|
||||
*
|
||||
* it uses UPNP_GetStatusInfo()
|
||||
* \param[in] urls IGD URLs
|
||||
* \param[in] data IGD data
|
||||
* \return 1 Connected / 0 Disconnected
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
20
Externals/miniupnpc/src/miniupnpc_declspec.h
vendored
20
Externals/miniupnpc/src/miniupnpc_declspec.h
vendored
|
@ -1,12 +1,22 @@
|
|||
#ifndef MINIUPNPC_DECLSPEC_H_INCLUDED
|
||||
#define MINIUPNPC_DECLSPEC_H_INCLUDED
|
||||
|
||||
#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")))
|
||||
/*! \file miniupnpc_declspec.h
|
||||
* \brief define #MINIUPNP_LIBSPEC for dll exports and imports */
|
||||
#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
|
||||
#define MINIUPNP_LIBSPEC
|
||||
#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 */
|
||||
|
||||
|
|
44
Externals/miniupnpc/src/miniupnpc_socketdef.h
vendored
Normal file
44
Externals/miniupnpc/src/miniupnpc_socketdef.h
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* $Id: miniupnpc_socketdef.h,v 1.1 2018/03/13 23:44:10 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 */
|
157
Externals/miniupnpc/src/miniupnpcmodule.c
vendored
157
Externals/miniupnpc/src/miniupnpcmodule.c
vendored
|
@ -1,17 +1,22 @@
|
|||
/* $Id: miniupnpcmodule.c,v 1.24 2014/06/10 09:48:11 nanard Exp $*/
|
||||
/* Project : miniupnp
|
||||
/* $Id: miniupnpcmodule.c,v 1.40 2024/05/09 15:10:29 nanard Exp $*/
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* Project : miniupnp
|
||||
* Author : Thomas BERNARD
|
||||
* website : http://miniupnp.tuxfamily.org/
|
||||
* copyright (c) 2007-2014 Thomas Bernard
|
||||
* website : https://miniupnp.tuxfamily.org/
|
||||
* copyright (c) 2007-2024 Thomas Bernard
|
||||
* This software is subjet to the conditions detailed in the
|
||||
* provided LICENCE file. */
|
||||
#include <Python.h>
|
||||
#define MINIUPNP_STATICLIB
|
||||
#include "structmember.h"
|
||||
#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
|
||||
|
@ -42,7 +47,9 @@ 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 wanaddr[40]; /* the ExternalIPAddress returned by the IGD */
|
||||
char * multicastif;
|
||||
char * minissdpdsocket;
|
||||
} UPnPObject;
|
||||
|
@ -51,10 +58,22 @@ static PyMemberDef UPnP_members[] = {
|
|||
{"lanaddr", T_STRING_INPLACE, offsetof(UPnPObject, lanaddr),
|
||||
READONLY, "ip address on the LAN"
|
||||
},
|
||||
{"wanaddr", T_STRING_INPLACE, offsetof(UPnPObject, wanaddr),
|
||||
READONLY, "public ip address on the WAN"
|
||||
},
|
||||
{"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"
|
||||
},
|
||||
|
@ -70,15 +89,22 @@ static int UPnP_init(UPnPObject *self, PyObject *args, PyObject *kwds)
|
|||
char* multicastif = NULL;
|
||||
char* minissdpdsocket = NULL;
|
||||
static char *kwlist[] = {
|
||||
"multicastif", "minissdpdsocket", "discoverdelay", NULL
|
||||
"multicastif", "minissdpdsocket", "discoverdelay",
|
||||
"localport", NULL
|
||||
};
|
||||
|
||||
if(!PyArg_ParseTupleAndKeywords(args, kwds, "|zzI", kwlist,
|
||||
if(!PyArg_ParseTupleAndKeywords(args, kwds, "|zzII", kwlist,
|
||||
&multicastif,
|
||||
&minissdpdsocket,
|
||||
&self->discoverdelay))
|
||||
return -1;
|
||||
&self->discoverdelay,
|
||||
&self->localport))
|
||||
return -1;
|
||||
|
||||
if(self->localport>1 &&
|
||||
(self->localport>65534||self->localport<1024)) {
|
||||
PyErr_SetString(PyExc_Exception, "Invalid localport value");
|
||||
return -1;
|
||||
}
|
||||
if(multicastif)
|
||||
self->multicastif = strdup(multicastif);
|
||||
if(minissdpdsocket)
|
||||
|
@ -100,9 +126,9 @@ UPnPObject_dealloc(UPnPObject *self)
|
|||
static PyObject *
|
||||
UPnP_discover(UPnPObject *self)
|
||||
{
|
||||
struct UPNPDev * dev;
|
||||
int i;
|
||||
int error = 0;
|
||||
PyObject *res = NULL;
|
||||
|
||||
if(self->devlist)
|
||||
{
|
||||
freeUPNPDevlist(self->devlist);
|
||||
|
@ -112,25 +138,42 @@ UPnP_discover(UPnPObject *self)
|
|||
self->devlist = upnpDiscover((int)self->discoverdelay/*timeout in ms*/,
|
||||
self->multicastif,
|
||||
self->minissdpdsocket,
|
||||
0/*sameport flag*/,
|
||||
(int)self->localport,
|
||||
0/*ip v6*/,
|
||||
2/* TTL */,
|
||||
0/*error */);
|
||||
&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),
|
||||
self->wanaddr, sizeof(self->wanaddr));
|
||||
} else {
|
||||
r = UPNP_GetIGDFromUrl(rootDescUrl, &self->urls, &self->data,
|
||||
self->lanaddr, sizeof(self->lanaddr));
|
||||
}
|
||||
Py_END_ALLOW_THREADS
|
||||
if(r)
|
||||
{
|
||||
|
@ -152,7 +195,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 *
|
||||
|
@ -163,7 +210,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 *
|
||||
|
@ -174,7 +225,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 *
|
||||
|
@ -185,7 +240,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 *
|
||||
|
@ -202,7 +261,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));
|
||||
|
@ -251,7 +314,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)
|
||||
|
@ -264,17 +327,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)
|
||||
{
|
||||
|
@ -308,7 +378,7 @@ UPnP_addanyportmapping(UPnPObject *self, PyObject *args)
|
|||
const char * remoteHost;
|
||||
const char * leaseDuration = "0";
|
||||
int r;
|
||||
if (!PyArg_ParseTuple(args, "HssHss", &ePort, &proto, &host, &iPort, &desc, &remoteHost))
|
||||
if (!PyArg_ParseTuple(args, "HssHzz", &ePort, &proto, &host, &iPort, &desc, &remoteHost))
|
||||
return NULL;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
sprintf(extPort, "%hu", ePort);
|
||||
|
@ -364,14 +434,14 @@ UPnP_deleteportmappingrange(UPnPObject *self, PyObject *args)
|
|||
unsigned short ePortEnd;
|
||||
const char * proto;
|
||||
unsigned char manage;
|
||||
char manageStr[1];
|
||||
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, "%hhu", manage);
|
||||
sprintf(manageStr, "%hu", (unsigned short)manage);
|
||||
r = UPNP_DeletePortMappingRange(self->urls.controlURL, self->data.first.servicetype,
|
||||
extPortStart, extPortEnd, proto, manageStr);
|
||||
Py_END_ALLOW_THREADS
|
||||
|
@ -395,7 +465,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));
|
||||
|
@ -480,9 +554,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
|
||||
{
|
||||
|
@ -495,7 +575,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,
|
||||
|
@ -585,8 +665,9 @@ static PyTypeObject UPnPType = {
|
|||
#ifndef _WIN32
|
||||
PyType_GenericNew,/*UPnP_new,*/ /* tp_new */
|
||||
#else
|
||||
0,
|
||||
0, /* tp_new */
|
||||
#endif
|
||||
0, /* tp_free */
|
||||
};
|
||||
|
||||
/* module methods */
|
||||
|
@ -622,6 +703,20 @@ initminiupnpc(void)
|
|||
PyObject* m;
|
||||
|
||||
#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)
|
||||
|
|
24
Externals/miniupnpc/src/miniupnpctypes.h
vendored
24
Externals/miniupnpc/src/miniupnpctypes.h
vendored
|
@ -1,19 +1,27 @@
|
|||
/* $Id: miniupnpctypes.h,v 1.1 2011/02/15 11:10:40 nanard Exp $ */
|
||||
/* Miniupnp project : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2011 Thomas Bernard
|
||||
/* $Id: miniupnpctypes.h,v 1.4 2025/02/08 23:15:16 nanard Exp $ */
|
||||
/* Project: miniupnp
|
||||
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org
|
||||
* Author: Thomas Bernard
|
||||
* Copyright (c) 2021-2025 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided within this distribution */
|
||||
#ifndef MINIUPNPCTYPES_H_INCLUDED
|
||||
#define MINIUPNPCTYPES_H_INCLUDED
|
||||
|
||||
#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
|
||||
/*! \file miniupnpctypes.h
|
||||
* \brief type definitions
|
||||
*
|
||||
* Use unsigned long long when available :
|
||||
* strtoull is C99
|
||||
*
|
||||
* \def UNSIGNED_INTEGER
|
||||
* \brief `unsigned long long` or `unsigned int`
|
||||
* \todo int can be 16 bits, so it should be `unsigned long`
|
||||
*/
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
#define UNSIGNED_INTEGER unsigned long long
|
||||
#define STRTOUI strtoull
|
||||
#else
|
||||
#define UNSIGNED_INTEGER unsigned int
|
||||
#define STRTOUI strtoul
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
283
Externals/miniupnpc/src/miniwget.c
vendored
283
Externals/miniupnpc/src/miniwget.c
vendored
|
@ -1,8 +1,8 @@
|
|||
/* $Id: miniwget.c,v 1.70 2015/07/15 12:41:13 nanard Exp $ */
|
||||
/* $Id: miniwget.c,v 1.85 2023/06/15 21:47:50 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Website : http://miniupnp.free.fr/
|
||||
* Website : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005-2015 Thomas Bernard
|
||||
* Copyright (c) 2005-2024 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution. */
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
|||
#include <ws2tcpip.h>
|
||||
#include <io.h>
|
||||
#define MAXHOSTNAMELEN 64
|
||||
#define snprintf _snprintf
|
||||
#include "win32_snprintf.h"
|
||||
#define socklen_t int
|
||||
#ifndef strncasecmp
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
|
@ -65,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;
|
||||
|
@ -83,7 +83,12 @@ getHTTPResponse(int s, int * size)
|
|||
unsigned int content_buf_used = 0;
|
||||
char chunksize_buf[32];
|
||||
unsigned int chunksize_buf_index;
|
||||
#ifdef DEBUG
|
||||
char * reason_phrase = NULL;
|
||||
int reason_phrase_len = 0;
|
||||
#endif
|
||||
|
||||
if(status_code) *status_code = -1;
|
||||
header_buf = malloc(header_buf_len);
|
||||
if(header_buf == NULL)
|
||||
{
|
||||
|
@ -106,7 +111,7 @@ getHTTPResponse(int s, int * size)
|
|||
chunksize_buf[0] = '\0';
|
||||
chunksize_buf_index = 0;
|
||||
|
||||
while((n = receivedata(s, buf, 2048, 5000, NULL)) > 0)
|
||||
while((n = receivedata(s, buf, sizeof(buf), 5000, NULL)) > 0)
|
||||
{
|
||||
if(endofheaders == 0)
|
||||
{
|
||||
|
@ -155,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)
|
||||
|
@ -166,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",
|
||||
|
@ -201,100 +233,69 @@ getHTTPResponse(int s, int * size)
|
|||
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') {
|
||||
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);
|
||||
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:(unsigned int)(n - i);
|
||||
if((content_buf_used + bytestocopy) > content_buf_len)
|
||||
{
|
||||
char * tmp;
|
||||
if(content_length >= (int)(content_buf_used + bytestocopy)) {
|
||||
content_buf_len = content_length;
|
||||
} else {
|
||||
content_buf_len = content_buf_used + bytestocopy;
|
||||
}
|
||||
tmp = realloc(content_buf, content_buf_len);
|
||||
if(tmp == NULL) {
|
||||
/* memory allocation error */
|
||||
free(content_buf);
|
||||
free(header_buf);
|
||||
*size = -1;
|
||||
return NULL;
|
||||
}
|
||||
content_buf = tmp;
|
||||
}
|
||||
memcpy(content_buf + content_buf_used, buf + i, bytestocopy);
|
||||
content_buf_used += bytestocopy;
|
||||
i += bytestocopy;
|
||||
chunksize -= bytestocopy;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* not chunked */
|
||||
if(content_length > 0
|
||||
&& (int)(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)
|
||||
{
|
||||
char * tmp;
|
||||
if(content_length >= (int)(content_buf_used + n)) {
|
||||
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;
|
||||
}
|
||||
tmp = realloc(content_buf, content_buf_len);
|
||||
if(tmp == NULL) {
|
||||
|
@ -306,12 +307,44 @@ getHTTPResponse(int s, int * size)
|
|||
}
|
||||
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 && (int)content_buf_used >= content_length)
|
||||
if(content_length > 0 && content_buf_used >= (unsigned int)content_length)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("End of HTTP content\n");
|
||||
|
@ -320,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)
|
||||
{
|
||||
|
@ -337,10 +370,11 @@ static void *
|
|||
miniwget3(const char * host,
|
||||
unsigned short port, const char * path,
|
||||
int * size, char * addr_str, int addr_str_len,
|
||||
const char * httpversion, unsigned int scope_id)
|
||||
const char * httpversion, unsigned int scope_id,
|
||||
int * status_code)
|
||||
{
|
||||
char buf[2048];
|
||||
int s;
|
||||
SOCKET s;
|
||||
int n;
|
||||
int len;
|
||||
int sent;
|
||||
|
@ -348,7 +382,7 @@ miniwget3(const char * host,
|
|||
|
||||
*size = 0;
|
||||
s = connecthostport(host, port, scope_id);
|
||||
if(s < 0)
|
||||
if(ISINVALID(s))
|
||||
return NULL;
|
||||
|
||||
/* get address for caller ! */
|
||||
|
@ -409,11 +443,15 @@ miniwget3(const char * host,
|
|||
len = snprintf(buf, sizeof(buf),
|
||||
"GET %s HTTP/%s\r\n"
|
||||
"Host: %s:%d\r\n"
|
||||
"Connection: Close\r\n"
|
||||
"User-Agent: " OS_STRING ", " UPNP_VERSION_STRING ", MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
|
||||
|
||||
"Connection: close\r\n"
|
||||
"User-Agent: " OS_STRING " " UPNP_VERSION_STRING " MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
|
||||
"\r\n",
|
||||
path, httpversion, host, port);
|
||||
if ((unsigned int)len >= sizeof(buf))
|
||||
{
|
||||
closesocket(s);
|
||||
return NULL;
|
||||
}
|
||||
sent = 0;
|
||||
/* sending the HTTP request */
|
||||
while(sent < len)
|
||||
|
@ -430,43 +468,11 @@ miniwget3(const char * host,
|
|||
sent += n;
|
||||
}
|
||||
}
|
||||
content = getHTTPResponse(s, size);
|
||||
content = getHTTPResponse(s, size, status_code);
|
||||
closesocket(s);
|
||||
return content;
|
||||
}
|
||||
|
||||
/* miniwget2() :
|
||||
* Call miniwget3(); retry with HTTP/1.1 if 1.0 fails. */
|
||||
static void *
|
||||
miniwget2(const char * host,
|
||||
unsigned short port, const char * path,
|
||||
int * size, char * addr_str, int addr_str_len,
|
||||
unsigned int scope_id)
|
||||
{
|
||||
char * respbuffer;
|
||||
|
||||
#if 1
|
||||
respbuffer = miniwget3(host, port, path, size,
|
||||
addr_str, addr_str_len, "1.1", scope_id);
|
||||
#else
|
||||
respbuffer = miniwget3(host, port, path, size,
|
||||
addr_str, addr_str_len, "1.0", scope_id);
|
||||
if (*size == 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Retrying with HTTP/1.1\n");
|
||||
#endif
|
||||
free(respbuffer);
|
||||
respbuffer = miniwget3(host, port, path, size,
|
||||
addr_str, addr_str_len, "1.1", scope_id);
|
||||
}
|
||||
#endif
|
||||
return respbuffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* parseURL()
|
||||
* arguments :
|
||||
* url : source string not modified
|
||||
|
@ -520,7 +526,7 @@ parseURL(const char * url,
|
|||
#else
|
||||
/* under windows, scope is numerical */
|
||||
char tmp[8];
|
||||
int l;
|
||||
size_t l;
|
||||
scope++;
|
||||
/* "%25" is just '%' in URL encoding */
|
||||
if(scope[0] == '2' && scope[1] == '5')
|
||||
|
@ -583,7 +589,8 @@ parseURL(const char * url,
|
|||
}
|
||||
|
||||
void *
|
||||
miniwget(const char * url, int * size, unsigned int scope_id)
|
||||
miniwget(const char * url, int * size,
|
||||
unsigned int scope_id, int * status_code)
|
||||
{
|
||||
unsigned short port;
|
||||
char * path;
|
||||
|
@ -596,12 +603,13 @@ miniwget(const char * url, int * size, unsigned int scope_id)
|
|||
printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
|
||||
hostname, port, path, scope_id);
|
||||
#endif
|
||||
return miniwget2(hostname, port, path, size, 0, 0, scope_id);
|
||||
return miniwget3(hostname, port, path, size, 0, 0, "1.1", scope_id, status_code);
|
||||
}
|
||||
|
||||
void *
|
||||
miniwget_getaddr(const char * url, int * size,
|
||||
char * addr, int addrlen, unsigned int scope_id)
|
||||
char * addr, int addrlen, unsigned int scope_id,
|
||||
int * status_code)
|
||||
{
|
||||
unsigned short port;
|
||||
char * path;
|
||||
|
@ -616,6 +624,5 @@ miniwget_getaddr(const char * url, int * size,
|
|||
printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
|
||||
hostname, port, path, scope_id);
|
||||
#endif
|
||||
return miniwget2(hostname, port, path, size, addr, addrlen, scope_id);
|
||||
return miniwget3(hostname, port, path, size, addr, addrlen, "1.1", scope_id, status_code);
|
||||
}
|
||||
|
||||
|
|
42
Externals/miniupnpc/src/miniwget.h
vendored
42
Externals/miniupnpc/src/miniwget.h
vendored
|
@ -1,30 +1,54 @@
|
|||
/* $Id: miniwget.h,v 1.7 2012/06/23 22:35:59 nanard Exp $ */
|
||||
/* $Id: miniwget.h,v 1.14 2025/02/08 23:15:17 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005-2015 Thomas Bernard
|
||||
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||
* Copyright (c) 2005-2025 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
|
||||
|
||||
/*! \file miniwget.h
|
||||
* \brief Lightweight HTTP client API
|
||||
*/
|
||||
#include "miniupnpc_declspec.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
MINIUPNP_LIBSPEC void * getHTTPResponse(int s, int * size);
|
||||
/*! \brief perform HTTP GET on an URL
|
||||
*
|
||||
* \param[in] url HTTP URL to GET
|
||||
* \param[out] size length of the returned buffer. -1 in case of memory
|
||||
* allocation error
|
||||
* \param[in] scope_id interface id for IPv6 to use if not specified in the URL
|
||||
* \param[out] status_code HTTP response status code (200, 404, etc.)
|
||||
* \return the body of the HTTP response
|
||||
*/
|
||||
MINIUPNP_LIBSPEC void * miniwget(const char * url, int * size,
|
||||
unsigned int scope_id, int * status_code);
|
||||
|
||||
MINIUPNP_LIBSPEC void * miniwget(const char *, int *, unsigned int);
|
||||
|
||||
MINIUPNP_LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int, unsigned int);
|
||||
|
||||
int parseURL(const char *, char *, unsigned short *, char * *, unsigned int *);
|
||||
/*! \brief perform HTTP GET on an URL
|
||||
*
|
||||
* Also get the local address used to reach the HTTP server
|
||||
*
|
||||
* \param[in] url HTTP URL to GET
|
||||
* \param[out] size length of the returned buffer. -1 in case of memory
|
||||
* allocation error
|
||||
* \param[out] addr local address used to connect to the server
|
||||
* \param[in] addrlen size of the addr buffer
|
||||
* \param[in] scope_id interface id for IPv6 to use if not specified in the URL
|
||||
* \param[out] status_code HTTP response status code (200, 404, etc.)
|
||||
* \return the body of the HTTP response
|
||||
*/
|
||||
MINIUPNP_LIBSPEC void * miniwget_getaddr(const char * url, int * size,
|
||||
char * addr, int addrlen,
|
||||
unsigned int scope_id, int * status_code);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
54
Externals/miniupnpc/src/miniwget_private.h
vendored
Normal file
54
Externals/miniupnpc/src/miniwget_private.h
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
/* $Id: miniwget_private.h,v 1.1 2018/04/06 10:17:58 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2018-2025 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
|
||||
|
||||
/*! \file miniwget_private.h
|
||||
* \brief Lightweight HTTP client private API
|
||||
*/
|
||||
#include "miniupnpc_socketdef.h"
|
||||
|
||||
/*! \brief Read a HTTP response from a socket
|
||||
*
|
||||
* Processed HTTP headers :
|
||||
* - `Content-Length`
|
||||
* - `Transfer-encoding`
|
||||
* return a pointer to the content buffer, which length is saved
|
||||
* to the length parameter.
|
||||
* \param[in] s socket
|
||||
* \param[out] size returned content buffer size
|
||||
* \param[out] status_code HTTP Status code
|
||||
* \return malloc'ed content buffer
|
||||
*/
|
||||
void * getHTTPResponse(SOCKET s, int * size, int * status_code);
|
||||
|
||||
/*! \brief parse a HTTP URL
|
||||
*
|
||||
* URL formats supported :
|
||||
* - `http://192.168.1.1/path/xxx`
|
||||
* - `http://192.168.1.1:8080/path/xxx`
|
||||
* - `http://[2a00:1234:5678:90ab::123]/path/xxx`
|
||||
* - `http://[2a00:1234:5678:90ab::123]:8080/path/xxx`
|
||||
* - `http://[fe80::1234:5678:90ab%%eth0]/path/xxx`
|
||||
* - `http://[fe80::1234:5678:90ab%%eth0]:8080/path/xxx`
|
||||
*
|
||||
* `%` may be encoded as `%25`
|
||||
*
|
||||
* \param[in] url URL to parse
|
||||
* \param[out] hostname hostname part of the URL (size of MAXHOSTNAMELEN+1)
|
||||
* \param[out] port set to the port specified in the URL or 80
|
||||
* \param[out] path set to the begining of the path part of the URL
|
||||
* \param[out] scope_id set to the interface id if specified in the
|
||||
* link-local IPv6 address
|
||||
* \return 0 for failure, 1 for success
|
||||
*/
|
||||
int parseURL(const char * url,
|
||||
char * hostname, unsigned short * port, char * * path,
|
||||
unsigned int * scope_id);
|
||||
|
||||
#endif
|
10
Externals/miniupnpc/src/minixml.c
vendored
10
Externals/miniupnpc/src/minixml.c
vendored
|
@ -1,10 +1,11 @@
|
|||
/* $Id: minixml.c,v 1.10 2012/03/05 19:42:47 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-2014, Thomas BERNARD
|
||||
Copyright (c) 2005-2017, Thomas BERNARD
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
@ -161,7 +162,8 @@ 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;
|
||||
|
|
2
Externals/miniupnpc/src/minixml.h
vendored
2
Externals/miniupnpc/src/minixml.h
vendored
|
@ -10,7 +10,7 @@
|
|||
* */
|
||||
#ifndef MINIXML_H_INCLUDED
|
||||
#define MINIXML_H_INCLUDED
|
||||
#define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n'))
|
||||
#define IS_WHITE_SPACE(c) ((c)==' ' || (c)=='\t' || (c)=='\r' || (c)=='\n')
|
||||
|
||||
/* if a callback function pointer is set to NULL,
|
||||
* the function is not called */
|
||||
|
|
163
Externals/miniupnpc/src/minixmlvalid.c
vendored
Normal file
163
Externals/miniupnpc/src/minixmlvalid.c
vendored
Normal file
|
@ -0,0 +1,163 @@
|
|||
/* $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 :
|
||||
* validation program for the minixml parser
|
||||
*
|
||||
* (c) 2006-2011 Thomas Bernard */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "minixml.h"
|
||||
|
||||
/* xml event structure */
|
||||
struct event {
|
||||
enum { ELTSTART, ELTEND, ATT, CHARDATA } type;
|
||||
const char * data;
|
||||
int len;
|
||||
};
|
||||
|
||||
struct eventlist {
|
||||
int n;
|
||||
struct event * events;
|
||||
};
|
||||
|
||||
/* compare 2 xml event lists
|
||||
* return 0 if the two lists are equals */
|
||||
int evtlistcmp(struct eventlist * a, struct eventlist * b)
|
||||
{
|
||||
int i;
|
||||
struct event * ae, * be;
|
||||
if(a->n != b->n)
|
||||
{
|
||||
printf("event number not matching : %d != %d\n", a->n, b->n);
|
||||
/*return 1;*/
|
||||
}
|
||||
for(i=0; i<a->n; i++)
|
||||
{
|
||||
ae = a->events + i;
|
||||
be = b->events + i;
|
||||
if( (ae->type != be->type)
|
||||
||(ae->len != be->len)
|
||||
||memcmp(ae->data, be->data, ae->len))
|
||||
{
|
||||
printf("Found a difference : %d '%.*s' != %d '%.*s'\n",
|
||||
ae->type, ae->len, ae->data,
|
||||
be->type, be->len, be->data);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test data */
|
||||
static const char xmldata[] =
|
||||
"<xmlroot>\n"
|
||||
" <elt1 att1=\"attvalue1\" att2=\"attvalue2\">"
|
||||
"character data"
|
||||
"</elt1> \n \t"
|
||||
"<elt1b/>"
|
||||
"<elt1>\n<![CDATA[ <html>stuff !\n ]]> \n</elt1>\n"
|
||||
"<elt2a> \t<elt2b>chardata1</elt2b><elt2b> chardata2 </elt2b></elt2a>"
|
||||
"</xmlroot>";
|
||||
|
||||
static const struct event evtref[] =
|
||||
{
|
||||
{ELTSTART, "xmlroot", 7},
|
||||
{ELTSTART, "elt1", 4},
|
||||
/* attributes */
|
||||
{CHARDATA, "character data", 14},
|
||||
{ELTEND, "elt1", 4},
|
||||
{ELTSTART, "elt1b", 5},
|
||||
{ELTSTART, "elt1", 4},
|
||||
{CHARDATA, " <html>stuff !\n ", 16},
|
||||
{ELTEND, "elt1", 4},
|
||||
{ELTSTART, "elt2a", 5},
|
||||
{ELTSTART, "elt2b", 5},
|
||||
{CHARDATA, "chardata1", 9},
|
||||
{ELTEND, "elt2b", 5},
|
||||
{ELTSTART, "elt2b", 5},
|
||||
{CHARDATA, " chardata2 ", 11},
|
||||
{ELTEND, "elt2b", 5},
|
||||
{ELTEND, "elt2a", 5},
|
||||
{ELTEND, "xmlroot", 7}
|
||||
};
|
||||
|
||||
void startelt(void * data, const char * p, int l)
|
||||
{
|
||||
struct eventlist * evtlist = data;
|
||||
struct event * evt;
|
||||
evt = evtlist->events + evtlist->n;
|
||||
/*printf("startelt : %.*s\n", l, p);*/
|
||||
evt->type = ELTSTART;
|
||||
evt->data = p;
|
||||
evt->len = l;
|
||||
evtlist->n++;
|
||||
}
|
||||
|
||||
void endelt(void * data, const char * p, int l)
|
||||
{
|
||||
struct eventlist * evtlist = data;
|
||||
struct event * evt;
|
||||
evt = evtlist->events + evtlist->n;
|
||||
/*printf("endelt : %.*s\n", l, p);*/
|
||||
evt->type = ELTEND;
|
||||
evt->data = p;
|
||||
evt->len = l;
|
||||
evtlist->n++;
|
||||
}
|
||||
|
||||
void chardata(void * data, const char * p, int l)
|
||||
{
|
||||
struct eventlist * evtlist = data;
|
||||
struct event * evt;
|
||||
evt = evtlist->events + evtlist->n;
|
||||
/*printf("chardata : '%.*s'\n", l, p);*/
|
||||
evt->type = CHARDATA;
|
||||
evt->data = p;
|
||||
evt->len = l;
|
||||
evtlist->n++;
|
||||
}
|
||||
|
||||
int testxmlparser(const char * xml, int size)
|
||||
{
|
||||
int r;
|
||||
struct eventlist evtlist;
|
||||
struct eventlist evtlistref;
|
||||
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;
|
||||
parser.data = &evtlist;
|
||||
parser.starteltfunc = startelt;
|
||||
parser.endeltfunc = endelt;
|
||||
parser.datafunc = chardata;
|
||||
parsexml(&parser);
|
||||
printf("%d events\n", evtlist.n);
|
||||
/* compare */
|
||||
evtlistref.n = sizeof(evtref)/sizeof(struct event);
|
||||
evtlistref.events = (struct event *)evtref;
|
||||
r = evtlistcmp(&evtlistref, &evtlist);
|
||||
free(evtlist.events);
|
||||
return r;
|
||||
}
|
||||
|
||||
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");
|
||||
return r;
|
||||
}
|
||||
|
9
Externals/miniupnpc/src/portlistingparse.c
vendored
9
Externals/miniupnpc/src/portlistingparse.c
vendored
|
@ -1,7 +1,7 @@
|
|||
/* $Id: portlistingparse.c,v 1.9 2015/07/15 12:41:13 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2011-2015 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>
|
||||
|
@ -12,6 +12,11 @@
|
|||
#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;
|
||||
|
@ -55,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;
|
||||
|
|
74
Externals/miniupnpc/src/portlistingparse.h
vendored
74
Externals/miniupnpc/src/portlistingparse.h
vendored
|
@ -1,12 +1,29 @@
|
|||
/* $Id: portlistingparse.h,v 1.10 2014/11/01 10:37:32 nanard Exp $ */
|
||||
/* $Id: portlistingparse.h,v 1.12 2025/02/08 23:15:17 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2011-2015 Thomas Bernard
|
||||
* (c) 2011-2025 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
#ifndef PORTLISTINGPARSE_H_INCLUDED
|
||||
#define PORTLISTINGPARSE_H_INCLUDED
|
||||
|
||||
/*! \file portlistingparse.h
|
||||
* \brief Parsing of the list of port mappings
|
||||
*
|
||||
* As returned by GetListOfPortMappings.
|
||||
* Sample of PortMappingEntry :
|
||||
*
|
||||
* <p:PortMappingEntry>
|
||||
* <p:NewRemoteHost>202.233.2.1</p:NewRemoteHost>
|
||||
* <p:NewExternalPort>2345</p:NewExternalPort>
|
||||
* <p:NewProtocol>TCP</p:NewProtocol>
|
||||
* <p:NewInternalPort>2345</p:NewInternalPort>
|
||||
* <p:NewInternalClient>192.168.1.137</p:NewInternalClient>
|
||||
* <p:NewEnabled>1</p:NewEnabled>
|
||||
* <p:NewDescription>dooom</p:NewDescription>
|
||||
* <p:NewLeaseTime>345</p:NewLeaseTime>
|
||||
* </p:PortMappingEntry>
|
||||
*/
|
||||
#include "miniupnpc_declspec.h"
|
||||
/* for the definition of UNSIGNED_INTEGER */
|
||||
#include "miniupnpctypes.h"
|
||||
|
@ -15,17 +32,8 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* sample of PortMappingEntry :
|
||||
<p:PortMappingEntry>
|
||||
<p:NewRemoteHost>202.233.2.1</p:NewRemoteHost>
|
||||
<p:NewExternalPort>2345</p:NewExternalPort>
|
||||
<p:NewProtocol>TCP</p:NewProtocol>
|
||||
<p:NewInternalPort>2345</p:NewInternalPort>
|
||||
<p:NewInternalClient>192.168.1.137</p:NewInternalClient>
|
||||
<p:NewEnabled>1</p:NewEnabled>
|
||||
<p:NewDescription>dooom</p:NewDescription>
|
||||
<p:NewLeaseTime>345</p:NewLeaseTime>
|
||||
</p:PortMappingEntry>
|
||||
/*!
|
||||
* \brief enum of all XML elements
|
||||
*/
|
||||
typedef enum { PortMappingEltNone,
|
||||
PortMappingEntry, NewRemoteHost,
|
||||
|
@ -34,27 +42,45 @@ typedef enum { PortMappingEltNone,
|
|||
NewEnabled, NewDescription,
|
||||
NewLeaseTime } portMappingElt;
|
||||
|
||||
/*!
|
||||
* \brief linked list of port mappings
|
||||
*/
|
||||
struct PortMapping {
|
||||
struct PortMapping * l_next; /* list next element */
|
||||
UNSIGNED_INTEGER leaseTime;
|
||||
unsigned short externalPort;
|
||||
unsigned short internalPort;
|
||||
char remoteHost[64];
|
||||
char internalClient[64];
|
||||
char description[64];
|
||||
char protocol[4];
|
||||
unsigned char enabled;
|
||||
struct PortMapping * l_next; /*!< \brief next list element */
|
||||
UNSIGNED_INTEGER leaseTime; /*!< \brief in seconds */
|
||||
unsigned short externalPort; /*!< \brief external port */
|
||||
unsigned short internalPort; /*!< \brief internal port */
|
||||
char remoteHost[64]; /*!< \brief empty for wildcard */
|
||||
char internalClient[64]; /*!< \brief internal IP address */
|
||||
char description[64]; /*!< \brief description */
|
||||
char protocol[4]; /*!< \brief `TCP` or `UDP` */
|
||||
unsigned char enabled; /*!< \brief 0 (false) or 1 (true) */
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief structure for ParsePortListing()
|
||||
*/
|
||||
struct PortMappingParserData {
|
||||
struct PortMapping * l_head; /* list head */
|
||||
portMappingElt curelt;
|
||||
struct PortMapping * l_head; /*!< \brief list head */
|
||||
portMappingElt curelt; /*!< \brief currently parsed element */
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief parse the NewPortListing part of GetListOfPortMappings response
|
||||
*
|
||||
* \param[in] buffer XML data
|
||||
* \param[in] bufsize length of XML data
|
||||
* \param[out] pdata Parsed data
|
||||
*/
|
||||
MINIUPNP_LIBSPEC void
|
||||
ParsePortListing(const char * buffer, int bufsize,
|
||||
struct PortMappingParserData * pdata);
|
||||
|
||||
/*!
|
||||
* \brief free parsed data structure
|
||||
*
|
||||
* \param[in] pdata Parsed data to free
|
||||
*/
|
||||
MINIUPNP_LIBSPEC void
|
||||
FreePortListing(struct PortMappingParserData * pdata);
|
||||
|
||||
|
|
24
Externals/miniupnpc/src/receivedata.c
vendored
24
Externals/miniupnpc/src/receivedata.c
vendored
|
@ -1,8 +1,8 @@
|
|||
/* $Id: receivedata.c,v 1.6 2014/11/13 13:51:52 nanard Exp $ */
|
||||
/* $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-2014 Thomas Bernard
|
||||
* Copyright (c) 2011-2021 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution. */
|
||||
|
||||
|
@ -27,20 +27,14 @@
|
|||
#define MINIUPNPC_IGNORE_EINTR
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#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,
|
||||
receivedata(SOCKET socket,
|
||||
char * data, int length,
|
||||
int timeout, unsigned int * scope_id)
|
||||
{
|
||||
#if MINIUPNPC_GET_SRC_ADDR
|
||||
#ifdef MINIUPNPC_GET_SRC_ADDR
|
||||
struct sockaddr_storage src_addr;
|
||||
socklen_t src_addr_len = sizeof(src_addr);
|
||||
#endif /* MINIUPNPC_GET_SRC_ADDR */
|
||||
|
@ -80,7 +74,7 @@ receivedata(int socket,
|
|||
return 0;
|
||||
}
|
||||
#endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
|
||||
#if MINIUPNPC_GET_SRC_ADDR
|
||||
#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);
|
||||
|
@ -90,7 +84,7 @@ receivedata(int socket,
|
|||
if(n<0) {
|
||||
PRINT_SOCKET_ERROR("recv");
|
||||
}
|
||||
#if MINIUPNPC_GET_SRC_ADDR
|
||||
#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
|
||||
|
@ -98,7 +92,13 @@ receivedata(int socket,
|
|||
#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;
|
||||
}
|
||||
|
|
6
Externals/miniupnpc/src/receivedata.h
vendored
6
Externals/miniupnpc/src/receivedata.h
vendored
|
@ -2,16 +2,18 @@
|
|||
/* Project: miniupnp
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* Author: Thomas Bernard
|
||||
* Copyright (c) 2011-2012 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(int socket,
|
||||
int receivedata(SOCKET socket,
|
||||
char * data, int length,
|
||||
int timeout, unsigned int * scope_id);
|
||||
|
||||
|
|
944
Externals/miniupnpc/src/upnpc.c
vendored
Normal file
944
Externals/miniupnpc/src/upnpc.c
vendored
Normal file
|
@ -0,0 +1,944 @@
|
|||
/* $Id: upnpc.c,v 1.146 2025/01/10 23:02:54 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005-2025 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 <time.h>
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#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"
|
||||
* returns NULL if not */
|
||||
const char * protofix(const char * proto)
|
||||
{
|
||||
static const char proto_tcp[4] = { 'T', 'C', 'P', 0};
|
||||
static const char proto_udp[4] = { 'U', 'D', 'P', 0};
|
||||
int i, b;
|
||||
for(i=0, b=1; i<4; i++)
|
||||
b = b && ( (proto[i] == proto_tcp[i])
|
||||
|| (proto[i] == (proto_tcp[i] | 32)) );
|
||||
if(b)
|
||||
return proto_tcp;
|
||||
for(i=0, b=1; i<4; i++)
|
||||
b = b && ( (proto[i] == proto_udp[i])
|
||||
|| (proto[i] == (proto_udp[i] | 32)) );
|
||||
if(b)
|
||||
return proto_udp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* is_int() checks if parameter is an integer or not
|
||||
* 1 for integer
|
||||
* 0 for not an integer */
|
||||
int is_int(char const* s)
|
||||
{
|
||||
if(s == NULL)
|
||||
return 0;
|
||||
while(*s) {
|
||||
/* #define isdigit(c) ((c) >= '0' && (c) <= '9') */
|
||||
if(!isdigit(*s))
|
||||
return 0;
|
||||
s++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void DisplayInfos(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data)
|
||||
{
|
||||
char externalIPAddress[40];
|
||||
char connectionType[64];
|
||||
char status[64];
|
||||
char lastconnerr[64];
|
||||
unsigned int uptime = 0;
|
||||
unsigned int brUp, brDown;
|
||||
time_t timenow, timestarted;
|
||||
int r;
|
||||
if(UPNP_GetConnectionTypeInfo(urls->controlURL,
|
||||
data->first.servicetype,
|
||||
connectionType) != UPNPCOMMAND_SUCCESS)
|
||||
printf("GetConnectionTypeInfo failed.\n");
|
||||
else
|
||||
printf("Connection Type : %s\n", connectionType);
|
||||
if(UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype,
|
||||
status, &uptime, lastconnerr) != UPNPCOMMAND_SUCCESS)
|
||||
printf("GetStatusInfo failed.\n");
|
||||
else
|
||||
printf("Status : %s, uptime=%us, LastConnectionError : %s\n",
|
||||
status, uptime, lastconnerr);
|
||||
if(uptime > 0) {
|
||||
timenow = time(NULL);
|
||||
timestarted = timenow - uptime;
|
||||
printf(" Time started : %s", ctime(×tarted));
|
||||
}
|
||||
if(UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, data->CIF.servicetype,
|
||||
&brDown, &brUp) != UPNPCOMMAND_SUCCESS) {
|
||||
printf("GetLinkLayerMaxBitRates failed.\n");
|
||||
} else {
|
||||
printf("MaxBitRateDown : %u bps", brDown);
|
||||
if(brDown >= 1000000) {
|
||||
printf(" (%u.%u Mbps)", brDown / 1000000, (brDown / 100000) % 10);
|
||||
} else if(brDown >= 1000) {
|
||||
printf(" (%u Kbps)", brDown / 1000);
|
||||
}
|
||||
printf(" MaxBitRateUp %u bps", brUp);
|
||||
if(brUp >= 1000000) {
|
||||
printf(" (%u.%u Mbps)", brUp / 1000000, (brUp / 100000) % 10);
|
||||
} else if(brUp >= 1000) {
|
||||
printf(" (%u Kbps)", brUp / 1000);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
r = UPNP_GetExternalIPAddress(urls->controlURL,
|
||||
data->first.servicetype,
|
||||
externalIPAddress);
|
||||
if(r != UPNPCOMMAND_SUCCESS) {
|
||||
printf("GetExternalIPAddress failed. (errorcode=%d)\n", r);
|
||||
} else if(!externalIPAddress[0]) {
|
||||
printf("GetExternalIPAddress failed. (empty string)\n");
|
||||
} else {
|
||||
printf("ExternalIPAddress = %s\n", externalIPAddress);
|
||||
}
|
||||
}
|
||||
|
||||
static void GetConnectionStatus(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data)
|
||||
{
|
||||
unsigned int bytessent, bytesreceived, packetsreceived, packetssent;
|
||||
DisplayInfos(urls, data);
|
||||
bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype);
|
||||
bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype);
|
||||
packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype);
|
||||
packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype);
|
||||
printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived);
|
||||
printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived);
|
||||
}
|
||||
|
||||
static void ListRedirections(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data)
|
||||
{
|
||||
int r;
|
||||
unsigned short i = 0;
|
||||
char index[6];
|
||||
char intClient[40];
|
||||
char intPort[6];
|
||||
char extPort[6];
|
||||
char protocol[4];
|
||||
char desc[80];
|
||||
char enabled[6];
|
||||
char rHost[64];
|
||||
char duration[16];
|
||||
/*unsigned int num=0;
|
||||
UPNP_GetPortMappingNumberOfEntries(urls->controlURL, data->servicetype, &num);
|
||||
printf("PortMappingNumberOfEntries : %u\n", num);*/
|
||||
printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n");
|
||||
do {
|
||||
snprintf(index, 6, "%hu", i);
|
||||
rHost[0] = '\0'; enabled[0] = '\0';
|
||||
duration[0] = '\0'; desc[0] = '\0';
|
||||
extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0';
|
||||
r = UPNP_GetGenericPortMappingEntry(urls->controlURL,
|
||||
data->first.servicetype,
|
||||
index,
|
||||
extPort, intClient, intPort,
|
||||
protocol, desc, enabled,
|
||||
rHost, duration);
|
||||
if(r==0)
|
||||
/*
|
||||
printf("%02hu - %s %s->%s:%s\tenabled=%s leaseDuration=%s\n"
|
||||
" desc='%s' rHost='%s'\n",
|
||||
i, protocol, extPort, intClient, intPort,
|
||||
enabled, duration,
|
||||
desc, rHost);
|
||||
*/
|
||||
printf("%2hu %s %5s->%s:%-5s '%s' '%s' %s\n",
|
||||
i, protocol, extPort, intClient, intPort,
|
||||
desc, rHost, duration);
|
||||
else if(r==713) /* ignore SpecifiedArrayIndexInvalid => we are at the end of the list */
|
||||
break;
|
||||
else
|
||||
printf("GetGenericPortMappingEntry() returned %d (%s)\n",
|
||||
r, strupnperror(r));
|
||||
} while(r == 0 && i++ < 65535);
|
||||
}
|
||||
|
||||
static void NewListRedirections(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data)
|
||||
{
|
||||
int r;
|
||||
int i = 0;
|
||||
struct PortMappingParserData pdata;
|
||||
struct PortMapping * pm;
|
||||
|
||||
memset(&pdata, 0, sizeof(struct PortMappingParserData));
|
||||
r = UPNP_GetListOfPortMappings(urls->controlURL,
|
||||
data->first.servicetype,
|
||||
"1",
|
||||
"65535",
|
||||
"TCP",
|
||||
"1000",
|
||||
&pdata);
|
||||
if(r == UPNPCOMMAND_SUCCESS)
|
||||
{
|
||||
printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n");
|
||||
for(pm = pdata.l_head; pm != NULL; pm = pm->l_next)
|
||||
{
|
||||
printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n",
|
||||
i, pm->protocol, pm->externalPort, pm->internalClient,
|
||||
pm->internalPort,
|
||||
pm->description, pm->remoteHost,
|
||||
(unsigned)pm->leaseTime);
|
||||
i++;
|
||||
}
|
||||
FreePortListing(&pdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("GetListOfPortMappings() returned %d (%s)\n",
|
||||
r, strupnperror(r));
|
||||
}
|
||||
r = UPNP_GetListOfPortMappings(urls->controlURL,
|
||||
data->first.servicetype,
|
||||
"1",
|
||||
"65535",
|
||||
"UDP",
|
||||
"1000",
|
||||
&pdata);
|
||||
if(r == UPNPCOMMAND_SUCCESS)
|
||||
{
|
||||
for(pm = pdata.l_head; pm != NULL; pm = pm->l_next)
|
||||
{
|
||||
printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n",
|
||||
i, pm->protocol, pm->externalPort, pm->internalClient,
|
||||
pm->internalPort,
|
||||
pm->description, pm->remoteHost,
|
||||
(unsigned)pm->leaseTime);
|
||||
i++;
|
||||
}
|
||||
FreePortListing(&pdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("GetListOfPortMappings() returned %d (%s)\n",
|
||||
r, strupnperror(r));
|
||||
}
|
||||
}
|
||||
|
||||
/* Test function
|
||||
* 1 - get connection type
|
||||
* 2 - get extenal ip address
|
||||
* 3 - Add port mapping
|
||||
* 4 - get this port mapping from the IGD */
|
||||
static int SetRedirectAndTest(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
const char * iaddr,
|
||||
const char * iport,
|
||||
const char * eport,
|
||||
const char * proto,
|
||||
const char * leaseDuration,
|
||||
const char * remoteHost,
|
||||
const char * description,
|
||||
int addAny)
|
||||
{
|
||||
char externalIPAddress[40];
|
||||
char intClient[40];
|
||||
char intPort[6];
|
||||
char reservedPort[6];
|
||||
char duration[16];
|
||||
int r;
|
||||
|
||||
if(!iaddr || !iport || !eport || !proto)
|
||||
{
|
||||
fprintf(stderr, "Wrong arguments\n");
|
||||
return -1;
|
||||
}
|
||||
proto = protofix(proto);
|
||||
if(!proto)
|
||||
{
|
||||
fprintf(stderr, "invalid protocol\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = UPNP_GetExternalIPAddress(urls->controlURL,
|
||||
data->first.servicetype,
|
||||
externalIPAddress);
|
||||
if(r!=UPNPCOMMAND_SUCCESS)
|
||||
printf("GetExternalIPAddress failed.\n");
|
||||
else
|
||||
printf("ExternalIPAddress = %s\n", externalIPAddress);
|
||||
|
||||
if (addAny) {
|
||||
r = UPNP_AddAnyPortMapping(urls->controlURL, data->first.servicetype,
|
||||
eport, iport, iaddr, description,
|
||||
proto, remoteHost, leaseDuration, reservedPort);
|
||||
if(r==UPNPCOMMAND_SUCCESS)
|
||||
eport = reservedPort;
|
||||
else
|
||||
printf("AddAnyPortMapping(%s, %s, %s) failed with code %d (%s)\n",
|
||||
eport, iport, iaddr, r, strupnperror(r));
|
||||
} else {
|
||||
r = UPNP_AddPortMapping(urls->controlURL, data->first.servicetype,
|
||||
eport, iport, iaddr, description,
|
||||
proto, remoteHost, leaseDuration);
|
||||
if(r!=UPNPCOMMAND_SUCCESS) {
|
||||
printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
|
||||
eport, iport, iaddr, r, strupnperror(r));
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
r = UPNP_GetSpecificPortMappingEntry(urls->controlURL,
|
||||
data->first.servicetype,
|
||||
eport, proto, remoteHost,
|
||||
intClient, intPort, NULL/*desc*/,
|
||||
NULL/*enabled*/, duration);
|
||||
if(r!=UPNPCOMMAND_SUCCESS) {
|
||||
printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n",
|
||||
r, strupnperror(r));
|
||||
return -2;
|
||||
} else {
|
||||
printf("InternalIP:Port = %s:%s\n", intClient, intPort);
|
||||
printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n",
|
||||
externalIPAddress, eport, proto, intClient, intPort, duration);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
RemoveRedirect(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
const char * eport,
|
||||
const char * proto,
|
||||
const char * remoteHost)
|
||||
{
|
||||
int r;
|
||||
if(!proto || !eport)
|
||||
{
|
||||
fprintf(stderr, "invalid arguments\n");
|
||||
return -1;
|
||||
}
|
||||
proto = protofix(proto);
|
||||
if(!proto)
|
||||
{
|
||||
fprintf(stderr, "protocol invalid\n");
|
||||
return -1;
|
||||
}
|
||||
r = UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, remoteHost);
|
||||
if(r!=UPNPCOMMAND_SUCCESS) {
|
||||
printf("UPNP_DeletePortMapping() failed with code : %d\n", r);
|
||||
return -2;
|
||||
}else {
|
||||
printf("UPNP_DeletePortMapping() returned : %d\n", r);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
RemoveRedirectRange(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
const char * ePortStart, char const * ePortEnd,
|
||||
const char * proto, const char * manage)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!manage)
|
||||
manage = "0";
|
||||
|
||||
if(!proto || !ePortStart || !ePortEnd)
|
||||
{
|
||||
fprintf(stderr, "invalid arguments\n");
|
||||
return -1;
|
||||
}
|
||||
proto = protofix(proto);
|
||||
if(!proto)
|
||||
{
|
||||
fprintf(stderr, "protocol invalid\n");
|
||||
return -1;
|
||||
}
|
||||
r = UPNP_DeletePortMappingRange(urls->controlURL, data->first.servicetype, ePortStart, ePortEnd, proto, manage);
|
||||
if(r!=UPNPCOMMAND_SUCCESS) {
|
||||
printf("UPNP_DeletePortMappingRange() failed with code : %d\n", r);
|
||||
return -2;
|
||||
}else {
|
||||
printf("UPNP_DeletePortMappingRange() returned : %d\n", r);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* IGD:2, functions for service WANIPv6FirewallControl:1 */
|
||||
static void GetFirewallStatus(struct UPNPUrls * urls, struct IGDdatas * data)
|
||||
{
|
||||
unsigned int bytessent, bytesreceived, packetsreceived, packetssent;
|
||||
int firewallEnabled = 0, inboundPinholeAllowed = 0;
|
||||
|
||||
UPNP_GetFirewallStatus(urls->controlURL_6FC, data->IPv6FC.servicetype, &firewallEnabled, &inboundPinholeAllowed);
|
||||
printf("FirewallEnabled: %d & Inbound Pinhole Allowed: %d\n", firewallEnabled, inboundPinholeAllowed);
|
||||
printf("GetFirewallStatus:\n Firewall Enabled: %s\n Inbound Pinhole Allowed: %s\n", (firewallEnabled)? "Yes":"No", (inboundPinholeAllowed)? "Yes":"No");
|
||||
|
||||
bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype);
|
||||
bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype);
|
||||
packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype);
|
||||
packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype);
|
||||
printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived);
|
||||
printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived);
|
||||
}
|
||||
|
||||
/* Test function
|
||||
* 1 - Add pinhole
|
||||
* 2 - Check if pinhole is working from the IGD side */
|
||||
static int SetPinholeAndTest(struct UPNPUrls * urls, struct IGDdatas * data,
|
||||
const char * remoteaddr, const char * eport,
|
||||
const char * intaddr, const char * iport,
|
||||
const char * proto, const char * lease_time)
|
||||
{
|
||||
char uniqueID[8];
|
||||
/*int isWorking = 0;*/
|
||||
int r;
|
||||
char proto_tmp[8];
|
||||
|
||||
if(!intaddr || !remoteaddr || !iport || !eport || !proto || !lease_time)
|
||||
{
|
||||
fprintf(stderr, "Wrong arguments\n");
|
||||
return -1;
|
||||
}
|
||||
if(atoi(proto) == 0)
|
||||
{
|
||||
const char * protocol;
|
||||
protocol = protofix(proto);
|
||||
if(protocol && (strcmp("TCP", protocol) == 0))
|
||||
{
|
||||
snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_TCP);
|
||||
proto = proto_tmp;
|
||||
}
|
||||
else if(protocol && (strcmp("UDP", protocol) == 0))
|
||||
{
|
||||
snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_UDP);
|
||||
proto = proto_tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "invalid protocol\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
r = UPNP_AddPinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, lease_time, uniqueID);
|
||||
if(r!=UPNPCOMMAND_SUCCESS)
|
||||
{
|
||||
printf("AddPinhole([%s]:%s -> [%s]:%s) failed with code %d (%s)\n",
|
||||
remoteaddr, eport, intaddr, iport, r, strupnperror(r));
|
||||
return -2;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("AddPinhole: ([%s]:%s -> [%s]:%s) / Pinhole ID = %s\n",
|
||||
remoteaddr, eport, intaddr, iport, uniqueID);
|
||||
/*r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->servicetype_6FC, uniqueID, &isWorking);
|
||||
if(r!=UPNPCOMMAND_SUCCESS)
|
||||
printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r));
|
||||
printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");*/
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test function
|
||||
* 1 - Check if pinhole is working from the IGD side
|
||||
* 2 - Update pinhole */
|
||||
static void GetPinholeAndUpdate(struct UPNPUrls * urls, struct IGDdatas * data,
|
||||
const char * uniqueID, const char * lease_time)
|
||||
{
|
||||
int isWorking = 0;
|
||||
int r;
|
||||
|
||||
if(!uniqueID || !lease_time)
|
||||
{
|
||||
fprintf(stderr, "Wrong arguments\n");
|
||||
return;
|
||||
}
|
||||
/* CheckPinholeWorking is an Optional Action, error 602 should be
|
||||
* returned if it is not implemented */
|
||||
r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking);
|
||||
if(r==UPNPCOMMAND_SUCCESS)
|
||||
printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");
|
||||
else
|
||||
printf("CheckPinholeWorking(%s) failed with code %d (%s)\n", uniqueID, r, strupnperror(r));
|
||||
/* 702 FirewallDisabled Firewall is disabled and this action is disabled
|
||||
* 703 InboundPinholeNotAllowed Creation of inbound pinholes by UPnP CPs
|
||||
* are not allowed and this action is disabled
|
||||
* 704 NoSuchEntry There is no pinhole with the specified UniqueID.
|
||||
* 709 NoTrafficReceived No traffic corresponding to this pinhole has
|
||||
* been received by the gateway. */
|
||||
if(isWorking || (r!=702 && r!=703 && r!=704))
|
||||
{
|
||||
r = UPNP_UpdatePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, lease_time);
|
||||
printf("UpdatePinhole: Pinhole ID = %s with Lease Time: %s\n", uniqueID, lease_time);
|
||||
if(r!=UPNPCOMMAND_SUCCESS)
|
||||
printf("UpdatePinhole: ID (%s) failed with code %d (%s)\n", uniqueID, r, strupnperror(r));
|
||||
}
|
||||
}
|
||||
|
||||
/* Test function
|
||||
* Get pinhole timeout
|
||||
*/
|
||||
static void GetPinholeOutboundTimeout(struct UPNPUrls * urls, struct IGDdatas * data,
|
||||
const char * remoteaddr, const char * eport,
|
||||
const char * intaddr, const char * iport,
|
||||
const char * proto)
|
||||
{
|
||||
int timeout = 0;
|
||||
int r;
|
||||
|
||||
if(!intaddr || !remoteaddr || !iport || !eport || !proto)
|
||||
{
|
||||
fprintf(stderr, "Wrong arguments\n");
|
||||
return;
|
||||
}
|
||||
|
||||
r = UPNP_GetOutboundPinholeTimeout(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, &timeout);
|
||||
if(r!=UPNPCOMMAND_SUCCESS)
|
||||
printf("GetOutboundPinholeTimeout([%s]:%s -> [%s]:%s) failed with code %d (%s)\n",
|
||||
intaddr, iport, remoteaddr, eport, r, strupnperror(r));
|
||||
else
|
||||
printf("GetOutboundPinholeTimeout: ([%s]:%s -> [%s]:%s) / Timeout = %d\n", intaddr, iport, remoteaddr, eport, timeout);
|
||||
}
|
||||
|
||||
static void
|
||||
GetPinholePackets(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data, const char * uniqueID)
|
||||
{
|
||||
int r, pinholePackets = 0;
|
||||
if(!uniqueID)
|
||||
{
|
||||
fprintf(stderr, "invalid arguments\n");
|
||||
return;
|
||||
}
|
||||
r = UPNP_GetPinholePackets(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &pinholePackets);
|
||||
if(r!=UPNPCOMMAND_SUCCESS)
|
||||
printf("GetPinholePackets() failed with code %d (%s)\n", r, strupnperror(r));
|
||||
else
|
||||
printf("GetPinholePackets: Pinhole ID = %s / PinholePackets = %d\n", uniqueID, pinholePackets);
|
||||
}
|
||||
|
||||
static void
|
||||
CheckPinhole(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data, const char * uniqueID)
|
||||
{
|
||||
int r, isWorking = 0;
|
||||
if(!uniqueID)
|
||||
{
|
||||
fprintf(stderr, "invalid arguments\n");
|
||||
return;
|
||||
}
|
||||
r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking);
|
||||
if(r!=UPNPCOMMAND_SUCCESS)
|
||||
printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r));
|
||||
else
|
||||
printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");
|
||||
}
|
||||
|
||||
static int
|
||||
RemovePinhole(struct UPNPUrls * urls,
|
||||
struct IGDdatas * data, const char * uniqueID)
|
||||
{
|
||||
int r;
|
||||
if(!uniqueID)
|
||||
{
|
||||
fprintf(stderr, "invalid arguments\n");
|
||||
return -1;
|
||||
}
|
||||
r = UPNP_DeletePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID);
|
||||
printf("UPNP_DeletePinhole() returned : %d\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void usage(FILE * out, const char * argv0) {
|
||||
fprintf(out, "Usage:\n");
|
||||
fprintf(out, " %s [options] -a ip port external_port protocol [duration] [remote host]\n Add port mapping\n", argv0);
|
||||
fprintf(out, " %s [options] -r port1 [external_port1] protocol1 [port2 [external_port2] protocol2] [...]\n Add multiple port mappings to the current host\n", argv0);
|
||||
fprintf(out, " %s [options] -d external_port protocol [remote host]\n Delete port redirection\n", argv0);
|
||||
fprintf(out, " %s [options] -f external_port1 protocol1 [external_port2 protocol2] [...]\n Delete multiple port redirections\n", argv0);
|
||||
fprintf(out, " %s [options] -s\n Get Connection status\n", argv0);
|
||||
fprintf(out, " %s [options] -l\n List redirections\n", argv0);
|
||||
fprintf(out, " %s [options] -L\n List redirections (using GetListOfPortMappings (for IGD:2 only)\n", argv0);
|
||||
fprintf(out, " %s [options] -n ip port external_port protocol [duration] [remote host]\n Add (any) port mapping allowing IGD to use alternative external_port (for IGD:2 only)\n", argv0);
|
||||
fprintf(out, " %s [options] -N external_port_start external_port_end protocol [manage]\n Delete range of port mappings (for IGD:2 only)\n", argv0);
|
||||
fprintf(out, " %s [options] -A remote_ip remote_port internal_ip internal_port protocol lease_time\n Add Pinhole (for IGD:2 only)\n", argv0);
|
||||
fprintf(out, " %s [options] -U uniqueID new_lease_time\n Update Pinhole (for IGD:2 only)\n", argv0);
|
||||
fprintf(out, " %s [options] -C uniqueID\n Check if Pinhole is Working (for IGD:2 only)\n", argv0);
|
||||
fprintf(out, " %s [options] -K uniqueID\n Get Number of packets going through the rule (for IGD:2 only)\n", argv0);
|
||||
fprintf(out, " %s [options] -D uniqueID\n Delete Pinhole (for IGD:2 only)\n", argv0);
|
||||
fprintf(out, " %s [options] -S\n Get Firewall status (for IGD:2 only)\n", argv0);
|
||||
fprintf(out, " %s [options] -G remote_ip remote_port internal_ip internal_port protocol\n Get Outbound Pinhole Timeout (for IGD:2 only)\n", argv0);
|
||||
fprintf(out, " %s [options] -P\n Get Presentation URL\n", argv0);
|
||||
fprintf(out, "\nNotes:\n");
|
||||
fprintf(out, " protocol is UDP or TCP.\n");
|
||||
fprintf(out, " Use \"\" for any remote_host and 0 for any remote_port.\n");
|
||||
fprintf(out, " @ can be used in option -a, -n, -A and -G to represent local LAN address.\n");
|
||||
fprintf(out, "\nOptions:\n");
|
||||
fprintf(out, " -e description : set description for port mapping.\n");
|
||||
fprintf(out, " -6 : use IPv6 instead of IPv4.\n");
|
||||
fprintf(out, " -u URL : bypass discovery process by providing the XML root description URL.\n");
|
||||
fprintf(out, " -m address/interface : provide IPv4 address or interface name (IPv4 or IPv6) to use for sending SSDP multicast packets.\n");
|
||||
fprintf(out, " -z localport : SSDP packets local (source) port (1024-65535).\n");
|
||||
fprintf(out, " -p path : use this path for MiniSSDPd socket.\n");
|
||||
fprintf(out, " -t ttl : set multicast TTL. Default value is 2.\n");
|
||||
fprintf(out, " -i : ignore errors and try to use also disconnected IGD or non-IGD device.\n");
|
||||
}
|
||||
|
||||
/* sample upnp client program */
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
char command = 0;
|
||||
char ** commandargv = 0;
|
||||
int commandargc = 0;
|
||||
struct UPNPDev * devlist = 0;
|
||||
char lanaddr[64] = "unset"; /* my ip address on the LAN */
|
||||
char wanaddr[64] = "unset"; /* up address of the IGD on the WAN */
|
||||
int i;
|
||||
const char * rootdescurl = 0;
|
||||
const char * multicastif = 0;
|
||||
const char * minissdpdpath = 0;
|
||||
int localport = UPNP_LOCAL_PORT_ANY;
|
||||
int retcode = 0;
|
||||
int error = 0;
|
||||
int ipv6 = 0;
|
||||
int ignore = 0;
|
||||
unsigned char ttl = 2; /* defaulting to 2 */
|
||||
const char * description = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
WSADATA wsaData;
|
||||
int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
|
||||
if(nResult != NO_ERROR)
|
||||
{
|
||||
fprintf(stderr, "WSAStartup() failed.\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
printf("upnpc: miniupnpc library test client, version %s.\n", MINIUPNPC_VERSION_STRING);
|
||||
printf(" (c) 2005-2025 Thomas Bernard.\n");
|
||||
printf("More information at https://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/\n\n");
|
||||
|
||||
/* command line processing */
|
||||
for(i=1; i<argc; i++)
|
||||
{
|
||||
if(0 == strcmp(argv[i], "--help") || 0 == strcmp(argv[i], "-h"))
|
||||
{
|
||||
usage(stdout, argv[0]);
|
||||
return 0;
|
||||
}
|
||||
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];
|
||||
i++;
|
||||
commandargv = argv + i;
|
||||
commandargc = argc - i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "option '%s' invalid\n", argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if(!command
|
||||
|| (command == 'a' && commandargc<4)
|
||||
|| (command == 'r' && commandargc<2)
|
||||
|| (command == 'A' && commandargc<6)
|
||||
|| (command == 'd' && commandargc<2)
|
||||
|| (command == 'D' && commandargc<1)
|
||||
|| (command == 'n' && commandargc<4)
|
||||
|| (command == 'N' && commandargc<3)
|
||||
|| (command == 'U' && commandargc<2)
|
||||
|| (command == 'K' && commandargc<1)
|
||||
|| (command == 'C' && commandargc<1)
|
||||
|| (command == 'G' && commandargc<5))
|
||||
{
|
||||
fprintf(stderr, "Command line argument error.\n\n");
|
||||
usage(stderr, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(ipv6 == 0 && (command == 'A' || command == 'D' || command == 'U' || command == 'K' || command == 'C' || command == 'G')) {
|
||||
printf("Use IPv6 (option -6) GUA address to ensure UPnP IGDv2 pinholes are allowed\n\n");
|
||||
}
|
||||
|
||||
if( rootdescurl
|
||||
|| (devlist = upnpDiscover(2000, multicastif, minissdpdpath,
|
||||
localport, ipv6, ttl, &error)))
|
||||
{
|
||||
struct UPNPDev * device;
|
||||
struct UPNPUrls urls;
|
||||
struct IGDdatas data;
|
||||
if(devlist)
|
||||
{
|
||||
printf("List of UPNP devices found on the network :\n");
|
||||
for(device = devlist; device; device = device->pNext)
|
||||
{
|
||||
printf(" desc: %s\n st: %s\n\n",
|
||||
device->descURL, device->st);
|
||||
}
|
||||
}
|
||||
else if(!rootdescurl)
|
||||
{
|
||||
printf("upnpDiscover() error code=%d\n", error);
|
||||
}
|
||||
i = 1;
|
||||
if( (rootdescurl && UPNP_GetIGDFromUrl(rootdescurl, &urls, &data, lanaddr, sizeof(lanaddr)))
|
||||
|| (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr), wanaddr, sizeof(wanaddr))))
|
||||
{
|
||||
switch(i) {
|
||||
case UPNP_CONNECTED_IGD:
|
||||
printf("Found valid IGD : %s\n", urls.controlURL);
|
||||
break;
|
||||
case UPNP_PRIVATEIP_IGD:
|
||||
printf("Found an IGD with a reserved IP address (%s) : %s\n", wanaddr, urls.controlURL);
|
||||
break;
|
||||
case UPNP_DISCONNECTED_IGD:
|
||||
printf("Found a (not connected?) IGD : %s\n", urls.controlURL);
|
||||
if (ignore) printf("Trying to continue anyway\n");
|
||||
break;
|
||||
case UPNP_UNKNOWN_DEVICE:
|
||||
printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL);
|
||||
if (ignore) printf("Trying to continue anyway\n");
|
||||
break;
|
||||
default:
|
||||
printf("Found device (igd ?) : %s\n", urls.controlURL);
|
||||
if (ignore) printf("Trying to continue anyway\n");
|
||||
}
|
||||
if(i==UPNP_CONNECTED_IGD || i==UPNP_PRIVATEIP_IGD || ignore) {
|
||||
|
||||
printf("Local LAN ip address : %s\n", lanaddr);
|
||||
#if 0
|
||||
printf("getting \"%s\"\n", urls.ipcondescURL);
|
||||
descXML = miniwget(urls.ipcondescURL, &descXMLsize);
|
||||
if(descXML)
|
||||
{
|
||||
/*fwrite(descXML, 1, descXMLsize, stdout);*/
|
||||
free(descXML); descXML = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* replace '@' with the local LAN ip address */
|
||||
if ((command == 'a' || command == 'n') && 0 == strcmp(commandargv[0], "@"))
|
||||
commandargv[0] = lanaddr;
|
||||
else if ((command == 'A' || command == 'G') && 0 == strcmp(commandargv[2], "@"))
|
||||
commandargv[2] = lanaddr;
|
||||
|
||||
switch(command)
|
||||
{
|
||||
case 'l':
|
||||
DisplayInfos(&urls, &data);
|
||||
ListRedirections(&urls, &data);
|
||||
break;
|
||||
case 'L':
|
||||
NewListRedirections(&urls, &data);
|
||||
break;
|
||||
case 'a':
|
||||
if (SetRedirectAndTest(&urls, &data,
|
||||
commandargv[0], commandargv[1],
|
||||
commandargv[2], commandargv[3],
|
||||
(commandargc > 4) && is_int(commandargv[4]) ? commandargv[4] : "0",
|
||||
(commandargc > 4) && !is_int(commandargv[4]) ? commandargv[4] : (commandargc > 5) ? commandargv[5] : NULL,
|
||||
description, 0) < 0)
|
||||
retcode = 2;
|
||||
break;
|
||||
case 'd':
|
||||
if (RemoveRedirect(&urls, &data, commandargv[0], commandargv[1],
|
||||
commandargc > 2 ? commandargv[2] : NULL) < 0)
|
||||
retcode = 2;
|
||||
break;
|
||||
case 'n': /* aNy */
|
||||
if (SetRedirectAndTest(&urls, &data,
|
||||
commandargv[0], commandargv[1],
|
||||
commandargv[2], commandargv[3],
|
||||
(commandargc > 4) && is_int(commandargv[4]) ? commandargv[4] : "0",
|
||||
(commandargc > 4) && !is_int(commandargv[4]) ? commandargv[4] : (commandargc > 5) ? commandargv[5] : NULL,
|
||||
description, 1) < 0)
|
||||
retcode = 2;
|
||||
break;
|
||||
case 'N':
|
||||
if (commandargc < 3)
|
||||
fprintf(stderr, "too few arguments\n");
|
||||
|
||||
if (RemoveRedirectRange(&urls, &data, commandargv[0], commandargv[1], commandargv[2],
|
||||
commandargc > 3 ? commandargv[3] : NULL) < 0)
|
||||
retcode = 2;
|
||||
break;
|
||||
case 's':
|
||||
GetConnectionStatus(&urls, &data);
|
||||
break;
|
||||
case 'r':
|
||||
i = 0;
|
||||
while(i<commandargc)
|
||||
{
|
||||
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 'f':
|
||||
i = 0;
|
||||
while(i<commandargc)
|
||||
{
|
||||
if(!is_int(commandargv[i])) {
|
||||
/* 1st parameter not an integer : error */
|
||||
fprintf(stderr, "command -f : %s is not an port number\n", commandargv[i]);
|
||||
retcode = 1;
|
||||
break;
|
||||
} else if(i+1 == commandargc){
|
||||
/* too few arguments */
|
||||
fprintf(stderr, "command -f : too few arguments\n");
|
||||
retcode = 2;
|
||||
break;
|
||||
} else {
|
||||
/* <port> <protocol> */
|
||||
if (RemoveRedirect(&urls, &data,
|
||||
commandargv[i], commandargv[i+1], NULL) < 0)
|
||||
retcode = 3;
|
||||
i+=2; /* 2 parameters parsed */
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'A':
|
||||
if (SetPinholeAndTest(&urls, &data,
|
||||
commandargv[0], commandargv[1],
|
||||
commandargv[2], commandargv[3],
|
||||
commandargv[4], commandargv[5]) < 0)
|
||||
retcode = 2;
|
||||
break;
|
||||
case 'U':
|
||||
GetPinholeAndUpdate(&urls, &data,
|
||||
commandargv[0], commandargv[1]);
|
||||
break;
|
||||
case 'C':
|
||||
for(i=0; i<commandargc; i++)
|
||||
{
|
||||
CheckPinhole(&urls, &data, commandargv[i]);
|
||||
}
|
||||
break;
|
||||
case 'K':
|
||||
for(i=0; i<commandargc; i++)
|
||||
{
|
||||
GetPinholePackets(&urls, &data, commandargv[i]);
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
for(i=0; i<commandargc; i++)
|
||||
{
|
||||
if (RemovePinhole(&urls, &data, commandargv[i]) < 0)
|
||||
retcode = 2;
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
GetFirewallStatus(&urls, &data);
|
||||
break;
|
||||
case 'G':
|
||||
GetPinholeOutboundTimeout(&urls, &data,
|
||||
commandargv[0], commandargv[1],
|
||||
commandargv[2], commandargv[3],
|
||||
commandargv[4]);
|
||||
break;
|
||||
case 'P':
|
||||
printf("Presentation URL found:\n");
|
||||
printf(" %s\n", data.presentationurl);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown switch -%c\n", command);
|
||||
retcode = 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n");
|
||||
retcode = 1;
|
||||
}
|
||||
FreeUPNPUrls(&urls);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n");
|
||||
retcode = 1;
|
||||
}
|
||||
freeUPNPDevlist(devlist); devlist = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
565
Externals/miniupnpc/src/upnpcommands.c
vendored
565
Externals/miniupnpc/src/upnpcommands.c
vendored
File diff suppressed because it is too large
Load diff
518
Externals/miniupnpc/src/upnpcommands.h
vendored
518
Externals/miniupnpc/src/upnpcommands.h
vendored
|
@ -1,50 +1,113 @@
|
|||
/* $Id: upnpcommands.h,v 1.30 2015/07/15 12:21:28 nanard Exp $ */
|
||||
/* Miniupnp project : http://miniupnp.free.fr/
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005-2015 Thomas Bernard
|
||||
/* $Id: upnpcommands.h,v 1.34 2025/02/08 23:15:17 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-2025 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided within this distribution */
|
||||
#ifndef UPNPCOMMANDS_H_INCLUDED
|
||||
#define UPNPCOMMANDS_H_INCLUDED
|
||||
|
||||
#include "upnpreplyparse.h"
|
||||
#include "portlistingparse.h"
|
||||
/*! \file upnpcommands.h
|
||||
* \brief Internet Gateway Device methods
|
||||
*
|
||||
* See the documentation for both IGD v1 and IGD v2 :
|
||||
* - https://upnp.org/specs/gw/UPnP-gw-InternetGatewayDevice-v1-Device.pdf
|
||||
* - https://upnp.org/specs/gw/UPnP-gw-InternetGatewayDevice-v2-Device.pdf
|
||||
*
|
||||
* The methods are from WANIPConnection:1 or 2, WANCommonInterfaceConfig:1,
|
||||
* and WANIPv6FirewallControl:1
|
||||
*
|
||||
*/
|
||||
|
||||
#include "miniupnpc_declspec.h"
|
||||
#include "miniupnpctypes.h"
|
||||
|
||||
/* MiniUPnPc return codes : */
|
||||
/*! \brief value for success */
|
||||
#define UPNPCOMMAND_SUCCESS (0)
|
||||
/*! \brief value for unknown error */
|
||||
#define UPNPCOMMAND_UNKNOWN_ERROR (-1)
|
||||
/*! \brief error while checking the arguments */
|
||||
#define UPNPCOMMAND_INVALID_ARGS (-2)
|
||||
/*! \brief HTTP communication error */
|
||||
#define UPNPCOMMAND_HTTP_ERROR (-3)
|
||||
/*! \brief The response contains invalid values */
|
||||
#define UPNPCOMMAND_INVALID_RESPONSE (-4)
|
||||
/*! \brief Memory allocation error */
|
||||
#define UPNPCOMMAND_MEM_ALLOC_ERROR (-5)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct PortMappingParserData;
|
||||
|
||||
/*! \brief WANCommonInterfaceConfig:GetTotalBytesSent
|
||||
*
|
||||
* Note: this is a 32bits unsigned value and rolls over to 0 after reaching
|
||||
* the maximum value
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANCommonInterfaceConfig of
|
||||
* a WANDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
|
||||
*/
|
||||
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
|
||||
UPNP_GetTotalBytesSent(const char * controlURL,
|
||||
const char * servicetype);
|
||||
|
||||
/*! \brief WANCommonInterfaceConfig:GetTotalBytesReceived
|
||||
*
|
||||
* Note: this is a 32bits unsigned value and rolls over to 0 after reaching
|
||||
* the maximum value
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANCommonInterfaceConfig of a WANDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
|
||||
*/
|
||||
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
|
||||
UPNP_GetTotalBytesReceived(const char * controlURL,
|
||||
const char * servicetype);
|
||||
|
||||
/*! \brief WANCommonInterfaceConfig:GetTotalPacketsSent
|
||||
*
|
||||
* Note: this is a 32bits unsigned value and rolls over to 0 after reaching
|
||||
* the maximum value
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANCommonInterfaceConfig of a WANDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
|
||||
*/
|
||||
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
|
||||
UPNP_GetTotalPacketsSent(const char * controlURL,
|
||||
const char * servicetype);
|
||||
|
||||
/*! \brief WANCommonInterfaceConfig:GetTotalBytesReceived
|
||||
*
|
||||
* Note: this is a 32bits unsigned value and rolls over to 0 after reaching
|
||||
* the maximum value
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANCommonInterfaceConfig of a WANDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
|
||||
*/
|
||||
MINIUPNP_LIBSPEC UNSIGNED_INTEGER
|
||||
UPNP_GetTotalPacketsReceived(const char * controlURL,
|
||||
const char * servicetype);
|
||||
|
||||
/* UPNP_GetStatusInfo()
|
||||
* status and lastconnerror are 64 byte buffers
|
||||
* Return values :
|
||||
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
|
||||
* or a UPnP Error code */
|
||||
/*! \brief WANIPConnection:GetStatusInfo()
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1
|
||||
* \param[out] status 64 bytes buffer : `Unconfigured`, `Connecting`,
|
||||
* `Connected`, `PendingDisconnect`, `Disconnecting`, `Disconnected`
|
||||
* \param[out] uptime time in seconds
|
||||
* \param[out] lastconnerror 64 bytes buffer : `ERROR_NONE`,
|
||||
* `ERROR_COMMAND_ABORTED`, `ERROR_NOT_ENABLED_FOR_INTERNET`,
|
||||
* `ERROR_USER_DISCONNECT`, `ERROR_ISP_DISCONNECT`,
|
||||
* `ERROR_IDLE_DISCONNECT`, `ERROR_FORCED_DISCONNECT`,
|
||||
* `ERROR_NO_CARRIER`, `ERROR_IP_CONFIGURATION`, `ERROR_UNKNOWN`
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP Error code
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetStatusInfo(const char * controlURL,
|
||||
const char * servicetype,
|
||||
|
@ -52,76 +115,87 @@ UPNP_GetStatusInfo(const char * controlURL,
|
|||
unsigned int * uptime,
|
||||
char * lastconnerror);
|
||||
|
||||
/* UPNP_GetConnectionTypeInfo()
|
||||
* argument connectionType is a 64 character buffer
|
||||
* Return Values :
|
||||
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
|
||||
* or a UPnP Error code */
|
||||
/*! \brief WANIPConnection:GetConnectionTypeInfo()
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1
|
||||
* \param[out] connectionType 64 characters buffer : `Unconfigured`,
|
||||
* `IP_Routed`, `IP_Bridged`
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP Error code
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetConnectionTypeInfo(const char * controlURL,
|
||||
const char * servicetype,
|
||||
char * connectionType);
|
||||
|
||||
/* UPNP_GetExternalIPAddress() call the corresponding UPNP method.
|
||||
* if the third arg is not null the value is copied to it.
|
||||
* at least 16 bytes must be available
|
||||
*
|
||||
* Return values :
|
||||
* 0 : SUCCESS
|
||||
* NON ZERO : ERROR Either an UPnP error code or an unknown error.
|
||||
/*! \brief WANIPConnection:GetExternalIPAddress()
|
||||
*
|
||||
* possible UPnP Errors :
|
||||
* 402 Invalid Args - See UPnP Device Architecture section on Control.
|
||||
* 501 Action Failed - See UPnP Device Architecture section on Control. */
|
||||
* - 402 Invalid Args - See UPnP Device Architecture section on Control.
|
||||
* - 501 Action Failed - See UPnP Device Architecture section on Control.
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1
|
||||
* \param[out] extIpAdd 16 bytes buffer
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_UNKNOWN_ERROR,
|
||||
* #UPNPCOMMAND_INVALID_ARGS, #UPNPCOMMAND_HTTP_ERROR or an
|
||||
* UPnP error code
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetExternalIPAddress(const char * controlURL,
|
||||
const char * servicetype,
|
||||
char * extIpAdd);
|
||||
|
||||
/* UPNP_GetLinkLayerMaxBitRates()
|
||||
* call WANCommonInterfaceConfig:1#GetCommonLinkProperties
|
||||
/*! \brief UPNP_GetLinkLayerMaxBitRates()
|
||||
* call `WANCommonInterfaceConfig:GetCommonLinkProperties`
|
||||
*
|
||||
* return values :
|
||||
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
|
||||
* or a UPnP Error Code. */
|
||||
* \param[in] controlURL controlURL of the WANCommonInterfaceConfig of a WANDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
|
||||
* \param[out] bitrateDown bits per second
|
||||
* \param[out] bitrateUp bits per second
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP Error Code.
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetLinkLayerMaxBitRates(const char* controlURL,
|
||||
const char* servicetype,
|
||||
unsigned int * bitrateDown,
|
||||
unsigned int * bitrateUp);
|
||||
|
||||
/* UPNP_AddPortMapping()
|
||||
* if desc is NULL, it will be defaulted to "libminiupnpc"
|
||||
* remoteHost is usually NULL because IGD don't support it.
|
||||
*
|
||||
* Return values :
|
||||
* 0 : SUCCESS
|
||||
* NON ZERO : ERROR. Either an UPnP error code or an unknown error.
|
||||
/*! \brief WANIPConnection:AddPortMapping()
|
||||
*
|
||||
* List of possible UPnP errors for AddPortMapping :
|
||||
* errorCode errorDescription (short) - Description (long)
|
||||
* 402 Invalid Args - See UPnP Device Architecture section on Control.
|
||||
* 501 Action Failed - See UPnP Device Architecture section on Control.
|
||||
* 606 Action not authorized - The action requested REQUIRES authorization and
|
||||
* the sender was not authorized.
|
||||
* 715 WildCardNotPermittedInSrcIP - The source IP address cannot be
|
||||
* wild-carded
|
||||
* 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded
|
||||
* 718 ConflictInMappingEntry - The port mapping entry specified conflicts
|
||||
* with a mapping assigned previously to another client
|
||||
* 724 SamePortValuesRequired - Internal and External port values
|
||||
* must be the same
|
||||
* 725 OnlyPermanentLeasesSupported - The NAT implementation only supports
|
||||
* permanent lease times on port mappings
|
||||
* 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard
|
||||
* and cannot be a specific IP address or DNS name
|
||||
* 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and
|
||||
* cannot be a specific port value
|
||||
* 728 NoPortMapsAvailable - There are not enough free ports available to
|
||||
* complete port mapping.
|
||||
* 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed
|
||||
* due to conflict with other mechanisms.
|
||||
* 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded
|
||||
* errorCode errorDescription (short) | Description (long)
|
||||
* ---------------------------------- | -----------------
|
||||
* 402 Invalid Args | See UPnP Device Architecture section on Control.
|
||||
* 501 Action Failed | See UPnP Device Architecture section on Control.
|
||||
* 606 Action not authorized | The action requested REQUIRES authorization and the sender was not authorized.
|
||||
* 715 WildCardNotPermittedInSrcIP | The source IP address cannot be wild-carded
|
||||
* 716 WildCardNotPermittedInExtPort | The external port cannot be wild-carded
|
||||
* 718 ConflictInMappingEntry | The port mapping entry specified conflicts with a mapping assigned previously to another client
|
||||
* 724 SamePortValuesRequired | Internal and External port values must be the same
|
||||
* 725 OnlyPermanentLeasesSupported | The NAT implementation only supports permanent lease times on port mappings
|
||||
* 726 RemoteHostOnlySupportsWildcard | RemoteHost must be a wildcard and cannot be a specific IP address or DNS name
|
||||
* 727 ExternalPortOnlySupportsWildcard | ExternalPort must be a wildcard and cannot be a specific port value
|
||||
* 728 NoPortMapsAvailable | There are not enough free ports available to complete port mapping.
|
||||
* 729 ConflictWithOtherMechanisms | Attempted port mapping is not allowed due to conflict with other mechanisms.
|
||||
* 732 WildCardNotPermittedInIntPort | The internal port cannot be wild-carded
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1
|
||||
* \param[in] extPort External port
|
||||
* \param[in] inPort Internal port
|
||||
* \param[in] inClient IP of Internal client.
|
||||
* \param[in] desc Port Mapping description. if NULL, defaults to
|
||||
* "libminiupnpc"
|
||||
* \param[in] proto `TCP` or `UDP`
|
||||
* \param[in] remoteHost IP or empty string for wildcard. Most IGD don't
|
||||
* support it
|
||||
* \param[in] leaseDuration between 0 and 604800
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_MEM_ALLOC_ERROR, #UPNPCOMMAND_HTTP_ERROR,
|
||||
* #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP error code.
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
|
||||
|
@ -133,28 +207,38 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
|
|||
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.
|
||||
/*! \brief WANIPConnection:AddAnyPortMapping()
|
||||
*
|
||||
* Return values :
|
||||
* 0 : SUCCESS
|
||||
* NON ZERO : ERROR. Either an UPnP error code or an unknown error.
|
||||
* Only in WANIPConnection:2
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:2
|
||||
* \param[in] extPort External port
|
||||
* \param[in] inPort Internal port
|
||||
* \param[in] inClient IP of Internal client.
|
||||
* \param[in] desc Port Mapping description. if NULL, defaults to
|
||||
* "libminiupnpc"
|
||||
* \param[in] proto `TCP` or `UDP`
|
||||
* \param[in] remoteHost IP or empty string for wildcard. Most IGD don't
|
||||
* support it
|
||||
* \param[in] leaseDuration between 0 and 604800
|
||||
* \param[out] reservedPort 6 bytes buffer
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_MEM_ALLOC_ERROR, #UPNPCOMMAND_HTTP_ERROR,
|
||||
* #UPNPCOMMAND_INVALID_RESPONSE, #UPNPCOMMAND_UNKNOWN_ERROR
|
||||
* or a UPnP error code.
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype,
|
||||
|
@ -167,24 +251,35 @@ UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype,
|
|||
const char * leaseDuration,
|
||||
char * reservedPort);
|
||||
|
||||
/* UPNP_DeletePortMapping()
|
||||
* Use same argument values as what was used for AddPortMapping().
|
||||
* remoteHost is usually NULL because IGD don't support it.
|
||||
* Return Values :
|
||||
* 0 : SUCCESS
|
||||
* NON ZERO : error. Either an UPnP error code or an undefined error.
|
||||
/*! \brief WANIPConnection:DeletePortMapping()
|
||||
*
|
||||
* 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 */
|
||||
* Use same argument values as what was used for UPNP_AddPortMapping()
|
||||
*
|
||||
* List of possible UPnP errors for UPNP_DeletePortMapping() :
|
||||
* errorCode errorDescription (short) | Description (long)
|
||||
* ---------------------------------- | ------------------
|
||||
* 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
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1
|
||||
* \param[in] extPort External port
|
||||
* \param[in] proto `TCP` or `UDP`
|
||||
* \param[in] remoteHost IP or empty string for wildcard. Most IGD don't
|
||||
* support it
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_MEM_ALLOC_ERROR, #UPNPCOMMAND_HTTP_ERROR,
|
||||
* #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP error code.
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
|
||||
const char * extPort, const char * proto,
|
||||
const char * remoteHost);
|
||||
|
||||
/* UPNP_DeletePortRangeMapping()
|
||||
/*! \brief WANIPConnection:DeletePortRangeMapping()
|
||||
*
|
||||
* Only in WANIPConnection:2
|
||||
* Use same argument values as what was used for AddPortMapping().
|
||||
* remoteHost is usually NULL because IGD don't support it.
|
||||
* Return Values :
|
||||
|
@ -192,46 +287,66 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
|
|||
* 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. */
|
||||
* errorCode errorDescription (short) | Description (long)
|
||||
* ---------------------------------- | ------------------
|
||||
* 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.
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:2
|
||||
* \param[in] extPortStart External port range start
|
||||
* \param[in] extPortEnd External port range end
|
||||
* \param[in] proto `TCP` or `UDP`
|
||||
* \param[in] manage `0` to remove only the port mappings of this IGD,
|
||||
* `1` to remove port mappings also for other clients
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_MEM_ALLOC_ERROR, #UPNPCOMMAND_HTTP_ERROR,
|
||||
* #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP error code.
|
||||
*/
|
||||
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 */
|
||||
/*! \brief WANIPConnection:GetPortMappingNumberOfEntries()
|
||||
*
|
||||
* not supported by all routers
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1
|
||||
* \param[out] numEntries Port mappings count
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_HTTP_ERROR,
|
||||
* #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP error code.
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetPortMappingNumberOfEntries(const char* controlURL,
|
||||
const char* servicetype,
|
||||
unsigned int * num);
|
||||
UPNP_GetPortMappingNumberOfEntries(const char * controlURL,
|
||||
const char * servicetype,
|
||||
unsigned int * numEntries);
|
||||
|
||||
/* UPNP_GetSpecificPortMappingEntry()
|
||||
* retrieves an existing port mapping
|
||||
* params :
|
||||
* in extPort
|
||||
* in proto
|
||||
* in remoteHost
|
||||
* out intClient (16 bytes)
|
||||
* out intPort (6 bytes)
|
||||
* out desc (80 bytes)
|
||||
* out enabled (4 bytes)
|
||||
* out leaseDuration (16 bytes)
|
||||
/*! \brief retrieves an existing port mapping for a port:protocol
|
||||
*
|
||||
* return value :
|
||||
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
|
||||
* or a UPnP Error Code.
|
||||
* List of possible UPnP errors for UPNP_GetSpecificPortMappingEntry() :
|
||||
* 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.
|
||||
* 714 NoSuchEntryInArray | The specified value does not exist in the array.
|
||||
*
|
||||
* 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.
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1
|
||||
* \param[in] extPort External port
|
||||
* \param[in] proto `TCP` or `UDP`
|
||||
* \param[in] remoteHost IP or empty string for wildcard. Most IGD don't
|
||||
* support it
|
||||
* \param[out] intClient 16 bytes buffer
|
||||
* \param[out] intPort 6 bytes buffer
|
||||
* \param[out] desc 80 bytes buffer
|
||||
* \param[out] enabled 4 bytes buffer
|
||||
* \param[out] leaseDuration 16 bytes
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP Error Code.
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetSpecificPortMappingEntry(const char * controlURL,
|
||||
|
@ -245,27 +360,27 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
|
|||
char * enabled,
|
||||
char * leaseDuration);
|
||||
|
||||
/* UPNP_GetGenericPortMappingEntry()
|
||||
* params :
|
||||
* in index
|
||||
* out extPort (6 bytes)
|
||||
* out intClient (16 bytes)
|
||||
* out intPort (6 bytes)
|
||||
* out protocol (4 bytes)
|
||||
* out desc (80 bytes)
|
||||
* out enabled (4 bytes)
|
||||
* out rHost (64 bytes)
|
||||
* out duration (16 bytes)
|
||||
/*! \brief WANIPConnection:GetGenericPortMappingEntry()
|
||||
*
|
||||
* return value :
|
||||
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
|
||||
* or a UPnP Error Code.
|
||||
* errorCode errorDescription (short) | Description (long)
|
||||
* ---------------------------------- | ------------------
|
||||
* 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
|
||||
*
|
||||
* 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
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:1
|
||||
* \param[in] index
|
||||
* \param[out] extPort 6 bytes buffer
|
||||
* \param[out] intClient 16 bytes buffer
|
||||
* \param[out] intPort 6 bytes buffer
|
||||
* \param[out] protocol 4 bytes buffer
|
||||
* \param[out] desc 80 bytes buffer
|
||||
* \param[out] enabled 4 bytes buffer
|
||||
* \param[out] rHost 64 bytes buffer
|
||||
* \param[out] duration 16 bytes buffer
|
||||
* \return #UPNPCOMMAND_SUCCESS, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_UNKNOWN_ERROR or a UPnP Error Code.
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetGenericPortMappingEntry(const char * controlURL,
|
||||
|
@ -280,14 +395,25 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL,
|
|||
char * rHost,
|
||||
char * duration);
|
||||
|
||||
/* UPNP_GetListOfPortMappings() Available in IGD v2
|
||||
/*! \brief retrieval of a list of existing port mappings
|
||||
*
|
||||
* Available in IGD v2 : WANIPConnection:GetListOfPortMappings()
|
||||
*
|
||||
* Possible UPNP Error codes :
|
||||
* 606 Action not Authorized
|
||||
* 730 PortMappingNotFound - no port mapping is found in the specified range.
|
||||
* 733 InconsistantParameters - NewStartPort and NewEndPort values are not
|
||||
* consistent.
|
||||
* errorCode errorDescription (short) | Description (long)
|
||||
* ---------------------------------- | ------------------
|
||||
* 606 Action not authorized | The action requested REQUIRES authorization and the sender was not authorized.
|
||||
* 730 PortMappingNotFound | no port mapping is found in the specified range.
|
||||
* 733 InconsistantParameters | NewStartPort and NewEndPort values are not consistent.
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPConnection of a
|
||||
* WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPConnection:2
|
||||
* \param[in] startPort port interval start
|
||||
* \param[in] endPort port interval end
|
||||
* \param[in] protocol `TCP` or `UDP`
|
||||
* \param[in] numberOfPorts size limit of the list returned. `0` to request
|
||||
* all port mappings
|
||||
* \param[out] data port mappings list
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetListOfPortMappings(const char * controlURL,
|
||||
|
@ -298,15 +424,48 @@ UPNP_GetListOfPortMappings(const char * controlURL,
|
|||
const char * numberOfPorts,
|
||||
struct PortMappingParserData * data);
|
||||
|
||||
/* IGD:2, functions for service WANIPv6FirewallControl:1 */
|
||||
/*! \brief GetFirewallStatus() retrieves whether the firewall is enabled
|
||||
* and pinhole can be created through UPnP
|
||||
*
|
||||
* IGD:2, functions for service WANIPv6FirewallControl:1
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPv6FirewallControl of a
|
||||
* WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
|
||||
* \param[out] firewallEnabled false (0) or true (1)
|
||||
* \param[out] inboundPinholeAllowed false (0) or true (1)
|
||||
* \return #UPNPCOMMAND_UNKNOWN_ERROR, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_HTTP_ERROR, #UPNPCOMMAND_SUCCESS or an UPnP error code
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetFirewallStatus(const char * controlURL,
|
||||
const char * servicetype,
|
||||
int * firewallEnabled,
|
||||
int * inboundPinholeAllowed);
|
||||
|
||||
/*! \brief retrieve default value after which automatically created pinholes
|
||||
* expire
|
||||
*
|
||||
* The returned value may be specific to the \p proto, \p remoteHost,
|
||||
* \p remotePort, \p intClient and \p intPort, but this behavior depends
|
||||
* on the implementation of the firewall.
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPv6FirewallControl of a
|
||||
* WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
|
||||
* \param[in] remoteHost
|
||||
* \param[in] remotePort
|
||||
* \param[in] intClient
|
||||
* \param[in] intPort
|
||||
* \param[in] proto `TCP` or `UDP`
|
||||
* \param[out] opTimeout lifetime in seconds of an inbound "automatic"
|
||||
* firewall pinhole created by an outbound traffic initiation.
|
||||
* \return #UPNPCOMMAND_UNKNOWN_ERROR, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_HTTP_ERROR, #UPNPCOMMAND_SUCCESS or an UPnP error code
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype,
|
||||
UPNP_GetOutboundPinholeTimeout(const char * controlURL,
|
||||
const char * servicetype,
|
||||
const char * remoteHost,
|
||||
const char * remotePort,
|
||||
const char * intClient,
|
||||
|
@ -314,6 +473,24 @@ UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype
|
|||
const char * proto,
|
||||
int * opTimeout);
|
||||
|
||||
/*! \brief create a new pinhole that allows incoming traffic to pass
|
||||
* through the firewall
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPv6FirewallControl of a
|
||||
* WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
|
||||
* \param[in] remoteHost literal presentation of IPv6 address or domain name.
|
||||
* empty string for wildcard
|
||||
* \param[in] remotePort remote host port. Likely 0 (for wildcard)
|
||||
* \param[in] intClient IP address of internal client. cannot be wildcarded
|
||||
* \param[in] intPort client port. 0 for wildcard
|
||||
* \param[in] proto IP protocol integer (6 for TCP, 17 for UDP, etc.)
|
||||
* 65535 for wildcard.
|
||||
* \param[in] leaseTime in seconds
|
||||
* \param[out] uniqueID 8 bytes buffer
|
||||
* \return #UPNPCOMMAND_UNKNOWN_ERROR, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_HTTP_ERROR, #UPNPCOMMAND_SUCCESS or an UPnP error code
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_AddPinhole(const char * controlURL, const char * servicetype,
|
||||
const char * remoteHost,
|
||||
|
@ -324,18 +501,61 @@ UPNP_AddPinhole(const char * controlURL, const char * servicetype,
|
|||
const char * leaseTime,
|
||||
char * uniqueID);
|
||||
|
||||
/*! \brief update a pinhole’s lease time
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPv6FirewallControl of a
|
||||
* WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
|
||||
* \param[in] uniqueID value obtained through UPNP_AddPinhole()
|
||||
* \param[in] leaseTime in seconds
|
||||
* \return #UPNPCOMMAND_UNKNOWN_ERROR, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_HTTP_ERROR, #UPNPCOMMAND_SUCCESS or an UPnP error code
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_UpdatePinhole(const char * controlURL, const char * servicetype,
|
||||
const char * uniqueID,
|
||||
const char * leaseTime);
|
||||
|
||||
/*! \brief remove a pinhole
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPv6FirewallControl of a
|
||||
* WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
|
||||
* \param[in] uniqueID value obtained through UPNP_AddPinhole()
|
||||
* \return #UPNPCOMMAND_UNKNOWN_ERROR, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_HTTP_ERROR, #UPNPCOMMAND_SUCCESS or an UPnP error code
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID);
|
||||
UPNP_DeletePinhole(const char * controlURL,
|
||||
const char * servicetype,
|
||||
const char * uniqueID);
|
||||
|
||||
/*! \brief checking if a certain pinhole allows traffic to pass through the firewall
|
||||
*
|
||||
* \param[in] controlURL controlURL of the WANIPv6FirewallControl of a
|
||||
* WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
|
||||
* \param[in] uniqueID value obtained through UPNP_AddPinhole()
|
||||
* \param[out] isWorking `0` for false, `1` for true
|
||||
* \return #UPNPCOMMAND_UNKNOWN_ERROR, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_HTTP_ERROR, #UPNPCOMMAND_SUCCESS or an UPnP error code
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype,
|
||||
const char * uniqueID, int * isWorking);
|
||||
|
||||
/*! \brief get the total number of IP packets which have been going through
|
||||
* the specified pinhole
|
||||
* \todo \p packets should be #UNSIGNED_INTEGER
|
||||
* \param[in] controlURL controlURL of the WANIPv6FirewallControl of a
|
||||
* WANConnectionDevice
|
||||
* \param[in] servicetype urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
|
||||
* \param[in] uniqueID value obtained through UPNP_AddPinhole()
|
||||
* \param[out] packets how many IP packets have been going through the
|
||||
* specified pinhole
|
||||
* \return #UPNPCOMMAND_UNKNOWN_ERROR, #UPNPCOMMAND_INVALID_ARGS,
|
||||
* #UPNPCOMMAND_HTTP_ERROR, #UPNPCOMMAND_SUCCESS or an UPnP error code
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetPinholePackets(const char * controlURL, const char * servicetype,
|
||||
const char * uniqueID, int * packets);
|
||||
|
|
36
Externals/miniupnpc/src/upnpdev.h
vendored
36
Externals/miniupnpc/src/upnpdev.h
vendored
|
@ -1,30 +1,52 @@
|
|||
/* $Id: upnpdev.h,v 1.1 2015/08/28 12:14:19 nanard Exp $ */
|
||||
/* $Id: upnpdev.h,v 1.6 2025/02/08 23:15:17 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Web : http://miniupnp.free.fr/
|
||||
* Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||
* Author : Thomas BERNARD
|
||||
* copyright (c) 2005-2015 Thomas Bernard
|
||||
* copyright (c) 2005-2025 Thomas Bernard
|
||||
* This software is subjet to the conditions detailed in the
|
||||
* provided LICENSE file. */
|
||||
#ifndef UPNPDEV_H_INCLUDED
|
||||
#define UPNPDEV_H_INCLUDED
|
||||
|
||||
/*! \file upnpdev.h
|
||||
* \brief UPNPDev device linked-list structure
|
||||
* \todo could be merged into miniupnpc.h
|
||||
*/
|
||||
#include "miniupnpc_declspec.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief UPnP device linked-list
|
||||
*/
|
||||
struct UPNPDev {
|
||||
/*! \brief pointer to the next element */
|
||||
struct UPNPDev * pNext;
|
||||
/*! \brief root description URL */
|
||||
char * descURL;
|
||||
/*! \brief ST: as advertised */
|
||||
char * st;
|
||||
unsigned int scope_id;
|
||||
/*! \brief USN: as advertised */
|
||||
char * usn;
|
||||
char buffer[3];
|
||||
/*! \brief IPv6 scope id of the network interface */
|
||||
unsigned int scope_id;
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
/* C99 flexible array member */
|
||||
/*! \brief buffer for descURL, st and usn */
|
||||
char buffer[];
|
||||
#elif defined(__GNUC__)
|
||||
char buffer[0];
|
||||
#else
|
||||
/* Fallback to a hack */
|
||||
char buffer[1];
|
||||
#endif
|
||||
};
|
||||
|
||||
/* freeUPNPDevlist()
|
||||
* free list returned by upnpDiscover() */
|
||||
/*! \brief free list returned by upnpDiscover()
|
||||
* \param[in] devlist linked list to free
|
||||
*/
|
||||
MINIUPNP_LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist);
|
||||
|
||||
|
||||
|
|
53
Externals/miniupnpc/src/upnperrors.c
vendored
53
Externals/miniupnpc/src/upnperrors.c
vendored
|
@ -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.12 2023/06/26 23:19:28 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>
|
||||
|
@ -27,10 +28,14 @@ const char * strupnperror(int err)
|
|||
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:
|
||||
|
@ -42,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;
|
||||
|
@ -67,10 +90,10 @@ const char * strupnperror(int err)
|
|||
s = "ProtocolWildcardingNotAllowed";
|
||||
break;
|
||||
case 708:
|
||||
s = "WildcardNotPermittedInSrcIP";
|
||||
s = "InvalidLayer2Address";
|
||||
break;
|
||||
case 709:
|
||||
s = "NoPacketSent";
|
||||
s = "NoTrafficReceived";
|
||||
break;
|
||||
case 713:
|
||||
s = "SpecifiedArrayIndexInvalid";
|
||||
|
@ -99,6 +122,24 @@ const char * strupnperror(int err)
|
|||
case 727:
|
||||
s = "ExternalPortOnlySupportsWildcard";
|
||||
break;
|
||||
case 728:
|
||||
s = "NoPortMapsAvailable";
|
||||
break;
|
||||
case 729:
|
||||
s = "ConflictWithOtherMechanisms";
|
||||
break;
|
||||
case 730:
|
||||
s = "PortMappingNotFound";
|
||||
break;
|
||||
case 731:
|
||||
s = "ReadOnly";
|
||||
break;
|
||||
case 732:
|
||||
s = "WildCardNotPermittedInIntPort";
|
||||
break;
|
||||
case 733:
|
||||
s = "InconsistentParameters";
|
||||
break;
|
||||
default:
|
||||
s = "UnknownError";
|
||||
break;
|
||||
|
|
22
Externals/miniupnpc/src/upnperrors.h
vendored
22
Externals/miniupnpc/src/upnperrors.h
vendored
|
@ -1,22 +1,32 @@
|
|||
/* $Id: upnperrors.h,v 1.2 2008/07/02 23:31:15 nanard Exp $ */
|
||||
/* (c) 2007-2015 Thomas Bernard
|
||||
/* $Id: upnperrors.h,v 1.8 2025/02/08 23:15:17 nanard Exp $ */
|
||||
/* (c) 2007-2025 Thomas Bernard
|
||||
* All rights reserved.
|
||||
* MiniUPnP Project.
|
||||
* 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. */
|
||||
#ifndef UPNPERRORS_H_INCLUDED
|
||||
#define UPNPERRORS_H_INCLUDED
|
||||
|
||||
/*! \file upnperrors.h
|
||||
* \brief code to string API for errors
|
||||
*/
|
||||
#include "miniupnpc_declspec.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* strupnperror()
|
||||
* Return a string description of the UPnP error code
|
||||
* or NULL for undefinded errors */
|
||||
/*!
|
||||
* \brief convert error code to string
|
||||
*
|
||||
* Work for both MiniUPnPc specific errors and UPnP standard defined
|
||||
* errors.
|
||||
*
|
||||
* \param[in] err numerical error code
|
||||
* \return a string description of the error code
|
||||
* or NULL for undefinded errors
|
||||
*/
|
||||
MINIUPNP_LIBSPEC const char * strupnperror(int err);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
68
Externals/miniupnpc/src/upnpreplyparse.c
vendored
68
Externals/miniupnpc/src/upnpreplyparse.c
vendored
|
@ -1,7 +1,8 @@
|
|||
/* $Id: upnpreplyparse.c,v 1.19 2015/07/15 10:29:11 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2006-2015 Thomas Bernard
|
||||
/* $Id: upnpreplyparse.c,v 1.22 2025/02/08 23:12:26 nanard Exp $ */
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||
* (c) 2006-2025 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
|
||||
|
@ -12,6 +13,23 @@
|
|||
#include "upnpreplyparse.h"
|
||||
#include "minixml.h"
|
||||
|
||||
struct NameValue {
|
||||
/*! \brief pointer to the next element */
|
||||
struct NameValue * l_next;
|
||||
/*! \brief name */
|
||||
char name[64];
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
/* C99 flexible array member */
|
||||
/*! \brief character value */
|
||||
char value[];
|
||||
#elif defined(__GNUC__)
|
||||
char value[0];
|
||||
#else
|
||||
/* Fallback to a hack */
|
||||
char value[1];
|
||||
#endif
|
||||
};
|
||||
|
||||
static void
|
||||
NameValueParserStartElt(void * d, const char * name, int l)
|
||||
{
|
||||
|
@ -26,12 +44,12 @@ NameValueParserStartElt(void * d, const char * name, int l)
|
|||
}
|
||||
|
||||
static void
|
||||
NameValueParserEndElt(void * d, const char * name, int l)
|
||||
NameValueParserEndElt(void * d, const char * name, int namelen)
|
||||
{
|
||||
struct NameValueParserData * data = (struct NameValueParserData *)d;
|
||||
struct NameValue * nv;
|
||||
(void)name;
|
||||
(void)l;
|
||||
(void)namelen;
|
||||
if(!data->topelt)
|
||||
return;
|
||||
if(strcmp(data->curelt, "NewPortListing") != 0)
|
||||
|
@ -39,7 +57,7 @@ NameValueParserEndElt(void * d, const char * name, int l)
|
|||
int l;
|
||||
/* standard case. Limited to n chars strings */
|
||||
l = data->cdatalen;
|
||||
nv = malloc(sizeof(struct NameValue));
|
||||
nv = malloc(sizeof(struct NameValue) + l + 1);
|
||||
if(nv == NULL)
|
||||
{
|
||||
/* malloc error */
|
||||
|
@ -49,8 +67,6 @@ NameValueParserEndElt(void * d, const char * name, int l)
|
|||
#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)
|
||||
|
@ -77,6 +93,7 @@ NameValueParserGetData(void * d, const char * datas, int l)
|
|||
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)
|
||||
{
|
||||
|
@ -104,9 +121,7 @@ ParseNameValue(const char * buffer, int bufsize,
|
|||
struct NameValueParserData * data)
|
||||
{
|
||||
struct xmlparser parser;
|
||||
data->l_head = NULL;
|
||||
data->portListing = NULL;
|
||||
data->portListingLength = 0;
|
||||
memset(data, 0, sizeof(struct NameValueParserData));
|
||||
/* init xmlparser object */
|
||||
parser.xmlstart = buffer;
|
||||
parser.xmlsize = bufsize;
|
||||
|
@ -137,7 +152,7 @@ ClearNameValueList(struct NameValueParserData * pdata)
|
|||
|
||||
char *
|
||||
GetValueFromNameValueList(struct NameValueParserData * pdata,
|
||||
const char * Name)
|
||||
const char * name)
|
||||
{
|
||||
struct NameValue * nv;
|
||||
char * p = NULL;
|
||||
|
@ -145,37 +160,12 @@ GetValueFromNameValueList(struct NameValueParserData * pdata,
|
|||
(nv != NULL) && (p == NULL);
|
||||
nv = nv->l_next)
|
||||
{
|
||||
if(strcmp(nv->name, Name) == 0)
|
||||
if(strcmp(nv->name, name) == 0)
|
||||
p = nv->value;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* useless now that minixml ignores namespaces by itself */
|
||||
char *
|
||||
GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
|
||||
const char * Name)
|
||||
{
|
||||
struct NameValue * nv;
|
||||
char * p = NULL;
|
||||
char * pname;
|
||||
for(nv = pdata->head.lh_first;
|
||||
(nv != NULL) && (p == NULL);
|
||||
nv = nv->entries.le_next)
|
||||
{
|
||||
pname = strrchr(nv->name, ':');
|
||||
if(pname)
|
||||
pname++;
|
||||
else
|
||||
pname = nv->name;
|
||||
if(strcmp(pname, Name)==0)
|
||||
p = nv->value;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* debug all-in-one function
|
||||
* do parsing then display to stdout */
|
||||
#ifdef DEBUG
|
||||
|
|
59
Externals/miniupnpc/src/upnpreplyparse.h
vendored
59
Externals/miniupnpc/src/upnpreplyparse.h
vendored
|
@ -1,53 +1,73 @@
|
|||
/* $Id: upnpreplyparse.h,v 1.19 2014/10/27 16:33:19 nanard Exp $ */
|
||||
/* $Id: upnpreplyparse.h,v 1.20 2025/02/08 23:15:17 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2006-2013 Thomas Bernard
|
||||
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||
* (c) 2006-2025 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
|
||||
#ifndef UPNPREPLYPARSE_H_INCLUDED
|
||||
#define UPNPREPLYPARSE_H_INCLUDED
|
||||
|
||||
/*! \file upnpreplyparse.h
|
||||
* \brief Parsing of UPnP SOAP responses
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct NameValue {
|
||||
struct NameValue * l_next;
|
||||
char name[64];
|
||||
char value[128];
|
||||
};
|
||||
/*! \brief Name/Value linked list
|
||||
* not exposed in the public API
|
||||
*/
|
||||
struct NameValue;
|
||||
|
||||
/*! \brief data structure for parsing */
|
||||
struct NameValueParserData {
|
||||
/*! \brief name/value linked list */
|
||||
struct NameValue * l_head;
|
||||
/*! \brief current element name */
|
||||
char curelt[64];
|
||||
/*! \brief port listing array */
|
||||
char * portListing;
|
||||
/*! \brief port listing array length */
|
||||
int portListingLength;
|
||||
/*! \brief flag indicating the current element is */
|
||||
int topelt;
|
||||
/*! \brief top element character data */
|
||||
const char * cdata;
|
||||
/*! \brief top element character data length */
|
||||
int cdatalen;
|
||||
};
|
||||
|
||||
/* ParseNameValue() */
|
||||
/*!
|
||||
* \brief Parse XML and fill the structure
|
||||
*
|
||||
* \param[in] buffer XML data
|
||||
* \param[in] bufsize buffer length
|
||||
* \param[out] data structure to fill
|
||||
*/
|
||||
void
|
||||
ParseNameValue(const char * buffer, int bufsize,
|
||||
struct NameValueParserData * data);
|
||||
|
||||
/* ClearNameValueList() */
|
||||
/*!
|
||||
* \brief free memory
|
||||
*
|
||||
* \param[in,out] pdata data structure
|
||||
*/
|
||||
void
|
||||
ClearNameValueList(struct NameValueParserData * pdata);
|
||||
|
||||
/* GetValueFromNameValueList() */
|
||||
/*!
|
||||
* \brief get a value from the parsed data
|
||||
*
|
||||
* \param[in] pdata data structure
|
||||
* \param[in] name name
|
||||
* \return the value or NULL if not found
|
||||
*/
|
||||
char *
|
||||
GetValueFromNameValueList(struct NameValueParserData * pdata,
|
||||
const char * Name);
|
||||
|
||||
#if 0
|
||||
/* GetValueFromNameValueListIgnoreNS() */
|
||||
char *
|
||||
GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
|
||||
const char * Name);
|
||||
#endif
|
||||
const char * name);
|
||||
|
||||
/* DisplayNameValueList() */
|
||||
#ifdef DEBUG
|
||||
|
@ -60,4 +80,3 @@ DisplayNameValueList(char * buffer, int bufsize);
|
|||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
71
Externals/miniupnpc/src/win32_snprintf.h
vendored
Normal file
71
Externals/miniupnpc/src/win32_snprintf.h
vendored
Normal 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 */
|
Loading…
Add table
Reference in a new issue