From 0cf4ddda4adb0de80d00c4e29736ecdbaa653999 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 10 Nov 2015 15:11:15 -0800 Subject: Some more test results, and fix OSX installer to put symlinks in /usr/local as per El Capitan requirements. --- ext/installfiles/mac/postinst.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'ext') diff --git a/ext/installfiles/mac/postinst.sh b/ext/installfiles/mac/postinst.sh index 7d3d516f..987e131b 100755 --- a/ext/installfiles/mac/postinst.sh +++ b/ext/installfiles/mac/postinst.sh @@ -1,6 +1,6 @@ #!/bin/bash -export PATH=/bin:/usr/bin:/sbin:/usr/sbin +export PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin launchctl unload /Library/LaunchDaemons/com.zerotier.one.plist >>/dev/null 2>&1 @@ -16,7 +16,8 @@ rm -f zerotier-cli zerotier-idtool ln -sf zerotier-one zerotier-cli ln -sf zerotier-one zerotier-idtool -cd /usr/bin +mkdir -p /usr/local/bin +cd /usr/local/bin rm -f zerotier-cli zerotier-idtool ln -sf "/Library/Application Support/ZeroTier/One/zerotier-one" zerotier-cli ln -sf "/Library/Application Support/ZeroTier/One/zerotier-one" zerotier-idtool -- cgit v1.2.3 From 141e2db38c35b0ba4ae30305800d17298ea5a2bf Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 10 Nov 2015 15:47:18 -0800 Subject: More results. --- ext/tap-mac/tuntap/README.orig | 85 --------------------- ext/tap-mac/tuntap/README.zerotier-build | 23 ------ .../http/2015-11-10_03_12500_ec2-east-only.out.xz | Bin 0 -> 802932 bytes 3 files changed, 108 deletions(-) delete mode 100644 ext/tap-mac/tuntap/README.orig delete mode 100644 ext/tap-mac/tuntap/README.zerotier-build create mode 100644 tests/http/2015-11-10_03_12500_ec2-east-only.out.xz (limited to 'ext') diff --git a/ext/tap-mac/tuntap/README.orig b/ext/tap-mac/tuntap/README.orig deleted file mode 100644 index 6a9e526b..00000000 --- a/ext/tap-mac/tuntap/README.orig +++ /dev/null @@ -1,85 +0,0 @@ - -tun/tap driver for Mac OS X -=========================== - -This is an experimental IP tunnel/ethertap driver for Mac OS X/Darwin. It -provides /dev/tunX and /dev/tapX devices. The maximum number of devices can be -configured at compile time, it is currently set to 16. That should be enough in -most cases. - -The driver ships as two kernel extensions, one for tap and one for tun. They are -located in /Library/Extensions and can also be loaded and unloaded by hand. If -you install the startup item, the system will load them automatically at -startup (tun and tap startup items get installed in /Library/StartupItems). - -Operation & Programming notes -============================= - -tapX are ethertap devices which provide an interface to the kernel's ethernet -layer. Packets can be read from and written to the /dev/tapX character devices -one at a time (same name as the interface that shows up in ifconfig). - -tunX are IP tunnel devices. These can be used to exchange IP packets with the -kernel. You will get single packets for each read() and should write() packets -one at a time to /dev/tunX. - -There are some special ioctls with the tun devices that allow you to have them -prepend the address family of the packet when reading it from /dev/tunX. Using -this mode the driver also expects you put this 4-byte address family field -(network byte order) in front of the packets you write to /dev/tunX. - -Here are the ioctls to setup up address prepending mode (for convenience there -also is a header called tun_ioctls.h in the source package that you can use) -Set the int argument to one if you want to have AF prepending, use 0 if you want -to switch it off. - -#define TUNSIFHEAD _IOW('t', 96, int) -#define TUNGIFHEAD _IOR('t', 97, int) - -Prepending mode is off by default. Currently it is not recommended to switch the -mode while packets are in flight on the device. - -The character devices are always visible in the filesystem as /dev/tunX and -/dev/tapX. The number of available character devices is a compile time constant -and is currently fixed to 16. Each character devices is associated with a -network interface of the same name. The network interfaces are only created when -the corresponding character device is opened by a program and will be removed -when the character device is closed. - -The character devices currently provide a pretty minimal interface. Whole -packets are read and written using a singe read/write call. File descriptors -opened on the devices can also be select()ed and support O_NONBLOCK. -Asynchronous i/o and some ioctls are currently unimplemented, but implementing -them shouldn't be very hard. Do it yourself or contact me if you can't live -without. - -There is another limitation imposed by the Darwin 8 kernel. It concerns the -poll() system call; Darwin currently does *not* support that for (character) -devices. Use select() instead. - -The interfaces can be configured using ifconfig, the tap devices also support -setting the MAC address to be used. Both tun and tap should be ready for IPv6. -Just setup addresses and routing as you would do with other interfaces. - -Please contact me if you find any bugs or have suggestions. - -Enjoy! - -Mattias - - - -Uninstalling -============ - -The installer packages for OS X currently don't have support for uninstall as -the installer doesn't provide it. Remove the following directories if you want -to completely remove the files installed: - -/Library/Extensions/tap.kext -/Library/Extensions/tun.kext -/Library/StartupItems/tap -/Library/StartupItems/tun - -Unload the the kernel extensions or reboot and you're done. - diff --git a/ext/tap-mac/tuntap/README.zerotier-build b/ext/tap-mac/tuntap/README.zerotier-build deleted file mode 100644 index 550e0378..00000000 --- a/ext/tap-mac/tuntap/README.zerotier-build +++ /dev/null @@ -1,23 +0,0 @@ -Building the tap for both x86_64 and i386 requires an older version of the -Xcode tools than what now ships for Mavericks (10.9). The newer version -does not support creating i386 kernel images. - -At the moment this is done on an OSX 10.6 virtual image that is used for -building. (It doesn't have to be done often.) Then the kext is signed on -the regular build system. That's because images built on newer OSX don't -seem to load on 10.6 but 10.6 built kexts seem fine on 10.9. Go figure. - -Older Xcode can also be found at: - -https://developer.apple.com/downloads - -It requires a bit of a dance to unpack the package and obtain an unpacked -tree, but once it's there you can change the line in tap/Makefile and -build for both architectures. - -This will go on until i386 is thoroughly legacy, at which point we'll -probably start just supporting x86_64. But that might be a while. We want -to support old Macs through their entire useful life. - -Since this build is irritating, a pre-built copy is packaged in ext/ and -is installed by 'make install'. So users shouldn't have to build this. diff --git a/tests/http/2015-11-10_03_12500_ec2-east-only.out.xz b/tests/http/2015-11-10_03_12500_ec2-east-only.out.xz new file mode 100644 index 00000000..3ae3555e Binary files /dev/null and b/tests/http/2015-11-10_03_12500_ec2-east-only.out.xz differ -- cgit v1.2.3 From 3b9411044fbc86bf9f4a64e22a11d4f4be2a1814 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 10 Nov 2015 16:00:21 -0800 Subject: Patch tap-mac to latest tuntaposx upstream changes, and add updated build for 10.8 or later (keep old one for 10.7). --- .../com.zerotier.tap.kext/Contents/Info.plist | 36 +++++++ .../com.zerotier.tap.kext/Contents/MacOS/tap | Bin 0 -> 50496 bytes .../Contents/_CodeSignature/CodeResources | 105 +++++++++++++++++++++ ext/tap-mac/tuntap/Makefile | 89 ++++++++++++++++- ext/tap-mac/tuntap/src/lock.cc | 15 ++- ext/tap-mac/tuntap/src/tap/Makefile | 20 ++-- ext/tap-mac/tuntap/src/tap/tap.cc | 81 ++++++++++++++++ ext/tap-mac/tuntap/src/tap/tap.h | 14 ++- ext/tap-mac/tuntap/src/tuntap.cc | 21 ++--- ext/tap-mac/tuntap/src/tuntap.h | 2 +- 10 files changed, 349 insertions(+), 34 deletions(-) create mode 100644 ext/bin/tap-mac/com.zerotier.tap.kext/Contents/Info.plist create mode 100755 ext/bin/tap-mac/com.zerotier.tap.kext/Contents/MacOS/tap create mode 100644 ext/bin/tap-mac/com.zerotier.tap.kext/Contents/_CodeSignature/CodeResources (limited to 'ext') diff --git a/ext/bin/tap-mac/com.zerotier.tap.kext/Contents/Info.plist b/ext/bin/tap-mac/com.zerotier.tap.kext/Contents/Info.plist new file mode 100644 index 00000000..c20eefa5 --- /dev/null +++ b/ext/bin/tap-mac/com.zerotier.tap.kext/Contents/Info.plist @@ -0,0 +1,36 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + tap + CFBundleIdentifier + com.zerotier.tap + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + tap + CFBundlePackageType + KEXT + CFBundleShortVersionString + 20150118 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + OSBundleLibraries + + com.apple.kpi.mach + 8.0 + com.apple.kpi.bsd + 8.0 + com.apple.kpi.libkern + 8.0 + com.apple.kpi.unsupported + 8.0 + + + + diff --git a/ext/bin/tap-mac/com.zerotier.tap.kext/Contents/MacOS/tap b/ext/bin/tap-mac/com.zerotier.tap.kext/Contents/MacOS/tap new file mode 100755 index 00000000..48bf9625 Binary files /dev/null and b/ext/bin/tap-mac/com.zerotier.tap.kext/Contents/MacOS/tap differ diff --git a/ext/bin/tap-mac/com.zerotier.tap.kext/Contents/_CodeSignature/CodeResources b/ext/bin/tap-mac/com.zerotier.tap.kext/Contents/_CodeSignature/CodeResources new file mode 100644 index 00000000..0710b400 --- /dev/null +++ b/ext/bin/tap-mac/com.zerotier.tap.kext/Contents/_CodeSignature/CodeResources @@ -0,0 +1,105 @@ + + + + + files + + files2 + + rules + + ^Resources/ + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ + + nested + + weight + 10 + + ^.* + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^Resources/ + + weight + 20 + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^[^/]+$ + + nested + + weight + 10 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/ext/tap-mac/tuntap/Makefile b/ext/tap-mac/tuntap/Makefile index 8d79577e..53ab1a9d 100644 --- a/ext/tap-mac/tuntap/Makefile +++ b/ext/tap-mac/tuntap/Makefile @@ -1,12 +1,95 @@ -TUNTAP_VERSION = 20131028 +# Lets have a version, at last! +TUNTAP_VERSION = 20150118 + +# BASE install directory BASE= all: tap.kext +keysetup: + -security delete-keychain net.sf.tuntaposx.tmp + security create-keychain -p $$(head -c 32 /dev/urandom | hexdump -e '"%02x"') \ + net.sf.tuntaposx.tmp + security set-keychain-settings -lut 60 net.sf.tuntaposx.tmp + security import identity.p12 -k net.sf.tuntaposx.tmp -f pkcs12 \ + -P $$(read -sp 'identity passphrase: ' pw && echo "$$pw") -A + security find-identity -v net.sf.tuntaposx.tmp | \ + awk -F \" '$$2 ~ /^Developer ID Application:/ { print $$2 }' > .signing_identity + security find-identity -v net.sf.tuntaposx.tmp | \ + awk -F \" '$$2 ~ /^Developer ID Installer:/ { print $$2 }' > .installer_identity + +pkgbuild/%.pkg: %.kext + mkdir -p pkgbuild/$*_root/Library/Extensions + cp -pR $*.kext pkgbuild/$*_root/Library/Extensions + mkdir -p pkgbuild/$*_root/Library/LaunchDaemons + cp pkg/launchd/net.sf.tuntaposx.$*.plist pkgbuild/$*_root/Library/LaunchDaemons + pkgbuild --root pkgbuild/$*_root \ + --component-plist pkg/components/$*.plist \ + --scripts pkg/scripts/$* pkgbuild/$*.pkg + +tuntap_$(TUNTAP_VERSION).pkg: pkgbuild/tap.pkg pkgbuild/tun.pkg + productbuild --distribution pkg/distribution.xml --package-path pkgbuild \ + --resources pkg/res.dummy \ + tuntap_$(TUNTAP_VERSION).pkg ; \ + pkgutil --expand tuntap_$(TUNTAP_VERSION).pkg pkgbuild/tuntap_pkg.d + cp -pR pkg/res/ pkgbuild/tuntap_pkg.d/Resources + pkgutil --flatten pkgbuild/tuntap_pkg.d tuntap_$(TUNTAP_VERSION).pkg + if test -s ".installer_identity"; then \ + productsign --sign "$$(cat .installer_identity)" --keychain net.sf.tuntaposx.tmp \ + tuntap_$(TUNTAP_VERSION).pkg tuntap_$(TUNTAP_VERSION).pkg.signed ; \ + mv tuntap_$(TUNTAP_VERSION).pkg.signed tuntap_$(TUNTAP_VERSION).pkg ; \ + fi + +pkg: tuntap_$(TUNTAP_VERSION).pkg + tar czf tuntap_$(TUNTAP_VERSION).tar.gz \ + README.installer README tuntap_$(TUNTAP_VERSION).pkg + +# Install targets +# They are provided for the gentoo ebuild, but should work just fine for other people as well. +install_%_kext: %.kext + mkdir -p $(BASE)/Library/Extensions + cp -pR $*.kext $(BASE)/Library/Extensions/ + chown -R root:wheel $(BASE)/Library/Extensions/$*.kext + mkdir -p $(BASE)/Library/LaunchDaemons + cp pkg/launchd/net.sf.tuntaposx.$*.plist $(BASE)/Library/LaunchDaemons + chown -R root:wheel $(BASE)/Library/LaunchDaemons/net.sf.tuntaposx.$*.plist + +install: install_tap_kext install_tun_kext + +tarball: clean + touch tuntap_$(TUNTAP_VERSION)_src.tar.gz + tar czf tuntap_$(TUNTAP_VERSION)_src.tar.gz \ + -C .. \ + --exclude "tuntap/identity.p12" \ + --exclude "tuntap/tuntap_$(TUNTAP_VERSION)_src.tar.gz" \ + --exclude "tuntap/tuntap_$(TUNTAP_VERSION).tar.gz" \ + --exclude "tuntap/tuntap_$(TUNTAP_VERSION).pkg" \ + --exclude "*/.*" \ + tuntap + clean: cd src/tap && make -f Makefile clean + cd src/tun && make -f Makefile clean + -rm -rf pkgbuild + -rm -rf tuntap_$(TUNTAP_VERSION).pkg + -rm -f tuntap_$(TUNTAP_VERSION).tar.gz + -rm -f tuntap_$(TUNTAP_VERSION)_src.tar.gz + +%.kext: + cd src/$* && make TUNTAP_VERSION=$(TUNTAP_VERSION) -f Makefile all + if test -s ".signing_identity"; then \ + codesign -fv --keychain net.sf.tuntaposx.tmp -s "$$(cat .signing_identity)" \ + $*.kext ; \ + fi -tap.kext: - cd src/tap && make TUNTAP_VERSION=$(TUNTAP_VERSION) -f Makefile all +test: + # configd messes with interface flags, issuing SIOCSIFFLAGS ioctls upon receiving kernel + # events indicating protocols have been attached and detached. Unfortunately, configd does + # this asynchronously, making the SIOCSIFFLAGS changes totally unpredictable when we bring + # our interfaces up and down in rapid succession during our tests. I haven't found a good + # way to suppress or handle this mess other than disabling configd temporarily. + killall -STOP configd + -PYTHONPATH=test python test/tuntap/tuntap_tests.py --tests='$(TESTS)' + killall -CONT configd .PHONY: test diff --git a/ext/tap-mac/tuntap/src/lock.cc b/ext/tap-mac/tuntap/src/lock.cc index 0da48be2..9c78783a 100644 --- a/ext/tap-mac/tuntap/src/lock.cc +++ b/ext/tap-mac/tuntap/src/lock.cc @@ -31,6 +31,8 @@ extern "C" { +#include + #include #include @@ -120,10 +122,13 @@ tt_mutex::sleep(void *cond) } void -tt_mutex::sleep(void *cond, uint64_t timeout) +tt_mutex::sleep(void *cond, uint64_t nanoseconds) { - if (lck != NULL) - lck_rw_sleep_deadline(lck, LCK_SLEEP_DEFAULT, cond, THREAD_INTERRUPTIBLE, timeout); + if (lck != NULL) { + uint64_t abstime; + nanoseconds_to_absolutetime(nanoseconds, &abstime); + lck_rw_sleep_deadline(lck, LCK_SLEEP_DEFAULT, cond, THREAD_INTERRUPTIBLE, abstime); + } } void @@ -188,9 +193,9 @@ tt_gate::sleep(void* cond) } void -tt_gate::sleep(void* cond, uint64_t timeout) +tt_gate::sleep(void* cond, uint64_t nanoseconds) { - slock.sleep(cond, timeout); + slock.sleep(cond, nanoseconds); } void diff --git a/ext/tap-mac/tuntap/src/tap/Makefile b/ext/tap-mac/tuntap/src/tap/Makefile index ee1f5457..306a86d7 100644 --- a/ext/tap-mac/tuntap/src/tap/Makefile +++ b/ext/tap-mac/tuntap/src/tap/Makefile @@ -19,18 +19,18 @@ BUNDLE_SIGNATURE = ???? BUNDLE_PACKAGETYPE = KEXT BUNDLE_VERSION = $(TAP_KEXT_VERSION) -INCLUDE = -I.. -I/System/Library/Frameworks/Kernel.framework/Headers -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/System/Library/Frameworks/Kernel.framework/Headers -CFLAGS = -Wall -mkernel -force_cpusubtype_ALL \ - -fno-builtin -fno-stack-protector -arch i386 -arch x86_64 \ - -DKERNEL -D__APPLE__ -DKERNEL_PRIVATE -DTUNTAP_VERSION=\"$(TUNTAP_VERSION)\" \ +INCLUDE = -I.. -I/System/Library/Frameworks/Kernel.framework/Headers +CFLAGS = -Wall -Werror -mkernel -force_cpusubtype_ALL \ + -nostdinc -fno-builtin -fno-stack-protector -msoft-float -fno-common \ + -arch x86_64 \ + -DKERNEL -DAPPLE -DKERNEL_PRIVATE -DTUNTAP_VERSION=\"$(TUNTAP_VERSION)\" \ -DTAP_KEXT_VERSION=\"$(TAP_KEXT_VERSION)\" CCFLAGS = $(CFLAGS) -LDFLAGS = -Wall -mkernel -nostdlib -r -lcc_kext -arch i386 -arch x86_64 -Xlinker -kext +LDFLAGS = -Wall -Werror -arch x86_64 -Xlinker -kext -nostdlib -lkmodc++ -lkmod -lcc_kext -#CCP = g++ -#CC = gcc -CCP = ../../../../llvm-g++-Xcode4.6.2/bin/llvm-g++ -CC = ../../../../llvm-g++-Xcode4.6.2/bin/llvm-gcc +CCP = clang -x c++ +CC = clang -x c +LD = clang all: $(KMOD_BIN) bundle @@ -40,7 +40,7 @@ all: $(KMOD_BIN) bundle $(CCP) $(CCFLAGS) $(INCLUDE) -c $< -o $@ $(KMOD_BIN): $(OBJS) - $(CCP) $(LDFLAGS) -o $(KMOD_BIN) $(OBJS) + $(LD) $(LDFLAGS) -o $(KMOD_BIN) $(OBJS) bundle: $(KMOD_BIN) rm -rf $(BUNDLE_DIR)/$(BUNDLE_NAME) diff --git a/ext/tap-mac/tuntap/src/tap/tap.cc b/ext/tap-mac/tuntap/src/tap/tap.cc index 149f1e71..b348a85e 100644 --- a/ext/tap-mac/tuntap/src/tap/tap.cc +++ b/ext/tap-mac/tuntap/src/tap/tap.cc @@ -38,6 +38,8 @@ extern "C" { #include #include +#include + #include #include #include @@ -89,10 +91,25 @@ struct ifmediareq32 { #define SIOCGIFMEDIA32 _IOWR('i', 56, struct ifmediareq32) /* get net media */ #define SIOCGIFMEDIA64 _IOWR('i', 56, struct ifmediareq64) /* get net media (64-bit) */ +/* thread_policy_set is exported in Mach.kext, but commented in mach/thread_policy.h in the + * Kernel.Framework headers (why?). Add a local declaration to work around that. + */ +extern "C" { +kern_return_t thread_policy_set( + thread_t thread, + thread_policy_flavor_t flavor, + thread_policy_t policy_info, + mach_msg_type_number_t count); +} static unsigned char ETHER_BROADCAST_ADDR[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; /* members */ +tap_interface::tap_interface() { + bzero(attached_protos, sizeof(attached_protos)); + input_thread = THREAD_NULL; +} + bool tap_interface::initialize(unsigned short major, unsigned short unit) { @@ -166,6 +183,30 @@ tap_interface::initialize_interface() */ bpfattach(ifp, DLT_EN10MB, ifnet_hdrlen(ifp)); + /* Inject an empty packet to trigger the input thread calling demux(), which will unblock + * thread_sync_lock. This is part of a hack to avoid a kernel crash on re-attaching + * interfaces, see comment in shutdown_interface for more information. + */ + mbuf_t empty_mbuf; + mbuf_gethdr(MBUF_WAITOK, MBUF_TYPE_DATA, &empty_mbuf); + if (empty_mbuf != NULL) { + mbuf_pkthdr_setrcvif(empty_mbuf, ifp); + mbuf_pkthdr_setlen(empty_mbuf, 0); + mbuf_pkthdr_setheader(empty_mbuf, mbuf_data(empty_mbuf)); + mbuf_set_csum_performed(empty_mbuf, 0, 0); + if (ifnet_input(ifp, empty_mbuf, NULL) == 0) { + auto_lock l(&thread_sync_lock); + for (int i = 0; i < 100 && input_thread == THREAD_NULL; ++i) { + dprintf("input thread not found, waiting...\n"); + thread_sync_lock.sleep(&input_thread, 10000000); + } + } else { + mbuf_freem(empty_mbuf); + } + } + if (input_thread == THREAD_NULL) + dprintf("Failed to determine input thread!\n"); + return 0; } @@ -186,6 +227,36 @@ tap_interface::shutdown_interface() cleanup_interface(); unregister_interface(); + + /* There's a race condition in the kernel that may cause crashes when quickly re-attaching + * interfaces. The crash happens when the interface gets re-attached before the input thread + * for the interface managed to terminate, in which case an assert on the input_waiting flag + * to be clear triggers in ifnet_attach. The bug is really that there's no synchronization + * for terminating the input thread. To work around this, the following code does add the + * missing synchronization to wait for the input thread to terminate. Of course, threading + * primitives available to kexts are few, and I'm not aware of a way to wait for a thread to + * terminate. Hence, the code calls thread_policy_set (passing bogus parameters) in a loop, + * until it returns KERN_TERMINATED. Since this is all rather fragile, there's an upper + * limit on the loop iteratations we're willing to make, so this terminates eventually even + * if things change on the kernel side eventually. + */ + if (input_thread != THREAD_NULL) { + dprintf("Waiting for input thread...\n"); + kern_return_t result = 0; + for (int i = 0; i < 100; ++i) { + result = thread_policy_set(input_thread, -1, NULL, 0); + dprintf("thread_policy_set result: %d\n", result); + if (result == KERN_TERMINATED) { + dprintf("Input thread terminated.\n"); + thread_deallocate(input_thread); + input_thread = THREAD_NULL; + break; + } + + auto_lock l(&thread_sync_lock); + thread_sync_lock.sleep(&input_thread, 10000000); + } + } } errno_t @@ -263,6 +334,16 @@ tap_interface::if_demux(mbuf_t m, char *header, protocol_family_t *proto) dprintf("tap: if_demux\n"); + /* Make note of what input thread this interface is running on. This is part of a hack to + * avoid a crash on re-attaching interfaces, see comment in shutdown_interface for details. + */ + if (input_thread == THREAD_NULL) { + auto_lock l(&thread_sync_lock); + input_thread = current_thread(); + thread_reference(input_thread); + thread_sync_lock.wakeup(&input_thread); + } + /* size check */ if (mbuf_len(m) < sizeof(struct ether_header)) return ENOENT; diff --git a/ext/tap-mac/tuntap/src/tap/tap.h b/ext/tap-mac/tuntap/src/tap/tap.h index 72339a95..a5164d4a 100644 --- a/ext/tap-mac/tuntap/src/tap/tap.h +++ b/ext/tap-mac/tuntap/src/tap/tap.h @@ -30,12 +30,15 @@ #include "tuntap.h" -#define TAP_FAMILY_NAME ((char *) "zt") +extern "C" { -#define TAP_IF_COUNT 32 /* max number of tap interfaces */ +#include -#define TAP_MTU 2800 +} +#define TAP_FAMILY_NAME ((char *) "zt") +#define TAP_IF_COUNT 32 /* max number of tap interfaces */ +#define TAP_MTU 2800 #define TAP_LLADDR tap_lladdr /* the mac address of our interfaces. note that the last byte will be replaced by the unit number */ @@ -52,6 +55,8 @@ class tap_manager : public tuntap_manager { /* the tap network interface */ class tap_interface : public tuntap_interface { + public: + tap_interface(); protected: /* maximum number of protocols that can be attached */ @@ -67,6 +72,9 @@ class tap_interface : public tuntap_interface { protocol_family_t proto; } attached_protos[MAX_ATTACHED_PROTOS]; + /* The input thread for the network interface. */ + thread_t input_thread; + /* initializes the interface */ virtual bool initialize(unsigned short major, unsigned short unit); diff --git a/ext/tap-mac/tuntap/src/tuntap.cc b/ext/tap-mac/tuntap/src/tuntap.cc index 7fdbb795..d0f89018 100644 --- a/ext/tap-mac/tuntap/src/tuntap.cc +++ b/ext/tap-mac/tuntap/src/tuntap.cc @@ -384,10 +384,10 @@ tuntap_interface::unregister_interface() dprintf("interface detaching\n"); /* Wait until the interface has completely been detached. */ - detach_lock.lock(); + thread_sync_lock.lock(); while (!interface_detached) - detach_lock.sleep(&interface_detached); - detach_lock.unlock(); + thread_sync_lock.sleep(&interface_detached); + thread_sync_lock.unlock(); dprintf("interface detached\n"); @@ -642,15 +642,14 @@ tuntap_interface::cdev_write(uio_t uio, int ioflag) unsigned int mlen = mbuf_maxlen(first); unsigned int chunk_len; unsigned int copied = 0; + unsigned int max_data_len = ifnet_mtu(ifp) + ifnet_hdrlen(ifp); int error; /* stuff the data into the mbuf(s) */ mb = first; while (uio_resid(uio) > 0) { /* copy a chunk. enforce mtu (don't know if this is correct behaviour) */ - // ... evidently not :) -- Adam Ierymenko - //chunk_len = min(ifnet_mtu(ifp), min(uio_resid(uio), mlen)); - chunk_len = min(uio_resid(uio),mlen); + chunk_len = min(max_data_len - copied, min(uio_resid(uio), mlen)); error = uiomove((caddr_t) mbuf_data(mb), chunk_len, uio); if (error) { log(LOG_ERR, "tuntap: could not copy data from userspace: %d\n", error); @@ -666,9 +665,7 @@ tuntap_interface::cdev_write(uio_t uio, int ioflag) copied += chunk_len; /* if done, break the loop */ - //if (uio_resid(uio) <= 0 || copied >= ifnet_mtu(ifp)) - // break; - if (uio_resid(uio) <= 0) + if (uio_resid(uio) <= 0 || copied >= max_data_len) break; /* allocate a new mbuf if the current is filled */ @@ -956,10 +953,10 @@ tuntap_interface::if_detached() dprintf("tuntap: if_detached\n"); /* wake unregister_interface() */ - detach_lock.lock(); + thread_sync_lock.lock(); interface_detached = true; - detach_lock.wakeup(&interface_detached); - detach_lock.unlock(); + thread_sync_lock.wakeup(&interface_detached); + thread_sync_lock.unlock(); dprintf("if_detached done\n"); } diff --git a/ext/tap-mac/tuntap/src/tuntap.h b/ext/tap-mac/tuntap/src/tuntap.h index f10d4a06..d5f398d0 100644 --- a/ext/tap-mac/tuntap/src/tuntap.h +++ b/ext/tap-mac/tuntap/src/tuntap.h @@ -197,7 +197,7 @@ class tuntap_interface { /* synchronization */ tt_mutex lock; tt_mutex bpf_lock; - tt_mutex detach_lock; + tt_mutex thread_sync_lock; /* the interface structure registered */ ifnet_t ifp; -- cgit v1.2.3 From bacb53fe8fdfa1ecd429cdfb07de96ec0fb0589b Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 12 Nov 2015 16:40:50 -0800 Subject: Remove old Windows NDIS5 tap driver -- I think this is dead. --- ext/installfiles/windows/ZeroTier One.aip | 8 +- windows/TapDriver/TapDriver.vcxproj | 385 ----- windows/TapDriver/TapDriver.vcxproj.filters | 75 - windows/TapDriver/config.h | 12 - windows/TapDriver/constants.h | 51 - windows/TapDriver/endian.h | 35 - windows/TapDriver/error.c | 387 ----- windows/TapDriver/error.h | 88 -- windows/TapDriver/instance.c | 241 --- windows/TapDriver/lock.h | 75 - windows/TapDriver/macinfo.c | 154 -- windows/TapDriver/macinfo.h | 38 - windows/TapDriver/mem.c | 186 --- windows/TapDriver/proto.h | 60 - windows/TapDriver/prototypes.h | 163 -- windows/TapDriver/tap-windows.h | 69 - windows/TapDriver/tapdrvr.c | 2183 --------------------------- windows/TapDriver/types.h | 137 -- windows/TapDriver/zttap200.inf | 78 - windows/ZeroTierOne.sln | 105 -- 20 files changed, 4 insertions(+), 4526 deletions(-) delete mode 100644 windows/TapDriver/TapDriver.vcxproj delete mode 100644 windows/TapDriver/TapDriver.vcxproj.filters delete mode 100644 windows/TapDriver/config.h delete mode 100644 windows/TapDriver/constants.h delete mode 100644 windows/TapDriver/endian.h delete mode 100644 windows/TapDriver/error.c delete mode 100644 windows/TapDriver/error.h delete mode 100644 windows/TapDriver/instance.c delete mode 100644 windows/TapDriver/lock.h delete mode 100644 windows/TapDriver/macinfo.c delete mode 100644 windows/TapDriver/macinfo.h delete mode 100644 windows/TapDriver/mem.c delete mode 100644 windows/TapDriver/proto.h delete mode 100644 windows/TapDriver/prototypes.h delete mode 100644 windows/TapDriver/tap-windows.h delete mode 100644 windows/TapDriver/tapdrvr.c delete mode 100644 windows/TapDriver/types.h delete mode 100644 windows/TapDriver/zttap200.inf (limited to 'ext') diff --git a/ext/installfiles/windows/ZeroTier One.aip b/ext/installfiles/windows/ZeroTier One.aip index 236e2559..8732e9f3 100644 --- a/ext/installfiles/windows/ZeroTier One.aip +++ b/ext/installfiles/windows/ZeroTier One.aip @@ -23,10 +23,10 @@ - + - + @@ -56,7 +56,7 @@ - + @@ -328,7 +328,7 @@ - + diff --git a/windows/TapDriver/TapDriver.vcxproj b/windows/TapDriver/TapDriver.vcxproj deleted file mode 100644 index 787cc68f..00000000 --- a/windows/TapDriver/TapDriver.vcxproj +++ /dev/null @@ -1,385 +0,0 @@ - - - - - Win8 Debug - Win32 - - - Win8 Release - Win32 - - - Win7 Debug - Win32 - - - Win7 Release - Win32 - - - Vista Debug - Win32 - - - Vista Release - Win32 - - - Win8 Debug - x64 - - - Win8 Release - x64 - - - Win7 Debug - x64 - - - Win7 Release - x64 - - - Vista Debug - x64 - - - Vista Release - x64 - - - - {689210B1-467C-4850-BB7D-2E10D5B4A3DA} - {1bc93793-694f-48fe-9372-81e2b05556fd} - v4.5 - 11.0 - Win8 Debug - Win32 - - - TapDriver - $(VCTargetsPath11) - - - WindowsKernelModeDriver8.0 - Driver - KMDF - - - - Windows8 - true - - - Windows8 - false - - - Windows7 - true - - - Windows7 - false - - - Vista - true - - - Vista - false - - - Windows8 - true - - - Windows8 - false - - - Windows7 - true - - - Windows7 - false - - - Vista - true - - - Vista - false - - - - - - - - - - zttap200 - $(SolutionDir)\Build\$(Platform)\$(ConfigurationName)\ - $(Platform)\$(ConfigurationName)\ - http://timestamp.digicert.com/ - - - DbgengKernelDebugger - - - zttap200 - $(SolutionDir)\Build\$(Platform)\$(ConfigurationName)\ - $(Platform)\$(ConfigurationName)\ - http://timestamp.digicert.com/ - - - zttap200 - $(SolutionDir)\Build\$(Platform)\$(ConfigurationName)\ - $(Platform)\$(ConfigurationName)\ - http://timestamp.digicert.com/ - - - zttap200 - $(SolutionDir)\Build\$(Platform)\$(ConfigurationName)\ - $(Platform)\$(ConfigurationName)\ - http://timestamp.digicert.com/ - - - zttap200 - $(SolutionDir)\Build\$(Platform)\$(ConfigurationName)\ - $(Platform)\$(ConfigurationName)\ - http://timestamp.digicert.com/ - - - zttap200 - $(SolutionDir)\Build\$(Platform)\$(ConfigurationName)\ - $(Platform)\$(ConfigurationName)\ - http://timestamp.digicert.com/ - - - zttap200 - $(SolutionDir)\Build\$(Platform)\$(ConfigurationName)\ - - - true - - - zttap200 - $(SolutionDir)\Build\$(Platform)\$(ConfigurationName)\ - - - true - - - zttap200 - $(SolutionDir)\Build\$(Platform)\$(ConfigurationName)\ - - - true - - - zttap200 - $(SolutionDir)\Build\$(Platform)\$(ConfigurationName)\ - - - true - - - zttap200 - $(SolutionDir)\Build\$(Platform)\$(ConfigurationName)\ - - - true - - - zttap200 - $(SolutionDir)\Build\$(Platform)\$(ConfigurationName)\ - - - true - - - - false - trace.h - true - Level2 - false - None - None - None - Level2 - false - Level2 - false - Level2 - false - Level2 - false - Level2 - false - Level2 - false - Level2 - false - Level2 - false - Level2 - false - Level2 - false - Level2 - false - None - None - None - - - C:\WinDDK\7600.16385.1\lib\wnet\i386\ndis.lib;C:\WinDDK\7600.16385.1\lib\wnet\i386\ntstrsafe.lib;%(AdditionalDependencies) - - - C:\WinDDK\7600.16385.1\lib\wnet\i386\ndis.lib;C:\WinDDK\7600.16385.1\lib\wnet\i386\ntstrsafe.lib;%(AdditionalDependencies) - - - C:\WinDDK\7600.16385.1\lib\wnet\i386\ndis.lib;C:\WinDDK\7600.16385.1\lib\wnet\i386\ntstrsafe.lib;%(AdditionalDependencies) - - - C:\WinDDK\7600.16385.1\lib\wnet\i386\ndis.lib;C:\WinDDK\7600.16385.1\lib\wnet\i386\ntstrsafe.lib;%(AdditionalDependencies) - - - C:\WinDDK\7600.16385.1\lib\wnet\i386\ndis.lib;C:\WinDDK\7600.16385.1\lib\wnet\i386\ntstrsafe.lib;%(AdditionalDependencies) - - - C:\WinDDK\7600.16385.1\lib\wnet\i386\ndis.lib;C:\WinDDK\7600.16385.1\lib\wnet\i386\ntstrsafe.lib;%(AdditionalDependencies) - - - C:\WinDDK\7600.16385.1\lib\wnet\amd64\ndis.lib;C:\WinDDK\7600.16385.1\lib\wnet\amd64\ntstrsafe.lib;%(AdditionalDependencies) - - - C:\WinDDK\7600.16385.1\lib\wnet\amd64\ndis.lib;C:\WinDDK\7600.16385.1\lib\wnet\amd64\ntstrsafe.lib;%(AdditionalDependencies) - - - C:\WinDDK\7600.16385.1\lib\wnet\amd64\ndis.lib;C:\WinDDK\7600.16385.1\lib\wnet\amd64\ntstrsafe.lib;%(AdditionalDependencies) - - - C:\WinDDK\7600.16385.1\lib\wnet\amd64\ndis.lib;C:\WinDDK\7600.16385.1\lib\wnet\amd64\ntstrsafe.lib;%(AdditionalDependencies) - - - C:\WinDDK\7600.16385.1\lib\wnet\amd64\ndis.lib;C:\WinDDK\7600.16385.1\lib\wnet\amd64\ntstrsafe.lib;%(AdditionalDependencies) - - - C:\WinDDK\7600.16385.1\lib\wnet\amd64\ndis.lib;C:\WinDDK\7600.16385.1\lib\wnet\amd64\ntstrsafe.lib;%(AdditionalDependencies) - - - SHA1 - /t "http://timestamp.digicert.com/" /d "ZeroTier One Virtual Network Port" /sha1 5809bb3255b4f32dd93619c1cf26a7df6c282a89 - - - SHA1 - /t "http://timestamp.digicert.com/" /d "ZeroTier One Virtual Network Port" /sha1 5809bb3255b4f32dd93619c1cf26a7df6c282a89 - - - SHA1 - /t "http://timestamp.digicert.com/" /d "ZeroTier One Virtual Network Port" /sha1 5809bb3255b4f32dd93619c1cf26a7df6c282a89 - - - SHA1 - /t "http://timestamp.digicert.com/" /d "ZeroTier One Virtual Network Port" /sha1 5809bb3255b4f32dd93619c1cf26a7df6c282a89 - - - SHA1 - /t "http://timestamp.digicert.com/" /d "ZeroTier One Virtual Network Port" /sha1 5809bb3255b4f32dd93619c1cf26a7df6c282a89 - - - SHA1 - /t "http://timestamp.digicert.com/" /d "ZeroTier One Virtual Network Port" /sha1 5809bb3255b4f32dd93619c1cf26a7df6c282a89 - - - - - - - - - - - - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/windows/TapDriver/TapDriver.vcxproj.filters b/windows/TapDriver/TapDriver.vcxproj.filters deleted file mode 100644 index 570ea727..00000000 --- a/windows/TapDriver/TapDriver.vcxproj.filters +++ /dev/null @@ -1,75 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - {8E41214B-6785-4CFE-B992-037D68949A14} - inf;inv;inx;mof;mc; - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Driver Files - - - \ No newline at end of file diff --git a/windows/TapDriver/config.h b/windows/TapDriver/config.h deleted file mode 100644 index 28bd73f6..00000000 --- a/windows/TapDriver/config.h +++ /dev/null @@ -1,12 +0,0 @@ -#define PRODUCT_NAME "ZeroTier One Virtual Network Port" -#define PRODUCT_VERSION "2.0.0" -#define PRODUCT_VERSION_RESOURCE 2,0,0,1 -#define PRODUCT_TAP_WIN_COMPONENT_ID "zttap200" -#define PRODUCT_TAP_WIN_MAJOR 2 -#define PRODUCT_TAP_WIN_MINOR 0 -#define PRODUCT_TAP_WIN_PROVIDER "ZeroTier Networks" -#define PRODUCT_TAP_WIN_DEVICE_DESCRIPTION PRODUCT_NAME -#define PRODUCT_TAP_WIN_RELDATE "01/22/2014" - -#define TAP_DRIVER_MAJOR_VERSION PRODUCT_TAP_WIN_MAJOR -#define TAP_DRIVER_MINOR_VERSION PRODUCT_TAP_WIN_MINOR diff --git a/windows/TapDriver/constants.h b/windows/TapDriver/constants.h deleted file mode 100644 index 78174d25..00000000 --- a/windows/TapDriver/constants.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * TAP-Windows -- A kernel driver to provide virtual tap - * device functionality on Windows. - * - * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. - * - * This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., - * and is released under the GPL version 2 (see below). - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program (see the file COPYING included with this - * distribution); if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -//==================================================================== -// Product and Version public settings -//==================================================================== - -#define PRODUCT_STRING PRODUCT_TAP_DEVICE_DESCRIPTION - -#define TAP_NDIS_MAJOR_VERSION 5 -#define TAP_NDIS_MINOR_VERSION 0 - -//=========================================================== -// Driver constants -//=========================================================== - -#define ETHERNET_HEADER_SIZE (sizeof (ETH_HEADER)) -#define ETHERNET_MTU 2800 // ZeroTier One MTU -#define ETHERNET_PACKET_SIZE (ETHERNET_MTU + ETHERNET_HEADER_SIZE) -#define DEFAULT_PACKET_LOOKAHEAD (ETHERNET_PACKET_SIZE) - -#define NIC_MAX_MCAST_LIST 128 // Max length of multicast address list - -#define MINIMUM_MTU 576 // USE TCP Minimum MTU -#define MAXIMUM_MTU 65536 // IP maximum MTU - -#define PACKET_QUEUE_SIZE 64 // tap -> userspace queue size -#define IRP_QUEUE_SIZE 16 // max number of simultaneous i/o operations from userspace - -#define TAP_LITTLE_ENDIAN // affects ntohs, htonl, etc. functions diff --git a/windows/TapDriver/endian.h b/windows/TapDriver/endian.h deleted file mode 100644 index 0f7025d5..00000000 --- a/windows/TapDriver/endian.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * TAP-Windows -- A kernel driver to provide virtual tap - * device functionality on Windows. - * - * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. - * - * This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., - * and is released under the GPL version 2 (see below). - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program (see the file COPYING included with this - * distribution); if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef TAP_LITTLE_ENDIAN -#define ntohs(x) RtlUshortByteSwap(x) -#define htons(x) RtlUshortByteSwap(x) -#define ntohl(x) RtlUlongByteSwap(x) -#define htonl(x) RtlUlongByteSwap(x) -#else -#define ntohs(x) ((USHORT)(x)) -#define htons(x) ((USHORT)(x)) -#define ntohl(x) ((ULONG)(x)) -#define htonl(x) ((ULONG)(x)) -#endif diff --git a/windows/TapDriver/error.c b/windows/TapDriver/error.c deleted file mode 100644 index 81ef50d1..00000000 --- a/windows/TapDriver/error.c +++ /dev/null @@ -1,387 +0,0 @@ -/* -* TAP-Windows -- A kernel driver to provide virtual tap -* device functionality on Windows. -* -* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. -* -* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., -* and is released under the GPL version 2 (see below). -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 2 -* as published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program (see the file COPYING included with this -* distribution); if not, write to the Free Software Foundation, Inc., -* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -//----------------- -// DEBUGGING OUTPUT -//----------------- - -const char *g_LastErrorFilename; -int g_LastErrorLineNumber; - -#if DBG - -DebugOutput g_Debug; - -BOOLEAN - NewlineExists (const char *str, int len) -{ - while (len-- > 0) - { - const char c = *str++; - if (c == '\n') - return TRUE; - else if (c == '\0') - break; - } - return FALSE; -} - -VOID - MyDebugInit (unsigned int bufsiz) -{ - NdisZeroMemory (&g_Debug, sizeof (g_Debug)); - g_Debug.text = (char *) MemAlloc (bufsiz, FALSE); - if (g_Debug.text) - g_Debug.capacity = bufsiz; -} - -VOID - MyDebugFree () -{ - if (g_Debug.text) - MemFree (g_Debug.text, g_Debug.capacity); - NdisZeroMemory (&g_Debug, sizeof (g_Debug)); -} - -VOID - MyDebugPrint (const unsigned char* format, ...) -{ - if (g_Debug.text && g_Debug.capacity > 0 && CAN_WE_PRINT) - { - BOOLEAN owned; - ACQUIRE_MUTEX_ADAPTIVE (&g_Debug.lock, owned); - if (owned) - { - const int remaining = (int)g_Debug.capacity - (int)g_Debug.out; - - if (remaining > 0) - { - va_list args; - NTSTATUS status; - char *end; - -#ifdef DBG_PRINT - va_start (args, format); - vDbgPrintEx (DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, format, args); - va_end (args); -#endif - va_start (args, format); - status = RtlStringCchVPrintfExA (g_Debug.text + g_Debug.out, - remaining, - &end, - NULL, - STRSAFE_NO_TRUNCATION | STRSAFE_IGNORE_NULLS, - format, - args); - va_end (args); - va_start (args, format); - vDbgPrintEx(DPFLTR_IHVDRIVER_ID , 1, format, args); - va_end (args); - if (status == STATUS_SUCCESS) - g_Debug.out = (unsigned int) (end - g_Debug.text); - else - g_Debug.error = TRUE; - } - else - g_Debug.error = TRUE; - - RELEASE_MUTEX (&g_Debug.lock); - } - else - g_Debug.error = TRUE; - } -} - -BOOLEAN - GetDebugLine (char *buf, const int len) -{ - static const char *truncated = "[OUTPUT TRUNCATED]\n"; - BOOLEAN ret = FALSE; - - NdisZeroMemory (buf, len); - - if (g_Debug.text && g_Debug.capacity > 0) - { - BOOLEAN owned; - ACQUIRE_MUTEX_ADAPTIVE (&g_Debug.lock, owned); - if (owned) - { - int i = 0; - - if (g_Debug.error || NewlineExists (g_Debug.text + g_Debug.in, (int)g_Debug.out - (int)g_Debug.in)) - { - while (i < (len - 1) && g_Debug.in < g_Debug.out) - { - const char c = g_Debug.text[g_Debug.in++]; - if (c == '\n') - break; - buf[i++] = c; - } - if (i < len) - buf[i] = '\0'; - } - - if (!i) - { - if (g_Debug.in == g_Debug.out) - { - g_Debug.in = g_Debug.out = 0; - if (g_Debug.error) - { - const unsigned int tlen = strlen (truncated); - if (tlen < g_Debug.capacity) - { - NdisMoveMemory (g_Debug.text, truncated, tlen+1); - g_Debug.out = tlen; - } - g_Debug.error = FALSE; - } - } - } - else - ret = TRUE; - - RELEASE_MUTEX (&g_Debug.lock); - } - } - return ret; -} - -VOID - MyAssert (const unsigned char *file, int line) -{ - DEBUGP (("MYASSERT failed %s/%d\n", file, line)); - KeBugCheckEx (0x0F00BABA, - (ULONG_PTR) line, - (ULONG_PTR) 0, - (ULONG_PTR) 0, - (ULONG_PTR) 0); -} - -VOID - PrMac (const MACADDR mac) -{ - DEBUGP (("%x:%x:%x:%x:%x:%x", - mac[0], mac[1], mac[2], - mac[3], mac[4], mac[5])); -} - -VOID - PrIP (IPADDR ip_addr) -{ - const unsigned char *ip = (const unsigned char *) &ip_addr; - - DEBUGP (("%d.%d.%d.%d", - ip[0], ip[1], ip[2], ip[3])); -} - -const char * - PrIPProto (int proto) -{ - switch (proto) - { - case IPPROTO_UDP: - return "UDP"; - case IPPROTO_TCP: - return "TCP"; - case IPPROTO_ICMP: - return "ICMP"; - case IPPROTO_IGMP: - return "IGMP"; - default: - return "???"; - } -} - -VOID - DumpARP (const char *prefix, const ARP_PACKET *arp) -{ - DEBUGP (("%s ARP src=", prefix)); - PrMac (arp->m_MAC_Source); - DEBUGP ((" dest=")); - PrMac (arp->m_MAC_Destination); - DEBUGP ((" OP=0x%04x", - (int)ntohs(arp->m_ARP_Operation))); - DEBUGP ((" M=0x%04x(%d)", - (int)ntohs(arp->m_MAC_AddressType), - (int)arp->m_MAC_AddressSize)); - DEBUGP ((" P=0x%04x(%d)", - (int)ntohs(arp->m_PROTO_AddressType), - (int)arp->m_PROTO_AddressSize)); - - DEBUGP ((" MacSrc=")); - PrMac (arp->m_ARP_MAC_Source); - DEBUGP ((" MacDest=")); - PrMac (arp->m_ARP_MAC_Destination); - - DEBUGP ((" IPSrc=")); - PrIP (arp->m_ARP_IP_Source); - DEBUGP ((" IPDest=")); - PrIP (arp->m_ARP_IP_Destination); - - DEBUGP (("\n")); -} - -struct ethpayload { - ETH_HEADER eth; - UCHAR payload[DEFAULT_PACKET_LOOKAHEAD]; -}; - -VOID - DumpPacket2 (const char *prefix, - const ETH_HEADER *eth, - const unsigned char *data, - unsigned int len) -{ - struct ethpayload *ep = (struct ethpayload *) MemAlloc (sizeof (struct ethpayload), TRUE); - if (ep) - { - if (len > DEFAULT_PACKET_LOOKAHEAD) - len = DEFAULT_PACKET_LOOKAHEAD; - ep->eth = *eth; - NdisMoveMemory (ep->payload, data, len); - DumpPacket (prefix, (unsigned char *) ep, sizeof (ETH_HEADER) + len); - MemFree (ep, sizeof (struct ethpayload)); - } -} - -VOID - DumpPacket (const char *prefix, - const unsigned char *data, - unsigned int len) -{ - const ETH_HEADER *eth = (const ETH_HEADER *) data; - const IPHDR *ip = (const IPHDR *) (data + sizeof (ETH_HEADER)); - - if (len < sizeof (ETH_HEADER)) - { - DEBUGP (("%s TRUNCATED PACKET LEN=%d\n", prefix, len)); - return; - } - - // ARP Packet? - if (len >= sizeof (ARP_PACKET) && eth->proto == htons (ETH_P_ARP)) - { - DumpARP (prefix, (const ARP_PACKET *) data); - return; - } - - // IPv4 packet? - if (len >= (sizeof (IPHDR) + sizeof (ETH_HEADER)) - && eth->proto == htons (ETH_P_IP) - && IPH_GET_VER (ip->version_len) == 4) - { - const int hlen = IPH_GET_LEN (ip->version_len); - const int blen = len - sizeof (ETH_HEADER); - BOOLEAN did = FALSE; - - DEBUGP (("%s IPv4 %s[%d]", prefix, PrIPProto (ip->protocol), len)); - - if (!(ntohs (ip->tot_len) == blen && hlen <= blen)) - { - DEBUGP ((" XXX")); - return; - } - - // TCP packet? - if (ip->protocol == IPPROTO_TCP - && blen - hlen >= (sizeof (TCPHDR))) - { - const TCPHDR *tcp = (TCPHDR *) (data + sizeof (ETH_HEADER) + hlen); - DEBUGP ((" ")); - PrIP (ip->saddr); - DEBUGP ((":%d", ntohs (tcp->source))); - DEBUGP ((" -> ")); - PrIP (ip->daddr); - DEBUGP ((":%d", ntohs (tcp->dest))); - did = TRUE; - } - - // UDP packet? - else if ((ntohs (ip->frag_off) & IP_OFFMASK) == 0 - && ip->protocol == IPPROTO_UDP - && blen - hlen >= (sizeof (UDPHDR))) - { - const UDPHDR *udp = (UDPHDR *) (data + sizeof (ETH_HEADER) + hlen); - -#if 0 - // DHCP packet? - if ((udp->dest == htons (BOOTPC_PORT) || udp->dest == htons (BOOTPS_PORT)) - && blen - hlen >= (sizeof (UDPHDR) + sizeof (DHCP))) - { - const DHCP *dhcp = (DHCP *) (data - + hlen - + sizeof (ETH_HEADER) - + sizeof (UDPHDR)); - - int optlen = len - - sizeof (ETH_HEADER) - - hlen - - sizeof (UDPHDR) - - sizeof (DHCP); - - if (optlen < 0) - optlen = 0; - - DumpDHCP (eth, ip, udp, dhcp, optlen); - did = TRUE; - } -#endif - - if (!did) - { - DEBUGP ((" ")); - PrIP (ip->saddr); - DEBUGP ((":%d", ntohs (udp->source))); - DEBUGP ((" -> ")); - PrIP (ip->daddr); - DEBUGP ((":%d", ntohs (udp->dest))); - did = TRUE; - } - } - - if (!did) - { - DEBUGP ((" ipproto=%d ", ip->protocol)); - PrIP (ip->saddr); - DEBUGP ((" -> ")); - PrIP (ip->daddr); - } - - DEBUGP (("\n")); - return; - } - - { - DEBUGP (("%s ??? src=", prefix)); - PrMac (eth->src); - DEBUGP ((" dest=")); - PrMac (eth->dest); - DEBUGP ((" proto=0x%04x len=%d\n", - (int) ntohs(eth->proto), - len)); - } -} - -#endif diff --git a/windows/TapDriver/error.h b/windows/TapDriver/error.h deleted file mode 100644 index 47f436c5..00000000 --- a/windows/TapDriver/error.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * TAP-Windows -- A kernel driver to provide virtual tap - * device functionality on Windows. - * - * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. - * - * This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., - * and is released under the GPL version 2 (see below). - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program (see the file COPYING included with this - * distribution); if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -//----------------- -// DEBUGGING OUTPUT -//----------------- - -#define NOTE_ERROR() \ -{ \ - g_LastErrorFilename = __FILE__; \ - g_LastErrorLineNumber = __LINE__; \ -} - -#if DBG - -typedef struct { - unsigned int in; - unsigned int out; - unsigned int capacity; - char *text; - BOOLEAN error; - MUTEX lock; -} DebugOutput; - -VOID MyDebugPrint (const unsigned char* format, ...); - -VOID MyAssert (const unsigned char *file, int line); - -VOID DumpPacket (const char *prefix, - const unsigned char *data, - unsigned int len); - -VOID DumpPacket2 (const char *prefix, - const ETH_HEADER *eth, - const unsigned char *data, - unsigned int len); - -#define CAN_WE_PRINT (DEBUGP_AT_DISPATCH || KeGetCurrentIrql () < DISPATCH_LEVEL) - -#if ALSO_DBGPRINT -#define DEBUGP(fmt) { MyDebugPrint fmt; if (CAN_WE_PRINT) DbgPrint fmt; } -#else -#define DEBUGP(fmt) { MyDebugPrint fmt; } -#endif - -#define MYASSERT(exp) \ -{ \ - if (!(exp)) \ - { \ - MyAssert(__FILE__, __LINE__); \ - } \ -} - -#define DUMP_PACKET(prefix, data, len) \ - DumpPacket (prefix, data, len) - -#define DUMP_PACKET2(prefix, eth, data, len) \ - DumpPacket2 (prefix, eth, data, len) - -#else - -#define DEBUGP(fmt) -#define MYASSERT(exp) -#define DUMP_PACKET(prefix, data, len) -#define DUMP_PACKET2(prefix, eth, data, len) - -#endif diff --git a/windows/TapDriver/instance.c b/windows/TapDriver/instance.c deleted file mode 100644 index 3e1034b3..00000000 --- a/windows/TapDriver/instance.c +++ /dev/null @@ -1,241 +0,0 @@ -/* -* TAP-Windows -- A kernel driver to provide virtual tap -* device functionality on Windows. -* -* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. -* -* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., -* and is released under the GPL version 2 (see below). -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 2 -* as published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program (see the file COPYING included with this -* distribution); if not, write to the Free Software Foundation, Inc., -* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#define INSTANCE_KEY(a) ((PVOID)((a)->m_Extension.m_TapDevice)) - -#define N_INSTANCE_BUCKETS 256 - -typedef struct _INSTANCE { - struct _INSTANCE *next; - TapAdapterPointer m_Adapter; -} INSTANCE; - -typedef struct { - INSTANCE *list; - MUTEX lock; -} INSTANCE_BUCKET; - -typedef struct { - INSTANCE_BUCKET buckets[N_INSTANCE_BUCKETS]; -} INSTANCE_HASH; - -INSTANCE_HASH *g_InstanceHash = NULL; - -// must return a hash >= 0 and < N_INSTANCE_BUCKETS -int - InstanceHashValue (PVOID addr) -{ - UCHAR *p = (UCHAR *) &addr; - - if (sizeof (addr) == 4) - return p[0] ^ p[1] ^ p[2] ^ p[3]; - else if (sizeof (addr) == 8) - return p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4] ^ p[5] ^ p[6] ^ p[7]; - else - { - MYASSERT (0); - } -} - -BOOLEAN - InitInstanceList (VOID) -{ - MYASSERT (g_InstanceHash == NULL); - g_InstanceHash = MemAlloc (sizeof (INSTANCE_HASH), TRUE); - if (g_InstanceHash) - { - int i; - for (i = 0; i < N_INSTANCE_BUCKETS; ++i) - INIT_MUTEX (&g_InstanceHash->buckets[i].lock); - return TRUE; - } - else - return FALSE; -} - -int - NInstances (VOID) -{ - int i, n = 0; - - if (g_InstanceHash) - { - for (i = 0; i < N_INSTANCE_BUCKETS; ++i) - { - BOOLEAN got_lock; - INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[i]; - ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock); - - if (got_lock) - { - INSTANCE *current; - for (current = ib->list; current != NULL; current = current->next) - ++n; - RELEASE_MUTEX (&ib->lock); - } - else - return -1; - } - } - - return n; -} - -int - InstanceMaxBucketSize (VOID) -{ - int i, n = 0; - - if (g_InstanceHash) - { - for (i = 0; i < N_INSTANCE_BUCKETS; ++i) - { - BOOLEAN got_lock; - int bucket_size = 0; - INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[i]; - ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock); - - if (got_lock) - { - INSTANCE *current; - for (current = ib->list; current != NULL; current = current->next) - ++bucket_size; - if (bucket_size > n) - n = bucket_size; - RELEASE_MUTEX (&ib->lock); - } - else - return -1; - } - } - - return n; -} - -VOID - FreeInstanceList (VOID) -{ - if (g_InstanceHash) - { - MYASSERT (NInstances() == 0); - MemFree (g_InstanceHash, sizeof (INSTANCE_HASH)); - g_InstanceHash = NULL; - } -} - -BOOLEAN - AddAdapterToInstanceList (TapAdapterPointer p_Adapter) -{ - BOOLEAN got_lock; - BOOLEAN ret = FALSE; - const int hash = InstanceHashValue(INSTANCE_KEY(p_Adapter)); - INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[hash]; - - DEBUGP (("[TAP] AddAdapterToInstanceList hash=%d\n", hash)); - - ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock); - - if (got_lock) - { - INSTANCE *i = MemAlloc (sizeof (INSTANCE), FALSE); - if (i) - { - MYASSERT (p_Adapter); - i->m_Adapter = p_Adapter; - i->next = ib->list; - ib->list = i; - ret = TRUE; - } - RELEASE_MUTEX (&ib->lock); - } - - return ret; -} - -BOOLEAN - RemoveAdapterFromInstanceList (TapAdapterPointer p_Adapter) -{ - BOOLEAN got_lock; - BOOLEAN ret = FALSE; - INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[InstanceHashValue(INSTANCE_KEY(p_Adapter))]; - - ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock); - - if (got_lock) - { - INSTANCE *current, *prev=NULL; - for (current = ib->list; current != NULL; current = current->next) - { - if (current->m_Adapter == p_Adapter) // found match - { - if (prev) - prev->next = current->next; - else - ib->list = current->next; - MemFree (current->m_Adapter, sizeof (TapAdapter)); - MemFree (current, sizeof (INSTANCE)); - ret = TRUE; - break; - } - prev = current; - } - RELEASE_MUTEX (&ib->lock); - } - - return ret; -} - -TapAdapterPointer - LookupAdapterInInstanceList (PDEVICE_OBJECT p_DeviceObject) -{ - BOOLEAN got_lock; - TapAdapterPointer ret = NULL; - INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[InstanceHashValue((PVOID)p_DeviceObject)]; - - ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock); - - if (got_lock) - { - INSTANCE *current, *prev=NULL; - for (current = ib->list; current != NULL; current = current->next) - { - if (p_DeviceObject == INSTANCE_KEY (current->m_Adapter)) // found match - { - // move it to head of list - if (prev) - { - prev->next = current->next; - current->next = ib->list; - ib->list = current; - } - ret = ib->list->m_Adapter; - break; - } - prev = current; - } - RELEASE_MUTEX (&ib->lock); - } - - return ret; -} diff --git a/windows/TapDriver/lock.h b/windows/TapDriver/lock.h deleted file mode 100644 index e2a2029e..00000000 --- a/windows/TapDriver/lock.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * TAP-Windows -- A kernel driver to provide virtual tap - * device functionality on Windows. - * - * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. - * - * This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., - * and is released under the GPL version 2 (see below). - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program (see the file COPYING included with this - * distribution); if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -typedef struct -{ - volatile long count; -} MUTEX; - -#define MUTEX_SLEEP_TIME 10000 // microseconds - -#define INIT_MUTEX(m) { (m)->count = 0; } - -#define ACQUIRE_MUTEX_BLOCKING(m) \ -{ \ - while (NdisInterlockedIncrement (&((m)->count)) != 1) \ - { \ - NdisInterlockedDecrement(&((m)->count)); \ - NdisMSleep(MUTEX_SLEEP_TIME); \ - } \ -} - -#define RELEASE_MUTEX(m) \ -{ \ - NdisInterlockedDecrement(&((m)->count)); \ -} - -#define ACQUIRE_MUTEX_NONBLOCKING(m, result) \ -{ \ - if (NdisInterlockedIncrement (&((m)->count)) != 1) \ - { \ - NdisInterlockedDecrement(&((m)->count)); \ - result = FALSE; \ - } \ - else \ - { \ - result = TRUE; \ - } \ -} - -#define ACQUIRE_MUTEX_ADAPTIVE(m, result) \ -{ \ - result = TRUE; \ - while (NdisInterlockedIncrement (&((m)->count)) != 1) \ - { \ - NdisInterlockedDecrement(&((m)->count)); \ - if (KeGetCurrentIrql () < DISPATCH_LEVEL) \ - NdisMSleep(MUTEX_SLEEP_TIME); \ - else \ - { \ - result = FALSE; \ - break; \ - } \ - } \ -} diff --git a/windows/TapDriver/macinfo.c b/windows/TapDriver/macinfo.c deleted file mode 100644 index 95f75861..00000000 --- a/windows/TapDriver/macinfo.c +++ /dev/null @@ -1,154 +0,0 @@ -/* -* TAP-Windows -- A kernel driver to provide virtual tap -* device functionality on Windows. -* -* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. -* -* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., -* and is released under the GPL version 2 (see below). -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 2 -* as published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program (see the file COPYING included with this -* distribution); if not, write to the Free Software Foundation, Inc., -* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "macinfo.h" - -int - HexStringToDecimalInt (const int p_Character) -{ - int l_Value = 0; - - if (p_Character >= 'A' && p_Character <= 'F') - l_Value = (p_Character - 'A') + 10; - else if (p_Character >= 'a' && p_Character <= 'f') - l_Value = (p_Character - 'a') + 10; - else if (p_Character >= '0' && p_Character <= '9') - l_Value = p_Character - '0'; - - return l_Value; -} - -BOOLEAN - ParseMAC (MACADDR dest, const char *src) -{ - int c; - int mac_index = 0; - BOOLEAN high_digit = FALSE; - int delim_action = 1; - - MYASSERT (src); - MYASSERT (dest); - - CLEAR_MAC (dest); - - while (c = *src++) - { - if (IsMacDelimiter (c)) - { - mac_index += delim_action; - high_digit = FALSE; - delim_action = 1; - } - else if (IsHexDigit (c)) - { - const int digit = HexStringToDecimalInt (c); - if (mac_index < sizeof (MACADDR)) - { - if (!high_digit) - { - dest[mac_index] = (char)(digit); - high_digit = TRUE; - delim_action = 1; - } - else - { - dest[mac_index] = (char)(dest[mac_index] * 16 + digit); - ++mac_index; - high_digit = FALSE; - delim_action = 0; - } - } - else - return FALSE; - } - else - return FALSE; - } - - return (mac_index + delim_action) >= sizeof (MACADDR); -} - -/* -* Generate a MAC using the GUID in the adapter name. -* -* The mac is constructed as 00:FF:xx:xx:xx:xx where -* the Xs are taken from the first 32 bits of the GUID in the -* adapter name. This is similar to the Linux 2.4 tap MAC -* generator, except linux uses 32 random bits for the Xs. -* -* In general, this solution is reasonable for most -* applications except for very large bridged TAP networks, -* where the probability of address collisions becomes more -* than infintesimal. -* -* Using the well-known "birthday paradox", on a 1000 node -* network the probability of collision would be -* 0.000116292153. On a 10,000 node network, the probability -* of collision would be 0.01157288998621678766. -*/ - -VOID GenerateRandomMac (MACADDR mac, const unsigned char *adapter_name) -{ - unsigned const char *cp = adapter_name; - unsigned char c; - unsigned int i = 2; - unsigned int byte = 0; - int brace = 0; - int state = 0; - - CLEAR_MAC (mac); - - mac[0] = 0x00; - mac[1] = 0xFF; - - while (c = *cp++) - { - if (i >= sizeof (MACADDR)) - break; - if (c == '{') - brace = 1; - if (IsHexDigit (c) && brace) - { - const unsigned int digit = HexStringToDecimalInt (c); - if (state) - { - byte <<= 4; - byte |= digit; - mac[i++] = (unsigned char) byte; - state = 0; - } - else - { - byte = digit; - state = 1; - } - } - } -} - -VOID GenerateRelatedMAC (MACADDR dest, const MACADDR src, const int delta) -{ - COPY_MAC (dest, src); - dest[2] += (UCHAR) delta; -} diff --git a/windows/TapDriver/macinfo.h b/windows/TapDriver/macinfo.h deleted file mode 100644 index ba843e8c..00000000 --- a/windows/TapDriver/macinfo.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * TAP-Windows -- A kernel driver to provide virtual tap - * device functionality on Windows. - * - * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. - * - * This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., - * and is released under the GPL version 2 (see below). - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program (see the file COPYING included with this - * distribution); if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef MacInfoDefined -#define MacInfoDefined - -//=================================================================================== -// Macros -//=================================================================================== -#define IsMacDelimiter(a) (a == ':' || a == '-' || a == '.') -#define IsHexDigit(c) ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) - -#define COPY_MAC(dest, src) NdisMoveMemory ((dest), (src), sizeof (MACADDR)) -#define CLEAR_MAC(dest) NdisZeroMemory ((dest), sizeof (MACADDR)) -#define MAC_EQUAL(a,b) (memcmp ((a), (b), sizeof (MACADDR)) == 0) - -#endif diff --git a/windows/TapDriver/mem.c b/windows/TapDriver/mem.c deleted file mode 100644 index 2f01616e..00000000 --- a/windows/TapDriver/mem.c +++ /dev/null @@ -1,186 +0,0 @@ -/* -* TAP-Windows -- A kernel driver to provide virtual tap -* device functionality on Windows. -* -* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. -* -* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., -* and is released under the GPL version 2 (see below). -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 2 -* as published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program (see the file COPYING included with this -* distribution); if not, write to the Free Software Foundation, Inc., -* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -//------------------ -// Memory Management -//------------------ - -PVOID - MemAlloc (ULONG p_Size, BOOLEAN zero) -{ - PVOID l_Return = NULL; - - if (p_Size) - { - __try - { - if (NdisAllocateMemoryWithTag (&l_Return, p_Size, 'APAT') - == NDIS_STATUS_SUCCESS) - { - if (zero) - NdisZeroMemory (l_Return, p_Size); - } - else - l_Return = NULL; - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - l_Return = NULL; - } - } - - return l_Return; -} - -VOID - MemFree (PVOID p_Addr, ULONG p_Size) -{ - if (p_Addr && p_Size) - { - __try - { -#if DBG - NdisZeroMemory (p_Addr, p_Size); -#endif - NdisFreeMemory (p_Addr, p_Size, 0); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - } - } -} - -/* -* Circular queue management routines. -*/ - -#define QUEUE_BYTE_ALLOCATION(size) \ - (sizeof (Queue) + (size * sizeof (PVOID))) - -#define QUEUE_ADD_INDEX(var, inc) \ -{ \ - var += inc; \ - if (var >= q->capacity) \ - var -= q->capacity; \ - MYASSERT (var < q->capacity); \ -} - -#define QUEUE_SANITY_CHECK() \ - MYASSERT (q != NULL && q->base < q->capacity && q->size <= q->capacity) - -#define QueueCount(q) (q->size) - -#define UPDATE_MAX_SIZE() \ -{ \ - if (q->size > q->max_size) \ - q->max_size = q->size; \ -} - -Queue * - QueueInit (ULONG capacity) -{ - Queue *q; - - MYASSERT (capacity > 0); - q = (Queue *) MemAlloc (QUEUE_BYTE_ALLOCATION (capacity), TRUE); - if (!q) - return NULL; - - q->base = q->size = 0; - q->capacity = capacity; - q->max_size = 0; - return q; -} - -VOID - QueueFree (Queue *q) -{ - if (q) - { - QUEUE_SANITY_CHECK (); - MemFree (q, QUEUE_BYTE_ALLOCATION (q->capacity)); - } -} - -PVOID - QueuePush (Queue *q, PVOID item) -{ - ULONG dest; - QUEUE_SANITY_CHECK (); - if (q->size == q->capacity) - return NULL; - dest = q->base; - QUEUE_ADD_INDEX (dest, q->size); - q->data[dest] = item; - ++q->size; - UPDATE_MAX_SIZE(); - return item; -} - -PVOID - QueuePop (Queue *q) -{ - ULONG oldbase; - QUEUE_SANITY_CHECK (); - if (!q->size) - return NULL; - oldbase = q->base; - QUEUE_ADD_INDEX (q->base, 1); - --q->size; - UPDATE_MAX_SIZE(); - return q->data[oldbase]; -} - -PVOID - QueueExtract (Queue *q, PVOID item) -{ - ULONG src, dest, count, n; - QUEUE_SANITY_CHECK (); - n = 0; - src = dest = q->base; - count = q->size; - while (count--) - { - if (item == q->data[src]) - { - ++n; - --q->size; - } - else - { - q->data[dest] = q->data[src]; - QUEUE_ADD_INDEX (dest, 1); - } - QUEUE_ADD_INDEX (src, 1); - } - if (n) - return item; - else - return NULL; -} - -#undef QUEUE_BYTE_ALLOCATION -#undef QUEUE_ADD_INDEX -#undef QUEUE_SANITY_CHECK -#undef UPDATE_MAX_SIZE diff --git a/windows/TapDriver/proto.h b/windows/TapDriver/proto.h deleted file mode 100644 index 06c712bc..00000000 --- a/windows/TapDriver/proto.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -* TAP-Windows -- A kernel driver to provide virtual tap -* device functionality on Windows. -* -* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. -* -* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., -* and is released under the GPL version 2 (see below). -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 2 -* as published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program (see the file COPYING included with this -* distribution); if not, write to the Free Software Foundation, Inc., -* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -//============================================================ -// MAC address, Ethernet header, and ARP -//============================================================ - -#pragma pack(1) - -typedef unsigned char MACADDR [6]; - -//----------------- -// Ethernet address -//----------------- - -typedef struct { - MACADDR addr; -} ETH_ADDR; - -typedef struct { - ETH_ADDR list[NIC_MAX_MCAST_LIST]; -} MC_LIST; - -//---------------- -// Ethernet header -//---------------- - -typedef struct -{ - MACADDR dest; /* destination eth addr */ - MACADDR src; /* source ether addr */ - -# define ETH_P_IP 0x0800 /* IPv4 protocol */ -# define ETH_P_IPV6 0x86DD /* IPv6 protocol */ -# define ETH_P_ARP 0x0806 /* ARP protocol */ - USHORT proto; /* packet type ID field */ -} ETH_HEADER, *PETH_HEADER; - -#pragma pack() diff --git a/windows/TapDriver/prototypes.h b/windows/TapDriver/prototypes.h deleted file mode 100644 index 4062fc18..00000000 --- a/windows/TapDriver/prototypes.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * TAP-Windows -- A kernel driver to provide virtual tap - * device functionality on Windows. - * - * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. - * - * This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., - * and is released under the GPL version 2 (see below). - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program (see the file COPYING included with this - * distribution); if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TAP_PROTOTYPES_DEFINED -#define TAP_PROTOTYPES_DEFINED - -NTSTATUS DriverEntry - ( - IN PDRIVER_OBJECT p_DriverObject, - IN PUNICODE_STRING p_RegistryPath - ); - -VOID TapDriverUnload - ( - IN PDRIVER_OBJECT p_DriverObject - ); - -NDIS_STATUS AdapterCreate - ( - OUT PNDIS_STATUS p_ErrorStatus, - OUT PUINT p_MediaIndex, - IN PNDIS_MEDIUM p_Media, - IN UINT p_MediaCount, - IN NDIS_HANDLE p_AdapterHandle, - IN NDIS_HANDLE p_ConfigurationHandle - ); - -VOID AdapterHalt - ( - IN NDIS_HANDLE p_AdapterContext - ); - -VOID AdapterFreeResources - ( - TapAdapterPointer p_Adapter - ); - -NDIS_STATUS AdapterReset - ( - OUT PBOOLEAN p_AddressingReset, - IN NDIS_HANDLE p_AdapterContext - ); - -NDIS_STATUS AdapterQuery - ( - IN NDIS_HANDLE p_AdapterContext, - IN NDIS_OID p_OID, - IN PVOID p_Buffer, - IN ULONG p_BufferLength, - OUT PULONG p_BytesWritten, - OUT PULONG p_BytesNeeded - ); - -NDIS_STATUS AdapterModify - ( - IN NDIS_HANDLE p_AdapterContext, - IN NDIS_OID p_OID, - IN PVOID p_Buffer, - IN ULONG p_BufferLength, - OUT PULONG p_BytesRead, - OUT PULONG p_BytesNeeded - ); - -NDIS_STATUS AdapterTransmit - ( - IN NDIS_HANDLE p_AdapterContext, - IN PNDIS_PACKET p_Packet, - IN UINT p_Flags - ); - -NDIS_STATUS AdapterReceive - ( - OUT PNDIS_PACKET p_Packet, - OUT PUINT p_Transferred, - IN NDIS_HANDLE p_AdapterContext, - IN NDIS_HANDLE p_ReceiveContext, - IN UINT p_Offset, - IN UINT p_ToTransfer - ); - -NTSTATUS TapDeviceHook - ( - IN PDEVICE_OBJECT p_DeviceObject, - IN PIRP p_IRP - ); - -NDIS_STATUS CreateTapDevice - ( - TapExtensionPointer p_Extension, - const char *p_Name - ); - -VOID DestroyTapDevice - ( - TapExtensionPointer p_Extension - ); - -VOID TapDeviceFreeResources - ( - TapExtensionPointer p_Extension - ); - -NTSTATUS CompleteIRP - ( - IN PIRP p_IRP, - IN TapPacketPointer p_PacketBuffer, - IN CCHAR PriorityBoost - ); - -VOID CancelIRPCallback - ( - IN PDEVICE_OBJECT p_DeviceObject, - IN PIRP p_IRP - ); - -VOID CancelIRP - ( - TapExtensionPointer p_Extension, - IN PIRP p_IRP, - BOOLEAN callback - ); - -VOID FlushQueues - ( - TapExtensionPointer p_Extension - ); - -VOID SetMediaStatus - ( - TapAdapterPointer p_Adapter, - BOOLEAN state - ); - -VOID HookDispatchFunctions(); - -struct WIN2K_NDIS_MINIPORT_BLOCK -{ - unsigned char opaque[16]; - UNICODE_STRING MiniportName; // how mini-port refers to us -}; - -#endif diff --git a/windows/TapDriver/tap-windows.h b/windows/TapDriver/tap-windows.h deleted file mode 100644 index 3b695e5d..00000000 --- a/windows/TapDriver/tap-windows.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * TAP-Windows -- A kernel driver to provide virtual tap - * device functionality on Windows. - * - * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. - * - * This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., - * and is released under the GPL version 2 (see below). - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program (see the file COPYING included with this - * distribution); if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef __TAP_WIN_H -#define __TAP_WIN_H - -/* - * ============= - * TAP IOCTLs - * ============= - */ - -#define TAP_WIN_CONTROL_CODE(request,method) \ - CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS) - -#define TAP_WIN_IOCTL_GET_MAC TAP_WIN_CONTROL_CODE (1, METHOD_BUFFERED) -#define TAP_WIN_IOCTL_GET_VERSION TAP_WIN_CONTROL_CODE (2, METHOD_BUFFERED) -#define TAP_WIN_IOCTL_GET_MTU TAP_WIN_CONTROL_CODE (3, METHOD_BUFFERED) -#define TAP_WIN_IOCTL_SET_MEDIA_STATUS TAP_WIN_CONTROL_CODE (6, METHOD_BUFFERED) -#define TAP_WIN_IOCTL_GET_LOG_LINE TAP_WIN_CONTROL_CODE (8, METHOD_BUFFERED) -#define TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS TAP_WIN_CONTROL_CODE (11, METHOD_BUFFERED) - -// Must be the same as NIC_MAX_MCAST_LIST in constants.h -#define TAP_MAX_MCAST_LIST 128 - -// Amount of memory that must be provided to ioctl TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS -#define TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS_OUTPUT_BUF_SIZE (TAP_MAX_MCAST_LIST * 6) - -/* - * ================= - * Registry keys - * ================= - */ - -#define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" -#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" - -/* - * ====================== - * Filesystem prefixes - * ====================== - */ - -#define USERMODEDEVICEDIR "\\\\.\\Global\\" -#define SYSDEVICEDIR "\\Device\\" -#define USERDEVICEDIR "\\DosDevices\\Global\\" -#define TAP_WIN_SUFFIX ".tap" - -#endif diff --git a/windows/TapDriver/tapdrvr.c b/windows/TapDriver/tapdrvr.c deleted file mode 100644 index d638cdf6..00000000 --- a/windows/TapDriver/tapdrvr.c +++ /dev/null @@ -1,2183 +0,0 @@ -/* -* TAP-Windows -- A kernel driver to provide virtual tap -* device functionality on Windows. -* -* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. -* -* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., -* and is released under the GPL version 2 (see below). -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 2 -* as published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program (see the file COPYING included with this -* distribution); if not, write to the Free Software Foundation, Inc., -* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -//====================================================== -// This driver is designed to work on Win 2000 or higher -// versions of Windows. -// -// It is SMP-safe and handles NDIS 5 power management. -// -// By default we operate as a "tap" virtual ethernet -// 802.3 interface, but we can emulate a "tun" -// interface (point-to-point IPv4) through the -// TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT or -// TAP_WIN_IOCTL_CONFIG_TUN ioctl. -//====================================================== - -#include "tap-windows.h" -#include "config.h" - -#define NDIS_MINIPORT_DRIVER -#define BINARY_COMPATIBLE 0 -#define NDIS50_MINIPORT 1 -#define NDIS_WDM 0 -#define NDIS50 1 -#define NTSTRSAFE_LIB - -// Debug info output -#define ALSO_DBGPRINT 1 -#define DEBUGP_AT_DISPATCH 0 - -#if defined(DDKVER_MAJOR) && DDKVER_MAJOR < 5600 -#include -#include -#include -#else -#include -#include -#include -#endif - -#include "lock.h" -#include "constants.h" -#include "proto.h" -#include "error.h" -#include "endian.h" -#include "types.h" -#include "prototypes.h" - -#include "mem.c" -#include "macinfo.c" -#include "error.c" -#include "instance.c" - -#define IS_UP(ta) \ - ((ta)->m_InterfaceIsRunning && (ta)->m_Extension.m_TapIsRunning) - -#define INCREMENT_STAT(s) ++(s) - -#define NAME_BUFFER_SIZE 80 - -//======================================================== -// Globals -//======================================================== - -NDIS_HANDLE g_NdisWrapperHandle; - -const UINT g_SupportedOIDList[] = { - OID_GEN_HARDWARE_STATUS, - OID_GEN_MEDIA_SUPPORTED, - OID_GEN_MEDIA_IN_USE, - OID_GEN_MAXIMUM_LOOKAHEAD, - OID_GEN_MAC_OPTIONS, - OID_GEN_LINK_SPEED, - OID_GEN_TRANSMIT_BLOCK_SIZE, - OID_GEN_RECEIVE_BLOCK_SIZE, - OID_GEN_VENDOR_DESCRIPTION, - OID_GEN_DRIVER_VERSION, - OID_GEN_XMIT_OK, - OID_GEN_RCV_OK, - OID_GEN_XMIT_ERROR, - OID_GEN_RCV_ERROR, - OID_802_3_PERMANENT_ADDRESS, - OID_802_3_CURRENT_ADDRESS, - OID_GEN_RCV_NO_BUFFER, - OID_802_3_RCV_ERROR_ALIGNMENT, - OID_802_3_XMIT_ONE_COLLISION, - OID_802_3_XMIT_MORE_COLLISIONS, - OID_802_3_MULTICAST_LIST, - OID_802_3_MAXIMUM_LIST_SIZE, - OID_GEN_VENDOR_ID, - OID_GEN_CURRENT_LOOKAHEAD, - OID_GEN_CURRENT_PACKET_FILTER, - OID_GEN_PROTOCOL_OPTIONS, - OID_GEN_MAXIMUM_TOTAL_SIZE, - OID_GEN_TRANSMIT_BUFFER_SPACE, - OID_GEN_RECEIVE_BUFFER_SPACE, - OID_GEN_MAXIMUM_FRAME_SIZE, - OID_GEN_VENDOR_DRIVER_VERSION, - OID_GEN_MAXIMUM_SEND_PACKETS, - OID_GEN_MEDIA_CONNECT_STATUS, - OID_GEN_SUPPORTED_LIST -}; - -//============================================================ -// Driver Entry -//============================================================ -#pragma NDIS_INIT_FUNCTION (DriverEntry) - -DRIVER_INITIALIZE DriverEntry; -NTSTATUS - DriverEntry (IN PDRIVER_OBJECT p_DriverObject, - IN PUNICODE_STRING p_RegistryPath) -{ - NDIS_STATUS l_Status = NDIS_STATUS_FAILURE; - NDIS_MINIPORT_CHARACTERISTICS *l_Properties = NULL; - - //======================================================== - // Notify NDIS that a new miniport driver is initializing. - //======================================================== - - NdisMInitializeWrapper (&g_NdisWrapperHandle, - p_DriverObject, - p_RegistryPath, NULL); - - //====================== - // Global initialization - //====================== - -#if DBG - MyDebugInit (10000); // Allocate debugging text space -#endif - - if (!InitInstanceList ()) - { - DEBUGP (("[TAP] Allocation failed for adapter instance list\n")); - goto cleanup; - } - - //======================================= - // Set and register miniport entry points - //======================================= - - l_Properties = (NDIS_MINIPORT_CHARACTERISTICS *)MemAlloc (sizeof (NDIS_MINIPORT_CHARACTERISTICS), TRUE); - - if (l_Properties == NULL) - { - DEBUGP (("[TAP] Allocation failed for miniport entry points\n")); - goto cleanup; - } - - l_Properties->MajorNdisVersion = TAP_NDIS_MAJOR_VERSION; - l_Properties->MinorNdisVersion = TAP_NDIS_MINOR_VERSION; - l_Properties->InitializeHandler = AdapterCreate; - l_Properties->HaltHandler = AdapterHalt; - l_Properties->ResetHandler = AdapterReset; /* DISPATCH_LEVEL */ - l_Properties->TransferDataHandler = AdapterReceive; /* DISPATCH_LEVEL */ - l_Properties->SendHandler = AdapterTransmit; /* DISPATCH_LEVEL */ - l_Properties->QueryInformationHandler = AdapterQuery; /* DISPATCH_LEVEL */ - l_Properties->SetInformationHandler = AdapterModify; /* DISPATCH_LEVEL */ - - switch (l_Status = - NdisMRegisterMiniport (g_NdisWrapperHandle, l_Properties, - sizeof (NDIS_MINIPORT_CHARACTERISTICS))) - { - case NDIS_STATUS_SUCCESS: - { - DEBUGP (("[TAP] version [%d.%d] %s %s registered miniport successfully\n", - TAP_DRIVER_MAJOR_VERSION, - TAP_DRIVER_MINOR_VERSION, - __DATE__, - __TIME__)); - DEBUGP (("Registry Path: '%.*S'\n", p_RegistryPath->Length/2, p_RegistryPath->Buffer)); - break; - } - - case NDIS_STATUS_BAD_CHARACTERISTICS: - { - DEBUGP (("[TAP] Miniport characteristics were badly defined\n")); - NdisTerminateWrapper (g_NdisWrapperHandle, NULL); - break; - } - - case NDIS_STATUS_BAD_VERSION: - { - DEBUGP - (("[TAP] NDIS Version is wrong for the given characteristics\n")); - NdisTerminateWrapper (g_NdisWrapperHandle, NULL); - break; - } - - case NDIS_STATUS_RESOURCES: - { - DEBUGP (("[TAP] Insufficient resources\n")); - NdisTerminateWrapper (g_NdisWrapperHandle, NULL); - break; - } - - default: - case NDIS_STATUS_FAILURE: - { - DEBUGP (("[TAP] Unknown fatal registration error\n")); - NdisTerminateWrapper (g_NdisWrapperHandle, NULL); - break; - } - } - -cleanup: - if (l_Properties) - MemFree (l_Properties, sizeof (NDIS_MINIPORT_CHARACTERISTICS)); - - if (l_Status == NDIS_STATUS_SUCCESS) - NdisMRegisterUnloadHandler (g_NdisWrapperHandle, TapDriverUnload); - else - TapDriverUnload (p_DriverObject); - - return l_Status; -} - -//============================================================ -// Driver Unload -//============================================================ -DRIVER_UNLOAD TapDriverUnload; -VOID - TapDriverUnload (IN PDRIVER_OBJECT p_DriverObject) -{ - DEBUGP (("[TAP] version [%d.%d] %s %s unloaded, instances=%d, imbs=%d\n", - TAP_DRIVER_MAJOR_VERSION, - TAP_DRIVER_MINOR_VERSION, - __DATE__, - __TIME__, - NInstances(), - InstanceMaxBucketSize())); - - FreeInstanceList (); - - //============================== - // Free debugging text space - //============================== -#if DBG - MyDebugFree (); -#endif -} - -//========================================================== -// Adapter Initialization -//========================================================== -NDIS_STATUS AdapterCreate - (OUT PNDIS_STATUS p_ErrorStatus, - OUT PUINT p_MediaIndex, - IN PNDIS_MEDIUM p_Media, - IN UINT p_MediaCount, - IN NDIS_HANDLE p_AdapterHandle, - IN NDIS_HANDLE p_ConfigurationHandle) -{ - TapAdapterPointer l_Adapter = NULL; - - NDIS_MEDIUM l_PreferredMedium = NdisMedium802_3; // Ethernet - BOOLEAN l_MacFromRegistry = FALSE; - UINT l_Index; - NDIS_STATUS status; - - DEBUGP (("[TAP] AdapterCreate called\n")); - - //==================================== - // Make sure adapter type is supported - //==================================== - - for (l_Index = 0; - l_Index < p_MediaCount && p_Media[l_Index] != l_PreferredMedium; - ++l_Index); - - if (l_Index == p_MediaCount) - { - DEBUGP (("[TAP] Unsupported adapter type [wanted: %d]\n", - l_PreferredMedium)); - return NDIS_STATUS_UNSUPPORTED_MEDIA; - } - - *p_MediaIndex = l_Index; - - //========================================= - // Allocate memory for TapAdapter structure - //========================================= - - l_Adapter = MemAlloc (sizeof (TapAdapter), TRUE); - - if (l_Adapter == NULL) - { - DEBUGP (("[TAP] Couldn't allocate adapter memory\n")); - return NDIS_STATUS_RESOURCES; - } - - //========================================== - // Inform the NDIS library about significant - // features of our virtual NIC. - //========================================== - - NdisMSetAttributesEx - (p_AdapterHandle, - (NDIS_HANDLE) l_Adapter, - 16, - NDIS_ATTRIBUTE_DESERIALIZE - | NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT - | NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT - | NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND, - NdisInterfaceInternal); - - //===================================== - // Initialize simple Adapter parameters - //===================================== - - l_Adapter->m_Lookahead = DEFAULT_PACKET_LOOKAHEAD; - l_Adapter->m_Medium = l_PreferredMedium; - l_Adapter->m_DeviceState = '?'; - l_Adapter->m_MiniportAdapterHandle = p_AdapterHandle; - - //================================== - // Allocate spinlock for controlling - // access to multicast address list. - //================================== - NdisAllocateSpinLock (&l_Adapter->m_MCLock); - l_Adapter->m_MCLockAllocated = TRUE; - - //==================================================== - // Register a shutdown handler which will be called - // on system restart/shutdown to halt our virtual NIC. - //==================================================== - - NdisMRegisterAdapterShutdownHandler (p_AdapterHandle, l_Adapter, - AdapterHalt); - l_Adapter->m_RegisteredAdapterShutdownHandler = TRUE; - - //============================================ - // Get parameters from registry which were set - // in the adapter advanced properties dialog. - //============================================ - { - NDIS_STATUS status; - NDIS_HANDLE configHandle; - NDIS_CONFIGURATION_PARAMETER *parm; - - // set defaults in case our registry query fails - l_Adapter->m_MTU = ETHERNET_MTU; - l_Adapter->m_MediaStateAlwaysConnected = FALSE; - l_Adapter->m_MediaState = FALSE; - - NdisOpenConfiguration (&status, &configHandle, p_ConfigurationHandle); - if (status != NDIS_STATUS_SUCCESS) - { - DEBUGP (("[TAP] Couldn't open adapter registry\n")); - AdapterFreeResources (l_Adapter); - return status; - } - - //==================================== - // Allocate and construct adapter name - //==================================== - { - - NDIS_STRING mkey = NDIS_STRING_CONST("MiniportName"); - NDIS_STRING vkey = NDIS_STRING_CONST("NdisVersion"); - NDIS_STATUS vstatus; - NDIS_CONFIGURATION_PARAMETER *vparm; - - NdisReadConfiguration (&vstatus, &vparm, configHandle, &vkey, NdisParameterInteger); - if (vstatus == NDIS_STATUS_SUCCESS) - DEBUGP (("[TAP] NdisReadConfiguration NdisVersion=%X\n", vparm->ParameterData.IntegerData)); - - NdisReadConfiguration (&status, &parm, configHandle, &mkey, NdisParameterString); - if (status == NDIS_STATUS_SUCCESS) - { - if (parm->ParameterType == NdisParameterString) - { - DEBUGP (("[TAP] NdisReadConfiguration (MiniportName=%.*S)\n", - parm->ParameterData.StringData.Length/2, - parm->ParameterData.StringData.Buffer)); - - if (RtlUnicodeStringToAnsiString ( - &l_Adapter->m_NameAnsi, - &parm->ParameterData.StringData, - TRUE) != STATUS_SUCCESS) - { - DEBUGP (("[TAP] MiniportName failed\n")); - status = NDIS_STATUS_RESOURCES; - } - } - } - else - { - /* "MiniportName" is available only XP and above. Not on Windows 2000. */ - if (vstatus == NDIS_STATUS_SUCCESS && vparm->ParameterData.IntegerData == 0x50000) - { - /* Fallback for Windows 2000 with NDIS version 5.00.00 - Don't use this on Vista, 'NDIS_MINIPORT_BLOCK' was changed! */ - if (RtlUnicodeStringToAnsiString (&l_Adapter->m_NameAnsi, - &((struct WIN2K_NDIS_MINIPORT_BLOCK *) p_AdapterHandle)->MiniportName, - TRUE) != STATUS_SUCCESS) - { - DEBUGP (("[TAP] MiniportName (W2K) failed\n")); - status = NDIS_STATUS_RESOURCES; - } - else - { - DEBUGP (("[TAP] MiniportName (W2K) succeeded: %s\n", l_Adapter->m_NameAnsi.Buffer)); - status = NDIS_STATUS_SUCCESS; - } - } - } - } - - /* Can't continue without name (see macro 'NAME') */ - if (status != NDIS_STATUS_SUCCESS || !l_Adapter->m_NameAnsi.Buffer) - { - NdisCloseConfiguration (configHandle); - AdapterFreeResources (l_Adapter); - DEBUGP (("[TAP] failed to get miniport name\n")); - return NDIS_STATUS_RESOURCES; - } - - /* Read MTU setting from registry */ - { - NDIS_STRING key = NDIS_STRING_CONST("MTU"); - NdisReadConfiguration (&status, &parm, configHandle, - &key, NdisParameterInteger); - if (status == NDIS_STATUS_SUCCESS) - { - if (parm->ParameterType == NdisParameterInteger) - { - int mtu = parm->ParameterData.IntegerData; - if (mtu < MINIMUM_MTU) - mtu = MINIMUM_MTU; - if (mtu > MAXIMUM_MTU) - mtu = MAXIMUM_MTU; - l_Adapter->m_MTU = mtu; - } - } - } - - /* Read Media Status setting from registry */ - { - NDIS_STRING key = NDIS_STRING_CONST("MediaStatus"); - NdisReadConfiguration (&status, &parm, configHandle, - &key, NdisParameterInteger); - if (status == NDIS_STATUS_SUCCESS) - { - if (parm->ParameterType == NdisParameterInteger) - { - if (parm->ParameterData.IntegerData) - { - l_Adapter->m_MediaStateAlwaysConnected = TRUE; - l_Adapter->m_MediaState = TRUE; - } - } - } - } - - /* Read optional MAC setting from registry */ - { - NDIS_STRING key = NDIS_STRING_CONST("MAC"); - ANSI_STRING mac_string; - NdisReadConfiguration (&status, &parm, configHandle, - &key, NdisParameterString); - if (status == NDIS_STATUS_SUCCESS) - { - if (parm->ParameterType == NdisParameterString) - { - if (RtlUnicodeStringToAnsiString (&mac_string, &parm->ParameterData.StringData, TRUE) == STATUS_SUCCESS) - { - l_MacFromRegistry = ParseMAC (l_Adapter->m_MAC, mac_string.Buffer); - RtlFreeAnsiString (&mac_string); - } - } - } - } - - NdisCloseConfiguration (configHandle); - - DEBUGP (("[%s] MTU=%d\n", NAME (l_Adapter), l_Adapter->m_MTU)); - } - - //================================== - // Store and update MAC address info - //================================== - - if (!l_MacFromRegistry) - GenerateRandomMac (l_Adapter->m_MAC, (const unsigned char *)NAME (l_Adapter)); - - DEBUGP (("[%s] Using MAC %x:%x:%x:%x:%x:%x\n", - NAME (l_Adapter), - l_Adapter->m_MAC[0], l_Adapter->m_MAC[1], l_Adapter->m_MAC[2], - l_Adapter->m_MAC[3], l_Adapter->m_MAC[4], l_Adapter->m_MAC[5])); - - //==================================== - // Initialize TAP device - //==================================== - { - NDIS_STATUS tap_status; - tap_status = CreateTapDevice (&l_Adapter->m_Extension, NAME (l_Adapter)); - if (tap_status != NDIS_STATUS_SUCCESS) - { - AdapterFreeResources (l_Adapter); - DEBUGP (("[TAP] CreateTapDevice failed\n")); - return tap_status; - } - } - - if (!AddAdapterToInstanceList (l_Adapter)) - { - NOTE_ERROR (); - TapDeviceFreeResources (&l_Adapter->m_Extension); - AdapterFreeResources (l_Adapter); - DEBUGP (("[TAP] AddAdapterToInstanceList failed\n")); - return NDIS_STATUS_RESOURCES; - } - - l_Adapter->m_InterfaceIsRunning = TRUE; - - return NDIS_STATUS_SUCCESS; -} - -VOID - AdapterHalt (IN NDIS_HANDLE p_AdapterContext) -{ - BOOLEAN status; - - TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext; - - NOTE_ERROR (); - - l_Adapter->m_InterfaceIsRunning = FALSE; - - DEBUGP (("[%s] is being halted\n", NAME (l_Adapter))); - - DestroyTapDevice (&l_Adapter->m_Extension); - - // Free resources - DEBUGP (("[%s] Freeing Resources\n", NAME (l_Adapter))); - AdapterFreeResources (l_Adapter); - - status = RemoveAdapterFromInstanceList (l_Adapter); - DEBUGP (("[TAP] RemoveAdapterFromInstanceList returned %d\n", (int) status)); - - DEBUGP (("[TAP] version [%d.%d] %s %s AdapterHalt returning\n", - TAP_DRIVER_MAJOR_VERSION, - TAP_DRIVER_MINOR_VERSION, - __DATE__, - __TIME__)); -} - -VOID - AdapterFreeResources (TapAdapterPointer p_Adapter) -{ - MYASSERT (!p_Adapter->m_CalledAdapterFreeResources); - p_Adapter->m_CalledAdapterFreeResources = TRUE; - - if (p_Adapter->m_NameAnsi.Buffer) - RtlFreeAnsiString (&p_Adapter->m_NameAnsi); - - if (p_Adapter->m_RegisteredAdapterShutdownHandler) - NdisMDeregisterAdapterShutdownHandler (p_Adapter->m_MiniportAdapterHandle); - - if (p_Adapter->m_MCLockAllocated) - NdisFreeSpinLock (&p_Adapter->m_MCLock); -} - -VOID - DestroyTapDevice (TapExtensionPointer p_Extension) -{ - DEBUGP (("[%s] Destroying tap device\n", p_Extension->m_TapName)); - - //====================================== - // Let clients know we are shutting down - //====================================== - p_Extension->m_TapIsRunning = FALSE; - p_Extension->m_TapOpens = 0; - p_Extension->m_Halt = TRUE; - - //===================================== - // If we are concurrently executing in - // TapDeviceHook or AdapterTransmit, - // give those calls time to finish. - // Note that we must be running at IRQL - // < DISPATCH_LEVEL in order to call - // NdisMSleep. - //===================================== - NdisMSleep (500000); - - //=========================================================== - // Exhaust IRP and packet queues. Any pending IRPs will - // be cancelled, causing user-space to get this error - // on overlapped reads: - // The I/O operation has been aborted because of either a - // thread exit or an application request. (code=995) - // It's important that user-space close the device handle - // when this code is returned, so that when we finally - // do a NdisMDeregisterDevice, the device reference count - // is 0. Otherwise the driver will not unload even if the - // the last adapter has been halted. - //=========================================================== - FlushQueues (p_Extension); - NdisMSleep (500000); // give user space time to respond to IRP cancel - - TapDeviceFreeResources (p_Extension); -} - -VOID - TapDeviceFreeResources (TapExtensionPointer p_Extension) -{ - MYASSERT (p_Extension); - MYASSERT (!p_Extension->m_CalledTapDeviceFreeResources); - p_Extension->m_CalledTapDeviceFreeResources = TRUE; - - if (p_Extension->m_PacketQueue) - QueueFree (p_Extension->m_PacketQueue); - if (p_Extension->m_IrpQueue) - QueueFree (p_Extension->m_IrpQueue); - - if (p_Extension->m_CreatedUnicodeLinkName) - RtlFreeUnicodeString (&p_Extension->m_UnicodeLinkName); - - //========================================================== - // According to DDK docs, the device is not actually deleted - // until its reference count falls to zero. That means we - // still need to gracefully fail TapDeviceHook requests - // after this point, otherwise ugly things would happen if - // the device was disabled (e.g. in the network connections - // control panel) while a userspace app still held an open - // file handle to it. - //========================================================== - - if (p_Extension->m_TapDevice) - { - BOOLEAN status; - status = (NdisMDeregisterDevice (p_Extension->m_TapDeviceHandle) - == NDIS_STATUS_SUCCESS); - DEBUGP (("[TAP] Deregistering TAP device, status=%d\n", (int)status)); - } - - if (p_Extension->m_TapName) - MemFree (p_Extension->m_TapName, NAME_BUFFER_SIZE); - - if (p_Extension->m_AllocatedSpinlocks) - { - NdisFreeSpinLock (&p_Extension->m_QueueLock); - } -} - -//======================================================================== -// Tap Device Initialization -//======================================================================== - -NDIS_STATUS - CreateTapDevice (TapExtensionPointer p_Extension, const char *p_Name) -{ -# define SIZEOF_DISPATCH (sizeof(PDRIVER_DISPATCH) * (IRP_MJ_MAXIMUM_FUNCTION + 1)) - PDRIVER_DISPATCH *l_Dispatch = NULL; - ANSI_STRING l_TapString, l_LinkString; - UNICODE_STRING l_TapUnicode; - BOOLEAN l_FreeTapUnicode = FALSE; - NTSTATUS l_Status, l_Return = NDIS_STATUS_SUCCESS; - const char *l_UsableName; - - DEBUGP (("[TAP] version [%d.%d] creating tap device: %s\n", - TAP_DRIVER_MAJOR_VERSION, - TAP_DRIVER_MINOR_VERSION, - p_Name)); - - NdisZeroMemory (p_Extension, sizeof (TapExtension)); - - INIT_MUTEX (&p_Extension->m_OpenCloseMutex); - - l_LinkString.Buffer = NULL; - l_TapString.Buffer = NULL; - - l_TapString.MaximumLength = l_LinkString.MaximumLength = NAME_BUFFER_SIZE; - - //======================================= - // Set TAP device entry points - //======================================= - - if ((l_Dispatch = MemAlloc (SIZEOF_DISPATCH, TRUE)) == NULL) - { - DEBUGP (("[%s] couldn't alloc TAP dispatch table\n", p_Name)); - l_Return = NDIS_STATUS_RESOURCES; - goto cleanup; - } - - l_Dispatch[IRP_MJ_DEVICE_CONTROL] = TapDeviceHook; - l_Dispatch[IRP_MJ_READ] = TapDeviceHook; - l_Dispatch[IRP_MJ_WRITE] = TapDeviceHook; - l_Dispatch[IRP_MJ_CREATE] = TapDeviceHook; - l_Dispatch[IRP_MJ_CLOSE] = TapDeviceHook; - - //================================== - // Find the beginning of the GUID - //================================== - l_UsableName = p_Name; - while (*l_UsableName != '{') - { - if (*l_UsableName == '\0') - { - DEBUGP (("[%s] couldn't find leading '{' in name\n", p_Name)); - l_Return = NDIS_STATUS_RESOURCES; - goto cleanup; - } - ++l_UsableName; - } - - //================================== - // Allocate pool for TAP device name - //================================== - - if ((p_Extension->m_TapName = l_TapString.Buffer = - MemAlloc (NAME_BUFFER_SIZE, TRUE)) == NULL) - { - DEBUGP (("[%s] couldn't alloc TAP name buffer\n", p_Name)); - l_Return = NDIS_STATUS_RESOURCES; - goto cleanup; - } - - //================================================ - // Allocate pool for TAP symbolic link name buffer - //================================================ - - if ((l_LinkString.Buffer = - (PCHAR)MemAlloc (NAME_BUFFER_SIZE, TRUE)) == NULL) - { - DEBUGP (("[%s] couldn't alloc TAP symbolic link name buffer\n", - p_Name)); - l_Return = NDIS_STATUS_RESOURCES; - goto cleanup; - } - - //======================================================= - // Set TAP device name - //======================================================= - - l_Status = RtlStringCchPrintfExA - (l_TapString.Buffer, - l_TapString.MaximumLength, - NULL, - NULL, - STRSAFE_FILL_BEHIND_NULL | STRSAFE_IGNORE_NULLS, - "%s%s%s", - SYSDEVICEDIR, - l_UsableName, - TAP_WIN_SUFFIX); - - if (l_Status != STATUS_SUCCESS) - { - DEBUGP (("[%s] couldn't format TAP device name\n", - p_Name)); - l_Return = NDIS_STATUS_RESOURCES; - goto cleanup; - } - l_TapString.Length = (USHORT) strlen (l_TapString.Buffer); - - DEBUGP (("TAP DEV NAME: '%s'\n", l_TapString.Buffer)); - - //======================================================= - // Set TAP link name - //======================================================= - - l_Status = RtlStringCchPrintfExA - (l_LinkString.Buffer, - l_LinkString.MaximumLength, - NULL, - NULL, - STRSAFE_FILL_BEHIND_NULL | STRSAFE_IGNORE_NULLS, - "%s%s%s", - USERDEVICEDIR, - l_UsableName, - TAP_WIN_SUFFIX); - - if (l_Status != STATUS_SUCCESS) - { - DEBUGP (("[%s] couldn't format TAP device symbolic link\n", - p_Name)); - l_Return = NDIS_STATUS_RESOURCES; - goto cleanup; - } - l_LinkString.Length = (USHORT) strlen (l_LinkString.Buffer); - - DEBUGP (("TAP LINK NAME: '%s'\n", l_LinkString.Buffer)); - - //================================================== - // Convert strings to unicode - //================================================== - if (RtlAnsiStringToUnicodeString (&l_TapUnicode, &l_TapString, TRUE) != - STATUS_SUCCESS) - { - DEBUGP (("[%s] couldn't alloc TAP unicode name buffer\n", - p_Name)); - l_Return = NDIS_STATUS_RESOURCES; - goto cleanup; - } - l_FreeTapUnicode = TRUE; - - if (RtlAnsiStringToUnicodeString - (&p_Extension->m_UnicodeLinkName, &l_LinkString, TRUE) - != STATUS_SUCCESS) - { - DEBUGP - (("[%s] Couldn't allocate unicode string for symbolic link name\n", - p_Name)); - l_Return = NDIS_STATUS_RESOURCES; - goto cleanup; - } - p_Extension->m_CreatedUnicodeLinkName = TRUE; - - //================================================== - // Create new TAP device with symbolic - // link and associate with adapter. - //================================================== - - l_Status = NdisMRegisterDevice - (g_NdisWrapperHandle, - &l_TapUnicode, - &p_Extension->m_UnicodeLinkName, - l_Dispatch, - &p_Extension->m_TapDevice, - &p_Extension->m_TapDeviceHandle - ); - - if (l_Status != STATUS_SUCCESS) - { - DEBUGP (("[%s] couldn't be created\n", p_Name)); - l_Return = NDIS_STATUS_RESOURCES; - goto cleanup; - } - - /* Set TAP device flags */ - p_Extension->m_TapDevice->Flags |= DO_DIRECT_IO; - - //======================================================== - // Initialize Packet and IRP queues. - // - // The packet queue is used to buffer data which has been - // "transmitted" by the virtual NIC, before user space - // has had a chance to read it. - // - // The IRP queue is used to buffer pending I/O requests - // from userspace, i.e. read requests on the TAP device - // waiting for the system to "transmit" something through - // the virtual NIC. - // - // Basically, packets in the packet queue are used - // to satisfy IRP requests in the IRP queue. - // - // QueueLock is used to lock the packet queue used - // for the TAP-Windows NIC -> User Space packet flow direction. - // - // All accesses to packet or IRP queues should be - // bracketed by the QueueLock spinlock, - // in order to be SMP-safe. - //======================================================== - - NdisAllocateSpinLock (&p_Extension->m_QueueLock); - p_Extension->m_AllocatedSpinlocks = TRUE; - - p_Extension->m_PacketQueue = QueueInit (PACKET_QUEUE_SIZE); - p_Extension->m_IrpQueue = QueueInit (IRP_QUEUE_SIZE); - if (!p_Extension->m_PacketQueue - || !p_Extension->m_IrpQueue) - { - DEBUGP (("[%s] couldn't alloc TAP queues\n", p_Name)); - l_Return = NDIS_STATUS_RESOURCES; - goto cleanup; - } - - //======================== - // Finalize initialization - //======================== - - p_Extension->m_TapIsRunning = TRUE; - - DEBUGP (("[%s] successfully created TAP device [%s]\n", p_Name, - p_Extension->m_TapName)); - -cleanup: - if (l_FreeTapUnicode) - RtlFreeUnicodeString (&l_TapUnicode); - if (l_LinkString.Buffer) - MemFree (l_LinkString.Buffer, NAME_BUFFER_SIZE); - if (l_Dispatch) - MemFree (l_Dispatch, SIZEOF_DISPATCH); - - if (l_Return != NDIS_STATUS_SUCCESS) - TapDeviceFreeResources (p_Extension); - - return l_Return; -} -#undef SIZEOF_DISPATCH - -//======================================================== -// Adapter Control -//======================================================== -NDIS_STATUS - AdapterReset (OUT PBOOLEAN p_AddressingReset, IN NDIS_HANDLE p_AdapterContext) -{ - TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext; - DEBUGP (("[%s] is resetting\n", NAME (l_Adapter))); - return NDIS_STATUS_SUCCESS; -} - -NDIS_STATUS AdapterReceive - (OUT PNDIS_PACKET p_Packet, - OUT PUINT p_Transferred, - IN NDIS_HANDLE p_AdapterContext, - IN NDIS_HANDLE p_ReceiveContext, - IN UINT p_Offset, - IN UINT p_ToTransfer) -{ - return NDIS_STATUS_SUCCESS; -} - -//============================================================== -// Adapter Option Query/Modification -//============================================================== -NDIS_STATUS AdapterQuery - (IN NDIS_HANDLE p_AdapterContext, - IN NDIS_OID p_OID, - IN PVOID p_Buffer, - IN ULONG p_BufferLength, - OUT PULONG p_BytesWritten, OUT PULONG p_BytesNeeded) -{ - TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext; - TapAdapterQuery l_Query, *l_QueryPtr = &l_Query; - NDIS_STATUS l_Status = NDIS_STATUS_SUCCESS; - UINT l_QueryLength = 4; - BOOLEAN lock_succeeded; - - NdisZeroMemory (&l_Query, sizeof (l_Query)); - - switch (p_OID) - { - //=================================================================== - // Vendor & Driver version Info - //=================================================================== - case OID_GEN_VENDOR_DESCRIPTION: - l_QueryPtr = (TapAdapterQueryPointer) PRODUCT_TAP_WIN_DEVICE_DESCRIPTION; - l_QueryLength = strlen (PRODUCT_TAP_WIN_DEVICE_DESCRIPTION) + 1; - break; - - case OID_GEN_VENDOR_ID: - l_Query.m_Long = 0xffffff; - break; - - case OID_GEN_DRIVER_VERSION: - l_Query.m_Short = - (((USHORT) TAP_NDIS_MAJOR_VERSION) << 8 | (USHORT) - TAP_NDIS_MINOR_VERSION); - l_QueryLength = sizeof (unsigned short); - break; - - case OID_GEN_VENDOR_DRIVER_VERSION: - l_Query.m_Long = - (((USHORT) PRODUCT_TAP_WIN_MAJOR) << 8 | (USHORT) - PRODUCT_TAP_WIN_MINOR); - break; - - //================================================================= - // Statistics - //================================================================= - case OID_GEN_RCV_NO_BUFFER: - l_Query.m_Long = 0; - break; - - case OID_802_3_RCV_ERROR_ALIGNMENT: - l_Query.m_Long = 0; - break; - - case OID_802_3_XMIT_ONE_COLLISION: - l_Query.m_Long = 0; - break; - - case OID_802_3_XMIT_MORE_COLLISIONS: - l_Query.m_Long = 0; - break; - - case OID_GEN_XMIT_OK: - l_Query.m_Long = l_Adapter->m_Tx; - break; - - case OID_GEN_RCV_OK: - l_Query.m_Long = l_Adapter->m_Rx; - break; - - case OID_GEN_XMIT_ERROR: - l_Query.m_Long = l_Adapter->m_TxErr; - break; - - case OID_GEN_RCV_ERROR: - l_Query.m_Long = l_Adapter->m_RxErr; - break; - - //=================================================================== - // Device & Protocol Options - //=================================================================== - case OID_GEN_SUPPORTED_LIST: - l_QueryPtr = (TapAdapterQueryPointer) g_SupportedOIDList; - l_QueryLength = sizeof (g_SupportedOIDList); - break; - - case OID_GEN_MAC_OPTIONS: - // This MUST be here !!! - l_Query.m_Long = (NDIS_MAC_OPTION_RECEIVE_SERIALIZED - | NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA - | NDIS_MAC_OPTION_NO_LOOPBACK - | NDIS_MAC_OPTION_TRANSFERS_NOT_PEND); - - break; - - case OID_GEN_CURRENT_PACKET_FILTER: - l_Query.m_Long = - (NDIS_PACKET_TYPE_ALL_LOCAL | - NDIS_PACKET_TYPE_BROADCAST | - NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_ALL_FUNCTIONAL); - - break; - - case OID_GEN_PROTOCOL_OPTIONS: - l_Query.m_Long = 0; - break; - - //================================================================== - // Device Info - //================================================================== - case OID_GEN_MEDIA_CONNECT_STATUS: - l_Query.m_Long = l_Adapter->m_MediaState - ? NdisMediaStateConnected : NdisMediaStateDisconnected; - break; - - case OID_GEN_HARDWARE_STATUS: - l_Query.m_HardwareStatus = NdisHardwareStatusReady; - l_QueryLength = sizeof (NDIS_HARDWARE_STATUS); - break; - - case OID_GEN_MEDIA_SUPPORTED: - case OID_GEN_MEDIA_IN_USE: - l_Query.m_Medium = l_Adapter->m_Medium; - l_QueryLength = sizeof (NDIS_MEDIUM); - break; - - case OID_GEN_PHYSICAL_MEDIUM: - l_Query.m_PhysicalMedium = NdisPhysicalMediumUnspecified; - l_QueryLength = sizeof (NDIS_PHYSICAL_MEDIUM); - break; - - case OID_GEN_LINK_SPEED: - l_Query.m_Long = 100000; // rate / 100 bps - break; - - case OID_802_3_PERMANENT_ADDRESS: - case OID_802_3_CURRENT_ADDRESS: - COPY_MAC (l_Query.m_MacAddress, l_Adapter->m_MAC); - l_QueryLength = sizeof (MACADDR); - break; - - //================================================================== - // Limits - //================================================================== - - case OID_GEN_MAXIMUM_SEND_PACKETS: - l_Query.m_Long = 1; - break; - - case OID_802_3_MAXIMUM_LIST_SIZE: - l_Query.m_Long = NIC_MAX_MCAST_LIST; - break; - - case OID_GEN_CURRENT_LOOKAHEAD: - l_Query.m_Long = l_Adapter->m_Lookahead; - break; - - case OID_GEN_MAXIMUM_LOOKAHEAD: - case OID_GEN_MAXIMUM_TOTAL_SIZE: - case OID_GEN_RECEIVE_BUFFER_SPACE: - case OID_GEN_RECEIVE_BLOCK_SIZE: - l_Query.m_Long = DEFAULT_PACKET_LOOKAHEAD; - break; - - case OID_GEN_MAXIMUM_FRAME_SIZE: - case OID_GEN_TRANSMIT_BLOCK_SIZE: - case OID_GEN_TRANSMIT_BUFFER_SPACE: - l_Query.m_Long = l_Adapter->m_MTU; - break; - - case OID_PNP_CAPABILITIES: - do - { - PNDIS_PNP_CAPABILITIES pPNPCapabilities; - PNDIS_PM_WAKE_UP_CAPABILITIES pPMstruct; - - if (p_BufferLength >= sizeof (NDIS_PNP_CAPABILITIES)) - { - pPNPCapabilities = (PNDIS_PNP_CAPABILITIES) (p_Buffer); - - // - // Setting up the buffer to be returned - // to the Protocol above the Passthru miniport - // - pPMstruct = &pPNPCapabilities->WakeUpCapabilities; - pPMstruct->MinMagicPacketWakeUp = NdisDeviceStateUnspecified; - pPMstruct->MinPatternWakeUp = NdisDeviceStateUnspecified; - pPMstruct->MinLinkChangeWakeUp = NdisDeviceStateUnspecified; - } - l_QueryLength = sizeof (NDIS_PNP_CAPABILITIES); - } - while (FALSE); - break; - case OID_PNP_QUERY_POWER: - break; - - // Required OIDs that we don't support - - case OID_GEN_SUPPORTED_GUIDS: - case OID_GEN_MEDIA_CAPABILITIES: - case OID_TCP_TASK_OFFLOAD: - case OID_FFP_SUPPORT: - l_Status = NDIS_STATUS_INVALID_OID; - break; - - // Optional stats OIDs - - case OID_GEN_DIRECTED_BYTES_XMIT: - case OID_GEN_DIRECTED_FRAMES_XMIT: - case OID_GEN_MULTICAST_BYTES_XMIT: - case OID_GEN_MULTICAST_FRAMES_XMIT: - case OID_GEN_BROADCAST_BYTES_XMIT: - case OID_GEN_BROADCAST_FRAMES_XMIT: - case OID_GEN_DIRECTED_BYTES_RCV: - case OID_GEN_DIRECTED_FRAMES_RCV: - case OID_GEN_MULTICAST_BYTES_RCV: - case OID_GEN_MULTICAST_FRAMES_RCV: - case OID_GEN_BROADCAST_BYTES_RCV: - case OID_GEN_BROADCAST_FRAMES_RCV: - l_Status = NDIS_STATUS_INVALID_OID; - break; - - //=================================================================== - // Not Handled - //=================================================================== - default: - DEBUGP (("[%s] Unhandled OID %lx\n", NAME (l_Adapter), p_OID)); - l_Status = NDIS_STATUS_INVALID_OID; - break; - } - - if (l_Status != NDIS_STATUS_SUCCESS) - ; - else if (l_QueryLength > p_BufferLength) - { - l_Status = NDIS_STATUS_INVALID_LENGTH; - *p_BytesNeeded = l_QueryLength; - } - else - NdisMoveMemory (p_Buffer, (PVOID) l_QueryPtr, - (*p_BytesWritten = l_QueryLength)); - - return l_Status; -} - -NDIS_STATUS AdapterModify - (IN NDIS_HANDLE p_AdapterContext, - IN NDIS_OID p_OID, - IN PVOID p_Buffer, - IN ULONG p_BufferLength, - OUT PULONG p_BytesRead, - OUT PULONG p_BytesNeeded) -{ - TapAdapterQueryPointer l_Query = (TapAdapterQueryPointer) p_Buffer; - TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext; - NDIS_STATUS l_Status = NDIS_STATUS_INVALID_OID; - ULONG l_Long; - - switch (p_OID) - { - //================================================================== - // Device Info - //================================================================== - case OID_802_3_MULTICAST_LIST: - DEBUGP (("[%s] Setting [OID_802_3_MULTICAST_LIST]\n", - NAME (l_Adapter))); - - *p_BytesNeeded = sizeof (ETH_ADDR); - *p_BytesRead = p_BufferLength; - - if (p_BufferLength % sizeof (ETH_ADDR)) - l_Status = NDIS_STATUS_INVALID_LENGTH; - else if (p_BufferLength > sizeof (MC_LIST)) - { - l_Status = NDIS_STATUS_MULTICAST_FULL; - *p_BytesNeeded = sizeof (MC_LIST); - } - else - { - NdisAcquireSpinLock (&l_Adapter->m_MCLock); - - NdisZeroMemory(&l_Adapter->m_MCList, sizeof (MC_LIST)); - - NdisMoveMemory(&l_Adapter->m_MCList, - p_Buffer, - p_BufferLength); - - l_Adapter->m_MCListSize = p_BufferLength / sizeof (ETH_ADDR); - - NdisReleaseSpinLock (&l_Adapter->m_MCLock); - - l_Status = NDIS_STATUS_SUCCESS; - } - break; - - case OID_GEN_CURRENT_PACKET_FILTER: - l_Status = NDIS_STATUS_INVALID_LENGTH; - *p_BytesNeeded = 4; - - if (p_BufferLength >= sizeof (ULONG)) - { - DEBUGP - (("[%s] Setting [OID_GEN_CURRENT_PACKET_FILTER] to [0x%02lx]\n", - NAME (l_Adapter), l_Query->m_Long)); - l_Status = NDIS_STATUS_SUCCESS; - *p_BytesRead = sizeof (ULONG); - } - break; - - case OID_GEN_CURRENT_LOOKAHEAD: - if (p_BufferLength < sizeof (ULONG)) - { - l_Status = NDIS_STATUS_INVALID_LENGTH; - *p_BytesNeeded = 4; - } - else if (l_Query->m_Long > DEFAULT_PACKET_LOOKAHEAD - || l_Query->m_Long <= 0) - { - l_Status = NDIS_STATUS_INVALID_DATA; - } - else - { - DEBUGP (("[%s] Setting [OID_GEN_CURRENT_LOOKAHEAD] to [%d]\n", - NAME (l_Adapter), l_Query->m_Long)); - l_Adapter->m_Lookahead = l_Query->m_Long; - l_Status = NDIS_STATUS_SUCCESS; - *p_BytesRead = sizeof (ULONG); - } - break; - - case OID_GEN_NETWORK_LAYER_ADDRESSES: - l_Status = NDIS_STATUS_SUCCESS; - *p_BytesRead = *p_BytesNeeded = 0; - break; - - case OID_GEN_TRANSPORT_HEADER_OFFSET: - l_Status = NDIS_STATUS_SUCCESS; - *p_BytesRead = *p_BytesNeeded = 0; - break; - - case OID_PNP_SET_POWER: - do - { - NDIS_DEVICE_POWER_STATE NewDeviceState; - - NewDeviceState = (*(PNDIS_DEVICE_POWER_STATE) p_Buffer); - - switch (NewDeviceState) - { - case NdisDeviceStateD0: - l_Adapter->m_DeviceState = '0'; - break; - case NdisDeviceStateD1: - l_Adapter->m_DeviceState = '1'; - break; - case NdisDeviceStateD2: - l_Adapter->m_DeviceState = '2'; - break; - case NdisDeviceStateD3: - l_Adapter->m_DeviceState = '3'; - break; - default: - l_Adapter->m_DeviceState = '?'; - break; - } - - l_Status = NDIS_STATUS_FAILURE; - - // - // Check for invalid length - // - if (p_BufferLength < sizeof (NDIS_DEVICE_POWER_STATE)) - { - l_Status = NDIS_STATUS_INVALID_LENGTH; - break; - } - - if (NewDeviceState > NdisDeviceStateD0) - { - l_Adapter->m_InterfaceIsRunning = FALSE; - DEBUGP (("[%s] Power management device state OFF\n", - NAME (l_Adapter))); - } - else - { - l_Adapter->m_InterfaceIsRunning = TRUE; - DEBUGP (("[%s] Power management device state ON\n", - NAME (l_Adapter))); - } - - l_Status = NDIS_STATUS_SUCCESS; - } - while (FALSE); - - if (l_Status == NDIS_STATUS_SUCCESS) - { - *p_BytesRead = sizeof (NDIS_DEVICE_POWER_STATE); - *p_BytesNeeded = 0; - } - else - { - *p_BytesRead = 0; - *p_BytesNeeded = sizeof (NDIS_DEVICE_POWER_STATE); - } - break; - - case OID_PNP_REMOVE_WAKE_UP_PATTERN: - case OID_PNP_ADD_WAKE_UP_PATTERN: - l_Status = NDIS_STATUS_SUCCESS; - *p_BytesRead = *p_BytesNeeded = 0; - break; - - default: - DEBUGP (("[%s] Can't set value for OID %lx\n", NAME (l_Adapter), - p_OID)); - l_Status = NDIS_STATUS_INVALID_OID; - *p_BytesRead = *p_BytesNeeded = 0; - break; - } - - return l_Status; -} - -//==================================================================== -// Adapter Transmission -//==================================================================== -NDIS_STATUS - AdapterTransmit (IN NDIS_HANDLE p_AdapterContext, - IN PNDIS_PACKET p_Packet, - IN UINT p_Flags) -{ - TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext; - ULONG l_Index = 0, l_PacketLength = 0; - UINT l_BufferLength = 0; - PIRP l_IRP; - TapPacketPointer l_PacketBuffer; - PNDIS_BUFFER l_NDIS_Buffer; - PUCHAR l_Buffer; - PVOID result; - - NdisQueryPacket (p_Packet, NULL, NULL, &l_NDIS_Buffer, &l_PacketLength); - - //==================================================== - // Here we abandon the transmission attempt if any of - // the parameters is wrong or memory allocation fails - // but we do not indicate failure. The packet is - // silently dropped. - //==================================================== - - if (l_PacketLength < ETHERNET_HEADER_SIZE || l_PacketLength > 65535) - goto exit_fail; - else if (!l_Adapter->m_Extension.m_TapOpens || !l_Adapter->m_MediaState) - goto exit_success; // Nothing is bound to the TAP device - - if (NdisAllocateMemoryWithTag (&l_PacketBuffer, - TAP_PACKET_SIZE (l_PacketLength), - '5PAT') != NDIS_STATUS_SUCCESS) - goto exit_no_resources; - - if (l_PacketBuffer == NULL) - goto exit_no_resources; - - l_PacketBuffer->m_SizeFlags = (l_PacketLength & TP_SIZE_MASK); - - //=========================== - // Reassemble packet contents - //=========================== - - __try - { - l_Index = 0; - while (l_NDIS_Buffer && l_Index < l_PacketLength) - { - ULONG newlen; - NdisQueryBuffer (l_NDIS_Buffer, (PVOID *) & l_Buffer, - &l_BufferLength); - newlen = l_Index + l_BufferLength; - if (newlen > l_PacketLength) - { - NOTE_ERROR (); - goto no_queue; /* overflow */ - } - NdisMoveMemory (l_PacketBuffer->m_Data + l_Index, l_Buffer, - l_BufferLength); - l_Index = newlen; - NdisGetNextBuffer (l_NDIS_Buffer, &l_NDIS_Buffer); - } - if (l_Index != l_PacketLength) - { - NOTE_ERROR (); - goto no_queue; /* underflow */ - } - - DUMP_PACKET ("AdapterTransmit", l_PacketBuffer->m_Data, l_PacketLength); - - //=============================================== - // Push packet onto queue to wait for read from - // userspace. - //=============================================== - - NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock); - - result = NULL; - if (IS_UP (l_Adapter)) - result = QueuePush (l_Adapter->m_Extension.m_PacketQueue, l_PacketBuffer); - - NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock); - - if ((TapPacketPointer) result != l_PacketBuffer) - { - // adapter receive overrun - INCREMENT_STAT (l_Adapter->m_TxErr); - goto no_queue; - } - else - { - INCREMENT_STAT (l_Adapter->m_Tx); - } - - //============================================================ - // Cycle through IRPs and packets, try to satisfy each pending - // IRP with a queued packet. - //============================================================ - while (TRUE) - { - l_IRP = NULL; - l_PacketBuffer = NULL; - - NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock); - - if (IS_UP (l_Adapter) - && QueueCount (l_Adapter->m_Extension.m_PacketQueue) - && QueueCount (l_Adapter->m_Extension.m_IrpQueue)) - { - l_IRP = (PIRP) QueuePop (l_Adapter->m_Extension.m_IrpQueue); - l_PacketBuffer = (TapPacketPointer) - QueuePop (l_Adapter->m_Extension.m_PacketQueue); - } - - NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock); - - MYASSERT ((l_IRP != NULL) + (l_PacketBuffer != NULL) != 1); - - if (l_IRP && l_PacketBuffer) - { - CompleteIRP (l_IRP, - l_PacketBuffer, - IO_NETWORK_INCREMENT); - } - else - break; - } - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - } - - return NDIS_STATUS_SUCCESS; - -no_queue: - NdisFreeMemory (l_PacketBuffer, - TAP_PACKET_SIZE (l_PacketLength), - 0); - -exit_success: - return NDIS_STATUS_SUCCESS; - -exit_fail: - return NDIS_STATUS_FAILURE; - -exit_no_resources: - return NDIS_STATUS_RESOURCES; -} - -//====================================================================== -// Hooks for catching TAP device IRP's. -//====================================================================== - -DRIVER_DISPATCH TapDeviceHook; -NTSTATUS - TapDeviceHook (IN PDEVICE_OBJECT p_DeviceObject, IN PIRP p_IRP) -{ - TapAdapterPointer l_Adapter = LookupAdapterInInstanceList (p_DeviceObject); - PIO_STACK_LOCATION l_IrpSp; - NTSTATUS l_Status = STATUS_SUCCESS; - BOOLEAN accessible; - ULONG i,j; - - l_IrpSp = IoGetCurrentIrpStackLocation (p_IRP); - - p_IRP->IoStatus.Status = STATUS_SUCCESS; - p_IRP->IoStatus.Information = 0; - - if (!l_Adapter || l_Adapter->m_Extension.m_Halt) - { - DEBUGP (("TapDeviceHook called when TAP device is halted, MajorFunction=%d\n", - (int)l_IrpSp->MajorFunction)); - - if (l_IrpSp->MajorFunction == IRP_MJ_CLOSE) - { - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - return STATUS_SUCCESS; - } - else - { - p_IRP->IoStatus.Status = STATUS_NO_SUCH_DEVICE; - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - return STATUS_NO_SUCH_DEVICE; - } - } - - switch (l_IrpSp->MajorFunction) - { - //=========================================================== - // Ioctl call handlers - //=========================================================== - case IRP_MJ_DEVICE_CONTROL: - { - switch (l_IrpSp->Parameters.DeviceIoControl.IoControlCode) - { - case TAP_WIN_IOCTL_GET_MAC: - { - if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength - >= sizeof (MACADDR)) - { - COPY_MAC (p_IRP->AssociatedIrp.SystemBuffer, - l_Adapter->m_MAC); - p_IRP->IoStatus.Information = sizeof (MACADDR); - } - else - { - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL; - } - break; - } - case TAP_WIN_IOCTL_GET_VERSION: - { - const ULONG size = sizeof (ULONG) * 3; - if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength - >= size) - { - ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0] - = TAP_DRIVER_MAJOR_VERSION; - ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[1] - = TAP_DRIVER_MINOR_VERSION; - ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[2] -#if DBG - = 1; -#else - = 0; -#endif - p_IRP->IoStatus.Information = size; - } - else - { - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL; - } - - break; - } - case TAP_WIN_IOCTL_GET_MTU: - { - const ULONG size = sizeof (ULONG) * 1; - if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength - >= size) - { - ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0] - = l_Adapter->m_MTU; - p_IRP->IoStatus.Information = size; - } - else - { - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL; - } - - break; - } - -#if DBG - case TAP_WIN_IOCTL_GET_LOG_LINE: - { - if (GetDebugLine ((LPTSTR)p_IRP->AssociatedIrp.SystemBuffer, - l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength)) - p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS; - else - p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; - - p_IRP->IoStatus.Information - = l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength; - - break; - } -#endif - - // Allow ZeroTier One to get multicast memberships at the L2 level in a - // protocol-neutral manner. - case TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS: - { - if (&l_Adapter->m_MCLockAllocated) - NdisAcquireSpinLock (&l_Adapter->m_MCLock); - if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength < TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS_OUTPUT_BUF_SIZE) { - /* output buffer too small */ - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; - } else { - char *out = (char *)p_IRP->AssociatedIrp.SystemBuffer; - char *end = out + TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS_OUTPUT_BUF_SIZE; - for(i=0;im_MCListSize;++i) { - if (i >= TAP_MAX_MCAST_LIST) - break; - for(j=0;j<6;++j) - *(out++) = l_Adapter->m_MCList.list[i].addr[j]; - if (out >= end) - break; - } - while (out < end) - *(out++) = (char)0; - p_IRP->IoStatus.Information - = l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength; - p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS; - } - if (&l_Adapter->m_MCLockAllocated) - NdisReleaseSpinLock (&l_Adapter->m_MCLock); - - break; - } - - case TAP_WIN_IOCTL_SET_MEDIA_STATUS: - { - if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >= - (sizeof (ULONG) * 1)) - { - ULONG parm = ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0]; - SetMediaStatus (l_Adapter, (BOOLEAN) parm); - p_IRP->IoStatus.Information = 1; - } - else - { - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; - } - break; - } - - default: - { - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; - break; - } - } - - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - break; - } - - //=========================================================== - // User mode thread issued a read request on the tap device - // If there are packets waiting to be read, then the request - // will be satisfied here. If not, then the request will be - // queued and satisfied by any packet that is not used to - // satisfy requests ahead of it. - //=========================================================== - case IRP_MJ_READ: - { - TapPacketPointer l_PacketBuffer; - BOOLEAN pending = FALSE; - - // Save IRP-accessible copy of buffer length - p_IRP->IoStatus.Information = l_IrpSp->Parameters.Read.Length; - - if (p_IRP->MdlAddress == NULL) - { - DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_READ\n", - NAME (l_Adapter))); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; - p_IRP->IoStatus.Information = 0; - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - break; - } - else if ((p_IRP->AssociatedIrp.SystemBuffer = - MmGetSystemAddressForMdlSafe - (p_IRP->MdlAddress, NormalPagePriority)) == NULL) - { - DEBUGP (("[%s] Could not map address in IRP_MJ_READ\n", - NAME (l_Adapter))); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_INSUFFICIENT_RESOURCES; - p_IRP->IoStatus.Information = 0; - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - break; - } - else if (!l_Adapter->m_InterfaceIsRunning) - { - DEBUGP (("[%s] Interface is down in IRP_MJ_READ\n", - NAME (l_Adapter))); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; - p_IRP->IoStatus.Information = 0; - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - break; - } - - //================================== - // Can we provide immediate service? - //================================== - - l_PacketBuffer = NULL; - - NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock); - - if (IS_UP (l_Adapter) - && QueueCount (l_Adapter->m_Extension.m_PacketQueue) - && QueueCount (l_Adapter->m_Extension.m_IrpQueue) == 0) - { - l_PacketBuffer = (TapPacketPointer) - QueuePop (l_Adapter->m_Extension.m_PacketQueue); - } - - NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock); - - if (l_PacketBuffer) - { - l_Status = CompleteIRP (p_IRP, - l_PacketBuffer, - IO_NO_INCREMENT); - break; - } - - //============================= - // Attempt to pend read request - //============================= - - NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock); - - if (IS_UP (l_Adapter) - && QueuePush (l_Adapter->m_Extension.m_IrpQueue, p_IRP) == (PIRP) p_IRP) - { - IoSetCancelRoutine (p_IRP, CancelIRPCallback); - l_Status = STATUS_PENDING; - IoMarkIrpPending (p_IRP); - pending = TRUE; - } - - NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock); - - if (pending) - break; - - // Can't queue anymore IRP's - DEBUGP (("[%s] TAP [%s] read IRP overrun\n", - NAME (l_Adapter), l_Adapter->m_Extension.m_TapName)); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; - p_IRP->IoStatus.Information = 0; - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - break; - } - - //============================================================== - // User mode issued a WriteFile request on the TAP file handle. - // The request will always get satisfied here. The call may - // fail if there are too many pending packets (queue full). - //============================================================== - case IRP_MJ_WRITE: - { - if (p_IRP->MdlAddress == NULL) - { - DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_WRITE\n", - NAME (l_Adapter))); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER; - p_IRP->IoStatus.Information = 0; - } - else if ((p_IRP->AssociatedIrp.SystemBuffer = - MmGetSystemAddressForMdlSafe - (p_IRP->MdlAddress, NormalPagePriority)) == NULL) - { - DEBUGP (("[%s] Could not map address in IRP_MJ_WRITE\n", - NAME (l_Adapter))); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_INSUFFICIENT_RESOURCES; - p_IRP->IoStatus.Information = 0; - } - else if (!l_Adapter->m_InterfaceIsRunning) - { - DEBUGP (("[%s] Interface is down in IRP_MJ_WRITE\n", - NAME (l_Adapter))); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; - p_IRP->IoStatus.Information = 0; - } - else if ((l_IrpSp->Parameters.Write.Length) >= ETHERNET_HEADER_SIZE) - { - __try - { - p_IRP->IoStatus.Information = l_IrpSp->Parameters.Write.Length; - - DUMP_PACKET ("IRP_MJ_WRITE ETH", - (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer, - l_IrpSp->Parameters.Write.Length); - - NdisMEthIndicateReceive - (l_Adapter->m_MiniportAdapterHandle, - (NDIS_HANDLE) l_Adapter, - (PCHAR)p_IRP->AssociatedIrp.SystemBuffer, - ETHERNET_HEADER_SIZE, - (unsigned char *)p_IRP->AssociatedIrp.SystemBuffer + ETHERNET_HEADER_SIZE, - l_IrpSp->Parameters.Write.Length - ETHERNET_HEADER_SIZE, - l_IrpSp->Parameters.Write.Length - ETHERNET_HEADER_SIZE); - - NdisMEthIndicateReceiveComplete (l_Adapter->m_MiniportAdapterHandle); - - p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS; - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - DEBUGP (("[%s] NdisMEthIndicateReceive failed in IRP_MJ_WRITE\n", - NAME (l_Adapter))); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; - p_IRP->IoStatus.Information = 0; - } - } - else - { - DEBUGP (("[%s] Bad buffer size in IRP_MJ_WRITE, len=%d\n", - NAME (l_Adapter), - l_IrpSp->Parameters.Write.Length)); - NOTE_ERROR (); - p_IRP->IoStatus.Information = 0; // ETHERNET_HEADER_SIZE; - p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL; - } - - if (l_Status == STATUS_SUCCESS) - INCREMENT_STAT (l_Adapter->m_Rx); - else - INCREMENT_STAT (l_Adapter->m_RxErr); - - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - break; - } - - //-------------------------------------------------------------- - // User mode thread has called CreateFile() on the tap device - //-------------------------------------------------------------- - case IRP_MJ_CREATE: - { - BOOLEAN succeeded = FALSE; - BOOLEAN mutex_succeeded; - - DEBUGP - (("[%s] [TAP] release [%d.%d] open request (m_TapOpens=%d)\n", - NAME (l_Adapter), TAP_DRIVER_MAJOR_VERSION, - TAP_DRIVER_MINOR_VERSION, l_Adapter->m_Extension.m_TapOpens)); - - ACQUIRE_MUTEX_ADAPTIVE (&l_Adapter->m_Extension.m_OpenCloseMutex, mutex_succeeded); - if (mutex_succeeded) - { - if (l_Adapter->m_Extension.m_TapIsRunning && !l_Adapter->m_Extension.m_TapOpens) - { - l_Adapter->m_Extension.m_TapOpens = 1; - succeeded = TRUE; - } - - if (succeeded) - { - INCREMENT_STAT (l_Adapter->m_Extension.m_NumTapOpens); - p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS; - p_IRP->IoStatus.Information = 0; - } - else - { - DEBUGP (("[%s] TAP is presently unavailable (m_TapOpens=%d)\n", - NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens)); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; - p_IRP->IoStatus.Information = 0; - } - - RELEASE_MUTEX (&l_Adapter->m_Extension.m_OpenCloseMutex); - } - else - { - DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n", - NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens)); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; - p_IRP->IoStatus.Information = 0; - } - - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - break; - } - - //----------------------------------------------------------- - // User mode thread called CloseHandle() on the tap device - //----------------------------------------------------------- - case IRP_MJ_CLOSE: - { - BOOLEAN mutex_succeeded; - - DEBUGP (("[%s] [TAP] release [%d.%d] close/cleanup request\n", - NAME (l_Adapter), TAP_DRIVER_MAJOR_VERSION, - TAP_DRIVER_MINOR_VERSION)); - - ACQUIRE_MUTEX_ADAPTIVE (&l_Adapter->m_Extension.m_OpenCloseMutex, mutex_succeeded); - if (mutex_succeeded) - { - l_Adapter->m_Extension.m_TapOpens = 0; - FlushQueues (&l_Adapter->m_Extension); - SetMediaStatus (l_Adapter, FALSE); - RELEASE_MUTEX (&l_Adapter->m_Extension.m_OpenCloseMutex); - } - else - { - DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n", - NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens)); - NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; - p_IRP->IoStatus.Information = 0; - } - - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - break; - } - - //------------------ - // Strange Request - //------------------ - default: - { - //NOTE_ERROR (); - p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL; - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - break; - } - } - - return l_Status; -} - -//============================================================= -// CompleteIRP is normally called with an adapter -> userspace -// network packet and an IRP (Pending I/O request) from userspace. -// -// The IRP will normally represent a queued overlapped read -// operation from userspace that is in a wait state. -// -// Use the ethernet packet to satisfy the IRP. -//============================================================= - -NTSTATUS - CompleteIRP (IN PIRP p_IRP, - IN TapPacketPointer p_PacketBuffer, - IN CCHAR PriorityBoost) -{ - NTSTATUS l_Status = STATUS_UNSUCCESSFUL; - - int offset; - int len; - - MYASSERT (p_IRP); - MYASSERT (p_PacketBuffer); - - IoSetCancelRoutine (p_IRP, NULL); // Disable cancel routine - - //------------------------------------------- - // While p_PacketBuffer always contains a - // full ethernet packet, including the - // ethernet header, in point-to-point mode, - // we only want to return the IPv4 - // component. - //------------------------------------------- - - if (p_PacketBuffer->m_SizeFlags & TP_TUN) - { - offset = ETHERNET_HEADER_SIZE; - len = (int) (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK) - ETHERNET_HEADER_SIZE; - } - else - { - offset = 0; - len = (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK); - } - - if (len < 0 || (int) p_IRP->IoStatus.Information < len) - { - p_IRP->IoStatus.Information = 0; - p_IRP->IoStatus.Status = STATUS_BUFFER_OVERFLOW; - NOTE_ERROR (); - } - else - { - p_IRP->IoStatus.Information = len; - p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS; - - __try - { - NdisMoveMemory (p_IRP->AssociatedIrp.SystemBuffer, - p_PacketBuffer->m_Data + offset, - len); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - NOTE_ERROR (); - p_IRP->IoStatus.Status = STATUS_UNSUCCESSFUL; - p_IRP->IoStatus.Information = 0; - } - } - - __try - { - NdisFreeMemory (p_PacketBuffer, - TAP_PACKET_SIZE (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK), - 0); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - } - - if (l_Status == STATUS_SUCCESS) - { - IoCompleteRequest (p_IRP, PriorityBoost); - } - else - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); - - return l_Status; -} - -//============================================== -// IRPs get cancelled for a number of reasons. -// -// The TAP device could be closed by userspace -// when there are still pending read operations. -// -// The user could disable the TAP adapter in the -// network connections control panel, while the -// device is still open by a process. -//============================================== -VOID - CancelIRPCallback (IN PDEVICE_OBJECT p_DeviceObject, - IN PIRP p_IRP) -{ - TapAdapterPointer l_Adapter = LookupAdapterInInstanceList (p_DeviceObject); - CancelIRP (l_Adapter ? &l_Adapter->m_Extension : NULL, p_IRP, TRUE); -} - -VOID - CancelIRP (TapExtensionPointer p_Extension, - IN PIRP p_IRP, - BOOLEAN callback) -{ - BOOLEAN exists = FALSE; - - MYASSERT (p_IRP); - - if (p_Extension) - { - NdisAcquireSpinLock (&p_Extension->m_QueueLock); - exists = (QueueExtract (p_Extension->m_IrpQueue, p_IRP) == p_IRP); - NdisReleaseSpinLock (&p_Extension->m_QueueLock); - } - else - exists = TRUE; - - if (exists) - { - IoSetCancelRoutine (p_IRP, NULL); - p_IRP->IoStatus.Status = STATUS_CANCELLED; - p_IRP->IoStatus.Information = 0; - } - - if (callback) - IoReleaseCancelSpinLock (p_IRP->CancelIrql); - - if (exists) - IoCompleteRequest (p_IRP, IO_NO_INCREMENT); -} - -//=========================================== -// Exhaust packet, IRP, and injection queues. -//=========================================== -VOID - FlushQueues (TapExtensionPointer p_Extension) -{ - PIRP l_IRP; - TapPacketPointer l_PacketBuffer; - - MYASSERT (p_Extension); - MYASSERT (p_Extension->m_TapDevice); - - while (TRUE) - { - NdisAcquireSpinLock (&p_Extension->m_QueueLock); - l_IRP = (PIRP)QueuePop (p_Extension->m_IrpQueue); - NdisReleaseSpinLock (&p_Extension->m_QueueLock); - if (l_IRP) - { - CancelIRP (NULL, l_IRP, FALSE); - } - else - break; - } - - while (TRUE) - { - NdisAcquireSpinLock (&p_Extension->m_QueueLock); - l_PacketBuffer = (TapPacketPointer)QueuePop (p_Extension->m_PacketQueue); - NdisReleaseSpinLock (&p_Extension->m_QueueLock); - if (l_PacketBuffer) - { - MemFree (l_PacketBuffer, TAP_PACKET_SIZE (l_PacketBuffer->m_SizeFlags & TP_SIZE_MASK)); - } - else - break; - } -} - -//=================================================== -// Tell Windows whether the TAP device should be -// considered "connected" or "disconnected". -//=================================================== -VOID - SetMediaStatus (TapAdapterPointer p_Adapter, BOOLEAN state) -{ - if (p_Adapter->m_MediaState != state && !p_Adapter->m_MediaStateAlwaysConnected) - { - if (state) - NdisMIndicateStatus (p_Adapter->m_MiniportAdapterHandle, - NDIS_STATUS_MEDIA_CONNECT, NULL, 0); - else - NdisMIndicateStatus (p_Adapter->m_MiniportAdapterHandle, - NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0); - - NdisMIndicateStatusComplete (p_Adapter->m_MiniportAdapterHandle); - p_Adapter->m_MediaState = state; - } -} diff --git a/windows/TapDriver/types.h b/windows/TapDriver/types.h deleted file mode 100644 index 94587a64..00000000 --- a/windows/TapDriver/types.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * TAP-Windows -- A kernel driver to provide virtual tap - * device functionality on Windows. - * - * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. - * - * This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., - * and is released under the GPL version 2 (see below). - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program (see the file COPYING included with this - * distribution); if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TAP_TYPES_DEFINED -#define TAP_TYPES_DEFINED - -typedef struct _Queue -{ - ULONG base; - ULONG size; - ULONG capacity; - ULONG max_size; - PVOID data[]; -} Queue; - -typedef struct _TapAdapter; -typedef struct _TapPacket; - -typedef union _TapAdapterQuery -{ - NDIS_HARDWARE_STATUS m_HardwareStatus; - NDIS_MEDIUM m_Medium; - NDIS_PHYSICAL_MEDIUM m_PhysicalMedium; - UCHAR m_MacAddress [6]; - UCHAR m_Buffer [256]; - ULONG m_Long; - USHORT m_Short; - UCHAR m_Byte; -} -TapAdapterQuery, *TapAdapterQueryPointer; - -typedef struct _TapExtension -{ - // TAP device object and packet queues - Queue *m_PacketQueue, *m_IrpQueue; - PDEVICE_OBJECT m_TapDevice; - NDIS_HANDLE m_TapDeviceHandle; - ULONG m_TapOpens; - - // Used to lock packet queues - NDIS_SPIN_LOCK m_QueueLock; - BOOLEAN m_AllocatedSpinlocks; - - // Used to bracket open/close - // state changes. - MUTEX m_OpenCloseMutex; - - // True if device has been permanently halted - BOOLEAN m_Halt; - - // TAP device name - unsigned char *m_TapName; - UNICODE_STRING m_UnicodeLinkName; - BOOLEAN m_CreatedUnicodeLinkName; - - // Used for device status ioctl only - const char *m_LastErrorFilename; - int m_LastErrorLineNumber; - LONG m_NumTapOpens; - - // Flags - BOOLEAN m_TapIsRunning; - BOOLEAN m_CalledTapDeviceFreeResources; -} -TapExtension, *TapExtensionPointer; - -typedef struct _TapPacket - { -# define TAP_PACKET_SIZE(data_size) (sizeof (TapPacket) + (data_size)) -# define TP_TUN 0x80000000 -# define TP_SIZE_MASK (~TP_TUN) - ULONG m_SizeFlags; - UCHAR m_Data []; // m_Data must be the last struct member - } -TapPacket, *TapPacketPointer; - -typedef struct _TapAdapter -{ -# define NAME(a) ((a)->m_NameAnsi.Buffer) - ANSI_STRING m_NameAnsi; - MACADDR m_MAC; - BOOLEAN m_InterfaceIsRunning; - NDIS_HANDLE m_MiniportAdapterHandle; - LONG m_Rx, m_Tx, m_RxErr, m_TxErr; - NDIS_MEDIUM m_Medium; - ULONG m_Lookahead; - ULONG m_MTU; - - // TRUE if adapter should always be - // "connected" even when device node - // is not open by a userspace process. - BOOLEAN m_MediaStateAlwaysConnected; - - // TRUE if device is "connected" - BOOLEAN m_MediaState; - - // Adapter power state - char m_DeviceState; - - // Help to tear down the adapter by keeping - // some state information on allocated - // resources. - BOOLEAN m_CalledAdapterFreeResources; - BOOLEAN m_RegisteredAdapterShutdownHandler; - - // Multicast list info - NDIS_SPIN_LOCK m_MCLock; - BOOLEAN m_MCLockAllocated; - ULONG m_MCListSize; - MC_LIST m_MCList; - - // Information on the TAP device - TapExtension m_Extension; -} TapAdapter, *TapAdapterPointer; - -#endif diff --git a/windows/TapDriver/zttap200.inf b/windows/TapDriver/zttap200.inf deleted file mode 100644 index fdd05f53..00000000 --- a/windows/TapDriver/zttap200.inf +++ /dev/null @@ -1,78 +0,0 @@ -[Version] -Signature="$WINDOWS NT$" -Class=Net -ClassGuid={4d36e972-e325-11ce-bfc1-08002be10318} -Provider=%Provider% -CatalogFile=zttap200.cat - -[Strings] -DeviceDescription = "ZeroTier One Virtual Network Port" -Provider = "ZeroTier Networks LLC" - -; To build for x86, take NTamd64 off this and off the named section manually, build, then put it back! -[Manufacturer] -%Provider%=zttap200,NTamd64 - -[zttap200] -%DeviceDescription%=zttap200.ndi,zttap200 - -[ztTap200.NTamd64] -%DeviceDescription%=zttap200.ndi,zttap200 - -[zttap200.ndi] -CopyFiles = zttap200.driver,zttap200.files -AddReg = zttap200.reg -AddReg = zttap200.params.reg -Characteristics = 0x81 - -[zttap200.ndi.Services] -AddService = zttap200, 2, zttap200.service - -[zttap200.reg] -HKR, Ndi, Service, 0, "zttap200" -HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" -HKR, Ndi\Interfaces, LowerRange, 0, "ethernet" -HKR, , Manufacturer, 0, "%Provider%" -HKR, , ProductName, 0, "%DeviceDescription%" - -[zttap200.params.reg] -HKR, Ndi\params\MTU, ParamDesc, 0, "MTU" -HKR, Ndi\params\MTU, Type, 0, "int" -HKR, Ndi\params\MTU, Default, 0, "2800" -HKR, Ndi\params\MTU, Optional, 0, "0" -HKR, Ndi\params\MTU, Min, 0, "100" -HKR, Ndi\params\MTU, Max, 0, "2800" -HKR, Ndi\params\MTU, Step, 0, "1" -HKR, Ndi\params\MediaStatus, ParamDesc, 0, "Media Status" -HKR, Ndi\params\MediaStatus, Type, 0, "enum" -HKR, Ndi\params\MediaStatus, Default, 0, "0" -HKR, Ndi\params\MediaStatus, Optional, 0, "0" -HKR, Ndi\params\MediaStatus\enum, "0", 0, "Application Controlled" -HKR, Ndi\params\MediaStatus\enum, "1", 0, "Always Connected" -HKR, Ndi\params\MAC, ParamDesc, 0, "MAC Address" -HKR, Ndi\params\MAC, Type, 0, "edit" -HKR, Ndi\params\MAC, Optional, 0, "1" - -[zttap200.service] -DisplayName = %DeviceDescription% -ServiceType = 1 -StartType = 3 -ErrorControl = 1 -LoadOrderGroup = NDIS -ServiceBinary = %12%\zttap200.sys - -[SourceDisksNames] -1 = %DeviceDescription%, zttap200.sys - -[SourceDisksFiles] -zttap200.sys = 1 - -[DestinationDirs] -zttap200.files = 11 -zttap200.driver = 12 - -[zttap200.files] -; - -[zttap200.driver] -zttap200.sys,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK diff --git a/windows/ZeroTierOne.sln b/windows/ZeroTierOne.sln index d86c212a..a2c65bd9 100644 --- a/windows/ZeroTierOne.sln +++ b/windows/ZeroTierOne.sln @@ -1,8 +1,6 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TapDriver", "TapDriver\TapDriver.vcxproj", "{689210B1-467C-4850-BB7D-2E10D5B4A3DA}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZeroTierOne", "ZeroTierOne\ZeroTierOne.vcxproj", "{B00A4957-5977-4AC1-9EF4-571DC27EADA2}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TapDriver6", "TapDriver6\TapDriver6.vcxproj", "{43BA7584-D4DB-4F7C-90FC-E2B18A68A213}" @@ -70,109 +68,6 @@ Global Win8 Release|x86 = Win8 Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.CD_ROM|Any CPU.ActiveCfg = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.CD_ROM|Mixed Platforms.ActiveCfg = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.CD_ROM|Mixed Platforms.Build.0 = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.CD_ROM|Mixed Platforms.Deploy.0 = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.CD_ROM|Win32.ActiveCfg = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.CD_ROM|Win32.Build.0 = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.CD_ROM|Win32.Deploy.0 = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.CD_ROM|x64.ActiveCfg = Win8 Release|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.CD_ROM|x64.Build.0 = Win8 Release|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.CD_ROM|x64.Deploy.0 = Win8 Release|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.CD_ROM|x86.ActiveCfg = Vista Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|Any CPU.ActiveCfg = Win8 Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|Mixed Platforms.ActiveCfg = Win8 Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|Win32.ActiveCfg = Win7 Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|Win32.Build.0 = Win7 Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|Win32.Deploy.0 = Win7 Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|x64.ActiveCfg = Win7 Debug|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|x64.Build.0 = Win7 Debug|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|x64.Deploy.0 = Win7 Debug|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|x86.ActiveCfg = Vista Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.DVD-5|Any CPU.ActiveCfg = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.DVD-5|Mixed Platforms.ActiveCfg = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.DVD-5|Mixed Platforms.Build.0 = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.DVD-5|Mixed Platforms.Deploy.0 = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.DVD-5|Win32.ActiveCfg = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.DVD-5|Win32.Build.0 = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.DVD-5|Win32.Deploy.0 = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.DVD-5|x64.ActiveCfg = Win8 Release|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.DVD-5|x64.Build.0 = Win8 Release|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.DVD-5|x64.Deploy.0 = Win8 Release|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.DVD-5|x86.ActiveCfg = Vista Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|Any CPU.ActiveCfg = Win7 Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|Mixed Platforms.ActiveCfg = Win7 Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|Win32.ActiveCfg = Win8 Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|Win32.Build.0 = Win8 Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|Win32.Deploy.0 = Win8 Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|x64.ActiveCfg = Win7 Release|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|x64.Build.0 = Win7 Release|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|x64.Deploy.0 = Win7 Release|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|x86.ActiveCfg = Win8 Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.SingleImage|Any CPU.ActiveCfg = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.SingleImage|Mixed Platforms.ActiveCfg = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.SingleImage|Mixed Platforms.Build.0 = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.SingleImage|Mixed Platforms.Deploy.0 = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.SingleImage|Win32.ActiveCfg = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.SingleImage|Win32.Build.0 = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.SingleImage|Win32.Deploy.0 = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.SingleImage|x64.ActiveCfg = Win8 Release|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.SingleImage|x64.Build.0 = Win8 Release|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.SingleImage|x64.Deploy.0 = Win8 Release|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.SingleImage|x86.ActiveCfg = Vista Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|Any CPU.ActiveCfg = Vista Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|Mixed Platforms.ActiveCfg = Vista Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|Win32.ActiveCfg = Vista Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|Win32.Build.0 = Vista Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|Win32.Deploy.0 = Vista Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|x64.ActiveCfg = Vista Debug|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|x64.Build.0 = Vista Debug|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|x64.Deploy.0 = Vista Debug|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|x86.ActiveCfg = Vista Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|Any CPU.ActiveCfg = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|Mixed Platforms.ActiveCfg = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|Win32.ActiveCfg = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|Win32.Build.0 = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|Win32.Deploy.0 = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|x64.ActiveCfg = Vista Release|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|x64.Build.0 = Vista Release|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|x64.Deploy.0 = Vista Release|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|x86.ActiveCfg = Vista Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|Any CPU.ActiveCfg = Win7 Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|Mixed Platforms.ActiveCfg = Win7 Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|Win32.ActiveCfg = Win7 Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|Win32.Build.0 = Win7 Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|Win32.Deploy.0 = Win7 Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|x64.ActiveCfg = Win7 Debug|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|x64.Build.0 = Win7 Debug|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|x64.Deploy.0 = Win7 Debug|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|x86.ActiveCfg = Win7 Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Release|Any CPU.ActiveCfg = Win7 Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Release|Mixed Platforms.ActiveCfg = Win7 Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Release|Win32.ActiveCfg = Win7 Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Release|Win32.Build.0 = Win7 Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Release|Win32.Deploy.0 = Win7 Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Release|x64.ActiveCfg = Win7 Release|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Release|x86.ActiveCfg = Win7 Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|Any CPU.ActiveCfg = Win8 Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|Mixed Platforms.ActiveCfg = Win8 Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|Win32.ActiveCfg = Win8 Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|Win32.Build.0 = Win8 Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|Win32.Deploy.0 = Win8 Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|x64.ActiveCfg = Win8 Debug|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|x64.Build.0 = Win8 Debug|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|x64.Deploy.0 = Win8 Debug|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|x86.ActiveCfg = Win8 Debug|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|Any CPU.ActiveCfg = Win8 Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|Mixed Platforms.ActiveCfg = Win8 Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|Win32.ActiveCfg = Win8 Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|Win32.Build.0 = Win8 Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|Win32.Deploy.0 = Win8 Release|Win32 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|x64.ActiveCfg = Win8 Release|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|x64.Build.0 = Win8 Release|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|x64.Deploy.0 = Win8 Release|x64 - {689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|x86.ActiveCfg = Win8 Release|Win32 {B00A4957-5977-4AC1-9EF4-571DC27EADA2}.CD_ROM|Any CPU.ActiveCfg = Release|Win32 {B00A4957-5977-4AC1-9EF4-571DC27EADA2}.CD_ROM|Mixed Platforms.ActiveCfg = Release|Win32 {B00A4957-5977-4AC1-9EF4-571DC27EADA2}.CD_ROM|Mixed Platforms.Build.0 = Release|Win32 -- cgit v1.2.3 From 90f9415107fded22346bfa94f98afa73c6c2811e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 13 Nov 2015 09:11:12 -0800 Subject: Update installer to drag along a net-install binary for .NET 4.5 that it runs if .NET 4.5 is not present... because yes we have to install Microsoft's own flagship runtime under some conditions. (Rare, but present.) --- ext/installfiles/windows/ZeroTier One.aip | 32 ++++++++++++++------- ext/installfiles/windows/dotNetFx45_Full_setup.exe | Bin 0 -> 1005568 bytes 2 files changed, 21 insertions(+), 11 deletions(-) create mode 100644 ext/installfiles/windows/dotNetFx45_Full_setup.exe (limited to 'ext') diff --git a/ext/installfiles/windows/ZeroTier One.aip b/ext/installfiles/windows/ZeroTier One.aip index 8732e9f3..3042005e 100644 --- a/ext/installfiles/windows/ZeroTier One.aip +++ b/ext/installfiles/windows/ZeroTier One.aip @@ -1,5 +1,5 @@ - + @@ -7,6 +7,7 @@ + @@ -23,10 +24,10 @@ - + - + @@ -56,8 +57,9 @@ - + + @@ -69,11 +71,12 @@ - + - + + @@ -87,7 +90,7 @@ - + @@ -144,8 +147,10 @@ + + @@ -194,6 +199,7 @@ + @@ -225,6 +231,7 @@ + @@ -243,7 +250,7 @@ - + @@ -253,14 +260,17 @@ + + - + + @@ -328,10 +338,10 @@ - + - + diff --git a/ext/installfiles/windows/dotNetFx45_Full_setup.exe b/ext/installfiles/windows/dotNetFx45_Full_setup.exe new file mode 100644 index 00000000..365b870b Binary files /dev/null and b/ext/installfiles/windows/dotNetFx45_Full_setup.exe differ -- cgit v1.2.3 From 220552af62cb229d70a62851a35c6b38a0bc3345 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 16 Nov 2015 14:30:25 -0800 Subject: GitHub issue #241 -- and also some appearance updates. Eventually this might get replaced by a native Mac app. --- .../bin/ZeroTier One.app/Contents/Info.plist | 21 +- .../ZeroTier One.app/Contents/MacOS/ZeroTier One | Bin 194640 -> 152736 bytes .../Contents/Resources/en.lproj/MainMenu.nib | Bin 25733 -> 25269 bytes .../Contents/Resources/en.lproj/Window.nib | Bin 3785 -> 3723 bytes .../Contents/_CodeSignature/CodeResources | 8 +- .../src/MacGap.xcodeproj/project.pbxproj | 7 +- .../src/MacGap/AppDelegate.m | 28 +- .../src/MacGap/Classes/ContentView.m | 10 +- .../src/MacGap/MacGap-Info.plist | 11 +- .../src/MacGap/en.lproj/Window.xib | 381 +++------------------ ui/ZeroTierNetwork.jsx | 24 +- ui/ZeroTierNode.jsx | 74 +--- ui/zerotier.css | 98 +----- ui/ztui.min.js | 2 +- 14 files changed, 129 insertions(+), 535 deletions(-) (limited to 'ext') diff --git a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Info.plist b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Info.plist index a11af6d9..c67923c7 100644 --- a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Info.plist +++ b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Info.plist @@ -3,7 +3,7 @@ BuildMachineOSBuild - 14E46 + 15B42 CFBundleDevelopmentRegion en CFBundleExecutable @@ -22,26 +22,35 @@ 1.0 CFBundleSignature ???? + CFBundleSupportedPlatforms + + MacOSX + CFBundleVersion 1 DTCompiler com.apple.compilers.llvm.clang.1_0 DTPlatformBuild - 6E35b + 7B1005 DTPlatformVersion GM DTSDKBuild - 14D125 + 15A278 DTSDKName - macosx10.10 + macosx10.11 DTXcode - 0640 + 0711 DTXcodeBuild - 6E35b + 7B1005 LSApplicationCategoryType public.app-category.utilities LSMinimumSystemVersion 10.7 + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + NSMainNibFile MainMenu NSPrincipalClass diff --git a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/MacOS/ZeroTier One b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/MacOS/ZeroTier One index 429efc0b..ba15bca9 100755 Binary files a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/MacOS/ZeroTier One and b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/MacOS/ZeroTier One differ diff --git a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/MainMenu.nib b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/MainMenu.nib index 4cd319b2..bac7faa7 100644 Binary files a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/MainMenu.nib and b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/MainMenu.nib differ diff --git a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Window.nib b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Window.nib index 559409d9..69258da6 100644 Binary files a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Window.nib and b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Window.nib differ diff --git a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/_CodeSignature/CodeResources b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/_CodeSignature/CodeResources index bd79b1f3..14556923 100644 --- a/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/_CodeSignature/CodeResources +++ b/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/_CodeSignature/CodeResources @@ -30,7 +30,7 @@ hash - kkFJZm0JXF9gTUF2keyMJQ9p9SY= + 8JZXf4/3df3LD+o74Y8WM0dV8io= optional @@ -39,7 +39,7 @@ hash - 42zB9+COYMmPW0WlnU1juN2B9SA= + 7dgumnPDtoIzhi9QoaFhDvCo9ys= optional @@ -73,7 +73,7 @@ hash - kkFJZm0JXF9gTUF2keyMJQ9p9SY= + 8JZXf4/3df3LD+o74Y8WM0dV8io= optional @@ -82,7 +82,7 @@ hash - 42zB9+COYMmPW0WlnU1juN2B9SA= + 7dgumnPDtoIzhi9QoaFhDvCo9ys= optional diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.pbxproj b/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.pbxproj index 08d72d06..775c5964 100644 --- a/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.pbxproj +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.pbxproj @@ -269,7 +269,7 @@ FAE451B114BA79C600190544 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0450; + LastUpgradeCheck = 0710; ORGANIZATIONNAME = Twitter; }; buildConfigurationList = FAE451B414BA79C600190544 /* Build configuration list for PBXProject "MacGap" */; @@ -374,9 +374,9 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_ENABLE_OBJC_ARC = YES; COPY_PHASE_STRIP = NO; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_OBJC_EXCEPTIONS = YES; @@ -402,7 +402,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_ENABLE_OBJC_ARC = YES; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; @@ -434,6 +433,7 @@ GCC_VERSION = ""; INFOPLIST_FILE = "MacGap/MacGap-Info.plist"; MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_BUNDLE_IDENTIFIER = "com.zerotier.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "ZeroTier One"; SDKROOT = macosx; WRAPPER_EXTENSION = app; @@ -455,6 +455,7 @@ GCC_VERSION = ""; INFOPLIST_FILE = "MacGap/MacGap-Info.plist"; MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_BUNDLE_IDENTIFIER = "com.zerotier.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "ZeroTier One"; SDKROOT = macosx; WRAPPER_EXTENSION = app; diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.m index 3e25ca13..45923bb3 100644 --- a/ext/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.m +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.m @@ -32,6 +32,7 @@ - (void) applicationDidFinishLaunching:(NSNotification *)aNotification { char buf[16384],userAuthTokenPath[4096]; + struct stat systemAuthTokenStat,userAuthTokenStat; FILE *pf = fopen("/Library/Application Support/ZeroTier/One/zerotier-one.port","r"); long port = 9993; // default @@ -50,14 +51,27 @@ const char *homeDir = getenv("HOME"); if (homeDir) { snprintf(userAuthTokenPath,sizeof(userAuthTokenPath),"%s/Library/Application Support/ZeroTier/One/authtoken.secret",homeDir); - pf = fopen(userAuthTokenPath,"r"); - if (pf) { - long n = fread(buf,1,sizeof(buf)-1,pf); - if (n > 0) { - buf[n] = (char)0; - snprintf(url,sizeof(url),"http://127.0.0.1:%ld/index.html?authToken=%s",port,buf); + + bool userAuthTokenOutOfDate = false; + memset(&systemAuthTokenStat,0,sizeof(systemAuthTokenStat)); + memset(&userAuthTokenStat,0,sizeof(userAuthTokenStat)); + if (stat("/Library/Application Support/ZeroTier/One/authtoken.secret",&systemAuthTokenStat) == 0) { + if (stat(userAuthTokenPath,&userAuthTokenStat) == 0) { + if (userAuthTokenStat.st_mtimespec.tv_sec < systemAuthTokenStat.st_mtimespec.tv_sec) + userAuthTokenOutOfDate = true; + } + } + + if (!userAuthTokenOutOfDate) { + pf = fopen(userAuthTokenPath,"r"); + if (pf) { + long n = fread(buf,1,sizeof(buf)-1,pf); + if (n > 0) { + buf[n] = (char)0; + snprintf(url,sizeof(url),"http://127.0.0.1:%ld/index.html?authToken=%s",port,buf); + } + fclose(pf); } - fclose(pf); } } diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.m b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.m index 24e58cd1..6558a191 100644 --- a/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.m +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.m @@ -39,11 +39,11 @@ [self.webView setApplicationNameForUserAgent: @"MacGap"]; self.delegate = [[WebViewDelegate alloc] initWithMenu:[NSApp mainMenu]]; - [self.webView setFrameLoadDelegate:self.delegate]; - [self.webView setUIDelegate:self.delegate]; - [self.webView setResourceLoadDelegate:self.delegate]; - [self.webView setDownloadDelegate:self.delegate]; - [self.webView setPolicyDelegate:self.delegate]; +// [self.webView setFrameLoadDelegate:self.delegate]; +// [self.webView setUIDelegate:self.delegate]; +// [self.webView setResourceLoadDelegate:self.delegate]; +// [self.webView setDownloadDelegate:self.delegate]; +// [self.webView setPolicyDelegate:self.delegate]; [self.webView setDrawsBackground:NO]; [self.webView setShouldCloseWithWindow:NO]; diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Info.plist b/ext/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Info.plist index 7e10a7a6..7f71ea22 100644 --- a/ext/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Info.plist +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Info.plist @@ -2,14 +2,14 @@ - CFBundleIconFile - ZeroTierIcon CFBundleDevelopmentRegion en CFBundleExecutable ZeroTier One + CFBundleIconFile + ZeroTierIcon CFBundleIdentifier - com.zerotier.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -30,5 +30,10 @@ MainMenu NSPrincipalClass NSApplication + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Window.xib b/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Window.xib index 70d0c57b..2c46b79f 100644 --- a/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Window.xib +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Window.xib @@ -1,337 +1,44 @@ - - - - 1070 - 11C74 - 1938 - 1138.23 - 567.00 - - YES - - YES - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.WebKitIBPlugin - - - YES - 1938 - 822 - - - - YES - NSWindowTemplate - NSView - NSCustomObject - WebView - - - YES - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.WebKitIBPlugin - - - PluginDependencyRecalculationVersion - - - - YES - - WindowController - - - FirstResponder - - - NSApplication - - - 15 - 2 - {{196, 240}, {758, 410}} - 544735232 - Window - NSWindow - - - - - 256 - - YES - - - 274 - - YES - - YES - Apple HTML pasteboard type - Apple PDF pasteboard type - Apple PICT pasteboard type - Apple URL pasteboard type - Apple Web Archive pasteboard type - NSColor pasteboard type - NSFilenamesPboardType - NSStringPboardType - NeXT RTFD pasteboard type - NeXT Rich Text Format v1.0 pasteboard type - NeXT TIFF v4.0 pasteboard type - WebURLsWithTitlesPboardType - public.png - public.url - public.url-name - - - {758, 410} - - - - 2 - _NS:51 - - - - - - YES - - YES - WebKitDefaultFixedFontSize - WebKitDefaultFontSize - WebKitMinimumFontSize - - - YES - - - - - - - YES - YES - - - {758, 410} - - - - - {{0, 0}, {1920, 1178}} - {10000000000000, 10000000000000} - 128 - YES - - - - - YES - - - contentView - - - - 23 - - - - window - - - - 25 - - - - title: contentView.webView.mainFrameTitle - - - - - - title: contentView.webView.mainFrameTitle - title - contentView.webView.mainFrameTitle - 2 - - - 31 - - - - webView - - - - 19 - - - - - YES - - 0 - - YES - - - - - - -2 - - - File's Owner - - - -1 - - - First Responder - - - -3 - - - Application - - - 1 - - - YES - - - - - - 2 - - - YES - - - - - - 5 - - - - - - - YES - - YES - -1.IBPluginDependency - -2.IBPluginDependency - -3.IBPluginDependency - 1.IBPluginDependency - 1.IBWindowTemplateEditedContentRect - 1.NSWindowTemplate.visibleAtLaunch - 2.CustomClassName - 2.IBPluginDependency - 5.IBPluginDependency - - - YES - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{357, 418}, {480, 270}} - - ContentView - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.WebKitIBPlugin - - - - YES - - - - - - YES - - - - - 31 - - - - YES - - ContentView - NSView - - webView - WebView - - - webView - - webView - WebView - - - - IBProjectSource - ./Classes/ContentView.h - - - - WebView - - reloadFromOrigin: - id - - - reloadFromOrigin: - - reloadFromOrigin: - id - - - - IBProjectSource - ./Classes/WebView.h - - - - WindowController - NSWindowController - - contentView - ContentView - - - contentView - - contentView - ContentView - - - - IBProjectSource - ./Classes/WindowController.h - - - - - 0 - IBCocoaFramework - - com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 - - - YES - 3 - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui/ZeroTierNetwork.jsx b/ui/ZeroTierNetwork.jsx index 4b37d888..f842d758 100644 --- a/ui/ZeroTierNetwork.jsx +++ b/ui/ZeroTierNetwork.jsx @@ -4,19 +4,17 @@ var ZeroTierNetwork = React.createClass({ }, leaveNetwork: function(event) { - if (confirm("Are you sure you want to leave this network?")) { - Ajax.call({ - url: 'network/'+this.props.nwid+'?auth='+this.props.authToken, - cache: false, - type: 'DELETE', - success: function(data) { - if (this.props.onNetworkDeleted) - this.props.onNetworkDeleted(this.props.nwid); - }.bind(this), - error: function(error) { - }.bind(this) - }); - } + Ajax.call({ + url: 'network/'+this.props.nwid+'?auth='+this.props.authToken, + cache: false, + type: 'DELETE', + success: function(data) { + if (this.props.onNetworkDeleted) + this.props.onNetworkDeleted(this.props.nwid); + }.bind(this), + error: function(error) { + }.bind(this) + }); event.preventDefault(); }, diff --git a/ui/ZeroTierNode.jsx b/ui/ZeroTierNode.jsx index 49d73460..b4c29220 100644 --- a/ui/ZeroTierNode.jsx +++ b/ui/ZeroTierNode.jsx @@ -122,7 +122,6 @@ var ZeroTierNode = React.createClass({ }, componentDidMount: function() { - this.tabIndex = 0; this.updateAll(); this.updateIntervalId = setInterval(this.updateAll,2500); }, @@ -130,74 +129,19 @@ var ZeroTierNode = React.createClass({ clearInterval(this.updateIntervalId); }, render: function() { - /* We implement tabs in a very simple way here with a React JSX conditional. The tabIndex - * local variable indicates the tab, and switching it determines which set of things we - * render in the main middle portion. On tab switch calls forceUpdate(). */ return (
-
   - - -
- { - (this.tabIndex === 1) ? ( -
-
-
Address
-
Version
-
Latency
-
Data Paths
-
Last Unicast
-
Last Multicast
-
Role
-
- { - this.state._peers.map(function(peer) { - return ( -
-
{peer['address']}
-
{(peer['version'] === '-1.-1.-1') ? '-' : peer['version']}
-
{peer['latency']}
-
- { - (peer['paths'].length === 0) ? ( -
- ) : ( -
- { - peer['paths'].map(function(path) { - var cn = ((path.active)||(path.fixed)) ? (path.preferred ? 'peerPathPreferred' : 'peerPathActive') : 'peerPathInactive'; - return ( -
{path.address}  {this.ago(path.lastSend)}/{this.ago(path.lastReceive)}
- ); - }.bind(this)) - } -
- ) - } -
-
{this.ago(peer['lastUnicastFrame'])}
-
{this.ago(peer['lastMulticastFrame'])}
-
{peer['role']}
-
- ); - }.bind(this)) - } -
- ) : ( -
- { - this.state._networks.map(function(network) { - network['authToken'] = this.props.authToken; - network['onNetworkDeleted'] = this.handleNetworkDelete; - return React.createElement('div',{className: 'network',key: network.nwid},React.createElement(ZeroTierNetwork,network)); - }.bind(this)) - } -
- ) - } +
+ { + this.state._networks.map(function(network) { + network['authToken'] = this.props.authToken; + network['onNetworkDeleted'] = this.handleNetworkDelete; + return React.createElement('div',{className: 'network',key: network.nwid},React.createElement(ZeroTierNetwork,network)); + }.bind(this)) + } +
diff --git a/ui/zerotier.css b/ui/zerotier.css index cde5cea8..e5c58838 100644 --- a/ui/zerotier.css +++ b/ui/zerotier.css @@ -25,34 +25,6 @@ html,body { display: table; } -.zeroTierNode > .top { - width: 100%; - overflow: hidden; - display: table-row; - white-space: nowrap; - background: #234447; - color: #ffffff; - padding: 0; - margin: 0; -} -.zeroTierNode > .top button { - display: inline-block; - padding: 0.25rem 0.75rem 0.25rem 0.75rem; - color: #ffffff; - margin: 0; - border: 0; - outline: none; - background: #234447; - font-size: 12pt; - cursor: pointer; -} -.zeroTierNode > .top button:hover { - background: #91a2a3; -} -.zeroTierNode > .top button:disabled { - background: #91a2a3; -} - .zeroTierNode > .middle { width: 100%; height: 100%; @@ -65,6 +37,7 @@ html,body { width: 100%; height: 100%; display: table-cell; + border-bottom: 1px solid #000000; } .zeroTierNode > .middle > .middleCell > .middleScroll { display: block; @@ -87,76 +60,19 @@ html,body { border-collapse: collapse; } .zeroTierNode > .middle > .middleCell > .middleScroll > .networks > .network { - display: inline-block; + display: block; + border-top: 0.12rem solid #dddddd; + border-bottom: 0.12rem solid #dddddd; padding: 0.25rem; - margin: 0.25rem 0 0 1%; - min-width: 31%; - max-width: 98%; - border: 1px solid #234447; - background: #ffffff; -} -.zeroTierNode > .middle > .middleCell > .middleScroll > .peers { - display: table; - width: 100%; - margin: 0; - border-collapse: collapse; -} -.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peer { - width: 100%; - display: table-row; background: #ffffff; } -.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peer:nth-child(odd) { - background: #f3f3f3; -} -.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peer:nth-child(even) { -} -.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peer .peerPathActive { - font-size: 8pt; - color: #555555; - font-style: italic; - font-family: monospace; - white-space: nowrap; -} -.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peer .peerPathPreferred { - font-size: 8pt; - color: #000000; - font-family: monospace; - white-space: nowrap; -} -.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peer .peerPathInactive { - font-size: 8pt; - font-family: monospace; - color: #aaaaaa; - font-style: italic; - text-decoration: line-through; - white-space: nowrap; -} -.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peer > .f { - display: table-cell; - padding: 0.05rem 0.15rem 0.05rem 0.15rem; - font-size: 8pt; -} -.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peerHeader { - width: 100%; - font-size: 8pt; - display: table-row; - background: #ffffff; - border-bottom: 1px solid #000000; -} -.zeroTierNode > .middle > .middleCell > .middleScroll > .peers > .peerHeader > .f { - display: table-cell; - font-size: 8pt; - padding: 0.05rem 0.15rem 0.05rem 0.15rem; - font-weight: bold; -} .zeroTierNode > .bottom { font-size: 12pt; width: 100%; overflow: hidden; display: table-row; - background: #234447; + background: #000000; color: #ffffff; } .zeroTierNode > .bottom > .left { @@ -233,7 +149,7 @@ html,body { .zeroTierNetwork .networkInfo .networkId { font-size: 11pt; font-family: monospace; - color: #91a2a3; + color: #000000; } .zeroTierNetwork .networkInfo .networkName { padding: 0 0 0 1rem; @@ -271,7 +187,7 @@ html,body { .zeroTierNetwork .leaveNetworkButton { padding: 0.25rem 0.5rem 0.25rem 0.5rem; margin: 0.25rem 0 0 0; - font-size: 10pt; + font-size: 9pt; background: #ffffff; outline: none; background: #ffb354; diff --git a/ui/ztui.min.js b/ui/ztui.min.js index dbde7734..17982839 100644 --- a/ui/ztui.min.js +++ b/ui/ztui.min.js @@ -1 +1 @@ -var ZeroTierNetwork=React.createClass({displayName:"ZeroTierNetwork",getInitialState:function(){return{}},leaveNetwork:function(e){confirm("Are you sure you want to leave this network?")&&Ajax.call({url:"network/"+this.props.nwid+"?auth="+this.props.authToken,cache:!1,type:"DELETE",success:function(e){this.props.onNetworkDeleted&&this.props.onNetworkDeleted(this.props.nwid)}.bind(this),error:function(e){}.bind(this)}),e.preventDefault()},render:function(){return React.createElement("div",{className:"zeroTierNetwork"},React.createElement("div",{className:"networkInfo"},React.createElement("span",{className:"networkId"},this.props.nwid)," ",React.createElement("span",{className:"networkName"},this.props.name)),React.createElement("div",{className:"networkProps"},React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Status"),React.createElement("div",{className:"value"},this.props.status)),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Type"),React.createElement("div",{className:"value"},this.props.type)),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"MAC"),React.createElement("div",{className:"value zeroTierAddress"},this.props.mac)),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"MTU"),React.createElement("div",{className:"value"},this.props.mtu)),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Broadcast"),React.createElement("div",{className:"value"},this.props.broadcastEnabled?"ENABLED":"DISABLED")),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Bridging"),React.createElement("div",{className:"value"},this.props.bridge?"ACTIVE":"DISABLED")),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Device"),React.createElement("div",{className:"value"},this.props.portDeviceName?this.props.portDeviceName:"(none)")),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Managed IPs"),React.createElement("div",{className:"value ipList"},this.props.assignedAddresses.map(function(e){return React.createElement("div",{key:e,className:"ipAddress"},e)})))),React.createElement("button",{type:"button",className:"leaveNetworkButton",onClick:this.leaveNetwork},"Leave Network"))}}); var ZeroTierNode=React.createClass({displayName:"ZeroTierNode",getInitialState:function(){return{address:"----------",online:!1,version:"_._._",_networks:[],_peers:[]}},ago:function(e){if(e>0){var t=Math.round((Date.now()-e)/1e3);return t>0?t:0}return 0},updatePeers:function(){Ajax.call({url:"peer?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(e){var t=JSON.parse(e);Array.isArray(t)&&this.setState({_peers:t})}}.bind(this),error:function(){}.bind(this)})},updateNetworks:function(){Ajax.call({url:"network?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(e){var t=JSON.parse(e);Array.isArray(t)&&this.setState({_networks:t})}}.bind(this),error:function(){}.bind(this)})},updateAll:function(){Ajax.call({url:"status?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(this.alertedToFailure=!1,e){var t=JSON.parse(e);this.setState(t),document.title="ZeroTier One ["+t.address+"]"}this.updateNetworks(),this.updatePeers()}.bind(this),error:function(){this.setState(this.getInitialState()),this.alertedToFailure||(this.alertedToFailure=!0,alert("Authorization token invalid or ZeroTier One service not running."))}.bind(this)})},joinNetwork:function(e){e.preventDefault(),this.networkToJoin&&16===this.networkToJoin.length?Ajax.call({url:"network/"+this.networkToJoin+"?auth="+this.props.authToken,cache:!1,type:"POST",success:function(e){this.networkToJoin="",this.networkInputElement&&(this.networkInputElement.value=""),this.updateNetworks()}.bind(this),error:function(){}.bind(this)}):alert("To join a network, enter its 16-digit network ID.")},handleNetworkIdEntry:function(e){this.networkInputElement=e.target;var t=this.networkInputElement.value;if(t){t=t.toLowerCase();for(var a="",s=0;ss;++s)"0123456789abcdef".indexOf(t.charAt(s))>=0&&(a+=t.charAt(s));this.networkToJoin=a,this.networkInputElement.value=a}else this.networkToJoin="",this.networkInputElement.value=""},handleNetworkDelete:function(e){for(var t=[],a=0;a0){var t=Math.round((Date.now()-e)/1e3);return t>0?t:0}return 0},updatePeers:function(){Ajax.call({url:"peer?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(e){var t=JSON.parse(e);Array.isArray(t)&&this.setState({_peers:t})}}.bind(this),error:function(){}.bind(this)})},updateNetworks:function(){Ajax.call({url:"network?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(e){var t=JSON.parse(e);Array.isArray(t)&&this.setState({_networks:t})}}.bind(this),error:function(){}.bind(this)})},updateAll:function(){Ajax.call({url:"status?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(this.alertedToFailure=!1,e){var t=JSON.parse(e);this.setState(t),document.title="ZeroTier One ["+t.address+"]"}this.updateNetworks(),this.updatePeers()}.bind(this),error:function(){this.setState(this.getInitialState()),this.alertedToFailure||(this.alertedToFailure=!0,alert("Authorization token invalid or ZeroTier One service not running."))}.bind(this)})},joinNetwork:function(e){e.preventDefault(),this.networkToJoin&&16===this.networkToJoin.length?Ajax.call({url:"network/"+this.networkToJoin+"?auth="+this.props.authToken,cache:!1,type:"POST",success:function(e){this.networkToJoin="",this.networkInputElement&&(this.networkInputElement.value=""),this.updateNetworks()}.bind(this),error:function(){}.bind(this)}):alert("To join a network, enter its 16-digit network ID.")},handleNetworkIdEntry:function(e){this.networkInputElement=e.target;var t=this.networkInputElement.value;if(t){t=t.toLowerCase();for(var n="",a=0;aa;++a)"0123456789abcdef".indexOf(t.charAt(a))>=0&&(n+=t.charAt(a));this.networkToJoin=n,this.networkInputElement.value=n}else this.networkToJoin="",this.networkInputElement.value=""},handleNetworkDelete:function(e){for(var t=[],n=0;n Date: Mon, 16 Nov 2015 16:19:24 -0800 Subject: Use new OSX tap version, and update OSX install scripts. --- .../com.zerotier.tap.kext/Contents/Info.plist | 36 ------- .../com.zerotier.tap.kext/Contents/MacOS/tap | Bin 50496 -> 0 bytes .../Contents/_CodeSignature/CodeResources | 105 --------------------- ext/bin/tap-mac/tap.kext.old/Contents/Info.plist | 36 +++++++ ext/bin/tap-mac/tap.kext.old/Contents/MacOS/tap | Bin 0 -> 81240 bytes .../Contents/_CodeSignature/CodeDirectory | Bin 0 -> 145 bytes .../Contents/_CodeSignature/CodeRequirements | Bin 0 -> 176 bytes .../Contents/_CodeSignature/CodeResources | 105 +++++++++++++++++++++ .../Contents/_CodeSignature/CodeSignature | Bin 0 -> 8578 bytes ext/bin/tap-mac/tap.kext/Contents/Info.plist | 2 +- ext/bin/tap-mac/tap.kext/Contents/MacOS/tap | Bin 81240 -> 50496 bytes .../tap.kext/Contents/_CodeSignature/CodeDirectory | Bin 145 -> 0 bytes .../Contents/_CodeSignature/CodeRequirements | Bin 176 -> 0 bytes .../tap.kext/Contents/_CodeSignature/CodeSignature | Bin 8578 -> 0 bytes ext/installfiles/mac/launch.sh | 10 +- ext/installfiles/mac/postinst.sh | 6 +- 16 files changed, 147 insertions(+), 153 deletions(-) delete mode 100644 ext/bin/tap-mac/com.zerotier.tap.kext/Contents/Info.plist delete mode 100755 ext/bin/tap-mac/com.zerotier.tap.kext/Contents/MacOS/tap delete mode 100644 ext/bin/tap-mac/com.zerotier.tap.kext/Contents/_CodeSignature/CodeResources create mode 100644 ext/bin/tap-mac/tap.kext.old/Contents/Info.plist create mode 100755 ext/bin/tap-mac/tap.kext.old/Contents/MacOS/tap create mode 100644 ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeDirectory create mode 100644 ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeRequirements create mode 100644 ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeResources create mode 100644 ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeSignature delete mode 100644 ext/bin/tap-mac/tap.kext/Contents/_CodeSignature/CodeDirectory delete mode 100644 ext/bin/tap-mac/tap.kext/Contents/_CodeSignature/CodeRequirements delete mode 100644 ext/bin/tap-mac/tap.kext/Contents/_CodeSignature/CodeSignature (limited to 'ext') diff --git a/ext/bin/tap-mac/com.zerotier.tap.kext/Contents/Info.plist b/ext/bin/tap-mac/com.zerotier.tap.kext/Contents/Info.plist deleted file mode 100644 index c20eefa5..00000000 --- a/ext/bin/tap-mac/com.zerotier.tap.kext/Contents/Info.plist +++ /dev/null @@ -1,36 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - tap - CFBundleIdentifier - com.zerotier.tap - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - tap - CFBundlePackageType - KEXT - CFBundleShortVersionString - 20150118 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - OSBundleLibraries - - com.apple.kpi.mach - 8.0 - com.apple.kpi.bsd - 8.0 - com.apple.kpi.libkern - 8.0 - com.apple.kpi.unsupported - 8.0 - - - - diff --git a/ext/bin/tap-mac/com.zerotier.tap.kext/Contents/MacOS/tap b/ext/bin/tap-mac/com.zerotier.tap.kext/Contents/MacOS/tap deleted file mode 100755 index 48bf9625..00000000 Binary files a/ext/bin/tap-mac/com.zerotier.tap.kext/Contents/MacOS/tap and /dev/null differ diff --git a/ext/bin/tap-mac/com.zerotier.tap.kext/Contents/_CodeSignature/CodeResources b/ext/bin/tap-mac/com.zerotier.tap.kext/Contents/_CodeSignature/CodeResources deleted file mode 100644 index 0710b400..00000000 --- a/ext/bin/tap-mac/com.zerotier.tap.kext/Contents/_CodeSignature/CodeResources +++ /dev/null @@ -1,105 +0,0 @@ - - - - - files - - files2 - - rules - - ^Resources/ - - ^Resources/.*\.lproj/ - - optional - - weight - 1000 - - ^Resources/.*\.lproj/locversion.plist$ - - omit - - weight - 1100 - - ^version.plist$ - - - rules2 - - .*\.dSYM($|/) - - weight - 11 - - ^(.*/)?\.DS_Store$ - - omit - - weight - 2000 - - ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ - - nested - - weight - 10 - - ^.* - - ^Info\.plist$ - - omit - - weight - 20 - - ^PkgInfo$ - - omit - - weight - 20 - - ^Resources/ - - weight - 20 - - ^Resources/.*\.lproj/ - - optional - - weight - 1000 - - ^Resources/.*\.lproj/locversion.plist$ - - omit - - weight - 1100 - - ^[^/]+$ - - nested - - weight - 10 - - ^embedded\.provisionprofile$ - - weight - 20 - - ^version\.plist$ - - weight - 20 - - - - diff --git a/ext/bin/tap-mac/tap.kext.old/Contents/Info.plist b/ext/bin/tap-mac/tap.kext.old/Contents/Info.plist new file mode 100644 index 00000000..45c2839a --- /dev/null +++ b/ext/bin/tap-mac/tap.kext.old/Contents/Info.plist @@ -0,0 +1,36 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + tap + CFBundleIdentifier + com.zerotier.tap + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + tap + CFBundlePackageType + KEXT + CFBundleShortVersionString + 20131028 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + OSBundleLibraries + + com.apple.kpi.mach + 8.0 + com.apple.kpi.bsd + 8.0 + com.apple.kpi.libkern + 8.0 + com.apple.kpi.unsupported + 8.0 + + + + diff --git a/ext/bin/tap-mac/tap.kext.old/Contents/MacOS/tap b/ext/bin/tap-mac/tap.kext.old/Contents/MacOS/tap new file mode 100755 index 00000000..6a9021a7 Binary files /dev/null and b/ext/bin/tap-mac/tap.kext.old/Contents/MacOS/tap differ diff --git a/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeDirectory b/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeDirectory new file mode 100644 index 00000000..58c421c2 Binary files /dev/null and b/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeDirectory differ diff --git a/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeRequirements b/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeRequirements new file mode 100644 index 00000000..1df93129 Binary files /dev/null and b/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeRequirements differ diff --git a/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeResources b/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeResources new file mode 100644 index 00000000..0710b400 --- /dev/null +++ b/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeResources @@ -0,0 +1,105 @@ + + + + + files + + files2 + + rules + + ^Resources/ + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ + + nested + + weight + 10 + + ^.* + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^Resources/ + + weight + 20 + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^[^/]+$ + + nested + + weight + 10 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeSignature b/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeSignature new file mode 100644 index 00000000..64429727 Binary files /dev/null and b/ext/bin/tap-mac/tap.kext.old/Contents/_CodeSignature/CodeSignature differ diff --git a/ext/bin/tap-mac/tap.kext/Contents/Info.plist b/ext/bin/tap-mac/tap.kext/Contents/Info.plist index 45c2839a..c20eefa5 100644 --- a/ext/bin/tap-mac/tap.kext/Contents/Info.plist +++ b/ext/bin/tap-mac/tap.kext/Contents/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType KEXT CFBundleShortVersionString - 20131028 + 20150118 CFBundleSignature ???? CFBundleVersion diff --git a/ext/bin/tap-mac/tap.kext/Contents/MacOS/tap b/ext/bin/tap-mac/tap.kext/Contents/MacOS/tap index 6a9021a7..48bf9625 100755 Binary files a/ext/bin/tap-mac/tap.kext/Contents/MacOS/tap and b/ext/bin/tap-mac/tap.kext/Contents/MacOS/tap differ diff --git a/ext/bin/tap-mac/tap.kext/Contents/_CodeSignature/CodeDirectory b/ext/bin/tap-mac/tap.kext/Contents/_CodeSignature/CodeDirectory deleted file mode 100644 index 58c421c2..00000000 Binary files a/ext/bin/tap-mac/tap.kext/Contents/_CodeSignature/CodeDirectory and /dev/null differ diff --git a/ext/bin/tap-mac/tap.kext/Contents/_CodeSignature/CodeRequirements b/ext/bin/tap-mac/tap.kext/Contents/_CodeSignature/CodeRequirements deleted file mode 100644 index 1df93129..00000000 Binary files a/ext/bin/tap-mac/tap.kext/Contents/_CodeSignature/CodeRequirements and /dev/null differ diff --git a/ext/bin/tap-mac/tap.kext/Contents/_CodeSignature/CodeSignature b/ext/bin/tap-mac/tap.kext/Contents/_CodeSignature/CodeSignature deleted file mode 100644 index 64429727..00000000 Binary files a/ext/bin/tap-mac/tap.kext/Contents/_CodeSignature/CodeSignature and /dev/null differ diff --git a/ext/installfiles/mac/launch.sh b/ext/installfiles/mac/launch.sh index ef22ccbd..41c4b9c8 100755 --- a/ext/installfiles/mac/launch.sh +++ b/ext/installfiles/mac/launch.sh @@ -1,15 +1,7 @@ #!/bin/bash zthome="/Library/Application Support/ZeroTier/One" -export PATH="/bin:/usr/bin:/sbin:/usr/sbin:$zthome" - -# If the app has been deleted, uninstall the service -cd "$zthome" -if [ -L './shutdownIfUnreadable' -a ! -f "`readlink ./shutdownIfUnreadable`" ]; then - rm -f /tmp/ZeroTierOneUninstall.log - /bin/bash "$zthome/uninstall.sh" >/tmp/ZeroTierOneUninstall.log 2>&1 - exit 0 -fi +export PATH="$zthome:/bin:/usr/bin:/sbin:/usr/sbin" # Launch ZeroTier One (not as daemon... launchd monitors it) exec zerotier-one diff --git a/ext/installfiles/mac/postinst.sh b/ext/installfiles/mac/postinst.sh index 987e131b..47d9ddd9 100755 --- a/ext/installfiles/mac/postinst.sh +++ b/ext/installfiles/mac/postinst.sh @@ -6,10 +6,12 @@ launchctl unload /Library/LaunchDaemons/com.zerotier.one.plist >>/dev/null 2>&1 cd "/Library/Application Support/ZeroTier/One" rm -rf node.log node.log.old root-topology shutdownIfUnreadable autoupdate.log updates.d +chown -R 0 tap.kext +chgrp -R 0 tap.kext if [ ! -f authtoken.secret ]; then head -c 4096 /dev/urandom | md5 | head -c 24 >authtoken.secret - chown root authtoken.secret - chgrp wheel authtoken.secret + chown 0 authtoken.secret + chgrp 0 authtoken.secret chmod 0600 authtoken.secret fi rm -f zerotier-cli zerotier-idtool -- cgit v1.2.3 From a13a21377c2d028d81b5cb26567ebe23bbb2e891 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 16 Nov 2015 18:18:08 -0800 Subject: Delete pre-build miniupnpc for Linux and Mac -- will add Make rules to build from source and include source in ext/ --- ext/bin/miniupnpc/linux-arm32/libminiupnpc.a | Bin 62698 -> 0 bytes ext/bin/miniupnpc/linux-x64/libminiupnpc.a | Bin 87942 -> 0 bytes ext/bin/miniupnpc/linux-x86/libminiupnpc.a | Bin 67782 -> 0 bytes ext/bin/miniupnpc/mac-x64/libminiupnpc.a | Bin 95616 -> 0 bytes 4 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 ext/bin/miniupnpc/linux-arm32/libminiupnpc.a delete mode 100644 ext/bin/miniupnpc/linux-x64/libminiupnpc.a delete mode 100644 ext/bin/miniupnpc/linux-x86/libminiupnpc.a delete mode 100644 ext/bin/miniupnpc/mac-x64/libminiupnpc.a (limited to 'ext') diff --git a/ext/bin/miniupnpc/linux-arm32/libminiupnpc.a b/ext/bin/miniupnpc/linux-arm32/libminiupnpc.a deleted file mode 100644 index 4983f628..00000000 Binary files a/ext/bin/miniupnpc/linux-arm32/libminiupnpc.a and /dev/null differ diff --git a/ext/bin/miniupnpc/linux-x64/libminiupnpc.a b/ext/bin/miniupnpc/linux-x64/libminiupnpc.a deleted file mode 100644 index 270366e0..00000000 Binary files a/ext/bin/miniupnpc/linux-x64/libminiupnpc.a and /dev/null differ diff --git a/ext/bin/miniupnpc/linux-x86/libminiupnpc.a b/ext/bin/miniupnpc/linux-x86/libminiupnpc.a deleted file mode 100644 index 99cbef21..00000000 Binary files a/ext/bin/miniupnpc/linux-x86/libminiupnpc.a and /dev/null differ diff --git a/ext/bin/miniupnpc/mac-x64/libminiupnpc.a b/ext/bin/miniupnpc/mac-x64/libminiupnpc.a deleted file mode 100644 index 3c2e528d..00000000 Binary files a/ext/bin/miniupnpc/mac-x64/libminiupnpc.a and /dev/null differ -- cgit v1.2.3 From cf6164e8477aaa65edd07d136ef1991288feff99 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 16 Nov 2015 18:28:55 -0800 Subject: Build libminiupnpc from source now, and update version. --- .gitignore | 3 + ext/miniupnpc/CMakeLists.txt | 178 +++ ext/miniupnpc/Changelog.txt | 667 +++++++++++ ext/miniupnpc/LICENSE | 27 + ext/miniupnpc/MANIFEST.in | 5 + ext/miniupnpc/Makefile | 379 ++++++ ext/miniupnpc/Makefile.mingw | 98 ++ ext/miniupnpc/README | 61 + ext/miniupnpc/VERSION | 1 + ext/miniupnpc/apiversions.txt | 167 +++ ext/miniupnpc/codelength.h | 54 + ext/miniupnpc/connecthostport.c | 264 +++++ ext/miniupnpc/connecthostport.h | 18 + ext/miniupnpc/external-ip.sh | 4 + ext/miniupnpc/igd_desc_parse.c | 123 ++ ext/miniupnpc/igd_desc_parse.h | 49 + ext/miniupnpc/java/JavaBridgeTest.java | 97 ++ ext/miniupnpc/java/testjava.bat | 8 + ext/miniupnpc/java/testjava.sh | 8 + ext/miniupnpc/listdevices.c | 110 ++ ext/miniupnpc/man3/miniupnpc.3 | 55 + ext/miniupnpc/mingw32make.bat | 8 + ext/miniupnpc/minihttptestserver.c | 655 +++++++++++ ext/miniupnpc/minisoap.c | 123 ++ ext/miniupnpc/minisoap.h | 15 + ext/miniupnpc/minissdpc.c | 849 ++++++++++++++ ext/miniupnpc/minissdpc.h | 58 + ext/miniupnpc/miniupnpc.c | 684 +++++++++++ ext/miniupnpc/miniupnpc.def | 45 + ext/miniupnpc/miniupnpc.h | 152 +++ ext/miniupnpc/miniupnpc_declspec.h | 21 + ext/miniupnpc/miniupnpcmodule.c | 695 +++++++++++ ext/miniupnpc/miniupnpcstrings.h.cmake | 15 + ext/miniupnpc/miniupnpcstrings.h.in | 23 + ext/miniupnpc/miniupnpctypes.h | 19 + ext/miniupnpc/miniwget.c | 626 ++++++++++ ext/miniupnpc/miniwget.h | 30 + ext/miniupnpc/minixml.c | 229 ++++ ext/miniupnpc/minixml.h | 37 + ext/miniupnpc/minixmlvalid.c | 163 +++ ext/miniupnpc/msvc/miniupnpc.sln | 29 + ext/miniupnpc/msvc/miniupnpc.vcproj | 283 +++++ ext/miniupnpc/msvc/upnpc-static.vcproj | 195 +++ ext/miniupnpc/portlistingparse.c | 172 +++ ext/miniupnpc/portlistingparse.h | 65 + ext/miniupnpc/pymoduletest.py | 88 ++ ext/miniupnpc/receivedata.c | 105 ++ ext/miniupnpc/receivedata.h | 19 + ext/miniupnpc/setup.py | 28 + ext/miniupnpc/setupmingw32.py | 28 + ext/miniupnpc/testdesc/linksys_WAG200G_desc.values | 14 + ext/miniupnpc/testdesc/linksys_WAG200G_desc.xml | 110 ++ ext/miniupnpc/testdesc/new_LiveBox_desc.values | 20 + ext/miniupnpc/testdesc/new_LiveBox_desc.xml | 90 ++ ext/miniupnpc/testigddescparse.c | 187 +++ ext/miniupnpc/testminiwget.c | 53 + ext/miniupnpc/testminiwget.sh | 96 ++ ext/miniupnpc/testminixml.c | 89 ++ ext/miniupnpc/testportlistingparse.c | 151 +++ .../testreplyparse/DeletePortMapping.namevalue | 3 + ext/miniupnpc/testreplyparse/DeletePortMapping.xml | 6 + .../testreplyparse/GetExternalIPAddress.namevalue | 2 + .../testreplyparse/GetExternalIPAddress.xml | 2 + .../GetSpecificPortMappingEntryReq.namevalue | 3 + .../GetSpecificPortMappingEntryReq.xml | 3 + .../GetSpecificPortMappingEntryResp.namevalue | 5 + .../GetSpecificPortMappingEntryResp.xml | 2 + .../SetDefaultConnectionService.namevalue | 1 + .../testreplyparse/SetDefaultConnectionService.xml | 1 + ext/miniupnpc/testreplyparse/readme.txt | 7 + ext/miniupnpc/testupnpigd.py | 84 ++ ext/miniupnpc/testupnpreplyparse.c | 96 ++ ext/miniupnpc/testupnpreplyparse.sh | 14 + ext/miniupnpc/updateminiupnpcstrings.sh | 53 + ext/miniupnpc/upnpc.c | 833 +++++++++++++ ext/miniupnpc/upnpcommands.c | 1237 ++++++++++++++++++++ ext/miniupnpc/upnpcommands.h | 348 ++++++ ext/miniupnpc/upnpdev.c | 23 + ext/miniupnpc/upnpdev.h | 36 + ext/miniupnpc/upnperrors.c | 107 ++ ext/miniupnpc/upnperrors.h | 26 + ext/miniupnpc/upnpreplyparse.c | 197 ++++ ext/miniupnpc/upnpreplyparse.h | 63 + ext/miniupnpc/wingenminiupnpcstrings.c | 83 ++ make-mac.mk | 14 +- 85 files changed, 11889 insertions(+), 5 deletions(-) create mode 100644 ext/miniupnpc/CMakeLists.txt create mode 100644 ext/miniupnpc/Changelog.txt create mode 100644 ext/miniupnpc/LICENSE create mode 100644 ext/miniupnpc/MANIFEST.in create mode 100644 ext/miniupnpc/Makefile create mode 100644 ext/miniupnpc/Makefile.mingw create mode 100644 ext/miniupnpc/README create mode 100644 ext/miniupnpc/VERSION create mode 100644 ext/miniupnpc/apiversions.txt create mode 100644 ext/miniupnpc/codelength.h create mode 100644 ext/miniupnpc/connecthostport.c create mode 100644 ext/miniupnpc/connecthostport.h create mode 100755 ext/miniupnpc/external-ip.sh create mode 100644 ext/miniupnpc/igd_desc_parse.c create mode 100644 ext/miniupnpc/igd_desc_parse.h create mode 100644 ext/miniupnpc/java/JavaBridgeTest.java create mode 100755 ext/miniupnpc/java/testjava.bat create mode 100755 ext/miniupnpc/java/testjava.sh create mode 100644 ext/miniupnpc/listdevices.c create mode 100644 ext/miniupnpc/man3/miniupnpc.3 create mode 100644 ext/miniupnpc/mingw32make.bat create mode 100644 ext/miniupnpc/minihttptestserver.c create mode 100644 ext/miniupnpc/minisoap.c create mode 100644 ext/miniupnpc/minisoap.h create mode 100644 ext/miniupnpc/minissdpc.c create mode 100644 ext/miniupnpc/minissdpc.h create mode 100644 ext/miniupnpc/miniupnpc.c create mode 100644 ext/miniupnpc/miniupnpc.def create mode 100644 ext/miniupnpc/miniupnpc.h create mode 100644 ext/miniupnpc/miniupnpc_declspec.h create mode 100644 ext/miniupnpc/miniupnpcmodule.c create mode 100644 ext/miniupnpc/miniupnpcstrings.h.cmake create mode 100644 ext/miniupnpc/miniupnpcstrings.h.in create mode 100644 ext/miniupnpc/miniupnpctypes.h create mode 100644 ext/miniupnpc/miniwget.c create mode 100644 ext/miniupnpc/miniwget.h create mode 100644 ext/miniupnpc/minixml.c create mode 100644 ext/miniupnpc/minixml.h create mode 100644 ext/miniupnpc/minixmlvalid.c create mode 100644 ext/miniupnpc/msvc/miniupnpc.sln create mode 100644 ext/miniupnpc/msvc/miniupnpc.vcproj create mode 100644 ext/miniupnpc/msvc/upnpc-static.vcproj create mode 100644 ext/miniupnpc/portlistingparse.c create mode 100644 ext/miniupnpc/portlistingparse.h create mode 100644 ext/miniupnpc/pymoduletest.py create mode 100644 ext/miniupnpc/receivedata.c create mode 100644 ext/miniupnpc/receivedata.h create mode 100644 ext/miniupnpc/setup.py create mode 100644 ext/miniupnpc/setupmingw32.py create mode 100644 ext/miniupnpc/testdesc/linksys_WAG200G_desc.values create mode 100644 ext/miniupnpc/testdesc/linksys_WAG200G_desc.xml create mode 100644 ext/miniupnpc/testdesc/new_LiveBox_desc.values create mode 100644 ext/miniupnpc/testdesc/new_LiveBox_desc.xml create mode 100644 ext/miniupnpc/testigddescparse.c create mode 100644 ext/miniupnpc/testminiwget.c create mode 100755 ext/miniupnpc/testminiwget.sh create mode 100644 ext/miniupnpc/testminixml.c create mode 100644 ext/miniupnpc/testportlistingparse.c create mode 100644 ext/miniupnpc/testreplyparse/DeletePortMapping.namevalue create mode 100644 ext/miniupnpc/testreplyparse/DeletePortMapping.xml create mode 100644 ext/miniupnpc/testreplyparse/GetExternalIPAddress.namevalue create mode 100644 ext/miniupnpc/testreplyparse/GetExternalIPAddress.xml create mode 100644 ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue create mode 100644 ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml create mode 100644 ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue create mode 100644 ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml create mode 100644 ext/miniupnpc/testreplyparse/SetDefaultConnectionService.namevalue create mode 100644 ext/miniupnpc/testreplyparse/SetDefaultConnectionService.xml create mode 100644 ext/miniupnpc/testreplyparse/readme.txt create mode 100755 ext/miniupnpc/testupnpigd.py create mode 100644 ext/miniupnpc/testupnpreplyparse.c create mode 100755 ext/miniupnpc/testupnpreplyparse.sh create mode 100755 ext/miniupnpc/updateminiupnpcstrings.sh create mode 100644 ext/miniupnpc/upnpc.c create mode 100644 ext/miniupnpc/upnpcommands.c create mode 100644 ext/miniupnpc/upnpcommands.h create mode 100644 ext/miniupnpc/upnpdev.c create mode 100644 ext/miniupnpc/upnpdev.h create mode 100644 ext/miniupnpc/upnperrors.c create mode 100644 ext/miniupnpc/upnperrors.h create mode 100644 ext/miniupnpc/upnpreplyparse.c create mode 100644 ext/miniupnpc/upnpreplyparse.h create mode 100644 ext/miniupnpc/wingenminiupnpcstrings.c (limited to 'ext') diff --git a/.gitignore b/.gitignore index f7a41b45..0ddbbb88 100755 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,9 @@ Thumbs.db *.pid *.pkg *.o +*.a +*.dylib +*.so *.o-* *.core *.deb diff --git a/ext/miniupnpc/CMakeLists.txt b/ext/miniupnpc/CMakeLists.txt new file mode 100644 index 00000000..dacb1f69 --- /dev/null +++ b/ext/miniupnpc/CMakeLists.txt @@ -0,0 +1,178 @@ +cmake_minimum_required (VERSION 2.6) + +project (miniupnpc C) +set (MINIUPNPC_VERSION 1.9) +set (MINIUPNPC_API_VERSION 15) + +if (NOT CMAKE_BUILD_TYPE) + if (WIN32) + set (DEFAULT_BUILD_TYPE MinSizeRel) + else (WIN32) + set (DEFAULT_BUILD_TYPE RelWithDebInfo) + endif(WIN32) + set (CMAKE_BUILD_TYPE ${DEFAULT_BUILD_TYPE} CACHE STRING + "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." + FORCE) +endif() + +option (UPNPC_BUILD_STATIC "Build static library" TRUE) +option (UPNPC_BUILD_SHARED "Build shared library" TRUE) +if (NOT WIN32) + option (UPNPC_BUILD_TESTS "Build test executables" TRUE) +endif (NOT WIN32) +option (NO_GETADDRINFO "Define NO_GETADDRINFO" FALSE) + +mark_as_advanced (NO_GETADDRINFO) + +if (NO_GETADDRINFO) + add_definitions (-DNO_GETADDRINFO) +endif (NO_GETADDRINFO) + +if (NOT WIN32) + add_definitions (-DMINIUPNPC_SET_SOCKET_TIMEOUT) + add_definitions (-D_BSD_SOURCE -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200112L) +else (NOT WIN32) + add_definitions (-D_WIN32_WINNT=0x0501) # XP or higher for getnameinfo and friends +endif (NOT WIN32) + +if (CMAKE_SYSTEM_NAME STREQUAL "Darwin") + add_definitions (-D_DARWIN_C_SOURCE) +endif () + +# Set compiler specific build flags +if (CMAKE_COMPILER_IS_GNUC) + # Set our own default flags at first run. + if (NOT CONFIGURED) + + if (NOT CMAKE_SYSTEM_NAME STREQUAL "AmigaOS") + set (_PIC -fPIC) + endif (CMAKE_SYSTEM_NAME STREQUAL "AmigaOS") + + set (CMAKE_C_FLAGS "${_PIC} -Wall $ENV{CFLAGS}" # CMAKE_C_FLAGS gets appended to the other C flags + CACHE STRING "Flags used by the C compiler during normal builds." FORCE) + set (CMAKE_C_FLAGS_DEBUG "-g -DDDEBUG" + CACHE STRING "Flags used by the C compiler during debug builds." FORCE) + set (CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG" + CACHE STRING "Flags used by the C compiler during release builds." FORCE) + set (CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g -DNDEBUG" + CACHE STRING "Flags used by the C compiler during release builds." FORCE) + set (CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG" + CACHE STRING "Flags used by the C compiler during release builds." FORCE) + + endif (NOT CONFIGURED) +endif () + +configure_file (${CMAKE_SOURCE_DIR}/miniupnpcstrings.h.cmake ${CMAKE_BINARY_DIR}/miniupnpcstrings.h) +include_directories (${CMAKE_BINARY_DIR}) + +set (MINIUPNPC_SOURCES + igd_desc_parse.c + miniupnpc.c + minixml.c + minisoap.c + minissdpc.c + miniwget.c + upnpc.c + upnpcommands.c + upnpdev.c + upnpreplyparse.c + upnperrors.c + connecthostport.c + portlistingparse.c + receivedata.c +) + +if (NOT WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL "AmigaOS") + set (MINIUPNPC_SOURCES ${MINIUPNPC_SOURCES} minissdpc.c) +endif (NOT WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL "AmigaOS") + +if (WIN32) + set_source_files_properties (${MINIUPNPC_SOURCES} PROPERTIES + COMPILE_DEFINITIONS "MINIUPNP_STATICLIB;MINIUPNP_EXPORTS" + ) +endif (WIN32) + +if (WIN32) + find_library (WINSOCK2_LIBRARY NAMES ws2_32 WS2_32 Ws2_32) + find_library (IPHLPAPI_LIBRARY NAMES iphlpapi) + set (LDLIBS ${WINSOCK2_LIBRARY} ${IPHLPAPI_LIBRARY} ${LDLIBS}) +#elseif (CMAKE_SYSTEM_NAME STREQUAL "Solaris") +# find_library (SOCKET_LIBRARY NAMES socket) +# find_library (NSL_LIBRARY NAMES nsl) +# find_library (RESOLV_LIBRARY NAMES resolv) +# set (LDLIBS ${SOCKET_LIBRARY} ${NSL_LIBRARY} ${RESOLV_LIBRARY} ${LDLIBS}) +endif (WIN32) + +if (NOT UPNPC_BUILD_STATIC AND NOT UPNPC_BUILD_SHARED) + message (FATAL "Both shared and static libraries are disabled!") +endif (NOT UPNPC_BUILD_STATIC AND NOT UPNPC_BUILD_SHARED) + +if (UPNPC_BUILD_STATIC) + add_library (upnpc-static STATIC ${MINIUPNPC_SOURCES}) + set_target_properties (upnpc-static PROPERTIES OUTPUT_NAME "miniupnpc") + target_link_libraries (upnpc-static ${LDLIBS}) + set (UPNPC_INSTALL_TARGETS ${UPNPC_INSTALL_TARGETS} upnpc-static) + set (UPNPC_LIBRARY_TARGET upnpc-static) +endif (UPNPC_BUILD_STATIC) + +if (UPNPC_BUILD_SHARED) + add_library (upnpc-shared SHARED ${MINIUPNPC_SOURCES}) + set_target_properties (upnpc-shared PROPERTIES OUTPUT_NAME "miniupnpc") + set_target_properties (upnpc-shared PROPERTIES VERSION ${MINIUPNPC_VERSION}) + set_target_properties (upnpc-shared PROPERTIES SOVERSION ${MINIUPNPC_API_VERSION}) + target_link_libraries (upnpc-shared ${LDLIBS}) + set (UPNPC_INSTALL_TARGETS ${UPNPC_INSTALL_TARGETS} upnpc-shared) + set (UPNPC_LIBRARY_TARGET upnpc-shared) +endif (UPNPC_BUILD_SHARED) + +if (UPNPC_BUILD_TESTS) + add_executable (testminixml testminixml.c minixml.c igd_desc_parse.c) + target_link_libraries (testminixml ${LDLIBS}) + + add_executable (minixmlvalid minixmlvalid.c minixml.c) + target_link_libraries (minixmlvalid ${LDLIBS}) + + add_executable (testupnpreplyparse testupnpreplyparse.c + minixml.c upnpreplyparse.c) + target_link_libraries (testupnpreplyparse ${LDLIBS}) + + add_executable (testigddescparse testigddescparse.c + igd_desc_parse.c minixml.c miniupnpc.c miniwget.c minissdpc.c + upnpcommands.c upnpreplyparse.c minisoap.c connecthostport.c + portlistingparse.c receivedata.c + ) + target_link_libraries (testigddescparse ${LDLIBS}) + + add_executable (testminiwget testminiwget.c + miniwget.c miniupnpc.c minisoap.c upnpcommands.c minissdpc.c + upnpreplyparse.c minixml.c igd_desc_parse.c connecthostport.c + portlistingparse.c receivedata.c + ) + target_link_libraries (testminiwget ${LDLIBS}) + +# set (UPNPC_INSTALL_TARGETS ${UPNPC_INSTALL_TARGETS} testminixml minixmlvalid testupnpreplyparse testigddescparse testminiwget) +endif (UPNPC_BUILD_TESTS) + + +install (TARGETS ${UPNPC_INSTALL_TARGETS} + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib${LIB_SUFFIX} + ARCHIVE DESTINATION lib${LIB_SUFFIX} +) +install (FILES + miniupnpc.h + miniwget.h + upnpcommands.h + igd_desc_parse.h + upnpreplyparse.h + upnperrors.h + upnpdev.h + miniupnpctypes.h + portlistingparse.h + miniupnpc_declspec.h + DESTINATION include/miniupnpc +) + +set (CONFIGURED YES CACHE INTERNAL "") + +# vim: ts=2:sw=2 diff --git a/ext/miniupnpc/Changelog.txt b/ext/miniupnpc/Changelog.txt new file mode 100644 index 00000000..bef61f59 --- /dev/null +++ b/ext/miniupnpc/Changelog.txt @@ -0,0 +1,667 @@ +$Id: Changelog.txt,v 1.219 2015/10/26 17:05:06 nanard Exp $ +miniUPnP client Changelog. + +2015/10/26: + snprintf() overflow check. check overflow in simpleUPnPcommand2() + +2015/10/25: + fix compilation with old macs + fix compilation with mingw32 (for Appveyor) + fix python module for python <= 2.3 + +2015/10/08: + Change sameport to localport + see https://github.com/miniupnp/miniupnp/pull/120 + increments API_VERSION to 15 + +2015/09/15: + Fix buffer overflow in igd_desc_parse.c/IGDstartelt() + Discovered by Aleksandar Nikolic of Cisco Talos + +2015/08/28: + move ssdpDiscoverDevices() to minissdpc.c + +2015/08/27: + avoid unix socket leak in getDevicesFromMiniSSDPD() + +2015/08/16: + Also accept "Up" as ConnectionStatus value + +2015/07/23: + split getDevicesFromMiniSSDPD + add ttl argument to upnpDiscover() functions + increments API_VERSION to 14 + +2015/07/22: + Read USN from SSDP messages. + +2015/07/15: + Check malloc/calloc + +2015/06/16: + update getDevicesFromMiniSSDPD() to process longer minissdpd + responses + +2015/05/22: + add searchalltypes param to upnpDiscoverDevices() + increments API_VERSION to 13 + +2015/04/30: + upnpc: output version on the terminal + +2015/04/27: + _BSD_SOURCE is deprecated in favor of _DEFAULT_SOURCE + fix CMakeLists.txt COMPILE_DEFINITIONS + fix getDevicesFromMiniSSDPD() not setting scope_id + improve -r command of upnpc command line tool + +2014/11/17: + search all : + upnpDiscoverDevices() / upnpDiscoverAll() functions + listdevices executable + increment API_VERSION to 12 + validate igd_desc_parse + +2014/11/13: + increment API_VERSION to 11 + +2014/11/05: + simplified function GetUPNPUrls() + +2014/09/11: + use remoteHost arg of DeletePortMapping + +2014/09/06: + Fix python3 build + +2014/07/01: + Fix parsing of IGD2 root descriptions + +2014/06/10: + rename LIBSPEC to MINIUPNP_LIBSPEC + +2014/05/15: + Add support for IGD2 AddAnyPortMapping and DeletePortMappingRange + +2014/02/05: + handle EINPROGRESS after connect() + +2014/02/03: + minixml now handle XML comments + +VERSION 1.9 : released 2014/01/31 + +2014/01/31: + added argument remoteHost to UPNP_GetSpecificPortMappingEntry() + increment API_VERSION to 10 + +2013/12/09: + --help and -h arguments in upnpc.c + +2013/10/07: + fixed potential buffer overrun in miniwget.c + Modified UPNP_GetValidIGD() to check for ExternalIpAddress + +2013/08/01: + define MAXHOSTNAMELEN if not already done + +2013/06/06: + update upnpreplyparse to allow larger values (128 chars instead of 64) + +2013/05/14: + Update upnpreplyparse to take into account "empty" elements + validate upnpreplyparse.c code with "make check" + +2013/05/03: + Fix Solaris build thanks to Maciej MaÅ‚ecki + +2013/04/27: + Fix testminiwget.sh for BSD + +2013/03/23: + Fixed Makefile for *BSD + +2013/03/11: + Update Makefile to use JNAerator version 0.11 + +2013/02/11: + Fix testminiwget.sh for use with dash + Use $(DESTDIR) in Makefile + +VERSION 1.8 : released 2013/02/06 + +2012/10/16: + fix testminiwget with no IPv6 support + +2012/09/27: + Rename all include guards to not clash with C99 + (7.1.3 Reserved identifiers). + +2012/08/30: + Added -e option to upnpc program (set description for port mappings) + +2012/08/29: + Python 3 support (thanks to Christopher Foo) + +2012/08/11: + Fix a memory link in UPNP_GetValidIGD() + Try to handle scope id in link local IPv6 URL under MS Windows + +2012/07/20: + Disable HAS_IP_MREQN on DragonFly BSD + +2012/06/28: + GetUPNPUrls() now inserts scope into link-local IPv6 addresses + +2012/06/23: + More error return checks in upnpc.c + #define MINIUPNPC_GET_SRC_ADDR enables receivedata() to get scope_id + parseURL() now parses IPv6 addresses scope + new parameter for miniwget() : IPv6 address scope + increment API_VERSION to 9 + +2012/06/20: + fixed CMakeLists.txt + +2012/05/29 + Improvements in testminiwget.sh + +VERSION 1.7 : released 2012/05/24 + +2012/05/01: + Cleanup settings of CFLAGS in Makefile + Fix signed/unsigned integer comparaisons + +2012/04/20: + Allow to specify protocol with TCP or UDP for -A option + +2012/04/09: + Only try to fetch XML description once in UPNP_GetValidIGD() + Added -ansi flag to compilation, and fixed C++ comments to ANSI C comments. + +2012/04/05: + minor improvements to minihttptestserver.c + +2012/03/15: + upnperrors.c returns valid error string for unrecognized error codes + +2012/03/08: + make minihttptestserver listen on loopback interface instead of 0.0.0.0 + +2012/01/25: + Maven installation thanks to Alexey Kuznetsov + +2012/01/21: + Replace WIN32 macro by _WIN32 + +2012/01/19: + Fixes in java wrappers thanks to Alexey Kuznetsov : + https://github.com/axet/miniupnp/tree/fix-javatest/miniupnpc + Make and install .deb packages (python) thanks to Alexey Kuznetsov : + https://github.com/axet/miniupnp/tree/feature-debbuild/miniupnpc + +2012/01/07: + The multicast interface can now be specified by name with IPv4. + +2012/01/02: + Install man page + +2011/11/25: + added header to Port Mappings list in upnpc.c + +2011/10/09: + Makefile : make clean now removes jnaerator generated files. + MINIUPNPC_VERSION in miniupnpc.h (updated by make) + +2011/09/12: + added rootdescURL to UPNPUrls structure. + +VERSION 1.6 : released 2011/07/25 + +2011/07/25: + Update doc for version 1.6 release + +2011/06/18: + Fix for windows in miniwget.c + +2011/06/04: + display remote host in port mapping listing + +2011/06/03: + Fix in make install : there were missing headers + +2011/05/26: + Fix the socket leak in miniwget thanks to Richard Marsh. + Permit to add leaseduration in -a command. Display lease duration. + +2011/05/15: + Try both LinkLocal and SiteLocal multicast address for SSDP in IPv6 + +2011/05/09: + add a test in testminiwget.sh. + more error checking in miniwget.c + +2011/05/06: + Adding some tool to test and validate miniwget.c + simplified and debugged miniwget.c + +2011/04/11: + moving ReceiveData() to a receivedata.c file. + parsing presentation url + adding IGD v2 WANIPv6FirewallControl commands + +2011/04/10: + update of miniupnpcmodule.c + comments in miniwget.c, update in testminiwget + Adding errors codes from IGD v2 + new functions in upnpc.c for IGD v2 + +2011/04/09: + Support for litteral ip v6 address in miniwget + +2011/04/08: + Adding support for urn:schemas-upnp-org:service:WANIPv6FirewallControl:1 + Updating APIVERSION + Supporting IPV6 in upnpDiscover() + Adding a -6 option to upnpc command line tool + +2011/03/18: + miniwget/parseURL() : return an error when url param is null. + fixing GetListOfPortMappings() + +2011/03/14: + upnpDiscover() now reporting an error code. + improvements in comments. + +2011/03/11: + adding miniupnpcstrings.h.cmake and CMakeLists.txt files. + +2011/02/15: + Implementation of GetListOfPortMappings() + +2011/02/07: + updates to minixml to support character data starting with spaces + minixml now support CDATA + upnpreplyparse treats specificaly + change in simpleUPnPcommand to return the buffer (simplification) + +2011/02/06: + Added leaseDuration argument to AddPortMapping() + Starting to implement GetListOfPortMappings() + +2011/01/11: + updating wingenminiupnpcstrings.c + +2011/01/04: + improving updateminiupnpcstrings.sh + +VERSION 1.5 : released 2011/01/01 + +2010/12/21: + use NO_GETADDRINFO macro to disable the use of getaddrinfo/freeaddrinfo + +2010/12/11: + Improvements on getHTTPResponse() code. + +2010/12/09: + new code for miniwget that handle Chunked transfer encoding + using getHTTPResponse() in SOAP call code + Adding MANIFEST.in for 'python setup.py bdist_rpm' + +2010/11/25: + changes to minissdpc.c to compile under Win32. + see http://miniupnp.tuxfamily.org/forum/viewtopic.php?t=729 + +2010/09/17: + Various improvement to Makefile from MichaÅ‚ Górny + +2010/08/05: + Adding the script "external-ip.sh" from Reuben Hawkins + +2010/06/09: + update to python module to match modification made on 2010/04/05 + update to Java test code to match modification made on 2010/04/05 + all UPNP_* function now return an error if the SOAP request failed + at HTTP level. + +2010/04/17: + Using GetBestRoute() under win32 in order to find the + right interface to use. + +2010/04/12: + Retrying with HTTP/1.1 if HTTP/1.0 failed. see + http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1703 + +2010/04/07: + avoid returning duplicates in upnpDiscover() + +2010/04/05: + Create a connecthostport.h/.c with connecthostport() function + and use it in miniwget and miniupnpc. + Use getnameinfo() instead of inet_ntop or inet_ntoa + Work to make miniupnpc IPV6 compatible... + Add java test code. + Big changes in order to support device having both WANIPConnection + and WANPPPConnection. + +2010/04/04: + Use getaddrinfo() instead of gethostbyname() in miniwget. + +2010/01/06: + #define _DARWIN_C_SOURCE for Mac OS X + +2009/12/19: + Improve MinGW32 build + +2009/12/11: + adding a MSVC9 project to build the static library and executable + +2009/12/10: + Fixing some compilation stuff for Windows/MinGW + +2009/12/07: + adaptations in Makefile and updateminiupnpcstring.sh for AmigaOS + some fixes for Windows when using virtual ethernet adapters (it is the + case with VMWare installed). + +2009/12/04: + some fixes for AmigaOS compilation + Changed HTTP version to HTTP/1.0 for Soap too (to prevent chunked + transfer encoding) + +2009/12/03: + updating printIDG and testigddescparse.c for debug. + modifications to compile under AmigaOS + adding a testminiwget program + Changed miniwget to advertise itself as HTTP/1.0 to prevent chunked + transfer encoding + +2009/11/26: + fixing updateminiupnpcstrings.sh to take into account + which command that does not return an error code. + +VERSION 1.4 : released 2009/10/30 + +2009/10/16: + using Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS in python module. + +2009/10/10: + Some fixes for compilation under Solaris + compilation fixes : http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1464 + +2009/09/21: + fixing the code to ignore EINTR during connect() calls. + +2009/08/07: + Set socket timeout for connect() + Some cleanup in miniwget.c + +2009/08/04: + remove multiple redirections with -d in upnpc.c + Print textual error code in upnpc.c + Ignore EINTR during the connect() and poll() calls. + +2009/07/29: + fix in updateminiupnpcstrings.sh if OS name contains "/" + Sending a correct value for MX: field in SSDP request + +2009/07/20: + Change the Makefile to compile under Mac OS X + Fixed a stackoverflow in getDevicesFromMiniSSDPD() + +2009/07/09: + Compile under Haiku + generate miniupnpcstrings.h.in from miniupnpcstrings.h + +2009/06/04: + patching to compile under CygWin and cross compile for minGW + +VERSION 1.3 : + +2009/04/17: + updating python module + Use strtoull() when using C99 + +2009/02/28: + Fixed miniwget.c for compiling under sun + +2008/12/18: + cleanup in Makefile (thanks to Paul de Weerd) + minissdpc.c : win32 compatibility + miniupnpc.c : changed xmlns prefix from 'm' to 'u' + Removed NDEBUG (using DEBUG) + +2008/10/14: + Added the ExternalHost argument to DeletePortMapping() + +2008/10/11: + Added the ExternalHost argument to AddPortMapping() + Put a correct User-Agent: header in HTTP requests. + +VERSION 1.2 : + +2008/10/07: + Update docs + +2008/09/25: + Integrated sameport patch from Dario Meloni : Added a "sameport" + argument to upnpDiscover(). + +2008/07/18: + small modif to make Clang happy :) + +2008/07/17: + #define SOAPPREFIX "s" in miniupnpc.c in order to remove SOAP-ENV... + +2008/07/14: + include declspec.h in installation (to /usr/include/miniupnpc) + +VERSION 1.1 : + +2008/07/04: + standard options for install/ln instead of gnu-specific stuff. + +2008/07/03: + now builds a .dll and .lib with win32. (mingw32) + +2008/04/28: + make install now install the binary of the upnpc tool + +2008/04/27: + added testupnpigd.py + added error strings for miniupnpc "internal" errors + improved python module error/exception reporting. + +2008/04/23: + Completely rewrite igd_desc_parse.c in order to be compatible with + Linksys WAG200G + Added testigddescparse + updated python module + +VERSION 1.0 : + +2008/02/21: + put some #ifdef DEBUG around DisplayNameValueList() + +2008/02/18: + Improved error reporting in upnpcommands.c + UPNP_GetStatusInfo() returns LastConnectionError + +2008/02/16: + better error handling in minisoap.c + improving display of "valid IGD found" in upnpc.c + +2008/02/03: + Fixing UPNP_GetValidIGD() + improved make install :) + +2007/12/22: + Adding upnperrors.c/h to provide a strupnperror() function + used to translate UPnP error codes to string. + +2007/12/19: + Fixing getDevicesFromMiniSSDPD() + improved error reporting of UPnP functions + +2007/12/18: + It is now possible to specify a different location for MiniSSDPd socket. + working with MiniSSDPd is now more efficient. + python module improved. + +2007/12/16: + improving error reporting + +2007/12/13: + Try to improve compatibility by using HTTP/1.0 instead of 1.1 and + XML a bit different for SOAP. + +2007/11/25: + fixed select() call for linux + +2007/11/15: + Added -fPIC to CFLAG for better shared library code. + +2007/11/02: + Fixed a potential socket leak in miniwget2() + +2007/10/16: + added a parameter to upnpDiscover() in order to allow the use of another + interface than the default multicast interface. + +2007/10/12: + Fixed the creation of symbolic link in Makefile + +2007/10/08: + Added man page + +2007/10/02: + fixed memory bug in GetUPNPUrls() + +2007/10/01: + fixes in the Makefile + Added UPNP_GetIGDFromUrl() and adapted the sample program accordingly. + Added SONAME in the shared library to please debian :) + fixed MS Windows compilation (minissdpd is not available under MS Windows). + +2007/09/25: + small change to Makefile to be able to install in a different location + (default is /usr) + +2007/09/24: + now compiling both shared and static library + +2007/09/19: + Cosmetic changes on upnpc.c + +2007/09/02: + adapting to new miniSSDPd (release version ?) + +2007/08/31: + Usage of miniSSDPd to skip discovery process. + +2007/08/27: + fixed python module to allow compilation with Python older than Python 2.4 + +2007/06/12: + Added a python module. + +2007/05/19: + Fixed compilation under MinGW + +2007/05/15: + fixed a memory leak in AddPortMapping() + Added testupnpreplyparse executable to check the parsing of + upnp soap messages + minixml now ignore namespace prefixes. + +2007/04/26: + 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" + +2007/03/19: + cleanup in miniwget.c + +2007/03/01: + Small typo fix... + +2007/01/30: + Now parsing the HTTP header from SOAP responses in order to + get content-length value. + +2007/01/29: + Fixed the Soap Query to speedup the HTTP request. + added some Win32 DLL stuff... + +2007/01/27: + Fixed some WIN32 compatibility issues + +2006/12/14: + Added UPNPIGD_IsConnected() function in miniupnp.c/.h + Added UPNP_GetValidIGD() in miniupnp.c/.h + cleaned upnpc.c main(). now using UPNP_GetValidIGD() + +2006/12/07: + Version 1.0-RC1 released + +2006/12/03: + Minor changes to compile under SunOS/Solaris + +2006/11/30: + made a minixml parser validator program + updated minixml to handle attributes correctly + +2006/11/22: + Added a -r option to the upnpc sample thanks to Alexander Hubmann. + +2006/11/19: + Cleanup code to make it more ANSI C compliant + +2006/11/10: + detect and display local lan address. + +2006/11/04: + Packets and Bytes Sent/Received are now unsigned int. + +2006/11/01: + Bug fix thanks to Giuseppe D'Angelo + +2006/10/31: + C++ compatibility for .h files. + Added a way to get ip Address on the LAN used to reach the IGD. + +2006/10/25: + Added M-SEARCH to the services in the discovery process. + +2006/10/22: + updated the Makefile to use makedepend, added a "make install" + update Makefile + +2006/10/20: + fixing the description url parsing thanks to patch sent by + Wayne Dawe. + Fixed/translated some comments. + Implemented a better discover process, first looking + for IGD then for root devices (as some devices only reply to + M-SEARCH for root devices). + +2006/09/02: + added freeUPNPDevlist() function. + +2006/08/04: + More command line arguments checking + +2006/08/01: + Added the .bat file to compile under Win32 with minGW32 + +2006/07/31: + Fixed the rootdesc parser (igd_desc_parse.c) + +2006/07/20: + parseMSEARCHReply() is now returning the ST: line as well + starting changes to detect several UPnP devices on the network + +2006/07/19: + using GetCommonLinkProperties to get down/upload bitrate + diff --git a/ext/miniupnpc/LICENSE b/ext/miniupnpc/LICENSE new file mode 100644 index 00000000..cb5a0604 --- /dev/null +++ b/ext/miniupnpc/LICENSE @@ -0,0 +1,27 @@ +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. + diff --git a/ext/miniupnpc/MANIFEST.in b/ext/miniupnpc/MANIFEST.in new file mode 100644 index 00000000..54b86f95 --- /dev/null +++ b/ext/miniupnpc/MANIFEST.in @@ -0,0 +1,5 @@ +include README +include miniupnpcmodule.c +include setup.py +include *.h +include libminiupnpc.a diff --git a/ext/miniupnpc/Makefile b/ext/miniupnpc/Makefile new file mode 100644 index 00000000..4a4f1612 --- /dev/null +++ b/ext/miniupnpc/Makefile @@ -0,0 +1,379 @@ +# $Id: Makefile,v 1.132 2015/10/26 16:59:54 nanard Exp $ +# MiniUPnP Project +# http://miniupnp.free.fr/ +# http://miniupnp.tuxfamily.org/ +# https://github.com/miniupnp/miniupnp +# (c) 2005-2015 Thomas Bernard +# to install use : +# $ make DESTDIR=/tmp/dummylocation install +# or +# $ INSTALLPREFIX=/usr/local make install +# or +# $ make install (default INSTALLPREFIX is /usr) +OS = $(shell uname -s) +VERSION = $(shell cat VERSION) + +ifeq ($(OS), Darwin) +JARSUFFIX=mac +LIBTOOL ?= $(shell which libtool) +endif +ifeq ($(OS), Linux) +JARSUFFIX=linux +endif +ifneq (,$(findstring NT-5.1,$(OS))) +JARSUFFIX=win32 +endif + +HAVE_IPV6 ?= yes +export HAVE_IPV6 + +CC ?= gcc +#AR = gar +#CFLAGS = -O -g -DDEBUG +CFLAGS ?= -O +CFLAGS += -Wall +CFLAGS += -W -Wstrict-prototypes +CFLAGS += -fno-common +CFLAGS += -DMINIUPNPC_SET_SOCKET_TIMEOUT +CFLAGS += -DMINIUPNPC_GET_SRC_ADDR +CFLAGS += -D_BSD_SOURCE +CFLAGS += -D_DEFAULT_SOURCE +ifneq ($(OS), FreeBSD) +ifneq ($(OS), Darwin) +#CFLAGS += -D_POSIX_C_SOURCE=200112L +CFLAGS += -D_XOPEN_SOURCE=600 +endif +endif +#CFLAGS += -ansi +# -DNO_GETADDRINFO +INSTALL = install +SH = /bin/sh +JAVA = java +# see http://code.google.com/p/jnaerator/ +#JNAERATOR = jnaerator-0.9.7.jar +#JNAERATOR = jnaerator-0.9.8-shaded.jar +#JNAERATORARGS = -library miniupnpc +#JNAERATOR = jnaerator-0.10-shaded.jar +#JNAERATOR = jnaerator-0.11-shaded.jar +# https://repo1.maven.org/maven2/com/nativelibs4java/jnaerator/0.12/jnaerator-0.12-shaded.jar +JNAERATOR = jnaerator-0.12-shaded.jar +JNAERATORARGS = -mode StandaloneJar -runtime JNAerator -library miniupnpc +#JNAERATORBASEURL = http://jnaerator.googlecode.com/files/ +JNAERATORBASEURL = https://repo1.maven.org/maven2/com/nativelibs4java/jnaerator/0.12 + +ifeq (SunOS, $(OS)) + LDFLAGS=-lsocket -lnsl -lresolv +endif + +# APIVERSION is used to build SONAME +APIVERSION = 15 + +SRCS = igd_desc_parse.c miniupnpc.c minixml.c minisoap.c miniwget.c \ + upnpc.c upnpcommands.c upnpreplyparse.c testminixml.c \ + minixmlvalid.c testupnpreplyparse.c minissdpc.c \ + upnperrors.c testigddescparse.c testminiwget.c \ + connecthostport.c portlistingparse.c receivedata.c \ + upnpdev.c testportlistingparse.c miniupnpcmodule.c \ + minihttptestserver.c \ + listdevices.c + +LIBOBJS = miniwget.o minixml.o igd_desc_parse.o minisoap.o \ + miniupnpc.o upnpreplyparse.o upnpcommands.o upnperrors.o \ + connecthostport.o portlistingparse.o receivedata.o upnpdev.o + +ifneq ($(OS), AmigaOS) +CFLAGS := -fPIC $(CFLAGS) +LIBOBJS := $(LIBOBJS) minissdpc.o +endif + +OBJS = $(patsubst %.c,%.o,$(SRCS)) + +# HEADERS to install +HEADERS = miniupnpc.h miniwget.h upnpcommands.h igd_desc_parse.h \ + upnpreplyparse.h upnperrors.h miniupnpctypes.h \ + portlistingparse.h \ + upnpdev.h \ + miniupnpc_declspec.h + +# library names +LIBRARY = libminiupnpc.a +ifeq ($(OS), Darwin) + SHAREDLIBRARY = libminiupnpc.dylib + SONAME = $(basename $(SHAREDLIBRARY)).$(APIVERSION).dylib + CFLAGS := -D_DARWIN_C_SOURCE $(CFLAGS) +else +ifeq ($(JARSUFFIX), win32) + SHAREDLIBRARY = miniupnpc.dll +else + # Linux/BSD/etc. + SHAREDLIBRARY = libminiupnpc.so + SONAME = $(SHAREDLIBRARY).$(APIVERSION) +endif +endif + +EXECUTABLES = upnpc-static listdevices +EXECUTABLES_ADDTESTS = testminixml minixmlvalid testupnpreplyparse \ + testigddescparse testminiwget testportlistingparse + +TESTMINIXMLOBJS = minixml.o igd_desc_parse.o testminixml.o + +TESTMINIWGETOBJS = miniwget.o testminiwget.o connecthostport.o receivedata.o + +TESTUPNPREPLYPARSE = testupnpreplyparse.o minixml.o upnpreplyparse.o + +TESTPORTLISTINGPARSE = testportlistingparse.o minixml.o portlistingparse.o + +TESTIGDDESCPARSE = testigddescparse.o igd_desc_parse.o minixml.o \ + miniupnpc.o miniwget.o upnpcommands.o upnpreplyparse.o \ + minisoap.o connecthostport.o receivedata.o \ + portlistingparse.o + +ifneq ($(OS), AmigaOS) +EXECUTABLES := $(EXECUTABLES) upnpc-shared +TESTMINIWGETOBJS := $(TESTMINIWGETOBJS) minissdpc.o +TESTIGDDESCPARSE := $(TESTIGDDESCPARSE) minissdpc.o +endif + +LIBDIR ?= lib +# install directories +INSTALLPREFIX ?= $(PREFIX)/usr +INSTALLDIRINC = $(INSTALLPREFIX)/include/miniupnpc +INSTALLDIRLIB = $(INSTALLPREFIX)/$(LIBDIR) +INSTALLDIRBIN = $(INSTALLPREFIX)/bin +INSTALLDIRMAN = $(INSTALLPREFIX)/share/man + +FILESTOINSTALL = $(LIBRARY) $(EXECUTABLES) +ifneq ($(OS), AmigaOS) +FILESTOINSTALL := $(FILESTOINSTALL) $(SHAREDLIBRARY) +endif + + +.PHONY: install clean depend all check test everything \ + installpythonmodule updateversion +# validateminixml validateminiwget + +all: $(LIBRARY) $(EXECUTABLES) + +test: check + +check: validateminixml validateminiwget validateupnpreplyparse \ + validateportlistingparse validateigddescparse + +everything: all $(EXECUTABLES_ADDTESTS) + +pythonmodule: $(LIBRARY) miniupnpcmodule.c setup.py + python setup.py build + touch $@ + +installpythonmodule: pythonmodule + python setup.py install + +pythonmodule3: $(LIBRARY) miniupnpcmodule.c setup.py + python3 setup.py build + touch $@ + +installpythonmodule3: pythonmodule3 + python3 setup.py install + +validateminixml: minixmlvalid + @echo "minixml validation test" + ./minixmlvalid + touch $@ + +validateminiwget: testminiwget minihttptestserver testminiwget.sh + @echo "miniwget validation test" + ./testminiwget.sh + touch $@ + +validateupnpreplyparse: testupnpreplyparse testupnpreplyparse.sh + @echo "upnpreplyparse validation test" + ./testupnpreplyparse.sh + touch $@ + +validateportlistingparse: testportlistingparse + @echo "portlistingparse validation test" + ./testportlistingparse + touch $@ + +validateigddescparse: testigddescparse + @echo "igd desc parse validation test" + ./testigddescparse testdesc/new_LiveBox_desc.xml testdesc/new_LiveBox_desc.values + ./testigddescparse testdesc/linksys_WAG200G_desc.xml testdesc/linksys_WAG200G_desc.values + touch $@ + +clean: + $(RM) $(LIBRARY) $(SHAREDLIBRARY) $(EXECUTABLES) $(OBJS) miniupnpcstrings.h + $(RM) $(EXECUTABLES_ADDTESTS) + # clean python stuff + $(RM) pythonmodule pythonmodule3 + $(RM) validateminixml validateminiwget validateupnpreplyparse + $(RM) validateigddescparse + $(RM) minihttptestserver + $(RM) -r build/ dist/ + #python setup.py clean + # clean jnaerator stuff + $(RM) _jnaerator.* java/miniupnpc_$(OS).jar + +distclean: clean + $(RM) $(JNAERATOR) java/*.jar java/*.class out.errors.txt + +updateversion: miniupnpc.h + cp miniupnpc.h miniupnpc.h.bak + sed 's/\(.*MINIUPNPC_API_VERSION\s\+\)[0-9]\+/\1$(APIVERSION)/' < miniupnpc.h.bak > miniupnpc.h + +install: updateversion $(FILESTOINSTALL) + $(INSTALL) -d $(DESTDIR)$(INSTALLDIRINC) + $(INSTALL) -m 644 $(HEADERS) $(DESTDIR)$(INSTALLDIRINC) + $(INSTALL) -d $(DESTDIR)$(INSTALLDIRLIB) + $(INSTALL) -m 644 $(LIBRARY) $(DESTDIR)$(INSTALLDIRLIB) +ifneq ($(OS), AmigaOS) + $(INSTALL) -m 644 $(SHAREDLIBRARY) $(DESTDIR)$(INSTALLDIRLIB)/$(SONAME) + ln -fs $(SONAME) $(DESTDIR)$(INSTALLDIRLIB)/$(SHAREDLIBRARY) +endif + $(INSTALL) -d $(DESTDIR)$(INSTALLDIRBIN) +ifeq ($(OS), AmigaOS) + $(INSTALL) -m 755 upnpc-static $(DESTDIR)$(INSTALLDIRBIN)/upnpc +else + $(INSTALL) -m 755 upnpc-shared $(DESTDIR)$(INSTALLDIRBIN)/upnpc +endif + $(INSTALL) -m 755 external-ip.sh $(DESTDIR)$(INSTALLDIRBIN)/external-ip +ifneq ($(OS), AmigaOS) + $(INSTALL) -d $(DESTDIR)$(INSTALLDIRMAN)/man3 + $(INSTALL) -m 644 man3/miniupnpc.3 $(DESTDIR)$(INSTALLDIRMAN)/man3/miniupnpc.3 +ifeq ($(OS), Linux) + gzip -f $(DESTDIR)$(INSTALLDIRMAN)/man3/miniupnpc.3 +endif +endif + +install-static: updateversion $(FILESTOINSTALL) + $(INSTALL) -d $(DESTDIR)$(INSTALLDIRINC) + $(INSTALL) -m 644 $(HEADERS) $(DESTDIR)$(INSTALLDIRINC) + $(INSTALL) -d $(DESTDIR)$(INSTALLDIRLIB) + $(INSTALL) -m 644 $(LIBRARY) $(DESTDIR)$(INSTALLDIRLIB) + $(INSTALL) -d $(DESTDIR)$(INSTALLDIRBIN) + $(INSTALL) -m 755 external-ip.sh $(DESTDIR)$(INSTALLDIRBIN)/external-ip + +cleaninstall: + $(RM) -r $(DESTDIR)$(INSTALLDIRINC) + $(RM) $(DESTDIR)$(INSTALLDIRLIB)/$(LIBRARY) + $(RM) $(DESTDIR)$(INSTALLDIRLIB)/$(SHAREDLIBRARY) + +depend: + makedepend -Y -- $(CFLAGS) -- $(SRCS) 2>/dev/null + +$(LIBRARY): $(LIBOBJS) +ifeq ($(OS), Darwin) + $(LIBTOOL) -static -o $@ $? +else + $(AR) crs $@ $? +endif + +$(SHAREDLIBRARY): $(LIBOBJS) +ifeq ($(OS), Darwin) +# $(CC) -dynamiclib $(LDFLAGS) -Wl,-install_name,$(SONAME) -o $@ $^ + $(CC) -dynamiclib $(LDFLAGS) -Wl,-install_name,$(INSTALLDIRLIB)/$(SONAME) -o $@ $^ +else + $(CC) -shared $(LDFLAGS) -Wl,-soname,$(SONAME) -o $@ $^ +endif + +upnpc-static: upnpc.o $(LIBRARY) + $(CC) $(LDFLAGS) -o $@ $^ $(LOADLIBES) $(LDLIBS) + +upnpc-shared: upnpc.o $(SHAREDLIBRARY) + $(CC) $(LDFLAGS) -o $@ $^ $(LOADLIBES) $(LDLIBS) + +listdevices: listdevices.o $(LIBRARY) + +testminixml: $(TESTMINIXMLOBJS) + +testminiwget: $(TESTMINIWGETOBJS) + +minixmlvalid: minixml.o minixmlvalid.o + +testupnpreplyparse: $(TESTUPNPREPLYPARSE) + +testigddescparse: $(TESTIGDDESCPARSE) + +testportlistingparse: $(TESTPORTLISTINGPARSE) + +miniupnpcstrings.h: miniupnpcstrings.h.in updateminiupnpcstrings.sh VERSION + $(SH) updateminiupnpcstrings.sh + +# ftp tool supplied with OpenBSD can download files from http. +jnaerator-%.jar: + wget $(JNAERATORBASEURL)/$@ || \ + curl -o $@ $(JNAERATORBASEURL)/$@ || \ + ftp $(JNAERATORBASEURL)/$@ + +jar: $(SHAREDLIBRARY) $(JNAERATOR) + $(JAVA) -jar $(JNAERATOR) $(JNAERATORARGS) \ + miniupnpc.h miniupnpc_declspec.h upnpcommands.h upnpreplyparse.h \ + igd_desc_parse.h miniwget.h upnperrors.h $(SHAREDLIBRARY) \ + -package fr.free.miniupnp -o . -jar java/miniupnpc_$(JARSUFFIX).jar -v + +mvn_install: + mvn install:install-file -Dfile=java/miniupnpc_$(JARSUFFIX).jar \ + -DgroupId=com.github \ + -DartifactId=miniupnp \ + -Dversion=$(VERSION) \ + -Dpackaging=jar \ + -Dclassifier=$(JARSUFFIX) \ + -DgeneratePom=true \ + -DcreateChecksum=true + +# make .deb packages +deb: /usr/share/pyshared/stdeb all + (python setup.py --command-packages=stdeb.command bdist_deb) + +# install .deb packages +ideb: + (sudo dpkg -i deb_dist/*.deb) + +/usr/share/pyshared/stdeb: /usr/share/doc/python-all-dev + (sudo apt-get install python-stdeb) + +/usr/share/doc/python-all-dev: + (sudo apt-get install python-all-dev) + +minihttptestserver: minihttptestserver.o + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +igd_desc_parse.o: igd_desc_parse.h +miniupnpc.o: miniupnpc.h miniupnpc_declspec.h igd_desc_parse.h upnpdev.h +miniupnpc.o: minissdpc.h miniwget.h minisoap.h minixml.h upnpcommands.h +miniupnpc.o: upnpreplyparse.h portlistingparse.h miniupnpctypes.h +miniupnpc.o: connecthostport.h +minixml.o: minixml.h +minisoap.o: minisoap.h miniupnpcstrings.h +miniwget.o: miniupnpcstrings.h miniwget.h miniupnpc_declspec.h +miniwget.o: connecthostport.h receivedata.h +upnpc.o: miniwget.h miniupnpc_declspec.h miniupnpc.h igd_desc_parse.h +upnpc.o: upnpdev.h upnpcommands.h upnpreplyparse.h portlistingparse.h +upnpc.o: miniupnpctypes.h upnperrors.h miniupnpcstrings.h +upnpcommands.o: upnpcommands.h upnpreplyparse.h portlistingparse.h +upnpcommands.o: miniupnpc_declspec.h miniupnpctypes.h miniupnpc.h +upnpcommands.o: igd_desc_parse.h upnpdev.h +upnpreplyparse.o: upnpreplyparse.h minixml.h +testminixml.o: minixml.h igd_desc_parse.h +minixmlvalid.o: minixml.h +testupnpreplyparse.o: upnpreplyparse.h +minissdpc.o: minissdpc.h miniupnpc_declspec.h upnpdev.h miniupnpc.h +minissdpc.o: igd_desc_parse.h receivedata.h codelength.h +upnperrors.o: upnperrors.h miniupnpc_declspec.h upnpcommands.h +upnperrors.o: upnpreplyparse.h portlistingparse.h miniupnpctypes.h +upnperrors.o: miniupnpc.h igd_desc_parse.h upnpdev.h +testigddescparse.o: igd_desc_parse.h minixml.h miniupnpc.h +testigddescparse.o: miniupnpc_declspec.h upnpdev.h +testminiwget.o: miniwget.h miniupnpc_declspec.h +connecthostport.o: connecthostport.h +portlistingparse.o: portlistingparse.h miniupnpc_declspec.h miniupnpctypes.h +portlistingparse.o: minixml.h +receivedata.o: receivedata.h +upnpdev.o: upnpdev.h miniupnpc_declspec.h +testportlistingparse.o: portlistingparse.h miniupnpc_declspec.h +testportlistingparse.o: miniupnpctypes.h +miniupnpcmodule.o: miniupnpc.h miniupnpc_declspec.h igd_desc_parse.h +miniupnpcmodule.o: upnpdev.h upnpcommands.h upnpreplyparse.h +miniupnpcmodule.o: portlistingparse.h miniupnpctypes.h upnperrors.h +listdevices.o: miniupnpc.h miniupnpc_declspec.h igd_desc_parse.h upnpdev.h diff --git a/ext/miniupnpc/Makefile.mingw b/ext/miniupnpc/Makefile.mingw new file mode 100644 index 00000000..6de325fe --- /dev/null +++ b/ext/miniupnpc/Makefile.mingw @@ -0,0 +1,98 @@ +# $Id: Makefile.mingw,v 1.22 2015/10/26 16:59:54 nanard Exp $ +# Miniupnp project. +# http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ +# (c) 2005-2015 Thomas Bernard +# This Makefile is made for MinGW +# +CC ?= gcc +#CFLAGS = -Wall -g -DDEBUG -D_WIN32_WINNT=0X501 +CFLAGS = -Wall -Os -DNDEBUG -D_WIN32_WINNT=0X501 +LDLIBS = -lws2_32 -liphlpapi +# -lwsock32 +# -liphlpapi is needed for GetBestRoute() and GetIpAddrTable() +PYTHON=\utils\python25\python +OBJS=miniwget.o minixml.o igd_desc_parse.o minisoap.o \ + minissdpc.o \ + miniupnpc.o upnpreplyparse.o upnpcommands.o upnperrors.o \ + connecthostport.o portlistingparse.o receivedata.o \ + upnpdev.o +OBJSDLL=$(addprefix dll/, $(OBJS)) + +all: init upnpc-static upnpc-shared testminixml libminiupnpc.a miniupnpc.dll + +init: + mkdir dll + echo init > init + +clean: + del upnpc testminixml *.o + del dll\*.o + del *.exe + del miniupnpc.dll + del libminiupnpc.a + +libminiupnpc.a: $(OBJS) + $(AR) cr $@ $? + +pythonmodule: libminiupnpc.a + $(PYTHON) setupmingw32.py build --compiler=mingw32 + $(PYTHON) setupmingw32.py install --skip-build + +miniupnpc.dll: libminiupnpc.a $(OBJSDLL) + dllwrap -k --driver-name gcc \ + --def miniupnpc.def \ + --output-def miniupnpc.dll.def \ + --implib miniupnpc.lib -o $@ \ + $(OBJSDLL) $(LDLIBS) + +miniupnpc.lib: miniupnpc.dll +# echo $@ generated with $< + +dll/upnpc.o: upnpc.o +# echo $@ generated with $< + +.c.o: + $(CC) $(CFLAGS) -DMINIUPNP_STATICLIB -c -o $@ $< + $(CC) $(CFLAGS) -DMINIUPNP_EXPORTS -c -o dll/$@ $< + +upnpc.o: upnpc.c + $(CC) $(CFLAGS) -DMINIUPNP_STATICLIB -c -o $@ $< + $(CC) $(CFLAGS) -c -o dll/$@ $< + +# --enable-stdcall-fixup +upnpc-static: upnpc.o libminiupnpc.a + $(CC) -o $@ $^ $(LDLIBS) + +upnpc-shared: dll/upnpc.o miniupnpc.lib + $(CC) -o $@ $^ $(LDLIBS) + +wingenminiupnpcstrings: wingenminiupnpcstrings.o + +wingenminiupnpcstrings.o: wingenminiupnpcstrings.c + +miniupnpcstrings.h: miniupnpcstrings.h.in wingenminiupnpcstrings + wingenminiupnpcstrings $< $@ + +minixml.o: minixml.c minixml.h + +upnpc.o: miniwget.h minisoap.h miniupnpc.h igd_desc_parse.h +upnpc.o: upnpreplyparse.h upnpcommands.h upnperrors.h miniupnpcstrings.h + +miniwget.o: miniwget.c miniwget.h miniupnpcstrings.h connecthostport.h + +minisoap.o: minisoap.c minisoap.h miniupnpcstrings.h + +miniupnpc.o: miniupnpc.c miniupnpc.h minisoap.h miniwget.h minixml.h + +igd_desc_parse.o: igd_desc_parse.c igd_desc_parse.h + +testminixml: minixml.o igd_desc_parse.o testminixml.c + +upnpreplyparse.o: upnpreplyparse.c upnpreplyparse.h minixml.h + +upnpcommands.o: upnpcommands.c upnpcommands.h upnpreplyparse.h miniupnpc.h portlistingparse.h + +minissdpc.o: minissdpc.c minissdpc.h receivedata.h + +upnpdev.o: upnpdev.c upnpdev.h + diff --git a/ext/miniupnpc/README b/ext/miniupnpc/README new file mode 100644 index 00000000..ab08de94 --- /dev/null +++ b/ext/miniupnpc/README @@ -0,0 +1,61 @@ +Project: miniupnp +Project web page: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ +github: https://github.com/miniupnp/miniupnp +freecode: http://freecode.com/projects/miniupnp +Author: Thomas Bernard +Copyright (c) 2005-2014 Thomas Bernard +This software is subject to the conditions detailed in the +LICENSE file provided within this distribution. + + +* 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 compilation is known to work under linux, FreeBSD, +OpenBSD, MacOS X, AmigaOS and cygwin. +The official AmigaOS4.1 SDK was used for AmigaOS4 and GeekGadgets for AmigaOS3. +upx (http://upx.sourceforge.net) is used to compress the win32 .exe files. + +To install the library and headers on the system use : +> su +> make install +> exit + +alternatively, to install into a specific location, use : +> INSTALLPREFIX=/usr/local make install + +upnpc.c is a sample client using the libminiupnpc. +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() +- miniwget() +- parserootdesc() +- GetUPNPUrls() +- UPNP_* (calling UPNP methods) + +Note : use #include etc... for the includes +and -lminiupnpc for the link + +Discovery process is speeded up when MiniSSDPd is running on the machine. + + +* Python module * + +you can build a python module with 'make pythonmodule' +and install it with 'make installpythonmodule'. +setup.py (and setupmingw32.py) are included in the distribution. + + +Feel free to contact me if you have any problem : +e-mail : miniupnp@free.fr + +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/ + diff --git a/ext/miniupnpc/VERSION b/ext/miniupnpc/VERSION new file mode 100644 index 00000000..2e0e38c6 --- /dev/null +++ b/ext/miniupnpc/VERSION @@ -0,0 +1 @@ +1.9 diff --git a/ext/miniupnpc/apiversions.txt b/ext/miniupnpc/apiversions.txt new file mode 100644 index 00000000..3e9ebef2 --- /dev/null +++ b/ext/miniupnpc/apiversions.txt @@ -0,0 +1,167 @@ +$Id: apiversions.txt,v 1.8 2015/10/08 16:15:47 nanard Exp $ + +Differences in API between miniUPnPc versions + +API version 15 + changed "sameport" argument of upnpDiscover() upnpDiscoverAll() upnpDiscoverDevice() + to "localport". When 0 or 1, behaviour is not changed, but it can take + any other value between 2 and 65535 + Existing programs should be compatible + updated macro : + #define MINIUPNPC_API_VERSION 15 + +API version 14 +miniupnpc.h + add ttl argument to upnpDiscover() upnpDiscoverAll() upnpDiscoverDevice() + upnpDiscoverDevices() + getDevicesFromMiniSSDPD() : + connectToMiniSSDPD() / disconnectFromMiniSSDPD() + requestDevicesFromMiniSSDPD() / receiveDevicesFromMiniSSDPD() + updated macro : + #define MINIUPNPC_API_VERSION 14 + +API version 13 +miniupnpc.h: + add searchalltype param to upnpDiscoverDevices() function + updated macro : + #define MINIUPNPC_API_VERSION 13 + +API version 12 +miniupnpc.h : + add upnpDiscoverAll() / upnpDiscoverDevice() / upnpDiscoverDevices() + functions + updated macros : + #define MINIUPNPC_API_VERSION 12 + +API version 11 + +upnpreplyparse.h / portlistingparse.h : + removed usage of sys/queue.h / bsdqueue.h + +miniupnpc.h: + updated macros : + #define MINIUPNPC_API_VERSION 11 + +====================== miniUPnPc version 1.9 ====================== +API version 10 + +upnpcommands.h: + added argument remoteHost to UPNP_GetSpecificPortMappingEntry() + +miniupnpc.h: + updated macros : + #define MINIUPNPC_VERSION "1.9" + #define MINIUPNPC_API_VERSION 10 + +====================== miniUPnPc version 1.8 ====================== +API version 9 + +miniupnpc.h: + updated macros : + #define MINIUPNPC_VERSION "1.8" + #define MINIUPNPC_API_VERSION 9 + added "unsigned int scope_id;" to struct UPNPDev + added scope_id argument to GetUPNPUrls() + + + +====================== miniUPnPc version 1.7 ====================== +API version 8 + +miniupnpc.h : + add new macros : + #define MINIUPNPC_VERSION "1.7" + #define MINIUPNPC_API_VERSION 8 + add rootdescURL to struct UPNPUrls + + + +====================== miniUPnPc version 1.6 ====================== +API version 8 + +Adding support for IPv6. +igd_desc_parse.h : + struct IGDdatas_service : + add char presentationurl[MINIUPNPC_URL_MAXSIZE]; + struct IGDdatas : + add struct IGDdatas_service IPv6FC; +miniupnpc.h : + new macros : + #define UPNPDISCOVER_SUCCESS (0) + #define UPNPDISCOVER_UNKNOWN_ERROR (-1) + #define UPNPDISCOVER_SOCKET_ERROR (-101) + #define UPNPDISCOVER_MEMORY_ERROR (-102) + simpleUPnPcommand() prototype changed (but is normaly not used by API users) + add arguments ipv6 and error to upnpDiscover() : + struct UPNPDev * + upnpDiscover(int delay, const char * multicastif, + const char * minissdpdsock, int sameport, + int ipv6, + int * error); + add controlURL_6FC member to struct UPNPUrls : + struct UPNPUrls { + char * controlURL; + char * ipcondescURL; + char * controlURL_CIF; + char * controlURL_6FC; + }; + +upnpcommands.h : + add leaseDuration argument to UPNP_AddPortMapping() + add desc, enabled and leaseDuration arguments to UPNP_GetSpecificPortMappingEntry() + add UPNP_GetListOfPortMappings() function (IGDv2) + add IGDv2 IPv6 related functions : + UPNP_GetFirewallStatus() + UPNP_GetOutboundPinholeTimeout() + UPNP_AddPinhole() + UPNP_UpdatePinhole() + UPNP_DeletePinhole() + UPNP_CheckPinholeWorking() + UPNP_GetPinholePackets() + + + +====================== miniUPnPc version 1.5 ====================== +API version 5 + +new function : +int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *); +new macro in upnpcommands.h : +#define UPNPCOMMAND_HTTP_ERROR + +====================== miniUPnPc version 1.4 ====================== +Same API as version 1.3 + +====================== miniUPnPc version 1.3 ====================== +API version 4 + +Use UNSIGNED_INTEGER type for +UPNP_GetTotalBytesSent(), UPNP_GetTotalBytesReceived(), +UPNP_GetTotalPacketsSent(), UPNP_GetTotalPacketsReceived() +Add remoteHost argument to UPNP_AddPortMapping() and UPNP_DeletePortMapping() + +====================== miniUPnPc version 1.2 ====================== +API version 3 + +added sameport argument to upnpDiscover() +struct UPNPDev * +upnpDiscover(int delay, const char * multicastif, + const char * minissdpdsock, int sameport); + +====================== miniUPnPc Version 1.1 ====================== +Same API as 1.0 + + +====================== miniUPnPc Version 1.0 ====================== +API version 2 + + +struct UPNPDev { + struct UPNPDev * pNext; + char * descURL; + char * st; + char buffer[2]; +}; +struct UPNPDev * upnpDiscover(int delay, const char * multicastif, + const char * minissdpdsock); + diff --git a/ext/miniupnpc/codelength.h b/ext/miniupnpc/codelength.h new file mode 100644 index 00000000..f5f8e30f --- /dev/null +++ b/ext/miniupnpc/codelength.h @@ -0,0 +1,54 @@ +/* $Id: codelength.h,v 1.5 2015/07/09 12:40:18 nanard Exp $ */ +/* Project : miniupnp + * Author : Thomas BERNARD + * copyright (c) 2005-2015 Thomas Bernard + * This software is subjet to the conditions detailed in the + * provided LICENCE file. */ +#ifndef CODELENGTH_H_INCLUDED +#define CODELENGTH_H_INCLUDED + +/* Encode length by using 7bit per Byte : + * Most significant bit of each byte specifies that the + * following byte is part of the code */ + +/* n : unsigned + * p : unsigned char * + */ +#define DECODELENGTH(n, p) n = 0; \ + do { n = (n << 7) | (*p & 0x7f); } \ + while((*(p++)&0x80) && (n<(1<<25))); + +/* n : unsigned + * READ : function/macro to read one byte (unsigned char) + */ +#define DECODELENGTH_READ(n, READ) \ + n = 0; \ + do { \ + unsigned char c; \ + READ(c); \ + n = (n << 7) | (c & 0x07f); \ + if(!(c&0x80)) break; \ + } while(n<(1<<25)); + +/* n : unsigned + * p : unsigned char * + * p_limit : unsigned char * + */ +#define DECODELENGTH_CHECKLIMIT(n, p, p_limit) \ + n = 0; \ + do { \ + if((p) >= (p_limit)) break; \ + n = (n << 7) | (*(p) & 0x7f); \ + } while((*((p)++)&0x80) && (n<(1<<25))); + + +/* n : unsigned + * p : unsigned char * + */ +#define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \ + if(n>=2097152) *(p++) = (n >> 21) | 0x80; \ + if(n>=16384) *(p++) = (n >> 14) | 0x80; \ + if(n>=128) *(p++) = (n >> 7) | 0x80; \ + *(p++) = n & 0x7f; + +#endif /* CODELENGTH_H_INCLUDED */ diff --git a/ext/miniupnpc/connecthostport.c b/ext/miniupnpc/connecthostport.c new file mode 100644 index 00000000..1f2a032e --- /dev/null +++ b/ext/miniupnpc/connecthostport.c @@ -0,0 +1,264 @@ +/* $Id: connecthostport.c,v 1.15 2015/10/09 16:26:19 nanard Exp $ */ +/* Project : miniupnp + * Author : Thomas Bernard + * Copyright (c) 2010-2015 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. */ + +/* use getaddrinfo() or gethostbyname() + * uncomment the following line in order to use gethostbyname() */ +#ifdef NO_GETADDRINFO +#define USE_GETHOSTBYNAME +#endif + +#include +#include +#ifdef _WIN32 +#include +#include +#include +#define MAXHOSTNAMELEN 64 +#define snprintf _snprintf +#define herror +#define socklen_t int +#else /* #ifdef _WIN32 */ +#include +#include +#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT +#include +#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ +#include +#include +#include +#define closesocket close +#include +#include +/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions + * during the connect() call */ +#define MINIUPNPC_IGNORE_EINTR +#ifndef USE_GETHOSTBYNAME +#include +#include +#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 + +#include "connecthostport.h" + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +/* connecthostport() + * return a socket connected (TCP) to the host and port + * or -1 in case of error */ +int connecthostport(const char * host, unsigned short port, + unsigned int scope_id) +{ + int s, n; +#ifdef USE_GETHOSTBYNAME + struct sockaddr_in dest; + struct hostent *hp; +#else /* #ifdef USE_GETHOSTBYNAME */ + char tmp_host[MAXHOSTNAMELEN+1]; + char port_str[8]; + struct addrinfo *ai, *p; + struct addrinfo hints; +#endif /* #ifdef USE_GETHOSTBYNAME */ +#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT + struct timeval timeout; +#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ + +#ifdef USE_GETHOSTBYNAME + hp = gethostbyname(host); + if(hp == NULL) + { + herror(host); + return -1; + } + 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) + { + PRINT_SOCKET_ERROR("socket"); + return -1; + } +#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT + /* setting a 3 seconds timeout for the connect() call */ + timeout.tv_sec = 3; + timeout.tv_usec = 0; + if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) + { + PRINT_SOCKET_ERROR("setsockopt"); + } + timeout.tv_sec = 3; + timeout.tv_usec = 0; + if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) + { + PRINT_SOCKET_ERROR("setsockopt"); + } +#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ + dest.sin_family = AF_INET; + dest.sin_port = htons(port); + n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in)); +#ifdef MINIUPNPC_IGNORE_EINTR + /* EINTR The system call was interrupted by a signal that was caught + * EINPROGRESS The socket is nonblocking and the connection cannot + * be completed immediately. */ + while(n < 0 && (errno == EINTR || errno == EINPROGRESS)) + { + socklen_t len; + fd_set wset; + int err; + FD_ZERO(&wset); + FD_SET(s, &wset); + if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR) + continue; + /*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; + } + if(err != 0) { + errno = err; + n = -1; + } + } +#endif /* #ifdef MINIUPNPC_IGNORE_EINTR */ + if(n<0) + { + PRINT_SOCKET_ERROR("connect"); + closesocket(s); + return -1; + } +#else /* #ifdef USE_GETHOSTBYNAME */ + /* use getaddrinfo() instead of gethostbyname() */ + memset(&hints, 0, sizeof(hints)); + /* hints.ai_flags = AI_ADDRCONFIG; */ +#ifdef AI_NUMERICSERV + hints.ai_flags = AI_NUMERICSERV; +#endif + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = AF_UNSPEC; /* AF_INET, AF_INET6 or AF_UNSPEC */ + /* hints.ai_protocol = IPPROTO_TCP; */ + snprintf(port_str, sizeof(port_str), "%hu", port); + if(host[0] == '[') + { + /* literal ip v6 address */ + int i, j; + 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 '%' */ + j+=2; /* skip "25" */ + } + tmp_host[i] = '\0'; + } + else + { + strncpy(tmp_host, host, MAXHOSTNAMELEN); + } + tmp_host[MAXHOSTNAMELEN] = '\0'; + n = getaddrinfo(tmp_host, port_str, &hints, &ai); + if(n != 0) + { +#ifdef _WIN32 + fprintf(stderr, "getaddrinfo() error : %d\n", n); +#else + fprintf(stderr, "getaddrinfo() error : %s\n", gai_strerror(n)); +#endif + return -1; + } + s = -1; + for(p = ai; p; p = p->ai_next) + { + s = socket(p->ai_family, p->ai_socktype, p->ai_protocol); + if(s < 0) + continue; + if(p->ai_addr->sa_family == AF_INET6 && scope_id > 0) { + struct sockaddr_in6 * addr6 = (struct sockaddr_in6 *)p->ai_addr; + addr6->sin6_scope_id = scope_id; + } +#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT + /* setting a 3 seconds timeout for the connect() call */ + timeout.tv_sec = 3; + timeout.tv_usec = 0; + if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) + { + PRINT_SOCKET_ERROR("setsockopt"); + } + timeout.tv_sec = 3; + timeout.tv_usec = 0; + if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) + { + PRINT_SOCKET_ERROR("setsockopt"); + } +#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ + n = connect(s, p->ai_addr, 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 + * be completed immediately. */ + while(n < 0 && (errno == EINTR || errno == EINPROGRESS)) + { + socklen_t len; + fd_set wset; + int err; + FD_ZERO(&wset); + FD_SET(s, &wset); + if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR) + continue; + /*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); + freeaddrinfo(ai); + return -1; + } + if(err != 0) { + errno = err; + n = -1; + } + } +#endif /* #ifdef MINIUPNPC_IGNORE_EINTR */ + if(n < 0) + { + closesocket(s); + continue; + } + else + { + break; + } + } + freeaddrinfo(ai); + if(s < 0) + { + PRINT_SOCKET_ERROR("socket"); + return -1; + } + if(n < 0) + { + PRINT_SOCKET_ERROR("connect"); + return -1; + } +#endif /* #ifdef USE_GETHOSTBYNAME */ + return s; +} + diff --git a/ext/miniupnpc/connecthostport.h b/ext/miniupnpc/connecthostport.h new file mode 100644 index 00000000..56941d6f --- /dev/null +++ b/ext/miniupnpc/connecthostport.h @@ -0,0 +1,18 @@ +/* $Id: connecthostport.h,v 1.3 2012/09/27 15:42:10 nanard Exp $ */ +/* Project: miniupnp + * http://miniupnp.free.fr/ + * Author: Thomas Bernard + * Copyright (c) 2010-2012 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 + +/* 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); + +#endif + diff --git a/ext/miniupnpc/external-ip.sh b/ext/miniupnpc/external-ip.sh new file mode 100755 index 00000000..965d86b2 --- /dev/null +++ b/ext/miniupnpc/external-ip.sh @@ -0,0 +1,4 @@ +#!/bin/sh +# $Id: external-ip.sh,v 1.1 2010/08/05 12:57:41 nanard Exp $ +# (c) 2010 Reuben Hawkins +upnpc -s | grep ExternalIPAddress | sed 's/[^0-9\.]//g' diff --git a/ext/miniupnpc/igd_desc_parse.c b/ext/miniupnpc/igd_desc_parse.c new file mode 100644 index 00000000..d2999ad0 --- /dev/null +++ b/ext/miniupnpc/igd_desc_parse.c @@ -0,0 +1,123 @@ +/* $Id: igd_desc_parse.c,v 1.17 2015/09/15 13:30:04 nanard Exp $ */ +/* Project : miniupnp + * http://miniupnp.free.fr/ + * Author : Thomas Bernard + * Copyright (c) 2005-2015 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. */ + +#include "igd_desc_parse.h" +#include +#include + +/* Start element handler : + * update nesting level counter and copy element name */ +void IGDstartelt(void * d, const char * name, int l) +{ + struct IGDdatas * datas = (struct IGDdatas *)d; + if(l >= MINIUPNPC_URL_MAXSIZE) + l = MINIUPNPC_URL_MAXSIZE-1; + memcpy(datas->cureltname, name, l); + datas->cureltname[l] = '\0'; + datas->level++; + if( (l==7) && !memcmp(name, "service", l) ) { + datas->tmp.controlurl[0] = '\0'; + datas->tmp.eventsuburl[0] = '\0'; + datas->tmp.scpdurl[0] = '\0'; + datas->tmp.servicetype[0] = '\0'; + } +} + +#define COMPARE(str, cstr) (0==memcmp(str, cstr, sizeof(cstr) - 1)) + +/* End element handler : + * update nesting level counter and update parser state if + * service element is parsed */ +void IGDendelt(void * d, const char * name, int l) +{ + struct IGDdatas * datas = (struct IGDdatas *)d; + datas->level--; + /*printf("endelt %2d %.*s\n", datas->level, l, name);*/ + if( (l==7) && !memcmp(name, "service", l) ) + { + if(COMPARE(datas->tmp.servicetype, + "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:")) { + memcpy(&datas->CIF, &datas->tmp, sizeof(struct IGDdatas_service)); + } else if(COMPARE(datas->tmp.servicetype, + "urn:schemas-upnp-org:service:WANIPv6FirewallControl:")) { + memcpy(&datas->IPv6FC, &datas->tmp, sizeof(struct IGDdatas_service)); + } else if(COMPARE(datas->tmp.servicetype, + "urn:schemas-upnp-org:service:WANIPConnection:") + || COMPARE(datas->tmp.servicetype, + "urn:schemas-upnp-org:service:WANPPPConnection:") ) { + if(datas->first.servicetype[0] == '\0') { + memcpy(&datas->first, &datas->tmp, sizeof(struct IGDdatas_service)); + } else { + memcpy(&datas->second, &datas->tmp, sizeof(struct IGDdatas_service)); + } + } + } +} + +/* Data handler : + * copy data depending on the current element name and state */ +void IGDdata(void * d, const char * data, int l) +{ + struct IGDdatas * datas = (struct IGDdatas *)d; + char * dstmember = 0; + /*printf("%2d %s : %.*s\n", + datas->level, datas->cureltname, l, data); */ + if( !strcmp(datas->cureltname, "URLBase") ) + dstmember = datas->urlbase; + else if( !strcmp(datas->cureltname, "presentationURL") ) + dstmember = datas->presentationurl; + else if( !strcmp(datas->cureltname, "serviceType") ) + dstmember = datas->tmp.servicetype; + else if( !strcmp(datas->cureltname, "controlURL") ) + dstmember = datas->tmp.controlurl; + else if( !strcmp(datas->cureltname, "eventSubURL") ) + dstmember = datas->tmp.eventsuburl; + else if( !strcmp(datas->cureltname, "SCPDURL") ) + dstmember = datas->tmp.scpdurl; +/* else if( !strcmp(datas->cureltname, "deviceType") ) + dstmember = datas->devicetype_tmp;*/ + if(dstmember) + { + if(l>=MINIUPNPC_URL_MAXSIZE) + l = MINIUPNPC_URL_MAXSIZE-1; + memcpy(dstmember, data, l); + dstmember[l] = '\0'; + } +} + +#ifdef DEBUG +void printIGD(struct IGDdatas * d) +{ + printf("urlbase = '%s'\n", d->urlbase); + printf("WAN Device (Common interface config) :\n"); + /*printf(" deviceType = '%s'\n", d->CIF.devicetype);*/ + printf(" serviceType = '%s'\n", d->CIF.servicetype); + printf(" controlURL = '%s'\n", d->CIF.controlurl); + printf(" eventSubURL = '%s'\n", d->CIF.eventsuburl); + printf(" SCPDURL = '%s'\n", d->CIF.scpdurl); + printf("primary WAN Connection Device (IP or PPP Connection):\n"); + /*printf(" deviceType = '%s'\n", d->first.devicetype);*/ + printf(" servicetype = '%s'\n", d->first.servicetype); + printf(" controlURL = '%s'\n", d->first.controlurl); + printf(" eventSubURL = '%s'\n", d->first.eventsuburl); + printf(" SCPDURL = '%s'\n", d->first.scpdurl); + printf("secondary WAN Connection Device (IP or PPP Connection):\n"); + /*printf(" deviceType = '%s'\n", d->second.devicetype);*/ + printf(" servicetype = '%s'\n", d->second.servicetype); + printf(" controlURL = '%s'\n", d->second.controlurl); + printf(" eventSubURL = '%s'\n", d->second.eventsuburl); + printf(" SCPDURL = '%s'\n", d->second.scpdurl); + printf("WAN IPv6 Firewall Control :\n"); + /*printf(" deviceType = '%s'\n", d->IPv6FC.devicetype);*/ + printf(" servicetype = '%s'\n", d->IPv6FC.servicetype); + printf(" controlURL = '%s'\n", d->IPv6FC.controlurl); + printf(" eventSubURL = '%s'\n", d->IPv6FC.eventsuburl); + printf(" SCPDURL = '%s'\n", d->IPv6FC.scpdurl); +} +#endif /* DEBUG */ + diff --git a/ext/miniupnpc/igd_desc_parse.h b/ext/miniupnpc/igd_desc_parse.h new file mode 100644 index 00000000..0de546b6 --- /dev/null +++ b/ext/miniupnpc/igd_desc_parse.h @@ -0,0 +1,49 @@ +/* $Id: igd_desc_parse.h,v 1.12 2014/11/17 17:19:13 nanard Exp $ */ +/* Project : miniupnp + * http://miniupnp.free.fr/ + * Author : Thomas Bernard + * Copyright (c) 2005-2014 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. + * */ +#ifndef IGD_DESC_PARSE_H_INCLUDED +#define IGD_DESC_PARSE_H_INCLUDED + +/* Structure to store the result of the parsing of UPnP + * descriptions of Internet Gateway Devices */ +#define MINIUPNPC_URL_MAXSIZE (128) +struct IGDdatas_service { + char controlurl[MINIUPNPC_URL_MAXSIZE]; + char eventsuburl[MINIUPNPC_URL_MAXSIZE]; + char scpdurl[MINIUPNPC_URL_MAXSIZE]; + char servicetype[MINIUPNPC_URL_MAXSIZE]; + /*char devicetype[MINIUPNPC_URL_MAXSIZE];*/ +}; + +struct IGDdatas { + char cureltname[MINIUPNPC_URL_MAXSIZE]; + char urlbase[MINIUPNPC_URL_MAXSIZE]; + char presentationurl[MINIUPNPC_URL_MAXSIZE]; + int level; + /*int state;*/ + /* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */ + struct IGDdatas_service CIF; + /* "urn:schemas-upnp-org:service:WANIPConnection:1" + * "urn:schemas-upnp-org:service:WANPPPConnection:1" */ + struct IGDdatas_service first; + /* if both WANIPConnection and WANPPPConnection are present */ + struct IGDdatas_service second; + /* "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1" */ + struct IGDdatas_service IPv6FC; + /* tmp */ + struct IGDdatas_service tmp; +}; + +void IGDstartelt(void *, const char *, int); +void IGDendelt(void *, const char *, int); +void IGDdata(void *, const char *, int); +#ifdef DEBUG +void printIGD(struct IGDdatas *); +#endif /* DEBUG */ + +#endif /* IGD_DESC_PARSE_H_INCLUDED */ diff --git a/ext/miniupnpc/java/JavaBridgeTest.java b/ext/miniupnpc/java/JavaBridgeTest.java new file mode 100644 index 00000000..c658c599 --- /dev/null +++ b/ext/miniupnpc/java/JavaBridgeTest.java @@ -0,0 +1,97 @@ +import java.nio.ByteBuffer; +import java.nio.IntBuffer; + +import fr.free.miniupnp.*; + +/** + * + * @author syuu + */ +public class JavaBridgeTest { + public static void main(String[] args) { + int UPNP_DELAY = 2000; + MiniupnpcLibrary miniupnpc = MiniupnpcLibrary.INSTANCE; + UPNPDev devlist = null; + UPNPUrls urls = new UPNPUrls(); + IGDdatas data = new IGDdatas(); + ByteBuffer lanaddr = ByteBuffer.allocate(16); + ByteBuffer intClient = ByteBuffer.allocate(16); + ByteBuffer intPort = ByteBuffer.allocate(6); + ByteBuffer desc = ByteBuffer.allocate(80); + ByteBuffer enabled = ByteBuffer.allocate(4); + ByteBuffer leaseDuration = ByteBuffer.allocate(16); + int ret; + int i; + + if(args.length < 2) { + System.err.println("Usage : java [...] JavaBridgeTest port protocol"); + System.out.println(" port is numeric, protocol is TCP or UDP"); + return; + } + + devlist = miniupnpc.upnpDiscover(UPNP_DELAY, (String) null, (String) null, 0, 0, (byte)2, IntBuffer.allocate(1)); + if (devlist != null) { + System.out.println("List of UPNP devices found on the network :"); + for (UPNPDev device = devlist; device != null; device = device.pNext) { + System.out.println("desc: " + device.descURL.getString(0) + " st: " + device.st.getString(0)); + } + if ((i = miniupnpc.UPNP_GetValidIGD(devlist, urls, data, lanaddr, 16)) != 0) { + switch (i) { + case 1: + System.out.println("Found valid IGD : " + urls.controlURL.getString(0)); + break; + case 2: + System.out.println("Found a (not connected?) IGD : " + urls.controlURL.getString(0)); + System.out.println("Trying to continue anyway"); + break; + case 3: + System.out.println("UPnP device found. Is it an IGD ? : " + urls.controlURL.getString(0)); + System.out.println("Trying to continue anyway"); + break; + default: + System.out.println("Found device (igd ?) : " + urls.controlURL.getString(0)); + System.out.println("Trying to continue anyway"); + + } + System.out.println("Local LAN ip address : " + new String(lanaddr.array())); + ByteBuffer externalAddress = ByteBuffer.allocate(16); + miniupnpc.UPNP_GetExternalIPAddress(urls.controlURL.getString(0), + new String(data.first.servicetype), externalAddress); + System.out.println("ExternalIPAddress = " + new String(externalAddress.array())); + ret = miniupnpc.UPNP_AddPortMapping( + urls.controlURL.getString(0), // controlURL + new String(data.first.servicetype), // servicetype + args[0], // external Port + args[0], // internal Port + new String(lanaddr.array()), // internal client + "added via miniupnpc/JAVA !", // description + args[1], // protocol UDP or TCP + null, // remote host (useless) + "0"); // leaseDuration + if (ret != MiniupnpcLibrary.UPNPCOMMAND_SUCCESS) + System.out.println("AddPortMapping() failed with code " + ret); + ret = miniupnpc.UPNP_GetSpecificPortMappingEntry( + urls.controlURL.getString(0), new String(data.first.servicetype), + args[0], args[1], null, intClient, intPort, + desc, enabled, leaseDuration); + if (ret != MiniupnpcLibrary.UPNPCOMMAND_SUCCESS) + System.out.println("GetSpecificPortMappingEntry() failed with code " + ret); + System.out.println("InternalIP:Port = " + + new String(intClient.array()) + ":" + new String(intPort.array()) + + " (" + new String(desc.array()) + ")"); + ret = miniupnpc.UPNP_DeletePortMapping( + urls.controlURL.getString(0), + new String(data.first.servicetype), + args[0], args[1], null); + if (ret != MiniupnpcLibrary.UPNPCOMMAND_SUCCESS) + System.out.println("DelPortMapping() failed with code " + ret); + miniupnpc.FreeUPNPUrls(urls); + } else { + System.out.println("No valid UPNP Internet Gateway Device found."); + } + miniupnpc.freeUPNPDevlist(devlist); + } else { + System.out.println("No IGD UPnP Device found on the network !\n"); + } + } +} diff --git a/ext/miniupnpc/java/testjava.bat b/ext/miniupnpc/java/testjava.bat new file mode 100755 index 00000000..b836da14 --- /dev/null +++ b/ext/miniupnpc/java/testjava.bat @@ -0,0 +1,8 @@ +@echo off +set JAVA=java +set JAVAC=javac +REM notice the semicolon for Windows. Write once, run ... oh nevermind +set CP=miniupnpc_win32.jar;. + +%JAVAC% -cp "%CP%" JavaBridgeTest.java || exit 1 +%JAVA% -cp "%CP%" JavaBridgeTest 12345 UDP || exit 1 diff --git a/ext/miniupnpc/java/testjava.sh b/ext/miniupnpc/java/testjava.sh new file mode 100755 index 00000000..9880523a --- /dev/null +++ b/ext/miniupnpc/java/testjava.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +JAVA=java +JAVAC=javac +CP=$(for i in *.jar; do echo -n $i:; done). + +$JAVAC -cp $CP JavaBridgeTest.java || exit 1 +$JAVA -cp $CP JavaBridgeTest 12345 UDP || exit 1 diff --git a/ext/miniupnpc/listdevices.c b/ext/miniupnpc/listdevices.c new file mode 100644 index 00000000..a93c29ff --- /dev/null +++ b/ext/miniupnpc/listdevices.c @@ -0,0 +1,110 @@ +/* $Id: listdevices.c,v 1.7 2015/10/08 16:15:47 nanard Exp $ */ +/* Project : miniupnp + * Author : Thomas Bernard + * Copyright (c) 2013-2015 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. */ + +#include +#include +#include +#ifdef _WIN32 +#include +#endif /* _WIN32 */ +#include "miniupnpc.h" + +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; + 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 ...]\n", argv[0]); + printf("options :\n"); + printf(" -6 : use IPv6\n"); + printf(" -m address/ifname : network interface to use for multicast\n"); + printf(" -d : search only for this type of device\n"); + printf(" -l ... : 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); + } + freeUPNPDevlist(devlist); + } else { + printf("no device found.\n"); + } + + return 0; +} + diff --git a/ext/miniupnpc/man3/miniupnpc.3 b/ext/miniupnpc/man3/miniupnpc.3 new file mode 100644 index 00000000..7b997d47 --- /dev/null +++ b/ext/miniupnpc/man3/miniupnpc.3 @@ -0,0 +1,55 @@ +.TH MINIUPNPC 3 +.SH NAME +miniupnpc \- UPnP client library +.SH SYNOPSIS +.SH DESCRIPTION +The miniupnpc library implement the UPnP protocol defined +to dialog with Internet Gateway Devices. It also has +the ability to use data gathered by minissdpd(1) about +UPnP devices up on the network in order to skip the +long UPnP device discovery process. +.PP +At first, upnpDiscover(3) has to be used to discover UPnP IGD present +on the network. Then UPNP_GetValidIGD(3) to select the right one. +Alternatively, UPNP_GetIGDFromUrl(3) could be used to bypass discovery +process if the root description url of the device to use is known. +Then all the UPNP_* functions can be used, such as +UPNP_GetConnectionTypeInfo(3), UPNP_AddPortMapping(3), etc... +.SH "HEADER FILES" +.IP miniupnpc.h +That's the main header file for the miniupnpc library API. +It contains all the functions and structures related to device discovery. +.IP upnpcommands.h +This header file contain the UPnP IGD methods that are accessible +through the miniupnpc API. The name of the C functions are matching +the UPnP methods names. ie: GetGenericPortMappingEntry is +UPNP_GetGenericPortMappingEntry. +.SH "API FUNCTIONS" +.IP "struct UPNPDev * upnpDiscover(int delay, const char * multicastif, const char * minissdpdsock, int localport, int ipv6, int * error);" +execute the discovery process. +delay (in millisecond) is the maximum time for waiting any device response. +If available, device list will be obtained from MiniSSDPd. +Default path for minissdpd socket will be used if minissdpdsock argument is NULL. +If multicastif is not NULL, it will be used instead of the default multicast interface for sending SSDP discover packets. +If localport is set to UPNP_LOCAL_PORT_SAME(1) SSDP packets will be sent +from the source port 1900 (same as destination port), if set to +UPNP_LOCAL_PORT_ANY(0) system assign a source port, any other value will +be attempted as the source port. +If ipv6 is not 0, IPv6 is used instead of IPv4 for the discovery process. +.IP "void freeUPNPDevlist(struct UPNPDev * devlist);" +free the list returned by upnpDiscover(). +.IP "int UPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen);" +browse the list of device returned by upnpDiscover(), find +a live UPnP internet gateway device and fill structures passed as arguments +with data used for UPNP methods invokation. +.IP "int UPNP_GetIGDFromUrl(const char * rootdescurl, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen);" +permit to bypass the upnpDiscover() call if the xml root description +URL of the UPnP IGD is known. +Fill structures passed as arguments +with data used for UPNP methods invokation. +.IP "void GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, const char *);" +.IP "void FreeUPNPUrls(struct UPNPUrls *);" + +.SH "SEE ALSO" +minissdpd(1) +.SH BUGS diff --git a/ext/miniupnpc/mingw32make.bat b/ext/miniupnpc/mingw32make.bat new file mode 100644 index 00000000..c5d3cc4f --- /dev/null +++ b/ext/miniupnpc/mingw32make.bat @@ -0,0 +1,8 @@ +@mingw32-make -f Makefile.mingw %1 +@if errorlevel 1 goto end +@if not exist upnpc-static.exe goto end +@strip upnpc-static.exe +@upx --best upnpc-static.exe +@strip upnpc-shared.exe +@upx --best upnpc-shared.exe +:end diff --git a/ext/miniupnpc/minihttptestserver.c b/ext/miniupnpc/minihttptestserver.c new file mode 100644 index 00000000..32e3cb78 --- /dev/null +++ b/ext/miniupnpc/minihttptestserver.c @@ -0,0 +1,655 @@ +/* $Id: minihttptestserver.c,v 1.18 2015/07/15 12:41:15 nanard Exp $ */ +/* Project : miniUPnP + * Author : Thomas Bernard + * Copyright (c) 2011-2015 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. + * */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CRAP_LENGTH (2048) + +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, int 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, int n) +{ + static const char crap[] = "_CRAP_\r\n"; + int 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(int content_length, int * response_len) +{ + char * response_buffer; + char * content_buffer; + int buffer_length; + int i, 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=%d buffer_length=%d content_length=%d\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(char * p, int 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 +}; + +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_INVALID, NULL} +}; + +/** + * write the response with random behaviour ! + */ +void send_response(int c, const char * buffer, int len) +{ + int n; + while(len > 0) { + n = (rand() % 99) + 1; + if(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]; + int request_len = 0; + int headers_found = 0; + int n, i; + char request_method[16]; + char request_uri[256]; + char http_version[16]; + char * p; + char * response_buffer; + int response_len; + enum modes mode; + int content_length = 16*1024; + + /* read the request */ + while(request_len < (int)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", request_len, request_buffer); + /* the request have been received, now parse the request line */ + p = request_buffer; + for(i = 0; i < (int)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) { + i = write(c, pc, n); + if(i<0) { + if(errno != EINTR) { + perror("write"); + return; + } + } else { + n -= i; + pc += i; + } + } + 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_CHUNKED: + response_buffer = build_chunked_response(content_length, &response_len); + break; + case MODE_ADDCRAP: + response_len = content_length+256; + response_buffer = malloc(response_len); + if(!response_buffer) + break; + n = snprintf(response_buffer, response_len, + "HTTP/1.1 200 OK\r\n" + "Server: minihttptestserver\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: %d\r\n" + "\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: %d\r\n" + "\r\n", content_length); + /* image/x-icon */ + build_favicon_content(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 s, c, i; + unsigned short port = 0; + struct sockaddr_storage server_addr; + socklen_t server_addrlen; + struct sockaddr_storage client_addr; + socklen_t client_addrlen; + pid_t pid; + int child = 0; + int status; + const char * expected_file_name = NULL; + struct sigaction sa; + + 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, "unkown command line argument '%s'\n", argv[i]); + } + } + + srand(time(NULL)); + + 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", 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", pid, status); + } + --child_to_wait_for; + } + printf("Bye...\n"); + } + return 0; +} + diff --git a/ext/miniupnpc/minisoap.c b/ext/miniupnpc/minisoap.c new file mode 100644 index 00000000..0b56558e --- /dev/null +++ b/ext/miniupnpc/minisoap.c @@ -0,0 +1,123 @@ +/* $Id: minisoap.c,v 1.24 2015/10/26 17:05:07 nanard Exp $ */ +/* Project : miniupnp + * Author : Thomas Bernard + * Copyright (c) 2005-2015 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. + * + * Minimal SOAP implementation for UPnP protocol. + */ +#include +#include +#ifdef _WIN32 +#include +#include +#define snprintf _snprintf +#else +#include +#include +#include +#endif +#include "minisoap.h" +#include "miniupnpcstrings.h" + +/* only for malloc */ +#include + +#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, + const char * headers, int headerssize) +{ + int n = 0; + /*n = write(fd, headers, headerssize);*/ + /*if(bodysize>0) + n += write(fd, body, bodysize);*/ + /* Note : my old linksys router only took into account + * soap request that are sent into only one packet */ + char * p; + /* TODO: AVOID MALLOC, we could use writev() for that */ + p = malloc(headerssize+bodysize); + if(!p) + return -1; + memcpy(p, headers, headerssize); + memcpy(p+headerssize, body, bodysize); + /*n = write(fd, p, headerssize+bodysize);*/ + n = send(fd, p, headerssize+bodysize, 0); + if(n<0) { + PRINT_SOCKET_ERROR("send"); + } + /* disable send on the socket */ + /* draytek routers dont seems to like that... */ +#if 0 +#ifdef _WIN32 + if(shutdown(fd, SD_SEND)<0) { +#else + if(shutdown(fd, SHUT_WR)<0) { /*SD_SEND*/ +#endif + PRINT_SOCKET_ERROR("shutdown"); + } +#endif + free(p); + return n; +} + +/* self explanatory */ +int soapPostSubmit(int fd, + const char * url, + const char * host, + unsigned short port, + const char * action, + const char * body, + const char * httpversion) +{ + int bodysize; + char headerbuf[512]; + int headerssize; + char portstr[8]; + 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 */ + 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" + "Content-Length: %d\r\n" + "Content-Type: text/xml\r\n" + "SOAPAction: \"%s\"\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); + */ + printf("SOAP request : POST %s HTTP/%s - Host: %s%s\n", + url, httpversion, host, portstr); + printf("SOAPAction: \"%s\" - Content-Length: %d\n", action, bodysize); + printf("Headers :\n%s", headerbuf); + printf("Body :\n%s\n", body); +#endif + return httpWrite(fd, body, bodysize, headerbuf, headerssize); +} + + diff --git a/ext/miniupnpc/minisoap.h b/ext/miniupnpc/minisoap.h new file mode 100644 index 00000000..14c859d1 --- /dev/null +++ b/ext/miniupnpc/minisoap.h @@ -0,0 +1,15 @@ +/* $Id: minisoap.h,v 1.5 2012/09/27 15:42:10 nanard Exp $ */ +/* Project : miniupnp + * Author : Thomas Bernard + * Copyright (c) 2005 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. */ +#ifndef MINISOAP_H_INCLUDED +#define MINISOAP_H_INCLUDED + +/*int httpWrite(int, const char *, int, const char *);*/ +int soapPostSubmit(int, const char *, const char *, unsigned short, + const char *, const char *, const char *); + +#endif + diff --git a/ext/miniupnpc/minissdpc.c b/ext/miniupnpc/minissdpc.c new file mode 100644 index 00000000..5a426739 --- /dev/null +++ b/ext/miniupnpc/minissdpc.c @@ -0,0 +1,849 @@ +/* $Id: minissdpc.c,v 1.30 2015/10/26 17:05:07 nanard Exp $ */ +/* Project : miniupnp + * Web : http://miniupnp.free.fr/ + * Author : Thomas BERNARD + * copyright (c) 2005-2015 Thomas Bernard + * This software is subjet to the conditions detailed in the + * provided LICENCE file. */ +/*#include */ +#include +#include +#include +#include +#if defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__) +#ifdef _WIN32 +#include +#include +#include +#include +#include +#define snprintf _snprintf +#if !defined(_MSC_VER) +#include +#else /* !defined(_MSC_VER) */ +typedef unsigned short uint16_t; +#endif /* !defined(_MSC_VER) */ +#ifndef strncasecmp +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#define strncasecmp _memicmp +#else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ +#define strncasecmp memicmp +#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ +#endif /* #ifndef strncasecmp */ +#endif /* _WIN32 */ +#if defined(__amigaos__) || defined(__amigaos4__) +#include +#endif /* defined(__amigaos__) || defined(__amigaos4__) */ +#if defined(__amigaos__) +#define uint16_t unsigned short +#endif /* defined(__amigaos__) */ +/* Hack */ +#define UNIX_PATH_LEN 108 +struct sockaddr_un { + uint16_t sun_family; + char sun_path[UNIX_PATH_LEN]; +}; +#else /* defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__) */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define closesocket close +#endif + +#ifdef _WIN32 +#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); +#else +#define PRINT_SOCKET_ERROR(x) perror(x) +#endif + +#if !defined(__DragonFly__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__APPLE__) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__sun) && !defined(__GNU__) && !defined(__FreeBSD_kernel__) +#define HAS_IP_MREQN +#endif + +#if defined(HAS_IP_MREQN) && defined(NEED_STRUCT_IP_MREQN) +/* Several versions of glibc don't define this structure, + * define it here and compile with CFLAGS NEED_STRUCT_IP_MREQN */ +struct ip_mreqn +{ + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_address; /* local IP address of interface */ + int imr_ifindex; /* Interface index */ +}; +#endif + +#if defined(__amigaos__) || defined(__amigaos4__) +/* Amiga OS specific stuff */ +#define TIMEVAL struct timeval +#endif + +#include "minissdpc.h" +#include "miniupnpc.h" +#include "receivedata.h" + +#if !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)) + +#include "codelength.h" + +struct UPNPDev * +getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath, int * error) +{ + struct UPNPDev * devlist = NULL; + int s; + int res; + + s = connectToMiniSSDPD(socketpath); + if (s < 0) { + if (error) + *error = s; + return NULL; + } + res = requestDevicesFromMiniSSDPD(s, devtype); + if (res < 0) { + if (error) + *error = res; + } else { + devlist = receiveDevicesFromMiniSSDPD(s, error); + } + disconnectFromMiniSSDPD(s); + return devlist; +} + +/* macros used to read from unix socket */ +#define READ_BYTE_BUFFER(c) \ + if((int)bufferindex >= n) { \ + n = read(s, buffer, sizeof(buffer)); \ + if(n<=0) break; \ + bufferindex = 0; \ + } \ + c = buffer[bufferindex++]; + +#ifndef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif /* MIN */ + +#define READ_COPY_BUFFER(dst, len) \ + for(l = len, p = (unsigned char *)dst; l > 0; ) { \ + unsigned int lcopy; \ + if((int)bufferindex >= n) { \ + n = read(s, buffer, sizeof(buffer)); \ + if(n<=0) break; \ + bufferindex = 0; \ + } \ + lcopy = MIN(l, (n - bufferindex)); \ + memcpy(p, buffer + bufferindex, lcopy); \ + l -= lcopy; \ + p += lcopy; \ + bufferindex += lcopy; \ + } + +#define READ_DISCARD_BUFFER(len) \ + for(l = len; l > 0; ) { \ + unsigned int lcopy; \ + if(bufferindex >= n) { \ + n = read(s, buffer, sizeof(buffer)); \ + if(n<=0) break; \ + bufferindex = 0; \ + } \ + lcopy = MIN(l, (n - bufferindex)); \ + l -= lcopy; \ + bufferindex += lcopy; \ + } + +int +connectToMiniSSDPD(const char * socketpath) +{ + int s; + struct sockaddr_un addr; +#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT + struct timeval timeout; +#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ + + s = socket(AF_UNIX, SOCK_STREAM, 0); + if(s < 0) + { + /*syslog(LOG_ERR, "socket(unix): %m");*/ + perror("socket(unix)"); + return MINISSDPC_SOCKET_ERROR; + } +#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT + /* setting a 3 seconds timeout */ + timeout.tv_sec = 3; + timeout.tv_usec = 0; + if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) + { + perror("setsockopt"); + } + timeout.tv_sec = 3; + timeout.tv_usec = 0; + if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) + { + perror("setsockopt"); + } +#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ + if(!socketpath) + socketpath = "/var/run/minissdpd.sock"; + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, socketpath, sizeof(addr.sun_path)); + /* TODO : check if we need to handle the EINTR */ + if(connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) + { + /*syslog(LOG_WARNING, "connect(\"%s\"): %m", socketpath);*/ + close(s); + return MINISSDPC_SOCKET_ERROR; + } + return s; +} + +int +disconnectFromMiniSSDPD(int s) +{ + if (close(s) < 0) + return MINISSDPC_SOCKET_ERROR; + return MINISSDPC_SUCCESS; +} + +int +requestDevicesFromMiniSSDPD(int s, const char * devtype) +{ + unsigned char buffer[256]; + unsigned char * p; + unsigned int stsize, l; + + stsize = strlen(devtype); + if(stsize == 8 && 0 == memcmp(devtype, "ssdp:all", 8)) + { + buffer[0] = 3; /* request type 3 : everything */ + } + else + { + buffer[0] = 1; /* request type 1 : request devices/services by type */ + } + p = buffer + 1; + l = stsize; CODELENGTH(l, p); + if(p + stsize > buffer + sizeof(buffer)) + { + /* devtype is too long ! */ +#ifdef DEBUG + fprintf(stderr, "devtype is too long ! stsize=%u sizeof(buffer)=%u\n", + stsize, (unsigned)sizeof(buffer)); +#endif /* DEBUG */ + return MINISSDPC_INVALID_INPUT; + } + memcpy(p, devtype, stsize); + p += stsize; + if(write(s, buffer, p - buffer) < 0) + { + /*syslog(LOG_ERR, "write(): %m");*/ + perror("minissdpc.c: write()"); + return MINISSDPC_SOCKET_ERROR; + } + return MINISSDPC_SUCCESS; +} + +struct UPNPDev * +receiveDevicesFromMiniSSDPD(int s, int * error) +{ + struct UPNPDev * tmp; + struct UPNPDev * devlist = NULL; + unsigned char buffer[256]; + ssize_t n; + unsigned char * p; + unsigned char * url; + unsigned char * st; + unsigned int bufferindex; + unsigned int i, ndev; + unsigned int urlsize, stsize, usnsize, l; + + n = read(s, buffer, sizeof(buffer)); + if(n<=0) + { + perror("minissdpc.c: read()"); + if (error) + *error = MINISSDPC_SOCKET_ERROR; + return NULL; + } + ndev = buffer[0]; + bufferindex = 1; + for(i = 0; i < ndev; i++) + { + DECODELENGTH_READ(urlsize, READ_BYTE_BUFFER); + if(n<=0) { + if (error) + *error = MINISSDPC_INVALID_SERVER_REPLY; + return devlist; + } +#ifdef DEBUG + printf(" urlsize=%u", urlsize); +#endif /* DEBUG */ + url = malloc(urlsize); + if(url == NULL) { + if (error) + *error = MINISSDPC_MEMORY_ERROR; + return devlist; + } + READ_COPY_BUFFER(url, urlsize); + if(n<=0) { + if (error) + *error = MINISSDPC_INVALID_SERVER_REPLY; + goto free_url_and_return; + } + DECODELENGTH_READ(stsize, READ_BYTE_BUFFER); + if(n<=0) { + if (error) + *error = MINISSDPC_INVALID_SERVER_REPLY; + goto free_url_and_return; + } +#ifdef DEBUG + printf(" stsize=%u", stsize); +#endif /* DEBUG */ + st = malloc(stsize); + if (st == NULL) { + if (error) + *error = MINISSDPC_MEMORY_ERROR; + goto free_url_and_return; + } + READ_COPY_BUFFER(st, stsize); + if(n<=0) { + if (error) + *error = MINISSDPC_INVALID_SERVER_REPLY; + goto free_url_and_st_and_return; + } + DECODELENGTH_READ(usnsize, READ_BYTE_BUFFER); + if(n<=0) { + if (error) + *error = MINISSDPC_INVALID_SERVER_REPLY; + goto free_url_and_st_and_return; + } +#ifdef DEBUG + printf(" usnsize=%u\n", usnsize); +#endif /* DEBUG */ + tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize); + if(tmp == NULL) { + if (error) + *error = MINISSDPC_MEMORY_ERROR; + goto free_url_and_st_and_return; + } + tmp->pNext = devlist; + tmp->descURL = tmp->buffer; + tmp->st = tmp->buffer + 1 + urlsize; + memcpy(tmp->buffer, url, urlsize); + tmp->buffer[urlsize] = '\0'; + memcpy(tmp->st, st, stsize); + tmp->buffer[urlsize+1+stsize] = '\0'; + free(url); + free(st); + url = NULL; + st = NULL; + tmp->usn = tmp->buffer + 1 + urlsize + 1 + stsize; + READ_COPY_BUFFER(tmp->usn, usnsize); + if(n<=0) { + if (error) + *error = MINISSDPC_INVALID_SERVER_REPLY; + goto free_tmp_and_return; + } + tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0'; + tmp->scope_id = 0; /* default value. scope_id is not available with MiniSSDPd */ + devlist = tmp; + } + if (error) + *error = MINISSDPC_SUCCESS; + return devlist; + +free_url_and_st_and_return: + free(st); +free_url_and_return: + free(url); + return devlist; + +free_tmp_and_return: + free(tmp); + return devlist; +} + +#endif /* !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)) */ + +/* parseMSEARCHReply() + * the last 4 arguments are filled during the parsing : + * - location/locationsize : "location:" field of the SSDP reply packet + * - st/stsize : "st:" field of the SSDP reply packet. + * The strings are NOT null terminated */ +static void +parseMSEARCHReply(const char * reply, int size, + const char * * location, int * locationsize, + const char * * st, int * stsize, + const char * * usn, int * usnsize) +{ + int a, b, i; + i = 0; + a = i; /* start of the line */ + b = 0; /* end of the "header" (position of the colon) */ + while(isin6_family = AF_INET6; + if(localport > 0 && localport < 65536) + p->sin6_port = htons((unsigned short)localport); + p->sin6_addr = in6addr_any; /* in6addr_any is not available with MinGW32 3.4.2 */ + } else { + struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_r; + p->sin_family = AF_INET; + if(localport > 0 && localport < 65536) + p->sin_port = htons((unsigned short)localport); + p->sin_addr.s_addr = INADDR_ANY; + } +#ifdef _WIN32 +/* This code could help us to use the right Network interface for + * SSDP multicast traffic */ +/* Get IP associated with the index given in the ip_forward struct + * in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */ + if(!ipv6 + && (GetBestRoute(inet_addr("223.255.255.255"), 0, &ip_forward) == NO_ERROR)) { + DWORD dwRetVal = 0; + PMIB_IPADDRTABLE pIPAddrTable; + DWORD dwSize = 0; +#ifdef DEBUG + IN_ADDR IPAddr; +#endif + int i; +#ifdef DEBUG + printf("ifIndex=%lu nextHop=%lx \n", ip_forward.dwForwardIfIndex, ip_forward.dwForwardNextHop); +#endif + pIPAddrTable = (MIB_IPADDRTABLE *) malloc(sizeof (MIB_IPADDRTABLE)); + if(pIPAddrTable) { + if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) { + free(pIPAddrTable); + pIPAddrTable = (MIB_IPADDRTABLE *) malloc(dwSize); + } + } + if(pIPAddrTable) { + dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 ); + if (dwRetVal == NO_ERROR) { +#ifdef DEBUG + printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries); +#endif + for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) { +#ifdef DEBUG + printf("\n\tInterface Index[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwIndex); + IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr; + printf("\tIP Address[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); + IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask; + printf("\tSubnet Mask[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); + IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr; + printf("\tBroadCast[%d]: \t%s (%ld)\n", i, inet_ntoa(IPAddr), pIPAddrTable->table[i].dwBCastAddr); + printf("\tReassembly size[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwReasmSize); + printf("\tType and State[%d]:", i); + printf("\n"); +#endif + if (pIPAddrTable->table[i].dwIndex == ip_forward.dwForwardIfIndex) { + /* Set the address of this interface to be used */ + struct in_addr mc_if; + memset(&mc_if, 0, sizeof(mc_if)); + mc_if.s_addr = pIPAddrTable->table[i].dwAddr; + if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) { + PRINT_SOCKET_ERROR("setsockopt"); + } + ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = pIPAddrTable->table[i].dwAddr; +#ifndef DEBUG + break; +#endif + } + } + } + free(pIPAddrTable); + pIPAddrTable = NULL; + } + } +#endif /* _WIN32 */ + +#ifdef _WIN32 + if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0) +#else + if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0) +#endif + { + if(error) + *error = MINISSDPC_SOCKET_ERROR; + PRINT_SOCKET_ERROR("setsockopt(SO_REUSEADDR,...)"); + return NULL; + } + +#ifdef _WIN32 + if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&_ttl, sizeof(_ttl)) < 0) +#else /* _WIN32 */ + if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) +#endif /* _WIN32 */ + { + /* not a fatal error */ + PRINT_SOCKET_ERROR("setsockopt(IP_MULTICAST_TTL,...)"); + } + + if(multicastif) + { + if(ipv6) { +#if !defined(_WIN32) + /* according to MSDN, if_nametoindex() is supported since + * MS Windows Vista and MS Windows Server 2008. + * http://msdn.microsoft.com/en-us/library/bb408409%28v=vs.85%29.aspx */ + unsigned int ifindex = if_nametoindex(multicastif); /* eth0, etc. */ + if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) < 0) + { + PRINT_SOCKET_ERROR("setsockopt"); + } +#else +#ifdef DEBUG + printf("Setting of multicast interface not supported in IPv6 under Windows.\n"); +#endif +#endif + } else { + struct in_addr mc_if; + mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */ + if(mc_if.s_addr != INADDR_NONE) + { + ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr; + if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) + { + PRINT_SOCKET_ERROR("setsockopt"); + } + } else { +#ifdef HAS_IP_MREQN + /* was not an ip address, try with an interface name */ + struct ip_mreqn reqn; /* only defined with -D_BSD_SOURCE or -D_GNU_SOURCE */ + memset(&reqn, 0, sizeof(struct ip_mreqn)); + reqn.imr_ifindex = if_nametoindex(multicastif); + if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0) + { + PRINT_SOCKET_ERROR("setsockopt"); + } +#else +#ifdef DEBUG + printf("Setting of multicast interface not supported with interface name.\n"); +#endif +#endif + } + } + } + + /* Before sending the packed, we first "bind" in order to be able + * to receive the response */ + if (bind(sudp, (const struct sockaddr *)&sockudp_r, + ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) != 0) + { + if(error) + *error = MINISSDPC_SOCKET_ERROR; + PRINT_SOCKET_ERROR("bind"); + closesocket(sudp); + return NULL; + } + + if(error) + *error = MINISSDPC_SUCCESS; + /* Calculating maximum response time in seconds */ + mx = ((unsigned int)delay) / 1000u; + if(mx == 0) { + mx = 1; + delay = 1000; + } + /* receiving SSDP response packet */ + for(deviceIndex = 0; deviceTypes[deviceIndex]; deviceIndex++) { + /* sending the SSDP M-SEARCH packet */ + n = snprintf(bufr, sizeof(bufr), + MSearchMsgFmt, + ipv6 ? + (linklocal ? "[" UPNP_MCAST_LL_ADDR "]" : "[" UPNP_MCAST_SL_ADDR "]") + : UPNP_MCAST_ADDR, + deviceTypes[deviceIndex], mx); + 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", + ipv6 ? + (linklocal ? "[" UPNP_MCAST_LL_ADDR "]" : "[" UPNP_MCAST_SL_ADDR "]") + : UPNP_MCAST_ADDR, + deviceTypes[deviceIndex]); +#endif +#ifdef NO_GETADDRINFO + /* the following code is not using getaddrinfo */ + /* emission */ + memset(&sockudp_w, 0, sizeof(struct sockaddr_storage)); + if(ipv6) { + struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_w; + p->sin6_family = AF_INET6; + p->sin6_port = htons(SSDP_PORT); + inet_pton(AF_INET6, + linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR, + &(p->sin6_addr)); + } else { + struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_w; + p->sin_family = AF_INET; + p->sin_port = htons(SSDP_PORT); + p->sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR); + } + n = sendto(sudp, bufr, n, 0, &sockudp_w, + ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)); + if (n < 0) { + if(error) + *error = MINISSDPC_SOCKET_ERROR; + PRINT_SOCKET_ERROR("sendto"); + break; + } +#else /* #ifdef NO_GETADDRINFO */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; /* AF_INET6 or AF_INET */ + hints.ai_socktype = SOCK_DGRAM; + /*hints.ai_flags = */ + if ((rv = getaddrinfo(ipv6 + ? (linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR) + : UPNP_MCAST_ADDR, + XSTR(SSDP_PORT), &hints, &servinfo)) != 0) { + if(error) + *error = MINISSDPC_SOCKET_ERROR; +#ifdef _WIN32 + fprintf(stderr, "getaddrinfo() failed: %d\n", rv); +#else + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); +#endif + break; + } + for(p = servinfo; p; p = p->ai_next) { + n = sendto(sudp, bufr, n, 0, p->ai_addr, p->ai_addrlen); + if (n < 0) { +#ifdef DEBUG + char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; + if (getnameinfo(p->ai_addr, p->ai_addrlen, hbuf, sizeof(hbuf), sbuf, + sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0) { + fprintf(stderr, "host:%s port:%s\n", hbuf, sbuf); + } +#endif + PRINT_SOCKET_ERROR("sendto"); + continue; + } + } + freeaddrinfo(servinfo); + if(n < 0) { + if(error) + *error = MINISSDPC_SOCKET_ERROR; + break; + } +#endif /* #ifdef NO_GETADDRINFO */ + /* Waiting for SSDP REPLY packet to M-SEARCH + * if searchalltypes is set, enter the loop only + * when the last deviceType is reached */ + if(!searchalltypes || !deviceTypes[deviceIndex + 1]) do { + n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id); + if (n < 0) { + /* error */ + if(error) + *error = MINISSDPC_SOCKET_ERROR; + goto error; + } else if (n == 0) { + /* no data or Time Out */ +#ifdef DEBUG + printf("NODATA or TIMEOUT\n"); +#endif /* DEBUG */ + if (devlist && !searchalltypes) { + /* found some devices, stop now*/ + if(error) + *error = MINISSDPC_SUCCESS; + goto error; + } + } else { + const char * descURL=NULL; + int urlsize=0; + const char * st=NULL; + int stsize=0; + const char * usn=NULL; + int usnsize=0; + parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize, &usn, &usnsize); + if(st&&descURL) { +#ifdef DEBUG + printf("M-SEARCH Reply:\n ST: %.*s\n USN: %.*s\n Location: %.*s\n", + stsize, st, usnsize, (usn?usn:""), urlsize, descURL); +#endif /* DEBUG */ + for(tmp=devlist; tmp; tmp = tmp->pNext) { + if(memcmp(tmp->descURL, descURL, urlsize) == 0 && + tmp->descURL[urlsize] == '\0' && + memcmp(tmp->st, st, stsize) == 0 && + tmp->st[stsize] == '\0' && + (usnsize == 0 || memcmp(tmp->usn, usn, usnsize) == 0) && + tmp->usn[usnsize] == '\0') + break; + } + /* at the exit of the loop above, tmp is null if + * no duplicate device was found */ + if(tmp) + continue; + tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize); + if(!tmp) { + /* memory allocation error */ + if(error) + *error = MINISSDPC_MEMORY_ERROR; + goto error; + } + tmp->pNext = devlist; + tmp->descURL = tmp->buffer; + tmp->st = tmp->buffer + 1 + urlsize; + tmp->usn = tmp->st + 1 + stsize; + memcpy(tmp->buffer, descURL, urlsize); + tmp->buffer[urlsize] = '\0'; + memcpy(tmp->st, st, stsize); + tmp->buffer[urlsize+1+stsize] = '\0'; + if(usn != NULL) + memcpy(tmp->usn, usn, usnsize); + tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0'; + tmp->scope_id = scope_id; + devlist = tmp; + } + } + } while(n > 0); + if(ipv6) { + /* switch linklocal flag */ + if(linklocal) { + linklocal = 0; + --deviceIndex; + } else { + linklocal = 1; + } + } + } +error: + closesocket(sudp); + return devlist; +} + diff --git a/ext/miniupnpc/minissdpc.h b/ext/miniupnpc/minissdpc.h new file mode 100644 index 00000000..a5c622b2 --- /dev/null +++ b/ext/miniupnpc/minissdpc.h @@ -0,0 +1,58 @@ +/* $Id: minissdpc.h,v 1.7 2015/10/08 16:15:47 nanard Exp $ */ +/* Project: miniupnp + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * Author: Thomas Bernard + * Copyright (c) 2005-2015 Thomas Bernard + * This software is subjects to the conditions detailed + * in the LICENCE file provided within this distribution */ +#ifndef MINISSDPC_H_INCLUDED +#define MINISSDPC_H_INCLUDED + +#include "miniupnpc_declspec.h" +#include "upnpdev.h" + +/* error codes : */ +#define MINISSDPC_SUCCESS (0) +#define MINISSDPC_UNKNOWN_ERROR (-1) +#define MINISSDPC_SOCKET_ERROR (-101) +#define MINISSDPC_MEMORY_ERROR (-102) +#define MINISSDPC_INVALID_INPUT (-103) +#define MINISSDPC_INVALID_SERVER_REPLY (-104) + +#ifdef __cplusplus +extern "C" { +#endif + +#if !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)) + +MINIUPNP_LIBSPEC struct UPNPDev * +getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath, int * error); + +MINIUPNP_LIBSPEC int +connectToMiniSSDPD(const char * socketpath); + +MINIUPNP_LIBSPEC int +disconnectFromMiniSSDPD(int fd); + +MINIUPNP_LIBSPEC int +requestDevicesFromMiniSSDPD(int fd, const char * devtype); + +MINIUPNP_LIBSPEC struct UPNPDev * +receiveDevicesFromMiniSSDPD(int fd, int * error); + +#endif /* !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)) */ + +MINIUPNP_LIBSPEC struct UPNPDev * +ssdpDiscoverDevices(const char * const deviceTypes[], + int delay, const char * multicastif, + int localport, + int ipv6, unsigned char ttl, + int * error, + int searchalltypes); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/ext/miniupnpc/miniupnpc.c b/ext/miniupnpc/miniupnpc.c new file mode 100644 index 00000000..4837fe7d --- /dev/null +++ b/ext/miniupnpc/miniupnpc.c @@ -0,0 +1,684 @@ +/* $Id: miniupnpc.c,v 1.141 2015/10/26 17:05:07 nanard Exp $ */ +/* vim: tabstop=4 shiftwidth=4 noexpandtab */ +/* Project : miniupnp + * Web : http://miniupnp.free.fr/ + * Author : Thomas BERNARD + * copyright (c) 2005-2015 Thomas Bernard + * This software is subjet to the conditions detailed in the + * provided LICENSE file. */ +#include +#include +#include +#ifdef _WIN32 +/* Win32 Specific includes and defines */ +#include +#include +#include +#include +#define snprintf _snprintf +#define strdup _strdup +#ifndef strncasecmp +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#define strncasecmp _memicmp +#else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ +#define strncasecmp memicmp +#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ +#endif /* #ifndef strncasecmp */ +#define MAXHOSTNAMELEN 64 +#else /* #ifdef _WIN32 */ +/* Standard POSIX includes */ +#include +#if defined(__amigaos__) && !defined(__amigaos4__) +/* Amiga OS 3 specific stuff */ +#define socklen_t int +#else +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#if !defined(__amigaos__) && !defined(__amigaos4__) +#include +#endif +#include +#include +#define closesocket close +#endif /* #else _WIN32 */ +#ifdef __GNU__ +#define MAXHOSTNAMELEN 64 +#endif + + +#include "miniupnpc.h" +#include "minissdpc.h" +#include "miniwget.h" +#include "minisoap.h" +#include "minixml.h" +#include "upnpcommands.h" +#include "connecthostport.h" + +/* compare the begining of a string with a constant string */ +#define COMPARE(str, cstr) (0==memcmp(str, cstr, sizeof(cstr) - 1)) + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#define SOAPPREFIX "s" +#define SERVICEPREFIX "u" +#define SERVICEPREFIX2 'u' + +/* root description parsing */ +MINIUPNP_LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data) +{ + struct xmlparser parser; + /* xmlparser object */ + parser.xmlstart = buffer; + parser.xmlsize = bufsize; + parser.data = data; + parser.starteltfunc = IGDstartelt; + parser.endeltfunc = IGDendelt; + parser.datafunc = IGDdata; + parser.attfunc = 0; + parsexml(&parser); +#ifdef DEBUG + printIGD(data); +#endif +} + +/* simpleUPnPcommand2 : + * not so simple ! + * return values : + * pointer - OK + * NULL - error */ +char * simpleUPnPcommand2(int s, const char * url, const char * service, + const char * action, struct UPNParg * args, + int * bufsize, const char * httpversion) +{ + char hostname[MAXHOSTNAMELEN+1]; + unsigned short port = 0; + char * path; + char soapact[128]; + char soapbody[2048]; + int soapbodylen; + char * buf; + int n; + + *bufsize = 0; + snprintf(soapact, sizeof(soapact), "%s#%s", service, action); + if(args==NULL) + { + soapbodylen = snprintf(soapbody, sizeof(soapbody), + "\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\">" + "" + "" + "\r\n", action, service, action); + if ((unsigned int)soapbodylen >= sizeof(soapbody)) + return NULL; + } + else + { + char * p; + const char * pe, * pv; + const char * const pend = soapbody + sizeof(soapbody); + soapbodylen = snprintf(soapbody, sizeof(soapbody), + "\r\n" + "<" SOAPPREFIX ":Envelope " + "xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" " + SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" + "<" SOAPPREFIX ":Body>" + "<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">", + action, service); + if ((unsigned int)soapbodylen >= sizeof(soapbody)) + return NULL; + p = soapbody + soapbodylen; + while(args->elt) + { + if(p >= pend) /* check for space to write next byte */ + return NULL; + *(p++) = '<'; + + pe = args->elt; + while(p < pend && *pe) + *(p++) = *(pe++); + + if(p >= pend) /* check for space to write next byte */ + return NULL; + *(p++) = '>'; + + if((pv = args->val)) + { + while(p < pend && *pv) + *(p++) = *(pv++); + } + + if((p+2) > pend) /* check for space to write next 2 bytes */ + return NULL; + *(p++) = '<'; + *(p++) = '/'; + + pe = args->elt; + while(p < pend && *pe) + *(p++) = *(pe++); + + if(p >= pend) /* check for space to write next byte */ + return NULL; + *(p++) = '>'; + + args++; + } + if((p+4) > pend) /* check for space to write next 4 bytes */ + return NULL; + *(p++) = '<'; + *(p++) = '/'; + *(p++) = SERVICEPREFIX2; + *(p++) = ':'; + + pe = action; + while(p < pend && *pe) + *(p++) = *(pe++); + + strncpy(p, ">\r\n", + pend - p); + if(soapbody[sizeof(soapbody)-1]) /* strncpy pads buffer with 0s, so if it doesn't end in 0, could not fit full string */ + return NULL; + } + if(!parseURL(url, hostname, &port, &path, NULL)) return NULL; + if(s < 0) { + s = connecthostport(hostname, port, 0); + if(s < 0) { + /* failed to connect */ + return NULL; + } + } + + n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, httpversion); + if(n<=0) { +#ifdef DEBUG + printf("Error sending SOAP request\n"); +#endif + closesocket(s); + return NULL; + } + + buf = getHTTPResponse(s, bufsize); +#ifdef DEBUG + if(*bufsize > 0 && buf) + { + printf("SOAP Response :\n%.*s\n", *bufsize, buf); + } +#endif + closesocket(s); + return buf; +} + +/* simpleUPnPcommand : + * not so simple ! + * return values : + * pointer - OK + * NULL - error */ +char * simpleUPnPcommand(int s, const char * url, const char * service, + const char * action, struct UPNParg * args, + int * bufsize) +{ + char * buf; + +#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. + * It is up to the caller to free the chained list + * delay is in millisecond (poll). + * UDA v1.1 says : + * The TTL for the IP packet SHOULD default to 2 and + * SHOULD be configurable. */ +MINIUPNP_LIBSPEC struct UPNPDev * +upnpDiscoverDevices(const char * const deviceTypes[], + int delay, const char * multicastif, + const char * minissdpdsock, int localport, + int ipv6, unsigned char ttl, + int * error, + int searchalltypes) +{ + struct UPNPDev * tmp; + struct UPNPDev * devlist = 0; +#if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) + int deviceIndex; +#endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ + + if(error) + *error = UPNPDISCOVER_UNKNOWN_ERROR; +#if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) + /* first try to get infos from minissdpd ! */ + if(!minissdpdsock) + minissdpdsock = "/var/run/minissdpd.sock"; + for(deviceIndex = 0; deviceTypes[deviceIndex]; deviceIndex++) { + struct UPNPDev * minissdpd_devlist; + int only_rootdevice = 1; + minissdpd_devlist = getDevicesFromMiniSSDPD(deviceTypes[deviceIndex], + minissdpdsock, 0); + if(minissdpd_devlist) { +#ifdef DEBUG + printf("returned by MiniSSDPD: %s\t%s\n", + minissdpd_devlist->st, minissdpd_devlist->descURL); +#endif /* DEBUG */ + if(!strstr(minissdpd_devlist->st, "rootdevice")) + only_rootdevice = 0; + for(tmp = minissdpd_devlist; tmp->pNext != NULL; tmp = tmp->pNext) { +#ifdef DEBUG + printf("returned by MiniSSDPD: %s\t%s\n", + tmp->pNext->st, tmp->pNext->descURL); +#endif /* DEBUG */ + if(!strstr(tmp->st, "rootdevice")) + only_rootdevice = 0; + } + tmp->pNext = devlist; + devlist = minissdpd_devlist; + if(!searchalltypes && !only_rootdevice) + break; + } + } + for(tmp = devlist; tmp != NULL; tmp = tmp->pNext) { + /* We return what we have found if it was not only a rootdevice */ + if(!strstr(tmp->st, "rootdevice")) { + if(error) + *error = UPNPDISCOVER_SUCCESS; + return devlist; + } + } +#endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ + + /* direct discovery if minissdpd responses are not sufficient */ + { + struct UPNPDev * discovered_devlist; + discovered_devlist = ssdpDiscoverDevices(deviceTypes, delay, multicastif, localport, + ipv6, ttl, error, searchalltypes); + if(devlist == NULL) + devlist = discovered_devlist; + else { + for(tmp = devlist; tmp->pNext != NULL; tmp = tmp->pNext); + tmp->pNext = discovered_devlist; + } + } + return devlist; +} + +/* upnpDiscover() Discover IGD device */ +MINIUPNP_LIBSPEC struct UPNPDev * +upnpDiscover(int delay, const char * multicastif, + const char * minissdpdsock, int localport, + int ipv6, unsigned char ttl, + int * error) +{ + static const char * const deviceList[] = { +#if 0 + "urn:schemas-upnp-org:device:InternetGatewayDevice:2", + "urn:schemas-upnp-org:service:WANIPConnection:2", +#endif + "urn:schemas-upnp-org:device:InternetGatewayDevice:1", + "urn:schemas-upnp-org:service:WANIPConnection:1", + "urn:schemas-upnp-org:service:WANPPPConnection:1", + "upnp:rootdevice", + /*"ssdp:all",*/ + 0 + }; + return upnpDiscoverDevices(deviceList, + delay, multicastif, minissdpdsock, localport, + ipv6, ttl, error, 0); +} + +/* upnpDiscoverAll() Discover all UPnP devices */ +MINIUPNP_LIBSPEC struct UPNPDev * +upnpDiscoverAll(int delay, const char * multicastif, + const char * minissdpdsock, int localport, + int ipv6, unsigned char ttl, + int * error) +{ + static const char * const deviceList[] = { + /*"upnp:rootdevice",*/ + "ssdp:all", + 0 + }; + return upnpDiscoverDevices(deviceList, + delay, multicastif, minissdpdsock, localport, + ipv6, ttl, error, 0); +} + +/* upnpDiscoverDevice() Discover a specific device */ +MINIUPNP_LIBSPEC struct UPNPDev * +upnpDiscoverDevice(const char * device, int delay, const char * multicastif, + const char * minissdpdsock, int localport, + int ipv6, unsigned char ttl, + int * error) +{ + const char * const deviceList[] = { + device, + 0 + }; + return upnpDiscoverDevices(deviceList, + delay, multicastif, minissdpdsock, localport, + ipv6, ttl, error, 0); +} + +static char * +build_absolute_url(const char * baseurl, const char * descURL, + const char * url, unsigned int scope_id) +{ + int l, n; + char * s; + const char * base; + char * p; +#if defined(IF_NAMESIZE) && !defined(_WIN32) + char ifname[IF_NAMESIZE]; +#else /* defined(IF_NAMESIZE) && !defined(_WIN32) */ + char scope_str[8]; +#endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */ + + if( (url[0] == 'h') + &&(url[1] == 't') + &&(url[2] == 't') + &&(url[3] == 'p') + &&(url[4] == ':') + &&(url[5] == '/') + &&(url[6] == '/')) + return strdup(url); + base = (baseurl[0] == '\0') ? descURL : baseurl; + n = strlen(base); + if(n > 7) { + p = strchr(base + 7, '/'); + if(p) + n = p - base; + } + l = n + strlen(url) + 1; + if(url[0] != '/') + l++; + if(scope_id != 0) { +#if defined(IF_NAMESIZE) && !defined(_WIN32) + if(if_indextoname(scope_id, ifname)) { + l += 3 + strlen(ifname); /* 3 == strlen(%25) */ + } +#else /* defined(IF_NAMESIZE) && !defined(_WIN32) */ + /* under windows, scope is numerical */ + l += 3 + snprintf(scope_str, sizeof(scope_str), "%u", scope_id); +#endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */ + } + s = malloc(l); + if(s == NULL) return NULL; + memcpy(s, base, n); + if(scope_id != 0) { + s[n] = '\0'; + if(0 == memcmp(s, "http://[fe80:", 13)) { + /* this is a linklocal IPv6 address */ + p = strchr(s, ']'); + if(p) { + /* insert %25 into URL */ +#if defined(IF_NAMESIZE) && !defined(_WIN32) + memmove(p + 3 + strlen(ifname), p, strlen(p) + 1); + memcpy(p, "%25", 3); + memcpy(p + 3, ifname, strlen(ifname)); + n += 3 + strlen(ifname); +#else /* defined(IF_NAMESIZE) && !defined(_WIN32) */ + memmove(p + 3 + strlen(scope_str), p, strlen(p) + 1); + memcpy(p, "%25", 3); + memcpy(p + 3, scope_str, strlen(scope_str)); + n += 3 + strlen(scope_str); +#endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */ + } + } + } + if(url[0] != '/') + s[n++] = '/'; + memcpy(s + n, url, l - n); + return s; +} + +/* Prepare the Urls for usage... + */ +MINIUPNP_LIBSPEC void +GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data, + const char * descURL, unsigned int scope_id) +{ + /* strdup descURL */ + urls->rootdescURL = strdup(descURL); + + /* get description of WANIPConnection */ + urls->ipcondescURL = build_absolute_url(data->urlbase, descURL, + data->first.scpdurl, scope_id); + urls->controlURL = build_absolute_url(data->urlbase, descURL, + data->first.controlurl, scope_id); + urls->controlURL_CIF = build_absolute_url(data->urlbase, descURL, + data->CIF.controlurl, scope_id); + urls->controlURL_6FC = build_absolute_url(data->urlbase, descURL, + data->IPv6FC.controlurl, scope_id); + +#ifdef DEBUG + printf("urls->ipcondescURL='%s'\n", urls->ipcondescURL); + printf("urls->controlURL='%s'\n", urls->controlURL); + printf("urls->controlURL_CIF='%s'\n", urls->controlURL_CIF); + printf("urls->controlURL_6FC='%s'\n", urls->controlURL_6FC); +#endif +} + +MINIUPNP_LIBSPEC void +FreeUPNPUrls(struct UPNPUrls * urls) +{ + if(!urls) + return; + free(urls->controlURL); + urls->controlURL = 0; + free(urls->ipcondescURL); + urls->ipcondescURL = 0; + free(urls->controlURL_CIF); + urls->controlURL_CIF = 0; + free(urls->controlURL_6FC); + urls->controlURL_6FC = 0; + free(urls->rootdescURL); + urls->rootdescURL = 0; +} + +int +UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data) +{ + char status[64]; + unsigned int uptime; + status[0] = '\0'; + UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype, + status, &uptime, NULL); + if(0 == strcmp("Connected", status)) + return 1; + else if(0 == strcmp("Up", status)) /* Also accept "Up" */ + return 1; + else + return 0; +} + + +/* UPNP_GetValidIGD() : + * return values : + * -1 = Internal error + * 0 = NO IGD found + * 1 = A valid connected IGD has been found + * 2 = A valid IGD has been found but it reported as + * not connected + * 3 = an UPnP device has been found but was not recognized as an IGD + * + * In any positive non zero return case, the urls and data structures + * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to + * free allocated memory. + */ +MINIUPNP_LIBSPEC int +UPNP_GetValidIGD(struct UPNPDev * devlist, + struct UPNPUrls * urls, + struct IGDdatas * data, + char * lanaddr, int lanaddrlen) +{ + struct xml_desc { + char * xml; + int size; + int is_igd; + } * desc = NULL; + struct UPNPDev * dev; + int ndev = 0; + int i; + int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */ + int n_igd = 0; + char extIpAddr[16]; + if(!devlist) + { +#ifdef DEBUG + printf("Empty devlist\n"); +#endif + return 0; + } + /* 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 */ + } + /* Step 1 : downloading descriptions and testing type */ + for(dev = devlist, i = 0; dev; dev = dev->pNext, i++) + { + /* we should choose an internet gateway device. + * with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */ + desc[i].xml = miniwget_getaddr(dev->descURL, &(desc[i].size), + lanaddr, lanaddrlen, + dev->scope_id); +#ifdef DEBUG + if(!desc[i].xml) + { + printf("error getting XML description %s\n", dev->descURL); + } +#endif + if(desc[i].xml) + { + memset(data, 0, sizeof(struct IGDdatas)); + memset(urls, 0, sizeof(struct UPNPUrls)); + parserootdesc(desc[i].xml, desc[i].size, data); + if(COMPARE(data->CIF.servicetype, + "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(dev = devlist, i = 0; dev; dev = dev->pNext, i++) + { + if(desc[i].xml) + { + memset(data, 0, sizeof(struct IGDdatas)); + memset(urls, 0, sizeof(struct UPNPUrls)); + parserootdesc(desc[i].xml, desc[i].size, data); + if(desc[i].is_igd || state >= 3 ) + { + GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); + + /* in state 2 and 3 we dont test if device is connected ! */ + if(state >= 2) + goto free_and_return; +#ifdef DEBUG + printf("UPNPIGD_IsConnected(%s) = %d\n", + urls->controlURL, + UPNPIGD_IsConnected(urls, data)); +#endif + /* checks that status is connected AND there is a external IP address assigned */ + if(UPNPIGD_IsConnected(urls, data) + && (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) + goto free_and_return; + FreeUPNPUrls(urls); + if(data->second.servicetype[0] != '\0') { +#ifdef DEBUG + printf("We tried %s, now we try %s !\n", + data->first.servicetype, data->second.servicetype); +#endif + /* swaping WANPPPConnection and WANIPConnection ! */ + memcpy(&data->tmp, &data->first, sizeof(struct IGDdatas_service)); + memcpy(&data->first, &data->second, sizeof(struct IGDdatas_service)); + memcpy(&data->second, &data->tmp, sizeof(struct IGDdatas_service)); + GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); +#ifdef DEBUG + printf("UPNPIGD_IsConnected(%s) = %d\n", + urls->controlURL, + UPNPIGD_IsConnected(urls, data)); +#endif + if(UPNPIGD_IsConnected(urls, data) + && (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) + goto free_and_return; + FreeUPNPUrls(urls); + } + } + memset(data, 0, sizeof(struct IGDdatas)); + } + } + } + state = 0; +free_and_return: + if(desc) { + for(i = 0; i < ndev; i++) { + if(desc[i].xml) { + free(desc[i].xml); + } + } + free(desc); + } + return state; +} + +/* UPNP_GetIGDFromUrl() + * Used when skipping the discovery process. + * return value : + * 0 - Not ok + * 1 - OK */ +int +UPNP_GetIGDFromUrl(const char * rootdescurl, + struct UPNPUrls * urls, + struct IGDdatas * data, + char * lanaddr, int lanaddrlen) +{ + char * descXML; + int descXMLsize = 0; + descXML = miniwget_getaddr(rootdescurl, &descXMLsize, + lanaddr, lanaddrlen, 0); + 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; + } +} + diff --git a/ext/miniupnpc/miniupnpc.def b/ext/miniupnpc/miniupnpc.def new file mode 100644 index 00000000..60e0bbe4 --- /dev/null +++ b/ext/miniupnpc/miniupnpc.def @@ -0,0 +1,45 @@ +LIBRARY +; miniupnpc library + miniupnpc + +EXPORTS +; miniupnpc + upnpDiscover + freeUPNPDevlist + parserootdesc + UPNP_GetValidIGD + UPNP_GetIGDFromUrl + GetUPNPUrls + FreeUPNPUrls +; miniwget + miniwget + miniwget_getaddr +; upnpcommands + UPNP_GetTotalBytesSent + UPNP_GetTotalBytesReceived + UPNP_GetTotalPacketsSent + UPNP_GetTotalPacketsReceived + UPNP_GetStatusInfo + UPNP_GetConnectionTypeInfo + UPNP_GetExternalIPAddress + UPNP_GetLinkLayerMaxBitRates + UPNP_AddPortMapping + UPNP_AddAnyPortMapping + UPNP_DeletePortMapping + UPNP_DeletePortMappingRange + UPNP_GetPortMappingNumberOfEntries + UPNP_GetSpecificPortMappingEntry + UPNP_GetGenericPortMappingEntry + UPNP_GetListOfPortMappings + UPNP_AddPinhole + UPNP_CheckPinholeWorking + UPNP_UpdatePinhole + UPNP_GetPinholePackets + UPNP_DeletePinhole + UPNP_GetFirewallStatus + UPNP_GetOutboundPinholeTimeout +; upnperrors + strupnperror +; portlistingparse + ParsePortListing + FreePortListing diff --git a/ext/miniupnpc/miniupnpc.h b/ext/miniupnpc/miniupnpc.h new file mode 100644 index 00000000..dfbfa01f --- /dev/null +++ b/ext/miniupnpc/miniupnpc.h @@ -0,0 +1,152 @@ +/* $Id: miniupnpc.h,v 1.48 2015/10/08 16:19:40 nanard Exp $ */ +/* Project: miniupnp + * http://miniupnp.free.fr/ + * Author: Thomas Bernard + * Copyright (c) 2005-2015 Thomas Bernard + * This software is subjects to the conditions detailed + * in the LICENCE file provided within this distribution */ +#ifndef MINIUPNPC_H_INCLUDED +#define MINIUPNPC_H_INCLUDED + +#include "miniupnpc_declspec.h" +#include "igd_desc_parse.h" +#include "upnpdev.h" + +/* error codes : */ +#define UPNPDISCOVER_SUCCESS (0) +#define UPNPDISCOVER_UNKNOWN_ERROR (-1) +#define UPNPDISCOVER_SOCKET_ERROR (-101) +#define UPNPDISCOVER_MEMORY_ERROR (-102) + +/* versions : */ +#define MINIUPNPC_VERSION "1.9.20151026" +#define MINIUPNPC_API_VERSION 15 + +/* Source port: + Using "1" as an alias for 1900 for backwards compatability + (presuming one would have used that for the "sameport" parameter) */ +#define UPNP_LOCAL_PORT_ANY 0 +#define UPNP_LOCAL_PORT_SAME 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structures definitions : */ +struct UPNParg { const char * elt; const char * val; }; + +char * +simpleUPnPcommand(int, const char *, const char *, + const char *, struct UPNParg *, + int *); + +/* upnpDiscover() + * discover UPnP devices on the network. + * The discovered devices are returned as a chained list. + * It is up to the caller to free the list with freeUPNPDevlist(). + * delay (in millisecond) is the maximum time for waiting any device + * response. + * If available, device list will be obtained from MiniSSDPd. + * Default path for minissdpd socket will be used if minissdpdsock argument + * is NULL. + * If multicastif is not NULL, it will be used instead of the default + * multicast interface for sending SSDP discover packets. + * If localport is set to UPNP_LOCAL_PORT_SAME(1) SSDP packets will be sent + * from the source port 1900 (same as destination port), if set to + * UPNP_LOCAL_PORT_ANY(0) system assign a source port, any other value will + * be attempted as the source port. + * "searchalltypes" parameter is useful when searching several types, + * if 0, the discovery will stop with the first type returning results. + * TTL should default to 2. */ +MINIUPNP_LIBSPEC struct UPNPDev * +upnpDiscover(int delay, const char * multicastif, + const char * minissdpdsock, int localport, + int ipv6, unsigned char ttl, + int * error); + +MINIUPNP_LIBSPEC struct UPNPDev * +upnpDiscoverAll(int delay, const char * multicastif, + const char * minissdpdsock, int localport, + int ipv6, unsigned char ttl, + int * error); + +MINIUPNP_LIBSPEC struct UPNPDev * +upnpDiscoverDevice(const char * device, int delay, const char * multicastif, + const char * minissdpdsock, int localport, + int ipv6, unsigned char ttl, + int * error); + +MINIUPNP_LIBSPEC struct UPNPDev * +upnpDiscoverDevices(const char * const deviceTypes[], + int delay, const char * multicastif, + const char * minissdpdsock, int localport, + int ipv6, unsigned char ttl, + int * error, + int searchalltypes); + +/* parserootdesc() : + * parse root XML description of a UPnP device and fill the IGDdatas + * structure. */ +MINIUPNP_LIBSPEC void parserootdesc(const char *, int, struct IGDdatas *); + +/* structure used to get fast access to urls + * controlURL: controlURL of the WANIPConnection + * ipcondescURL: url of the description of the WANIPConnection + * controlURL_CIF: controlURL of the WANCommonInterfaceConfig + * controlURL_6FC: controlURL of the WANIPv6FirewallControl + */ +struct UPNPUrls { + char * controlURL; + char * ipcondescURL; + char * controlURL_CIF; + char * controlURL_6FC; + char * rootdescURL; +}; + +/* UPNP_GetValidIGD() : + * return values : + * 0 = NO IGD found + * 1 = A valid connected IGD has been found + * 2 = A valid IGD has been found but it reported as + * not connected + * 3 = an UPnP device has been found but was not recognized as an IGD + * + * In any non zero return case, the urls and data structures + * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to + * free allocated memory. + */ +MINIUPNP_LIBSPEC int +UPNP_GetValidIGD(struct UPNPDev * devlist, + struct UPNPUrls * urls, + struct IGDdatas * data, + char * lanaddr, int lanaddrlen); + +/* UPNP_GetIGDFromUrl() + * Used when skipping the discovery process. + * When succeding, urls, data, and lanaddr arguments are set. + * return value : + * 0 - Not ok + * 1 - OK */ +MINIUPNP_LIBSPEC int +UPNP_GetIGDFromUrl(const char * rootdescurl, + struct UPNPUrls * urls, + struct IGDdatas * data, + char * lanaddr, int lanaddrlen); + +MINIUPNP_LIBSPEC void +GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, + const char *, unsigned int); + +MINIUPNP_LIBSPEC void +FreeUPNPUrls(struct UPNPUrls *); + +/* return 0 or 1 */ +MINIUPNP_LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/ext/miniupnpc/miniupnpc_declspec.h b/ext/miniupnpc/miniupnpc_declspec.h new file mode 100644 index 00000000..40adb922 --- /dev/null +++ b/ext/miniupnpc/miniupnpc_declspec.h @@ -0,0 +1,21 @@ +#ifndef MINIUPNPC_DECLSPEC_H_INCLUDED +#define MINIUPNPC_DECLSPEC_H_INCLUDED + +#if defined(_WIN32) && !defined(MINIUPNP_STATICLIB) + /* for windows dll */ + #ifdef MINIUPNP_EXPORTS + #define MINIUPNP_LIBSPEC __declspec(dllexport) + #else + #define MINIUPNP_LIBSPEC __declspec(dllimport) + #endif +#else + #if defined(__GNUC__) && __GNUC__ >= 4 + /* fix dynlib for OS X 10.9.2 and Apple LLVM version 5.0 */ + #define MINIUPNP_LIBSPEC __attribute__ ((visibility ("default"))) + #else + #define MINIUPNP_LIBSPEC + #endif +#endif + +#endif /* MINIUPNPC_DECLSPEC_H_INCLUDED */ + diff --git a/ext/miniupnpc/miniupnpcmodule.c b/ext/miniupnpc/miniupnpcmodule.c new file mode 100644 index 00000000..a5bdce44 --- /dev/null +++ b/ext/miniupnpc/miniupnpcmodule.c @@ -0,0 +1,695 @@ +/* $Id: miniupnpcmodule.c,v 1.29 2015/10/26 17:01:30 nanard Exp $*/ +/* Project : miniupnp + * Author : Thomas BERNARD + * website : http://miniupnp.tuxfamily.org/ + * copyright (c) 2007-2014 Thomas Bernard + * This software is subjet to the conditions detailed in the + * provided LICENCE file. */ +#include +#define MINIUPNP_STATICLIB +#include "structmember.h" +#include "miniupnpc.h" +#include "upnpcommands.h" +#include "upnperrors.h" + +/* for compatibility with Python < 2.4 */ +#ifndef Py_RETURN_NONE +#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None +#endif + +#ifndef Py_RETURN_TRUE +#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True +#endif + +#ifndef Py_RETURN_FALSE +#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False +#endif + +/* for compatibility with Python < 3.0 */ +#ifndef PyVarObject_HEAD_INIT +#define PyVarObject_HEAD_INIT(type, size) \ + PyObject_HEAD_INIT(type) size, +#endif + +#ifndef Py_TYPE +#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) +#endif + +typedef struct { + PyObject_HEAD + /* Type-specific fields go here. */ + struct UPNPDev * devlist; + struct UPNPUrls urls; + struct IGDdatas data; + unsigned int discoverdelay; /* value passed to upnpDiscover() */ + unsigned int localport; /* value passed to upnpDiscover() */ + char lanaddr[40]; /* our ip address on the LAN */ + char * multicastif; + char * minissdpdsocket; +} UPnPObject; + +static PyMemberDef UPnP_members[] = { + {"lanaddr", T_STRING_INPLACE, offsetof(UPnPObject, lanaddr), + READONLY, "ip address on the LAN" + }, + {"discoverdelay", T_UINT, offsetof(UPnPObject, discoverdelay), + 0/*READWRITE*/, "value in ms used to wait for SSDP responses" + }, + {"localport", T_UINT, offsetof(UPnPObject, localport), + 0/*READWRITE*/, + "If localport is set to UPNP_LOCAL_PORT_SAME(1) " + "SSDP packets will be sent from the source port " + "1900 (same as destination port), if set to " + "UPNP_LOCAL_PORT_ANY(0) system assign a source " + "port, any other value will be attempted as the " + "source port" + }, + /* T_STRING is allways readonly :( */ + {"multicastif", T_STRING, offsetof(UPnPObject, multicastif), + 0, "IP of the network interface to be used for multicast operations" + }, + {"minissdpdsocket", T_STRING, offsetof(UPnPObject, minissdpdsocket), + 0, "path of the MiniSSDPd unix socket" + }, + {NULL} +}; + + +static int UPnP_init(UPnPObject *self, PyObject *args, PyObject *kwds) +{ + char* multicastif = NULL; + char* minissdpdsocket = NULL; + static char *kwlist[] = { + "multicastif", "minissdpdsocket", "discoverdelay", + "localport", NULL + }; + + if(!PyArg_ParseTupleAndKeywords(args, kwds, "|zzII", kwlist, + &multicastif, + &minissdpdsocket, + &self->discoverdelay, + &self->localport)) + return -1; + + if(self->localport>1 && + (self->localport>65534||self->localport<1024)) { + PyErr_SetString(PyExc_Exception, "Invalid localport value"); + return -1; + } + if(multicastif) + self->multicastif = strdup(multicastif); + if(minissdpdsocket) + self->minissdpdsocket = strdup(minissdpdsocket); + + return 0; +} + +static void +UPnPObject_dealloc(UPnPObject *self) +{ + freeUPNPDevlist(self->devlist); + FreeUPNPUrls(&self->urls); + free(self->multicastif); + free(self->minissdpdsocket); + Py_TYPE(self)->tp_free((PyObject*)self); +} + +static PyObject * +UPnP_discover(UPnPObject *self) +{ + struct UPNPDev * dev; + int i; + PyObject *res = NULL; + if(self->devlist) + { + freeUPNPDevlist(self->devlist); + self->devlist = 0; + } + Py_BEGIN_ALLOW_THREADS + self->devlist = upnpDiscover((int)self->discoverdelay/*timeout in ms*/, + self->multicastif, + self->minissdpdsocket, + (int)self->localport, + 0/*ip v6*/, + 2/* TTL */, + 0/*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; +} + +static PyObject * +UPnP_selectigd(UPnPObject *self) +{ + int r; +Py_BEGIN_ALLOW_THREADS + r = UPNP_GetValidIGD(self->devlist, &self->urls, &self->data, + self->lanaddr, sizeof(self->lanaddr)); +Py_END_ALLOW_THREADS + if(r) + { + return Py_BuildValue("s", self->urls.controlURL); + } + else + { + /* TODO: have our own exception type ! */ + PyErr_SetString(PyExc_Exception, "No UPnP device discovered"); + return NULL; + } +} + +static PyObject * +UPnP_totalbytesent(UPnPObject *self) +{ + UNSIGNED_INTEGER i; +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 * +UPnP_totalbytereceived(UPnPObject *self) +{ + UNSIGNED_INTEGER i; +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 * +UPnP_totalpacketsent(UPnPObject *self) +{ + UNSIGNED_INTEGER i; +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 * +UPnP_totalpacketreceived(UPnPObject *self) +{ + UNSIGNED_INTEGER i; +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 * +UPnP_statusinfo(UPnPObject *self) +{ + char status[64]; + char lastconnerror[64]; + unsigned int uptime = 0; + int r; + status[0] = '\0'; + lastconnerror[0] = '\0'; +Py_BEGIN_ALLOW_THREADS + r = UPNP_GetStatusInfo(self->urls.controlURL, self->data.first.servicetype, + 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)); + return NULL; + } +} + +static PyObject * +UPnP_connectiontype(UPnPObject *self) +{ + char connectionType[64]; + int r; + connectionType[0] = '\0'; +Py_BEGIN_ALLOW_THREADS + r = UPNP_GetConnectionTypeInfo(self->urls.controlURL, + self->data.first.servicetype, + connectionType); +Py_END_ALLOW_THREADS + if(r==UPNPCOMMAND_SUCCESS) { + return Py_BuildValue("s", connectionType); + } else { + /* TODO: have our own exception type ! */ + PyErr_SetString(PyExc_Exception, strupnperror(r)); + return NULL; + } +} + +static PyObject * +UPnP_externalipaddress(UPnPObject *self) +{ + char externalIPAddress[40]; + int r; + externalIPAddress[0] = '\0'; +Py_BEGIN_ALLOW_THREADS + r = UPNP_GetExternalIPAddress(self->urls.controlURL, + self->data.first.servicetype, + externalIPAddress); +Py_END_ALLOW_THREADS + if(r==UPNPCOMMAND_SUCCESS) { + return Py_BuildValue("s", externalIPAddress); + } else { + /* TODO: have our own exception type ! */ + PyErr_SetString(PyExc_Exception, strupnperror(r)); + return NULL; + } +} + +/* AddPortMapping(externalPort, protocol, internalHost, internalPort, desc, + * remoteHost) + * protocol is 'UDP' or 'TCP' */ +static PyObject * +UPnP_addportmapping(UPnPObject *self, PyObject *args) +{ + char extPort[6]; + unsigned short ePort; + char inPort[6]; + unsigned short iPort; + const char * proto; + const char * host; + const char * desc; + const char * remoteHost; + const char * leaseDuration = "0"; + int r; + if (!PyArg_ParseTuple(args, "HssHss", &ePort, &proto, + &host, &iPort, &desc, &remoteHost)) + return NULL; +Py_BEGIN_ALLOW_THREADS + sprintf(extPort, "%hu", ePort); + sprintf(inPort, "%hu", iPort); + r = UPNP_AddPortMapping(self->urls.controlURL, self->data.first.servicetype, + extPort, inPort, host, desc, proto, + remoteHost, leaseDuration); +Py_END_ALLOW_THREADS + if(r==UPNPCOMMAND_SUCCESS) + { + Py_RETURN_TRUE; + } + else + { + // TODO: RAISE an Exception. See upnpcommands.h for errors codes. + // upnperrors.c + //Py_RETURN_FALSE; + /* TODO: have our own exception type ! */ + PyErr_SetString(PyExc_Exception, strupnperror(r)); + return NULL; + } +} + +/* AddAnyPortMapping(externalPort, protocol, internalHost, internalPort, desc, + * remoteHost) + * protocol is 'UDP' or 'TCP' */ +static PyObject * +UPnP_addanyportmapping(UPnPObject *self, PyObject *args) +{ + char extPort[6]; + unsigned short ePort; + char inPort[6]; + unsigned short iPort; + char reservedPort[6]; + const char * proto; + const char * host; + const char * desc; + const char * remoteHost; + const char * leaseDuration = "0"; + int r; + if (!PyArg_ParseTuple(args, "HssHss", &ePort, &proto, &host, &iPort, &desc, &remoteHost)) + return NULL; +Py_BEGIN_ALLOW_THREADS + sprintf(extPort, "%hu", ePort); + sprintf(inPort, "%hu", iPort); + r = UPNP_AddAnyPortMapping(self->urls.controlURL, self->data.first.servicetype, + extPort, inPort, host, desc, proto, + remoteHost, leaseDuration, reservedPort); +Py_END_ALLOW_THREADS + if(r==UPNPCOMMAND_SUCCESS) { + return Py_BuildValue("i", atoi(reservedPort)); + } else { + /* TODO: have our own exception type ! */ + PyErr_SetString(PyExc_Exception, strupnperror(r)); + return NULL; + } +} + + +/* DeletePortMapping(extPort, proto, removeHost='') + * proto = 'UDP', 'TCP' */ +static PyObject * +UPnP_deleteportmapping(UPnPObject *self, PyObject *args) +{ + char extPort[6]; + unsigned short ePort; + const char * proto; + const char * remoteHost = ""; + int r; + if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost)) + return NULL; +Py_BEGIN_ALLOW_THREADS + sprintf(extPort, "%hu", ePort); + r = UPNP_DeletePortMapping(self->urls.controlURL, self->data.first.servicetype, + extPort, proto, remoteHost); +Py_END_ALLOW_THREADS + if(r==UPNPCOMMAND_SUCCESS) { + Py_RETURN_TRUE; + } else { + /* TODO: have our own exception type ! */ + PyErr_SetString(PyExc_Exception, strupnperror(r)); + return NULL; + } +} + +/* DeletePortMappingRange(extPort, proto, removeHost='') + * proto = 'UDP', 'TCP' */ +static PyObject * +UPnP_deleteportmappingrange(UPnPObject *self, PyObject *args) +{ + char extPortStart[6]; + unsigned short ePortStart; + char extPortEnd[6]; + unsigned short ePortEnd; + const char * proto; + unsigned char manage; + char manageStr[1]; + 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); + r = UPNP_DeletePortMappingRange(self->urls.controlURL, self->data.first.servicetype, + extPortStart, extPortEnd, proto, manageStr); +Py_END_ALLOW_THREADS + if(r==UPNPCOMMAND_SUCCESS) { + Py_RETURN_TRUE; + } else { + /* TODO: have our own exception type ! */ + PyErr_SetString(PyExc_Exception, strupnperror(r)); + return NULL; + } +} + +static PyObject * +UPnP_getportmappingnumberofentries(UPnPObject *self) +{ + unsigned int n = 0; + int r; +Py_BEGIN_ALLOW_THREADS + r = UPNP_GetPortMappingNumberOfEntries(self->urls.controlURL, + self->data.first.servicetype, + &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)); + return NULL; + } +} + +/* GetSpecificPortMapping(ePort, proto, remoteHost='') + * proto = 'UDP' or 'TCP' */ +static PyObject * +UPnP_getspecificportmapping(UPnPObject *self, PyObject *args) +{ + char extPort[6]; + unsigned short ePort; + const char * proto; + const char * remoteHost = ""; + char intClient[40]; + char intPort[6]; + unsigned short iPort; + char desc[80]; + char enabled[4]; + char leaseDuration[16]; + if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost)) + return NULL; + extPort[0] = '\0'; intClient[0] = '\0'; intPort[0] = '\0'; + desc[0] = '\0'; enabled[0] = '\0'; leaseDuration[0] = '\0'; +Py_BEGIN_ALLOW_THREADS + sprintf(extPort, "%hu", ePort); + UPNP_GetSpecificPortMappingEntry(self->urls.controlURL, + self->data.first.servicetype, + extPort, proto, remoteHost, + intClient, intPort, + desc, enabled, leaseDuration); +Py_END_ALLOW_THREADS + if(intClient[0]) + { + iPort = (unsigned short)atoi(intPort); + return Py_BuildValue("(s,H,s,O,i)", + intClient, iPort, desc, + PyBool_FromLong(atoi(enabled)), + atoi(leaseDuration)); + } + else + { + Py_RETURN_NONE; + } +} + +/* GetGenericPortMapping(index) */ +static PyObject * +UPnP_getgenericportmapping(UPnPObject *self, PyObject *args) +{ + int i, r; + char index[8]; + char intClient[40]; + char intPort[6]; + unsigned short iPort; + char extPort[6]; + unsigned short ePort; + char protocol[4]; + char desc[80]; + char enabled[6]; + char rHost[64]; + char duration[16]; /* lease duration */ + unsigned int dur; + if(!PyArg_ParseTuple(args, "i", &i)) + return NULL; +Py_BEGIN_ALLOW_THREADS + snprintf(index, sizeof(index), "%d", 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(self->urls.controlURL, + self->data.first.servicetype, + index, + extPort, intClient, intPort, + protocol, desc, enabled, rHost, + duration); +Py_END_ALLOW_THREADS + if(r==UPNPCOMMAND_SUCCESS) + { + 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 + { + Py_RETURN_NONE; + } +} + +/* miniupnpc.UPnP object Method Table */ +static PyMethodDef UPnP_methods[] = { + {"discover", (PyCFunction)UPnP_discover, METH_NOARGS, + "discover UPnP IGD devices on the network" + }, + {"selectigd", (PyCFunction)UPnP_selectigd, METH_NOARGS, + "select a valid UPnP IGD among discovered devices" + }, + {"totalbytesent", (PyCFunction)UPnP_totalbytesent, METH_NOARGS, + "return the total number of bytes sent by UPnP IGD" + }, + {"totalbytereceived", (PyCFunction)UPnP_totalbytereceived, METH_NOARGS, + "return the total number of bytes received by UPnP IGD" + }, + {"totalpacketsent", (PyCFunction)UPnP_totalpacketsent, METH_NOARGS, + "return the total number of packets sent by UPnP IGD" + }, + {"totalpacketreceived", (PyCFunction)UPnP_totalpacketreceived, METH_NOARGS, + "return the total number of packets received by UPnP IGD" + }, + {"statusinfo", (PyCFunction)UPnP_statusinfo, METH_NOARGS, + "return status and uptime" + }, + {"connectiontype", (PyCFunction)UPnP_connectiontype, METH_NOARGS, + "return IGD WAN connection type" + }, + {"externalipaddress", (PyCFunction)UPnP_externalipaddress, METH_NOARGS, + "return external IP address" + }, + {"addportmapping", (PyCFunction)UPnP_addportmapping, METH_VARARGS, + "add a port mapping" + }, + {"addanyportmapping", (PyCFunction)UPnP_addanyportmapping, METH_VARARGS, + "add a port mapping, IGD to select alternative if necessary" + }, + {"deleteportmapping", (PyCFunction)UPnP_deleteportmapping, METH_VARARGS, + "delete a port mapping" + }, + {"deleteportmappingrange", (PyCFunction)UPnP_deleteportmappingrange, METH_VARARGS, + "delete a range of port mappings" + }, + {"getportmappingnumberofentries", (PyCFunction)UPnP_getportmappingnumberofentries, METH_NOARGS, + "-- non standard --" + }, + {"getspecificportmapping", (PyCFunction)UPnP_getspecificportmapping, METH_VARARGS, + "get details about a specific port mapping entry" + }, + {"getgenericportmapping", (PyCFunction)UPnP_getgenericportmapping, METH_VARARGS, + "get all details about the port mapping at index" + }, + {NULL} /* Sentinel */ +}; + +static PyTypeObject UPnPType = { + PyVarObject_HEAD_INIT(NULL, + 0) /*ob_size*/ + "miniupnpc.UPnP", /*tp_name*/ + sizeof(UPnPObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)UPnPObject_dealloc,/*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "UPnP objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + UPnP_methods, /* tp_methods */ + UPnP_members, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)UPnP_init, /* tp_init */ + 0, /* tp_alloc */ +#ifndef _WIN32 + PyType_GenericNew,/*UPnP_new,*/ /* tp_new */ +#else + 0, +#endif +}; + +/* module methods */ +static PyMethodDef miniupnpc_methods[] = { + {NULL} /* Sentinel */ +}; + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "miniupnpc", /* m_name */ + "miniupnpc module.", /* m_doc */ + -1, /* m_size */ + miniupnpc_methods, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ +}; +#endif + +#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ +#define PyMODINIT_FUNC void +#endif + +PyMODINIT_FUNC +#if PY_MAJOR_VERSION >= 3 +PyInit_miniupnpc(void) +#else +initminiupnpc(void) +#endif +{ + PyObject* m; + +#ifdef _WIN32 + UPnPType.tp_new = PyType_GenericNew; +#endif + if (PyType_Ready(&UPnPType) < 0) +#if PY_MAJOR_VERSION >= 3 + return 0; +#else + return; +#endif + +#if PY_MAJOR_VERSION >= 3 + m = PyModule_Create(&moduledef); +#else + m = Py_InitModule3("miniupnpc", miniupnpc_methods, + "miniupnpc module."); +#endif + + Py_INCREF(&UPnPType); + PyModule_AddObject(m, "UPnP", (PyObject *)&UPnPType); + +#if PY_MAJOR_VERSION >= 3 + return m; +#endif +} + diff --git a/ext/miniupnpc/miniupnpcstrings.h.cmake b/ext/miniupnpc/miniupnpcstrings.h.cmake new file mode 100644 index 00000000..78c8fe9c --- /dev/null +++ b/ext/miniupnpc/miniupnpcstrings.h.cmake @@ -0,0 +1,15 @@ +#ifndef MINIUPNPCSTRINGS_H_INCLUDED +#define MINIUPNPCSTRINGS_H_INCLUDED + +#define OS_STRING "${CMAKE_SYSTEM_NAME}" +#define MINIUPNPC_VERSION_STRING "${MINIUPNPC_VERSION}" + +#if 0 +/* according to "UPnP Device Architecture 1.0" */ +#define UPNP_VERSION_STRING "UPnP/1.0" +#else +/* according to "UPnP Device Architecture 1.1" */ +#define UPNP_VERSION_STRING "UPnP/1.1" +#endif + +#endif diff --git a/ext/miniupnpc/miniupnpcstrings.h.in b/ext/miniupnpc/miniupnpcstrings.h.in new file mode 100644 index 00000000..68bf4293 --- /dev/null +++ b/ext/miniupnpc/miniupnpcstrings.h.in @@ -0,0 +1,23 @@ +/* $Id: miniupnpcstrings.h.in,v 1.6 2014/11/04 22:31:55 nanard Exp $ */ +/* Project: miniupnp + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * Author: Thomas Bernard + * Copyright (c) 2005-2014 Thomas Bernard + * This software is subjects to the conditions detailed + * in the LICENCE file provided within this distribution */ +#ifndef MINIUPNPCSTRINGS_H_INCLUDED +#define MINIUPNPCSTRINGS_H_INCLUDED + +#define OS_STRING "OS/version" +#define MINIUPNPC_VERSION_STRING "version" + +#if 0 +/* according to "UPnP Device Architecture 1.0" */ +#define UPNP_VERSION_STRING "UPnP/1.0" +#else +/* according to "UPnP Device Architecture 1.1" */ +#define UPNP_VERSION_STRING "UPnP/1.1" +#endif + +#endif + diff --git a/ext/miniupnpc/miniupnpctypes.h b/ext/miniupnpc/miniupnpctypes.h new file mode 100644 index 00000000..591c32fb --- /dev/null +++ b/ext/miniupnpc/miniupnpctypes.h @@ -0,0 +1,19 @@ +/* $Id: miniupnpctypes.h,v 1.2 2012/09/27 15:42:10 nanard Exp $ */ +/* Miniupnp project : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org + * Author : Thomas Bernard + * Copyright (c) 2011 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided within this distribution */ +#ifndef MINIUPNPCTYPES_H_INCLUDED +#define MINIUPNPCTYPES_H_INCLUDED + +#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 + diff --git a/ext/miniupnpc/miniwget.c b/ext/miniupnpc/miniwget.c new file mode 100644 index 00000000..40aa7180 --- /dev/null +++ b/ext/miniupnpc/miniwget.c @@ -0,0 +1,626 @@ +/* $Id: miniwget.c,v 1.72 2015/10/26 17:05:08 nanard Exp $ */ +/* Project : miniupnp + * Website : http://miniupnp.free.fr/ + * Author : Thomas Bernard + * Copyright (c) 2005-2015 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. */ + +#include +#include +#include +#include +#ifdef _WIN32 +#include +#include +#include +#define MAXHOSTNAMELEN 64 +#define snprintf _snprintf +#define socklen_t int +#ifndef strncasecmp +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#define strncasecmp _memicmp +#else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ +#define strncasecmp memicmp +#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ +#endif /* #ifndef strncasecmp */ +#else /* #ifdef _WIN32 */ +#include +#include +#if defined(__amigaos__) && !defined(__amigaos4__) +#define socklen_t int +#else /* #if defined(__amigaos__) && !defined(__amigaos4__) */ +#include +#endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */ +#include +#include +#include +#include +#include +#define closesocket close +#include +#endif /* #else _WIN32 */ +#ifdef __GNU__ +#define MAXHOSTNAMELEN 64 +#endif /* __GNU__ */ + +#ifndef MIN +#define MIN(x,y) (((x)<(y))?(x):(y)) +#endif /* MIN */ + + +#include "miniupnpcstrings.h" +#include "miniwget.h" +#include "connecthostport.h" +#include "receivedata.h" + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +/* + * Read a HTTP response from a socket. + * Process Content-Length and Transfer-encoding headers. + * return a pointer to the content buffer, which length is saved + * to the length parameter. + */ +void * +getHTTPResponse(int s, int * size) +{ + char buf[2048]; + int n; + int endofheaders = 0; + int chunked = 0; + int content_length = -1; + unsigned int chunksize = 0; + unsigned int bytestocopy = 0; + /* buffers : */ + char * header_buf; + unsigned int header_buf_len = 2048; + unsigned int header_buf_used = 0; + char * content_buf; + unsigned int content_buf_len = 2048; + unsigned int content_buf_used = 0; + char chunksize_buf[32]; + unsigned int chunksize_buf_index; + + header_buf = malloc(header_buf_len); + if(header_buf == NULL) + { +#ifdef DEBUG + fprintf(stderr, "%s: Memory allocation error\n", "getHTTPResponse"); +#endif /* DEBUG */ + *size = -1; + return NULL; + } + content_buf = malloc(content_buf_len); + if(content_buf == NULL) + { + free(header_buf); +#ifdef DEBUG + fprintf(stderr, "%s: Memory allocation error\n", "getHTTPResponse"); +#endif /* DEBUG */ + *size = -1; + return NULL; + } + chunksize_buf[0] = '\0'; + chunksize_buf_index = 0; + + while((n = receivedata(s, buf, 2048, 5000, NULL)) > 0) + { + if(endofheaders == 0) + { + int i; + int linestart=0; + int colon=0; + int valuestart=0; + if(header_buf_used + n > header_buf_len) { + char * tmp = realloc(header_buf, header_buf_used + n); + if(tmp == NULL) { + /* memory allocation error */ + free(header_buf); + free(content_buf); + *size = -1; + return NULL; + } + header_buf = tmp; + header_buf_len = header_buf_used + n; + } + memcpy(header_buf + header_buf_used, buf, n); + header_buf_used += n; + /* search for CR LF CR LF (end of headers) + * recognize also LF LF */ + i = 0; + while(i < ((int)header_buf_used-1) && (endofheaders == 0)) { + if(header_buf[i] == '\r') { + i++; + if(header_buf[i] == '\n') { + i++; + if(i < (int)header_buf_used && header_buf[i] == '\r') { + i++; + if(i < (int)header_buf_used && header_buf[i] == '\n') { + endofheaders = i+1; + } + } + } + } else if(header_buf[i] == '\n') { + i++; + if(header_buf[i] == '\n') { + endofheaders = i+1; + } + } + i++; + } + if(endofheaders == 0) + continue; + /* parse header lines */ + for(i = 0; i < endofheaders - 1; i++) { + if(colon <= linestart && header_buf[i]==':') + { + colon = i; + while(i < (endofheaders-1) + && (header_buf[i+1] == ' ' || header_buf[i+1] == '\t')) + i++; + valuestart = i + 1; + } + /* detecting end of line */ + else if(header_buf[i]=='\r' || header_buf[i]=='\n') + { + if(colon > linestart && valuestart > colon) + { +#ifdef DEBUG + printf("header='%.*s', value='%.*s'\n", + colon-linestart, header_buf+linestart, + i-valuestart, header_buf+valuestart); +#endif + if(0==strncasecmp(header_buf+linestart, "content-length", colon-linestart)) + { + content_length = atoi(header_buf+valuestart); +#ifdef DEBUG + printf("Content-Length: %d\n", content_length); +#endif + } + else if(0==strncasecmp(header_buf+linestart, "transfer-encoding", colon-linestart) + && 0==strncasecmp(header_buf+valuestart, "chunked", 7)) + { +#ifdef DEBUG + printf("chunked transfer-encoding!\n"); +#endif + chunked = 1; + } + } + while((i < (int)header_buf_used) && (header_buf[i]=='\r' || header_buf[i] == '\n')) + i++; + linestart = i; + colon = linestart; + valuestart = 0; + } + } + /* copy the remaining of the received data back to buf */ + n = header_buf_used - endofheaders; + memcpy(buf, header_buf + endofheaders, n); + /* if(headers) */ + } + if(endofheaders) + { + /* content */ + if(chunked) + { + int i = 0; + while(i < n) + { + if(chunksize == 0) + { + /* reading chunk size */ + if(chunksize_buf_index == 0) { + /* skipping any leading CR LF */ + if(i= '0' + && chunksize_buf[j] <= '9') + chunksize = (chunksize << 4) + (chunksize_buf[j] - '0'); + else + chunksize = (chunksize << 4) + ((chunksize_buf[j] | 32) - 'a' + 10); + } + chunksize_buf[0] = '\0'; + chunksize_buf_index = 0; + i++; + } else { + /* not finished to get chunksize */ + continue; + } +#ifdef DEBUG + printf("chunksize = %u (%x)\n", chunksize, chunksize); +#endif + if(chunksize == 0) + { +#ifdef DEBUG + printf("end of HTTP content - %d %d\n", i, n); + /*printf("'%.*s'\n", n-i, buf+i);*/ +#endif + goto end_of_stream; + } + } + 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) + { + char * tmp; + if(content_length >= (int)(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) + { +#ifdef DEBUG + printf("End of HTTP content\n"); +#endif + break; + } + } +end_of_stream: + free(header_buf); header_buf = NULL; + *size = content_buf_used; + if(content_buf_used == 0) + { + free(content_buf); + content_buf = NULL; + } + return content_buf; +} + +/* miniwget3() : + * do all the work. + * Return NULL if something failed. */ +static void * +miniwget3(const char * host, + unsigned short port, const char * path, + int * size, char * addr_str, int addr_str_len, + const char * httpversion, unsigned int scope_id) +{ + char buf[2048]; + int s; + int n; + int len; + int sent; + void * content; + + *size = 0; + s = connecthostport(host, port, scope_id); + if(s < 0) + return NULL; + + /* get address for caller ! */ + if(addr_str) + { + struct sockaddr_storage saddr; + socklen_t saddrlen; + + saddrlen = sizeof(saddr); + if(getsockname(s, (struct sockaddr *)&saddr, &saddrlen) < 0) + { + perror("getsockname"); + } + else + { +#if defined(__amigaos__) && !defined(__amigaos4__) + /* using INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD); + * But his function make a string with the port : nn.nn.nn.nn:port */ +/* if(WSAAddressToStringA((SOCKADDR *)&saddr, sizeof(saddr), + NULL, addr_str, (DWORD *)&addr_str_len)) + { + printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError()); + }*/ + /* the following code is only compatible with ip v4 addresses */ + strncpy(addr_str, inet_ntoa(((struct sockaddr_in *)&saddr)->sin_addr), addr_str_len); +#else +#if 0 + if(saddr.sa_family == AF_INET6) { + inet_ntop(AF_INET6, + &(((struct sockaddr_in6 *)&saddr)->sin6_addr), + addr_str, addr_str_len); + } else { + inet_ntop(AF_INET, + &(((struct sockaddr_in *)&saddr)->sin_addr), + addr_str, addr_str_len); + } +#endif + /* getnameinfo return ip v6 address with the scope identifier + * such as : 2a01:e35:8b2b:7330::%4281128194 */ + n = getnameinfo((const struct sockaddr *)&saddr, saddrlen, + addr_str, addr_str_len, + NULL, 0, + NI_NUMERICHOST | NI_NUMERICSERV); + if(n != 0) { +#ifdef _WIN32 + fprintf(stderr, "getnameinfo() failed : %d\n", n); +#else + fprintf(stderr, "getnameinfo() failed : %s\n", gai_strerror(n)); +#endif + } +#endif + } +#ifdef DEBUG + printf("address miniwget : %s\n", addr_str); +#endif + } + + len = snprintf(buf, sizeof(buf), + "GET %s HTTP/%s\r\n" + "Host: %s:%d\r\n" + "Connection: Close\r\n" + "User-Agent: " OS_STRING ", " UPNP_VERSION_STRING ", MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n" + + "\r\n", + path, httpversion, host, port); + if ((unsigned int)len >= sizeof(buf)) + { + closesocket(s); + return NULL; + } + sent = 0; + /* sending the HTTP request */ + while(sent < len) + { + n = send(s, buf+sent, len-sent, 0); + if(n < 0) + { + perror("send"); + closesocket(s); + return NULL; + } + else + { + sent += n; + } + } + content = getHTTPResponse(s, size); + 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 + * hostname : hostname destination string (size of MAXHOSTNAMELEN+1) + * port : port (destination) + * path : pointer to the path part of the URL + * + * Return values : + * 0 - Failure + * 1 - Success */ +int +parseURL(const char * url, + char * hostname, unsigned short * port, + char * * path, unsigned int * scope_id) +{ + char * p1, *p2, *p3; + if(!url) + return 0; + p1 = strstr(url, "://"); + if(!p1) + return 0; + p1 += 3; + if( (url[0]!='h') || (url[1]!='t') + ||(url[2]!='t') || (url[3]!='p')) + return 0; + memset(hostname, 0, MAXHOSTNAMELEN + 1); + if(*p1 == '[') + { + /* IP v6 : http://[2a00:1450:8002::6a]/path/abc */ + char * scope; + scope = strchr(p1, '%'); + p2 = strchr(p1, ']'); + if(p2 && scope && scope < p2 && scope_id) { + /* parse scope */ +#ifdef IF_NAMESIZE + char tmp[IF_NAMESIZE]; + int l; + scope++; + /* "%25" is just '%' in URL encoding */ + if(scope[0] == '2' && scope[1] == '5') + scope += 2; /* skip "25" */ + l = p2 - scope; + if(l >= IF_NAMESIZE) + l = IF_NAMESIZE - 1; + memcpy(tmp, scope, l); + tmp[l] = '\0'; + *scope_id = if_nametoindex(tmp); + if(*scope_id == 0) { + *scope_id = (unsigned int)strtoul(tmp, NULL, 10); + } +#else + /* under windows, scope is numerical */ + char tmp[8]; + int l; + scope++; + /* "%25" is just '%' in URL encoding */ + if(scope[0] == '2' && scope[1] == '5') + scope += 2; /* skip "25" */ + l = p2 - scope; + if(l >= sizeof(tmp)) + l = sizeof(tmp) - 1; + memcpy(tmp, scope, l); + tmp[l] = '\0'; + *scope_id = (unsigned int)strtoul(tmp, NULL, 10); +#endif + } + p3 = strchr(p1, '/'); + if(p2 && p3) + { + p2++; + strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1))); + if(*p2 == ':') + { + *port = 0; + p2++; + while( (*p2 >= '0') && (*p2 <= '9')) + { + *port *= 10; + *port += (unsigned short)(*p2 - '0'); + p2++; + } + } + else + { + *port = 80; + } + *path = p3; + return 1; + } + } + p2 = strchr(p1, ':'); + p3 = strchr(p1, '/'); + if(!p3) + return 0; + if(!p2 || (p2>p3)) + { + strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p3-p1))); + *port = 80; + } + else + { + strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1))); + *port = 0; + p2++; + while( (*p2 >= '0') && (*p2 <= '9')) + { + *port *= 10; + *port += (unsigned short)(*p2 - '0'); + p2++; + } + } + *path = p3; + return 1; +} + +void * +miniwget(const char * url, int * size, unsigned int scope_id) +{ + unsigned short port; + char * path; + /* protocol://host:port/chemin */ + char hostname[MAXHOSTNAMELEN+1]; + *size = 0; + if(!parseURL(url, hostname, &port, &path, &scope_id)) + return NULL; +#ifdef DEBUG + printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n", + hostname, port, path, scope_id); +#endif + return miniwget2(hostname, port, path, size, 0, 0, scope_id); +} + +void * +miniwget_getaddr(const char * url, int * size, + char * addr, int addrlen, unsigned int scope_id) +{ + unsigned short port; + char * path; + /* protocol://host:port/path */ + char hostname[MAXHOSTNAMELEN+1]; + *size = 0; + if(addr) + addr[0] = '\0'; + if(!parseURL(url, hostname, &port, &path, &scope_id)) + return NULL; +#ifdef DEBUG + printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n", + hostname, port, path, scope_id); +#endif + return miniwget2(hostname, port, path, size, addr, addrlen, scope_id); +} + diff --git a/ext/miniupnpc/miniwget.h b/ext/miniupnpc/miniwget.h new file mode 100644 index 00000000..d6db71a8 --- /dev/null +++ b/ext/miniupnpc/miniwget.h @@ -0,0 +1,30 @@ +/* $Id: miniwget.h,v 1.10 2015/07/21 13:16:55 nanard Exp $ */ +/* Project : miniupnp + * Author : Thomas Bernard + * Copyright (c) 2005-2015 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. + * */ +#ifndef MINIWGET_H_INCLUDED +#define MINIWGET_H_INCLUDED + +#include "miniupnpc_declspec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MINIUPNP_LIBSPEC void * getHTTPResponse(int s, int * size); + +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 *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/ext/miniupnpc/minixml.c b/ext/miniupnpc/minixml.c new file mode 100644 index 00000000..3e201ec2 --- /dev/null +++ b/ext/miniupnpc/minixml.c @@ -0,0 +1,229 @@ +/* $Id: minixml.c,v 1.11 2014/02/03 15:54:12 nanard Exp $ */ +/* minixml.c : the minimum size a xml parser can be ! */ +/* Project : miniupnp + * webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * Author : Thomas Bernard + +Copyright (c) 2005-2014, Thomas BERNARD +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include "minixml.h" + +/* parseatt : used to parse the argument list + * return 0 (false) in case of success and -1 (true) if the end + * of the xmlbuffer is reached. */ +static int parseatt(struct xmlparser * p) +{ + const char * attname; + int attnamelen; + const char * attvalue; + int attvaluelen; + while(p->xml < p->xmlend) + { + if(*p->xml=='/' || *p->xml=='>') + return 0; + if( !IS_WHITE_SPACE(*p->xml) ) + { + char sep; + attname = p->xml; + attnamelen = 0; + while(*p->xml!='=' && !IS_WHITE_SPACE(*p->xml) ) + { + attnamelen++; p->xml++; + if(p->xml >= p->xmlend) + return -1; + } + while(*(p->xml++) != '=') + { + if(p->xml >= p->xmlend) + return -1; + } + while(IS_WHITE_SPACE(*p->xml)) + { + p->xml++; + if(p->xml >= p->xmlend) + return -1; + } + sep = *p->xml; + if(sep=='\'' || sep=='\"') + { + p->xml++; + if(p->xml >= p->xmlend) + return -1; + attvalue = p->xml; + attvaluelen = 0; + while(*p->xml != sep) + { + attvaluelen++; p->xml++; + if(p->xml >= p->xmlend) + return -1; + } + } + else + { + attvalue = p->xml; + attvaluelen = 0; + while( !IS_WHITE_SPACE(*p->xml) + && *p->xml != '>' && *p->xml != '/') + { + attvaluelen++; p->xml++; + if(p->xml >= p->xmlend) + return -1; + } + } + /*printf("%.*s='%.*s'\n", + attnamelen, attname, attvaluelen, attvalue);*/ + if(p->attfunc) + p->attfunc(p->data, attname, attnamelen, attvalue, attvaluelen); + } + p->xml++; + } + return -1; +} + +/* parseelt parse the xml stream and + * call the callback functions when needed... */ +static void parseelt(struct xmlparser * p) +{ + int i; + const char * elementname; + while(p->xml < (p->xmlend - 1)) + { + if((p->xml + 4) <= p->xmlend && (0 == memcmp(p->xml, "", 3) != 0); + p->xml += 3; + } + else if((p->xml)[0]=='<' && (p->xml)[1]!='?') + { + i = 0; elementname = ++p->xml; + while( !IS_WHITE_SPACE(*p->xml) + && (*p->xml!='>') && (*p->xml!='/') + ) + { + i++; p->xml++; + if (p->xml >= p->xmlend) + return; + /* to ignore namespace : */ + if(*p->xml==':') + { + i = 0; + elementname = ++p->xml; + } + } + if(i>0) + { + if(p->starteltfunc) + p->starteltfunc(p->data, elementname, i); + if(parseatt(p)) + return; + if(*p->xml!='/') + { + const char * data; + i = 0; data = ++p->xml; + if (p->xml >= p->xmlend) + return; + while( IS_WHITE_SPACE(*p->xml) ) + { + i++; p->xml++; + if (p->xml >= p->xmlend) + return; + } + if(memcmp(p->xml, "xml += 9; + data = p->xml; + i = 0; + while(memcmp(p->xml, "]]>", 3) != 0) + { + i++; p->xml++; + if ((p->xml + 3) >= p->xmlend) + return; + } + if(i>0 && p->datafunc) + p->datafunc(p->data, data, i); + while(*p->xml!='<') + { + p->xml++; + if (p->xml >= p->xmlend) + return; + } + } + else + { + while(*p->xml!='<') + { + i++; p->xml++; + if ((p->xml + 1) >= p->xmlend) + return; + } + if(i>0 && p->datafunc && *(p->xml + 1) == '/') + p->datafunc(p->data, data, i); + } + } + } + else if(*p->xml == '/') + { + i = 0; elementname = ++p->xml; + if (p->xml >= p->xmlend) + return; + while((*p->xml != '>')) + { + i++; p->xml++; + if (p->xml >= p->xmlend) + return; + } + if(p->endeltfunc) + p->endeltfunc(p->data, elementname, i); + p->xml++; + } + } + else + { + p->xml++; + } + } +} + +/* the parser must be initialized before calling this function */ +void parsexml(struct xmlparser * parser) +{ + parser->xml = parser->xmlstart; + parser->xmlend = parser->xmlstart + parser->xmlsize; + parseelt(parser); +} + + diff --git a/ext/miniupnpc/minixml.h b/ext/miniupnpc/minixml.h new file mode 100644 index 00000000..9f43aa48 --- /dev/null +++ b/ext/miniupnpc/minixml.h @@ -0,0 +1,37 @@ +/* $Id: minixml.h,v 1.7 2012/09/27 15:42:10 nanard Exp $ */ +/* minimal xml parser + * + * Project : miniupnp + * Website : http://miniupnp.free.fr/ + * Author : Thomas Bernard + * Copyright (c) 2005 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. + * */ +#ifndef MINIXML_H_INCLUDED +#define MINIXML_H_INCLUDED +#define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n')) + +/* if a callback function pointer is set to NULL, + * the function is not called */ +struct xmlparser { + const char *xmlstart; + const char *xmlend; + const char *xml; /* pointer to current character */ + int xmlsize; + void * data; + void (*starteltfunc) (void *, const char *, int); + void (*endeltfunc) (void *, const char *, int); + void (*datafunc) (void *, const char *, int); + void (*attfunc) (void *, const char *, int, const char *, int); +}; + +/* parsexml() + * the xmlparser structure must be initialized before the call + * the following structure members have to be initialized : + * xmlstart, xmlsize, data, *func + * xml is for internal usage, xmlend is computed automatically */ +void parsexml(struct xmlparser *); + +#endif + diff --git a/ext/miniupnpc/minixmlvalid.c b/ext/miniupnpc/minixmlvalid.c new file mode 100644 index 00000000..dad14881 --- /dev/null +++ b/ext/miniupnpc/minixmlvalid.c @@ -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 +#include +#include +#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; in; 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[] = +"\n" +" " +"character data" +" \n \t" +"" +"\nstuff !\n ]]> \n\n" +" \tchardata1 chardata2 " +""; + +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, " 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; +} + diff --git a/ext/miniupnpc/msvc/miniupnpc.sln b/ext/miniupnpc/msvc/miniupnpc.sln new file mode 100644 index 00000000..b3da1919 --- /dev/null +++ b/ext/miniupnpc/msvc/miniupnpc.sln @@ -0,0 +1,29 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C++ Express 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniupnpc", "miniupnpc.vcproj", "{D28CE435-CB33-4BAE-8A52-C6EF915956F5}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "upnpc-static", "upnpc-static.vcproj", "{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}" + ProjectSection(ProjectDependencies) = postProject + {D28CE435-CB33-4BAE-8A52-C6EF915956F5} = {D28CE435-CB33-4BAE-8A52-C6EF915956F5} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug|Win32.ActiveCfg = Debug|Win32 + {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug|Win32.Build.0 = Debug|Win32 + {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release|Win32.ActiveCfg = Release|Win32 + {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release|Win32.Build.0 = Release|Win32 + {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug|Win32.ActiveCfg = Debug|Win32 + {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug|Win32.Build.0 = Debug|Win32 + {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release|Win32.ActiveCfg = Release|Win32 + {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ext/miniupnpc/msvc/miniupnpc.vcproj b/ext/miniupnpc/msvc/miniupnpc.vcproj new file mode 100644 index 00000000..fb301e3b --- /dev/null +++ b/ext/miniupnpc/msvc/miniupnpc.vcproj @@ -0,0 +1,283 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/miniupnpc/msvc/upnpc-static.vcproj b/ext/miniupnpc/msvc/upnpc-static.vcproj new file mode 100644 index 00000000..c88c9a6e --- /dev/null +++ b/ext/miniupnpc/msvc/upnpc-static.vcproj @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/miniupnpc/portlistingparse.c b/ext/miniupnpc/portlistingparse.c new file mode 100644 index 00000000..0e092780 --- /dev/null +++ b/ext/miniupnpc/portlistingparse.c @@ -0,0 +1,172 @@ +/* $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 + * This software is subject to the conditions detailed + * in the LICENCE file provided within the distribution */ +#include +#include +#ifdef DEBUG +#include +#endif /* DEBUG */ +#include "portlistingparse.h" +#include "minixml.h" + +/* list of the elements */ +static const struct { + const portMappingElt code; + const char * const str; +} elements[] = { + { PortMappingEntry, "PortMappingEntry"}, + { NewRemoteHost, "NewRemoteHost"}, + { NewExternalPort, "NewExternalPort"}, + { NewProtocol, "NewProtocol"}, + { NewInternalPort, "NewInternalPort"}, + { NewInternalClient, "NewInternalClient"}, + { NewEnabled, "NewEnabled"}, + { NewDescription, "NewDescription"}, + { NewLeaseTime, "NewLeaseTime"}, + { PortMappingEltNone, NULL} +}; + +/* Helper function */ +static UNSIGNED_INTEGER +atoui(const char * p, int l) +{ + UNSIGNED_INTEGER r = 0; + while(l > 0 && *p) + { + if(*p >= '0' && *p <= '9') + r = r*10 + (*p - '0'); + else + break; + p++; + l--; + } + return r; +} + +/* Start element handler */ +static void +startelt(void * d, const char * name, int l) +{ + int i; + struct PortMappingParserData * pdata = (struct PortMappingParserData *)d; + pdata->curelt = PortMappingEltNone; + for(i = 0; elements[i].str; i++) + { + if(memcmp(name, elements[i].str, l) == 0) + { + pdata->curelt = elements[i].code; + break; + } + } + if(pdata->curelt == PortMappingEntry) + { + struct PortMapping * pm; + pm = calloc(1, sizeof(struct PortMapping)); + if(pm == NULL) + { + /* malloc error */ +#ifdef DEBUG + fprintf(stderr, "%s: error allocating memory", + "startelt"); +#endif /* DEBUG */ + return; + } + pm->l_next = pdata->l_head; /* insert in list */ + pdata->l_head = pm; + } +} + +/* End element handler */ +static void +endelt(void * d, const char * name, int l) +{ + struct PortMappingParserData * pdata = (struct PortMappingParserData *)d; + (void)name; + (void)l; + pdata->curelt = PortMappingEltNone; +} + +/* Data handler */ +static void +data(void * d, const char * data, int l) +{ + struct PortMapping * pm; + struct PortMappingParserData * pdata = (struct PortMappingParserData *)d; + pm = pdata->l_head; + if(!pm) + return; + if(l > 63) + l = 63; + switch(pdata->curelt) + { + case NewRemoteHost: + memcpy(pm->remoteHost, data, l); + pm->remoteHost[l] = '\0'; + break; + case NewExternalPort: + pm->externalPort = (unsigned short)atoui(data, l); + break; + case NewProtocol: + if(l > 3) + l = 3; + memcpy(pm->protocol, data, l); + pm->protocol[l] = '\0'; + break; + case NewInternalPort: + pm->internalPort = (unsigned short)atoui(data, l); + break; + case NewInternalClient: + memcpy(pm->internalClient, data, l); + pm->internalClient[l] = '\0'; + break; + case NewEnabled: + pm->enabled = (unsigned char)atoui(data, l); + break; + case NewDescription: + memcpy(pm->description, data, l); + pm->description[l] = '\0'; + break; + case NewLeaseTime: + pm->leaseTime = atoui(data, l); + break; + default: + break; + } +} + + +/* Parse the PortMappingList XML document for IGD version 2 + */ +void +ParsePortListing(const char * buffer, int bufsize, + struct PortMappingParserData * pdata) +{ + struct xmlparser parser; + + memset(pdata, 0, sizeof(struct PortMappingParserData)); + /* init xmlparser */ + parser.xmlstart = buffer; + parser.xmlsize = bufsize; + parser.data = pdata; + parser.starteltfunc = startelt; + parser.endeltfunc = endelt; + parser.datafunc = data; + parser.attfunc = 0; + parsexml(&parser); +} + +void +FreePortListing(struct PortMappingParserData * pdata) +{ + struct PortMapping * pm; + while((pm = pdata->l_head) != NULL) + { + /* remove from list */ + pdata->l_head = pm->l_next; + free(pm); + } +} + diff --git a/ext/miniupnpc/portlistingparse.h b/ext/miniupnpc/portlistingparse.h new file mode 100644 index 00000000..661ad1fa --- /dev/null +++ b/ext/miniupnpc/portlistingparse.h @@ -0,0 +1,65 @@ +/* $Id: portlistingparse.h,v 1.11 2015/07/21 13:16:55 nanard Exp $ */ +/* MiniUPnP project + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * (c) 2011-2015 Thomas Bernard + * This software is subject to the conditions detailed + * in the LICENCE file provided within the distribution */ +#ifndef PORTLISTINGPARSE_H_INCLUDED +#define PORTLISTINGPARSE_H_INCLUDED + +#include "miniupnpc_declspec.h" +/* for the definition of UNSIGNED_INTEGER */ +#include "miniupnpctypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* sample of PortMappingEntry : + + 202.233.2.1 + 2345 + TCP + 2345 + 192.168.1.137 + 1 + dooom + 345 + + */ +typedef enum { PortMappingEltNone, + PortMappingEntry, NewRemoteHost, + NewExternalPort, NewProtocol, + NewInternalPort, NewInternalClient, + NewEnabled, NewDescription, + NewLeaseTime } portMappingElt; + +struct PortMapping { + struct PortMapping * l_next; /* list next element */ + UNSIGNED_INTEGER leaseTime; + unsigned short externalPort; + unsigned short internalPort; + char remoteHost[64]; + char internalClient[64]; + char description[64]; + char protocol[4]; + unsigned char enabled; +}; + +struct PortMappingParserData { + struct PortMapping * l_head; /* list head */ + portMappingElt curelt; +}; + +MINIUPNP_LIBSPEC void +ParsePortListing(const char * buffer, int bufsize, + struct PortMappingParserData * pdata); + +MINIUPNP_LIBSPEC void +FreePortListing(struct PortMappingParserData * pdata); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ext/miniupnpc/pymoduletest.py b/ext/miniupnpc/pymoduletest.py new file mode 100644 index 00000000..9fddd9c2 --- /dev/null +++ b/ext/miniupnpc/pymoduletest.py @@ -0,0 +1,88 @@ +#! /usr/bin/python +# vim: tabstop=2 shiftwidth=2 expandtab +# MiniUPnP project +# Author : Thomas Bernard +# This Sample code is public domain. +# website : http://miniupnp.tuxfamily.org/ + +# import the python miniupnpc module +import miniupnpc +import sys + +try: + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('-m', '--multicastif') + parser.add_argument('-p', '--minissdpdsocket') + parser.add_argument('-d', '--discoverdelay', type=int, default=200) + parser.add_argument('-z', '--localport', type=int, default=0) + # create the object + u = miniupnpc.UPnP(**vars(parser.parse_args())) +except: + print 'argparse not available' + i = 1 + multicastif = None + minissdpdsocket = None + discoverdelay = 200 + localport = 0 + while i < len(sys.argv): + print sys.argv[i] + if sys.argv[i] == '-m' or sys.argv[i] == '--multicastif': + multicastif = sys.argv[i+1] + elif sys.argv[i] == '-p' or sys.argv[i] == '--minissdpdsocket': + minissdpdsocket = sys.argv[i+1] + elif sys.argv[i] == '-d' or sys.argv[i] == '--discoverdelay': + discoverdelay = int(sys.argv[i+1]) + elif sys.argv[i] == '-z' or sys.argv[i] == '--localport': + localport = int(sys.argv[i+1]) + else: + raise Exception('invalid argument %s' % sys.argv[i]) + i += 2 + # create the object + u = miniupnpc.UPnP(multicastif, minissdpdsocket, discoverdelay, localport) + +print 'inital(default) values :' +print ' discoverdelay', u.discoverdelay +print ' lanaddr', u.lanaddr +print ' multicastif', u.multicastif +print ' minissdpdsocket', u.minissdpdsocket +#u.minissdpdsocket = '../minissdpd/minissdpd.sock' +# discovery process, it usualy takes several seconds (2 seconds or more) +print 'Discovering... delay=%ums' % u.discoverdelay +print u.discover(), 'device(s) detected' +# select an igd +try: + u.selectigd() +except Exception, e: + print 'Exception :', e + sys.exit(1) +# display information about the IGD and the internet connection +print 'local ip address :', u.lanaddr +print 'external ip address :', u.externalipaddress() +print u.statusinfo(), u.connectiontype() +print 'total bytes : sent', u.totalbytesent(), 'received', u.totalbytereceived() +print 'total packets : sent', u.totalpacketsent(), 'received', u.totalpacketreceived() + +#print u.addportmapping(64000, 'TCP', +# '192.168.1.166', 63000, 'port mapping test', '') +#print u.deleteportmapping(64000, 'TCP') + +port = 0 +proto = 'UDP' +# list the redirections : +i = 0 +while True: + p = u.getgenericportmapping(i) + if p==None: + break + print i, p + (port, proto, (ihost,iport), desc, c, d, e) = p + #print port, desc + i = i + 1 + +print u.getspecificportmapping(port, proto) +try: + print u.getportmappingnumberofentries() +except Exception, e: + print 'GetPortMappingNumberOfEntries() is not supported :', e + diff --git a/ext/miniupnpc/receivedata.c b/ext/miniupnpc/receivedata.c new file mode 100644 index 00000000..fb05e09d --- /dev/null +++ b/ext/miniupnpc/receivedata.c @@ -0,0 +1,105 @@ +/* $Id: receivedata.c,v 1.6 2014/11/13 13:51:52 nanard Exp $ */ +/* Project : miniupnp + * Website : http://miniupnp.free.fr/ + * Author : Thomas Bernard + * Copyright (c) 2011-2014 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. */ + +#include +#include +#ifdef _WIN32 +#include +#include +#else /* _WIN32 */ +#include +#if defined(__amigaos__) && !defined(__amigaos4__) +#define socklen_t int +#else /* #if defined(__amigaos__) && !defined(__amigaos4__) */ +#include +#endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */ +#include +#include +#if !defined(__amigaos__) && !defined(__amigaos4__) +#include +#endif /* !defined(__amigaos__) && !defined(__amigaos4__) */ +#include +#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, + char * data, int length, + int timeout, unsigned int * scope_id) +{ +#if MINIUPNPC_GET_SRC_ADDR + struct sockaddr_storage src_addr; + socklen_t src_addr_len = sizeof(src_addr); +#endif /* MINIUPNPC_GET_SRC_ADDR */ + int n; +#if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) + /* using poll */ + struct pollfd fds[1]; /* for the poll */ +#ifdef MINIUPNPC_IGNORE_EINTR + do { +#endif /* MINIUPNPC_IGNORE_EINTR */ + fds[0].fd = socket; + fds[0].events = POLLIN; + n = poll(fds, 1, timeout); +#ifdef MINIUPNPC_IGNORE_EINTR + } while(n < 0 && errno == EINTR); +#endif /* MINIUPNPC_IGNORE_EINTR */ + if(n < 0) { + PRINT_SOCKET_ERROR("poll"); + return -1; + } else if(n == 0) { + /* timeout */ + return 0; + } +#else /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ + /* using select under _WIN32 and amigaos */ + fd_set socketSet; + TIMEVAL timeval; + FD_ZERO(&socketSet); + FD_SET(socket, &socketSet); + timeval.tv_sec = timeout / 1000; + timeval.tv_usec = (timeout % 1000) * 1000; + n = select(FD_SETSIZE, &socketSet, NULL, NULL, &timeval); + if(n < 0) { + PRINT_SOCKET_ERROR("select"); + return -1; + } else if(n == 0) { + return 0; + } +#endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ +#if MINIUPNPC_GET_SRC_ADDR + memset(&src_addr, 0, sizeof(src_addr)); + n = recvfrom(socket, data, length, 0, + (struct sockaddr *)&src_addr, &src_addr_len); +#else /* MINIUPNPC_GET_SRC_ADDR */ + n = recv(socket, data, length, 0); +#endif /* MINIUPNPC_GET_SRC_ADDR */ + if(n<0) { + PRINT_SOCKET_ERROR("recv"); + } +#if MINIUPNPC_GET_SRC_ADDR + if (src_addr.ss_family == AF_INET6) { + const struct sockaddr_in6 * src_addr6 = (struct sockaddr_in6 *)&src_addr; +#ifdef DEBUG + printf("scope_id=%u\n", src_addr6->sin6_scope_id); +#endif /* DEBUG */ + if(scope_id) + *scope_id = src_addr6->sin6_scope_id; + } +#endif /* MINIUPNPC_GET_SRC_ADDR */ + return n; +} + diff --git a/ext/miniupnpc/receivedata.h b/ext/miniupnpc/receivedata.h new file mode 100644 index 00000000..0520a11d --- /dev/null +++ b/ext/miniupnpc/receivedata.h @@ -0,0 +1,19 @@ +/* $Id: receivedata.h,v 1.4 2012/09/27 15:42:10 nanard Exp $ */ +/* Project: miniupnp + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * Author: Thomas Bernard + * Copyright (c) 2011-2012 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 + +/* Reads data from the specified socket. + * Returns the number of bytes read if successful, zero if no bytes were + * read or if we timed out. Returns negative if there was an error. */ +int receivedata(int socket, + char * data, int length, + int timeout, unsigned int * scope_id); + +#endif + diff --git a/ext/miniupnpc/setup.py b/ext/miniupnpc/setup.py new file mode 100644 index 00000000..97e42bf1 --- /dev/null +++ b/ext/miniupnpc/setup.py @@ -0,0 +1,28 @@ +#! /usr/bin/python +# vim: tabstop=8 shiftwidth=8 expandtab +# $Id: setup.py,v 1.12 2015/10/26 17:03:17 nanard Exp $ +# the MiniUPnP Project (c) 2007-2014 Thomas Bernard +# http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/ +# +# python script to build the miniupnpc module under unix +# +# replace libminiupnpc.a by libminiupnpc.so for shared library usage +try: + from setuptools import setup, Extension +except ImportError: + from distutils.core import setup, Extension +from distutils import sysconfig +sysconfig.get_config_vars()["OPT"] = '' +sysconfig.get_config_vars()["CFLAGS"] = '' +setup(name="miniupnpc", + version=open('VERSION').read().strip(), + author='Thomas BERNARD', + author_email='miniupnp@free.fr', + license=open('LICENSE').read(), + url='http://miniupnp.free.fr/', + description='miniUPnP client', + ext_modules=[ + Extension(name="miniupnpc", sources=["miniupnpcmodule.c"], + extra_objects=["libminiupnpc.a"]) + ]) + diff --git a/ext/miniupnpc/setupmingw32.py b/ext/miniupnpc/setupmingw32.py new file mode 100644 index 00000000..43dfb465 --- /dev/null +++ b/ext/miniupnpc/setupmingw32.py @@ -0,0 +1,28 @@ +#! /usr/bin/python +# vim: tabstop=8 shiftwidth=8 expandtab +# $Id: setupmingw32.py,v 1.10 2015/10/26 17:03:17 nanard Exp $ +# the MiniUPnP Project (c) 2007-2014 Thomas Bernard +# http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/ +# +# python script to build the miniupnpc module under windows (using mingw32) +# +try: + from setuptools import setup, Extension +except ImportError: + from distutils.core import setup, Extension +from distutils import sysconfig +sysconfig.get_config_vars()["OPT"] = '' +sysconfig.get_config_vars()["CFLAGS"] = '' +setup(name="miniupnpc", + version=open('VERSION').read().strip(), + author='Thomas BERNARD', + author_email='miniupnp@free.fr', + license=open('LICENSE').read(), + url='http://miniupnp.free.fr/', + description='miniUPnP client', + ext_modules=[ + Extension(name="miniupnpc", sources=["miniupnpcmodule.c"], + libraries=["ws2_32", "iphlpapi"], + extra_objects=["libminiupnpc.a"]) + ]) + diff --git a/ext/miniupnpc/testdesc/linksys_WAG200G_desc.values b/ext/miniupnpc/testdesc/linksys_WAG200G_desc.values new file mode 100644 index 00000000..cf422218 --- /dev/null +++ b/ext/miniupnpc/testdesc/linksys_WAG200G_desc.values @@ -0,0 +1,14 @@ +# values for linksys_WAG200G_desc.xml + +CIF: + servicetype = urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 + controlurl = /upnp/control/WANCommonIFC1 + eventsuburl = /upnp/event/WANCommonIFC1 + scpdurl = /cmnicfg.xml + +first: + servicetype = urn:schemas-upnp-org:service:WANPPPConnection:1 + controlurl = /upnp/control/WANPPPConn1 + eventsuburl = /upnp/event/WANPPPConn1 + scpdurl = /pppcfg.xml + diff --git a/ext/miniupnpc/testdesc/linksys_WAG200G_desc.xml b/ext/miniupnpc/testdesc/linksys_WAG200G_desc.xml new file mode 100644 index 00000000..d428d73b --- /dev/null +++ b/ext/miniupnpc/testdesc/linksys_WAG200G_desc.xml @@ -0,0 +1,110 @@ + + + +1 +0 + +http://192.168.1.1:49152 + +urn:schemas-upnp-org:device:InternetGatewayDevice:1 +LINKSYS WAG200G Gateway +LINKSYS +http://www.linksys.com +LINKSYS WAG200G Gateway +Wireless-G ADSL Home Gateway +WAG200G +http://www.linksys.com +123456789 +uuid:8ca2eb37-1dd2-11b2-86f1-001a709b5aa8 +WAG200G + + +urn:schemas-upnp-org:service:Layer3Forwarding:1 +urn:upnp-org:serviceId:L3Forwarding1 +/upnp/control/L3Forwarding1 +/upnp/event/L3Forwarding1 +/l3frwd.xml + + + + +urn:schemas-upnp-org:device:WANDevice:1 +WANDevice +LINKSYS +http://www.linksys.com/ +Residential Gateway +Internet Connection Sharing +1 +http://www.linksys.com/ +0000001 +uuid:8ca2eb36-1dd2-11b2-86f1-001a709b5aa8 +WAG200G + + +urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 +urn:upnp-org:serviceId:WANCommonIFC1 +/upnp/control/WANCommonIFC1 +/upnp/event/WANCommonIFC1 +/cmnicfg.xml + + + + +urn:schemas-upnp-org:device:WANConnectionDevice:1 +WANConnectionDevice +LINKSYS +http://www.linksys.com/ +Residential Gateway +Internet Connection Sharing +1 +http://www.linksys.com/ +0000001 +uuid:8ca2eb37-1dd2-11b2-86f0-001a709b5aa8 +WAG200G + + +urn:schemas-upnp-org:service:WANEthernetLinkConfig:1 +urn:upnp-org:serviceId:WANEthLinkC1 +/upnp/control/WANEthLinkC1 +/upnp/event/WANEthLinkC1 +/wanelcfg.xml + + +urn:schemas-upnp-org:service:WANPPPConnection:1 +urn:upnp-org:serviceId:WANPPPConn1 +/upnp/control/WANPPPConn1 +/upnp/event/WANPPPConn1 +/pppcfg.xml + + + + + + +urn:schemas-upnp-org:device:LANDevice:1 +LANDevice +LINKSYS +http://www.linksys.com/ +Residential Gateway +Residential Gateway +1 +http://www.linksys.com/ +0000001 +uuid:8ca2eb36-1dd2-11b2-86f0-001a709b5aa +8 +WAG200G + + +urn:schemas-upnp-org:service:LANHostConfigManagement:1 +urn:upnp-org:serviceId:LANHostCfg1 +/upnp/control/LANHostCfg1 +/upnp/event/LANHostCfg1 +/lanhostc.xml + + + + +http://192.168.1.1/index.htm + + + diff --git a/ext/miniupnpc/testdesc/new_LiveBox_desc.values b/ext/miniupnpc/testdesc/new_LiveBox_desc.values new file mode 100644 index 00000000..c55552e5 --- /dev/null +++ b/ext/miniupnpc/testdesc/new_LiveBox_desc.values @@ -0,0 +1,20 @@ +# values for new_LiveBox_desc.xml + +CIF: + servicetype = urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 + controlurl = /87895a19/upnp/control/WANCommonIFC1 + eventsuburl = /87895a19/upnp/control/WANCommonIFC1 + scpdurl = /87895a19/gateicfgSCPD.xml + +first: + servicetype = urn:schemas-upnp-org:service:WANPPPConnection:2 + controlurl = /87895a19/upnp/control/WANIPConn1 + eventsuburl = /87895a19/upnp/control/WANIPConn1 + scpdurl = /87895a19/gateconnSCPD_PPP.xml + +IPv6FC: + servicetype = urn:schemas-upnp-org:service:WANIPv6FirewallControl:1 + controlurl = /87895a19/upnp/control/WANIPv6FwCtrl1 + eventsuburl = /87895a19/upnp/control/WANIPv6FwCtrl1 + scpdurl = /87895a19/wanipv6fwctrlSCPD.xml + diff --git a/ext/miniupnpc/testdesc/new_LiveBox_desc.xml b/ext/miniupnpc/testdesc/new_LiveBox_desc.xml new file mode 100644 index 00000000..620eb55a --- /dev/null +++ b/ext/miniupnpc/testdesc/new_LiveBox_desc.xml @@ -0,0 +1,90 @@ + + + + 1 + 0 + + + VEN_0129&DEV_0000&SUBSYS_03&REV_250417 + GenericUmPass + NetworkInfrastructure.Gateway + Network.Gateway + urn:schemas-upnp-org:device:InternetGatewayDevice:2 + Orange Livebox + Sagemcom + http://www.sagemcom.com/ + Residential Livebox,(DSL,WAN Ethernet) + uuid:87895a19-50f9-3736-a87f-115c230155f8 + Sagemcom,fr,SG30_sip-fr-4.28.35.1 + 3 + LK14129DP441489 + http://192.168.1.1 + + + + image/png + 16 + 16 + 8 + /87895a19/ligd.png + + + + + urn:schemas-upnp-org:device:WANDevice:2 + WANDevice + Sagemcom + http://www.sagemcom.com/ + WAN Device on Sagemcom,fr,SG30_sip-fr-4.28.35.1 + Residential Livebox,(DSL,WAN Ethernet) + 3 + http://www.sagemcom.com/ + LK14129DP441489 + http://192.168.1.1 + uuid:e2397374-53d8-3fc6-8306-593ba1a34625 + + + + urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 + urn:upnp-org:serviceId:WANCommonIFC1 + /87895a19/upnp/control/WANCommonIFC1 + /87895a19/upnp/control/WANCommonIFC1 + /87895a19/gateicfgSCPD.xml + + + + + urn:schemas-upnp-org:device:WANConnectionDevice:2 + WANConnectionDevice + Sagemcom + http://www.sagemcom.com/ + WanConnectionDevice on Sagemcom,fr,SG30_sip-fr-4.28.35.1 + Residential Livebox,(DSL,WAN Ethernet) + 3 + http://www.sagemcom.com/ + LK14129DP441489 + http://192.168.1.1 + uuid:44598a08-288e-32c9-8a4d-d3c008ede331 + + + + urn:schemas-upnp-org:service:WANPPPConnection:2 + urn:upnp-org:serviceId:WANIPConn1 + /87895a19/upnp/control/WANIPConn1 + /87895a19/upnp/control/WANIPConn1 + /87895a19/gateconnSCPD_PPP.xml + + + urn:schemas-upnp-org:service:WANIPv6FirewallControl:1 + urn:upnp-org:serviceId:WANIPv6FwCtrl1 + /87895a19/upnp/control/WANIPv6FwCtrl1 + /87895a19/upnp/control/WANIPv6FwCtrl1 + /87895a19/wanipv6fwctrlSCPD.xml + + + + + + + + \ No newline at end of file diff --git a/ext/miniupnpc/testigddescparse.c b/ext/miniupnpc/testigddescparse.c new file mode 100644 index 00000000..c1907fd0 --- /dev/null +++ b/ext/miniupnpc/testigddescparse.c @@ -0,0 +1,187 @@ +/* $Id: testigddescparse.c,v 1.10 2015/08/06 09:55:24 nanard Exp $ */ +/* Project : miniupnp + * http://miniupnp.free.fr/ + * Author : Thomas Bernard + * Copyright (c) 2008-2015 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. + * */ +#include +#include +#include +#include "igd_desc_parse.h" +#include "minixml.h" +#include "miniupnpc.h" + +/* count number of differences */ +int compare_service(struct IGDdatas_service * s, FILE * f) +{ + int n = 0; + char line[1024]; + + while(fgets(line, sizeof(line), f)) { + char * value; + char * equal; + char * name; + char * parsedvalue; + int l; + l = strlen(line); + while((l > 0) && ((line[l-1] == '\r') || (line[l-1] == '\n') || (line[l-1] == ' '))) + line[--l] = '\0'; + if(l == 0) + break; /* end on blank line */ + if(line[0] == '#') + continue; /* skip comments */ + equal = strchr(line, '='); + if(equal == NULL) { + fprintf(stderr, "Warning, line does not contain '=' : %s\n", line); + continue; + } + *equal = '\0'; + name = line; + while(*name == ' ' || *name == '\t') + name++; + l = strlen(name); + while((l > 0) && (name[l-1] == ' ' || name[l-1] == '\t')) + name[--l] = '\0'; + value = equal + 1; + while(*value == ' ' || *value == '\t') + value++; + if(strcmp(name, "controlurl") == 0) + parsedvalue = s->controlurl; + else if(strcmp(name, "eventsuburl") == 0) + parsedvalue = s->eventsuburl; + else if(strcmp(name, "scpdurl") == 0) + parsedvalue = s->scpdurl; + else if(strcmp(name, "servicetype") == 0) + parsedvalue = s->servicetype; + else { + fprintf(stderr, "unknown field '%s'\n", name); + continue; + } + if(0 != strcmp(parsedvalue, value)) { + fprintf(stderr, "difference : '%s' != '%s'\n", parsedvalue, value); + n++; + } + } + return n; +} + +int compare_igd(struct IGDdatas * p, FILE * f) +{ + int n = 0; + char line[1024]; + struct IGDdatas_service * s; + + while(fgets(line, sizeof(line), f)) { + char * colon; + int l = (int)strlen(line); + while((l > 0) && (line[l-1] == '\r' || (line[l-1] == '\n'))) + line[--l] = '\0'; + if(l == 0 || line[0] == '#') + continue; /* skip blank lines and comments */ + colon = strchr(line, ':'); + if(colon == NULL) { + fprintf(stderr, "Warning, no ':' : %s\n", line); + continue; + } + s = NULL; + *colon = '\0'; + if(strcmp(line, "CIF") == 0) + s = &p->CIF; + else if(strcmp(line, "first") == 0) + s = &p->first; + else if(strcmp(line, "second") == 0) + s = &p->second; + else if(strcmp(line, "IPv6FC") == 0) + s = &p->IPv6FC; + else { + s = NULL; + fprintf(stderr, "*** unknown service '%s' ***\n", line); + n++; + continue; + } + n += compare_service(s, f); + } + if(n > 0) + fprintf(stderr, "*** %d difference%s ***\n", n, (n > 1) ? "s" : ""); + return n; +} + +int test_igd_desc_parse(char * buffer, int len, FILE * f) +{ + int n; + struct IGDdatas igd; + struct xmlparser parser; + struct UPNPUrls urls; + + memset(&igd, 0, sizeof(struct IGDdatas)); + memset(&parser, 0, sizeof(struct xmlparser)); + parser.xmlstart = buffer; + parser.xmlsize = len; + parser.data = &igd; + parser.starteltfunc = IGDstartelt; + parser.endeltfunc = IGDendelt; + parser.datafunc = IGDdata; + parsexml(&parser); +#ifdef DEBUG + printIGD(&igd); +#endif /* DEBUG */ + GetUPNPUrls(&urls, &igd, "http://fake/desc/url/file.xml", 0); + printf("ipcondescURL='%s'\n", urls.ipcondescURL); + printf("controlURL='%s'\n", urls.controlURL); + printf("controlURL_CIF='%s'\n", urls.controlURL_CIF); + n = f ? compare_igd(&igd, f) : 0; + FreeUPNPUrls(&urls); + return n; +} + +int main(int argc, char * * argv) +{ + FILE * f; + char * buffer; + int len; + int r; + if(argc<2) { + fprintf(stderr, "Usage: %s file.xml [file.values]\n", argv[0]); + return 1; + } + f = fopen(argv[1], "r"); + if(!f) { + fprintf(stderr, "Cannot open %s for reading.\n", argv[1]); + return 1; + } + fseek(f, 0, SEEK_END); + len = ftell(f); + fseek(f, 0, SEEK_SET); + buffer = malloc(len); + if(!buffer) { + fprintf(stderr, "Memory allocation error.\n"); + fclose(f); + return 1; + } + r = (int)fread(buffer, 1, len, f); + if(r != len) { + fprintf(stderr, "Failed to read file %s. %d out of %d bytes.\n", + argv[1], r, len); + fclose(f); + free(buffer); + return 1; + } + fclose(f); + f = NULL; + if(argc > 2) { + f = fopen(argv[2], "r"); + if(!f) { + fprintf(stderr, "Cannot open %s for reading.\n", argv[2]); + free(buffer); + return 1; + } + } + r = test_igd_desc_parse(buffer, len, f); + free(buffer); + if(f) + fclose(f); + return r; +} + diff --git a/ext/miniupnpc/testminiwget.c b/ext/miniupnpc/testminiwget.c new file mode 100644 index 00000000..8ae90320 --- /dev/null +++ b/ext/miniupnpc/testminiwget.c @@ -0,0 +1,53 @@ +/* $Id: testminiwget.c,v 1.4 2012/06/23 22:35:59 nanard Exp $ */ +/* Project : miniupnp + * Author : Thomas Bernard + * Copyright (c) 2005-2012 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. + * */ +#include +#include +#include "miniwget.h" + +/** + * This program uses the miniwget / miniwget_getaddr function + * from miniwget.c in order to retreive a web ressource using + * a GET HTTP method, and store it in a file. + */ +int main(int argc, char * * argv) +{ + void * data; + int size, writtensize; + FILE *f; + char addr[64]; + + if(argc < 3) { + fprintf(stderr, "Usage:\t%s url file\n", argv[0]); + fprintf(stderr, "Example:\t%s http://www.google.com/ out.html\n", argv[0]); + return 1; + } + data = miniwget_getaddr(argv[1], &size, addr, sizeof(addr), 0); + if(!data) { + fprintf(stderr, "Error fetching %s\n", argv[1]); + return 1; + } + printf("local address : %s\n", addr); + printf("got %d bytes\n", size); + f = fopen(argv[2], "wb"); + if(!f) { + fprintf(stderr, "Cannot open file %s for writing\n", argv[2]); + free(data); + return 1; + } + writtensize = fwrite(data, 1, size, f); + if(writtensize != size) { + fprintf(stderr, "Could only write %d bytes out of %d to %s\n", + writtensize, size, argv[2]); + } else { + printf("%d bytes written to %s\n", writtensize, argv[2]); + } + fclose(f); + free(data); + return 0; +} + diff --git a/ext/miniupnpc/testminiwget.sh b/ext/miniupnpc/testminiwget.sh new file mode 100755 index 00000000..690b4056 --- /dev/null +++ b/ext/miniupnpc/testminiwget.sh @@ -0,0 +1,96 @@ +#!/bin/sh +# $Id: testminiwget.sh,v 1.13 2015/09/03 17:57:44 nanard Exp $ +# project miniupnp : http://miniupnp.free.fr/ +# (c) 2011-2015 Thomas Bernard +# +# test program for miniwget.c +# is usually invoked by "make check" +# +# This test program : +# 1 - launches a local HTTP server (minihttptestserver) +# 2 - uses testminiwget to retreive data from this server +# 3 - compares served and received data +# 4 - kills the local HTTP server and exits +# +# The script was tested and works with ksh, bash +# it should now also run with dash + +TMPD=`mktemp -d -t miniwgetXXXXXXXXXX` +HTTPSERVEROUT="${TMPD}/httpserverout" +EXPECTEDFILE="${TMPD}/expectedfile" +DOWNLOADEDFILE="${TMPD}/downloadedfile" +PORT= +RET=0 + +case "$HAVE_IPV6" in + n|no|0) + ADDR=localhost + SERVERARGS="" + ;; + *) + ADDR="[::1]" + SERVERARGS="-6" + ;; + +esac + +#make minihttptestserver +#make testminiwget + +# launching the test HTTP server +./minihttptestserver $SERVERARGS -e $EXPECTEDFILE > $HTTPSERVEROUT & +SERVERPID=$! +while [ -z "$PORT" ]; do + sleep 1 + PORT=`cat $HTTPSERVEROUT | sed 's/Listening on port \([0-9]*\)/\1/' ` +done +echo "Test HTTP server is listening on $PORT" + +URL1="http://$ADDR:$PORT/index.html" +URL2="http://$ADDR:$PORT/chunked" +URL3="http://$ADDR:$PORT/addcrap" + +echo "standard test ..." +./testminiwget $URL1 "${DOWNLOADEDFILE}.1" +if cmp $EXPECTEDFILE "${DOWNLOADEDFILE}.1" ; then + echo "ok" +else + echo "standard test FAILED" + RET=1 +fi + +echo "chunked transfert encoding test ..." +./testminiwget $URL2 "${DOWNLOADEDFILE}.2" +if cmp $EXPECTEDFILE "${DOWNLOADEDFILE}.2" ; then + echo "ok" +else + echo "chunked transfert encoding test FAILED" + RET=1 +fi + +echo "response too long test ..." +./testminiwget $URL3 "${DOWNLOADEDFILE}.3" +if cmp $EXPECTEDFILE "${DOWNLOADEDFILE}.3" ; then + echo "ok" +else + echo "response too long test FAILED" + RET=1 +fi + +# kill the test HTTP server +kill $SERVERPID +wait $SERVERPID + +# remove temporary files (for success cases) +if [ $RET -eq 0 ]; then + rm -f "${DOWNLOADEDFILE}.1" + rm -f "${DOWNLOADEDFILE}.2" + rm -f "${DOWNLOADEDFILE}.3" + rm -f $EXPECTEDFILE $HTTPSERVEROUT + rmdir ${TMPD} +else + echo "at least one of the test FAILED" + echo "directory ${TMPD} is left intact" +fi +exit $RET + diff --git a/ext/miniupnpc/testminixml.c b/ext/miniupnpc/testminixml.c new file mode 100644 index 00000000..57c4a85e --- /dev/null +++ b/ext/miniupnpc/testminixml.c @@ -0,0 +1,89 @@ +/* $Id: testminixml.c,v 1.10 2014/11/17 17:19:13 nanard Exp $ + * MiniUPnP project + * Website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * Author : Thomas Bernard. + * Copyright (c) 2005-2014 Thomas Bernard + * + * testminixml.c + * test program for the "minixml" functions. + */ +#include +#include +#include +#include "minixml.h" +#include "igd_desc_parse.h" + +/* ---------------------------------------------------------------------- */ +void printeltname1(void * d, const char * name, int l) +{ + int i; + (void)d; + printf("element "); + for(i=0;i +#include +#include "portlistingparse.h" + +struct port_mapping { + unsigned int leasetime; + unsigned short externalport; + unsigned short internalport; + const char * remotehost; + const char * client; + const char * proto; + const char * desc; + unsigned char enabled; +}; + +/* return the number of differences */ +int test(const char * portListingXml, int portListingXmlLen, + const struct port_mapping * ref, int count) +{ + int i; + int r = 0; + struct PortMappingParserData data; + struct PortMapping * pm; + + memset(&data, 0, sizeof(data)); + ParsePortListing(portListingXml, portListingXmlLen, &data); + for(i = 0, pm = data.l_head; + (pm != NULL) && (i < count); + i++, pm = pm->l_next) { + printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n", + i, pm->protocol, pm->externalPort, pm->internalClient, + pm->internalPort, + pm->description, pm->remoteHost, + (unsigned)pm->leaseTime); + if(0 != strcmp(pm->protocol, ref[i].proto)) { + printf("protocol : '%s' != '%s'\n", pm->protocol, ref[i].proto); + r++; + } + if(pm->externalPort != ref[i].externalport) { + printf("externalPort : %hu != %hu\n", + pm->externalPort, ref[i].externalport); + r++; + } + if(0 != strcmp(pm->internalClient, ref[i].client)) { + printf("client : '%s' != '%s'\n", + pm->internalClient, ref[i].client); + r++; + } + if(pm->internalPort != ref[i].internalport) { + printf("internalPort : %hu != %hu\n", + pm->internalPort, ref[i].internalport); + r++; + } + if(0 != strcmp(pm->description, ref[i].desc)) { + printf("description : '%s' != '%s'\n", + pm->description, ref[i].desc); + r++; + } + if(0 != strcmp(pm->remoteHost, ref[i].remotehost)) { + printf("remoteHost : '%s' != '%s'\n", + pm->remoteHost, ref[i].remotehost); + r++; + } + if((unsigned)pm->leaseTime != ref[i].leasetime) { + printf("leaseTime : %u != %u\n", + (unsigned)pm->leaseTime, ref[i].leasetime); + r++; + } + if(pm->enabled != ref[i].enabled) { + printf("enabled : %d != %d\n", + (int)pm->enabled, (int)ref[i].enabled); + r++; + } + } + if((i != count) || (pm != NULL)) { + printf("count mismatch : i=%d count=%d pm=%p\n", i, count, pm); + r++; + } + FreePortListing(&data); + return r; +} + +const char test_document[] = +"\n" +"\n" +" \n" +" \n" +" 5002\n" +" UDP\n" +" 4001\n" +" 192.168.1.123\n" +" 1\n" +" xxx\n" +" 0\n" +" \n" +" \n" +" 202.233.2.1\n" +" 2345\n" +" TCP\n" +" 2349\n" +" 192.168.1.137\n" +" 1\n" +" dooom\n" +" 346\n" +" \n" +" \n" +" 134.231.2.11\n" +" 12345\n" +" TCP\n" +" 12345\n" +" 192.168.1.137\n" +" 1\n" +" dooom A\n" +" 347\n" +" \n" +""; + +#define PORT_MAPPINGS_COUNT 3 +const struct port_mapping port_mappings[PORT_MAPPINGS_COUNT] = { +{347, 12345, 12345, "134.231.2.11", "192.168.1.137", "TCP", "dooom A", 1}, +{346, 2345, 2349, "202.233.2.1", "192.168.1.137", "TCP", "dooom", 1}, +{0, 5002, 4001, "", "192.168.1.123", "UDP", "xxx", 1} +}; + +/* --- main --- */ +int main(void) +{ + int r; + r = test(test_document, sizeof(test_document) - 1, + port_mappings, PORT_MAPPINGS_COUNT); + if(r == 0) { + printf("test of portlistingparse OK\n"); + return 0; + } else { + printf("test FAILED (%d differences counted)\n", r); + return 1; + } +} + diff --git a/ext/miniupnpc/testreplyparse/DeletePortMapping.namevalue b/ext/miniupnpc/testreplyparse/DeletePortMapping.namevalue new file mode 100644 index 00000000..48ca0ccc --- /dev/null +++ b/ext/miniupnpc/testreplyparse/DeletePortMapping.namevalue @@ -0,0 +1,3 @@ +NewRemoteHost= +NewExternalPort=123 +NewProtocol=TCP diff --git a/ext/miniupnpc/testreplyparse/DeletePortMapping.xml b/ext/miniupnpc/testreplyparse/DeletePortMapping.xml new file mode 100644 index 00000000..a955c53f --- /dev/null +++ b/ext/miniupnpc/testreplyparse/DeletePortMapping.xml @@ -0,0 +1,6 @@ + +123 +TCP + + + diff --git a/ext/miniupnpc/testreplyparse/GetExternalIPAddress.namevalue b/ext/miniupnpc/testreplyparse/GetExternalIPAddress.namevalue new file mode 100644 index 00000000..5aa75f88 --- /dev/null +++ b/ext/miniupnpc/testreplyparse/GetExternalIPAddress.namevalue @@ -0,0 +1,2 @@ +NewExternalIPAddress=1.2.3.4 + diff --git a/ext/miniupnpc/testreplyparse/GetExternalIPAddress.xml b/ext/miniupnpc/testreplyparse/GetExternalIPAddress.xml new file mode 100644 index 00000000..db7ec1f9 --- /dev/null +++ b/ext/miniupnpc/testreplyparse/GetExternalIPAddress.xml @@ -0,0 +1,2 @@ +1.2.3.4 + diff --git a/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue b/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue new file mode 100644 index 00000000..26b169c3 --- /dev/null +++ b/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue @@ -0,0 +1,3 @@ +NewProtocol=UDP +NewExternalPort=12345 +NewRemoteHost= diff --git a/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml b/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml new file mode 100644 index 00000000..bbb540ea --- /dev/null +++ b/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml @@ -0,0 +1,3 @@ + +12345UDP + diff --git a/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue b/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue new file mode 100644 index 00000000..2189789b --- /dev/null +++ b/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue @@ -0,0 +1,5 @@ +NewInternalPort=12345 +NewInternalClient=192.168.10.110 +NewEnabled=1 +NewPortMappingDescription=libminiupnpc +NewLeaseDuration=0 diff --git a/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml b/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml new file mode 100644 index 00000000..77e8d9c7 --- /dev/null +++ b/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml @@ -0,0 +1,2 @@ +12345192.168.10.1101libminiupnpc0 + diff --git a/ext/miniupnpc/testreplyparse/SetDefaultConnectionService.namevalue b/ext/miniupnpc/testreplyparse/SetDefaultConnectionService.namevalue new file mode 100644 index 00000000..f78c7e2a --- /dev/null +++ b/ext/miniupnpc/testreplyparse/SetDefaultConnectionService.namevalue @@ -0,0 +1 @@ +NewDefaultConnectionService=uuid:c6c05a33-f704-48df-9910-e099b3471d81:WANConnectionDevice:1,INVALID_SERVICE_ID diff --git a/ext/miniupnpc/testreplyparse/SetDefaultConnectionService.xml b/ext/miniupnpc/testreplyparse/SetDefaultConnectionService.xml new file mode 100644 index 00000000..ac04c07a --- /dev/null +++ b/ext/miniupnpc/testreplyparse/SetDefaultConnectionService.xml @@ -0,0 +1 @@ +uuid:c6c05a33-f704-48df-9910-e099b3471d81:WANConnectionDevice:1,INVALID_SERVICE_ID diff --git a/ext/miniupnpc/testreplyparse/readme.txt b/ext/miniupnpc/testreplyparse/readme.txt new file mode 100644 index 00000000..3eb1f015 --- /dev/null +++ b/ext/miniupnpc/testreplyparse/readme.txt @@ -0,0 +1,7 @@ +This directory contains files used for validation of upnpreplyparse.c code. + +Each .xml file to parse should give the results which are in the .namevalue +file. + +A .namevalue file contain name=value lines. + diff --git a/ext/miniupnpc/testupnpigd.py b/ext/miniupnpc/testupnpigd.py new file mode 100755 index 00000000..6d167a4c --- /dev/null +++ b/ext/miniupnpc/testupnpigd.py @@ -0,0 +1,84 @@ +#! /usr/bin/python +# $Id: testupnpigd.py,v 1.4 2008/10/11 10:27:20 nanard Exp $ +# MiniUPnP project +# Author : Thomas Bernard +# This Sample code is public domain. +# website : http://miniupnp.tuxfamily.org/ + +# import the python miniupnpc module +import miniupnpc +import socket +import BaseHTTPServer + +# function definition +def list_redirections(): + i = 0 + while True: + p = u.getgenericportmapping(i) + if p==None: + break + print i, p + i = i + 1 + +#define the handler class for HTTP connections +class handler_class(BaseHTTPServer.BaseHTTPRequestHandler): + def do_GET(self): + self.send_response(200) + self.end_headers() + self.wfile.write("OK MON GARS") + +# create the object +u = miniupnpc.UPnP() +#print 'inital(default) values :' +#print ' discoverdelay', u.discoverdelay +#print ' lanaddr', u.lanaddr +#print ' multicastif', u.multicastif +#print ' minissdpdsocket', u.minissdpdsocket +u.discoverdelay = 200; + +try: + print 'Discovering... delay=%ums' % u.discoverdelay + ndevices = u.discover() + print ndevices, 'device(s) detected' + + # select an igd + u.selectigd() + # display information about the IGD and the internet connection + print 'local ip address :', u.lanaddr + externalipaddress = u.externalipaddress() + print 'external ip address :', externalipaddress + print u.statusinfo(), u.connectiontype() + + #instanciate a HTTPd object. The port is assigned by the system. + httpd = BaseHTTPServer.HTTPServer((u.lanaddr, 0), handler_class) + eport = httpd.server_port + + # find a free port for the redirection + r = u.getspecificportmapping(eport, 'TCP') + while r != None and eport < 65536: + eport = eport + 1 + r = u.getspecificportmapping(eport, 'TCP') + + print 'trying to redirect %s port %u TCP => %s port %u TCP' % (externalipaddress, eport, u.lanaddr, httpd.server_port) + + b = u.addportmapping(eport, 'TCP', u.lanaddr, httpd.server_port, + 'UPnP IGD Tester port %u' % eport, '') + if b: + print 'Success. Now waiting for some HTTP request on http://%s:%u' % (externalipaddress ,eport) + try: + httpd.handle_request() + httpd.server_close() + except KeyboardInterrupt, details: + print "CTRL-C exception!", details + b = u.deleteportmapping(eport, 'TCP') + if b: + print 'Successfully deleted port mapping' + else: + print 'Failed to remove port mapping' + else: + print 'Failed' + + httpd.server_close() + +except Exception, e: + print 'Exception :', e diff --git a/ext/miniupnpc/testupnpreplyparse.c b/ext/miniupnpc/testupnpreplyparse.c new file mode 100644 index 00000000..7ba7131e --- /dev/null +++ b/ext/miniupnpc/testupnpreplyparse.c @@ -0,0 +1,96 @@ +/* $Id: testupnpreplyparse.c,v 1.4 2014/01/27 11:45:19 nanard Exp $ */ +/* MiniUPnP project + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * (c) 2006-2014 Thomas Bernard + * This software is subject to the conditions detailed + * in the LICENCE file provided within the distribution */ +#include +#include +#include +#include "upnpreplyparse.h" + +int +test_parsing(const char * buf, int len, FILE * f) +{ + char line[1024]; + struct NameValueParserData pdata; + int ok = 1; + ParseNameValue(buf, len, &pdata); + /* check result */ + if(f != NULL) + { + while(fgets(line, sizeof(line), f)) + { + char * value; + char * equal; + char * parsedvalue; + int l; + l = strlen(line); + while((l > 0) && ((line[l-1] == '\r') || (line[l-1] == '\n'))) + line[--l] = '\0'; + /* skip empty lines */ + if(l == 0) + continue; + equal = strchr(line, '='); + if(equal == NULL) + { + fprintf(stderr, "Warning, line does not contain '=' : %s\n", line); + continue; + } + *equal = '\0'; + value = equal + 1; + parsedvalue = GetValueFromNameValueList(&pdata, line); + if((parsedvalue == NULL) || (strcmp(parsedvalue, value) != 0)) + { + fprintf(stderr, "Element <%s> : expecting value '%s', got '%s'\n", + line, value, parsedvalue ? parsedvalue : ""); + ok = 0; + } + } + } + ClearNameValueList(&pdata); + return ok; +} + +int main(int argc, char * * argv) +{ + FILE * f; + char buffer[4096]; + int l; + int ok; + + if(argc<2) + { + fprintf(stderr, "Usage: %s file.xml [file.namevalues]\n", argv[0]); + return 1; + } + f = fopen(argv[1], "r"); + if(!f) + { + fprintf(stderr, "Error : can not open file %s\n", argv[1]); + return 2; + } + l = fread(buffer, 1, sizeof(buffer)-1, f); + fclose(f); + f = NULL; + buffer[l] = '\0'; + if(argc > 2) + { + f = fopen(argv[2], "r"); + if(!f) + { + fprintf(stderr, "Error : can not open file %s\n", argv[2]); + return 2; + } + } +#ifdef DEBUG + DisplayNameValueList(buffer, l); +#endif + ok = test_parsing(buffer, l, f); + if(f) + { + fclose(f); + } + return ok ? 0 : 3; +} + diff --git a/ext/miniupnpc/testupnpreplyparse.sh b/ext/miniupnpc/testupnpreplyparse.sh new file mode 100755 index 00000000..992930b7 --- /dev/null +++ b/ext/miniupnpc/testupnpreplyparse.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +for f in testreplyparse/*.xml ; do + bf="`dirname $f`/`basename $f .xml`" + if ./testupnpreplyparse $f $bf.namevalue ; then + echo "$f : passed" + else + echo "$f : FAILED" + exit 1 + fi +done + +exit 0 + diff --git a/ext/miniupnpc/updateminiupnpcstrings.sh b/ext/miniupnpc/updateminiupnpcstrings.sh new file mode 100755 index 00000000..dde4354a --- /dev/null +++ b/ext/miniupnpc/updateminiupnpcstrings.sh @@ -0,0 +1,53 @@ +#! /bin/sh +# $Id: updateminiupnpcstrings.sh,v 1.7 2011/01/04 11:41:53 nanard Exp $ +# project miniupnp : http://miniupnp.free.fr/ +# (c) 2009 Thomas Bernard + +FILE=miniupnpcstrings.h +TMPFILE=miniupnpcstrings.h.tmp +TEMPLATE_FILE=${FILE}.in + +# detecting the OS name and version +OS_NAME=`uname -s` +OS_VERSION=`uname -r` +if [ -f /etc/debian_version ]; then + OS_NAME=Debian + OS_VERSION=`cat /etc/debian_version` +fi +# use lsb_release (Linux Standard Base) when available +LSB_RELEASE=`which lsb_release` +if [ 0 -eq $? -a -x "${LSB_RELEASE}" ]; then + OS_NAME=`${LSB_RELEASE} -i -s` + OS_VERSION=`${LSB_RELEASE} -r -s` + case $OS_NAME in + Debian) + #OS_VERSION=`${LSB_RELEASE} -c -s` + ;; + Ubuntu) + #OS_VERSION=`${LSB_RELEASE} -c -s` + ;; + esac +fi + +# on AmigaOS 3, uname -r returns "unknown", so we use uname -v +if [ "$OS_NAME" = "AmigaOS" ]; then + if [ "$OS_VERSION" = "unknown" ]; then + OS_VERSION=`uname -v` + fi +fi + +echo "Detected OS [$OS_NAME] version [$OS_VERSION]" +MINIUPNPC_VERSION=`cat VERSION` +echo "MiniUPnPc version [${MINIUPNPC_VERSION}]" + +EXPR="s|OS_STRING \".*\"|OS_STRING \"${OS_NAME}/${OS_VERSION}\"|" +#echo $EXPR +test -f ${FILE}.in +echo "setting OS_STRING macro value to ${OS_NAME}/${OS_VERSION} in $FILE." +sed -e "$EXPR" < $TEMPLATE_FILE > $TMPFILE + +EXPR="s|MINIUPNPC_VERSION_STRING \".*\"|MINIUPNPC_VERSION_STRING \"${MINIUPNPC_VERSION}\"|" +echo "setting MINIUPNPC_VERSION_STRING macro value to ${MINIUPNPC_VERSION} in $FILE." +sed -e "$EXPR" < $TMPFILE > $FILE +rm $TMPFILE + diff --git a/ext/miniupnpc/upnpc.c b/ext/miniupnpc/upnpc.c new file mode 100644 index 00000000..8bc552ef --- /dev/null +++ b/ext/miniupnpc/upnpc.c @@ -0,0 +1,833 @@ +/* $Id: upnpc.c,v 1.112 2015/10/08 16:15:48 nanard Exp $ */ +/* Project : miniupnp + * Author : Thomas Bernard + * Copyright (c) 2005-2015 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. */ + +#include +#include +#include +#include +#ifdef _WIN32 +#include +#define snprintf _snprintf +#else +/* for IPPROTO_TCP / IPPROTO_UDP */ +#include +#endif +#include +#include "miniwget.h" +#include "miniupnpc.h" +#include "upnpcommands.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; + 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); + 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 { + 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; + int 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, "%d", 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("%02d - %s %s->%s:%s\tenabled=%s leaseDuration=%s\n" + " desc='%s' rHost='%s'\n", + i, protocol, extPort, intClient, intPort, + enabled, duration, + desc, rHost); + */ + printf("%2d %s %5s->%s:%-5s '%s' '%s' %s\n", + i, protocol, extPort, intClient, intPort, + desc, rHost, duration); + else + printf("GetGenericPortMappingEntry() returned %d (%s)\n", + r, strupnperror(r)); + i++; + } while(r==0); +} + +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, + "0", + "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, + "0", + "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 void SetRedirectAndTest(struct UPNPUrls * urls, + struct IGDdatas * data, + const char * iaddr, + const char * iport, + const char * eport, + const char * proto, + const char * leaseDuration, + 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; + } + proto = protofix(proto); + if(!proto) + { + fprintf(stderr, "invalid protocol\n"); + return; + } + + 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, 0, 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, 0, leaseDuration); + if(r!=UPNPCOMMAND_SUCCESS) + printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", + eport, iport, iaddr, r, strupnperror(r)); + } + + r = UPNP_GetSpecificPortMappingEntry(urls->controlURL, + data->first.servicetype, + eport, proto, NULL/*remoteHost*/, + intClient, intPort, NULL/*desc*/, + NULL/*enabled*/, duration); + if(r!=UPNPCOMMAND_SUCCESS) + printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n", + r, strupnperror(r)); + 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); + } +} + +static void +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; + } + proto = protofix(proto); + if(!proto) + { + fprintf(stderr, "protocol invalid\n"); + return; + } + r = UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, remoteHost); + printf("UPNP_DeletePortMapping() returned : %d\n", r); +} + +static void +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; + } + proto = protofix(proto); + if(!proto) + { + fprintf(stderr, "protocol invalid\n"); + return; + } + r = UPNP_DeletePortMappingRange(urls->controlURL, data->first.servicetype, ePortStart, ePortEnd, proto, manage); + printf("UPNP_DeletePortMappingRange() returned : %d\n", r); +} + +/* IGD:2, functions for service WANIPv6FirewallControl:1 */ +static void GetFirewallStatus(struct UPNPUrls * urls, struct IGDdatas * data) +{ + unsigned int bytessent, bytesreceived, packetsreceived, packetssent; + int firewallEnabled = 0, inboundPinholeAllowed = 0; + + UPNP_GetFirewallStatus(urls->controlURL_6FC, data->IPv6FC.servicetype, &firewallEnabled, &inboundPinholeAllowed); + printf("FirewallEnabled: %d & Inbound Pinhole Allowed: %d\n", firewallEnabled, inboundPinholeAllowed); + printf("GetFirewallStatus:\n Firewall Enabled: %s\n Inbound Pinhole Allowed: %s\n", (firewallEnabled)? "Yes":"No", (inboundPinholeAllowed)? "Yes":"No"); + + bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype); + bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype); + packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype); + packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype); + printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived); + printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived); +} + +/* Test function + * 1 - Add pinhole + * 2 - Check if pinhole is working from the IGD side */ +static void SetPinholeAndTest(struct UPNPUrls * urls, struct IGDdatas * data, + const char * remoteaddr, const char * eport, + const char * intaddr, const char * iport, + const char * proto, const char * lease_time) +{ + char uniqueID[8]; + /*int isWorking = 0;*/ + int r; + char proto_tmp[8]; + + if(!intaddr || !remoteaddr || !iport || !eport || !proto || !lease_time) + { + fprintf(stderr, "Wrong arguments\n"); + return; + } + if(atoi(proto) == 0) + { + const char * protocol; + protocol = protofix(proto); + if(protocol && (strcmp("TCP", protocol) == 0)) + { + snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_TCP); + proto = proto_tmp; + } + else if(protocol && (strcmp("UDP", protocol) == 0)) + { + snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_UDP); + proto = proto_tmp; + } + else + { + fprintf(stderr, "invalid protocol\n"); + return; + } + } + r = UPNP_AddPinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, lease_time, uniqueID); + if(r!=UPNPCOMMAND_SUCCESS) + printf("AddPinhole([%s]:%s -> [%s]:%s) failed with code %d (%s)\n", + remoteaddr, eport, intaddr, iport, r, strupnperror(r)); + else + { + printf("AddPinhole: ([%s]:%s -> [%s]:%s) / Pinhole ID = %s\n", + remoteaddr, eport, intaddr, iport, uniqueID); + /*r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->servicetype_6FC, uniqueID, &isWorking); + if(r!=UPNPCOMMAND_SUCCESS) + printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r)); + printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");*/ + } +} + +/* Test function + * 1 - Check if pinhole is working from the IGD side + * 2 - Update pinhole */ +static void GetPinholeAndUpdate(struct UPNPUrls * urls, struct IGDdatas * data, + const char * uniqueID, const char * lease_time) +{ + int isWorking = 0; + int r; + + if(!uniqueID || !lease_time) + { + fprintf(stderr, "Wrong arguments\n"); + return; + } + r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking); + printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No"); + if(r!=UPNPCOMMAND_SUCCESS) + printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r)); + if(isWorking || r==709) + { + r = UPNP_UpdatePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, lease_time); + printf("UpdatePinhole: Pinhole ID = %s with Lease Time: %s\n", uniqueID, lease_time); + if(r!=UPNPCOMMAND_SUCCESS) + printf("UpdatePinhole: ID (%s) failed with code %d (%s)\n", uniqueID, r, strupnperror(r)); + } +} + +/* Test function + * Get pinhole timeout + */ +static void GetPinholeOutboundTimeout(struct UPNPUrls * urls, struct IGDdatas * data, + const char * remoteaddr, const char * eport, + const char * intaddr, const char * iport, + const char * proto) +{ + int timeout = 0; + int r; + + if(!intaddr || !remoteaddr || !iport || !eport || !proto) + { + fprintf(stderr, "Wrong arguments\n"); + return; + } + + r = UPNP_GetOutboundPinholeTimeout(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, &timeout); + if(r!=UPNPCOMMAND_SUCCESS) + printf("GetOutboundPinholeTimeout([%s]:%s -> [%s]:%s) failed with code %d (%s)\n", + intaddr, iport, remoteaddr, eport, r, strupnperror(r)); + else + printf("GetOutboundPinholeTimeout: ([%s]:%s -> [%s]:%s) / Timeout = %d\n", intaddr, iport, remoteaddr, eport, timeout); +} + +static void +GetPinholePackets(struct UPNPUrls * urls, + struct IGDdatas * data, const char * uniqueID) +{ + int r, pinholePackets = 0; + if(!uniqueID) + { + fprintf(stderr, "invalid arguments\n"); + return; + } + r = UPNP_GetPinholePackets(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &pinholePackets); + if(r!=UPNPCOMMAND_SUCCESS) + printf("GetPinholePackets() failed with code %d (%s)\n", r, strupnperror(r)); + else + printf("GetPinholePackets: Pinhole ID = %s / PinholePackets = %d\n", uniqueID, pinholePackets); +} + +static void +CheckPinhole(struct UPNPUrls * urls, + struct IGDdatas * data, const char * uniqueID) +{ + int r, isWorking = 0; + if(!uniqueID) + { + fprintf(stderr, "invalid arguments\n"); + return; + } + r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking); + if(r!=UPNPCOMMAND_SUCCESS) + printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r)); + else + printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No"); +} + +static void +RemovePinhole(struct UPNPUrls * urls, + struct IGDdatas * data, const char * uniqueID) +{ + int r; + if(!uniqueID) + { + fprintf(stderr, "invalid arguments\n"); + return; + } + r = UPNP_DeletePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID); + printf("UPNP_DeletePinhole() returned : %d\n", r); +} + + +/* sample upnp client program */ +int main(int argc, char ** argv) +{ + char command = 0; + char ** commandargv = 0; + int commandargc = 0; + struct UPNPDev * devlist = 0; + char lanaddr[64]; /* my ip address on the LAN */ + int i; + const char * rootdescurl = 0; + const char * multicastif = 0; + const char * minissdpdpath = 0; + int localport = UPNP_LOCAL_PORT_ANY; + int retcode = 0; + int error = 0; + int ipv6 = 0; + 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-2015 Thomas Bernard.\n"); + printf("Go to http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/\n" + "for more information.\n"); + /* command line processing */ + for(i=1; i65535 || + (localport >1 && localport < 1024)) + { + fprintf(stderr, "Invalid localport '%s'\n", argv[i]); + localport = UPNP_LOCAL_PORT_ANY; + break; + } + } + else if(argv[i][1] == 'p') + minissdpdpath = argv[++i]; + else if(argv[i][1] == '6') + ipv6 = 1; + else if(argv[i][1] == 'e') + description = argv[++i]; + else if(argv[i][1] == 't') + ttl = (unsigned char)atoi(argv[++i]); + else + { + command = argv[i][1]; + i++; + commandargv = argv + i; + commandargc = argc - i; + break; + } + } + else + { + fprintf(stderr, "option '%s' invalid\n", argv[i]); + } + } + + if(!command + || (command == 'a' && commandargc<4) + || (command == 'd' && argc<2) + || (command == 'r' && argc<2) + || (command == 'A' && commandargc<6) + || (command == 'U' && commandargc<2) + || (command == 'D' && commandargc<1)) + { + fprintf(stderr, "Usage :\t%s [options] -a ip port external_port protocol [duration]\n\t\tAdd port redirection\n", argv[0]); + fprintf(stderr, " \t%s [options] -d external_port protocol \n\t\tDelete port redirection\n", argv[0]); + fprintf(stderr, " \t%s [options] -s\n\t\tGet Connection status\n", argv[0]); + fprintf(stderr, " \t%s [options] -l\n\t\tList redirections\n", argv[0]); + fprintf(stderr, " \t%s [options] -L\n\t\tList redirections (using GetListOfPortMappings (for IGD:2 only)\n", argv[0]); + fprintf(stderr, " \t%s [options] -n ip port external_port protocol [duration]\n\t\tAdd (any) port redirection allowing IGD to use alternative external_port (for IGD:2 only)\n", argv[0]); + fprintf(stderr, " \t%s [options] -N external_port_start external_port_end protocol [manage]\n\t\tDelete range of port redirections (for IGD:2 only)\n", argv[0]); + fprintf(stderr, " \t%s [options] -r port1 [external_port1] protocol1 [port2 [external_port2] protocol2] [...]\n\t\tAdd all redirections to the current host\n", argv[0]); + fprintf(stderr, " \t%s [options] -A remote_ip remote_port internal_ip internal_port protocol lease_time\n\t\tAdd Pinhole (for IGD:2 only)\n", argv[0]); + fprintf(stderr, " \t%s [options] -U uniqueID new_lease_time\n\t\tUpdate Pinhole (for IGD:2 only)\n", argv[0]); + fprintf(stderr, " \t%s [options] -C uniqueID\n\t\tCheck if Pinhole is Working (for IGD:2 only)\n", argv[0]); + fprintf(stderr, " \t%s [options] -K uniqueID\n\t\tGet Number of packets going through the rule (for IGD:2 only)\n", argv[0]); + fprintf(stderr, " \t%s [options] -D uniqueID\n\t\tDelete Pinhole (for IGD:2 only)\n", argv[0]); + fprintf(stderr, " \t%s [options] -S\n\t\tGet Firewall status (for IGD:2 only)\n", argv[0]); + fprintf(stderr, " \t%s [options] -G remote_ip remote_port internal_ip internal_port protocol\n\t\tGet Outbound Pinhole Timeout (for IGD:2 only)\n", argv[0]); + fprintf(stderr, " \t%s [options] -P\n\t\tGet Presentation url\n", argv[0]); + fprintf(stderr, "\nprotocol is UDP or TCP\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -e description : set description for port mapping.\n"); + fprintf(stderr, " -6 : use ip v6 instead of ip v4.\n"); + fprintf(stderr, " -u url : bypass discovery process by providing the XML root description url.\n"); + fprintf(stderr, " -m address/interface : provide ip address (ip v4) or interface name (ip v4 or v6) to use for sending SSDP multicast packets.\n"); + fprintf(stderr, " -z localport : SSDP packets local (source) port (1024-65535).\n"); + fprintf(stderr, " -p path : use this path for MiniSSDPd socket.\n"); + fprintf(stderr, " -t ttl : set multicast TTL. Default value is 2.\n"); + return 1; + } + + if( rootdescurl + || (devlist = upnpDiscover(2000, multicastif, minissdpdpath, + localport, ipv6, ttl, &error))) + { + struct UPNPDev * device; + struct UPNPUrls urls; + struct IGDdatas data; + if(devlist) + { + printf("List of UPNP devices found on the network :\n"); + for(device = devlist; device; device = device->pNext) + { + printf(" desc: %s\n st: %s\n\n", + device->descURL, device->st); + } + } + else if(!rootdescurl) + { + printf("upnpDiscover() error code=%d\n", error); + } + i = 1; + if( (rootdescurl && UPNP_GetIGDFromUrl(rootdescurl, &urls, &data, lanaddr, sizeof(lanaddr))) + || (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)))) + { + switch(i) { + case 1: + printf("Found valid IGD : %s\n", urls.controlURL); + break; + case 2: + printf("Found a (not connected?) IGD : %s\n", urls.controlURL); + printf("Trying to continue anyway\n"); + break; + case 3: + printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL); + printf("Trying to continue anyway\n"); + break; + default: + printf("Found device (igd ?) : %s\n", urls.controlURL); + printf("Trying to continue anyway\n"); + } + 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 + + switch(command) + { + case 'l': + DisplayInfos(&urls, &data); + ListRedirections(&urls, &data); + break; + case 'L': + NewListRedirections(&urls, &data); + break; + case 'a': + SetRedirectAndTest(&urls, &data, + commandargv[0], commandargv[1], + commandargv[2], commandargv[3], + (commandargc > 4)?commandargv[4]:"0", + description, 0); + break; + case 'd': + RemoveRedirect(&urls, &data, commandargv[0], commandargv[1], + commandargc > 2 ? commandargv[2] : NULL); + break; + case 'n': /* aNy */ + SetRedirectAndTest(&urls, &data, + commandargv[0], commandargv[1], + commandargv[2], commandargv[3], + (commandargc > 4)?commandargv[4]:"0", + description, 1); + break; + case 'N': + if (commandargc < 3) + fprintf(stderr, "too few arguments\n"); + + RemoveRedirectRange(&urls, &data, commandargv[0], commandargv[1], commandargv[2], + commandargc > 3 ? commandargv[3] : NULL); + break; + case 's': + GetConnectionStatus(&urls, &data); + break; + case 'r': + i = 0; + while(i */ + SetRedirectAndTest(&urls, &data, + lanaddr, commandargv[i], + commandargv[i+1], commandargv[i+2], "0", + description, 0); + i+=3; /* 3 parameters parsed */ + } else { + /* 2nd parameter not an integer : */ + SetRedirectAndTest(&urls, &data, + lanaddr, commandargv[i], + commandargv[i], commandargv[i+1], "0", + description, 0); + i+=2; /* 2 parameters parsed */ + } + } + break; + case 'A': + SetPinholeAndTest(&urls, &data, + commandargv[0], commandargv[1], + commandargv[2], commandargv[3], + commandargv[4], commandargv[5]); + break; + case 'U': + GetPinholeAndUpdate(&urls, &data, + commandargv[0], commandargv[1]); + break; + case 'C': + for(i=0; i +#include +#include +#include "upnpcommands.h" +#include "miniupnpc.h" +#include "portlistingparse.h" + +static UNSIGNED_INTEGER +my_atoui(const char * s) +{ + return s ? ((UNSIGNED_INTEGER)STRTOUI(s, NULL, 0)) : 0; +} + +/* + * */ +MINIUPNP_LIBSPEC UNSIGNED_INTEGER +UPNP_GetTotalBytesSent(const char * controlURL, + const char * servicetype) +{ + struct NameValueParserData pdata; + char * buffer; + int bufsize; + unsigned int r = 0; + char * p; + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetTotalBytesSent", 0, &bufsize))) { + return UPNPCOMMAND_HTTP_ERROR; + } + ParseNameValue(buffer, bufsize, &pdata); + /*DisplayNameValueList(buffer, bufsize);*/ + free(buffer); buffer = NULL; + p = GetValueFromNameValueList(&pdata, "NewTotalBytesSent"); + r = my_atoui(p); + ClearNameValueList(&pdata); + return r; +} + +/* + * */ +MINIUPNP_LIBSPEC UNSIGNED_INTEGER +UPNP_GetTotalBytesReceived(const char * controlURL, + const char * servicetype) +{ + struct NameValueParserData pdata; + char * buffer; + int bufsize; + unsigned int r = 0; + char * p; + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetTotalBytesReceived", 0, &bufsize))) { + return UPNPCOMMAND_HTTP_ERROR; + } + ParseNameValue(buffer, bufsize, &pdata); + /*DisplayNameValueList(buffer, bufsize);*/ + free(buffer); buffer = NULL; + p = GetValueFromNameValueList(&pdata, "NewTotalBytesReceived"); + r = my_atoui(p); + ClearNameValueList(&pdata); + return r; +} + +/* + * */ +MINIUPNP_LIBSPEC UNSIGNED_INTEGER +UPNP_GetTotalPacketsSent(const char * controlURL, + const char * servicetype) +{ + struct NameValueParserData pdata; + char * buffer; + int bufsize; + unsigned int r = 0; + char * p; + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetTotalPacketsSent", 0, &bufsize))) { + return UPNPCOMMAND_HTTP_ERROR; + } + ParseNameValue(buffer, bufsize, &pdata); + /*DisplayNameValueList(buffer, bufsize);*/ + free(buffer); buffer = NULL; + p = GetValueFromNameValueList(&pdata, "NewTotalPacketsSent"); + r = my_atoui(p); + ClearNameValueList(&pdata); + return r; +} + +/* + * */ +MINIUPNP_LIBSPEC UNSIGNED_INTEGER +UPNP_GetTotalPacketsReceived(const char * controlURL, + const char * servicetype) +{ + struct NameValueParserData pdata; + char * buffer; + int bufsize; + unsigned int r = 0; + char * p; + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetTotalPacketsReceived", 0, &bufsize))) { + return UPNPCOMMAND_HTTP_ERROR; + } + ParseNameValue(buffer, bufsize, &pdata); + /*DisplayNameValueList(buffer, bufsize);*/ + free(buffer); buffer = NULL; + p = GetValueFromNameValueList(&pdata, "NewTotalPacketsReceived"); + r = my_atoui(p); + ClearNameValueList(&pdata); + return r; +} + +/* UPNP_GetStatusInfo() call the corresponding UPNP method + * returns the current status and uptime */ +MINIUPNP_LIBSPEC int +UPNP_GetStatusInfo(const char * controlURL, + const char * servicetype, + char * status, + unsigned int * uptime, + char * lastconnerror) +{ + struct NameValueParserData pdata; + char * buffer; + int bufsize; + char * p; + char * up; + char * err; + int ret = UPNPCOMMAND_UNKNOWN_ERROR; + + if(!status && !uptime) + return UPNPCOMMAND_INVALID_ARGS; + + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetStatusInfo", 0, &bufsize))) { + return UPNPCOMMAND_HTTP_ERROR; + } + ParseNameValue(buffer, bufsize, &pdata); + /*DisplayNameValueList(buffer, bufsize);*/ + free(buffer); buffer = NULL; + up = GetValueFromNameValueList(&pdata, "NewUptime"); + p = GetValueFromNameValueList(&pdata, "NewConnectionStatus"); + err = GetValueFromNameValueList(&pdata, "NewLastConnectionError"); + if(p && up) + ret = UPNPCOMMAND_SUCCESS; + + if(status) { + if(p){ + strncpy(status, p, 64 ); + status[63] = '\0'; + }else + status[0]= '\0'; + } + + if(uptime) { + if(up) + sscanf(up,"%u",uptime); + else + *uptime = 0; + } + + if(lastconnerror) { + if(err) { + strncpy(lastconnerror, err, 64 ); + lastconnerror[63] = '\0'; + } else + lastconnerror[0] = '\0'; + } + + p = GetValueFromNameValueList(&pdata, "errorCode"); + if(p) { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(p, "%d", &ret); + } + ClearNameValueList(&pdata); + return ret; +} + +/* UPNP_GetConnectionTypeInfo() call the corresponding UPNP method + * returns the connection type */ +MINIUPNP_LIBSPEC int +UPNP_GetConnectionTypeInfo(const char * controlURL, + const char * servicetype, + char * connectionType) +{ + struct NameValueParserData pdata; + char * buffer; + int bufsize; + char * p; + int ret = UPNPCOMMAND_UNKNOWN_ERROR; + + if(!connectionType) + return UPNPCOMMAND_INVALID_ARGS; + + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetConnectionTypeInfo", 0, &bufsize))) { + return UPNPCOMMAND_HTTP_ERROR; + } + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + p = GetValueFromNameValueList(&pdata, "NewConnectionType"); + /*p = GetValueFromNameValueList(&pdata, "NewPossibleConnectionTypes");*/ + /* PossibleConnectionTypes will have several values.... */ + if(p) { + strncpy(connectionType, p, 64 ); + connectionType[63] = '\0'; + ret = UPNPCOMMAND_SUCCESS; + } else + connectionType[0] = '\0'; + p = GetValueFromNameValueList(&pdata, "errorCode"); + if(p) { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(p, "%d", &ret); + } + ClearNameValueList(&pdata); + return ret; +} + +/* UPNP_GetLinkLayerMaxBitRate() call the corresponding UPNP method. + * Returns 2 values: Downloadlink bandwidth and Uplink bandwidth. + * One of the values can be null + * Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only + * We can use the GetCommonLinkProperties from WANCommonInterfaceConfig:1 */ +MINIUPNP_LIBSPEC int +UPNP_GetLinkLayerMaxBitRates(const char * controlURL, + const char * servicetype, + unsigned int * bitrateDown, + unsigned int * bitrateUp) +{ + struct NameValueParserData pdata; + char * buffer; + int bufsize; + int ret = UPNPCOMMAND_UNKNOWN_ERROR; + char * down; + char * up; + char * p; + + if(!bitrateDown && !bitrateUp) + return UPNPCOMMAND_INVALID_ARGS; + + /* shouldn't we use GetCommonLinkProperties ? */ + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetCommonLinkProperties", 0, &bufsize))) { + /*"GetLinkLayerMaxBitRates", 0, &bufsize);*/ + return UPNPCOMMAND_HTTP_ERROR; + } + /*DisplayNameValueList(buffer, bufsize);*/ + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + /*down = GetValueFromNameValueList(&pdata, "NewDownstreamMaxBitRate");*/ + /*up = GetValueFromNameValueList(&pdata, "NewUpstreamMaxBitRate");*/ + down = GetValueFromNameValueList(&pdata, "NewLayer1DownstreamMaxBitRate"); + up = GetValueFromNameValueList(&pdata, "NewLayer1UpstreamMaxBitRate"); + /*GetValueFromNameValueList(&pdata, "NewWANAccessType");*/ + /*GetValueFromNameValueList(&pdata, "NewPhysicalLinkStatus");*/ + if(down && up) + ret = UPNPCOMMAND_SUCCESS; + + if(bitrateDown) { + if(down) + sscanf(down,"%u",bitrateDown); + else + *bitrateDown = 0; + } + + if(bitrateUp) { + if(up) + sscanf(up,"%u",bitrateUp); + else + *bitrateUp = 0; + } + p = GetValueFromNameValueList(&pdata, "errorCode"); + if(p) { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(p, "%d", &ret); + } + ClearNameValueList(&pdata); + return ret; +} + + +/* 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. + * + * 402 Invalid Args - See UPnP Device Architecture section on Control. + * 501 Action Failed - See UPnP Device Architecture section on Control. + */ +MINIUPNP_LIBSPEC int +UPNP_GetExternalIPAddress(const char * controlURL, + const char * servicetype, + char * extIpAdd) +{ + struct NameValueParserData pdata; + char * buffer; + int bufsize; + char * p; + int ret = UPNPCOMMAND_UNKNOWN_ERROR; + + if(!extIpAdd || !controlURL || !servicetype) + return UPNPCOMMAND_INVALID_ARGS; + + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetExternalIPAddress", 0, &bufsize))) { + return UPNPCOMMAND_HTTP_ERROR; + } + /*DisplayNameValueList(buffer, bufsize);*/ + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + /*printf("external ip = %s\n", GetValueFromNameValueList(&pdata, "NewExternalIPAddress") );*/ + p = GetValueFromNameValueList(&pdata, "NewExternalIPAddress"); + if(p) { + strncpy(extIpAdd, p, 16 ); + extIpAdd[15] = '\0'; + ret = UPNPCOMMAND_SUCCESS; + } else + extIpAdd[0] = '\0'; + + p = GetValueFromNameValueList(&pdata, "errorCode"); + if(p) { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(p, "%d", &ret); + } + + ClearNameValueList(&pdata); + return ret; +} + +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) +{ + struct UPNParg * AddPortMappingArgs; + char * buffer; + int bufsize; + struct NameValueParserData pdata; + const char * resVal; + int ret; + + if(!inPort || !inClient || !proto || !extPort) + return UPNPCOMMAND_INVALID_ARGS; + + AddPortMappingArgs = calloc(9, sizeof(struct UPNParg)); + if(AddPortMappingArgs == NULL) + return UPNPCOMMAND_MEM_ALLOC_ERROR; + AddPortMappingArgs[0].elt = "NewRemoteHost"; + AddPortMappingArgs[0].val = remoteHost; + AddPortMappingArgs[1].elt = "NewExternalPort"; + AddPortMappingArgs[1].val = extPort; + AddPortMappingArgs[2].elt = "NewProtocol"; + AddPortMappingArgs[2].val = proto; + AddPortMappingArgs[3].elt = "NewInternalPort"; + AddPortMappingArgs[3].val = inPort; + AddPortMappingArgs[4].elt = "NewInternalClient"; + AddPortMappingArgs[4].val = inClient; + AddPortMappingArgs[5].elt = "NewEnabled"; + AddPortMappingArgs[5].val = "1"; + AddPortMappingArgs[6].elt = "NewPortMappingDescription"; + AddPortMappingArgs[6].val = desc?desc:"libminiupnpc"; + AddPortMappingArgs[7].elt = "NewLeaseDuration"; + AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0"; + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "AddPortMapping", AddPortMappingArgs, + &bufsize))) { + free(AddPortMappingArgs); + return UPNPCOMMAND_HTTP_ERROR; + } + /*DisplayNameValueList(buffer, bufsize);*/ + /*buffer[bufsize] = '\0';*/ + /*puts(buffer);*/ + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + resVal = GetValueFromNameValueList(&pdata, "errorCode"); + if(resVal) { + /*printf("AddPortMapping errorCode = '%s'\n", resVal); */ + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(resVal, "%d", &ret); + } else { + ret = UPNPCOMMAND_SUCCESS; + } + ClearNameValueList(&pdata); + free(AddPortMappingArgs); + return ret; +} + +MINIUPNP_LIBSPEC int +UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype, + const char * extPort, + const char * inPort, + const char * inClient, + const char * desc, + const char * proto, + const char * remoteHost, + const char * leaseDuration, + char * reservedPort) +{ + struct UPNParg * AddPortMappingArgs; + char * buffer; + int bufsize; + struct NameValueParserData pdata; + const char * resVal; + int ret; + + if(!inPort || !inClient || !proto || !extPort) + return UPNPCOMMAND_INVALID_ARGS; + + AddPortMappingArgs = calloc(9, sizeof(struct UPNParg)); + if(AddPortMappingArgs == NULL) + return UPNPCOMMAND_MEM_ALLOC_ERROR; + AddPortMappingArgs[0].elt = "NewRemoteHost"; + AddPortMappingArgs[0].val = remoteHost; + AddPortMappingArgs[1].elt = "NewExternalPort"; + AddPortMappingArgs[1].val = extPort; + AddPortMappingArgs[2].elt = "NewProtocol"; + AddPortMappingArgs[2].val = proto; + AddPortMappingArgs[3].elt = "NewInternalPort"; + AddPortMappingArgs[3].val = inPort; + AddPortMappingArgs[4].elt = "NewInternalClient"; + AddPortMappingArgs[4].val = inClient; + AddPortMappingArgs[5].elt = "NewEnabled"; + AddPortMappingArgs[5].val = "1"; + AddPortMappingArgs[6].elt = "NewPortMappingDescription"; + AddPortMappingArgs[6].val = desc?desc:"libminiupnpc"; + AddPortMappingArgs[7].elt = "NewLeaseDuration"; + AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0"; + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "AddAnyPortMapping", AddPortMappingArgs, + &bufsize))) { + free(AddPortMappingArgs); + return UPNPCOMMAND_HTTP_ERROR; + } + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + resVal = GetValueFromNameValueList(&pdata, "errorCode"); + if(resVal) { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(resVal, "%d", &ret); + } else { + char *p; + + p = GetValueFromNameValueList(&pdata, "NewReservedPort"); + if(p) { + strncpy(reservedPort, p, 6); + reservedPort[5] = '\0'; + ret = UPNPCOMMAND_SUCCESS; + } else { + ret = UPNPCOMMAND_INVALID_RESPONSE; + } + } + ClearNameValueList(&pdata); + free(AddPortMappingArgs); + return ret; +} + +MINIUPNP_LIBSPEC int +UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, + const char * extPort, const char * proto, + const char * remoteHost) +{ + /*struct NameValueParserData pdata;*/ + struct UPNParg * DeletePortMappingArgs; + char * buffer; + int bufsize; + struct NameValueParserData pdata; + const char * resVal; + int ret; + + if(!extPort || !proto) + return UPNPCOMMAND_INVALID_ARGS; + + DeletePortMappingArgs = calloc(4, sizeof(struct UPNParg)); + if(DeletePortMappingArgs == NULL) + return UPNPCOMMAND_MEM_ALLOC_ERROR; + DeletePortMappingArgs[0].elt = "NewRemoteHost"; + DeletePortMappingArgs[0].val = remoteHost; + DeletePortMappingArgs[1].elt = "NewExternalPort"; + DeletePortMappingArgs[1].val = extPort; + DeletePortMappingArgs[2].elt = "NewProtocol"; + DeletePortMappingArgs[2].val = proto; + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "DeletePortMapping", + DeletePortMappingArgs, &bufsize))) { + free(DeletePortMappingArgs); + return UPNPCOMMAND_HTTP_ERROR; + } + /*DisplayNameValueList(buffer, bufsize);*/ + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + resVal = GetValueFromNameValueList(&pdata, "errorCode"); + if(resVal) { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(resVal, "%d", &ret); + } else { + ret = UPNPCOMMAND_SUCCESS; + } + ClearNameValueList(&pdata); + free(DeletePortMappingArgs); + return ret; +} + +MINIUPNP_LIBSPEC int +UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype, + const char * extPortStart, const char * extPortEnd, + const char * proto, + const char * manage) +{ + struct UPNParg * DeletePortMappingArgs; + char * buffer; + int bufsize; + struct NameValueParserData pdata; + const char * resVal; + int ret; + + if(!extPortStart || !extPortEnd || !proto || !manage) + return UPNPCOMMAND_INVALID_ARGS; + + DeletePortMappingArgs = calloc(5, sizeof(struct UPNParg)); + if(DeletePortMappingArgs == NULL) + return UPNPCOMMAND_MEM_ALLOC_ERROR; + DeletePortMappingArgs[0].elt = "NewStartPort"; + DeletePortMappingArgs[0].val = extPortStart; + DeletePortMappingArgs[1].elt = "NewEndPort"; + DeletePortMappingArgs[1].val = extPortEnd; + DeletePortMappingArgs[2].elt = "NewProtocol"; + DeletePortMappingArgs[2].val = proto; + DeletePortMappingArgs[3].elt = "NewManage"; + DeletePortMappingArgs[3].val = manage; + + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "DeletePortMappingRange", + DeletePortMappingArgs, &bufsize))) { + free(DeletePortMappingArgs); + return UPNPCOMMAND_HTTP_ERROR; + } + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + resVal = GetValueFromNameValueList(&pdata, "errorCode"); + if(resVal) { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(resVal, "%d", &ret); + } else { + ret = UPNPCOMMAND_SUCCESS; + } + ClearNameValueList(&pdata); + free(DeletePortMappingArgs); + return ret; +} + +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) +{ + struct NameValueParserData pdata; + struct UPNParg * GetPortMappingArgs; + char * buffer; + int bufsize; + char * p; + int r = UPNPCOMMAND_UNKNOWN_ERROR; + if(!index) + return UPNPCOMMAND_INVALID_ARGS; + intClient[0] = '\0'; + intPort[0] = '\0'; + GetPortMappingArgs = calloc(2, sizeof(struct UPNParg)); + if(GetPortMappingArgs == NULL) + return UPNPCOMMAND_MEM_ALLOC_ERROR; + GetPortMappingArgs[0].elt = "NewPortMappingIndex"; + GetPortMappingArgs[0].val = index; + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetGenericPortMappingEntry", + GetPortMappingArgs, &bufsize))) { + free(GetPortMappingArgs); + return UPNPCOMMAND_HTTP_ERROR; + } + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + + p = GetValueFromNameValueList(&pdata, "NewRemoteHost"); + if(p && rHost) + { + strncpy(rHost, p, 64); + rHost[63] = '\0'; + } + p = GetValueFromNameValueList(&pdata, "NewExternalPort"); + if(p && extPort) + { + strncpy(extPort, p, 6); + extPort[5] = '\0'; + r = UPNPCOMMAND_SUCCESS; + } + p = GetValueFromNameValueList(&pdata, "NewProtocol"); + if(p && protocol) + { + strncpy(protocol, p, 4); + protocol[3] = '\0'; + } + p = GetValueFromNameValueList(&pdata, "NewInternalClient"); + if(p && intClient) + { + strncpy(intClient, p, 16); + intClient[15] = '\0'; + r = 0; + } + p = GetValueFromNameValueList(&pdata, "NewInternalPort"); + if(p && intPort) + { + strncpy(intPort, p, 6); + intPort[5] = '\0'; + } + p = GetValueFromNameValueList(&pdata, "NewEnabled"); + if(p && enabled) + { + strncpy(enabled, p, 4); + enabled[3] = '\0'; + } + p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription"); + if(p && desc) + { + strncpy(desc, p, 80); + desc[79] = '\0'; + } + p = GetValueFromNameValueList(&pdata, "NewLeaseDuration"); + if(p && duration) + { + strncpy(duration, p, 16); + duration[15] = '\0'; + } + p = GetValueFromNameValueList(&pdata, "errorCode"); + if(p) { + r = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(p, "%d", &r); + } + ClearNameValueList(&pdata); + free(GetPortMappingArgs); + return r; +} + +MINIUPNP_LIBSPEC int +UPNP_GetPortMappingNumberOfEntries(const char * controlURL, + const char * servicetype, + unsigned int * numEntries) +{ + struct NameValueParserData pdata; + char * buffer; + int bufsize; + char* p; + int ret = UPNPCOMMAND_UNKNOWN_ERROR; + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetPortMappingNumberOfEntries", 0, + &bufsize))) { + return UPNPCOMMAND_HTTP_ERROR; + } +#ifdef DEBUG + DisplayNameValueList(buffer, bufsize); +#endif + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + + p = GetValueFromNameValueList(&pdata, "NewPortMappingNumberOfEntries"); + if(numEntries && p) { + *numEntries = 0; + sscanf(p, "%u", numEntries); + ret = UPNPCOMMAND_SUCCESS; + } + + p = GetValueFromNameValueList(&pdata, "errorCode"); + if(p) { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(p, "%d", &ret); + } + + ClearNameValueList(&pdata); + return ret; +} + +/* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping + * the result is returned in the intClient and intPort strings + * please provide 16 and 6 bytes of data */ +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) +{ + struct NameValueParserData pdata; + struct UPNParg * GetPortMappingArgs; + char * buffer; + int bufsize; + char * p; + int ret = UPNPCOMMAND_UNKNOWN_ERROR; + + if(!intPort || !intClient || !extPort || !proto) + return UPNPCOMMAND_INVALID_ARGS; + + GetPortMappingArgs = calloc(4, sizeof(struct UPNParg)); + if(GetPortMappingArgs == NULL) + return UPNPCOMMAND_MEM_ALLOC_ERROR; + GetPortMappingArgs[0].elt = "NewRemoteHost"; + GetPortMappingArgs[0].val = remoteHost; + GetPortMappingArgs[1].elt = "NewExternalPort"; + GetPortMappingArgs[1].val = extPort; + GetPortMappingArgs[2].elt = "NewProtocol"; + GetPortMappingArgs[2].val = proto; + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetSpecificPortMappingEntry", + GetPortMappingArgs, &bufsize))) { + free(GetPortMappingArgs); + return UPNPCOMMAND_HTTP_ERROR; + } + /*DisplayNameValueList(buffer, bufsize);*/ + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + + p = GetValueFromNameValueList(&pdata, "NewInternalClient"); + if(p) { + strncpy(intClient, p, 16); + intClient[15] = '\0'; + ret = UPNPCOMMAND_SUCCESS; + } else + intClient[0] = '\0'; + + p = GetValueFromNameValueList(&pdata, "NewInternalPort"); + if(p) { + strncpy(intPort, p, 6); + intPort[5] = '\0'; + } else + intPort[0] = '\0'; + + p = GetValueFromNameValueList(&pdata, "NewEnabled"); + if(p && enabled) { + strncpy(enabled, p, 4); + enabled[3] = '\0'; + } + + p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription"); + if(p && desc) { + strncpy(desc, p, 80); + desc[79] = '\0'; + } + + p = GetValueFromNameValueList(&pdata, "NewLeaseDuration"); + if(p && leaseDuration) + { + strncpy(leaseDuration, p, 16); + leaseDuration[15] = '\0'; + } + + p = GetValueFromNameValueList(&pdata, "errorCode"); + if(p) { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(p, "%d", &ret); + } + + ClearNameValueList(&pdata); + free(GetPortMappingArgs); + return ret; +} + +/* UPNP_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. + */ +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) +{ + struct NameValueParserData pdata; + struct UPNParg * GetListOfPortMappingsArgs; + const char * p; + char * buffer; + int bufsize; + int ret = UPNPCOMMAND_UNKNOWN_ERROR; + + if(!startPort || !endPort || !protocol) + return UPNPCOMMAND_INVALID_ARGS; + + GetListOfPortMappingsArgs = calloc(6, sizeof(struct UPNParg)); + if(GetListOfPortMappingsArgs == NULL) + return UPNPCOMMAND_MEM_ALLOC_ERROR; + GetListOfPortMappingsArgs[0].elt = "NewStartPort"; + GetListOfPortMappingsArgs[0].val = startPort; + GetListOfPortMappingsArgs[1].elt = "NewEndPort"; + GetListOfPortMappingsArgs[1].val = endPort; + GetListOfPortMappingsArgs[2].elt = "NewProtocol"; + GetListOfPortMappingsArgs[2].val = protocol; + GetListOfPortMappingsArgs[3].elt = "NewManage"; + GetListOfPortMappingsArgs[3].val = "1"; + GetListOfPortMappingsArgs[4].elt = "NewNumberOfPorts"; + GetListOfPortMappingsArgs[4].val = numberOfPorts?numberOfPorts:"1000"; + + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetListOfPortMappings", + GetListOfPortMappingsArgs, &bufsize))) { + free(GetListOfPortMappingsArgs); + return UPNPCOMMAND_HTTP_ERROR; + } + free(GetListOfPortMappingsArgs); + + /*DisplayNameValueList(buffer, bufsize);*/ + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + + /*p = GetValueFromNameValueList(&pdata, "NewPortListing");*/ + /*if(p) { + printf("NewPortListing : %s\n", p); + }*/ + /*printf("NewPortListing(%d chars) : %s\n", + pdata.portListingLength, pdata.portListing);*/ + if(pdata.portListing) + { + /*struct PortMapping * pm; + int i = 0;*/ + ParsePortListing(pdata.portListing, pdata.portListingLength, + data); + ret = UPNPCOMMAND_SUCCESS; + /* + for(pm = data->head.lh_first; pm != NULL; pm = pm->entries.le_next) + { + printf("%2d %s %5hu->%s:%-5hu '%s' '%s'\n", + i, pm->protocol, pm->externalPort, pm->internalClient, + pm->internalPort, + pm->description, pm->remoteHost); + i++; + } + */ + /*FreePortListing(&data);*/ + } + + p = GetValueFromNameValueList(&pdata, "errorCode"); + if(p) { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(p, "%d", &ret); + } + ClearNameValueList(&pdata); + + /*printf("%.*s", bufsize, buffer);*/ + + return ret; +} + +/* IGD:2, functions for service WANIPv6FirewallControl:1 */ +MINIUPNP_LIBSPEC int +UPNP_GetFirewallStatus(const char * controlURL, + const char * servicetype, + int * firewallEnabled, + int * inboundPinholeAllowed) +{ + struct NameValueParserData pdata; + char * buffer; + int bufsize; + char * fe, *ipa, *p; + int ret = UPNPCOMMAND_UNKNOWN_ERROR; + + if(!firewallEnabled || !inboundPinholeAllowed) + return UPNPCOMMAND_INVALID_ARGS; + + buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetFirewallStatus", 0, &bufsize); + if(!buffer) { + return UPNPCOMMAND_HTTP_ERROR; + } + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + fe = GetValueFromNameValueList(&pdata, "FirewallEnabled"); + ipa = GetValueFromNameValueList(&pdata, "InboundPinholeAllowed"); + if(ipa && fe) + ret = UPNPCOMMAND_SUCCESS; + if(fe) + *firewallEnabled = my_atoui(fe); + /*else + *firewallEnabled = 0;*/ + if(ipa) + *inboundPinholeAllowed = my_atoui(ipa); + /*else + *inboundPinholeAllowed = 0;*/ + p = GetValueFromNameValueList(&pdata, "errorCode"); + if(p) + { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(p, "%d", &ret); + } + ClearNameValueList(&pdata); + return ret; +} + +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) +{ + struct UPNParg * GetOutboundPinholeTimeoutArgs; + char * buffer; + int bufsize; + struct NameValueParserData pdata; + const char * resVal; + char * p; + int ret; + + if(!intPort || !intClient || !proto || !remotePort || !remoteHost) + return UPNPCOMMAND_INVALID_ARGS; + + GetOutboundPinholeTimeoutArgs = calloc(6, sizeof(struct UPNParg)); + if(GetOutboundPinholeTimeoutArgs == NULL) + return UPNPCOMMAND_MEM_ALLOC_ERROR; + GetOutboundPinholeTimeoutArgs[0].elt = "RemoteHost"; + GetOutboundPinholeTimeoutArgs[0].val = remoteHost; + GetOutboundPinholeTimeoutArgs[1].elt = "RemotePort"; + GetOutboundPinholeTimeoutArgs[1].val = remotePort; + GetOutboundPinholeTimeoutArgs[2].elt = "Protocol"; + GetOutboundPinholeTimeoutArgs[2].val = proto; + GetOutboundPinholeTimeoutArgs[3].elt = "InternalPort"; + GetOutboundPinholeTimeoutArgs[3].val = intPort; + GetOutboundPinholeTimeoutArgs[4].elt = "InternalClient"; + GetOutboundPinholeTimeoutArgs[4].val = intClient; + buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetOutboundPinholeTimeout", GetOutboundPinholeTimeoutArgs, &bufsize); + if(!buffer) + return UPNPCOMMAND_HTTP_ERROR; + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + resVal = GetValueFromNameValueList(&pdata, "errorCode"); + if(resVal) + { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(resVal, "%d", &ret); + } + else + { + ret = UPNPCOMMAND_SUCCESS; + p = GetValueFromNameValueList(&pdata, "OutboundPinholeTimeout"); + if(p) + *opTimeout = my_atoui(p); + } + ClearNameValueList(&pdata); + free(GetOutboundPinholeTimeoutArgs); + return ret; +} + +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) +{ + struct UPNParg * AddPinholeArgs; + char * buffer; + int bufsize; + struct NameValueParserData pdata; + const char * resVal; + char * p; + int ret; + + if(!intPort || !intClient || !proto || !remoteHost || !remotePort || !leaseTime) + return UPNPCOMMAND_INVALID_ARGS; + + AddPinholeArgs = calloc(7, sizeof(struct UPNParg)); + if(AddPinholeArgs == NULL) + return UPNPCOMMAND_MEM_ALLOC_ERROR; + /* RemoteHost can be wilcarded */ + if(strncmp(remoteHost, "empty", 5)==0) + { + AddPinholeArgs[0].elt = "RemoteHost"; + AddPinholeArgs[0].val = ""; + } + else + { + AddPinholeArgs[0].elt = "RemoteHost"; + AddPinholeArgs[0].val = remoteHost; + } + AddPinholeArgs[1].elt = "RemotePort"; + AddPinholeArgs[1].val = remotePort; + AddPinholeArgs[2].elt = "Protocol"; + AddPinholeArgs[2].val = proto; + AddPinholeArgs[3].elt = "InternalPort"; + AddPinholeArgs[3].val = intPort; + if(strncmp(intClient, "empty", 5)==0) + { + AddPinholeArgs[4].elt = "InternalClient"; + AddPinholeArgs[4].val = ""; + } + else + { + AddPinholeArgs[4].elt = "InternalClient"; + AddPinholeArgs[4].val = intClient; + } + AddPinholeArgs[5].elt = "LeaseTime"; + AddPinholeArgs[5].val = leaseTime; + buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "AddPinhole", AddPinholeArgs, &bufsize); + if(!buffer) + return UPNPCOMMAND_HTTP_ERROR; + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + p = GetValueFromNameValueList(&pdata, "UniqueID"); + if(p) + { + strncpy(uniqueID, p, 8); + uniqueID[7] = '\0'; + } + resVal = GetValueFromNameValueList(&pdata, "errorCode"); + if(resVal) + { + /*printf("AddPortMapping errorCode = '%s'\n", resVal);*/ + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(resVal, "%d", &ret); + } + else + { + ret = UPNPCOMMAND_SUCCESS; + } + ClearNameValueList(&pdata); + free(AddPinholeArgs); + return ret; +} + +MINIUPNP_LIBSPEC int +UPNP_UpdatePinhole(const char * controlURL, const char * servicetype, + const char * uniqueID, + const char * leaseTime) +{ + struct UPNParg * UpdatePinholeArgs; + char * buffer; + int bufsize; + struct NameValueParserData pdata; + const char * resVal; + int ret; + + if(!uniqueID || !leaseTime) + return UPNPCOMMAND_INVALID_ARGS; + + UpdatePinholeArgs = calloc(3, sizeof(struct UPNParg)); + if(UpdatePinholeArgs == NULL) + return UPNPCOMMAND_MEM_ALLOC_ERROR; + UpdatePinholeArgs[0].elt = "UniqueID"; + UpdatePinholeArgs[0].val = uniqueID; + UpdatePinholeArgs[1].elt = "NewLeaseTime"; + UpdatePinholeArgs[1].val = leaseTime; + buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "UpdatePinhole", UpdatePinholeArgs, &bufsize); + if(!buffer) + return UPNPCOMMAND_HTTP_ERROR; + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + resVal = GetValueFromNameValueList(&pdata, "errorCode"); + if(resVal) + { + /*printf("AddPortMapping errorCode = '%s'\n", resVal); */ + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(resVal, "%d", &ret); + } + else + { + ret = UPNPCOMMAND_SUCCESS; + } + ClearNameValueList(&pdata); + free(UpdatePinholeArgs); + return ret; +} + +MINIUPNP_LIBSPEC int +UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID) +{ + /*struct NameValueParserData pdata;*/ + struct UPNParg * DeletePinholeArgs; + char * buffer; + int bufsize; + struct NameValueParserData pdata; + const char * resVal; + int ret; + + if(!uniqueID) + return UPNPCOMMAND_INVALID_ARGS; + + DeletePinholeArgs = calloc(2, sizeof(struct UPNParg)); + if(DeletePinholeArgs == NULL) + return UPNPCOMMAND_MEM_ALLOC_ERROR; + DeletePinholeArgs[0].elt = "UniqueID"; + DeletePinholeArgs[0].val = uniqueID; + buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "DeletePinhole", DeletePinholeArgs, &bufsize); + if(!buffer) + return UPNPCOMMAND_HTTP_ERROR; + /*DisplayNameValueList(buffer, bufsize);*/ + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + resVal = GetValueFromNameValueList(&pdata, "errorCode"); + if(resVal) + { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(resVal, "%d", &ret); + } + else + { + ret = UPNPCOMMAND_SUCCESS; + } + ClearNameValueList(&pdata); + free(DeletePinholeArgs); + return ret; +} + +MINIUPNP_LIBSPEC int +UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype, + const char * uniqueID, int * isWorking) +{ + struct NameValueParserData pdata; + struct UPNParg * CheckPinholeWorkingArgs; + char * buffer; + int bufsize; + char * p; + int ret = UPNPCOMMAND_UNKNOWN_ERROR; + + if(!uniqueID) + return UPNPCOMMAND_INVALID_ARGS; + + CheckPinholeWorkingArgs = calloc(4, sizeof(struct UPNParg)); + if(CheckPinholeWorkingArgs == NULL) + return UPNPCOMMAND_MEM_ALLOC_ERROR; + CheckPinholeWorkingArgs[0].elt = "UniqueID"; + CheckPinholeWorkingArgs[0].val = uniqueID; + buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "CheckPinholeWorking", CheckPinholeWorkingArgs, &bufsize); + if(!buffer) + return UPNPCOMMAND_HTTP_ERROR; + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + + p = GetValueFromNameValueList(&pdata, "IsWorking"); + if(p) + { + *isWorking=my_atoui(p); + ret = UPNPCOMMAND_SUCCESS; + } + else + *isWorking = 0; + + p = GetValueFromNameValueList(&pdata, "errorCode"); + if(p) + { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(p, "%d", &ret); + } + + ClearNameValueList(&pdata); + free(CheckPinholeWorkingArgs); + return ret; +} + +MINIUPNP_LIBSPEC int +UPNP_GetPinholePackets(const char * controlURL, const char * servicetype, + const char * uniqueID, int * packets) +{ + struct NameValueParserData pdata; + struct UPNParg * GetPinholePacketsArgs; + char * buffer; + int bufsize; + char * p; + int ret = UPNPCOMMAND_UNKNOWN_ERROR; + + if(!uniqueID) + return UPNPCOMMAND_INVALID_ARGS; + + GetPinholePacketsArgs = calloc(4, sizeof(struct UPNParg)); + if(GetPinholePacketsArgs == NULL) + return UPNPCOMMAND_MEM_ALLOC_ERROR; + GetPinholePacketsArgs[0].elt = "UniqueID"; + GetPinholePacketsArgs[0].val = uniqueID; + buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetPinholePackets", GetPinholePacketsArgs, &bufsize); + if(!buffer) + return UPNPCOMMAND_HTTP_ERROR; + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + + p = GetValueFromNameValueList(&pdata, "PinholePackets"); + if(p) + { + *packets=my_atoui(p); + ret = UPNPCOMMAND_SUCCESS; + } + + p = GetValueFromNameValueList(&pdata, "errorCode"); + if(p) + { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(p, "%d", &ret); + } + + ClearNameValueList(&pdata); + free(GetPinholePacketsArgs); + return ret; +} + + diff --git a/ext/miniupnpc/upnpcommands.h b/ext/miniupnpc/upnpcommands.h new file mode 100644 index 00000000..22eda5e3 --- /dev/null +++ b/ext/miniupnpc/upnpcommands.h @@ -0,0 +1,348 @@ +/* $Id: upnpcommands.h,v 1.31 2015/07/21 13:16:55 nanard Exp $ */ +/* Miniupnp project : http://miniupnp.free.fr/ + * Author : Thomas Bernard + * Copyright (c) 2005-2015 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided within this distribution */ +#ifndef UPNPCOMMANDS_H_INCLUDED +#define UPNPCOMMANDS_H_INCLUDED + +#include "upnpreplyparse.h" +#include "portlistingparse.h" +#include "miniupnpc_declspec.h" +#include "miniupnpctypes.h" + +/* MiniUPnPc return codes : */ +#define UPNPCOMMAND_SUCCESS (0) +#define UPNPCOMMAND_UNKNOWN_ERROR (-1) +#define UPNPCOMMAND_INVALID_ARGS (-2) +#define UPNPCOMMAND_HTTP_ERROR (-3) +#define UPNPCOMMAND_INVALID_RESPONSE (-4) +#define UPNPCOMMAND_MEM_ALLOC_ERROR (-5) + +#ifdef __cplusplus +extern "C" { +#endif + +MINIUPNP_LIBSPEC UNSIGNED_INTEGER +UPNP_GetTotalBytesSent(const char * controlURL, + const char * servicetype); + +MINIUPNP_LIBSPEC UNSIGNED_INTEGER +UPNP_GetTotalBytesReceived(const char * controlURL, + const char * servicetype); + +MINIUPNP_LIBSPEC UNSIGNED_INTEGER +UPNP_GetTotalPacketsSent(const char * controlURL, + const char * servicetype); + +MINIUPNP_LIBSPEC UNSIGNED_INTEGER +UPNP_GetTotalPacketsReceived(const char * controlURL, + const char * servicetype); + +/* UPNP_GetStatusInfo() + * status and lastconnerror are 64 byte buffers + * Return values : + * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR + * or a UPnP Error code */ +MINIUPNP_LIBSPEC int +UPNP_GetStatusInfo(const char * controlURL, + const char * servicetype, + char * status, + unsigned int * uptime, + char * lastconnerror); + +/* UPNP_GetConnectionTypeInfo() + * argument connectionType is a 64 character buffer + * Return Values : + * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR + * or a UPnP Error code */ +MINIUPNP_LIBSPEC int +UPNP_GetConnectionTypeInfo(const char * controlURL, + const char * servicetype, + char * connectionType); + +/* UPNP_GetExternalIPAddress() call the corresponding UPNP method. + * if the third arg is not null the value is copied to it. + * at least 16 bytes must be available + * + * Return values : + * 0 : SUCCESS + * NON ZERO : ERROR Either an UPnP error code or an unknown error. + * + * possible UPnP Errors : + * 402 Invalid Args - See UPnP Device Architecture section on Control. + * 501 Action Failed - See UPnP Device Architecture section on Control. */ +MINIUPNP_LIBSPEC int +UPNP_GetExternalIPAddress(const char * controlURL, + const char * servicetype, + char * extIpAdd); + +/* UPNP_GetLinkLayerMaxBitRates() + * call WANCommonInterfaceConfig:1#GetCommonLinkProperties + * + * return values : + * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR + * or a UPnP Error Code. */ +MINIUPNP_LIBSPEC int +UPNP_GetLinkLayerMaxBitRates(const char* controlURL, + const char* servicetype, + unsigned int * bitrateDown, + unsigned int * bitrateUp); + +/* UPNP_AddPortMapping() + * if desc is NULL, it will be defaulted to "libminiupnpc" + * remoteHost is usually NULL because IGD don't support it. + * + * Return values : + * 0 : SUCCESS + * NON ZERO : ERROR. Either an UPnP error code or an unknown error. + * + * List of possible UPnP errors for AddPortMapping : + * errorCode errorDescription (short) - Description (long) + * 402 Invalid Args - See UPnP Device Architecture section on Control. + * 501 Action Failed - See UPnP Device Architecture section on Control. + * 606 Action not authorized - The action requested REQUIRES authorization and + * the sender was not authorized. + * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be + * wild-carded + * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded + * 718 ConflictInMappingEntry - The port mapping entry specified conflicts + * with a mapping assigned previously to another client + * 724 SamePortValuesRequired - Internal and External port values + * must be the same + * 725 OnlyPermanentLeasesSupported - The NAT implementation only supports + * permanent lease times on port mappings + * 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard + * and cannot be a specific IP address or DNS name + * 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and + * cannot be a specific port value + * 728 NoPortMapsAvailable - There are not enough free ports available to + * complete port mapping. + * 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed + * due to conflict with other mechanisms. + * 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded + */ +MINIUPNP_LIBSPEC int +UPNP_AddPortMapping(const char * controlURL, const char * servicetype, + const char * extPort, + const char * inPort, + const char * inClient, + const char * desc, + const char * proto, + const char * remoteHost, + const char * leaseDuration); + +/* UPNP_AddAnyPortMapping() + * if desc is NULL, it will be defaulted to "libminiupnpc" + * remoteHost is usually NULL because IGD don't support it. + * + * Return values : + * 0 : SUCCESS + * NON ZERO : ERROR. Either an UPnP error code or an unknown error. + * + * List of possible UPnP errors for AddPortMapping : + * errorCode errorDescription (short) - Description (long) + * 402 Invalid Args - See UPnP Device Architecture section on Control. + * 501 Action Failed - See UPnP Device Architecture section on Control. + * 606 Action not authorized - The action requested REQUIRES authorization and + * the sender was not authorized. + * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be + * wild-carded + * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded + * 728 NoPortMapsAvailable - There are not enough free ports available to + * complete port mapping. + * 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed + * due to conflict with other mechanisms. + * 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded + */ +MINIUPNP_LIBSPEC int +UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype, + const char * extPort, + const char * inPort, + const char * inClient, + const char * desc, + const char * proto, + const char * remoteHost, + const char * leaseDuration, + char * reservedPort); + +/* UPNP_DeletePortMapping() + * Use same argument values as what was used for AddPortMapping(). + * remoteHost is usually NULL because IGD don't support it. + * Return Values : + * 0 : SUCCESS + * NON ZERO : error. Either an UPnP error code or an undefined error. + * + * List of possible UPnP errors for DeletePortMapping : + * 402 Invalid Args - See UPnP Device Architecture section on Control. + * 606 Action not authorized - The action requested REQUIRES authorization + * and the sender was not authorized. + * 714 NoSuchEntryInArray - The specified value does not exist in the array */ +MINIUPNP_LIBSPEC int +UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, + const char * extPort, const char * proto, + const char * remoteHost); + +/* UPNP_DeletePortRangeMapping() + * Use same argument values as what was used for AddPortMapping(). + * remoteHost is usually NULL because IGD don't support it. + * Return Values : + * 0 : SUCCESS + * NON ZERO : error. Either an UPnP error code or an undefined error. + * + * List of possible UPnP errors for DeletePortMapping : + * 606 Action not authorized - The action requested REQUIRES authorization + * and the sender was not authorized. + * 730 PortMappingNotFound - This error message is returned if no port + * mapping is found in the specified range. + * 733 InconsistentParameters - NewStartPort and NewEndPort values are not consistent. */ +MINIUPNP_LIBSPEC int +UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype, + const char * extPortStart, const char * extPortEnd, + const char * proto, + const char * manage); + +/* UPNP_GetPortMappingNumberOfEntries() + * not supported by all routers */ +MINIUPNP_LIBSPEC int +UPNP_GetPortMappingNumberOfEntries(const char* controlURL, + const char* servicetype, + unsigned int * num); + +/* UPNP_GetSpecificPortMappingEntry() + * retrieves an existing port mapping + * params : + * in extPort + * in proto + * in remoteHost + * out intClient (16 bytes) + * out intPort (6 bytes) + * out desc (80 bytes) + * out enabled (4 bytes) + * out leaseDuration (16 bytes) + * + * return value : + * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR + * or a UPnP Error Code. + * + * List of possible UPnP errors for _GetSpecificPortMappingEntry : + * 402 Invalid Args - See UPnP Device Architecture section on Control. + * 501 Action Failed - See UPnP Device Architecture section on Control. + * 606 Action not authorized - The action requested REQUIRES authorization + * and the sender was not authorized. + * 714 NoSuchEntryInArray - The specified value does not exist in the array. + */ +MINIUPNP_LIBSPEC int +UPNP_GetSpecificPortMappingEntry(const char * controlURL, + const char * servicetype, + const char * extPort, + const char * proto, + const char * remoteHost, + char * intClient, + char * intPort, + char * desc, + char * enabled, + char * leaseDuration); + +/* UPNP_GetGenericPortMappingEntry() + * params : + * in index + * out extPort (6 bytes) + * out intClient (16 bytes) + * out intPort (6 bytes) + * out protocol (4 bytes) + * out desc (80 bytes) + * out enabled (4 bytes) + * out rHost (64 bytes) + * out duration (16 bytes) + * + * return value : + * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR + * or a UPnP Error Code. + * + * Possible UPNP Error codes : + * 402 Invalid Args - See UPnP Device Architecture section on Control. + * 606 Action not authorized - The action requested REQUIRES authorization + * and the sender was not authorized. + * 713 SpecifiedArrayIndexInvalid - The specified array index is out of bounds + */ +MINIUPNP_LIBSPEC int +UPNP_GetGenericPortMappingEntry(const char * controlURL, + const char * servicetype, + const char * index, + char * extPort, + char * intClient, + char * intPort, + char * protocol, + char * desc, + char * enabled, + char * rHost, + char * duration); + +/* UPNP_GetListOfPortMappings() Available in IGD v2 + * + * + * Possible UPNP Error codes : + * 606 Action not Authorized + * 730 PortMappingNotFound - no port mapping is found in the specified range. + * 733 InconsistantParameters - NewStartPort and NewEndPort values are not + * consistent. + */ +MINIUPNP_LIBSPEC int +UPNP_GetListOfPortMappings(const char * controlURL, + const char * servicetype, + const char * startPort, + const char * endPort, + const char * protocol, + const char * numberOfPorts, + struct PortMappingParserData * data); + +/* IGD:2, functions for service WANIPv6FirewallControl:1 */ +MINIUPNP_LIBSPEC int +UPNP_GetFirewallStatus(const char * controlURL, + const char * servicetype, + int * firewallEnabled, + int * inboundPinholeAllowed); + +MINIUPNP_LIBSPEC int +UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype, + const char * remoteHost, + const char * remotePort, + const char * intClient, + const char * intPort, + const char * proto, + int * opTimeout); + +MINIUPNP_LIBSPEC int +UPNP_AddPinhole(const char * controlURL, const char * servicetype, + const char * remoteHost, + const char * remotePort, + const char * intClient, + const char * intPort, + const char * proto, + const char * leaseTime, + char * uniqueID); + +MINIUPNP_LIBSPEC int +UPNP_UpdatePinhole(const char * controlURL, const char * servicetype, + const char * uniqueID, + const char * leaseTime); + +MINIUPNP_LIBSPEC int +UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID); + +MINIUPNP_LIBSPEC int +UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype, + const char * uniqueID, int * isWorking); + +MINIUPNP_LIBSPEC int +UPNP_GetPinholePackets(const char * controlURL, const char * servicetype, + const char * uniqueID, int * packets); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/ext/miniupnpc/upnpdev.c b/ext/miniupnpc/upnpdev.c new file mode 100644 index 00000000..d89a9934 --- /dev/null +++ b/ext/miniupnpc/upnpdev.c @@ -0,0 +1,23 @@ +/* $Id: upnpdev.c,v 1.1 2015/08/28 12:14:19 nanard Exp $ */ +/* Project : miniupnp + * Web : http://miniupnp.free.fr/ + * Author : Thomas BERNARD + * copyright (c) 2005-2015 Thomas Bernard + * This software is subjet to the conditions detailed in the + * provided LICENSE file. */ +#include +#include "upnpdev.h" + +/* freeUPNPDevlist() should be used to + * free the chained list returned by upnpDiscover() */ +void freeUPNPDevlist(struct UPNPDev * devlist) +{ + struct UPNPDev * next; + while(devlist) + { + next = devlist->pNext; + free(devlist); + devlist = next; + } +} + diff --git a/ext/miniupnpc/upnpdev.h b/ext/miniupnpc/upnpdev.h new file mode 100644 index 00000000..f49fbe17 --- /dev/null +++ b/ext/miniupnpc/upnpdev.h @@ -0,0 +1,36 @@ +/* $Id: upnpdev.h,v 1.1 2015/08/28 12:14:19 nanard Exp $ */ +/* Project : miniupnp + * Web : http://miniupnp.free.fr/ + * Author : Thomas BERNARD + * copyright (c) 2005-2015 Thomas Bernard + * This software is subjet to the conditions detailed in the + * provided LICENSE file. */ +#ifndef UPNPDEV_H_INCLUDED +#define UPNPDEV_H_INCLUDED + +#include "miniupnpc_declspec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct UPNPDev { + struct UPNPDev * pNext; + char * descURL; + char * st; + unsigned int scope_id; + char * usn; + char buffer[3]; +}; + +/* freeUPNPDevlist() + * free list returned by upnpDiscover() */ +MINIUPNP_LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist); + + +#ifdef __cplusplus +} +#endif + + +#endif /* UPNPDEV_H_INCLUDED */ diff --git a/ext/miniupnpc/upnperrors.c b/ext/miniupnpc/upnperrors.c new file mode 100644 index 00000000..7ab8ee96 --- /dev/null +++ b/ext/miniupnpc/upnperrors.c @@ -0,0 +1,107 @@ +/* $Id: upnperrors.c,v 1.8 2014/06/10 09:41:48 nanard Exp $ */ +/* Project : miniupnp + * Author : Thomas BERNARD + * copyright (c) 2007 Thomas Bernard + * All Right reserved. + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * This software is subjet to the conditions detailed in the + * provided LICENCE file. */ +#include +#include "upnperrors.h" +#include "upnpcommands.h" +#include "miniupnpc.h" + +const char * strupnperror(int err) +{ + const char * s = NULL; + switch(err) { + case UPNPCOMMAND_SUCCESS: + s = "Success"; + break; + case UPNPCOMMAND_UNKNOWN_ERROR: + s = "Miniupnpc Unknown Error"; + break; + case UPNPCOMMAND_INVALID_ARGS: + s = "Miniupnpc Invalid Arguments"; + break; + case UPNPCOMMAND_INVALID_RESPONSE: + s = "Miniupnpc Invalid response"; + break; + case UPNPDISCOVER_SOCKET_ERROR: + s = "Miniupnpc Socket error"; + break; + case UPNPDISCOVER_MEMORY_ERROR: + s = "Miniupnpc Memory allocation error"; + break; + case 401: + s = "Invalid Action"; + break; + case 402: + s = "Invalid Args"; + break; + case 501: + s = "Action Failed"; + break; + case 606: + s = "Action not authorized"; + break; + case 701: + s = "PinholeSpaceExhausted"; + break; + case 702: + s = "FirewallDisabled"; + break; + case 703: + s = "InboundPinholeNotAllowed"; + break; + case 704: + s = "NoSuchEntry"; + break; + case 705: + s = "ProtocolNotSupported"; + break; + case 706: + s = "InternalPortWildcardingNotAllowed"; + break; + case 707: + s = "ProtocolWildcardingNotAllowed"; + break; + case 708: + s = "WildcardNotPermittedInSrcIP"; + break; + case 709: + s = "NoPacketSent"; + break; + case 713: + s = "SpecifiedArrayIndexInvalid"; + break; + case 714: + s = "NoSuchEntryInArray"; + break; + case 715: + s = "WildCardNotPermittedInSrcIP"; + break; + case 716: + s = "WildCardNotPermittedInExtPort"; + break; + case 718: + s = "ConflictInMappingEntry"; + break; + case 724: + s = "SamePortValuesRequired"; + break; + case 725: + s = "OnlyPermanentLeasesSupported"; + break; + case 726: + s = "RemoteHostOnlySupportsWildcard"; + break; + case 727: + s = "ExternalPortOnlySupportsWildcard"; + break; + default: + s = "UnknownError"; + break; + } + return s; +} diff --git a/ext/miniupnpc/upnperrors.h b/ext/miniupnpc/upnperrors.h new file mode 100644 index 00000000..3115aee5 --- /dev/null +++ b/ext/miniupnpc/upnperrors.h @@ -0,0 +1,26 @@ +/* $Id: upnperrors.h,v 1.6 2015/07/21 13:16:55 nanard Exp $ */ +/* (c) 2007-2015 Thomas Bernard + * All rights reserved. + * MiniUPnP Project. + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * This software is subjet to the conditions detailed in the + * provided LICENCE file. */ +#ifndef UPNPERRORS_H_INCLUDED +#define UPNPERRORS_H_INCLUDED + +#include "miniupnpc_declspec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* strupnperror() + * Return a string description of the UPnP error code + * or NULL for undefinded errors */ +MINIUPNP_LIBSPEC const char * strupnperror(int err); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ext/miniupnpc/upnpreplyparse.c b/ext/miniupnpc/upnpreplyparse.c new file mode 100644 index 00000000..5de5796a --- /dev/null +++ b/ext/miniupnpc/upnpreplyparse.c @@ -0,0 +1,197 @@ +/* $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 + * This software is subject to the conditions detailed + * in the LICENCE file provided within the distribution */ + +#include +#include +#include + +#include "upnpreplyparse.h" +#include "minixml.h" + +static void +NameValueParserStartElt(void * d, const char * name, int l) +{ + struct NameValueParserData * data = (struct NameValueParserData *)d; + data->topelt = 1; + if(l>63) + l = 63; + memcpy(data->curelt, name, l); + data->curelt[l] = '\0'; + data->cdata = NULL; + data->cdatalen = 0; +} + +static void +NameValueParserEndElt(void * d, const char * name, int l) +{ + struct NameValueParserData * data = (struct NameValueParserData *)d; + struct NameValue * nv; + (void)name; + (void)l; + if(!data->topelt) + return; + if(strcmp(data->curelt, "NewPortListing") != 0) + { + int l; + /* standard case. Limited to n chars strings */ + l = data->cdatalen; + nv = malloc(sizeof(struct NameValue)); + if(nv == NULL) + { + /* malloc error */ +#ifdef DEBUG + fprintf(stderr, "%s: error allocating memory", + "NameValueParserEndElt"); +#endif /* DEBUG */ + return; + } + if(l>=(int)sizeof(nv->value)) + l = sizeof(nv->value) - 1; + strncpy(nv->name, data->curelt, 64); + nv->name[63] = '\0'; + if(data->cdata != NULL) + { + memcpy(nv->value, data->cdata, l); + nv->value[l] = '\0'; + } + else + { + nv->value[0] = '\0'; + } + nv->l_next = data->l_head; /* insert in list */ + data->l_head = nv; + } + data->cdata = NULL; + data->cdatalen = 0; + data->topelt = 0; +} + +static void +NameValueParserGetData(void * d, const char * datas, int l) +{ + struct NameValueParserData * data = (struct NameValueParserData *)d; + if(strcmp(data->curelt, "NewPortListing") == 0) + { + /* specific case for NewPortListing which is a XML Document */ + data->portListing = malloc(l + 1); + if(!data->portListing) + { + /* malloc error */ +#ifdef DEBUG + fprintf(stderr, "%s: error allocating memory", + "NameValueParserGetData"); +#endif /* DEBUG */ + return; + } + memcpy(data->portListing, datas, l); + data->portListing[l] = '\0'; + data->portListingLength = l; + } + else + { + /* standard case. */ + data->cdata = datas; + data->cdatalen = l; + } +} + +void +ParseNameValue(const char * buffer, int bufsize, + struct NameValueParserData * data) +{ + struct xmlparser parser; + data->l_head = NULL; + data->portListing = NULL; + data->portListingLength = 0; + /* init xmlparser object */ + parser.xmlstart = buffer; + parser.xmlsize = bufsize; + parser.data = data; + parser.starteltfunc = NameValueParserStartElt; + parser.endeltfunc = NameValueParserEndElt; + parser.datafunc = NameValueParserGetData; + parser.attfunc = 0; + parsexml(&parser); +} + +void +ClearNameValueList(struct NameValueParserData * pdata) +{ + struct NameValue * nv; + if(pdata->portListing) + { + free(pdata->portListing); + pdata->portListing = NULL; + pdata->portListingLength = 0; + } + while((nv = pdata->l_head) != NULL) + { + pdata->l_head = nv->l_next; + free(nv); + } +} + +char * +GetValueFromNameValueList(struct NameValueParserData * pdata, + const char * Name) +{ + struct NameValue * nv; + char * p = NULL; + for(nv = pdata->l_head; + (nv != NULL) && (p == NULL); + nv = nv->l_next) + { + 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 +void +DisplayNameValueList(char * buffer, int bufsize) +{ + struct NameValueParserData pdata; + struct NameValue * nv; + ParseNameValue(buffer, bufsize, &pdata); + for(nv = pdata.l_head; + nv != NULL; + nv = nv->l_next) + { + printf("%s = %s\n", nv->name, nv->value); + } + ClearNameValueList(&pdata); +} +#endif /* DEBUG */ + diff --git a/ext/miniupnpc/upnpreplyparse.h b/ext/miniupnpc/upnpreplyparse.h new file mode 100644 index 00000000..6badd15b --- /dev/null +++ b/ext/miniupnpc/upnpreplyparse.h @@ -0,0 +1,63 @@ +/* $Id: upnpreplyparse.h,v 1.19 2014/10/27 16:33:19 nanard Exp $ */ +/* MiniUPnP project + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * (c) 2006-2013 Thomas Bernard + * This software is subject to the conditions detailed + * in the LICENCE file provided within the distribution */ + +#ifndef UPNPREPLYPARSE_H_INCLUDED +#define UPNPREPLYPARSE_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +struct NameValue { + struct NameValue * l_next; + char name[64]; + char value[128]; +}; + +struct NameValueParserData { + struct NameValue * l_head; + char curelt[64]; + char * portListing; + int portListingLength; + int topelt; + const char * cdata; + int cdatalen; +}; + +/* ParseNameValue() */ +void +ParseNameValue(const char * buffer, int bufsize, + struct NameValueParserData * data); + +/* ClearNameValueList() */ +void +ClearNameValueList(struct NameValueParserData * pdata); + +/* GetValueFromNameValueList() */ +char * +GetValueFromNameValueList(struct NameValueParserData * pdata, + const char * Name); + +#if 0 +/* GetValueFromNameValueListIgnoreNS() */ +char * +GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, + const char * Name); +#endif + +/* DisplayNameValueList() */ +#ifdef DEBUG +void +DisplayNameValueList(char * buffer, int bufsize); +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/ext/miniupnpc/wingenminiupnpcstrings.c b/ext/miniupnpc/wingenminiupnpcstrings.c new file mode 100644 index 00000000..50df06a7 --- /dev/null +++ b/ext/miniupnpc/wingenminiupnpcstrings.c @@ -0,0 +1,83 @@ +/* $Id: wingenminiupnpcstrings.c,v 1.4 2015/02/08 08:46:06 nanard Exp $ */ +/* Project: miniupnp + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * Author: Thomas Bernard + * Copyright (c) 2005-2015 Thomas Bernard + * This software is subjects to the conditions detailed + * in the LICENSE file provided within this distribution */ +#include +#include + +/* This program display the Windows version and is used to + * generate the miniupnpcstrings.h + * wingenminiupnpcstrings miniupnpcstrings.h.in miniupnpcstrings.h + */ +int main(int argc, char * * argv) { + char buffer[256]; + OSVERSIONINFO osvi; + FILE * fin; + FILE * fout; + int n; + char miniupnpcVersion[32]; + /* dwMajorVersion : + The major version number of the operating system. For more information, see Remarks. + dwMinorVersion : + The minor version number of the operating system. For more information, see Remarks. + dwBuildNumber : + The build number of the operating system. + dwPlatformId + The operating system platform. This member can be the following value. + szCSDVersion + A null-terminated string, such as "Service Pack 3", that indicates the + latest Service Pack installed on the system. If no Service Pack has + been installed, the string is empty. + */ + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + GetVersionEx(&osvi); + + printf("Windows %lu.%lu Build %lu %s\n", + osvi.dwMajorVersion, osvi.dwMinorVersion, + osvi.dwBuildNumber, (const char *)&(osvi.szCSDVersion)); + + fin = fopen("VERSION", "r"); + fgets(miniupnpcVersion, sizeof(miniupnpcVersion), fin); + fclose(fin); + for(n = 0; n < sizeof(miniupnpcVersion); n++) { + if(miniupnpcVersion[n] < ' ') + miniupnpcVersion[n] = '\0'; + } + printf("MiniUPnPc version %s\n", miniupnpcVersion); + + if(argc >= 3) { + fin = fopen(argv[1], "r"); + if(!fin) { + fprintf(stderr, "Cannot open %s for reading.\n", argv[1]); + return 1; + } + fout = fopen(argv[2], "w"); + if(!fout) { + fprintf(stderr, "Cannot open %s for writing.\n", argv[2]); + fclose(fin); + return 1; + } + n = 0; + while(fgets(buffer, sizeof(buffer), fin)) { + if(0 == memcmp(buffer, "#define OS_STRING \"OS/version\"", 30)) { + sprintf(buffer, "#define OS_STRING \"MSWindows/%ld.%ld.%ld\"\n", + osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber); + } else if(0 == memcmp(buffer, "#define MINIUPNPC_VERSION_STRING \"version\"", 42)) { + sprintf(buffer, "#define MINIUPNPC_VERSION_STRING \"%s\"\n", + miniupnpcVersion); + } + /*fputs(buffer, stdout);*/ + fputs(buffer, fout); + n++; + } + fclose(fin); + fclose(fout); + printf("%d lines written to %s.\n", n, argv[2]); + } + return 0; +} diff --git a/make-mac.mk b/make-mac.mk index 6ea23859..d30fc5bd 100644 --- a/make-mac.mk +++ b/make-mac.mk @@ -13,15 +13,15 @@ ARCH_FLAGS=-arch x86_64 include objects.mk OBJS+=osdep/OSXEthernetTap.o -# Comment out to disable building against shipped libminiupnpc binary for Mac -ZT_USE_MINIUPNPC?=1 - # Disable codesign since open source users will not have ZeroTier's certs CODESIGN=echo PRODUCTSIGN=echo CODESIGN_APP_CERT= CODESIGN_INSTALLER_CERT= +# Build with libminiupnpc by default for Mac +ZT_USE_MINIUPNPC?=1 + # For internal use only -- signs everything with ZeroTier's developer cert ifeq ($(ZT_OFFICIAL_RELEASE),1) DEFS+=-DZT_OFFICIAL_RELEASE -DZT_AUTO_UPDATE @@ -34,7 +34,7 @@ endif # Build with ZT_ENABLE_CLUSTER=1 to build with cluster support ifeq ($(ZT_ENABLE_CLUSTER),1) - DEFS+=-DZT_ENABLE_CLUSTER + DEFS+=-DZT_ENABLE_CLUSTER endif ifeq ($(ZT_AUTO_UPDATE),1) @@ -43,7 +43,7 @@ endif ifeq ($(ZT_USE_MINIUPNPC),1) DEFS+=-DZT_USE_MINIUPNPC - LIBS+=ext/bin/miniupnpc/mac-x64/libminiupnpc.a + LIBS+=ext/miniupnpc/libminiupnpc.a OBJS+=osdep/UPNPClient.o endif @@ -73,6 +73,9 @@ CXXFLAGS=$(CFLAGS) -fno-rtti all: one one: $(OBJS) one.o +ifeq ($(ZT_USE_MINIUPNPC),1) + cd ext/miniupnpc ; make clean ; make 'CFLAGS=-D_DARWIN_C_SOURCE -O2 -fstack-protector -fPIE -flto -pthread -mmacosx-version-min=10.7 -fno-common -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE' -j 2 libminiupnpc.a +endif $(CXX) $(CXXFLAGS) -o zerotier-one $(OBJS) one.o $(LIBS) $(STRIP) zerotier-one ln -sf zerotier-one zerotier-idtool @@ -99,6 +102,7 @@ official: FORCE clean: rm -rf *.dSYM build-* *.pkg *.dmg *.o node/*.o controller/*.o service/*.o osdep/*.o ext/http-parser/*.o ext/lz4/*.o ext/json-parser/*.o zerotier-one zerotier-idtool zerotier-selftest zerotier-cli ZeroTierOneInstaller-* mkworld + cd ext/miniupnpc ; make clean # For those building from source -- installs signed binary tap driver in system ZT home install-mac-tap: FORCE -- cgit v1.2.3 From 0f5fb48a0ba70ced52aa69ca7ff00824cf8fb829 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 16 Nov 2015 19:04:04 -0800 Subject: Turns out it wasn't hard to add miniupnpc to the VS2012 project and just have it build with the rest of the code. --- ext/bin/miniupnpc/Changelog.txt | 633 --------------------- ext/bin/miniupnpc/LICENSE | 27 - ext/bin/miniupnpc/README.md | 4 - ext/bin/miniupnpc/VERSION | 1 - ext/bin/miniupnpc/include/miniupnpc/codelength.h | 54 -- .../miniupnpc/include/miniupnpc/connecthostport.h | 18 - .../miniupnpc/include/miniupnpc/igd_desc_parse.h | 49 -- ext/bin/miniupnpc/include/miniupnpc/minisoap.h | 15 - ext/bin/miniupnpc/include/miniupnpc/minissdpc.h | 15 - ext/bin/miniupnpc/include/miniupnpc/miniupnpc.h | 154 ----- .../include/miniupnpc/miniupnpc_declspec.h | 21 - .../miniupnpc/include/miniupnpc/miniupnpcstrings.h | 23 - .../miniupnpc/include/miniupnpc/miniupnpctypes.h | 19 - ext/bin/miniupnpc/include/miniupnpc/miniwget.h | 30 - ext/bin/miniupnpc/include/miniupnpc/minixml.h | 37 -- .../miniupnpc/include/miniupnpc/portlistingparse.h | 65 --- ext/bin/miniupnpc/include/miniupnpc/receivedata.h | 19 - ext/bin/miniupnpc/include/miniupnpc/upnpcommands.h | 348 ----------- ext/bin/miniupnpc/include/miniupnpc/upnperrors.h | 26 - .../miniupnpc/include/miniupnpc/upnpreplyparse.h | 63 -- ext/bin/miniupnpc/windows-x64/miniupnpc.lib | Bin 731616 -> 0 bytes ext/bin/miniupnpc/windows-x86/miniupnpc.lib | Bin 702786 -> 0 bytes ext/installfiles/windows/ZeroTier One.aip | 2 +- ext/miniupnpc/connecthostport.c | 2 + ext/miniupnpc/minisoap.c | 7 + ext/miniupnpc/minissdpc.c | 2 + ext/miniupnpc/miniupnpc.c | 1 + ext/miniupnpc/miniwget.c | 7 + ext/miniupnpc/minixml.c | 1 + ext/miniupnpc/minixmlvalid.c | 1 + ext/miniupnpc/upnpcommands.c | 1 + ext/miniupnpc/upnpreplyparse.c | 1 + osdep/UPNPClient.cpp | 6 +- windows/ZeroTierOne/ZeroTierOne.vcxproj | 45 +- windows/ZeroTierOne/ZeroTierOne.vcxproj.filters | 93 +++ 35 files changed, 157 insertions(+), 1633 deletions(-) delete mode 100644 ext/bin/miniupnpc/Changelog.txt delete mode 100644 ext/bin/miniupnpc/LICENSE delete mode 100644 ext/bin/miniupnpc/README.md delete mode 100644 ext/bin/miniupnpc/VERSION delete mode 100644 ext/bin/miniupnpc/include/miniupnpc/codelength.h delete mode 100644 ext/bin/miniupnpc/include/miniupnpc/connecthostport.h delete mode 100644 ext/bin/miniupnpc/include/miniupnpc/igd_desc_parse.h delete mode 100644 ext/bin/miniupnpc/include/miniupnpc/minisoap.h delete mode 100644 ext/bin/miniupnpc/include/miniupnpc/minissdpc.h delete mode 100644 ext/bin/miniupnpc/include/miniupnpc/miniupnpc.h delete mode 100644 ext/bin/miniupnpc/include/miniupnpc/miniupnpc_declspec.h delete mode 100644 ext/bin/miniupnpc/include/miniupnpc/miniupnpcstrings.h delete mode 100644 ext/bin/miniupnpc/include/miniupnpc/miniupnpctypes.h delete mode 100644 ext/bin/miniupnpc/include/miniupnpc/miniwget.h delete mode 100644 ext/bin/miniupnpc/include/miniupnpc/minixml.h delete mode 100644 ext/bin/miniupnpc/include/miniupnpc/portlistingparse.h delete mode 100644 ext/bin/miniupnpc/include/miniupnpc/receivedata.h delete mode 100644 ext/bin/miniupnpc/include/miniupnpc/upnpcommands.h delete mode 100644 ext/bin/miniupnpc/include/miniupnpc/upnperrors.h delete mode 100644 ext/bin/miniupnpc/include/miniupnpc/upnpreplyparse.h delete mode 100644 ext/bin/miniupnpc/windows-x64/miniupnpc.lib delete mode 100644 ext/bin/miniupnpc/windows-x86/miniupnpc.lib (limited to 'ext') diff --git a/ext/bin/miniupnpc/Changelog.txt b/ext/bin/miniupnpc/Changelog.txt deleted file mode 100644 index bb2abb7e..00000000 --- a/ext/bin/miniupnpc/Changelog.txt +++ /dev/null @@ -1,633 +0,0 @@ -$Id: Changelog.txt,v 1.208 2015/07/15 12:18:59 nanard Exp $ -miniUPnP client Changelog. - -2015/07/15: - Check malloc/calloc - -2015/06/16: - update getDevicesFromMiniSSDPD() to process longer minissdpd - responses - -2015/05/22: - add searchalltypes param to upnpDiscoverDevices() - increments API_VERSION to 13 - -2015/04/30: - upnpc: output version on the terminal - -2015/04/27: - _BSD_SOURCE is deprecated in favor of _DEFAULT_SOURCE - fix CMakeLists.txt COMPILE_DEFINITIONS - fix getDevicesFromMiniSSDPD() not setting scope_id - improve -r command of upnpc command line tool - -2014/11/17: - search all : - upnpDiscoverDevices() / upnpDiscoverAll() functions - listdevices executable - increment API_VERSION to 12 - validate igd_desc_parse - -2014/11/13: - increment API_VERSION to 11 - -2014/11/05: - simplified function GetUPNPUrls() - -2014/09/11: - use remoteHost arg of DeletePortMapping - -2014/09/06: - Fix python3 build - -2014/07/01: - Fix parsing of IGD2 root descriptions - -2014/06/10: - rename LIBSPEC to MINIUPNP_LIBSPEC - -2014/05/15: - Add support for IGD2 AddAnyPortMapping and DeletePortMappingRange - -2014/02/05: - handle EINPROGRESS after connect() - -2014/02/03: - minixml now handle XML comments - -VERSION 1.9 : released 2014/01/31 - -2014/01/31: - added argument remoteHost to UPNP_GetSpecificPortMappingEntry() - increment API_VERSION to 10 - -2013/12/09: - --help and -h arguments in upnpc.c - -2013/10/07: - fixed potential buffer overrun in miniwget.c - Modified UPNP_GetValidIGD() to check for ExternalIpAddress - -2013/08/01: - define MAXHOSTNAMELEN if not already done - -2013/06/06: - update upnpreplyparse to allow larger values (128 chars instead of 64) - -2013/05/14: - Update upnpreplyparse to take into account "empty" elements - validate upnpreplyparse.c code with "make check" - -2013/05/03: - Fix Solaris build thanks to Maciej MaÅ‚ecki - -2013/04/27: - Fix testminiwget.sh for BSD - -2013/03/23: - Fixed Makefile for *BSD - -2013/03/11: - Update Makefile to use JNAerator version 0.11 - -2013/02/11: - Fix testminiwget.sh for use with dash - Use $(DESTDIR) in Makefile - -VERSION 1.8 : released 2013/02/06 - -2012/10/16: - fix testminiwget with no IPv6 support - -2012/09/27: - Rename all include guards to not clash with C99 - (7.1.3 Reserved identifiers). - -2012/08/30: - Added -e option to upnpc program (set description for port mappings) - -2012/08/29: - Python 3 support (thanks to Christopher Foo) - -2012/08/11: - Fix a memory link in UPNP_GetValidIGD() - Try to handle scope id in link local IPv6 URL under MS Windows - -2012/07/20: - Disable HAS_IP_MREQN on DragonFly BSD - -2012/06/28: - GetUPNPUrls() now inserts scope into link-local IPv6 addresses - -2012/06/23: - More error return checks in upnpc.c - #define MINIUPNPC_GET_SRC_ADDR enables receivedata() to get scope_id - parseURL() now parses IPv6 addresses scope - new parameter for miniwget() : IPv6 address scope - increment API_VERSION to 9 - -2012/06/20: - fixed CMakeLists.txt - -2012/05/29 - Improvements in testminiwget.sh - -VERSION 1.7 : released 2012/05/24 - -2012/05/01: - Cleanup settings of CFLAGS in Makefile - Fix signed/unsigned integer comparaisons - -2012/04/20: - Allow to specify protocol with TCP or UDP for -A option - -2012/04/09: - Only try to fetch XML description once in UPNP_GetValidIGD() - Added -ansi flag to compilation, and fixed C++ comments to ANSI C comments. - -2012/04/05: - minor improvements to minihttptestserver.c - -2012/03/15: - upnperrors.c returns valid error string for unrecognized error codes - -2012/03/08: - make minihttptestserver listen on loopback interface instead of 0.0.0.0 - -2012/01/25: - Maven installation thanks to Alexey Kuznetsov - -2012/01/21: - Replace WIN32 macro by _WIN32 - -2012/01/19: - Fixes in java wrappers thanks to Alexey Kuznetsov : - https://github.com/axet/miniupnp/tree/fix-javatest/miniupnpc - Make and install .deb packages (python) thanks to Alexey Kuznetsov : - https://github.com/axet/miniupnp/tree/feature-debbuild/miniupnpc - -2012/01/07: - The multicast interface can now be specified by name with IPv4. - -2012/01/02: - Install man page - -2011/11/25: - added header to Port Mappings list in upnpc.c - -2011/10/09: - Makefile : make clean now removes jnaerator generated files. - MINIUPNPC_VERSION in miniupnpc.h (updated by make) - -2011/09/12: - added rootdescURL to UPNPUrls structure. - -VERSION 1.6 : released 2011/07/25 - -2011/07/25: - Update doc for version 1.6 release - -2011/06/18: - Fix for windows in miniwget.c - -2011/06/04: - display remote host in port mapping listing - -2011/06/03: - Fix in make install : there were missing headers - -2011/05/26: - Fix the socket leak in miniwget thanks to Richard Marsh. - Permit to add leaseduration in -a command. Display lease duration. - -2011/05/15: - Try both LinkLocal and SiteLocal multicast address for SSDP in IPv6 - -2011/05/09: - add a test in testminiwget.sh. - more error checking in miniwget.c - -2011/05/06: - Adding some tool to test and validate miniwget.c - simplified and debugged miniwget.c - -2011/04/11: - moving ReceiveData() to a receivedata.c file. - parsing presentation url - adding IGD v2 WANIPv6FirewallControl commands - -2011/04/10: - update of miniupnpcmodule.c - comments in miniwget.c, update in testminiwget - Adding errors codes from IGD v2 - new functions in upnpc.c for IGD v2 - -2011/04/09: - Support for litteral ip v6 address in miniwget - -2011/04/08: - Adding support for urn:schemas-upnp-org:service:WANIPv6FirewallControl:1 - Updating APIVERSION - Supporting IPV6 in upnpDiscover() - Adding a -6 option to upnpc command line tool - -2011/03/18: - miniwget/parseURL() : return an error when url param is null. - fixing GetListOfPortMappings() - -2011/03/14: - upnpDiscover() now reporting an error code. - improvements in comments. - -2011/03/11: - adding miniupnpcstrings.h.cmake and CMakeLists.txt files. - -2011/02/15: - Implementation of GetListOfPortMappings() - -2011/02/07: - updates to minixml to support character data starting with spaces - minixml now support CDATA - upnpreplyparse treats specificaly - change in simpleUPnPcommand to return the buffer (simplification) - -2011/02/06: - Added leaseDuration argument to AddPortMapping() - Starting to implement GetListOfPortMappings() - -2011/01/11: - updating wingenminiupnpcstrings.c - -2011/01/04: - improving updateminiupnpcstrings.sh - -VERSION 1.5 : released 2011/01/01 - -2010/12/21: - use NO_GETADDRINFO macro to disable the use of getaddrinfo/freeaddrinfo - -2010/12/11: - Improvements on getHTTPResponse() code. - -2010/12/09: - new code for miniwget that handle Chunked transfer encoding - using getHTTPResponse() in SOAP call code - Adding MANIFEST.in for 'python setup.py bdist_rpm' - -2010/11/25: - changes to minissdpc.c to compile under Win32. - see http://miniupnp.tuxfamily.org/forum/viewtopic.php?t=729 - -2010/09/17: - Various improvement to Makefile from MichaÅ‚ Górny - -2010/08/05: - Adding the script "external-ip.sh" from Reuben Hawkins - -2010/06/09: - update to python module to match modification made on 2010/04/05 - update to Java test code to match modification made on 2010/04/05 - all UPNP_* function now return an error if the SOAP request failed - at HTTP level. - -2010/04/17: - Using GetBestRoute() under win32 in order to find the - right interface to use. - -2010/04/12: - Retrying with HTTP/1.1 if HTTP/1.0 failed. see - http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1703 - -2010/04/07: - avoid returning duplicates in upnpDiscover() - -2010/04/05: - Create a connecthostport.h/.c with connecthostport() function - and use it in miniwget and miniupnpc. - Use getnameinfo() instead of inet_ntop or inet_ntoa - Work to make miniupnpc IPV6 compatible... - Add java test code. - Big changes in order to support device having both WANIPConnection - and WANPPPConnection. - -2010/04/04: - Use getaddrinfo() instead of gethostbyname() in miniwget. - -2010/01/06: - #define _DARWIN_C_SOURCE for Mac OS X - -2009/12/19: - Improve MinGW32 build - -2009/12/11: - adding a MSVC9 project to build the static library and executable - -2009/12/10: - Fixing some compilation stuff for Windows/MinGW - -2009/12/07: - adaptations in Makefile and updateminiupnpcstring.sh for AmigaOS - some fixes for Windows when using virtual ethernet adapters (it is the - case with VMWare installed). - -2009/12/04: - some fixes for AmigaOS compilation - Changed HTTP version to HTTP/1.0 for Soap too (to prevent chunked - transfer encoding) - -2009/12/03: - updating printIDG and testigddescparse.c for debug. - modifications to compile under AmigaOS - adding a testminiwget program - Changed miniwget to advertise itself as HTTP/1.0 to prevent chunked - transfer encoding - -2009/11/26: - fixing updateminiupnpcstrings.sh to take into account - which command that does not return an error code. - -VERSION 1.4 : released 2009/10/30 - -2009/10/16: - using Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS in python module. - -2009/10/10: - Some fixes for compilation under Solaris - compilation fixes : http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1464 - -2009/09/21: - fixing the code to ignore EINTR during connect() calls. - -2009/08/07: - Set socket timeout for connect() - Some cleanup in miniwget.c - -2009/08/04: - remove multiple redirections with -d in upnpc.c - Print textual error code in upnpc.c - Ignore EINTR during the connect() and poll() calls. - -2009/07/29: - fix in updateminiupnpcstrings.sh if OS name contains "/" - Sending a correct value for MX: field in SSDP request - -2009/07/20: - Change the Makefile to compile under Mac OS X - Fixed a stackoverflow in getDevicesFromMiniSSDPD() - -2009/07/09: - Compile under Haiku - generate miniupnpcstrings.h.in from miniupnpcstrings.h - -2009/06/04: - patching to compile under CygWin and cross compile for minGW - -VERSION 1.3 : - -2009/04/17: - updating python module - Use strtoull() when using C99 - -2009/02/28: - Fixed miniwget.c for compiling under sun - -2008/12/18: - cleanup in Makefile (thanks to Paul de Weerd) - minissdpc.c : win32 compatibility - miniupnpc.c : changed xmlns prefix from 'm' to 'u' - Removed NDEBUG (using DEBUG) - -2008/10/14: - Added the ExternalHost argument to DeletePortMapping() - -2008/10/11: - Added the ExternalHost argument to AddPortMapping() - Put a correct User-Agent: header in HTTP requests. - -VERSION 1.2 : - -2008/10/07: - Update docs - -2008/09/25: - Integrated sameport patch from Dario Meloni : Added a "sameport" - argument to upnpDiscover(). - -2008/07/18: - small modif to make Clang happy :) - -2008/07/17: - #define SOAPPREFIX "s" in miniupnpc.c in order to remove SOAP-ENV... - -2008/07/14: - include declspec.h in installation (to /usr/include/miniupnpc) - -VERSION 1.1 : - -2008/07/04: - standard options for install/ln instead of gnu-specific stuff. - -2008/07/03: - now builds a .dll and .lib with win32. (mingw32) - -2008/04/28: - make install now install the binary of the upnpc tool - -2008/04/27: - added testupnpigd.py - added error strings for miniupnpc "internal" errors - improved python module error/exception reporting. - -2008/04/23: - Completely rewrite igd_desc_parse.c in order to be compatible with - Linksys WAG200G - Added testigddescparse - updated python module - -VERSION 1.0 : - -2008/02/21: - put some #ifdef DEBUG around DisplayNameValueList() - -2008/02/18: - Improved error reporting in upnpcommands.c - UPNP_GetStatusInfo() returns LastConnectionError - -2008/02/16: - better error handling in minisoap.c - improving display of "valid IGD found" in upnpc.c - -2008/02/03: - Fixing UPNP_GetValidIGD() - improved make install :) - -2007/12/22: - Adding upnperrors.c/h to provide a strupnperror() function - used to translate UPnP error codes to string. - -2007/12/19: - Fixing getDevicesFromMiniSSDPD() - improved error reporting of UPnP functions - -2007/12/18: - It is now possible to specify a different location for MiniSSDPd socket. - working with MiniSSDPd is now more efficient. - python module improved. - -2007/12/16: - improving error reporting - -2007/12/13: - Try to improve compatibility by using HTTP/1.0 instead of 1.1 and - XML a bit different for SOAP. - -2007/11/25: - fixed select() call for linux - -2007/11/15: - Added -fPIC to CFLAG for better shared library code. - -2007/11/02: - Fixed a potential socket leak in miniwget2() - -2007/10/16: - added a parameter to upnpDiscover() in order to allow the use of another - interface than the default multicast interface. - -2007/10/12: - Fixed the creation of symbolic link in Makefile - -2007/10/08: - Added man page - -2007/10/02: - fixed memory bug in GetUPNPUrls() - -2007/10/01: - fixes in the Makefile - Added UPNP_GetIGDFromUrl() and adapted the sample program accordingly. - Added SONAME in the shared library to please debian :) - fixed MS Windows compilation (minissdpd is not available under MS Windows). - -2007/09/25: - small change to Makefile to be able to install in a different location - (default is /usr) - -2007/09/24: - now compiling both shared and static library - -2007/09/19: - Cosmetic changes on upnpc.c - -2007/09/02: - adapting to new miniSSDPd (release version ?) - -2007/08/31: - Usage of miniSSDPd to skip discovery process. - -2007/08/27: - fixed python module to allow compilation with Python older than Python 2.4 - -2007/06/12: - Added a python module. - -2007/05/19: - Fixed compilation under MinGW - -2007/05/15: - fixed a memory leak in AddPortMapping() - Added testupnpreplyparse executable to check the parsing of - upnp soap messages - minixml now ignore namespace prefixes. - -2007/04/26: - 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" - -2007/03/19: - cleanup in miniwget.c - -2007/03/01: - Small typo fix... - -2007/01/30: - Now parsing the HTTP header from SOAP responses in order to - get content-length value. - -2007/01/29: - Fixed the Soap Query to speedup the HTTP request. - added some Win32 DLL stuff... - -2007/01/27: - Fixed some WIN32 compatibility issues - -2006/12/14: - Added UPNPIGD_IsConnected() function in miniupnp.c/.h - Added UPNP_GetValidIGD() in miniupnp.c/.h - cleaned upnpc.c main(). now using UPNP_GetValidIGD() - -2006/12/07: - Version 1.0-RC1 released - -2006/12/03: - Minor changes to compile under SunOS/Solaris - -2006/11/30: - made a minixml parser validator program - updated minixml to handle attributes correctly - -2006/11/22: - Added a -r option to the upnpc sample thanks to Alexander Hubmann. - -2006/11/19: - Cleanup code to make it more ANSI C compliant - -2006/11/10: - detect and display local lan address. - -2006/11/04: - Packets and Bytes Sent/Received are now unsigned int. - -2006/11/01: - Bug fix thanks to Giuseppe D'Angelo - -2006/10/31: - C++ compatibility for .h files. - Added a way to get ip Address on the LAN used to reach the IGD. - -2006/10/25: - Added M-SEARCH to the services in the discovery process. - -2006/10/22: - updated the Makefile to use makedepend, added a "make install" - update Makefile - -2006/10/20: - fixing the description url parsing thanks to patch sent by - Wayne Dawe. - Fixed/translated some comments. - Implemented a better discover process, first looking - for IGD then for root devices (as some devices only reply to - M-SEARCH for root devices). - -2006/09/02: - added freeUPNPDevlist() function. - -2006/08/04: - More command line arguments checking - -2006/08/01: - Added the .bat file to compile under Win32 with minGW32 - -2006/07/31: - Fixed the rootdesc parser (igd_desc_parse.c) - -2006/07/20: - parseMSEARCHReply() is now returning the ST: line as well - starting changes to detect several UPnP devices on the network - -2006/07/19: - using GetCommonLinkProperties to get down/upload bitrate - diff --git a/ext/bin/miniupnpc/LICENSE b/ext/bin/miniupnpc/LICENSE deleted file mode 100644 index cb5a0604..00000000 --- a/ext/bin/miniupnpc/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -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. - diff --git a/ext/bin/miniupnpc/README.md b/ext/bin/miniupnpc/README.md deleted file mode 100644 index c3d538ba..00000000 --- a/ext/bin/miniupnpc/README.md +++ /dev/null @@ -1,4 +0,0 @@ -libminiupnpc binaries -====== - -This is a binary build of [libminiupnpc](http://miniupnp.free.fr) for certain architectures to faciliate easy building. Where possible the build flags were set for improved security by enabling options like stack protector (a.k.a. stack canary), ASLR support, etc. diff --git a/ext/bin/miniupnpc/VERSION b/ext/bin/miniupnpc/VERSION deleted file mode 100644 index 2e0e38c6..00000000 --- a/ext/bin/miniupnpc/VERSION +++ /dev/null @@ -1 +0,0 @@ -1.9 diff --git a/ext/bin/miniupnpc/include/miniupnpc/codelength.h b/ext/bin/miniupnpc/include/miniupnpc/codelength.h deleted file mode 100644 index f5f8e30f..00000000 --- a/ext/bin/miniupnpc/include/miniupnpc/codelength.h +++ /dev/null @@ -1,54 +0,0 @@ -/* $Id: codelength.h,v 1.5 2015/07/09 12:40:18 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas BERNARD - * copyright (c) 2005-2015 Thomas Bernard - * This software is subjet to the conditions detailed in the - * provided LICENCE file. */ -#ifndef CODELENGTH_H_INCLUDED -#define CODELENGTH_H_INCLUDED - -/* Encode length by using 7bit per Byte : - * Most significant bit of each byte specifies that the - * following byte is part of the code */ - -/* n : unsigned - * p : unsigned char * - */ -#define DECODELENGTH(n, p) n = 0; \ - do { n = (n << 7) | (*p & 0x7f); } \ - while((*(p++)&0x80) && (n<(1<<25))); - -/* n : unsigned - * READ : function/macro to read one byte (unsigned char) - */ -#define DECODELENGTH_READ(n, READ) \ - n = 0; \ - do { \ - unsigned char c; \ - READ(c); \ - n = (n << 7) | (c & 0x07f); \ - if(!(c&0x80)) break; \ - } while(n<(1<<25)); - -/* n : unsigned - * p : unsigned char * - * p_limit : unsigned char * - */ -#define DECODELENGTH_CHECKLIMIT(n, p, p_limit) \ - n = 0; \ - do { \ - if((p) >= (p_limit)) break; \ - n = (n << 7) | (*(p) & 0x7f); \ - } while((*((p)++)&0x80) && (n<(1<<25))); - - -/* n : unsigned - * p : unsigned char * - */ -#define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \ - if(n>=2097152) *(p++) = (n >> 21) | 0x80; \ - if(n>=16384) *(p++) = (n >> 14) | 0x80; \ - if(n>=128) *(p++) = (n >> 7) | 0x80; \ - *(p++) = n & 0x7f; - -#endif /* CODELENGTH_H_INCLUDED */ diff --git a/ext/bin/miniupnpc/include/miniupnpc/connecthostport.h b/ext/bin/miniupnpc/include/miniupnpc/connecthostport.h deleted file mode 100644 index 56941d6f..00000000 --- a/ext/bin/miniupnpc/include/miniupnpc/connecthostport.h +++ /dev/null @@ -1,18 +0,0 @@ -/* $Id: connecthostport.h,v 1.3 2012/09/27 15:42:10 nanard Exp $ */ -/* Project: miniupnp - * http://miniupnp.free.fr/ - * Author: Thomas Bernard - * Copyright (c) 2010-2012 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 - -/* 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); - -#endif - diff --git a/ext/bin/miniupnpc/include/miniupnpc/igd_desc_parse.h b/ext/bin/miniupnpc/include/miniupnpc/igd_desc_parse.h deleted file mode 100644 index 0de546b6..00000000 --- a/ext/bin/miniupnpc/include/miniupnpc/igd_desc_parse.h +++ /dev/null @@ -1,49 +0,0 @@ -/* $Id: igd_desc_parse.h,v 1.12 2014/11/17 17:19:13 nanard Exp $ */ -/* Project : miniupnp - * http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2005-2014 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ -#ifndef IGD_DESC_PARSE_H_INCLUDED -#define IGD_DESC_PARSE_H_INCLUDED - -/* Structure to store the result of the parsing of UPnP - * descriptions of Internet Gateway Devices */ -#define MINIUPNPC_URL_MAXSIZE (128) -struct IGDdatas_service { - char controlurl[MINIUPNPC_URL_MAXSIZE]; - char eventsuburl[MINIUPNPC_URL_MAXSIZE]; - char scpdurl[MINIUPNPC_URL_MAXSIZE]; - char servicetype[MINIUPNPC_URL_MAXSIZE]; - /*char devicetype[MINIUPNPC_URL_MAXSIZE];*/ -}; - -struct IGDdatas { - char cureltname[MINIUPNPC_URL_MAXSIZE]; - char urlbase[MINIUPNPC_URL_MAXSIZE]; - char presentationurl[MINIUPNPC_URL_MAXSIZE]; - int level; - /*int state;*/ - /* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */ - struct IGDdatas_service CIF; - /* "urn:schemas-upnp-org:service:WANIPConnection:1" - * "urn:schemas-upnp-org:service:WANPPPConnection:1" */ - struct IGDdatas_service first; - /* if both WANIPConnection and WANPPPConnection are present */ - struct IGDdatas_service second; - /* "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1" */ - struct IGDdatas_service IPv6FC; - /* tmp */ - struct IGDdatas_service tmp; -}; - -void IGDstartelt(void *, const char *, int); -void IGDendelt(void *, const char *, int); -void IGDdata(void *, const char *, int); -#ifdef DEBUG -void printIGD(struct IGDdatas *); -#endif /* DEBUG */ - -#endif /* IGD_DESC_PARSE_H_INCLUDED */ diff --git a/ext/bin/miniupnpc/include/miniupnpc/minisoap.h b/ext/bin/miniupnpc/include/miniupnpc/minisoap.h deleted file mode 100644 index 14c859d1..00000000 --- a/ext/bin/miniupnpc/include/miniupnpc/minisoap.h +++ /dev/null @@ -1,15 +0,0 @@ -/* $Id: minisoap.h,v 1.5 2012/09/27 15:42:10 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas Bernard - * Copyright (c) 2005 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. */ -#ifndef MINISOAP_H_INCLUDED -#define MINISOAP_H_INCLUDED - -/*int httpWrite(int, const char *, int, const char *);*/ -int soapPostSubmit(int, const char *, const char *, unsigned short, - const char *, const char *, const char *); - -#endif - diff --git a/ext/bin/miniupnpc/include/miniupnpc/minissdpc.h b/ext/bin/miniupnpc/include/miniupnpc/minissdpc.h deleted file mode 100644 index 915b0026..00000000 --- a/ext/bin/miniupnpc/include/miniupnpc/minissdpc.h +++ /dev/null @@ -1,15 +0,0 @@ -/* $Id: minissdpc.h,v 1.2 2012/09/27 15:42:10 nanard Exp $ */ -/* Project: miniupnp - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author: Thomas Bernard - * Copyright (c) 2005-2007 Thomas Bernard - * This software is subjects to the conditions detailed - * in the LICENCE file provided within this distribution */ -#ifndef MINISSDPC_H_INCLUDED -#define MINISSDPC_H_INCLUDED - -struct UPNPDev * -getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath); - -#endif - diff --git a/ext/bin/miniupnpc/include/miniupnpc/miniupnpc.h b/ext/bin/miniupnpc/include/miniupnpc/miniupnpc.h deleted file mode 100644 index 0eeabc23..00000000 --- a/ext/bin/miniupnpc/include/miniupnpc/miniupnpc.h +++ /dev/null @@ -1,154 +0,0 @@ -/* $Id: miniupnpc.h,v 1.42 2015/07/21 13:16:55 nanard Exp $ */ -/* Project: miniupnp - * http://miniupnp.free.fr/ - * Author: Thomas Bernard - * Copyright (c) 2005-2015 Thomas Bernard - * This software is subjects to the conditions detailed - * in the LICENCE file provided within this distribution */ -#ifndef MINIUPNPC_H_INCLUDED -#define MINIUPNPC_H_INCLUDED - -#include "miniupnpc_declspec.h" -#include "igd_desc_parse.h" - -/* error codes : */ -#define UPNPDISCOVER_SUCCESS (0) -#define UPNPDISCOVER_UNKNOWN_ERROR (-1) -#define UPNPDISCOVER_SOCKET_ERROR (-101) -#define UPNPDISCOVER_MEMORY_ERROR (-102) - -/* versions : */ -#define MINIUPNPC_VERSION "1.9.20150721" -#define MINIUPNPC_API_VERSION 13 - -#ifdef __cplusplus -extern "C" { -#endif - -/* Structures definitions : */ -struct UPNParg { const char * elt; const char * val; }; - -char * -simpleUPnPcommand(int, const char *, const char *, - const char *, struct UPNParg *, - int *); - -struct UPNPDev { - struct UPNPDev * pNext; - char * descURL; - char * st; - unsigned int scope_id; - char buffer[2]; -}; - -/* upnpDiscover() - * discover UPnP devices on the network. - * The discovered devices are returned as a chained list. - * It is up to the caller to free the list with freeUPNPDevlist(). - * delay (in millisecond) is the maximum time for waiting any device - * response. - * If available, device list will be obtained from MiniSSDPd. - * Default path for minissdpd socket will be used if minissdpdsock argument - * is NULL. - * If multicastif is not NULL, it will be used instead of the default - * multicast interface for sending SSDP discover packets. - * If 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. */ -MINIUPNP_LIBSPEC struct UPNPDev * -upnpDiscover(int delay, const char * multicastif, - const char * minissdpdsock, int sameport, - int ipv6, - int * error); - -MINIUPNP_LIBSPEC struct UPNPDev * -upnpDiscoverAll(int delay, const char * multicastif, - const char * minissdpdsock, int sameport, - int ipv6, - int * error); - -MINIUPNP_LIBSPEC struct UPNPDev * -upnpDiscoverDevice(const char * device, int delay, const char * multicastif, - const char * minissdpdsock, int sameport, - int ipv6, - int * error); - -MINIUPNP_LIBSPEC struct UPNPDev * -upnpDiscoverDevices(const char * const deviceTypes[], - int delay, const char * multicastif, - const char * minissdpdsock, int sameport, - int ipv6, - int * error, - int searchalltypes); - -/* freeUPNPDevlist() - * free list returned by upnpDiscover() */ -MINIUPNP_LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist); - -/* parserootdesc() : - * parse root XML description of a UPnP device and fill the IGDdatas - * structure. */ -MINIUPNP_LIBSPEC void parserootdesc(const char *, int, struct IGDdatas *); - -/* structure used to get fast access to urls - * controlURL: controlURL of the WANIPConnection - * ipcondescURL: url of the description of the WANIPConnection - * controlURL_CIF: controlURL of the WANCommonInterfaceConfig - * controlURL_6FC: controlURL of the WANIPv6FirewallControl - */ -struct UPNPUrls { - char * controlURL; - char * ipcondescURL; - char * controlURL_CIF; - char * controlURL_6FC; - char * rootdescURL; -}; - -/* UPNP_GetValidIGD() : - * return values : - * 0 = NO IGD found - * 1 = A valid connected IGD has been found - * 2 = A valid IGD has been found but it reported as - * not connected - * 3 = an UPnP device has been found but was not recognized as an IGD - * - * In any non zero return case, the urls and data structures - * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to - * free allocated memory. - */ -MINIUPNP_LIBSPEC int -UPNP_GetValidIGD(struct UPNPDev * devlist, - struct UPNPUrls * urls, - struct IGDdatas * data, - char * lanaddr, int lanaddrlen); - -/* UPNP_GetIGDFromUrl() - * Used when skipping the discovery process. - * When succeding, urls, data, and lanaddr arguments are set. - * return value : - * 0 - Not ok - * 1 - OK */ -MINIUPNP_LIBSPEC int -UPNP_GetIGDFromUrl(const char * rootdescurl, - struct UPNPUrls * urls, - struct IGDdatas * data, - char * lanaddr, int lanaddrlen); - -MINIUPNP_LIBSPEC void -GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, - const char *, unsigned int); - -MINIUPNP_LIBSPEC void -FreeUPNPUrls(struct UPNPUrls *); - -/* return 0 or 1 */ -MINIUPNP_LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *); - - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/ext/bin/miniupnpc/include/miniupnpc/miniupnpc_declspec.h b/ext/bin/miniupnpc/include/miniupnpc/miniupnpc_declspec.h deleted file mode 100644 index 40adb922..00000000 --- a/ext/bin/miniupnpc/include/miniupnpc/miniupnpc_declspec.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MINIUPNPC_DECLSPEC_H_INCLUDED -#define MINIUPNPC_DECLSPEC_H_INCLUDED - -#if defined(_WIN32) && !defined(MINIUPNP_STATICLIB) - /* for windows dll */ - #ifdef MINIUPNP_EXPORTS - #define MINIUPNP_LIBSPEC __declspec(dllexport) - #else - #define MINIUPNP_LIBSPEC __declspec(dllimport) - #endif -#else - #if defined(__GNUC__) && __GNUC__ >= 4 - /* fix dynlib for OS X 10.9.2 and Apple LLVM version 5.0 */ - #define MINIUPNP_LIBSPEC __attribute__ ((visibility ("default"))) - #else - #define MINIUPNP_LIBSPEC - #endif -#endif - -#endif /* MINIUPNPC_DECLSPEC_H_INCLUDED */ - diff --git a/ext/bin/miniupnpc/include/miniupnpc/miniupnpcstrings.h b/ext/bin/miniupnpc/include/miniupnpc/miniupnpcstrings.h deleted file mode 100644 index 80a1d757..00000000 --- a/ext/bin/miniupnpc/include/miniupnpc/miniupnpcstrings.h +++ /dev/null @@ -1,23 +0,0 @@ -/* $Id: miniupnpcstrings.h.in,v 1.6 2014/11/04 22:31:55 nanard Exp $ */ -/* Project: miniupnp - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author: Thomas Bernard - * Copyright (c) 2005-2014 Thomas Bernard - * This software is subjects to the conditions detailed - * in the LICENCE file provided within this distribution */ -#ifndef MINIUPNPCSTRINGS_H_INCLUDED -#define MINIUPNPCSTRINGS_H_INCLUDED - -#define OS_STRING "Darwin/14.4.0" -#define MINIUPNPC_VERSION_STRING "1.9" - -#if 0 -/* according to "UPnP Device Architecture 1.0" */ -#define UPNP_VERSION_STRING "UPnP/1.0" -#else -/* according to "UPnP Device Architecture 1.1" */ -#define UPNP_VERSION_STRING "UPnP/1.1" -#endif - -#endif - diff --git a/ext/bin/miniupnpc/include/miniupnpc/miniupnpctypes.h b/ext/bin/miniupnpc/include/miniupnpc/miniupnpctypes.h deleted file mode 100644 index 591c32fb..00000000 --- a/ext/bin/miniupnpc/include/miniupnpc/miniupnpctypes.h +++ /dev/null @@ -1,19 +0,0 @@ -/* $Id: miniupnpctypes.h,v 1.2 2012/09/27 15:42:10 nanard Exp $ */ -/* Miniupnp project : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org - * Author : Thomas Bernard - * Copyright (c) 2011 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided within this distribution */ -#ifndef MINIUPNPCTYPES_H_INCLUDED -#define MINIUPNPCTYPES_H_INCLUDED - -#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 - diff --git a/ext/bin/miniupnpc/include/miniupnpc/miniwget.h b/ext/bin/miniupnpc/include/miniupnpc/miniwget.h deleted file mode 100644 index d6db71a8..00000000 --- a/ext/bin/miniupnpc/include/miniupnpc/miniwget.h +++ /dev/null @@ -1,30 +0,0 @@ -/* $Id: miniwget.h,v 1.10 2015/07/21 13:16:55 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas Bernard - * Copyright (c) 2005-2015 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ -#ifndef MINIWGET_H_INCLUDED -#define MINIWGET_H_INCLUDED - -#include "miniupnpc_declspec.h" - -#ifdef __cplusplus -extern "C" { -#endif - -MINIUPNP_LIBSPEC void * getHTTPResponse(int s, int * size); - -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 *); - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/ext/bin/miniupnpc/include/miniupnpc/minixml.h b/ext/bin/miniupnpc/include/miniupnpc/minixml.h deleted file mode 100644 index 9f43aa48..00000000 --- a/ext/bin/miniupnpc/include/miniupnpc/minixml.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $Id: minixml.h,v 1.7 2012/09/27 15:42:10 nanard Exp $ */ -/* minimal xml parser - * - * Project : miniupnp - * Website : http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2005 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ -#ifndef MINIXML_H_INCLUDED -#define MINIXML_H_INCLUDED -#define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n')) - -/* if a callback function pointer is set to NULL, - * the function is not called */ -struct xmlparser { - const char *xmlstart; - const char *xmlend; - const char *xml; /* pointer to current character */ - int xmlsize; - void * data; - void (*starteltfunc) (void *, const char *, int); - void (*endeltfunc) (void *, const char *, int); - void (*datafunc) (void *, const char *, int); - void (*attfunc) (void *, const char *, int, const char *, int); -}; - -/* parsexml() - * the xmlparser structure must be initialized before the call - * the following structure members have to be initialized : - * xmlstart, xmlsize, data, *func - * xml is for internal usage, xmlend is computed automatically */ -void parsexml(struct xmlparser *); - -#endif - diff --git a/ext/bin/miniupnpc/include/miniupnpc/portlistingparse.h b/ext/bin/miniupnpc/include/miniupnpc/portlistingparse.h deleted file mode 100644 index 661ad1fa..00000000 --- a/ext/bin/miniupnpc/include/miniupnpc/portlistingparse.h +++ /dev/null @@ -1,65 +0,0 @@ -/* $Id: portlistingparse.h,v 1.11 2015/07/21 13:16:55 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2011-2015 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ -#ifndef PORTLISTINGPARSE_H_INCLUDED -#define PORTLISTINGPARSE_H_INCLUDED - -#include "miniupnpc_declspec.h" -/* for the definition of UNSIGNED_INTEGER */ -#include "miniupnpctypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* sample of PortMappingEntry : - - 202.233.2.1 - 2345 - TCP - 2345 - 192.168.1.137 - 1 - dooom - 345 - - */ -typedef enum { PortMappingEltNone, - PortMappingEntry, NewRemoteHost, - NewExternalPort, NewProtocol, - NewInternalPort, NewInternalClient, - NewEnabled, NewDescription, - NewLeaseTime } portMappingElt; - -struct PortMapping { - struct PortMapping * l_next; /* list next element */ - UNSIGNED_INTEGER leaseTime; - unsigned short externalPort; - unsigned short internalPort; - char remoteHost[64]; - char internalClient[64]; - char description[64]; - char protocol[4]; - unsigned char enabled; -}; - -struct PortMappingParserData { - struct PortMapping * l_head; /* list head */ - portMappingElt curelt; -}; - -MINIUPNP_LIBSPEC void -ParsePortListing(const char * buffer, int bufsize, - struct PortMappingParserData * pdata); - -MINIUPNP_LIBSPEC void -FreePortListing(struct PortMappingParserData * pdata); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ext/bin/miniupnpc/include/miniupnpc/receivedata.h b/ext/bin/miniupnpc/include/miniupnpc/receivedata.h deleted file mode 100644 index 0520a11d..00000000 --- a/ext/bin/miniupnpc/include/miniupnpc/receivedata.h +++ /dev/null @@ -1,19 +0,0 @@ -/* $Id: receivedata.h,v 1.4 2012/09/27 15:42:10 nanard Exp $ */ -/* Project: miniupnp - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author: Thomas Bernard - * Copyright (c) 2011-2012 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 - -/* Reads data from the specified socket. - * Returns the number of bytes read if successful, zero if no bytes were - * read or if we timed out. Returns negative if there was an error. */ -int receivedata(int socket, - char * data, int length, - int timeout, unsigned int * scope_id); - -#endif - diff --git a/ext/bin/miniupnpc/include/miniupnpc/upnpcommands.h b/ext/bin/miniupnpc/include/miniupnpc/upnpcommands.h deleted file mode 100644 index 22eda5e3..00000000 --- a/ext/bin/miniupnpc/include/miniupnpc/upnpcommands.h +++ /dev/null @@ -1,348 +0,0 @@ -/* $Id: upnpcommands.h,v 1.31 2015/07/21 13:16:55 nanard Exp $ */ -/* Miniupnp project : http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2005-2015 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided within this distribution */ -#ifndef UPNPCOMMANDS_H_INCLUDED -#define UPNPCOMMANDS_H_INCLUDED - -#include "upnpreplyparse.h" -#include "portlistingparse.h" -#include "miniupnpc_declspec.h" -#include "miniupnpctypes.h" - -/* MiniUPnPc return codes : */ -#define UPNPCOMMAND_SUCCESS (0) -#define UPNPCOMMAND_UNKNOWN_ERROR (-1) -#define UPNPCOMMAND_INVALID_ARGS (-2) -#define UPNPCOMMAND_HTTP_ERROR (-3) -#define UPNPCOMMAND_INVALID_RESPONSE (-4) -#define UPNPCOMMAND_MEM_ALLOC_ERROR (-5) - -#ifdef __cplusplus -extern "C" { -#endif - -MINIUPNP_LIBSPEC UNSIGNED_INTEGER -UPNP_GetTotalBytesSent(const char * controlURL, - const char * servicetype); - -MINIUPNP_LIBSPEC UNSIGNED_INTEGER -UPNP_GetTotalBytesReceived(const char * controlURL, - const char * servicetype); - -MINIUPNP_LIBSPEC UNSIGNED_INTEGER -UPNP_GetTotalPacketsSent(const char * controlURL, - const char * servicetype); - -MINIUPNP_LIBSPEC UNSIGNED_INTEGER -UPNP_GetTotalPacketsReceived(const char * controlURL, - const char * servicetype); - -/* UPNP_GetStatusInfo() - * status and lastconnerror are 64 byte buffers - * Return values : - * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error code */ -MINIUPNP_LIBSPEC int -UPNP_GetStatusInfo(const char * controlURL, - const char * servicetype, - char * status, - unsigned int * uptime, - char * lastconnerror); - -/* UPNP_GetConnectionTypeInfo() - * argument connectionType is a 64 character buffer - * Return Values : - * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error code */ -MINIUPNP_LIBSPEC int -UPNP_GetConnectionTypeInfo(const char * controlURL, - const char * servicetype, - char * connectionType); - -/* UPNP_GetExternalIPAddress() call the corresponding UPNP method. - * if the third arg is not null the value is copied to it. - * at least 16 bytes must be available - * - * Return values : - * 0 : SUCCESS - * NON ZERO : ERROR Either an UPnP error code or an unknown error. - * - * possible UPnP Errors : - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 501 Action Failed - See UPnP Device Architecture section on Control. */ -MINIUPNP_LIBSPEC int -UPNP_GetExternalIPAddress(const char * controlURL, - const char * servicetype, - char * extIpAdd); - -/* UPNP_GetLinkLayerMaxBitRates() - * call WANCommonInterfaceConfig:1#GetCommonLinkProperties - * - * return values : - * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error Code. */ -MINIUPNP_LIBSPEC int -UPNP_GetLinkLayerMaxBitRates(const char* controlURL, - const char* servicetype, - unsigned int * bitrateDown, - unsigned int * bitrateUp); - -/* UPNP_AddPortMapping() - * if desc is NULL, it will be defaulted to "libminiupnpc" - * remoteHost is usually NULL because IGD don't support it. - * - * Return values : - * 0 : SUCCESS - * NON ZERO : ERROR. Either an UPnP error code or an unknown error. - * - * List of possible UPnP errors for AddPortMapping : - * errorCode errorDescription (short) - Description (long) - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 501 Action Failed - See UPnP Device Architecture section on Control. - * 606 Action not authorized - The action requested REQUIRES authorization and - * the sender was not authorized. - * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be - * wild-carded - * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded - * 718 ConflictInMappingEntry - The port mapping entry specified conflicts - * with a mapping assigned previously to another client - * 724 SamePortValuesRequired - Internal and External port values - * must be the same - * 725 OnlyPermanentLeasesSupported - The NAT implementation only supports - * permanent lease times on port mappings - * 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard - * and cannot be a specific IP address or DNS name - * 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and - * cannot be a specific port value - * 728 NoPortMapsAvailable - There are not enough free ports available to - * complete port mapping. - * 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed - * due to conflict with other mechanisms. - * 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded - */ -MINIUPNP_LIBSPEC int -UPNP_AddPortMapping(const char * controlURL, const char * servicetype, - const char * extPort, - const char * inPort, - const char * inClient, - const char * desc, - const char * proto, - const char * remoteHost, - const char * leaseDuration); - -/* UPNP_AddAnyPortMapping() - * if desc is NULL, it will be defaulted to "libminiupnpc" - * remoteHost is usually NULL because IGD don't support it. - * - * Return values : - * 0 : SUCCESS - * NON ZERO : ERROR. Either an UPnP error code or an unknown error. - * - * List of possible UPnP errors for AddPortMapping : - * errorCode errorDescription (short) - Description (long) - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 501 Action Failed - See UPnP Device Architecture section on Control. - * 606 Action not authorized - The action requested REQUIRES authorization and - * the sender was not authorized. - * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be - * wild-carded - * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded - * 728 NoPortMapsAvailable - There are not enough free ports available to - * complete port mapping. - * 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed - * due to conflict with other mechanisms. - * 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded - */ -MINIUPNP_LIBSPEC int -UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype, - const char * extPort, - const char * inPort, - const char * inClient, - const char * desc, - const char * proto, - const char * remoteHost, - const char * leaseDuration, - char * reservedPort); - -/* UPNP_DeletePortMapping() - * Use same argument values as what was used for AddPortMapping(). - * remoteHost is usually NULL because IGD don't support it. - * Return Values : - * 0 : SUCCESS - * NON ZERO : error. Either an UPnP error code or an undefined error. - * - * List of possible UPnP errors for DeletePortMapping : - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 606 Action not authorized - The action requested REQUIRES authorization - * and the sender was not authorized. - * 714 NoSuchEntryInArray - The specified value does not exist in the array */ -MINIUPNP_LIBSPEC int -UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, - const char * extPort, const char * proto, - const char * remoteHost); - -/* UPNP_DeletePortRangeMapping() - * Use same argument values as what was used for AddPortMapping(). - * remoteHost is usually NULL because IGD don't support it. - * Return Values : - * 0 : SUCCESS - * NON ZERO : error. Either an UPnP error code or an undefined error. - * - * List of possible UPnP errors for DeletePortMapping : - * 606 Action not authorized - The action requested REQUIRES authorization - * and the sender was not authorized. - * 730 PortMappingNotFound - This error message is returned if no port - * mapping is found in the specified range. - * 733 InconsistentParameters - NewStartPort and NewEndPort values are not consistent. */ -MINIUPNP_LIBSPEC int -UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype, - const char * extPortStart, const char * extPortEnd, - const char * proto, - const char * manage); - -/* UPNP_GetPortMappingNumberOfEntries() - * not supported by all routers */ -MINIUPNP_LIBSPEC int -UPNP_GetPortMappingNumberOfEntries(const char* controlURL, - const char* servicetype, - unsigned int * num); - -/* UPNP_GetSpecificPortMappingEntry() - * retrieves an existing port mapping - * params : - * in extPort - * in proto - * in remoteHost - * out intClient (16 bytes) - * out intPort (6 bytes) - * out desc (80 bytes) - * out enabled (4 bytes) - * out leaseDuration (16 bytes) - * - * return value : - * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error Code. - * - * List of possible UPnP errors for _GetSpecificPortMappingEntry : - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 501 Action Failed - See UPnP Device Architecture section on Control. - * 606 Action not authorized - The action requested REQUIRES authorization - * and the sender was not authorized. - * 714 NoSuchEntryInArray - The specified value does not exist in the array. - */ -MINIUPNP_LIBSPEC int -UPNP_GetSpecificPortMappingEntry(const char * controlURL, - const char * servicetype, - const char * extPort, - const char * proto, - const char * remoteHost, - char * intClient, - char * intPort, - char * desc, - char * enabled, - char * leaseDuration); - -/* UPNP_GetGenericPortMappingEntry() - * params : - * in index - * out extPort (6 bytes) - * out intClient (16 bytes) - * out intPort (6 bytes) - * out protocol (4 bytes) - * out desc (80 bytes) - * out enabled (4 bytes) - * out rHost (64 bytes) - * out duration (16 bytes) - * - * return value : - * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error Code. - * - * Possible UPNP Error codes : - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 606 Action not authorized - The action requested REQUIRES authorization - * and the sender was not authorized. - * 713 SpecifiedArrayIndexInvalid - The specified array index is out of bounds - */ -MINIUPNP_LIBSPEC int -UPNP_GetGenericPortMappingEntry(const char * controlURL, - const char * servicetype, - const char * index, - char * extPort, - char * intClient, - char * intPort, - char * protocol, - char * desc, - char * enabled, - char * rHost, - char * duration); - -/* UPNP_GetListOfPortMappings() Available in IGD v2 - * - * - * Possible UPNP Error codes : - * 606 Action not Authorized - * 730 PortMappingNotFound - no port mapping is found in the specified range. - * 733 InconsistantParameters - NewStartPort and NewEndPort values are not - * consistent. - */ -MINIUPNP_LIBSPEC int -UPNP_GetListOfPortMappings(const char * controlURL, - const char * servicetype, - const char * startPort, - const char * endPort, - const char * protocol, - const char * numberOfPorts, - struct PortMappingParserData * data); - -/* IGD:2, functions for service WANIPv6FirewallControl:1 */ -MINIUPNP_LIBSPEC int -UPNP_GetFirewallStatus(const char * controlURL, - const char * servicetype, - int * firewallEnabled, - int * inboundPinholeAllowed); - -MINIUPNP_LIBSPEC int -UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype, - const char * remoteHost, - const char * remotePort, - const char * intClient, - const char * intPort, - const char * proto, - int * opTimeout); - -MINIUPNP_LIBSPEC int -UPNP_AddPinhole(const char * controlURL, const char * servicetype, - const char * remoteHost, - const char * remotePort, - const char * intClient, - const char * intPort, - const char * proto, - const char * leaseTime, - char * uniqueID); - -MINIUPNP_LIBSPEC int -UPNP_UpdatePinhole(const char * controlURL, const char * servicetype, - const char * uniqueID, - const char * leaseTime); - -MINIUPNP_LIBSPEC int -UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID); - -MINIUPNP_LIBSPEC int -UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype, - const char * uniqueID, int * isWorking); - -MINIUPNP_LIBSPEC int -UPNP_GetPinholePackets(const char * controlURL, const char * servicetype, - const char * uniqueID, int * packets); - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/ext/bin/miniupnpc/include/miniupnpc/upnperrors.h b/ext/bin/miniupnpc/include/miniupnpc/upnperrors.h deleted file mode 100644 index 3115aee5..00000000 --- a/ext/bin/miniupnpc/include/miniupnpc/upnperrors.h +++ /dev/null @@ -1,26 +0,0 @@ -/* $Id: upnperrors.h,v 1.6 2015/07/21 13:16:55 nanard Exp $ */ -/* (c) 2007-2015 Thomas Bernard - * All rights reserved. - * MiniUPnP Project. - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * This software is subjet to the conditions detailed in the - * provided LICENCE file. */ -#ifndef UPNPERRORS_H_INCLUDED -#define UPNPERRORS_H_INCLUDED - -#include "miniupnpc_declspec.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* strupnperror() - * Return a string description of the UPnP error code - * or NULL for undefinded errors */ -MINIUPNP_LIBSPEC const char * strupnperror(int err); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ext/bin/miniupnpc/include/miniupnpc/upnpreplyparse.h b/ext/bin/miniupnpc/include/miniupnpc/upnpreplyparse.h deleted file mode 100644 index 6badd15b..00000000 --- a/ext/bin/miniupnpc/include/miniupnpc/upnpreplyparse.h +++ /dev/null @@ -1,63 +0,0 @@ -/* $Id: upnpreplyparse.h,v 1.19 2014/10/27 16:33:19 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef UPNPREPLYPARSE_H_INCLUDED -#define UPNPREPLYPARSE_H_INCLUDED - -#ifdef __cplusplus -extern "C" { -#endif - -struct NameValue { - struct NameValue * l_next; - char name[64]; - char value[128]; -}; - -struct NameValueParserData { - struct NameValue * l_head; - char curelt[64]; - char * portListing; - int portListingLength; - int topelt; - const char * cdata; - int cdatalen; -}; - -/* ParseNameValue() */ -void -ParseNameValue(const char * buffer, int bufsize, - struct NameValueParserData * data); - -/* ClearNameValueList() */ -void -ClearNameValueList(struct NameValueParserData * pdata); - -/* GetValueFromNameValueList() */ -char * -GetValueFromNameValueList(struct NameValueParserData * pdata, - const char * Name); - -#if 0 -/* GetValueFromNameValueListIgnoreNS() */ -char * -GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, - const char * Name); -#endif - -/* DisplayNameValueList() */ -#ifdef DEBUG -void -DisplayNameValueList(char * buffer, int bufsize); -#endif - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/ext/bin/miniupnpc/windows-x64/miniupnpc.lib b/ext/bin/miniupnpc/windows-x64/miniupnpc.lib deleted file mode 100644 index e05fefc8..00000000 Binary files a/ext/bin/miniupnpc/windows-x64/miniupnpc.lib and /dev/null differ diff --git a/ext/bin/miniupnpc/windows-x86/miniupnpc.lib b/ext/bin/miniupnpc/windows-x86/miniupnpc.lib deleted file mode 100644 index a7fe4191..00000000 Binary files a/ext/bin/miniupnpc/windows-x86/miniupnpc.lib and /dev/null differ diff --git a/ext/installfiles/windows/ZeroTier One.aip b/ext/installfiles/windows/ZeroTier One.aip index 3042005e..8c3aa6bf 100644 --- a/ext/installfiles/windows/ZeroTier One.aip +++ b/ext/installfiles/windows/ZeroTier One.aip @@ -24,7 +24,7 @@ - + diff --git a/ext/miniupnpc/connecthostport.c b/ext/miniupnpc/connecthostport.c index 1f2a032e..854203e0 100644 --- a/ext/miniupnpc/connecthostport.c +++ b/ext/miniupnpc/connecthostport.c @@ -5,6 +5,8 @@ * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ +#define _CRT_SECURE_NO_WARNINGS + /* use getaddrinfo() or gethostbyname() * uncomment the following line in order to use gethostbyname() */ #ifdef NO_GETADDRINFO diff --git a/ext/miniupnpc/minisoap.c b/ext/miniupnpc/minisoap.c index 0b56558e..478bce6b 100644 --- a/ext/miniupnpc/minisoap.c +++ b/ext/miniupnpc/minisoap.c @@ -1,3 +1,4 @@ +#define _CRT_SECURE_NO_WARNINGS /* $Id: minisoap.c,v 1.24 2015/10/26 17:05:07 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard @@ -19,7 +20,13 @@ #include #endif #include "minisoap.h" +#ifdef _WIN32 +#define OS_STRING "Win32" +#define MINIUPNPC_VERSION_STRING "1.9" +#define UPNP_VERSION_STRING "UPnP/1.1" +#else #include "miniupnpcstrings.h" +#endif /* only for malloc */ #include diff --git a/ext/miniupnpc/minissdpc.c b/ext/miniupnpc/minissdpc.c index 5a426739..a371d161 100644 --- a/ext/miniupnpc/minissdpc.c +++ b/ext/miniupnpc/minissdpc.c @@ -1,3 +1,5 @@ +#define _CRT_SECURE_NO_WARNINGS + /* $Id: minissdpc.c,v 1.30 2015/10/26 17:05:07 nanard Exp $ */ /* Project : miniupnp * Web : http://miniupnp.free.fr/ diff --git a/ext/miniupnpc/miniupnpc.c b/ext/miniupnpc/miniupnpc.c index 4837fe7d..56638881 100644 --- a/ext/miniupnpc/miniupnpc.c +++ b/ext/miniupnpc/miniupnpc.c @@ -1,3 +1,4 @@ +#define _CRT_SECURE_NO_WARNINGS /* $Id: miniupnpc.c,v 1.141 2015/10/26 17:05:07 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab */ /* Project : miniupnp diff --git a/ext/miniupnpc/miniwget.c b/ext/miniupnpc/miniwget.c index 40aa7180..d0dd721b 100644 --- a/ext/miniupnpc/miniwget.c +++ b/ext/miniupnpc/miniwget.c @@ -1,3 +1,4 @@ +#define _CRT_SECURE_NO_WARNINGS /* $Id: miniwget.c,v 1.72 2015/10/26 17:05:08 nanard Exp $ */ /* Project : miniupnp * Website : http://miniupnp.free.fr/ @@ -49,7 +50,13 @@ #endif /* MIN */ +#ifdef _WIN32 +#define OS_STRING "Win32" +#define MINIUPNPC_VERSION_STRING "1.9" +#define UPNP_VERSION_STRING "UPnP/1.1" +#else #include "miniupnpcstrings.h" +#endif #include "miniwget.h" #include "connecthostport.h" #include "receivedata.h" diff --git a/ext/miniupnpc/minixml.c b/ext/miniupnpc/minixml.c index 3e201ec2..5c79b3c9 100644 --- a/ext/miniupnpc/minixml.c +++ b/ext/miniupnpc/minixml.c @@ -1,3 +1,4 @@ +#define _CRT_SECURE_NO_WARNINGS /* $Id: minixml.c,v 1.11 2014/02/03 15:54:12 nanard Exp $ */ /* minixml.c : the minimum size a xml parser can be ! */ /* Project : miniupnp diff --git a/ext/miniupnpc/minixmlvalid.c b/ext/miniupnpc/minixmlvalid.c index dad14881..a86beba8 100644 --- a/ext/miniupnpc/minixmlvalid.c +++ b/ext/miniupnpc/minixmlvalid.c @@ -1,3 +1,4 @@ +#define _CRT_SECURE_NO_WARNINGS /* $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/ diff --git a/ext/miniupnpc/upnpcommands.c b/ext/miniupnpc/upnpcommands.c index cabdb50d..660b5d9f 100644 --- a/ext/miniupnpc/upnpcommands.c +++ b/ext/miniupnpc/upnpcommands.c @@ -1,3 +1,4 @@ +#define _CRT_SECURE_NO_WARNINGS /* $Id: upnpcommands.c,v 1.46 2015/07/15 12:19:00 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard diff --git a/ext/miniupnpc/upnpreplyparse.c b/ext/miniupnpc/upnpreplyparse.c index 5de5796a..88d77a66 100644 --- a/ext/miniupnpc/upnpreplyparse.c +++ b/ext/miniupnpc/upnpreplyparse.c @@ -1,3 +1,4 @@ +#define _CRT_SECURE_NO_WARNINGS /* $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/ diff --git a/osdep/UPNPClient.cpp b/osdep/UPNPClient.cpp index 3193f507..b7c7e768 100644 --- a/osdep/UPNPClient.cpp +++ b/osdep/UPNPClient.cpp @@ -46,8 +46,8 @@ #endif #endif -#include "../ext/bin/miniupnpc/include/miniupnpc/miniupnpc.h" -#include "../ext/bin/miniupnpc/include/miniupnpc/upnpcommands.h" +#include "../ext/miniupnpc/miniupnpc.h" +#include "../ext/miniupnpc/upnpcommands.h" namespace ZeroTier { @@ -81,7 +81,7 @@ public: while (run) { { int upnpError = 0; - UPNPDev *devlist = upnpDiscover(2000,(const char *)0,(const char *)0,0,0,&upnpError); + UPNPDev *devlist = upnpDiscover(2000,(const char *)0,(const char *)0,0,0,0,&upnpError); if (devlist) { #ifdef ZT_UPNP_TRACE { diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj b/windows/ZeroTierOne/ZeroTierOne.vcxproj index 82b70400..5da01505 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj @@ -22,6 +22,19 @@ + + + + + + + + + + + + + @@ -79,6 +92,22 @@ + + + + + + + + + + + + + + + + @@ -214,11 +243,11 @@ true - NOMINMAX;ZT_TRACE;ZT_USE_MINIUPNPC;%(PreprocessorDefinitions) + NOMINMAX;ZT_TRACE;ZT_USE_MINIUPNPC;MINIUPNP_STATICLIB;%(PreprocessorDefinitions) true - $(SolutionDir)..\ext\bin\miniupnpc\windows-x86\miniupnpc.lib;wsock32.lib;ws2_32.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies) + wsock32.lib;ws2_32.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies) false @@ -229,12 +258,12 @@ true - NOMINMAX;ZT_TRACE;ZT_USE_MINIUPNPC;%(PreprocessorDefinitions) + NOMINMAX;ZT_TRACE;ZT_USE_MINIUPNPC;MINIUPNP_STATICLIB;%(PreprocessorDefinitions) false true - $(SolutionDir)..\ext\bin\miniupnpc\windows-x64\miniupnpc.lib;wsock32.lib;ws2_32.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies) + wsock32.lib;ws2_32.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies) false @@ -247,7 +276,7 @@ true - ZT_OFFICIAL_RELEASE;ZT_AUTO_UPDATE;ZT_SALSA20_SSE;ZT_USE_MINIUPNPC;NOMINMAX;%(PreprocessorDefinitions) + ZT_OFFICIAL_RELEASE;ZT_AUTO_UPDATE;ZT_SALSA20_SSE;ZT_USE_MINIUPNPC;MINIUPNP_STATICLIB;NOMINMAX;%(PreprocessorDefinitions) MultiThreaded NoExtensions true @@ -259,7 +288,7 @@ true true true - $(SolutionDir)..\ext\bin\miniupnpc\windows-x86\miniupnpc.lib;wsock32.lib;ws2_32.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies) + wsock32.lib;ws2_32.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies) false @@ -272,7 +301,7 @@ true - ZT_OFFICIAL_RELEASE;ZT_AUTO_UPDATE;ZT_SALSA20_SSE;ZT_USE_MINIUPNPC;NOMINMAX;%(PreprocessorDefinitions) + ZT_OFFICIAL_RELEASE;ZT_AUTO_UPDATE;ZT_SALSA20_SSE;ZT_USE_MINIUPNPC;MINIUPNP_STATICLIB;NOMINMAX;%(PreprocessorDefinitions) MultiThreaded NotSet true @@ -284,7 +313,7 @@ true true true - $(SolutionDir)..\ext\bin\miniupnpc\windows-x64\miniupnpc.lib;wsock32.lib;ws2_32.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies) + wsock32.lib;ws2_32.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies) false diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters index 5a2767e4..6475137c 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters @@ -79,6 +79,12 @@ {1a47071e-e51b-4535-89ae-858946f03118} + + {5423fb64-896b-432e-a19d-88d4467f89f9} + + + {56cc3ab8-3336-4a22-9471-c267ee46cd54} + @@ -192,6 +198,45 @@ Source Files\node + + Source Files\ext\miniupnpc + + + Source Files\ext\miniupnpc + + + Source Files\ext\miniupnpc + + + Source Files\ext\miniupnpc + + + Source Files\ext\miniupnpc + + + Source Files\ext\miniupnpc + + + Source Files\ext\miniupnpc + + + Source Files\ext\miniupnpc + + + Source Files\ext\miniupnpc + + + Source Files\ext\miniupnpc + + + Source Files\ext\miniupnpc + + + Source Files\ext\miniupnpc + + + Source Files\ext\miniupnpc + @@ -422,6 +467,54 @@ Header Files\node + + Header Files\ext\miniupnpc + + + Header Files\ext\miniupnpc + + + Header Files\ext\miniupnpc + + + Header Files\ext\miniupnpc + + + Header Files\ext\miniupnpc + + + Header Files\ext\miniupnpc + + + Header Files\ext\miniupnpc + + + Header Files\ext\miniupnpc + + + Header Files\ext\miniupnpc + + + Header Files\ext\miniupnpc + + + Header Files\ext\miniupnpc + + + Header Files\ext\miniupnpc + + + Header Files\ext\miniupnpc + + + Header Files\ext\miniupnpc + + + Header Files\ext\miniupnpc + + + Header Files\ext\miniupnpc + -- cgit v1.2.3 From 48745eca571a87558a4a0a3741ffa106a6ae14bf Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 16 Nov 2015 19:54:58 -0800 Subject: Fix ARM dpkg build. --- ext/installfiles/linux/buildinstaller.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext') diff --git a/ext/installfiles/linux/buildinstaller.sh b/ext/installfiles/linux/buildinstaller.sh index 4f661b8d..1f6f8935 100755 --- a/ext/installfiles/linux/buildinstaller.sh +++ b/ext/installfiles/linux/buildinstaller.sh @@ -41,7 +41,7 @@ case "$system" in machine="x64" debian_arch="amd64" ;; - armv6l|arm|armhf) + armv6l|arm|armhf|arm7l|armv7l) machine="armv6l" debian_arch="armhf" ;; -- cgit v1.2.3 From 1c0c3e62dceb96b9dc67b7aadae2a495adde3c7d Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 17 Nov 2015 11:13:44 -0800 Subject: Just add a launch prerequisite for .NET 4.5 -- it's usually there, and if not it can be easily installed. This is mostly an issue on old Windows Server systems, and in that case the admin will likely want to decide how to proceed. --- ext/installfiles/windows/ZeroTier One.aip | 10 +++++----- ext/installfiles/windows/dotNetFx45_Full_setup.exe | Bin 1005568 -> 0 bytes 2 files changed, 5 insertions(+), 5 deletions(-) delete mode 100644 ext/installfiles/windows/dotNetFx45_Full_setup.exe (limited to 'ext') diff --git a/ext/installfiles/windows/ZeroTier One.aip b/ext/installfiles/windows/ZeroTier One.aip index 8c3aa6bf..147094f9 100644 --- a/ext/installfiles/windows/ZeroTier One.aip +++ b/ext/installfiles/windows/ZeroTier One.aip @@ -9,6 +9,8 @@ + + @@ -24,7 +26,7 @@ - + @@ -42,7 +44,7 @@ - + @@ -150,7 +152,6 @@ - @@ -231,7 +232,6 @@ - @@ -260,7 +260,6 @@ - @@ -276,6 +275,7 @@ + diff --git a/ext/installfiles/windows/dotNetFx45_Full_setup.exe b/ext/installfiles/windows/dotNetFx45_Full_setup.exe deleted file mode 100644 index 365b870b..00000000 Binary files a/ext/installfiles/windows/dotNetFx45_Full_setup.exe and /dev/null differ -- cgit v1.2.3 From 6f16f4443833917f9c70de924c818431b1ec64da Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 17 Nov 2015 11:19:58 -0800 Subject: VERSION 1.1.0: Win/Mac UI improvements, improved NAT-t, CIRCUIT_TEST, and more! ZeroTier 1.1.0 introduces a number of fixes and improvements in several areas. We incremented the secondary version to indicate the significance of this release. Version numbering has been a bit ad-hoc in the past. In future versions we will adopt the following scheme: odd-numbered revision numbers like 1.1.1 will indicate development versions, while even numbered ones like 1.1.2 will indicate tagged releases. The public git repo branching has also been revised: master will always be the latest tagged release, dev will be usually-working development, and edge will host maybe-broken "bleeding edge" development. Pull requests on GitHub should generally be made against dev, not master or edge. Other branches that may appear from time to time may be feature or experimental branches. Only master is confirmed good, with dev usually being okay but not guaranteed to be such. (To the extent that any software is ever guaranteed to be anything.) Change summary: User-facing changes and improvements: - Windows now has a new .NET-based native UI, which replaces the old WebControl wrapper around the React UI. This just didn't work well on older Windows systems, and we did not want to bundle 40+ megabytes of web browser with our app just for its very simple UI. - The web UI (still used for Mac and usable in Linux as well) is updated with improved look and simplifications. - Both UIs no longer have the "Peers" tab, since several users reported that non- technical users found this confusing and even alarming (does this mean people can access my system?). This information is visibile with "listpeers" from the command line (zerotier-cli). New features: - Virtual networks that use our RFC4193-based IPv6 numbering scheme now emulate IPv6 NDP for queries that target these addresses within the same network. This allows for faster multicast-free connection init and improved security since the address is now hard-wired to the device ID (which is a crypto token). This does not affect IPv6 NDP for other IPv6 addresses or link-local, which will continue to work normally. This also opens the potential for a reduced footprint multicast-free build for embedded applications. - This version includes beta support for a feature called CIRCUIT_TEST. Network controllers for networks you have joined can now send a special message called CIRCUIT_TEST which allows for ZeroTier-layer link testing and remote diagnosis of link issues. Any operator of a network controller can do this; more documentation will be forthcoming. The only information that may be gathered in this way is IP addressing info and very basic system info (OS, 32/64 bit, ZeroTier version). No personal information, hard drive data, location, or other private info is available. This can only be ordered by a controller of a network you have joined and is secured using cryptographic signatures. - This version includes an alpha version of clustering a.k.a. multi-homing! This powerful feature allows for a single ZeroTier device to be run from multiple endpoints, with connecting peers being handed off to endpoints that are closer via GeoIP lookup and/or are more lightly loaded. Currently this is only suitable for use in our soon-to-be-upgraded root server infrastructure (details will be blogged soon), but in the future it will be capable of hosting multi-homed devices on user networks. This will allow things like (for example) a geo- clustered Cassandra server that appears behind a single IP on a virtual LAN. This feature must be enabled with the ZT_ENABLE_CLUSTER=1 build option. Bug fixes and other improvements (including performance!): - A faster version of the Poly1305 cryptographic MAC function was substituted for sometimes greatly improved performance. - C++ STL std::map was replaced throughout the entire core with a hand-rolled Hashtable implementation for improved performance and in some cases a reduced memory footprint. Some maps are still used in peripheral code that is not performance critical or where ordered keys are needed. - The zerotier-cli and zerotier-idtool symbolic links are now created in /usr/local/bin on OSX to comply with El Capitan file security restrictions. - The OSX tap device driver has been updated. This update may fix issues that some users have reported with bridging on OSX. This new tap device driver drops 32-bit support, but if you have a 32-bit system you can manually install the old driver from ext/bin/tap-mac. - Mac users could experience a problem with the UI if they installed ZeroTier, then uninstalled it, then installed again. This is now fixed. - UPnP port mappings should work better on some routers, and a different local port is now used for UPnP mapped traffic vs. NAT-t'd traffic to get around a bug in several popular mid-tier routers where using UPnP mapping alongside traditional NAT traversal made a port unreachable. - Debian package now builds with the right arch label on armv7l systems (Pi 2) - The old "root topology" has been replaced with a similar but better thought out concept called a World. The World defines the root servers and possibly in the future other things, and can be updated in-band from trusted peers allowing for software-upgrade-free network upgrades to keep up with growing demand. See node/World.hpp for details. - A fix was made to "self-awareness," which keeps track of your external IP info and adapts to changes, to eliminate a problem that could cause "link thrashing" behind some symmetric NATs. - Escalating UDP TTLs was re-introduced to better transit some port-restricted cone NATs such as Linux IP MASQ (used for Docker). - An otherwise harmless crash-on-exit bug in the network controller was fixed. - All new direct links are now confirmed in both directions. This adds a very small amount of initial HELLO/OK traffic but fixes some edge cases where an incomplete or unidirectional path might be used. - [SECURITY] Better rate limiting was put in place for VERB_PUSH_DIRECT_PATHS to prevent potential abuse for amplification attacks. - [SECURITY] Build flags were tweaked on OSX to ensure that all code including dependency libraries are built with full stack canary protection and ASLR support. Visit https://www.zerotier.com/blog or follow @ZeroTier on Twitter for updates and announcements! --- ext/installfiles/mac/postinst.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'ext') diff --git a/ext/installfiles/mac/postinst.sh b/ext/installfiles/mac/postinst.sh index 47d9ddd9..da15f9c8 100755 --- a/ext/installfiles/mac/postinst.sh +++ b/ext/installfiles/mac/postinst.sh @@ -2,9 +2,26 @@ export PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin +OSX_RELEASE=`sw_vers -productVersion | cut -d . -f 1,2` + launchctl unload /Library/LaunchDaemons/com.zerotier.one.plist >>/dev/null 2>&1 +sleep 1 cd "/Library/Application Support/ZeroTier/One" + +if [ "$OSX_RELEASE" = "10.7" ]; then + # OSX 10.7 cannot use the new tap driver since the new way of kext signing + # is not backward compatible. Pull the old one for 10.7 users and replace. + # We use https to fetch and check hash as an extra added measure. + rm -f tap.kext.10_7.tar.gz + curl -s https://download.zerotier.com/tap.kext.10_7.tar.gz >tap.kext.10_7.tar.gz + if [ -s tap.kext.10_7.tar.gz -a "`shasum -a 256 tap.kext.10_7.tar.gz | cut -d ' ' -f 1`" = "e133d4832cef571621d3618f417381b44f51a76ed625089fb4e545e65d3ef2a9" ]; then + rm -rf tap.kext + tar -xzf tap.kext.10_7.tar.gz + fi + rm -f tap.kext.10_7.tar.gz +fi + rm -rf node.log node.log.old root-topology shutdownIfUnreadable autoupdate.log updates.d chown -R 0 tap.kext chgrp -R 0 tap.kext -- cgit v1.2.3