36 changed files with 3703 additions and 245 deletions
@ -0,0 +1,98 @@
|
||||
$Id: Changelog.txt,v 1.33 2013/11/26 08:47:36 nanard Exp $ |
||||
|
||||
2013/11/26: |
||||
enforce strict aliasing rules. |
||||
|
||||
2013/09/10: |
||||
small patch for MSVC >= 16 |
||||
rename win32 implementation of gettimeofday() to natpmp_gettimeofday() |
||||
|
||||
2012/08/21: |
||||
Little change in Makefile |
||||
removed warnings in testgetgateway.c |
||||
Fixed bugs in command line argumentparsing in natpmpc.c |
||||
|
||||
2011/08/07: |
||||
Patch to build on debian/kFreeBSD. |
||||
|
||||
2011/07/15: |
||||
Put 3 clauses BSD licence at the top of source files. |
||||
|
||||
2011/06/18: |
||||
--no-undefined => -Wl,--no-undefined |
||||
adding a natpmpc.1 man page |
||||
|
||||
2011/05/19: |
||||
Small fix in libnatpmpmodule.c thanks to Manuel Mausz |
||||
|
||||
2011/01/03: |
||||
Added an argument to initnatpmp() in order to force the gateway to be used |
||||
|
||||
2011/01/01: |
||||
fix in make install |
||||
|
||||
2010/05/21: |
||||
make install now working under MacOSX (and BSD) |
||||
|
||||
2010/04/12: |
||||
cplusplus stuff in natpmp.h |
||||
|
||||
2010/02/02: |
||||
Fixed compilation under Mac OS X |
||||
|
||||
2009/12/19: |
||||
improve and fix building under Windows. |
||||
Project files for MS Visual Studio 2008 |
||||
More simple (and working) code for Win32. |
||||
More checks in the /proc/net/route parsing. Add some comments. |
||||
|
||||
2009/08/04: |
||||
improving getgateway.c for windows |
||||
|
||||
2009/07/13: |
||||
Adding Haiku code in getgateway.c |
||||
|
||||
2009/06/04: |
||||
Adding Python module thanks to David Wu |
||||
|
||||
2009/03/10: |
||||
Trying to have windows get gateway working if not using DHCP |
||||
|
||||
2009/02/27: |
||||
dont include declspec.h if not under WIN32. |
||||
|
||||
2009/01/23: |
||||
Prefixed the libraries name with lib |
||||
|
||||
2008/10/06: |
||||
Fixed a memory leak in getdefaultgateway() (USE_SYSCTL_NET_ROUTE) |
||||
|
||||
2008/07/03: |
||||
Adding WIN32 code from Robbie Hanson |
||||
|
||||
2008/06/30: |
||||
added a Solaris implementation for getgateway(). |
||||
added a LICENCE file to the distribution |
||||
|
||||
2008/05/29: |
||||
Anonymous unions are forbidden in ANSI C. That was causing problems with |
||||
non-GCC compilers. |
||||
|
||||
2008/04/28: |
||||
introduced strnatpmperr() |
||||
improved natpmpc.c sample |
||||
make install now install the binary |
||||
|
||||
2007/12/13: |
||||
Fixed getgateway.c for working under OS X ;) |
||||
Fixed values for NATPMP_PROTOCOL_TCP and NATPMP_PROTOCOL_UDP |
||||
|
||||
2007/12/11: |
||||
Fixed getgateway.c for compilation under Mac OS X |
||||
|
||||
2007/12/01: |
||||
added some comments in .h |
||||
|
||||
2007/11/30: |
||||
implemented almost everything |
||||
|
||||
@ -0,0 +1,42 @@
|
||||
import java.net.InetAddress; |
||||
import java.net.UnknownHostException; |
||||
import java.nio.ByteBuffer; |
||||
|
||||
import fr.free.miniupnp.libnatpmp.NatPmp; |
||||
import fr.free.miniupnp.libnatpmp.NatPmpResponse; |
||||
|
||||
class JavaTest { |
||||
public static void main(String[] args) { |
||||
NatPmp natpmp = new NatPmp(); |
||||
|
||||
natpmp.sendPublicAddressRequest(); |
||||
NatPmpResponse response = new NatPmpResponse(); |
||||
|
||||
int result = -1; |
||||
do{ |
||||
result = natpmp.readNatPmpResponseOrRetry(response); |
||||
try { |
||||
Thread.sleep(4000); |
||||
} catch (InterruptedException e) { |
||||
//fallthrough
|
||||
} |
||||
} while (result != 0); |
||||
|
||||
byte[] bytes = intToByteArray(response.addr); |
||||
|
||||
try { |
||||
InetAddress inetAddress = InetAddress.getByAddress(bytes); |
||||
System.out.println("Public address is " + inetAddress); |
||||
} catch (UnknownHostException e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
} |
||||
|
||||
public static final byte[] intToByteArray(int value) { |
||||
return new byte[] { |
||||
(byte)value, |
||||
(byte)(value >>> 8), |
||||
(byte)(value >>> 16), |
||||
(byte)(value >>> 24)}; |
||||
} |
||||
} |
||||
@ -0,0 +1,26 @@
|
||||
Copyright (c) 2007-2011, 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. |
||||
|
||||
@ -0,0 +1,177 @@
|
||||
# $Id: Makefile,v 1.23 2013/11/26 16:38:15 nanard Exp $
|
||||
# This Makefile is designed for use with GNU make
|
||||
# libnatpmp
|
||||
# (c) 2007-2013 Thomas Bernard
|
||||
# http://miniupnp.free.fr/libnatpmp.html
|
||||
|
||||
OS = $(shell uname -s)
|
||||
CC = gcc
|
||||
INSTALL = install -p
|
||||
ARCH = $(shell uname -m | sed -e s/i.86/i686/)
|
||||
VERSION = $(shell cat VERSION)
|
||||
|
||||
ifeq ($(OS), Darwin) |
||||
JARSUFFIX=mac
|
||||
endif |
||||
ifeq ($(OS), Linux) |
||||
JARSUFFIX=linux
|
||||
endif |
||||
ifneq (,$(findstring WIN,$(OS))) |
||||
JARSUFFIX=win32
|
||||
endif |
||||
|
||||
# APIVERSION is used in soname
|
||||
APIVERSION = 1
|
||||
#LDFLAGS = -Wl,--no-undefined
|
||||
CFLAGS ?= -Os
|
||||
#CFLAGS = -g -O0
|
||||
CFLAGS += -fPIC
|
||||
CFLAGS += -Wall
|
||||
#CFLAGS += -Wextra
|
||||
CFLAGS += -DENABLE_STRNATPMPERR
|
||||
#CFLAGS += -Wstrict-aliasing
|
||||
|
||||
LIBOBJS = natpmp.o getgateway.o
|
||||
|
||||
OBJS = $(LIBOBJS) testgetgateway.o natpmpc.o natpmp-jni.o
|
||||
|
||||
STATICLIB = libnatpmp.a
|
||||
ifeq ($(OS), Darwin) |
||||
SHAREDLIB = libnatpmp.dylib
|
||||
JNISHAREDLIB = libjninatpmp.dylib
|
||||
SONAME = $(basename $(SHAREDLIB)).$(APIVERSION).dylib
|
||||
CFLAGS := -DMACOSX -D_DARWIN_C_SOURCE $(CFLAGS)
|
||||
SONAMEFLAGS=-Wl,-install_name,$(JNISHAREDLIB) -dynamiclib -framework JavaVM
|
||||
else |
||||
ifneq (,$(findstring WIN,$(OS))) |
||||
SHAREDLIB = natpmp.dll
|
||||
JNISHAREDLIB = jninatpmp.dll
|
||||
CC = i686-w64-mingw32-gcc
|
||||
EXTRA_LD = -lws2_32 -lIphlpapi -Wl,--no-undefined -Wl,--enable-runtime-pseudo-reloc --Wl,kill-at
|
||||
else |
||||
SHAREDLIB = libnatpmp.so
|
||||
JNISHAREDLIB = libjninatpmp.so
|
||||
SONAME = $(SHAREDLIB).$(APIVERSION)
|
||||
SONAMEFLAGS=-Wl,-soname,$(JNISHAREDLIB)
|
||||
endif |
||||
endif |
||||
|
||||
HEADERS = natpmp.h
|
||||
|
||||
EXECUTABLES = testgetgateway natpmpc-shared natpmpc-static
|
||||
|
||||
INSTALLPREFIX ?= $(PREFIX)/usr
|
||||
INSTALLDIRINC = $(INSTALLPREFIX)/include
|
||||
INSTALLDIRLIB = $(INSTALLPREFIX)/lib
|
||||
INSTALLDIRBIN = $(INSTALLPREFIX)/bin
|
||||
|
||||
JAVA ?= java
|
||||
JAVAC ?= javac
|
||||
JAVAH ?= javah
|
||||
JAVAPACKAGE = fr/free/miniupnp/libnatpmp
|
||||
JAVACLASSES = $(JAVAPACKAGE)/NatPmp.class $(JAVAPACKAGE)/NatPmpResponse.class $(JAVAPACKAGE)/LibraryExtractor.class $(JAVAPACKAGE)/URLUtils.class
|
||||
JNIHEADERS = fr_free_miniupnp_libnatpmp_NatPmp.h
|
||||
|
||||
.PHONY: all clean depend install cleaninstall installpythonmodule |
||||
|
||||
all: $(STATICLIB) $(SHAREDLIB) $(EXECUTABLES) |
||||
|
||||
pythonmodule: $(STATICLIB) libnatpmpmodule.c setup.py |
||||
python setup.py build
|
||||
touch $@
|
||||
|
||||
installpythonmodule: pythonmodule |
||||
python setup.py install
|
||||
|
||||
clean: |
||||
$(RM) $(OBJS) $(EXECUTABLES) $(STATICLIB) $(SHAREDLIB) $(JAVACLASSES) $(JNISHAREDLIB)
|
||||
$(RM) pythonmodule
|
||||
$(RM) -r build/ dist/ libraries/
|
||||
|
||||
depend: |
||||
makedepend -f$(MAKEFILE_LIST) -Y $(OBJS:.o=.c) 2>/dev/null
|
||||
|
||||
install: $(HEADERS) $(STATICLIB) $(SHAREDLIB) natpmpc-shared |
||||
$(INSTALL) -d $(INSTALLDIRINC)
|
||||
$(INSTALL) -m 644 $(HEADERS) $(INSTALLDIRINC)
|
||||
$(INSTALL) -d $(INSTALLDIRLIB)
|
||||
$(INSTALL) -m 644 $(STATICLIB) $(INSTALLDIRLIB)
|
||||
$(INSTALL) -m 644 $(SHAREDLIB) $(INSTALLDIRLIB)/$(SONAME)
|
||||
$(INSTALL) -d $(INSTALLDIRBIN)
|
||||
$(INSTALL) -m 755 natpmpc-shared $(INSTALLDIRBIN)/natpmpc
|
||||
ln -s -f $(SONAME) $(INSTALLDIRLIB)/$(SHAREDLIB)
|
||||
|
||||
$(JNIHEADERS): fr/free/miniupnp/libnatpmp/NatPmp.class |
||||
$(JAVAH) -jni fr.free.miniupnp.libnatpmp.NatPmp
|
||||
|
||||
%.class: %.java |
||||
$(JAVAC) -cp . $<
|
||||
|
||||
$(JNISHAREDLIB): $(SHAREDLIB) $(JNIHEADERS) $(JAVACLASSES) |
||||
ifeq (,$(JAVA_HOME)) |
||||
@echo "Check your JAVA_HOME environement variable" && false
|
||||
endif |
||||
ifneq (,$(findstring WIN,$(OS))) |
||||
$(CC) -m32 -D_JNI_Implementation_ -Wl,--kill-at \
|
||||
-I"$(JAVA_HOME)/include" -I"$(JAVA_HOME)/include/win32" \
|
||||
natpmp-jni.c -shared \
|
||||
-o $(JNISHAREDLIB) -L. -lnatpmp -lws2_32 -lIphlpapi
|
||||
else |
||||
$(CC) $(CFLAGS) -c -I"$(JAVA_HOME)/include" -I"$(JAVA_HOME)/include/win32" natpmp-jni.c
|
||||
$(CC) $(CFLAGS) -o $(JNISHAREDLIB) -shared $(SONAMEFLAGS) natpmp-jni.o -lc -L. -lnatpmp
|
||||
endif |
||||
|
||||
jar: $(JNISHAREDLIB) |
||||
find fr -name '*.class' -print > classes.list
|
||||
$(eval JNISHAREDLIBPATH := $(shell java fr.free.miniupnp.libnatpmp.LibraryExtractor))
|
||||
mkdir -p libraries/$(JNISHAREDLIBPATH)
|
||||
mv $(JNISHAREDLIB) libraries/$(JNISHAREDLIBPATH)/$(JNISHAREDLIB)
|
||||
jar cf natpmp_$(JARSUFFIX).jar @classes.list libraries/$(JNISHAREDLIBPATH)/$(JNISHAREDLIB)
|
||||
$(RM) classes.list
|
||||
|
||||
jnitest: $(JNISHAREDLIB) JavaTest.class |
||||
$(RM) libjninatpmp.so
|
||||
$(JAVA) -Djna.nosys=true -cp . JavaTest
|
||||
|
||||
mvn_install: |
||||
mvn install:install-file -Dfile=java/natpmp_$(JARSUFFIX).jar \
|
||||
-DgroupId=com.github \
|
||||
-DartifactId=natpmp \
|
||||
-Dversion=$(VERSION) \
|
||||
-Dpackaging=jar \
|
||||
-Dclassifier=$(JARSUFFIX) \
|
||||
-DgeneratePom=true \
|
||||
-DcreateChecksum=true
|
||||
|
||||
cleaninstall: |
||||
$(RM) $(addprefix $(INSTALLDIRINC), $(HEADERS))
|
||||
$(RM) $(INSTALLDIRLIB)/$(SONAME)
|
||||
$(RM) $(INSTALLDIRLIB)/$(SHAREDLIB)
|
||||
$(RM) $(INSTALLDIRLIB)/$(STATICLIB)
|
||||
|
||||
testgetgateway: testgetgateway.o getgateway.o |
||||
$(CC) $(LDFLAGS) -o $@ $^ $(EXTRA_LD)
|
||||
|
||||
natpmpc-static: natpmpc.o $(STATICLIB) |
||||
$(CC) $(LDFLAGS) -o $@ $^ $(EXTRA_LD)
|
||||
|
||||
natpmpc-shared: natpmpc.o $(SHAREDLIB) |
||||
$(CC) $(LDFLAGS) -o $@ $^ $(EXTRA_LD)
|
||||
|
||||
$(STATICLIB): $(LIBOBJS) |
||||
$(AR) crs $@ $?
|
||||
|
||||
$(SHAREDLIB): $(LIBOBJS) |
||||
ifeq ($(OS), Darwin) |
||||
$(CC) -dynamiclib -Wl,-install_name,$(SONAME) -o $@ $^
|
||||
else |
||||
$(CC) -shared -Wl,-soname,$(SONAME) -o $@ $^ $(EXTRA_LD)
|
||||
endif |
||||
|
||||
|
||||
# DO NOT DELETE
|
||||
|
||||
natpmp.o: natpmp.h getgateway.h declspec.h |
||||
getgateway.o: getgateway.h declspec.h |
||||
testgetgateway.o: getgateway.h declspec.h |
||||
natpmpc.o: natpmp.h |
||||
@ -0,0 +1,7 @@
|
||||
libnatpmp (c) 2007-2009 Thomas Bernard |
||||
contact : miniupnp@free.fr |
||||
|
||||
see http://miniupnp.free.fr/libnatpmp.html |
||||
or http://miniupnp.tuxfamily.org/libnatpmp.html |
||||
for some documentation and code samples. |
||||
|
||||
@ -0,0 +1,30 @@
|
||||
@echo Compiling with MinGW |
||||
@SET LIBS=-lws2_32 -liphlpapi |
||||
|
||||
@echo Compile getgateway |
||||
gcc -c -Wall -Os -DWIN32 -DSTATICLIB -DENABLE_STRNATPMPERR getgateway.c |
||||
gcc -c -Wall -Os -DWIN32 -DSTATICLIB -DENABLE_STRNATPMPERR testgetgateway.c |
||||
gcc -o testgetgateway getgateway.o testgetgateway.o %LIBS% |
||||
del testgetgateway.o |
||||
|
||||
@echo Compile natpmp-static: |
||||
gcc -c -Wall -Os -DWIN32 -DSTATICLIB -DENABLE_STRNATPMPERR getgateway.c |
||||
gcc -c -Wall -Os -DWIN32 -DSTATICLIB -DENABLE_STRNATPMPERR natpmp.c |
||||
gcc -c -Wall -Os -DWIN32 wingettimeofday.c |
||||
ar cr natpmp.a getgateway.o natpmp.o wingettimeofday.o |
||||
del getgateway.o natpmp.o |
||||
gcc -c -Wall -Os -DWIN32 -DSTATICLIB -DENABLE_STRNATPMPERR natpmpc.c |
||||
gcc -o natpmpc-static natpmpc.o natpmp.a %LIBS% |
||||
upx --best natpmpc-static.exe |
||||
del natpmpc.o |
||||
|
||||
@echo Create natpmp.dll: |
||||
gcc -c -Wall -Os -DWIN32 -DENABLE_STRNATPMPERR -DNATPMP_EXPORTS getgateway.c |
||||
gcc -c -Wall -Os -DWIN32 -DENABLE_STRNATPMPERR -DNATPMP_EXPORTS natpmp.c |
||||
dllwrap -k --driver-name gcc --def natpmp.def --output-def natpmp.dll.def --implib natpmp.lib -o natpmp.dll getgateway.o natpmp.o wingettimeofday.o %LIBS% |
||||
|
||||
@echo Compile natpmp-shared: |
||||
gcc -c -Wall -Os -DWIN32 -DENABLE_STRNATPMPERR -DNATPMP_EXPORTS natpmpc.c |
||||
gcc -o natpmpc-shared natpmpc.o natpmp.lib -lws2_32 |
||||
upx --best natpmpc-shared.exe |
||||
del *.o |
||||
@ -0,0 +1,21 @@
|
||||
#ifndef DECLSPEC_H_INCLUDED |
||||
#define DECLSPEC_H_INCLUDED |
||||
|
||||
#if defined(WIN32) && !defined(STATICLIB) |
||||
/* for windows dll */ |
||||
#ifdef NATPMP_EXPORTS |
||||
#define LIBSPEC __declspec(dllexport) |
||||
#else |
||||
#define 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 LIBSPEC __attribute__ ((visibility ("default"))) |
||||
#else |
||||
#define LIBSPEC |
||||
#endif |
||||
#endif |
||||
|
||||
#endif |
||||
|
||||
@ -0,0 +1,238 @@
|
||||
package fr.free.miniupnp.libnatpmp; |
||||
|
||||
/** I (Leah X Schmidt) copied this code from jnaerator, because |
||||
JNAerator's extractor requires you to buy into the whole JNA |
||||
concept. |
||||
|
||||
JNAErator is |
||||
Copyright (c) 2009 Olivier Chafik, All Rights Reserved |
||||
|
||||
JNAerator is free software: you can redistribute it and/or modify |
||||
it under the terms of the GNU General Public License as published by |
||||
the Free Software Foundation, either version 3 of the License, or |
||||
(at your option) any later version. |
||||
|
||||
JNAerator 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 JNAerator. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/ |
||||
|
||||
import java.io.File; |
||||
import java.io.FileOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.OutputStream; |
||||
import java.net.URL; |
||||
import java.net.URLConnection; |
||||
import java.net.URLDecoder; |
||||
import java.util.ArrayList; |
||||
import java.util.Iterator; |
||||
import java.util.List; |
||||
|
||||
import java.lang.reflect.InvocationHandler; |
||||
import java.lang.reflect.Method; |
||||
import java.lang.reflect.Proxy; |
||||
import java.util.Arrays; |
||||
import java.util.HashSet; |
||||
import java.util.Set; |
||||
|
||||
public class LibraryExtractor { |
||||
|
||||
private static boolean libPathSet = false; |
||||
|
||||
public static String getLibraryPath(String libraryName, boolean extractAllLibraries, Class<?> cl) { |
||||
try { |
||||
String customPath = System.getProperty("library." + libraryName); |
||||
if (customPath == null) |
||||
customPath = System.getenv(libraryName.toUpperCase() + "_LIBRARY"); |
||||
if (customPath != null) { |
||||
File f = new File(customPath); |
||||
if (!f.exists()) |
||||
System.err.println("Library file '" + customPath + "' does not exist !"); |
||||
else |
||||
return f.getAbsolutePath(); |
||||
} |
||||
//ClassLoader cl = LibraryExtractor.class.getClassLoader();
|
||||
String prefix = "(?i)" + (isWindows() ? "" : "lib") + libraryName + "[^A-Za-z_].*"; |
||||
String libsuffix = "(?i).*\\.(so|dll|dylib|jnilib)"; |
||||
//String othersuffix = "(?i).*\\.(pdb)";
|
||||
|
||||
URL sourceURL = null; |
||||
List<URL> otherURLs = new ArrayList<URL>(); |
||||
|
||||
|
||||
String arch = getCurrentOSAndArchString(); |
||||
//System.out.println("libURL = " + libURL);
|
||||
List<URL> list = URLUtils.listFiles(URLUtils.getResource(cl, "libraries/" + arch)), |
||||
noArchList = URLUtils.listFiles(URLUtils.getResource(cl, "libraries/noarch")); |
||||
|
||||
Set<String> names = new HashSet<String>(); |
||||
for (URL url : list) { |
||||
String name = getFileName(url); |
||||
names.add(name); |
||||
} |
||||
for (URL url : noArchList) { |
||||
String name = getFileName(url); |
||||
if (names.add(name)) |
||||
list.add(url); |
||||
} |
||||
|
||||
for (File f : new File(".").listFiles()) |
||||
if (f.isFile()) |
||||
list.add(f.toURI().toURL()); |
||||
|
||||
for (URL url : list) { |
||||
String name = getFileName(url); |
||||
boolean pref = name.matches(prefix), suff = name.matches(libsuffix); |
||||
if (pref && suff) |
||||
sourceURL = url; |
||||
else //if (suff || fileName.matches(othersuffix))
|
||||
otherURLs.add(url); |
||||
} |
||||
List<File> files = new ArrayList<File>(); |
||||
if (extractAllLibraries) { |
||||
for (URL url : otherURLs) |
||||
files.add(extract(url)); |
||||
} |
||||
|
||||
if (System.getProperty("javawebstart.version") != null) { |
||||
if (isWindows()) { |
||||
//File f = new File("c:\\Windows\\" + (Platform.is64Bit() ? "SysWOW64\\" : "System32\\") + libraryName + ".dll");
|
||||
File f = new File("c:\\Windows\\" + "System32\\" + libraryName + ".dll"); |
||||
if (f.exists()) |
||||
return f.toString(); |
||||
} else if (isMac()) { |
||||
File f = new File("/System/Library/Frameworks/" + libraryName + ".framework/" + libraryName); |
||||
if (f.exists()) |
||||
return f.toString(); |
||||
} |
||||
} |
||||
|
||||
if (sourceURL == null) |
||||
return libraryName; |
||||
else { |
||||
File file = extract(sourceURL); |
||||
files.add(file); |
||||
|
||||
int lastSize; |
||||
do { |
||||
lastSize = files.size(); |
||||
for (Iterator<File> it = files.iterator(); it.hasNext();) { |
||||
File f = it.next(); |
||||
if (!f.getName().matches(libsuffix)) |
||||
continue; |
||||
|
||||
try { |
||||
System.load(f.toString()); |
||||
it.remove(); |
||||
} catch (Throwable ex) { |
||||
System.err.println("Loading " + f.getName() + " failed (" + ex + ")"); |
||||
} |
||||
} |
||||
} while (files.size() < lastSize); |
||||
|
||||
return file.getCanonicalPath(); |
||||
} |
||||
} catch (Throwable ex) { |
||||
System.err.println("ERROR: Failed to extract library " + libraryName); |
||||
ex.printStackTrace(); |
||||
return libraryName; |
||||
} |
||||
} |
||||
|
||||
public static final boolean isWindows() { |
||||
String osName = System.getProperty("os.name"); |
||||
return osName.startsWith("Windows"); |
||||
} |
||||
|
||||
public static final boolean isMac() { |
||||
String osName = System.getProperty("os.name"); |
||||
return osName.startsWith("Mac") || osName.startsWith("Darwin"); |
||||
} |
||||
|
||||
//this code is from JNA, but JNA has a fallback to some native
|
||||
//stuff in case this doesn't work. Since sun.arch.data.model is
|
||||
//defined for Sun and IBM, this should work nearly everywhere.
|
||||
public static final boolean is64Bit() { |
||||
String model = System.getProperty("sun.arch.data.model", |
||||
System.getProperty("com.ibm.vm.bitmode")); |
||||
if (model != null) { |
||||
return "64".equals(model); |
||||
} |
||||
String arch = System.getProperty("os.arch").toLowerCase(); |
||||
if ("x86_64".equals(arch) |
||||
|| "ia64".equals(arch) |
||||
|| "ppc64".equals(arch) |
||||
|| "sparcv9".equals(arch) |
||||
|| "amd64".equals(arch)) { |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public static String getCurrentOSAndArchString() { |
||||
String os = System.getProperty("os.name"), arch = System.getProperty("os.arch"); |
||||
if (os.equals("Mac OS X")) { |
||||
os = "darwin"; |
||||
arch = "fat"; |
||||
} else if (os.startsWith("Windows")) { |
||||
return "win" + (is64Bit() ? "64" : "32"); |
||||
} else if (os.matches("SunOS|Solaris")) |
||||
os = "solaris"; |
||||
return os + "-" + arch; |
||||
} |
||||
|
||||
private static File extract(URL url) throws IOException { |
||||
File localFile; |
||||
if ("file".equals(url.getProtocol())) |
||||
localFile = new File(URLDecoder.decode(url.getFile(), "UTF-8")); |
||||
else { |
||||
File f = new File(System.getProperty("user.home")); |
||||
f = new File(f, ".jnaerator"); |
||||
f = new File(f, "extractedLibraries"); |
||||
if (!f.exists()) |
||||
f.mkdirs(); |
||||
|
||||
if (!libPathSet) { |
||||
String path = System.getProperty("java.library.path"); |
||||
if (path == null) { |
||||
System.setProperty("java.library.path", f.toString()); |
||||
} else { |
||||
System.setProperty("java.library.path", path + ":" + f); |
||||
} |
||||
|
||||
libPathSet = true; |
||||
} |
||||
localFile = new File(f, new File(url.getFile()).getName()); |
||||
URLConnection c = url.openConnection(); |
||||
if (localFile.exists() && localFile.lastModified() > c.getLastModified()) { |
||||
c.getInputStream().close(); |
||||
} else { |
||||
System.out.println("Extracting " + url); |
||||
InputStream in = c.getInputStream(); |
||||
OutputStream out = new FileOutputStream(localFile); |
||||
int len; |
||||
byte[] b = new byte[1024]; |
||||
while ((len = in.read(b)) > 0) |
||||
out.write(b, 0, len); |
||||
out.close(); |
||||
in.close(); |
||||
} |
||||
} |
||||
return localFile; |
||||
} |
||||
|
||||
private static String getFileName(URL url) { |
||||
return new File(url.getFile()).getName(); |
||||
} |
||||
|
||||
public static void main(String[] args) { |
||||
System.out.println(getCurrentOSAndArchString()); |
||||
} |
||||
} |
||||
@ -0,0 +1,50 @@
|
||||
package fr.free.miniupnp.libnatpmp; |
||||
|
||||
import java.nio.ByteBuffer; |
||||
|
||||
|
||||
public class NatPmp { |
||||
private static final String JNA_LIBRARY_NAME = LibraryExtractor.getLibraryPath("jninatpmp", true, NatPmp.class); |
||||
|
||||
static { |
||||
String s = JNA_LIBRARY_NAME; |
||||
startup(); |
||||
} |
||||
|
||||
public ByteBuffer natpmp; |
||||
|
||||
public NatPmp() { |
||||
init(0, 0); |
||||
} |
||||
|
||||
public NatPmp(int forcedgw) { |
||||
init(1, forcedgw); |
||||
} |
||||
|
||||
/** Cleans up the native resources used by this object. |
||||
Attempting to use the object after this has been called |
||||
will lead to crashes.*/ |
||||
public void dispose() { |
||||
free(); |
||||
} |
||||
|
||||
|
||||
protected void finalize() { |
||||
if (natpmp != null) |
||||
free(); |
||||
} |
||||
|
||||
private native void init(int forcegw, int forcedgw); |
||||
private native void free(); |
||||
|
||||
private static native void startup(); |
||||
|
||||
public native int sendPublicAddressRequest(); |
||||
public native int sendNewPortMappingRequest(int protocol, int privateport, int publicport, int lifetime); |
||||
|
||||
//returns a number of milliseconds, in accordance with Java convention
|
||||
public native long getNatPmpRequestTimeout(); |
||||
|
||||
public native int readNatPmpResponseOrRetry(NatPmpResponse response); |
||||
|
||||
} |
||||
@ -0,0 +1,28 @@
|
||||
package fr.free.miniupnp.libnatpmp; |
||||
|
||||
public class NatPmpResponse { |
||||
|
||||
public static final int TYPE_PUBLICADDRESS=0; |
||||
public static final int TYPE_UDPPORTMAPPING=1; |
||||
public static final int TYPE_TCPPORTMAPPING=2; |
||||
|
||||
/** see TYPE_* constants */ |
||||
public short type; |
||||
/** NAT-PMP response code */ |
||||
public short resultcode; |
||||
/** milliseconds since start of epoch */ |
||||
public long epoch; |
||||
|
||||
/** only defined if type == 0*/ |
||||
public int addr; |
||||
|
||||
/** only defined if type != 0 */ |
||||
public int privateport; |
||||
|
||||
/** only defined if type != 0 */ |
||||
public int mappedpublicport; |
||||
|
||||
/** only defined if type != 0 */ |
||||
public long lifetime; //milliseconds
|
||||
|
||||
} |
||||
@ -0,0 +1,81 @@
|
||||
package fr.free.miniupnp.libnatpmp; |
||||
|
||||
/** I (Leah X Schmidt) copied this code from jnaerator, because |
||||
JNAerator's extractor requires you to buy into the whole JNA |
||||
concept. |
||||
|
||||
JNAErator is |
||||
Copyright (c) 2009 Olivier Chafik, All Rights Reserved |
||||
|
||||
JNAerator is free software: you can redistribute it and/or modify |
||||
it under the terms of the GNU General Public License as published by |
||||
the Free Software Foundation, either version 3 of the License, or |
||||
(at your option) any later version. |
||||
|
||||
JNAerator 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 JNAerator. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/ |
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.net.URL; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.jar.JarEntry; |
||||
import java.util.jar.JarInputStream; |
||||
|
||||
public class URLUtils { |
||||
|
||||
public static URL getResource(Class<?> cl, String path) throws IOException { |
||||
String clp = cl.getName().replace('.', '/') + ".class"; |
||||
URL clu = cl.getClassLoader().getResource(clp); |
||||
String s = clu.toString(); |
||||
if (s.endsWith(clp)) |
||||
return new URL(s.substring(0, s.length() - clp.length()) + path); |
||||
|
||||
if (s.startsWith("jar:")) { |
||||
String[] ss = s.split("!"); |
||||
return new URL(ss[1] + "!/" + path); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public static List<URL> listFiles(URL directory) throws IOException { |
||||
List<URL> ret = new ArrayList<URL>(); |
||||
String s = directory.toString(); |
||||
if (s.startsWith("jar:")) { |
||||
String[] ss = s.substring("jar:".length()).split("!"); |
||||
String path = ss[1]; |
||||
URL target = new URL(ss[0]); |
||||
InputStream tin = target.openStream(); |
||||
try { |
||||
JarInputStream jin = new JarInputStream(tin); |
||||
JarEntry je; |
||||
while ((je = jin.getNextJarEntry()) != null) { |
||||
String p = "/" + je.getName(); |
||||
if (p.startsWith(path) && p.indexOf('/', path.length() + 1) < 0) |
||||
|
||||
ret.add(new URL("jar:" + target + "!" + p)); |
||||
} |
||||
} finally { |
||||
tin.close(); |
||||
} |
||||
} else if (s.startsWith("file:")) { |
||||
File f = new File(directory.getFile()); |
||||
File[] ffs = f.listFiles(); |
||||
if (ffs != null) |
||||
for (File ff : ffs) |
||||
ret.add(ff.toURI().toURL()); |
||||
} else |
||||
throw new IOException("Cannot list contents of " + directory); |
||||
|
||||
return ret; |
||||
} |
||||
} |
||||
@ -0,0 +1,573 @@
|
||||
/* $Id: getgateway.c,v 1.25 2014/04/22 10:28:57 nanard Exp $ */ |
||||
/* libnatpmp
|
||||
|
||||
Copyright (c) 2007-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 <stdio.h> |
||||
#include <ctype.h> |
||||
#ifndef WIN32 |
||||
#include <netinet/in.h> |
||||
#endif |
||||
#if !defined(_MSC_VER) |
||||
#include <sys/param.h> |
||||
#endif |
||||
/* There is no portable method to get the default route gateway.
|
||||
* So below are four (or five ?) differents functions implementing this. |
||||
* Parsing /proc/net/route is for linux. |
||||
* sysctl is the way to access such informations on BSD systems. |
||||
* Many systems should provide route information through raw PF_ROUTE |
||||
* sockets. |
||||
* In MS Windows, default gateway is found by looking into the registry |
||||
* or by using GetBestRoute(). */ |
||||
#ifdef __linux__ |
||||
#define USE_PROC_NET_ROUTE |
||||
#undef USE_SOCKET_ROUTE |
||||
#undef USE_SYSCTL_NET_ROUTE |
||||
#endif |
||||
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__) |
||||
#undef USE_PROC_NET_ROUTE |
||||
#define USE_SOCKET_ROUTE |
||||
#undef USE_SYSCTL_NET_ROUTE |
||||
#endif |
||||
|
||||
#ifdef __APPLE__ |
||||
#undef USE_PROC_NET_ROUTE |
||||
#undef USE_SOCKET_ROUTE |
||||
#define USE_SYSCTL_NET_ROUTE |
||||
#endif |
||||
|
||||
#if (defined(sun) && defined(__SVR4)) |
||||
#undef USE_PROC_NET_ROUTE |
||||
#define USE_SOCKET_ROUTE |
||||
#undef USE_SYSCTL_NET_ROUTE |
||||
#endif |
||||
|
||||
#ifdef WIN32 |
||||
#undef USE_PROC_NET_ROUTE |
||||
#undef USE_SOCKET_ROUTE |
||||
#undef USE_SYSCTL_NET_ROUTE |
||||
//#define USE_WIN32_CODE
|
||||
#define USE_WIN32_CODE_2 |
||||
#endif |
||||
|
||||
#ifdef __CYGWIN__ |
||||
#undef USE_PROC_NET_ROUTE |
||||
#undef USE_SOCKET_ROUTE |
||||
#undef USE_SYSCTL_NET_ROUTE |
||||
#define USE_WIN32_CODE |
||||
#include <stdarg.h> |
||||
#include <w32api/windef.h> |
||||
#include <w32api/winbase.h> |
||||
#include <w32api/winreg.h> |
||||
#endif |
||||
|
||||
#ifdef __HAIKU__ |
||||
#include <stdlib.h> |
||||
#include <unistd.h> |
||||
#include <net/if.h> |
||||
#include <sys/sockio.h> |
||||
#define USE_HAIKU_CODE |
||||
#endif |
||||
|
||||
#ifdef USE_SYSCTL_NET_ROUTE |
||||
#include <stdlib.h> |
||||
#include <sys/sysctl.h> |
||||
#include <sys/socket.h> |
||||
#include <net/route.h> |
||||
#endif |
||||
#ifdef USE_SOCKET_ROUTE |
||||
#include <unistd.h> |
||||
#include <string.h> |
||||
#include <sys/socket.h> |
||||
#include <net/if.h> |
||||
#include <net/route.h> |
||||
#endif |
||||
|
||||
#ifdef USE_WIN32_CODE |
||||
#include <unknwn.h> |
||||
#include <winreg.h> |
||||
#define MAX_KEY_LENGTH 255 |
||||
#define MAX_VALUE_LENGTH 16383 |
||||
#endif |
||||
|
||||
#ifdef USE_WIN32_CODE_2 |
||||
#include <windows.h> |
||||
#include <iphlpapi.h> |
||||
#endif |
||||
|
||||
#include "getgateway.h" |
||||
|
||||
#ifndef WIN32 |
||||
#define SUCCESS (0) |
||||
#define FAILED (-1) |
||||
#endif |
||||
|
||||
#ifdef USE_PROC_NET_ROUTE |
||||
/*
|
||||
parse /proc/net/route which is as follow : |
||||
|
||||
Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT |
||||
wlan0 0001A8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0 |
||||
eth0 0000FEA9 00000000 0001 0 0 0 0000FFFF 0 0 0 |
||||
wlan0 00000000 0101A8C0 0003 0 0 0 00000000 0 0 0 |
||||
eth0 00000000 00000000 0001 0 0 1000 00000000 0 0 0 |
||||
|
||||
One header line, and then one line by route by route table entry. |
||||
*/ |
||||
int getdefaultgateway(in_addr_t * addr) |
||||
{ |
||||
unsigned long d, g; |
||||
char buf[256]; |
||||
int line = 0; |
||||
FILE * f; |
||||
char * p; |
||||
f = fopen("/proc/net/route", "r"); |
||||
if(!f) |
||||
return FAILED; |
||||
while(fgets(buf, sizeof(buf), f)) { |
||||
if(line > 0) { /* skip the first line */ |
||||
p = buf; |
||||
/* skip the interface name */ |
||||
while(*p && !isspace(*p)) |
||||
p++; |
||||
while(*p && isspace(*p)) |
||||
p++; |
||||
if(sscanf(p, "%lx%lx", &d, &g)==2) { |
||||
if(d == 0 && g != 0) { /* default */ |
||||
*addr = g; |
||||
fclose(f); |
||||
return SUCCESS; |
||||
} |
||||
} |
||||
} |
||||
line++; |
||||
} |
||||
/* default route not found ! */ |
||||
if(f) |
||||
fclose(f); |
||||
return FAILED; |
||||
} |
||||
#endif /* #ifdef USE_PROC_NET_ROUTE */ |
||||
|
||||
|
||||
#ifdef USE_SYSCTL_NET_ROUTE |
||||
|
||||
#define ROUNDUP(a) \ |
||||
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) |
||||
|
||||
int getdefaultgateway(in_addr_t * addr) |
||||
{ |
||||
#if 0 |
||||
/* net.route.0.inet.dump.0.0 ? */ |
||||
int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET, |
||||
NET_RT_DUMP, 0, 0/*tableid*/}; |
||||
#endif |
||||
/* net.route.0.inet.flags.gateway */ |
||||
int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET, |
||||
NET_RT_FLAGS, RTF_GATEWAY}; |
||||
size_t l; |
||||
char * buf, * p; |
||||
struct rt_msghdr * rt; |
||||
struct sockaddr * sa; |
||||
struct sockaddr * sa_tab[RTAX_MAX]; |
||||
int i; |
||||
int r = FAILED; |
||||
if(sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0) { |
||||
return FAILED; |
||||
} |
||||
if(l>0) { |
||||
buf = malloc(l); |
||||
if(sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) { |
||||
free(buf); |
||||
return FAILED; |
||||
} |
||||
for(p=buf; p<buf+l; p+=rt->rtm_msglen) { |
||||
rt = (struct rt_msghdr *)p; |
||||
sa = (struct sockaddr *)(rt + 1); |
||||
for(i=0; i<RTAX_MAX; i++) { |
||||
if(rt->rtm_addrs & (1 << i)) { |
||||
sa_tab[i] = sa; |
||||
sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len)); |
||||
} else { |
||||
sa_tab[i] = NULL; |
||||
} |
||||
} |
||||
if( ((rt->rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY)) |
||||
&& sa_tab[RTAX_DST]->sa_family == AF_INET |
||||
&& sa_tab[RTAX_GATEWAY]->sa_family == AF_INET) { |
||||
if(((struct sockaddr_in *)sa_tab[RTAX_DST])->sin_addr.s_addr == 0) { |
||||
*addr = ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr; |
||||
r = SUCCESS; |
||||
} |
||||
} |
||||
} |
||||
free(buf); |
||||
} |
||||
return r; |
||||
} |
||||
#endif /* #ifdef USE_SYSCTL_NET_ROUTE */ |
||||
|
||||
|
||||
#ifdef USE_SOCKET_ROUTE |
||||
/* Thanks to Darren Kenny for this code */ |
||||
#define NEXTADDR(w, u) \ |
||||
if (rtm_addrs & (w)) {\
|
||||
l = sizeof(struct sockaddr); memmove(cp, &(u), l); cp += l;\
|
||||
} |
||||
|
||||
#define rtm m_rtmsg.m_rtm |
||||
|
||||
struct { |
||||
struct rt_msghdr m_rtm; |
||||
char m_space[512]; |
||||
} m_rtmsg; |
||||
|
||||
int getdefaultgateway(in_addr_t *addr) |
||||
{ |
||||
int s, seq, l, rtm_addrs, i; |
||||
pid_t pid; |
||||
struct sockaddr so_dst, so_mask; |
||||
char *cp = m_rtmsg.m_space; |
||||
struct sockaddr *gate = NULL, *sa; |
||||
struct rt_msghdr *msg_hdr; |
||||
|
||||
pid = getpid(); |
||||
seq = 0; |
||||
rtm_addrs = RTA_DST | RTA_NETMASK; |
||||
|
||||
memset(&so_dst, 0, sizeof(so_dst)); |
||||
memset(&so_mask, 0, sizeof(so_mask)); |
||||
memset(&rtm, 0, sizeof(struct rt_msghdr)); |
||||
|
||||
rtm.rtm_type = RTM_GET; |
||||
rtm.rtm_flags = RTF_UP | RTF_GATEWAY; |
||||
rtm.rtm_version = RTM_VERSION; |
||||
rtm.rtm_seq = ++seq; |
||||
rtm.rtm_addrs = rtm_addrs; |
||||
|
||||
so_dst.sa_family = AF_INET; |
||||
so_mask.sa_family = AF_INET; |
||||
|
||||
NEXTADDR(RTA_DST, so_dst); |
||||
NEXTADDR(RTA_NETMASK, so_mask); |
||||
|
||||
rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; |
||||
|
||||
s = socket(PF_ROUTE, SOCK_RAW, 0); |
||||
|
||||
if (write(s, (char *)&m_rtmsg, l) < 0) { |
||||
close(s); |
||||
return FAILED; |
||||
} |
||||
|
||||
do { |
||||
l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg)); |
||||
} while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid)); |
||||
|
||||
close(s); |
||||
|
||||
msg_hdr = &rtm; |
||||
|
||||
cp = ((char *)(msg_hdr + 1)); |
||||
if (msg_hdr->rtm_addrs) { |
||||
for (i = 1; i; i <<= 1) |
||||
if (i & msg_hdr->rtm_addrs) { |
||||
sa = (struct sockaddr *)cp; |
||||
if (i == RTA_GATEWAY ) |
||||
gate = sa; |
||||
|
||||
cp += sizeof(struct sockaddr); |
||||
} |
||||
} else { |
||||
return FAILED; |
||||
} |
||||
|
||||
|
||||
if (gate != NULL ) { |
||||
*addr = ((struct sockaddr_in *)gate)->sin_addr.s_addr; |
||||
return SUCCESS; |
||||
} else { |
||||
return FAILED; |
||||
} |
||||
} |
||||
#endif /* #ifdef USE_SOCKET_ROUTE */ |
||||
|
||||
#ifdef USE_WIN32_CODE |
||||
LIBSPEC int getdefaultgateway(in_addr_t * addr) |
||||
{ |
||||
HKEY networkCardsKey; |
||||
HKEY networkCardKey; |
||||
HKEY interfacesKey; |
||||
HKEY interfaceKey; |
||||
DWORD i = 0; |
||||
DWORD numSubKeys = 0; |
||||
TCHAR keyName[MAX_KEY_LENGTH]; |
||||
DWORD keyNameLength = MAX_KEY_LENGTH; |
||||
TCHAR keyValue[MAX_VALUE_LENGTH]; |
||||
DWORD keyValueLength = MAX_VALUE_LENGTH; |
||||
DWORD keyValueType = REG_SZ; |
||||
TCHAR gatewayValue[MAX_VALUE_LENGTH]; |
||||
DWORD gatewayValueLength = MAX_VALUE_LENGTH; |
||||
DWORD gatewayValueType = REG_MULTI_SZ; |
||||
int done = 0; |
||||
|
||||
//const char * networkCardsPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards";
|
||||
//const char * interfacesPath = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces";
|
||||
#ifdef UNICODE |
||||
LPCTSTR networkCardsPath = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards"; |
||||
LPCTSTR interfacesPath = L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"; |
||||
#define STR_SERVICENAME L"ServiceName" |
||||
#define STR_DHCPDEFAULTGATEWAY L"DhcpDefaultGateway" |
||||
#define STR_DEFAULTGATEWAY L"DefaultGateway" |
||||
#else |
||||
LPCTSTR networkCardsPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards"; |
||||
LPCTSTR interfacesPath = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"; |
||||
#define STR_SERVICENAME "ServiceName" |
||||
#define STR_DHCPDEFAULTGATEWAY "DhcpDefaultGateway" |
||||
#define STR_DEFAULTGATEWAY "DefaultGateway" |
||||
#endif |
||||
// The windows registry lists its primary network devices in the following location:
|
||||
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards
|
||||
//
|
||||
// Each network device has its own subfolder, named with an index, with various properties:
|
||||
// -NetworkCards
|
||||
// -5
|
||||
// -Description = Broadcom 802.11n Network Adapter
|
||||
// -ServiceName = {E35A72F8-5065-4097-8DFE-C7790774EE4D}
|
||||
// -8
|
||||
// -Description = Marvell Yukon 88E8058 PCI-E Gigabit Ethernet Controller
|
||||
// -ServiceName = {86226414-5545-4335-A9D1-5BD7120119AD}
|
||||
//
|
||||
// The above service name is the name of a subfolder within:
|
||||
// HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces
|
||||
//
|
||||
// There may be more subfolders in this interfaces path than listed in the network cards path above:
|
||||
// -Interfaces
|
||||
// -{3a539854-6a70-11db-887c-806e6f6e6963}
|
||||
// -DhcpIPAddress = 0.0.0.0
|
||||
// -[more]
|
||||
// -{E35A72F8-5065-4097-8DFE-C7790774EE4D}
|
||||
// -DhcpIPAddress = 10.0.1.4
|
||||
// -DhcpDefaultGateway = 10.0.1.1
|
||||
// -[more]
|
||||
// -{86226414-5545-4335-A9D1-5BD7120119AD}
|
||||
// -DhcpIpAddress = 10.0.1.5
|
||||
// -DhcpDefaultGateay = 10.0.1.1
|
||||
// -[more]
|
||||
//
|
||||
// In order to extract this information, we enumerate each network card, and extract the ServiceName value.
|
||||
// This is then used to open the interface subfolder, and attempt to extract a DhcpDefaultGateway value.
|
||||
// Once one is found, we're done.
|
||||
//
|
||||
// It may be possible to simply enumerate the interface folders until we find one with a DhcpDefaultGateway value.
|
||||
// However, the technique used is the technique most cited on the web, and we assume it to be more correct.
|
||||
|
||||
if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, // Open registry key or predifined key
|
||||
networkCardsPath, // Name of registry subkey to open
|
||||
0, // Reserved - must be zero
|
||||
KEY_READ, // Mask - desired access rights
|
||||
&networkCardsKey)) // Pointer to output key
|
||||
{ |
||||
// Unable to open network cards keys
|
||||
return -1; |
||||
} |
||||
|
||||
if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, // Open registry key or predefined key
|
||||
interfacesPath, // Name of registry subkey to open
|
||||
0, // Reserved - must be zero
|
||||
KEY_READ, // Mask - desired access rights
|
||||
&interfacesKey)) // Pointer to output key
|
||||
{ |
||||
// Unable to open interfaces key
|
||||
RegCloseKey(networkCardsKey); |
||||
return -1; |
||||
} |
||||
|
||||
// Figure out how many subfolders are within the NetworkCards folder
|
||||
RegQueryInfoKey(networkCardsKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
||||
|
||||
//printf( "Number of subkeys: %u\n", (unsigned int)numSubKeys);
|
||||
|
||||
// Enumrate through each subfolder within the NetworkCards folder
|
||||
for(i = 0; i < numSubKeys && !done; i++) |
||||
{ |
||||
keyNameLength = MAX_KEY_LENGTH; |
||||
if(ERROR_SUCCESS == RegEnumKeyEx(networkCardsKey, // Open registry key
|
||||
i, // Index of subkey to retrieve
|
||||
keyName, // Buffer that receives the name of the subkey
|
||||
&keyNameLength, // Variable that receives the size of the above buffer
|
||||
NULL, // Reserved - must be NULL
|
||||
NULL, // Buffer that receives the class string
|
||||
NULL, // Variable that receives the size of the above buffer
|
||||
NULL)) // Variable that receives the last write time of subkey
|
||||
{ |
||||
if(RegOpenKeyEx(networkCardsKey, keyName, 0, KEY_READ, &networkCardKey) == ERROR_SUCCESS) |
||||
{ |
||||
keyValueLength = MAX_VALUE_LENGTH; |
||||
if(ERROR_SUCCESS == RegQueryValueEx(networkCardKey, // Open registry key
|
||||
STR_SERVICENAME, // Name of key to query
|
||||
NULL, // Reserved - must be NULL
|
||||
&keyValueType, // Receives value type
|
||||
(LPBYTE)keyValue, // Receives value
|
||||
&keyValueLength)) // Receives value length in bytes
|
||||
{ |
||||
// printf("keyValue: %s\n", keyValue);
|
||||
if(RegOpenKeyEx(interfacesKey, keyValue, 0, KEY_READ, &interfaceKey) == ERROR_SUCCESS) |
||||
{ |
||||
gatewayValueLength = MAX_VALUE_LENGTH; |
||||
if(ERROR_SUCCESS == RegQueryValueEx(interfaceKey, // Open registry key
|
||||
STR_DHCPDEFAULTGATEWAY, // Name of key to query
|
||||
NULL, // Reserved - must be NULL
|
||||
&gatewayValueType, // Receives value type
|
||||
(LPBYTE)gatewayValue, // Receives value
|
||||
&gatewayValueLength)) // Receives value length in bytes
|
||||
{ |
||||
// Check to make sure it's a string
|
||||
if((gatewayValueType == REG_MULTI_SZ || gatewayValueType == REG_SZ) && (gatewayValueLength > 1)) |
||||
{ |
||||
//printf("gatewayValue: %s\n", gatewayValue);
|
||||
done = 1; |
||||
} |
||||
} |
||||
else if(ERROR_SUCCESS == RegQueryValueEx(interfaceKey, // Open registry key
|
||||
STR_DEFAULTGATEWAY, // Name of key to query
|
||||
NULL, // Reserved - must be NULL
|
||||
&gatewayValueType, // Receives value type
|
||||
(LPBYTE)gatewayValue,// Receives value
|
||||
&gatewayValueLength)) // Receives value length in bytes
|
||||
{ |
||||
// Check to make sure it's a string
|
||||
if((gatewayValueType == REG_MULTI_SZ || gatewayValueType == REG_SZ) && (gatewayValueLength > 1)) |
||||
{ |
||||
//printf("gatewayValue: %s\n", gatewayValue);
|
||||
done = 1; |
||||
} |
||||
} |
||||
RegCloseKey(interfaceKey); |
||||
} |
||||
} |
||||
RegCloseKey(networkCardKey); |
||||
} |
||||
} |
||||
} |
||||
|
||||
RegCloseKey(interfacesKey); |
||||
RegCloseKey(networkCardsKey); |
||||
|
||||
if(done) |
||||
{ |
||||
#if UNICODE |
||||
char tmp[32]; |
||||
for(i = 0; i < 32; i++) { |
||||
tmp[i] = (char)gatewayValue[i]; |
||||
if(!tmp[i]) |
||||
break; |
||||
} |
||||
tmp[31] = '\0'; |
||||
*addr = inet_addr(tmp); |
||||
#else |
||||
*addr = inet_addr(gatewayValue); |
||||
#endif |
||||
return 0; |
||||
} |
||||
|
||||
return -1; |
||||
} |
||||
#endif /* #ifdef USE_WIN32_CODE */ |
||||
|
||||
#ifdef USE_WIN32_CODE_2 |
||||
int getdefaultgateway(in_addr_t *addr) |
||||
{ |
||||
MIB_IPFORWARDROW ip_forward; |
||||
memset(&ip_forward, 0, sizeof(ip_forward)); |
||||
if(GetBestRoute(inet_addr("0.0.0.0"), 0, &ip_forward) != NO_ERROR) |
||||
return -1; |
||||
*addr = ip_forward.dwForwardNextHop; |
||||
return 0; |
||||
} |
||||
#endif /* #ifdef USE_WIN32_CODE_2 */ |
||||
|
||||
#ifdef USE_HAIKU_CODE |
||||
int getdefaultgateway(in_addr_t *addr) |
||||
{ |
||||
int fd, ret = -1; |
||||
struct ifconf config; |
||||
void *buffer = NULL; |
||||
struct ifreq *interface; |
||||
|
||||
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { |
||||
return -1; |
||||
} |
||||
if (ioctl(fd, SIOCGRTSIZE, &config, sizeof(config)) != 0) { |
||||
goto fail; |
||||
} |
||||
if (config.ifc_value < 1) { |
||||
goto fail; /* No routes */ |
||||
} |
||||
if ((buffer = malloc(config.ifc_value)) == NULL) { |
||||
goto fail; |
||||
} |
||||
config.ifc_len = config.ifc_value; |
||||
config.ifc_buf = buffer; |
||||
if (ioctl(fd, SIOCGRTTABLE, &config, sizeof(config)) != 0) { |
||||
goto fail; |
||||
} |
||||
for (interface = buffer; |
||||
(uint8_t *)interface < (uint8_t *)buffer + config.ifc_len; ) { |
||||
struct route_entry route = interface->ifr_route; |
||||
int intfSize; |
||||
if (route.flags & (RTF_GATEWAY | RTF_DEFAULT)) { |
||||
*addr = ((struct sockaddr_in *)route.gateway)->sin_addr.s_addr; |
||||
ret = 0; |
||||
break; |
||||
} |
||||
intfSize = sizeof(route) + IF_NAMESIZE; |
||||
if (route.destination != NULL) { |
||||
intfSize += route.destination->sa_len; |
||||
} |
||||
if (route.mask != NULL) { |
||||
intfSize += route.mask->sa_len; |
||||
} |
||||
if (route.gateway != NULL) { |
||||
intfSize += route.gateway->sa_len; |
||||
} |
||||
interface = (struct ifreq *)((uint8_t *)interface + intfSize); |
||||
} |
||||
fail: |
||||
free(buffer); |
||||
close(fd); |
||||
return ret; |
||||
} |
||||
#endif /* #ifdef USE_HAIKU_CODE */ |
||||
|
||||
#if !defined(USE_PROC_NET_ROUTE) && !defined(USE_SOCKET_ROUTE) && !defined(USE_SYSCTL_NET_ROUTE) && !defined(USE_WIN32_CODE) && !defined(USE_WIN32_CODE_2) && !defined(USE_HAIKU_CODE) |
||||
int getdefaultgateway(in_addr_t * addr) |
||||
{ |
||||
return -1; |
||||
} |
||||
#endif |
||||
@ -0,0 +1,49 @@
|
||||
/* $Id: getgateway.h,v 1.8 2014/04/22 09:15:40 nanard Exp $ */ |
||||
/* libnatpmp
|
||||
Copyright (c) 2007-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. |
||||
*/ |
||||
#ifndef __GETGATEWAY_H__ |
||||
#define __GETGATEWAY_H__ |
||||
|
||||
#ifdef WIN32 |
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1600 |
||||
#include <stdint.h> |
||||
#else |
||||
typedef unsigned long uint32_t; |
||||
typedef unsigned short uint16_t; |
||||
#endif |
||||
#define in_addr_t uint32_t |
||||
#endif |
||||
/* #include "declspec.h" */ |
||||
|
||||
/* getdefaultgateway() :
|
||||
* return value : |
||||
* 0 : success |
||||
* -1 : failure */ |
||||
/* LIBSPEC */int getdefaultgateway(in_addr_t * addr); |
||||
|
||||
#endif |
||||
@ -0,0 +1,281 @@
|
||||
/* $Id: libnatpmpmodule.c,v 1.7 2012/03/05 19:38:37 nanard Exp $ */ |
||||
/* libnatpmp
|
||||
* http://miniupnp.free.fr/libnatpmp.html
|
||||
Copyright (c) 2007-2011, 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 <Python.h> |
||||
#ifdef WIN32 |
||||
#include <winsock2.h> |
||||
#else |
||||
#include <netinet/in.h> |
||||
#include <arpa/inet.h> |
||||
#endif |
||||
|
||||
#define STATICLIB |
||||
#include "structmember.h" |
||||
#include "natpmp.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 |
||||
|
||||
typedef struct { |
||||
PyObject_HEAD |
||||
|
||||
/* Type-specific fields go here. */ |
||||
unsigned int discoverdelay; |
||||
|
||||
natpmp_t natpmp; |
||||
} NATPMPObject; |
||||
|
||||
static PyMemberDef NATPMP_members[] = { |
||||
{"discoverdelay", T_UINT, offsetof(NATPMPObject, discoverdelay), |
||||
0/*READWRITE*/, "value in ms used to wait for NATPMP responses" |
||||
}, |
||||
{NULL} |
||||
}; |
||||
|
||||
static PyObject * |
||||
NATPMPObject_new(PyTypeObject *type, PyObject *args, PyObject *kwds) |
||||
{ |
||||
NATPMPObject *self; |
||||
|
||||
self = (NATPMPObject *)type->tp_alloc(type, 0); |
||||
if (self) { |
||||
initnatpmp(&self->natpmp, 0, 0); |
||||
} |
||||
|
||||
return (PyObject *)self; |
||||
} |
||||
|
||||
static void |
||||
NATPMPObject_dealloc(NATPMPObject *self) |
||||
{ |
||||
closenatpmp(&self->natpmp); |
||||
self->ob_type->tp_free((PyObject*)self); |
||||
} |
||||
|
||||
static PyObject * |
||||
NATPMP_externalipaddress(NATPMPObject *self) |
||||
{ |
||||
int r; |
||||
struct timeval timeout; |
||||
fd_set fds; |
||||
natpmpresp_t response; |
||||
|
||||
r = sendpublicaddressrequest(&self->natpmp); |
||||
|
||||
if (r < 0) { |
||||
#ifdef ENABLE_STRNATPMPERR |
||||
PyErr_SetString(PyExc_Exception, strnatpmperr(r)); |
||||
#endif |
||||
return NULL; |
||||
} |
||||
|
||||
do { |
||||
FD_ZERO(&fds); |
||||
FD_SET(self->natpmp.s, &fds); |
||||
getnatpmprequesttimeout(&self->natpmp, &timeout); |
||||
select(FD_SETSIZE, &fds, NULL, NULL, &timeout); |
||||
r = readnatpmpresponseorretry(&self->natpmp, &response); |
||||
if (r < 0 && r != NATPMP_TRYAGAIN) { |
||||
#ifdef ENABLE_STRNATPMPERR |
||||
PyErr_SetString(PyExc_Exception, strnatpmperr(r)); |
||||
#endif |
||||
return NULL; |
||||
} |
||||
} while (r == NATPMP_TRYAGAIN); |
||||
|
||||
return Py_BuildValue("s", inet_ntoa(response.pnu.publicaddress.addr)); |
||||
} |
||||
|
||||
static PyObject * |
||||
NATPMP_domapping(natpmp_t *n, unsigned short eport, unsigned short iport, |
||||
const char *protocol, unsigned int lifetime) |
||||
{ |
||||
int proto; |
||||
struct timeval timeout; |
||||
fd_set fds; |
||||
natpmpresp_t response; |
||||
int r; |
||||
|
||||
if (!strncasecmp("tcp", protocol, 3)) { |
||||
proto = NATPMP_PROTOCOL_TCP; |
||||
} else if (!strncasecmp("udp", protocol, 3)) { |
||||
proto = NATPMP_PROTOCOL_UDP; |
||||
} else { |
||||
PyErr_SetString(PyExc_Exception, "Unknown protocol"); |
||||
return NULL; |
||||
} |
||||
|
||||
r = sendnewportmappingrequest(n, proto, iport, eport, |
||||
lifetime); |
||||
|
||||
if (r < 0) { |
||||
#ifdef ENABLE_STRNATPMPERR |
||||
PyErr_SetString(PyExc_Exception, strnatpmperr(r)); |
||||
#endif |
||||
return NULL; |
||||
} |
||||
|
||||
do { |
||||
FD_ZERO(&fds); |
||||
FD_SET(n->s, &fds); |
||||
getnatpmprequesttimeout(n, &timeout); |
||||
select(FD_SETSIZE, &fds, NULL, NULL, &timeout); |
||||
r = readnatpmpresponseorretry(n, &response); |
||||
if (r < 0 && r != NATPMP_TRYAGAIN) { |
||||
#ifdef ENABLE_STRNATPMPERR |
||||
PyErr_SetString(PyExc_Exception, strnatpmperr(r)); |
||||
#endif |
||||
return NULL; |
||||
} |
||||
} while (r == NATPMP_TRYAGAIN); |
||||
|
||||
return Py_BuildValue("H", response.pnu.newportmapping.mappedpublicport); |
||||
} |
||||
|
||||
|
||||
/* AddPortMapping(externalPort, protocol, internalPort, lifetime)
|
||||
* protocol is 'UDP' or 'TCP' */ |
||||
static PyObject * |
||||
NATPMP_addportmapping(NATPMPObject *self, PyObject *args) |
||||
{ |
||||
unsigned short eport; |
||||
unsigned short iport; |
||||
unsigned int lifetime; |
||||
const char *protocol; |
||||
|
||||
if (!PyArg_ParseTuple(args, "HsHI", &eport, &protocol, &iport, &lifetime)) |
||||
return NULL; |
||||
|
||||
return NATPMP_domapping(&self->natpmp, eport, iport, protocol, lifetime); |
||||
} |
||||
|
||||
/* DeletePortMapping(externalPort, protocol, internalPort)
|
||||
* protocol is 'UDP' or 'TCP' */ |
||||
static PyObject * |
||||
NATPMP_deleteportmapping(NATPMPObject *self, PyObject *args) |
||||
{ |
||||
unsigned short eport; |
||||
unsigned short iport; |
||||
const char *protocol; |
||||
|
||||
if (!PyArg_ParseTuple(args, "HsH", &eport, &protocol, &iport)) |
||||
return NULL; |
||||
|
||||
return NATPMP_domapping(&self->natpmp, eport, iport, protocol, 0); |
||||
} |
||||
|
||||
/* natpmp.NATPMP object Method Table */ |
||||
static PyMethodDef NATPMP_methods[] = { |
||||
{"externalipaddress", (PyCFunction)NATPMP_externalipaddress, METH_NOARGS, |
||||
"return external IP address" |
||||
}, |
||||
{"addportmapping", (PyCFunction)NATPMP_addportmapping, METH_VARARGS, |
||||
"add a port mapping" |
||||
}, |
||||
{"deleteportmapping", (PyCFunction)NATPMP_deleteportmapping, METH_VARARGS, |
||||
"delete a port mapping" |
||||
}, |
||||
{NULL} /* Sentinel */ |
||||
}; |
||||
|
||||
static PyTypeObject NATPMPType = { |
||||
PyObject_HEAD_INIT(NULL) |
||||
0, /*ob_size*/ |
||||
"libnatpmp.NATPMP", /*tp_name*/ |
||||
sizeof(NATPMPObject), /*tp_basicsize*/ |
||||
0, /*tp_itemsize*/ |
||||
(destructor)NATPMPObject_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*/ |
||||
"NATPMP objects", /* tp_doc */ |
||||
0, /* tp_traverse */ |
||||
0, /* tp_clear */ |
||||
0, /* tp_richcompare */ |
||||
0, /* tp_weaklistoffset */ |
||||
0, /* tp_iter */ |
||||
0, /* tp_iternext */ |
||||
NATPMP_methods, /* tp_methods */ |
||||
NATPMP_members, /* tp_members */ |
||||
0, /* tp_getset */ |
||||
0, /* tp_base */ |
||||
0, /* tp_dict */ |
||||
0, /* tp_descr_get */ |
||||
0, /* tp_descr_set */ |
||||
0, /* tp_dictoffset */ |
||||
0, /* tp_init */ |
||||
0, /* tp_alloc */ |
||||
NATPMPObject_new, /* tp_new */ |
||||
}; |
||||
|
||||
/* module methods */ |
||||
static PyMethodDef libnatpmp_methods[] = { |
||||
{NULL} /* Sentinel */ |
||||
}; |
||||
|
||||
#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ |
||||
#define PyMODINIT_FUNC void |
||||
#endif |
||||
PyMODINIT_FUNC |
||||
initlibnatpmp(void) |
||||
{ |
||||
PyObject* m; |
||||
|
||||
if (PyType_Ready(&NATPMPType) < 0) |
||||
return; |
||||
|
||||
m = Py_InitModule3("libnatpmp", libnatpmp_methods, |
||||
"libnatpmp module."); |
||||
|
||||
Py_INCREF(&NATPMPType); |
||||
PyModule_AddObject(m, "NATPMP", (PyObject *)&NATPMPType); |
||||
} |
||||
|
||||
@ -0,0 +1,29 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00 |
||||
# Visual C++ Express 2008 |
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libnatpmp", "libnatpmp.vcproj", "{D59B6527-F3DE-4D26-A08D-52F1EE989301}" |
||||
EndProject |
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "natpmpc-static", "natpmpc-static.vcproj", "{A0B49FA9-98AB-4A74-8B4C-8AB7FA36089B}" |
||||
ProjectSection(ProjectDependencies) = postProject |
||||
{D59B6527-F3DE-4D26-A08D-52F1EE989301} = {D59B6527-F3DE-4D26-A08D-52F1EE989301} |
||||
EndProjectSection |
||||
EndProject |
||||
Global |
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
||||
Debug|Win32 = Debug|Win32 |
||||
Release|Win32 = Release|Win32 |
||||
EndGlobalSection |
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
||||
{D59B6527-F3DE-4D26-A08D-52F1EE989301}.Debug|Win32.ActiveCfg = Debug|Win32 |
||||
{D59B6527-F3DE-4D26-A08D-52F1EE989301}.Debug|Win32.Build.0 = Debug|Win32 |
||||
{D59B6527-F3DE-4D26-A08D-52F1EE989301}.Release|Win32.ActiveCfg = Release|Win32 |
||||
{D59B6527-F3DE-4D26-A08D-52F1EE989301}.Release|Win32.Build.0 = Release|Win32 |
||||
{A0B49FA9-98AB-4A74-8B4C-8AB7FA36089B}.Debug|Win32.ActiveCfg = Debug|Win32 |
||||
{A0B49FA9-98AB-4A74-8B4C-8AB7FA36089B}.Debug|Win32.Build.0 = Debug|Win32 |
||||
{A0B49FA9-98AB-4A74-8B4C-8AB7FA36089B}.Release|Win32.ActiveCfg = Release|Win32 |
||||
{A0B49FA9-98AB-4A74-8B4C-8AB7FA36089B}.Release|Win32.Build.0 = Release|Win32 |
||||
EndGlobalSection |
||||
GlobalSection(SolutionProperties) = preSolution |
||||
HideSolutionNode = FALSE |
||||
EndGlobalSection |
||||
EndGlobal |
||||
@ -0,0 +1,195 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?> |
||||
<VisualStudioProject |
||||
ProjectType="Visual C++" |
||||
Version="9,00" |
||||
Name="libnatpmp" |
||||
ProjectGUID="{D59B6527-F3DE-4D26-A08D-52F1EE989301}" |
||||
RootNamespace="libnatpmp" |
||||
Keyword="Win32Proj" |
||||
TargetFrameworkVersion="196613" |
||||
> |
||||
<Platforms> |
||||
<Platform |
||||
Name="Win32" |
||||
/> |
||||
</Platforms> |
||||
<ToolFiles> |
||||
</ToolFiles> |
||||
<Configurations> |
||||
<Configuration |
||||
Name="Debug|Win32" |
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)" |
||||
IntermediateDirectory="$(ConfigurationName)" |
||||
ConfigurationType="4" |
||||
CharacterSet="1" |
||||
> |
||||
<Tool |
||||
Name="VCPreBuildEventTool" |
||||
/> |
||||
<Tool |
||||
Name="VCCustomBuildTool" |
||||
/> |
||||
<Tool |
||||
Name="VCXMLDataGeneratorTool" |
||||
/> |
||||
<Tool |
||||
Name="VCWebServiceProxyGeneratorTool" |
||||
/> |
||||
<Tool |
||||
Name="VCMIDLTool" |
||||
/> |
||||
<Tool |
||||
Name="VCCLCompilerTool" |
||||
Optimization="0" |
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;STATICLIB" |
||||
MinimalRebuild="true" |
||||
BasicRuntimeChecks="3" |
||||
RuntimeLibrary="3" |
||||
UsePrecompiledHeader="0" |
||||
WarningLevel="3" |
||||
DebugInformationFormat="4" |
||||
/> |
||||
<Tool |
||||
Name="VCManagedResourceCompilerTool" |
||||
/> |
||||
<Tool |
||||
Name="VCResourceCompilerTool" |
||||
/> |
||||
<Tool |
||||
Name="VCPreLinkEventTool" |
||||
/> |
||||
<Tool |
||||
Name="VCLibrarianTool" |
||||
/> |
||||
<Tool |
||||
Name="VCALinkTool" |
||||
/> |
||||
<Tool |
||||
Name="VCXDCMakeTool" |
||||
/> |
||||
<Tool |
||||
Name="VCBscMakeTool" |
||||
/> |
||||
<Tool |
||||
Name="VCFxCopTool" |
||||
/> |
||||
<Tool |
||||
Name="VCPostBuildEventTool" |
||||
/> |
||||
</Configuration> |
||||
<Configuration |
||||
Name="Release|Win32" |
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)" |
||||
IntermediateDirectory="$(ConfigurationName)" |
||||
ConfigurationType="4" |
||||
CharacterSet="1" |
||||
WholeProgramOptimization="1" |
||||
> |
||||
<Tool |
||||
Name="VCPreBuildEventTool" |
||||
/> |
||||
<Tool |
||||
Name="VCCustomBuildTool" |
||||
/> |
||||
<Tool |
||||
Name="VCXMLDataGeneratorTool" |
||||
/> |
||||
<Tool |
||||
Name="VCWebServiceProxyGeneratorTool" |
||||
/> |
||||
<Tool |
||||
Name="VCMIDLTool" |
||||
/> |
||||
<Tool |
||||
Name="VCCLCompilerTool" |
||||
Optimization="2" |
||||
EnableIntrinsicFunctions="true" |
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;STATICLIB" |
||||
RuntimeLibrary="2" |
||||
EnableFunctionLevelLinking="true" |
||||
UsePrecompiledHeader="0" |
||||
WarningLevel="3" |
||||
DebugInformationFormat="3" |
||||
/> |
||||
<Tool |
||||
Name="VCManagedResourceCompilerTool" |
||||
/> |
||||
<Tool |
||||
Name="VCResourceCompilerTool" |
||||
/> |
||||
<Tool |
||||
Name="VCPreLinkEventTool" |
||||
/> |
||||
<Tool |
||||
Name="VCLibrarianTool" |
||||
/> |
||||
<Tool |
||||
Name="VCALinkTool" |
||||
/> |
||||
<Tool |
||||
Name="VCXDCMakeTool" |
||||
/> |
||||
<Tool |
||||
Name="VCBscMakeTool" |
||||
/> |
||||
<Tool |
||||
Name="VCFxCopTool" |
||||
/> |
||||
<Tool |
||||
Name="VCPostBuildEventTool" |
||||
/> |
||||
</Configuration> |
||||
</Configurations> |
||||
<References> |
||||
</References> |
||||
<Files> |
||||
<Filter |
||||
Name="Fichiers sources" |
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" |
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" |
||||
> |
||||
<File |
||||
RelativePath="..\getgateway.c" |
||||
> |
||||
</File> |
||||
<File |
||||
RelativePath="..\natpmp.c" |
||||
> |
||||
</File> |
||||
<File |
||||
RelativePath="..\wingettimeofday.c" |
||||
> |
||||
</File> |
||||
</Filter> |
||||
<Filter |
||||
Name="Fichiers d'en-tête" |
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd" |
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" |
||||
> |
||||
<File |
||||
RelativePath="..\declspec.h" |
||||
> |
||||
</File> |
||||
<File |
||||
RelativePath="..\getgateway.h" |
||||
> |
||||
</File> |
||||
<File |
||||
RelativePath="..\natpmp.h" |
||||
> |
||||
</File> |
||||
<File |
||||
RelativePath="..\wingettimeofday.h" |
||||
> |
||||
</File> |
||||
</Filter> |
||||
<Filter |
||||
Name="Fichiers de ressources" |
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav" |
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" |
||||
> |
||||
</Filter> |
||||
</Files> |
||||
<Globals> |
||||
</Globals> |
||||
</VisualStudioProject> |
||||
@ -0,0 +1,195 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?> |
||||
<VisualStudioProject |
||||
ProjectType="Visual C++" |
||||
Version="9,00" |
||||
Name="natpmpc-static" |
||||
ProjectGUID="{A0B49FA9-98AB-4A74-8B4C-8AB7FA36089B}" |
||||
RootNamespace="natpmpcstatic" |
||||
Keyword="Win32Proj" |
||||
TargetFrameworkVersion="196613" |
||||
> |
||||
<Platforms> |
||||
<Platform |
||||
Name="Win32" |
||||
/> |
||||
</Platforms> |
||||
<ToolFiles> |
||||
</ToolFiles> |
||||
<Configurations> |
||||
<Configuration |
||||
Name="Debug|Win32" |
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)" |
||||
IntermediateDirectory="$(ConfigurationName)" |
||||
ConfigurationType="1" |
||||
CharacterSet="1" |
||||
> |
||||
<Tool |
||||
Name="VCPreBuildEventTool" |
||||
/> |
||||
<Tool |
||||
Name="VCCustomBuildTool" |
||||
/> |
||||
<Tool |
||||
Name="VCXMLDataGeneratorTool" |
||||
/> |
||||
<Tool |
||||
Name="VCWebServiceProxyGeneratorTool" |
||||
/> |
||||
<Tool |
||||
Name="VCMIDLTool" |
||||
/> |
||||
<Tool |
||||
Name="VCCLCompilerTool" |
||||
Optimization="0" |
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;STATICLIB;_CRT_SECURE_NO_WARNINGS" |
||||
MinimalRebuild="true" |
||||
BasicRuntimeChecks="3" |
||||
RuntimeLibrary="3" |
||||
UsePrecompiledHeader="0" |
||||
WarningLevel="3" |
||||
DebugInformationFormat="4" |
||||
/> |
||||
<Tool |
||||
Name="VCManagedResourceCompilerTool" |
||||
/> |
||||
<Tool |
||||
Name="VCResourceCompilerTool" |
||||
/> |
||||
<Tool |
||||
Name="VCPreLinkEventTool" |
||||
/> |
||||
<Tool |
||||
Name="VCLinkerTool" |
||||
AdditionalDependencies="ws2_32.lib Iphlpapi.lib" |
||||
LinkIncremental="2" |
||||
GenerateDebugInformation="true" |
||||
SubSystem="1" |
||||
TargetMachine="1" |
||||
/> |
||||
<Tool |
||||
Name="VCALinkTool" |
||||
/> |
||||
<Tool |
||||
Name="VCManifestTool" |
||||
/> |
||||
<Tool |
||||
Name="VCXDCMakeTool" |
||||
/> |
||||
<Tool |
||||
Name="VCBscMakeTool" |
||||
/> |
||||
<Tool |
||||
Name="VCFxCopTool" |
||||
/> |
||||
<Tool |
||||
Name="VCAppVerifierTool" |
||||
/> |
||||
<Tool |
||||
Name="VCPostBuildEventTool" |
||||
/> |
||||
</Configuration> |
||||
<Configuration |
||||
Name="Release|Win32" |
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)" |
||||
IntermediateDirectory="$(ConfigurationName)" |
||||
ConfigurationType="1" |
||||
CharacterSet="1" |
||||
WholeProgramOptimization="1" |
||||
> |
||||
<Tool |
||||
Name="VCPreBuildEventTool" |
||||
/> |
||||
<Tool |
||||
Name="VCCustomBuildTool" |
||||
/> |
||||
<Tool |
||||
Name="VCXMLDataGeneratorTool" |
||||
/> |
||||
<Tool |
||||
Name="VCWebServiceProxyGeneratorTool" |
||||
/> |
||||
<Tool |
||||
Name="VCMIDLTool" |
||||
/> |
||||
<Tool |
||||
Name="VCCLCompilerTool" |
||||
Optimization="2" |
||||
EnableIntrinsicFunctions="true" |
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;STATICLIB;_CRT_SECURE_NO_WARNINGS" |
||||
RuntimeLibrary="2" |
||||
EnableFunctionLevelLinking="true" |
||||
UsePrecompiledHeader="0" |
||||
WarningLevel="3" |
||||
DebugInformationFormat="3" |
||||
/> |
||||
<Tool |
||||
Name="VCManagedResourceCompilerTool" |
||||
/> |
||||
<Tool |
||||
Name="VCResourceCompilerTool" |
||||
/> |
||||
<Tool |
||||
Name="VCPreLinkEventTool" |
||||
/> |
||||
<Tool |
||||
Name="VCLinkerTool" |
||||
AdditionalDependencies="ws2_32.lib iphlpapi.lib" |
||||
LinkIncremental="1" |
||||
GenerateDebugInformation="true" |
||||
SubSystem="1" |
||||
OptimizeReferences="2" |
||||
EnableCOMDATFolding="2" |
||||
TargetMachine="1" |
||||
/> |
||||
<Tool |
||||
Name="VCALinkTool" |
||||
/> |
||||
<Tool |
||||
Name="VCManifestTool" |
||||
/> |
||||
<Tool |
||||
Name="VCXDCMakeTool" |
||||
/> |
||||
<Tool |
||||
Name="VCBscMakeTool" |
||||
/> |
||||
<Tool |
||||
Name="VCFxCopTool" |
||||
/> |
||||
<Tool |
||||
Name="VCAppVerifierTool" |
||||
/> |
||||
<Tool |
||||
Name="VCPostBuildEventTool" |
||||
/> |
||||
</Configuration> |
||||
</Configurations> |
||||
<References> |
||||
</References> |
||||
<Files> |
||||
<Filter |
||||
Name="Fichiers sources" |
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" |
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" |
||||
> |
||||
<File |
||||
RelativePath="..\natpmpc.c" |
||||
> |
||||
</File> |
||||
</Filter> |
||||
<Filter |
||||
Name="Fichiers d'en-tête" |
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd" |
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" |
||||
> |
||||
</Filter> |
||||
<Filter |
||||
Name="Fichiers de ressources" |
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav" |
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" |
||||
> |
||||
</Filter> |
||||
</Files> |
||||
<Globals> |
||||
</Globals> |
||||
</VisualStudioProject> |
||||
@ -0,0 +1,157 @@
|
||||
#ifdef __CYGWIN__ |
||||
#include <stdint.h> |
||||
#define __int64 uint64_t |
||||
#endif |
||||
|
||||
#ifdef WIN32 |
||||
#include <windows.h> |
||||
#include <winsock2.h> |
||||
#include <ws2tcpip.h> |
||||
#endif |
||||
|
||||
#include <stdlib.h> |
||||
#include "natpmp.h" |
||||
|
||||
#include "fr_free_miniupnp_libnatpmp_NatPmp.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
JNIEXPORT void JNICALL Java_fr_free_miniupnp_libnatpmp_NatPmp_init (JNIEnv *env, jobject obj, jint forcegw, jint forcedgw) { |
||||
natpmp_t *p = malloc (sizeof(natpmp_t)); |
||||
if (p == NULL) return; |
||||
|
||||
initnatpmp(p, forcegw, (in_addr_t) forcedgw); |
||||
|
||||
jobject wrapped = (*env)->NewDirectByteBuffer(env, p, sizeof(natpmp_t)); |
||||
if (wrapped == NULL) return; |
||||
|
||||
jclass thisClass = (*env)->GetObjectClass(env,obj); |
||||
if (thisClass == NULL) return; |
||||
|
||||
jfieldID fid = (*env)->GetFieldID(env, thisClass, "natpmp", "Ljava/nio/ByteBuffer;"); |
||||
if (fid == NULL) return; |
||||
(*env)->SetObjectField(env, obj, fid, wrapped); |
||||
} |
||||
|
||||
JNIEXPORT void JNICALL Java_fr_free_miniupnp_libnatpmp_NatPmp_free (JNIEnv *env, jobject obj) { |
||||
|
||||
jclass thisClass = (*env)->GetObjectClass(env,obj); |
||||
if (thisClass == NULL) return; |
||||
|
||||
jfieldID fid = (*env)->GetFieldID(env, thisClass, "natpmp", "Ljava/nio/ByteBuffer;"); |
||||
|
||||
if (fid == NULL) return; |
||||
jobject wrapped = (*env)->GetObjectField(env, obj, fid); |
||||
if (wrapped == NULL) return; |
||||
|
||||
natpmp_t* natpmp = (natpmp_t*) (*env)->GetDirectBufferAddress(env, wrapped); |
||||
|
||||
closenatpmp(natpmp); |
||||
|
||||
if (natpmp == NULL) return; |
||||
free(natpmp); |
||||
|
||||
(*env)->SetObjectField(env, obj, fid, NULL); |
||||
} |
||||
|
||||
static natpmp_t* getNatPmp(JNIEnv* env, jobject obj) { |
||||
jclass thisClass = (*env)->GetObjectClass(env,obj); |
||||
if (thisClass == NULL) return NULL; |
||||
|
||||
jfieldID fid = (*env)->GetFieldID(env, thisClass, "natpmp", "Ljava/nio/ByteBuffer;"); |
||||
|
||||
if (fid == NULL) return NULL; |
||||
jobject wrapped = (*env)->GetObjectField(env, obj, fid); |
||||
if (wrapped == NULL) return NULL; |
||||
|
||||
natpmp_t* natpmp = (natpmp_t*) (*env)->GetDirectBufferAddress(env, wrapped); |
||||
|
||||
return natpmp; |
||||
} |
||||
|
||||
JNIEXPORT jint JNICALL Java_fr_free_miniupnp_libnatpmp_NatPmp_sendPublicAddressRequest(JNIEnv* env, jobject obj) { |
||||
natpmp_t* natpmp = getNatPmp(env, obj); |
||||
if (natpmp == NULL) return -1; |
||||
|
||||
return sendpublicaddressrequest(natpmp); |
||||
} |
||||
|
||||
|
||||
JNIEXPORT void JNICALL Java_fr_free_miniupnp_libnatpmp_NatPmp_startup(JNIEnv* env, jclass cls) { |
||||
(void)env; |
||||
(void)cls; |
||||
#ifdef WIN32 |
||||
WSADATA wsaData; |
||||
WORD wVersionRequested = MAKEWORD(2, 2); |
||||
WSAStartup(wVersionRequested, &wsaData); |
||||
#endif |
||||
} |
||||
|
||||
|
||||
JNIEXPORT jint JNICALL Java_fr_free_miniupnp_libnatpmp_NatPmp_sendNewPortMappingRequest(JNIEnv* env, jobject obj, jint protocol, jint privateport, jint publicport, jint lifetime) { |
||||
natpmp_t* natpmp = getNatPmp(env, obj); |
||||
if (natpmp == NULL) return -1; |
||||
|
||||
return sendnewportmappingrequest(natpmp, protocol, privateport, publicport, lifetime); |
||||
} |
||||
|
||||
JNIEXPORT jlong JNICALL Java_fr_free_miniupnp_libnatpmp_NatPmp_getNatPmpRequestTimeout(JNIEnv* env, jobject obj) { |
||||
natpmp_t* natpmp = getNatPmp(env, obj); |
||||
|
||||
struct timeval timeout; |
||||
|
||||
getnatpmprequesttimeout(natpmp, &timeout); |
||||
|
||||
return ((jlong) timeout.tv_sec) * 1000 + (timeout.tv_usec / 1000); |
||||
|
||||
} |
||||
|
||||
#define SET_FIELD(prefix, name, type, longtype) { \ |
||||
jfieldID fid = (*env)->GetFieldID(env, thisClass, #name, type); \
|
||||
if (fid == NULL) return -1; \
|
||||
(*env)->Set ## longtype ## Field(env, response, fid, resp. prefix name); \
|
||||
} |
||||
|
||||
JNIEXPORT jint JNICALL Java_fr_free_miniupnp_libnatpmp_NatPmp_readNatPmpResponseOrRetry(JNIEnv* env, jobject obj, jobject response) { |
||||
|
||||
natpmp_t* natpmp = getNatPmp(env, obj); |
||||
natpmpresp_t resp; |
||||
int result = readnatpmpresponseorretry(natpmp, &resp); |
||||
|
||||
if (result != 0) { |
||||
return result; |
||||
} |
||||
|
||||
jclass thisClass = (*env)->GetObjectClass(env, response); |
||||
if (thisClass == NULL) return -1; |
||||
|
||||
SET_FIELD(,type, "S", Short); |
||||
SET_FIELD(,resultcode, "S", Short); |
||||
|
||||
jfieldID fid = (*env)->GetFieldID(env, thisClass, "epoch", "J"); |
||||
if (fid == NULL) return -1; |
||||
(*env)->SetLongField(env, response, fid, ((jlong)resp.epoch) * 1000); |
||||
|
||||
if (resp.type == 0) { |
||||
jfieldID fid = (*env)->GetFieldID(env, thisClass, "addr", "I"); |
||||
if (fid == NULL) return -1; |
||||
(*env)->SetIntField(env, response, fid, resp.pnu.publicaddress.addr.s_addr); |
||||
|
||||
|
||||
} else { |
||||
SET_FIELD(pnu.newportmapping., privateport, "I", Int); |
||||
SET_FIELD(pnu.newportmapping., mappedpublicport, "I", Int); |
||||
|
||||
jfieldID fid = (*env)->GetFieldID(env, thisClass, "lifetime", "J"); |
||||
if (fid == NULL) return -1; |
||||
(*env)->SetLongField(env, response, fid, ((jlong) resp.pnu.newportmapping.lifetime) * 1000 * 1000); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
@ -0,0 +1,379 @@
|
||||
/* $Id: natpmp.c,v 1.20 2015/05/27 12:43:15 nanard Exp $ */ |
||||
/* libnatpmp
|
||||
Copyright (c) 2007-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. |
||||
*/ |
||||
#ifdef __linux__ |
||||
#define _BSD_SOURCE 1 |
||||
#endif |
||||
#include <string.h> |
||||
#include <time.h> |
||||
#if !defined(_MSC_VER) |
||||
#include <sys/time.h> |
||||
#endif |
||||
#ifdef WIN32 |
||||
#include <errno.h> |
||||
#include <winsock2.h> |
||||
#include <ws2tcpip.h> |
||||
#include <io.h> |
||||
#define EWOULDBLOCK WSAEWOULDBLOCK |
||||
#define ECONNREFUSED WSAECONNREFUSED |
||||
#include "wingettimeofday.h" |
||||
#define gettimeofday natpmp_gettimeofday |
||||
#else |
||||
#include <errno.h> |
||||
#include <unistd.h> |
||||
#include <fcntl.h> |
||||
#include <sys/types.h> |
||||
#include <sys/socket.h> |
||||
#define closesocket close |
||||
#endif |
||||
#include "natpmp.h" |
||||
#include "getgateway.h" |
||||
#include <stdio.h> |
||||
|
||||
LIBSPEC int initnatpmp(natpmp_t * p, int forcegw, in_addr_t forcedgw) |
||||
{ |
||||
#ifdef WIN32 |
||||
u_long ioctlArg = 1; |
||||
#else |
||||
int flags; |
||||
#endif |
||||
struct sockaddr_in addr; |
||||
if(!p) |
||||
return NATPMP_ERR_INVALIDARGS; |
||||
memset(p, 0, sizeof(natpmp_t)); |
||||
p->s = socket(PF_INET, SOCK_DGRAM, 0); |
||||
if(p->s < 0) |
||||
return NATPMP_ERR_SOCKETERROR; |
||||
#ifdef WIN32 |
||||
if(ioctlsocket(p->s, FIONBIO, &ioctlArg) == SOCKET_ERROR) |
||||
return NATPMP_ERR_FCNTLERROR; |
||||
#else |
||||
if((flags = fcntl(p->s, F_GETFL, 0)) < 0) |
||||
return NATPMP_ERR_FCNTLERROR; |
||||
if(fcntl(p->s, F_SETFL, flags | O_NONBLOCK) < 0) |
||||
return NATPMP_ERR_FCNTLERROR; |
||||
#endif |
||||
|
||||
if(forcegw) { |
||||
p->gateway = forcedgw; |
||||
} else { |
||||
if(getdefaultgateway(&(p->gateway)) < 0) |
||||
return NATPMP_ERR_CANNOTGETGATEWAY; |
||||
} |
||||
|
||||
memset(&addr, 0, sizeof(addr)); |
||||
addr.sin_family = AF_INET; |
||||
addr.sin_port = htons(NATPMP_PORT); |
||||
addr.sin_addr.s_addr = p->gateway; |
||||
if(connect(p->s, (struct sockaddr *)&addr, sizeof(addr)) < 0) |
||||
return NATPMP_ERR_CONNECTERR; |
||||
return 0; |
||||
} |
||||
|
||||
LIBSPEC int closenatpmp(natpmp_t * p) |
||||
{ |
||||
if(!p) |
||||
return NATPMP_ERR_INVALIDARGS; |
||||
if(closesocket(p->s) < 0) |
||||
return NATPMP_ERR_CLOSEERR; |
||||
return 0; |
||||
} |
||||
|
||||
int sendpendingrequest(natpmp_t * p) |
||||
{ |
||||
int r; |
||||
/* struct sockaddr_in addr;*/ |
||||
if(!p) |
||||
return NATPMP_ERR_INVALIDARGS; |
||||
/* memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET; |
||||
addr.sin_port = htons(NATPMP_PORT); |
||||
addr.sin_addr.s_addr = p->gateway; |
||||
r = (int)sendto(p->s, p->pending_request, p->pending_request_len, 0, |
||||
(struct sockaddr *)&addr, sizeof(addr));*/ |
||||
r = (int)send(p->s, (const char *)p->pending_request, p->pending_request_len, 0); |
||||
return (r<0) ? NATPMP_ERR_SENDERR : r; |
||||
} |
||||
|
||||
int sendnatpmprequest(natpmp_t * p) |
||||
{ |
||||
int n; |
||||
if(!p) |
||||
return NATPMP_ERR_INVALIDARGS; |
||||
/* TODO : check if no request is already pending */ |
||||
p->has_pending_request = 1; |
||||
p->try_number = 1; |
||||
n = sendpendingrequest(p); |
||||
gettimeofday(&p->retry_time, NULL); // check errors !
|
||||
p->retry_time.tv_usec += 250000; /* add 250ms */ |
||||
if(p->retry_time.tv_usec >= 1000000) { |
||||
p->retry_time.tv_usec -= 1000000; |
||||
p->retry_time.tv_sec++; |
||||
} |
||||
return n; |
||||
} |
||||
|
||||
LIBSPEC int getnatpmprequesttimeout(natpmp_t * p, struct timeval * timeout) |
||||
{ |
||||
struct timeval now; |
||||
if(!p || !timeout) |
||||
return NATPMP_ERR_INVALIDARGS; |
||||
if(!p->has_pending_request) |
||||
return NATPMP_ERR_NOPENDINGREQ; |
||||
if(gettimeofday(&now, NULL) < 0) |
||||
return NATPMP_ERR_GETTIMEOFDAYERR; |
||||
timeout->tv_sec = p->retry_time.tv_sec - now.tv_sec; |
||||
timeout->tv_usec = p->retry_time.tv_usec - now.tv_usec; |
||||
if(timeout->tv_usec < 0) { |
||||
timeout->tv_usec += 1000000; |
||||
timeout->tv_sec--; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
LIBSPEC int sendpublicaddressrequest(natpmp_t * p) |
||||
{ |
||||
if(!p) |
||||
return NATPMP_ERR_INVALIDARGS; |
||||
//static const unsigned char request[] = { 0, 0 };
|
||||
p->pending_request[0] = 0; |
||||
p->pending_request[1] = 0; |
||||
p->pending_request_len = 2; |
||||
// TODO: return 0 instead of sizeof(request) ??
|
||||
return sendnatpmprequest(p); |
||||
} |
||||
|
||||
LIBSPEC int sendnewportmappingrequest(natpmp_t * p, int protocol, |
||||
uint16_t privateport, uint16_t publicport, |
||||
uint32_t lifetime) |
||||
{ |
||||
if(!p || (protocol!=NATPMP_PROTOCOL_TCP && protocol!=NATPMP_PROTOCOL_UDP)) |
||||
return NATPMP_ERR_INVALIDARGS; |
||||
p->pending_request[0] = 0; |
||||
p->pending_request[1] = protocol; |
||||
p->pending_request[2] = 0; |
||||
p->pending_request[3] = 0; |
||||
/* break strict-aliasing rules :
|
||||
*((uint16_t *)(p->pending_request + 4)) = htons(privateport); */ |
||||
p->pending_request[4] = (privateport >> 8) & 0xff; |
||||
p->pending_request[5] = privateport & 0xff; |
||||
/* break stric-aliasing rules :
|
||||
*((uint16_t *)(p->pending_request + 6)) = htons(publicport); */ |
||||
p->pending_request[6] = (publicport >> 8) & 0xff; |
||||
p->pending_request[7] = publicport & 0xff; |
||||
/* break stric-aliasing rules :
|
||||
*((uint32_t *)(p->pending_request + 8)) = htonl(lifetime); */ |
||||
p->pending_request[8] = (lifetime >> 24) & 0xff; |
||||
p->pending_request[9] = (lifetime >> 16) & 0xff; |
||||
p->pending_request[10] = (lifetime >> 8) & 0xff; |
||||
p->pending_request[11] = lifetime & 0xff; |
||||
p->pending_request_len = 12; |
||||
return sendnatpmprequest(p); |
||||
} |
||||
|
||||
LIBSPEC int readnatpmpresponse(natpmp_t * p, natpmpresp_t * response) |
||||
{ |
||||
unsigned char buf[16]; |
||||
struct sockaddr_in addr; |
||||
socklen_t addrlen = sizeof(addr); |
||||
int n; |
||||
if(!p) |
||||
return NATPMP_ERR_INVALIDARGS; |
||||
n = recvfrom(p->s, (char *)buf, sizeof(buf), 0, |
||||
(struct sockaddr *)&addr, &addrlen); |
||||
if(n<0) |
||||
#ifdef WIN32 |
||||
switch(WSAGetLastError()) { |
||||
#else |
||||
switch(errno) { |
||||
#endif |
||||
/*case EAGAIN:*/ |
||||
case EWOULDBLOCK: |
||||
n = NATPMP_TRYAGAIN; |
||||
break; |
||||
case ECONNREFUSED: |
||||
n = NATPMP_ERR_NOGATEWAYSUPPORT; |
||||
break; |
||||
default: |
||||
n = NATPMP_ERR_RECVFROM; |
||||
} |
||||
/* check that addr is correct (= gateway) */ |
||||
else if(addr.sin_addr.s_addr != p->gateway) |
||||
n = NATPMP_ERR_WRONGPACKETSOURCE; |
||||
else { |
||||
response->resultcode = ntohs(*((uint16_t *)(buf + 2))); |
||||
response->epoch = ntohl(*((uint32_t *)(buf + 4))); |
||||
if(buf[0] != 0) |
||||
n = NATPMP_ERR_UNSUPPORTEDVERSION; |
||||
else if(buf[1] < 128 || buf[1] > 130) |
||||
n = NATPMP_ERR_UNSUPPORTEDOPCODE; |
||||
else if(response->resultcode != 0) { |
||||
switch(response->resultcode) { |
||||
case 1: |
||||
n = NATPMP_ERR_UNSUPPORTEDVERSION; |
||||
break; |
||||
case 2: |
||||
n = NATPMP_ERR_NOTAUTHORIZED; |
||||
break; |
||||
case 3: |
||||
n = NATPMP_ERR_NETWORKFAILURE; |
||||
break; |
||||
case 4: |
||||
n = NATPMP_ERR_OUTOFRESOURCES; |
||||
break; |
||||
case 5: |
||||
n = NATPMP_ERR_UNSUPPORTEDOPCODE; |
||||
break; |
||||
default: |
||||
n = NATPMP_ERR_UNDEFINEDERROR; |
||||
} |
||||
} else { |
||||
response->type = buf[1] & 0x7f; |
||||
if(buf[1] == 128) |
||||
//response->publicaddress.addr = *((uint32_t *)(buf + 8));
|
||||
response->pnu.publicaddress.addr.s_addr = *((uint32_t *)(buf + 8)); |
||||
else { |
||||
response->pnu.newportmapping.privateport = ntohs(*((uint16_t *)(buf + 8))); |
||||
response->pnu.newportmapping.mappedpublicport = ntohs(*((uint16_t *)(buf + 10))); |
||||
response->pnu.newportmapping.lifetime = ntohl(*((uint32_t *)(buf + 12))); |
||||
} |
||||
n = 0; |
||||
} |
||||
} |
||||
return n; |
||||
} |
||||
|
||||
int readnatpmpresponseorretry(natpmp_t * p, natpmpresp_t * response) |
||||
{ |
||||
int n; |
||||
if(!p || !response) |
||||
return NATPMP_ERR_INVALIDARGS; |
||||
if(!p->has_pending_request) |
||||
return NATPMP_ERR_NOPENDINGREQ; |
||||
n = readnatpmpresponse(p, response); |
||||
if(n<0) { |
||||
if(n==NATPMP_TRYAGAIN) { |
||||
struct timeval now; |
||||
gettimeofday(&now, NULL); // check errors !
|
||||
if(timercmp(&now, &p->retry_time, >=)) { |
||||
int delay, r; |
||||
if(p->try_number >= 9) { |
||||
return NATPMP_ERR_NOGATEWAYSUPPORT; |
||||
} |
||||
/*printf("retry! %d\n", p->try_number);*/ |
||||
delay = 250 * (1<<p->try_number); // ms
|
||||
/*for(i=0; i<p->try_number; i++)
|
||||
delay += delay;*/ |
||||
p->retry_time.tv_sec += (delay / 1000); |
||||
p->retry_time.tv_usec += (delay % 1000) * 1000; |
||||
if(p->retry_time.tv_usec >= 1000000) { |
||||
p->retry_time.tv_usec -= 1000000; |
||||
p->retry_time.tv_sec++; |
||||
} |
||||
p->try_number++; |
||||
r = sendpendingrequest(p); |
||||
if(r<0) |
||||
return r; |
||||
} |
||||
} |
||||
} else { |
||||
p->has_pending_request = 0; |
||||
} |
||||
return n; |
||||
} |
||||
|
||||
#ifdef ENABLE_STRNATPMPERR |
||||
LIBSPEC const char * strnatpmperr(int r) |
||||
{ |
||||
const char * s; |
||||
switch(r) { |
||||
case NATPMP_ERR_INVALIDARGS: |
||||
s = "invalid arguments"; |
||||
break; |
||||
case NATPMP_ERR_SOCKETERROR: |
||||
s = "socket() failed"; |
||||
break; |
||||
case NATPMP_ERR_CANNOTGETGATEWAY: |
||||
s = "cannot get default gateway ip address"; |
||||
break; |
||||
case NATPMP_ERR_CLOSEERR: |
||||
#ifdef WIN32 |
||||
s = "closesocket() failed"; |
||||
#else |
||||
s = "close() failed"; |
||||
#endif |
||||
break; |
||||
case NATPMP_ERR_RECVFROM: |
||||
s = "recvfrom() failed"; |
||||
break; |
||||
case NATPMP_ERR_NOPENDINGREQ: |
||||
s = "no pending request"; |
||||
break; |
||||
case NATPMP_ERR_NOGATEWAYSUPPORT: |
||||
s = "the gateway does not support nat-pmp"; |
||||
break; |
||||
case NATPMP_ERR_CONNECTERR: |
||||
s = "connect() failed"; |
||||
break; |
||||
case NATPMP_ERR_WRONGPACKETSOURCE: |
||||
s = "packet not received from the default gateway"; |
||||
break; |
||||
case NATPMP_ERR_SENDERR: |
||||
s = "send() failed"; |
||||
break; |
||||
case NATPMP_ERR_FCNTLERROR: |
||||
s = "fcntl() failed"; |
||||
break; |
||||
case NATPMP_ERR_GETTIMEOFDAYERR: |
||||
s = "gettimeofday() failed"; |
||||
break; |
||||
case NATPMP_ERR_UNSUPPORTEDVERSION: |
||||
s = "unsupported nat-pmp version error from server"; |
||||
break; |
||||
case NATPMP_ERR_UNSUPPORTEDOPCODE: |
||||
s = "unsupported nat-pmp opcode error from server"; |
||||
break; |
||||
case NATPMP_ERR_UNDEFINEDERROR: |
||||
s = "undefined nat-pmp server error"; |
||||
break; |
||||
case NATPMP_ERR_NOTAUTHORIZED: |
||||
s = "not authorized"; |
||||
break; |
||||
case NATPMP_ERR_NETWORKFAILURE: |
||||
s = "network failure"; |
||||
break; |
||||
case NATPMP_ERR_OUTOFRESOURCES: |
||||
s = "nat-pmp server out of resources"; |
||||
break; |
||||
default: |
||||
s = "Unknown libnatpmp error"; |
||||
} |
||||
return s; |
||||
} |
||||
#endif |
||||
|
||||
@ -0,0 +1,11 @@
|
||||
LIBRARY |
||||
; libnatpmp library |
||||
|
||||
EXPORTS |
||||
initnatpmp |
||||
closenatpmp |
||||
sendpublicaddressrequest |
||||
sendnewportmappingrequest |
||||
getnatpmprequesttimeout |
||||
readnatpmpresponseorretry |
||||
strnatpmperr |
||||
@ -0,0 +1,219 @@
|
||||
/* $Id: natpmp.h,v 1.20 2014/04/22 09:15:40 nanard Exp $ */ |
||||
/* libnatpmp
|
||||
Copyright (c) 2007-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. |
||||
*/ |
||||
#ifndef __NATPMP_H__ |
||||
#define __NATPMP_H__ |
||||
|
||||
/* NAT-PMP Port as defined by the NAT-PMP draft */ |
||||
#define NATPMP_PORT (5351) |
||||
|
||||
#include <time.h> |
||||
#if !defined(_MSC_VER) |
||||
#include <sys/time.h> |
||||
#endif /* !defined(_MSC_VER) */ |
||||
|
||||
#ifdef WIN32 |
||||
#include <winsock2.h> |
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1600 |
||||
#include <stdint.h> |
||||
#else /* !defined(_MSC_VER) || _MSC_VER >= 1600 */ |
||||
typedef unsigned long uint32_t; |
||||
typedef unsigned short uint16_t; |
||||
#endif /* !defined(_MSC_VER) || _MSC_VER >= 1600 */ |
||||
#define in_addr_t uint32_t |
||||
#include "declspec.h" |
||||
#else /* WIN32 */ |
||||
#define LIBSPEC |
||||
#include <netinet/in.h> |
||||
#endif /* WIN32 */ |
||||
|
||||
/* causes problem when installing. Maybe should it be inlined ? */ |
||||
/* #include "declspec.h" */ |
||||
|
||||
typedef struct { |
||||
int s; /* socket */ |
||||
in_addr_t gateway; /* default gateway (IPv4) */ |
||||
int has_pending_request; |
||||
unsigned char pending_request[12]; |
||||
int pending_request_len; |
||||
int try_number; |
||||
struct timeval retry_time; |
||||
} natpmp_t; |
||||
|
||||
typedef struct { |
||||
uint16_t type; /* NATPMP_RESPTYPE_* */ |
||||
uint16_t resultcode; /* NAT-PMP response code */ |
||||
uint32_t epoch; /* Seconds since start of epoch */ |
||||
union { |
||||
struct { |
||||
//in_addr_t addr;
|
||||
struct in_addr addr; |
||||
} publicaddress; |
||||
struct { |
||||
uint16_t privateport; |
||||
uint16_t mappedpublicport; |
||||
uint32_t lifetime; |
||||
} newportmapping; |
||||
} pnu; |
||||
} natpmpresp_t; |
||||
|
||||
/* possible values for type field of natpmpresp_t */ |
||||
#define NATPMP_RESPTYPE_PUBLICADDRESS (0) |
||||
#define NATPMP_RESPTYPE_UDPPORTMAPPING (1) |
||||
#define NATPMP_RESPTYPE_TCPPORTMAPPING (2) |
||||
|
||||
/* Values to pass to sendnewportmappingrequest() */ |
||||
#define NATPMP_PROTOCOL_UDP (1) |
||||
#define NATPMP_PROTOCOL_TCP (2) |
||||
|
||||
/* return values */ |
||||
/* NATPMP_ERR_INVALIDARGS : invalid arguments passed to the function */ |
||||
#define NATPMP_ERR_INVALIDARGS (-1) |
||||
/* NATPMP_ERR_SOCKETERROR : socket() failed. check errno for details */ |
||||
#define NATPMP_ERR_SOCKETERROR (-2) |
||||
/* NATPMP_ERR_CANNOTGETGATEWAY : can't get default gateway IP */ |
||||
#define NATPMP_ERR_CANNOTGETGATEWAY (-3) |
||||
/* NATPMP_ERR_CLOSEERR : close() failed. check errno for details */ |
||||
#define NATPMP_ERR_CLOSEERR (-4) |
||||
/* NATPMP_ERR_RECVFROM : recvfrom() failed. check errno for details */ |
||||
#define NATPMP_ERR_RECVFROM (-5) |
||||
/* NATPMP_ERR_NOPENDINGREQ : readnatpmpresponseorretry() called while
|
||||
* no NAT-PMP request was pending */ |
||||
#define NATPMP_ERR_NOPENDINGREQ (-6) |
||||
/* NATPMP_ERR_NOGATEWAYSUPPORT : the gateway does not support NAT-PMP */ |
||||
#define NATPMP_ERR_NOGATEWAYSUPPORT (-7) |
||||
/* NATPMP_ERR_CONNECTERR : connect() failed. check errno for details */ |
||||
#define NATPMP_ERR_CONNECTERR (-8) |
||||
/* NATPMP_ERR_WRONGPACKETSOURCE : packet not received from the network gateway */ |
||||
#define NATPMP_ERR_WRONGPACKETSOURCE (-9) |
||||
/* NATPMP_ERR_SENDERR : send() failed. check errno for details */ |
||||
#define NATPMP_ERR_SENDERR (-10) |
||||
/* NATPMP_ERR_FCNTLERROR : fcntl() failed. check errno for details */ |
||||
#define NATPMP_ERR_FCNTLERROR (-11) |
||||
/* NATPMP_ERR_GETTIMEOFDAYERR : gettimeofday() failed. check errno for details */ |
||||
#define NATPMP_ERR_GETTIMEOFDAYERR (-12) |
||||
|
||||
/* */ |
||||
#define NATPMP_ERR_UNSUPPORTEDVERSION (-14) |
||||
#define NATPMP_ERR_UNSUPPORTEDOPCODE (-15) |
||||
|
||||
/* Errors from the server : */ |
||||
#define NATPMP_ERR_UNDEFINEDERROR (-49) |
||||
#define NATPMP_ERR_NOTAUTHORIZED (-51) |
||||
#define NATPMP_ERR_NETWORKFAILURE (-52) |
||||
#define NATPMP_ERR_OUTOFRESOURCES (-53) |
||||
|
||||
/* NATPMP_TRYAGAIN : no data available for the moment. try again later */ |
||||
#define NATPMP_TRYAGAIN (-100) |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/* initnatpmp()
|
||||
* initialize a natpmp_t object |
||||
* With forcegw=1 the gateway is not detected automaticaly. |
||||
* Return values : |
||||
* 0 = OK |
||||
* NATPMP_ERR_INVALIDARGS |
||||
* NATPMP_ERR_SOCKETERROR |
||||
* NATPMP_ERR_FCNTLERROR |
||||
* NATPMP_ERR_CANNOTGETGATEWAY |
||||
* NATPMP_ERR_CONNECTERR */ |
||||
LIBSPEC int initnatpmp(natpmp_t * p, int forcegw, in_addr_t forcedgw); |
||||
|
||||
/* closenatpmp()
|
||||
* close resources associated with a natpmp_t object |
||||
* Return values : |
||||
* 0 = OK |
||||
* NATPMP_ERR_INVALIDARGS |
||||
* NATPMP_ERR_CLOSEERR */ |
||||
LIBSPEC int closenatpmp(natpmp_t * p); |
||||
|
||||
/* sendpublicaddressrequest()
|
||||
* send a public address NAT-PMP request to the network gateway |
||||
* Return values : |
||||
* 2 = OK (size of the request) |
||||
* NATPMP_ERR_INVALIDARGS |
||||
* NATPMP_ERR_SENDERR */ |
||||
LIBSPEC int sendpublicaddressrequest(natpmp_t * p); |
||||
|
||||
/* sendnewportmappingrequest()
|
||||
* send a new port mapping NAT-PMP request to the network gateway |
||||
* Arguments : |
||||
* protocol is either NATPMP_PROTOCOL_TCP or NATPMP_PROTOCOL_UDP, |
||||
* lifetime is in seconds. |
||||
* To remove a port mapping, set lifetime to zero. |
||||
* To remove all port mappings to the host, set lifetime and both ports |
||||
* to zero. |
||||
* Return values : |
||||
* 12 = OK (size of the request) |
||||
* NATPMP_ERR_INVALIDARGS |
||||
* NATPMP_ERR_SENDERR */ |
||||
LIBSPEC int sendnewportmappingrequest(natpmp_t * p, int protocol, |
||||
uint16_t privateport, uint16_t publicport, |
||||
uint32_t lifetime); |
||||
|
||||
/* getnatpmprequesttimeout()
|
||||
* fills the timeval structure with the timeout duration of the |
||||
* currently pending NAT-PMP request. |
||||
* Return values : |
||||
* 0 = OK |
||||
* NATPMP_ERR_INVALIDARGS |
||||
* NATPMP_ERR_GETTIMEOFDAYERR |
||||
* NATPMP_ERR_NOPENDINGREQ */ |
||||
LIBSPEC int getnatpmprequesttimeout(natpmp_t * p, struct timeval * timeout); |
||||
|
||||
/* readnatpmpresponseorretry()
|
||||
* fills the natpmpresp_t structure if possible |
||||
* Return values : |
||||
* 0 = OK |
||||
* NATPMP_TRYAGAIN |
||||
* NATPMP_ERR_INVALIDARGS |
||||
* NATPMP_ERR_NOPENDINGREQ |
||||
* NATPMP_ERR_NOGATEWAYSUPPORT |
||||
* NATPMP_ERR_RECVFROM |
||||
* NATPMP_ERR_WRONGPACKETSOURCE |
||||
* NATPMP_ERR_UNSUPPORTEDVERSION |
||||
* NATPMP_ERR_UNSUPPORTEDOPCODE |
||||
* NATPMP_ERR_NOTAUTHORIZED |
||||
* NATPMP_ERR_NETWORKFAILURE |
||||
* NATPMP_ERR_OUTOFRESOURCES |
||||
* NATPMP_ERR_UNSUPPORTEDOPCODE |
||||
* NATPMP_ERR_UNDEFINEDERROR */ |
||||
LIBSPEC int readnatpmpresponseorretry(natpmp_t * p, natpmpresp_t * response); |
||||
|
||||
#ifdef ENABLE_STRNATPMPERR |
||||
LIBSPEC const char * strnatpmperr(int t); |
||||
#endif |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif |
||||
@ -0,0 +1,19 @@
|
||||
.TH natpmpc 1 |
||||
|
||||
.SH NAME |
||||
natpmpc \- NAT\-PMP library test client and mapping setter. |
||||
|
||||
.SH "SYNOPSIS" |
||||
Display the public IP address: |
||||
.br |
||||
\fBnatpmpc\fP |
||||
|
||||
Add a port mapping: |
||||
.br |
||||
\fBnatpmpc\fP \-a <public port> <private port> <protocol> [lifetime] |
||||
|
||||
.SH DESCRIPTION |
||||
|
||||
In order to remove a mapping, set it with a lifetime of 0 seconds. |
||||
To remove all mappings for your machine, use 0 as private port and |
||||
lifetime. |
||||
@ -0,0 +1,244 @@
|
||||
/* $Id: natpmpc.c,v 1.13 2012/08/21 17:23:38 nanard Exp $ */ |
||||
/* libnatpmp
|
||||
Copyright (c) 2007-2011, 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 <stdio.h> |
||||
#include <errno.h> |
||||
#include <string.h> |
||||
#if defined(_MSC_VER) |
||||
#if _MSC_VER >= 1400 |
||||
#define strcasecmp _stricmp |
||||
#else |
||||
#define strcasecmp stricmp |
||||
#endif |
||||
#else |
||||
#include <unistd.h> |
||||
#endif |
||||
#ifdef WIN32 |
||||
#include <winsock2.h> |
||||
#else |
||||
#include <netinet/in.h> |
||||
#include <arpa/inet.h> |
||||
#endif |
||||
#include "natpmp.h" |
||||
|
||||
void usage(FILE * out, const char * argv0) |
||||
{ |
||||
fprintf(out, "Usage :\n"); |
||||
fprintf(out, " %s [options]\n", argv0); |
||||
fprintf(out, "\tdisplay the public IP address.\n"); |
||||
fprintf(out, " %s -h\n", argv0); |
||||
fprintf(out, "\tdisplay this help screen.\n"); |
||||
fprintf(out, " %s [options] -a <public port> <private port> <protocol> [lifetime]\n", argv0); |
||||
fprintf(out, "\tadd a port mapping.\n"); |
||||
fprintf(out, "\nOption available :\n"); |
||||
fprintf(out, " -g ipv4address\n"); |
||||
fprintf(out, "\tforce the gateway to be used as destination for NAT-PMP commands.\n"); |
||||
fprintf(out, "\n In order to remove a mapping, set it with a lifetime of 0 seconds.\n"); |
||||
fprintf(out, " To remove all mappings for your machine, use 0 as private port and lifetime.\n"); |
||||
} |
||||
|
||||
/* sample code for using libnatpmp */ |
||||
int main(int argc, char * * argv) |
||||
{ |
||||
natpmp_t natpmp; |
||||
natpmpresp_t response; |
||||
int r; |
||||
int sav_errno; |
||||
struct timeval timeout; |
||||
fd_set fds; |
||||
int i; |
||||
int protocol = 0; |
||||
uint16_t privateport = 0; |
||||
uint16_t publicport = 0; |
||||
uint32_t lifetime = 3600; |
||||
int command = 0; |
||||
int forcegw = 0; |
||||
in_addr_t gateway = 0; |
||||
struct in_addr gateway_in_use; |
||||
|
||||
#ifdef WIN32 |
||||
WSADATA wsaData; |
||||
int nResult = WSAStartup(MAKEWORD(2,2), &wsaData); |
||||
if(nResult != NO_ERROR) |
||||
{ |
||||
fprintf(stderr, "WSAStartup() failed.\n"); |
||||
return -1; |
||||
} |
||||
#endif |
||||
|
||||
/* argument parsing */ |
||||
for(i=1; i<argc; i++) { |
||||
if(argv[i][0] == '-') { |
||||
switch(argv[i][1]) { |
||||
case 'h': |
||||
usage(stdout, argv[0]); |
||||
return 0; |
||||
case 'g': |
||||
forcegw = 1; |
||||
if(argc < i + 1) { |
||||
fprintf(stderr, "Not enough arguments for option -%c\n", argv[i][1]); |
||||
return 1; |
||||
} |
||||
gateway = inet_addr(argv[++i]); |
||||
break; |
||||
case 'a': |
||||
command = 'a'; |
||||
if(argc < i + 4) { |
||||
fprintf(stderr, "Not enough arguments for option -%c\n", argv[i][1]); |
||||
return 1; |
||||
} |
||||
i++; |
||||
if(1 != sscanf(argv[i], "%hu", &publicport)) { |
||||
fprintf(stderr, "%s is not a correct 16bits unsigned integer\n", argv[i]); |
||||
return 1; |
||||
} |
||||
i++; |
||||
if(1 != sscanf(argv[i], "%hu", &privateport)) { |
||||
fprintf(stderr, "%s is not a correct 16bits unsigned integer\n", argv[i]); |
||||
return 1; |
||||
} |
||||
i++; |
||||
if(0 == strcasecmp(argv[i], "tcp")) |
||||
protocol = NATPMP_PROTOCOL_TCP; |
||||
else if(0 == strcasecmp(argv[i], "udp")) |
||||
protocol = NATPMP_PROTOCOL_UDP; |
||||
else { |
||||
fprintf(stderr, "%s is not a valid protocol\n", argv[i]); |
||||
return 1; |
||||
} |
||||
if(argc > i + 1) { |
||||
if(1 != sscanf(argv[i+1], "%u", &lifetime)) { |
||||
fprintf(stderr, "%s is not a correct 32bits unsigned integer\n", argv[i]); |
||||
} else { |
||||
i++; |
||||
} |
||||
} |
||||
break; |
||||
default: |
||||
fprintf(stderr, "Unknown option %s\n", argv[i]); |
||||
usage(stderr, argv[0]); |
||||
return 1; |
||||
} |
||||
} else { |
||||
fprintf(stderr, "Unknown option %s\n", argv[i]); |
||||
usage(stderr, argv[0]); |
||||
return 1; |
||||
} |
||||
} |
||||
|
||||
/* initnatpmp() */ |
||||
r = initnatpmp(&natpmp, forcegw, gateway); |
||||
printf("initnatpmp() returned %d (%s)\n", r, r?"FAILED":"SUCCESS"); |
||||
if(r<0) |
||||
return 1; |
||||
|
||||
gateway_in_use.s_addr = natpmp.gateway; |
||||
printf("using gateway : %s\n", inet_ntoa(gateway_in_use)); |
||||
|
||||
/* sendpublicaddressrequest() */ |
||||
r = sendpublicaddressrequest(&natpmp); |
||||
printf("sendpublicaddressrequest returned %d (%s)\n", |
||||
r, r==2?"SUCCESS":"FAILED"); |
||||
if(r<0) |
||||
return 1; |
||||
|
||||
do { |
||||
FD_ZERO(&fds); |
||||
FD_SET(natpmp.s, &fds); |
||||
getnatpmprequesttimeout(&natpmp, &timeout); |
||||
r = select(FD_SETSIZE, &fds, NULL, NULL, &timeout); |
||||
if(r<0) { |
||||
fprintf(stderr, "select()"); |
||||
return 1; |
||||
} |
||||
r = readnatpmpresponseorretry(&natpmp, &response); |
||||
sav_errno = errno; |
||||
printf("readnatpmpresponseorretry returned %d (%s)\n", |
||||
r, r==0?"OK":(r==NATPMP_TRYAGAIN?"TRY AGAIN":"FAILED")); |
||||
if(r<0 && r!=NATPMP_TRYAGAIN) { |
||||
#ifdef ENABLE_STRNATPMPERR |
||||
fprintf(stderr, "readnatpmpresponseorretry() failed : %s\n", |
||||
strnatpmperr(r)); |
||||
#endif |
||||
fprintf(stderr, " errno=%d '%s'\n", |
||||
sav_errno, strerror(sav_errno)); |
||||
} |
||||
} while(r==NATPMP_TRYAGAIN); |
||||
if(r<0) |
||||
return 1; |
||||
|
||||
/* TODO : check that response.type == 0 */ |
||||
printf("Public IP address : %s\n", inet_ntoa(response.pnu.publicaddress.addr)); |
||||
printf("epoch = %u\n", response.epoch); |
||||
|
||||
if(command == 'a') { |
||||
/* sendnewportmappingrequest() */ |
||||
r = sendnewportmappingrequest(&natpmp, protocol, |
||||
privateport, publicport, |
||||
lifetime); |
||||
printf("sendnewportmappingrequest returned %d (%s)\n", |
||||
r, r==12?"SUCCESS":"FAILED"); |
||||
if(r < 0) |
||||
return 1; |
||||
|
||||
do { |
||||
FD_ZERO(&fds); |
||||
FD_SET(natpmp.s, &fds); |
||||
getnatpmprequesttimeout(&natpmp, &timeout); |
||||
select(FD_SETSIZE, &fds, NULL, NULL, &timeout); |
||||
r = readnatpmpresponseorretry(&natpmp, &response); |
||||
printf("readnatpmpresponseorretry returned %d (%s)\n", |
||||
r, r==0?"OK":(r==NATPMP_TRYAGAIN?"TRY AGAIN":"FAILED")); |
||||
} while(r==NATPMP_TRYAGAIN); |
||||
if(r<0) { |
||||
#ifdef ENABLE_STRNATPMPERR |
||||
fprintf(stderr, "readnatpmpresponseorretry() failed : %s\n", |
||||
strnatpmperr(r)); |
||||
#endif |
||||
return 1; |
||||
} |
||||
|
||||
printf("Mapped public port %hu protocol %s to local port %hu " |
||||
"liftime %u\n", |
||||
response.pnu.newportmapping.mappedpublicport, |
||||
response.type == NATPMP_RESPTYPE_UDPPORTMAPPING ? "UDP" : |
||||
(response.type == NATPMP_RESPTYPE_TCPPORTMAPPING ? "TCP" : |
||||
"UNKNOWN"), |
||||
response.pnu.newportmapping.privateport, |
||||
response.pnu.newportmapping.lifetime); |
||||
printf("epoch = %u\n", response.epoch); |
||||
} |
||||
|
||||
r = closenatpmp(&natpmp); |
||||
printf("closenatpmp() returned %d (%s)\n", r, r==0?"SUCCESS":"FAILED"); |
||||
if(r<0) |
||||
return 1; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
@ -0,0 +1,18 @@
|
||||
#! /usr/bin/python |
||||
# $Id: setup.py,v 1.3 2012/03/05 04:54:01 nanard Exp $ |
||||
# |
||||
# python script to build the libnatpmp module under unix |
||||
# |
||||
# replace libnatpmp.a by libnatpmp.so for shared library usage |
||||
from distutils.core import setup, Extension |
||||
from distutils import sysconfig |
||||
sysconfig.get_config_vars()["OPT"] = '' |
||||
sysconfig.get_config_vars()["CFLAGS"] = '' |
||||
setup(name="libnatpmp", version="1.0", |
||||
ext_modules=[ |
||||
Extension(name="libnatpmp", sources=["libnatpmpmodule.c"], |
||||
extra_objects=["libnatpmp.a"], |
||||
define_macros=[('ENABLE_STRNATPMPERR', None)] |
||||
)] |
||||
) |
||||
|
||||
@ -0,0 +1,17 @@
|
||||
#! /usr/bin/python |
||||
# $Id: setupmingw32.py,v 1.3 2012/03/05 04:54:01 nanard Exp $ |
||||
# python script to build the miniupnpc module under windows |
||||
# |
||||
from distutils.core import setup, Extension |
||||
from distutils import sysconfig |
||||
sysconfig.get_config_vars()["OPT"] = '' |
||||
sysconfig.get_config_vars()["CFLAGS"] = '' |
||||
setup(name="libnatpmp", version="1.0", |
||||
ext_modules=[ |
||||
Extension(name="libnatpmp", sources=["libnatpmpmodule.c"], |
||||
libraries=["ws2_32"], |
||||
extra_objects=["libnatpmp.a"], |
||||
define_macros=[('ENABLE_STRNATPMPERR', None)] |
||||
)] |
||||
) |
||||
|
||||
@ -0,0 +1,57 @@
|
||||
/* $Id: testgetgateway.c,v 1.7 2012/08/21 17:13:31 nanard Exp $ */ |
||||
/* libnatpmp
|
||||
Copyright (c) 2007-2011, 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 <stdio.h> |
||||
#ifdef WIN32 |
||||
#include <winsock2.h> |
||||
#else |
||||
#include <netinet/in.h> |
||||
#include <arpa/inet.h> |
||||
#endif |
||||
#include "getgateway.h" |
||||
|
||||
int main(int argc, char * * argv) |
||||
{ |
||||
(void)argc; |
||||
(void)argv; |
||||
struct in_addr gatewayaddr; |
||||
int r; |
||||
#ifdef WIN32 |
||||
uint32_t temp = 0; |
||||
r = getdefaultgateway(&temp); |
||||
gatewayaddr.S_un.S_addr = temp; |
||||
#else |
||||
r = getdefaultgateway(&(gatewayaddr.s_addr)); |
||||
#endif |
||||
if(r>=0) |
||||
printf("default gateway : %s\n", inet_ntoa(gatewayaddr)); |
||||
else |
||||
fprintf(stderr, "getdefaultgateway() failed\n"); |
||||
return 0; |
||||
} |
||||
|
||||
@ -0,0 +1,60 @@
|
||||
/* $Id: wingettimeofday.c,v 1.6 2013/09/10 20:13:26 nanard Exp $ */ |
||||
/* libnatpmp
|
||||
Copyright (c) 2007-2013, 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. |
||||
*/ |
||||
#ifdef WIN32 |
||||
#if defined(_MSC_VER) |
||||
struct timeval { |
||||
long tv_sec; |
||||
long tv_usec; |
||||
}; |
||||
#else |
||||
#include <sys/time.h> |
||||
#endif |
||||
|
||||
typedef struct _FILETIME { |
||||
unsigned long dwLowDateTime; |
||||
unsigned long dwHighDateTime; |
||||
} FILETIME; |
||||
|
||||
void __stdcall GetSystemTimeAsFileTime(FILETIME*); |
||||
|
||||
int natpmp_gettimeofday(struct timeval* p, void* tz /* IGNORED */) { |
||||
union { |
||||
long long ns100; /*time since 1 Jan 1601 in 100ns units */ |
||||
FILETIME ft; |
||||
} _now; |
||||
|
||||
if(!p) |
||||
return -1; |
||||
GetSystemTimeAsFileTime( &(_now.ft) ); |
||||
p->tv_usec =(long)((_now.ns100 / 10LL) % 1000000LL ); |
||||
p->tv_sec = (long)((_now.ns100-(116444736000000000LL))/10000000LL); |
||||
return 0; |
||||
} |
||||
#endif |
||||
|
||||
@ -0,0 +1,39 @@
|
||||
/* $Id: wingettimeofday.h,v 1.5 2013/09/11 07:22:25 nanard Exp $ */ |
||||
/* libnatpmp
|
||||
Copyright (c) 2007-2013, 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. |
||||
*/ |
||||
#ifndef __WINGETTIMEOFDAY_H__ |
||||
#define __WINGETTIMEOFDAY_H__ |
||||
#ifdef WIN32 |
||||
#if defined(_MSC_VER) |
||||
#include <time.h> |
||||
#else |
||||
#include <sys/time.h> |
||||
#endif |
||||
int natpmp_gettimeofday(struct timeval* p, void* tz /* IGNORED */); |
||||
#endif |
||||
#endif |
||||
@ -0,0 +1,314 @@
|
||||
/*
|
||||
* ZeroTier One - Network Virtualization Everywhere |
||||
* Copyright (C) 2011-2015 ZeroTier, Inc. |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* 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. If not, see <http://www.gnu.org/licenses/>.
|
||||
* |
||||
* -- |
||||
* |
||||
* ZeroTier may be used and distributed under the terms of the GPLv3, which |
||||
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
|
||||
* |
||||
* If you would like to embed ZeroTier into a commercial application or |
||||
* redistribute it in a modified binary form, please contact ZeroTier Networks |
||||
* LLC. Start here: http://www.zerotier.com/
|
||||
*/ |
||||
|
||||
#ifdef ZT_USE_MINIUPNPC |
||||
|
||||
// Uncomment to dump debug messages
|
||||
#define ZT_PORTMAPPER_TRACE 1 |
||||
|
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include <string> |
||||
|
||||
#include "../node/Utils.hpp" |
||||
#include "OSUtils.hpp" |
||||
#include "PortMapper.hpp" |
||||
|
||||
#ifdef __WINDOWS__ |
||||
#ifndef MINIUPNP_STATICLIB |
||||
#define MINIUPNP_STATICLIB |
||||
#endif |
||||
#endif |
||||
|
||||
#include "../ext/miniupnpc/miniupnpc.h" |
||||
#include "../ext/miniupnpc/upnpcommands.h" |
||||
#include "../ext/libnatpmp/natpmp.h" |
||||
|
||||
namespace ZeroTier { |
||||
|
||||
class PortMapperImpl |
||||
{ |
||||
public: |
||||
PortMapperImpl(int localUdpPortToMap,const char *un) : |
||||
run(true), |
||||
localPort(localUdpPortToMap), |
||||
uniqueName(un) |
||||
{ |
||||
} |
||||
|
||||
~PortMapperImpl() {} |
||||
|
||||
void threadMain() |
||||
throw() |
||||
{ |
||||
int mode = 0; // 0 == NAT-PMP, 1 == UPnP
|
||||
|
||||
#ifdef ZT_PORTMAPPER_TRACE |
||||
fprintf(stderr,"PortMapper: started for UDP port %d"ZT_EOL_S,localPort); |
||||
#endif |
||||
|
||||
while (run) { |
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// NAT-PMP mode (preferred)
|
||||
// ---------------------------------------------------------------------
|
||||
if (mode == 0) { |
||||
natpmp_t natpmp; |
||||
natpmpresp_t response; |
||||
int r = 0; |
||||
|
||||
bool natPmpSuccess = false; |
||||
for(int tries=0;tries<60;++tries) { |
||||
int tryPort = (int)localPort + tries; |
||||
if (tryPort >= 65535) |
||||
tryPort = (tryPort - 65535) + 1025; |
||||
|
||||
memset(&natpmp,0,sizeof(natpmp)); |
||||
memset(&response,0,sizeof(response)); |
||||
|
||||
if (initnatpmp(&natpmp,0,0) != 0) { |
||||
mode = 1; |
||||
#ifdef ZT_PORTMAPPER_TRACE |
||||
fprintf(stderr,"PortMapper: NAT-PMP: init failed, switching to UPnP mode"ZT_EOL_S); |
||||
#endif |
||||
break; |
||||
} |
||||
|
||||
InetAddress publicAddress; |
||||
sendpublicaddressrequest(&natpmp); |
||||
uint64_t myTimeout = OSUtils::now() + 30000; |
||||
do { |
||||
fd_set fds; |
||||
struct timeval timeout; |
||||
FD_ZERO(&fds); |
||||
FD_SET(natpmp.s, &fds); |
||||
getnatpmprequesttimeout(&natpmp, &timeout); |
||||
select(FD_SETSIZE, &fds, NULL, NULL, &timeout); |
||||
r = readnatpmpresponseorretry(&natpmp, &response); |
||||
if (OSUtils::now() >= myTimeout) |
||||
break; |
||||
} while (r == NATPMP_TRYAGAIN); |
||||
if (r == 0) { |
||||
publicAddress = InetAddress((uint32_t)response.pnu.publicaddress.addr.s_addr,0); |
||||
} else { |
||||
#ifdef ZT_PORTMAPPER_TRACE |
||||
fprintf(stderr,"PortMapper: NAT-PMP: request for external address failed, aborting..."ZT_EOL_S); |
||||
#endif |
||||
break; |
||||
} |
||||
|
||||
sendnewportmappingrequest(&natpmp,NATPMP_PROTOCOL_UDP,localPort,tryPort,(ZT_PORTMAPPER_REFRESH_DELAY * 2) / 1000); |
||||
do { |
||||
fd_set fds; |
||||
struct timeval timeout; |
||||
FD_ZERO(&fds); |
||||
FD_SET(natpmp.s, &fds); |
||||
getnatpmprequesttimeout(&natpmp, &timeout); |
||||
select(FD_SETSIZE, &fds, NULL, NULL, &timeout); |
||||
r = readnatpmpresponseorretry(&natpmp, &response); |
||||
} while (r == NATPMP_TRYAGAIN); |
||||
if (r == 0) { |
||||
publicAddress.setPort(response.pnu.newportmapping.mappedpublicport); |
||||
#ifdef ZT_PORTMAPPER_TRACE |
||||
fprintf(stderr,"PortMapper: NAT-PMP: mapped %u to %s"ZT_EOL_S,(unsigned int)localPort,publicAddress.toString().c_str()); |
||||
#endif |
||||
Mutex::Lock sl(surface_l); |
||||
surface.clear(); |
||||
surface.push_back(publicAddress); |
||||
natPmpSuccess = true; |
||||
break; |
||||
} |
||||
|
||||
closenatpmp(&natpmp); |
||||
} |
||||
|
||||
if (!natPmpSuccess) { |
||||
mode = 1; |
||||
#ifdef ZT_PORTMAPPER_TRACE |
||||
fprintf(stderr,"PortMapper: NAT-PMP: request failed, switching to UPnP mode"ZT_EOL_S); |
||||
#endif |
||||
} |
||||
} |
||||
// ---------------------------------------------------------------------
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// UPnP mode
|
||||
// ---------------------------------------------------------------------
|
||||
if (mode == 1) { |
||||
char lanaddr[4096]; |
||||
char externalip[4096]; // no range checking? so make these buffers larger than any UDP packet a uPnP server could send us as a precaution :P
|
||||
char inport[16]; |
||||
char outport[16]; |
||||
struct UPNPUrls urls; |
||||
struct IGDdatas data; |
||||
|
||||
int upnpError = 0; |
||||
UPNPDev *devlist = upnpDiscover(5000,(const char *)0,(const char *)0,0,0,0,&upnpError); |
||||
if (devlist) { |
||||
|
||||
#ifdef ZT_PORTMAPPER_TRACE |
||||
{ |
||||
UPNPDev *dev = devlist; |
||||
while (dev) { |
||||
fprintf(stderr,"PortMapper: found UPnP device at URL '%s': %s"ZT_EOL_S,dev->descURL,dev->st); |
||||
dev = dev->pNext; |
||||
} |
||||
} |
||||
#endif |
||||
|
||||
memset(lanaddr,0,sizeof(lanaddr)); |
||||
memset(externalip,0,sizeof(externalip)); |
||||
memset(&urls,0,sizeof(urls)); |
||||
memset(&data,0,sizeof(data)); |
||||
Utils::snprintf(inport,sizeof(inport),"%d",localPort); |
||||
|
||||
if ((UPNP_GetValidIGD(devlist,&urls,&data,lanaddr,sizeof(lanaddr)))&&(lanaddr[0])) { |
||||
#ifdef ZT_PORTMAPPER_TRACE |
||||
fprintf(stderr,"PortMapper: UPnP: my LAN IP address: %s"ZT_EOL_S,lanaddr); |
||||
#endif |
||||
if ((UPNP_GetExternalIPAddress(urls.controlURL,data.first.servicetype,externalip) == UPNPCOMMAND_SUCCESS)&&(externalip[0])) { |
||||
#ifdef ZT_PORTMAPPER_TRACE |
||||
fprintf(stderr,"PortMapper: UPnP: my external IP address: %s"ZT_EOL_S,externalip); |
||||
#endif |
||||
|
||||
for(int tries=0;tries<60;++tries) { |
||||
int tryPort = (int)localPort + tries; |
||||
if (tryPort >= 65535) |
||||
tryPort = (tryPort - 65535) + 1025; |
||||
Utils::snprintf(outport,sizeof(outport),"%u",tryPort); |
||||
|
||||
// First check and see if this port is already mapped to the
|
||||
// same unique name. If so, keep this mapping and don't try
|
||||
// to map again since this can break buggy routers. But don't
|
||||
// fail if this command fails since not all routers support it.
|
||||
{ |
||||
char haveIntClient[128]; // 128 == big enough for all these as per miniupnpc "documentation"
|
||||
char haveIntPort[128]; |
||||
char haveDesc[128]; |
||||
char haveEnabled[128]; |
||||
char haveLeaseDuration[128]; |
||||
memset(haveIntClient,0,sizeof(haveIntClient)); |
||||
memset(haveIntPort,0,sizeof(haveIntPort)); |
||||
memset(haveDesc,0,sizeof(haveDesc)); |
||||
memset(haveEnabled,0,sizeof(haveEnabled)); |
||||
memset(haveLeaseDuration,0,sizeof(haveLeaseDuration)); |
||||
if ((UPNP_GetSpecificPortMappingEntry(urls.controlURL,data.first.servicetype,outport,"UDP",(const char *)0,haveIntClient,haveIntPort,haveDesc,haveEnabled,haveLeaseDuration) == UPNPCOMMAND_SUCCESS)&&(uniqueName == haveDesc)) { |
||||
#ifdef ZT_PORTMAPPER_TRACE |
||||
fprintf(stderr,"PortMapper: UPnP: reusing previously reserved external port: %s"ZT_EOL_S,outport); |
||||
#endif |
||||
Mutex::Lock sl(surface_l); |
||||
surface.clear(); |
||||
InetAddress tmp(externalip); |
||||
tmp.setPort(tryPort); |
||||
surface.push_back(tmp); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
// Try to map this port
|
||||
int mapResult = 0; |
||||
if ((mapResult = UPNP_AddPortMapping(urls.controlURL,data.first.servicetype,outport,inport,lanaddr,uniqueName.c_str(),"UDP",(const char *)0,"0")) == UPNPCOMMAND_SUCCESS) { |
||||
#ifdef ZT_PORTMAPPER_TRACE |
||||
fprintf(stderr,"PortMapper: UPnP: reserved external port: %s"ZT_EOL_S,outport); |
||||
#endif |
||||
Mutex::Lock sl(surface_l); |
||||
surface.clear(); |
||||
InetAddress tmp(externalip); |
||||
tmp.setPort(tryPort); |
||||
surface.push_back(tmp); |
||||
break; |
||||
} else { |
||||
#ifdef ZT_PORTMAPPER_TRACE |
||||
fprintf(stderr,"PortMapper: UPnP: UPNP_AddPortMapping(%s) failed: %d"ZT_EOL_S,outport,mapResult); |
||||
#endif |
||||
Thread::sleep(1000); |
||||
} |
||||
} |
||||
|
||||
} else { |
||||
mode = 0; |
||||
#ifdef ZT_PORTMAPPER_TRACE |
||||
fprintf(stderr,"PortMapper: UPnP: UPNP_GetExternalIPAddress failed, returning to NAT-PMP mode"ZT_EOL_S); |
||||
#endif |
||||
} |
||||
} else { |
||||
mode = 0; |
||||
#ifdef ZT_PORTMAPPER_TRACE |
||||
fprintf(stderr,"PortMapper: UPnP: UPNP_GetValidIGD failed, returning to NAT-PMP mode"ZT_EOL_S); |
||||
#endif |
||||
} |
||||
|
||||
freeUPNPDevlist(devlist); |
||||
|
||||
} else { |
||||
mode = 0; |
||||
#ifdef ZT_PORTMAPPER_TRACE |
||||
fprintf(stderr,"PortMapper: upnpDiscover failed, returning to NAT-PMP mode: %d"ZT_EOL_S,upnpError); |
||||
#endif |
||||
} |
||||
} |
||||
// ---------------------------------------------------------------------
|
||||
|
||||
#ifdef ZT_PORTMAPPER_TRACE |
||||
fprintf(stderr,"UPNPClient: rescanning in %d ms"ZT_EOL_S,ZT_PORTMAPPER_REFRESH_DELAY); |
||||
#endif |
||||
Thread::sleep(ZT_PORTMAPPER_REFRESH_DELAY); |
||||
} |
||||
|
||||
delete this; |
||||
} |
||||
|
||||
volatile bool run; |
||||
int localPort; |
||||
std::string uniqueName; |
||||
|
||||
Mutex surface_l; |
||||
std::vector<InetAddress> surface; |
||||
}; |
||||
|
||||
PortMapper::PortMapper(int localUdpPortToMap,const char *uniqueName) |
||||
{ |
||||
_impl = new PortMapperImpl(localUdpPortToMap,uniqueName); |
||||
Thread::start(_impl); |
||||
} |
||||
|
||||
PortMapper::~PortMapper() |
||||
{ |
||||
_impl->run = false; |
||||
} |
||||
|
||||
std::vector<InetAddress> PortMapper::get() const |
||||
{ |
||||
Mutex::Lock _l(_impl->surface_l); |
||||
return _impl->surface; |
||||
} |
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif // ZT_USE_MINIUPNPC
|
||||
@ -1,198 +0,0 @@
|
||||
/*
|
||||
* ZeroTier One - Network Virtualization Everywhere |
||||
* Copyright (C) 2011-2015 ZeroTier, Inc. |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* 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. If not, see <http://www.gnu.org/licenses/>.
|
||||
* |
||||
* -- |
||||
* |
||||
* ZeroTier may be used and distributed under the terms of the GPLv3, which |
||||
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
|
||||
* |
||||
* If you would like to embed ZeroTier into a commercial application or |
||||
* redistribute it in a modified binary form, please contact ZeroTier Networks |
||||
* LLC. Start here: http://www.zerotier.com/
|
||||
*/ |
||||
|
||||
#ifdef ZT_USE_MINIUPNPC |
||||
|
||||
// Uncomment to dump debug messages
|
||||
//#define ZT_UPNP_TRACE 1
|
||||
|
||||
// Uncomment to build a main() for ad-hoc testing
|
||||
//#define ZT_UPNP_TEST 1
|
||||
|
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include "../node/Utils.hpp" |
||||
#include "UPNPClient.hpp" |
||||
|
||||
#ifdef __WINDOWS__ |
||||
#ifndef MINIUPNP_STATICLIB |
||||
#define MINIUPNP_STATICLIB |
||||
#endif |
||||
#endif |
||||
|
||||
#include "../ext/miniupnpc/miniupnpc.h" |
||||
#include "../ext/miniupnpc/upnpcommands.h" |
||||
|
||||
namespace ZeroTier { |
||||
|
||||
class UPNPClientImpl |
||||
{ |
||||
public: |
||||
UPNPClientImpl(int localUdpPortToMap) : |
||||
run(true), |
||||
localPort(localUdpPortToMap) |
||||
{ |
||||
} |
||||
|
||||
void threadMain() |
||||
throw() |
||||
{ |
||||
char lanaddr[4096]; |
||||
char externalip[4096]; // no range checking? so make these buffers larger than any UDP packet a uPnP server could send us as a precaution :P
|
||||
char inport[16]; |
||||
char outport[16]; |
||||
struct UPNPUrls urls; |
||||
struct IGDdatas data; |
||||
|
||||
#ifdef ZT_UPNP_TRACE |
||||
fprintf(stderr,"UPNPClient: started for UDP port %d"ZT_EOL_S,localPort); |
||||
#endif |
||||
|
||||
unsigned int tryPortStart = 0; |
||||
Utils::getSecureRandom(&tryPortStart,sizeof(tryPortStart)); |
||||
tryPortStart = (tryPortStart % (65535 - 1025)) + 1025; |
||||
|
||||
while (run) { |
||||
{ |
||||
int upnpError = 0; |
||||
UPNPDev *devlist = upnpDiscover(2000,(const char *)0,(const char *)0,0,0,0,&upnpError); |
||||
if (devlist) { |
||||
#ifdef ZT_UPNP_TRACE |
||||
{ |
||||
UPNPDev *dev = devlist; |
||||
while (dev) { |
||||
fprintf(stderr,"UPNPClient: found device at URL '%s': %s"ZT_EOL_S,dev->descURL,dev->st); |
||||
dev = dev->pNext; |
||||
} |
||||
} |
||||
#endif |
||||
|
||||
memset(lanaddr,0,sizeof(lanaddr)); |
||||
memset(externalip,0,sizeof(externalip)); |
||||
memset(&urls,0,sizeof(urls)); |
||||
memset(&data,0,sizeof(data)); |
||||
Utils::snprintf(inport,sizeof(inport),"%d",localPort); |
||||
|
||||
if ((UPNP_GetValidIGD(devlist,&urls,&data,lanaddr,sizeof(lanaddr)))&&(lanaddr[0])) { |
||||
#ifdef ZT_UPNP_TRACE |
||||
fprintf(stderr,"UPNPClient: my LAN IP address: %s"ZT_EOL_S,lanaddr); |
||||
#endif |
||||
if ((UPNP_GetExternalIPAddress(urls.controlURL,data.first.servicetype,externalip) == UPNPCOMMAND_SUCCESS)&&(externalip[0])) { |
||||
#ifdef ZT_UPNP_TRACE |
||||
fprintf(stderr,"UPNPClient: my external IP address: %s"ZT_EOL_S,externalip); |
||||
#endif |
||||
|
||||
for(int tries=0;tries<64;++tries) { |
||||
int tryPort = (int)tryPortStart + tries; |
||||
if (tryPort >= 65535) |
||||
tryPort = (tryPort - 65535) + 1025; |
||||
Utils::snprintf(outport,sizeof(outport),"%u",tryPort); |
||||
|
||||
int mapResult = 0; |
||||
if ((mapResult = UPNP_AddPortMapping(urls.controlURL,data.first.servicetype,outport,inport,lanaddr,"ZeroTier","UDP",(const char *)0,"0")) == UPNPCOMMAND_SUCCESS) { |
||||
#ifdef ZT_UPNP_TRACE |
||||
fprintf(stderr,"UPNPClient: reserved external port: %s"ZT_EOL_S,outport); |
||||
#endif |
||||
{ |
||||
Mutex::Lock sl(surface_l); |
||||
surface.clear(); |
||||
InetAddress tmp(externalip); |
||||
tmp.setPort(tryPort); |
||||
surface.push_back(tmp); |
||||
} |
||||
break; |
||||
} else { |
||||
#ifdef ZT_UPNP_TRACE |
||||
fprintf(stderr,"UPNPClient: UPNP_AddAnyPortMapping(%s) failed: %d"ZT_EOL_S,outport,mapResult); |
||||
#endif |
||||
Thread::sleep(1000); |
||||
} |
||||
} |
||||
} else { |
||||
#ifdef ZT_UPNP_TRACE |
||||
fprintf(stderr,"UPNPClient: UPNP_GetExternalIPAddress failed"ZT_EOL_S); |
||||
#endif |
||||
} |
||||
} else { |
||||
#ifdef ZT_UPNP_TRACE |
||||
fprintf(stderr,"UPNPClient: UPNP_GetValidIGD failed"ZT_EOL_S); |
||||
#endif |
||||
} |
||||
|
||||
freeUPNPDevlist(devlist); |
||||
} else { |
||||
#ifdef ZT_UPNP_TRACE |
||||
fprintf(stderr,"UPNPClient: upnpDiscover error code: %d"ZT_EOL_S,upnpError); |
||||
#endif |
||||
} |
||||
} |
||||
|
||||
#ifdef ZT_UPNP_TRACE |
||||
fprintf(stderr,"UPNPClient: rescanning in %d ms"ZT_EOL_S,ZT_UPNP_CLIENT_REFRESH_DELAY); |
||||
#endif |
||||
Thread::sleep(ZT_UPNP_CLIENT_REFRESH_DELAY); |
||||
} |
||||
delete this; |
||||
} |
||||
|
||||
volatile bool run; |
||||
int localPort; |
||||
Mutex surface_l; |
||||
std::vector<InetAddress> surface; |
||||
}; |
||||
|
||||
UPNPClient::UPNPClient(int localUdpPortToMap) |
||||
{ |
||||
_impl = new UPNPClientImpl(localUdpPortToMap); |
||||
Thread::start(_impl); |
||||
} |
||||
|
||||
UPNPClient::~UPNPClient() |
||||
{ |
||||
_impl->run = false; |
||||
} |
||||
|
||||
std::vector<InetAddress> UPNPClient::get() const |
||||
{ |
||||
Mutex::Lock _l(_impl->surface_l); |
||||
return _impl->surface; |
||||
} |
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#ifdef ZT_UPNP_TEST |
||||
int main(int argc,char **argv) |
||||
{ |
||||
ZeroTier::UPNPClient *client = new ZeroTier::UPNPClient(12345); |
||||
ZeroTier::Thread::sleep(0xffffffff); // wait forever
|
||||
return 0; |
||||
} |
||||
#endif |
||||
|
||||
#endif // ZT_USE_MINIUPNPC
|
||||
Loading…
Reference in new issue