mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2024-12-19 13:07:55 +00:00
Merge dev
This commit is contained in:
commit
7e28161638
98
ext/libnatpmp/Changelog.txt
Normal file
98
ext/libnatpmp/Changelog.txt
Normal file
@ -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
|
||||
|
42
ext/libnatpmp/JavaTest.java
Normal file
42
ext/libnatpmp/JavaTest.java
Normal file
@ -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)};
|
||||
}
|
||||
}
|
26
ext/libnatpmp/LICENSE
Normal file
26
ext/libnatpmp/LICENSE
Normal file
@ -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.
|
||||
|
177
ext/libnatpmp/Makefile
Normal file
177
ext/libnatpmp/Makefile
Normal file
@ -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
|
7
ext/libnatpmp/README
Normal file
7
ext/libnatpmp/README
Normal file
@ -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.
|
||||
|
30
ext/libnatpmp/build.bat
Normal file
30
ext/libnatpmp/build.bat
Normal file
@ -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
|
21
ext/libnatpmp/declspec.h
Normal file
21
ext/libnatpmp/declspec.h
Normal file
@ -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
|
||||
|
238
ext/libnatpmp/fr/free/miniupnp/libnatpmp/LibraryExtractor.java
Normal file
238
ext/libnatpmp/fr/free/miniupnp/libnatpmp/LibraryExtractor.java
Normal file
@ -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());
|
||||
}
|
||||
}
|
50
ext/libnatpmp/fr/free/miniupnp/libnatpmp/NatPmp.java
Normal file
50
ext/libnatpmp/fr/free/miniupnp/libnatpmp/NatPmp.java
Normal file
@ -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);
|
||||
|
||||
}
|
28
ext/libnatpmp/fr/free/miniupnp/libnatpmp/NatPmpResponse.java
Normal file
28
ext/libnatpmp/fr/free/miniupnp/libnatpmp/NatPmpResponse.java
Normal file
@ -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
|
||||
|
||||
}
|
81
ext/libnatpmp/fr/free/miniupnp/libnatpmp/URLUtils.java
Normal file
81
ext/libnatpmp/fr/free/miniupnp/libnatpmp/URLUtils.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
573
ext/libnatpmp/getgateway.c
Normal file
573
ext/libnatpmp/getgateway.c
Normal file
@ -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
|
49
ext/libnatpmp/getgateway.h
Normal file
49
ext/libnatpmp/getgateway.h
Normal file
@ -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
|
281
ext/libnatpmp/libnatpmpmodule.c
Normal file
281
ext/libnatpmp/libnatpmpmodule.c
Normal file
@ -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);
|
||||
}
|
||||
|
29
ext/libnatpmp/msvc/libnatpmp.sln
Normal file
29
ext/libnatpmp/msvc/libnatpmp.sln
Normal file
@ -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
|
195
ext/libnatpmp/msvc/libnatpmp.vcproj
Normal file
195
ext/libnatpmp/msvc/libnatpmp.vcproj
Normal file
@ -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>
|
195
ext/libnatpmp/msvc/natpmpc-static.vcproj
Normal file
195
ext/libnatpmp/msvc/natpmpc-static.vcproj
Normal file
@ -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>
|
157
ext/libnatpmp/natpmp-jni.c
Normal file
157
ext/libnatpmp/natpmp-jni.c
Normal file
@ -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
|
379
ext/libnatpmp/natpmp.c
Normal file
379
ext/libnatpmp/natpmp.c
Normal file
@ -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
|
||||
|
11
ext/libnatpmp/natpmp.def
Normal file
11
ext/libnatpmp/natpmp.def
Normal file
@ -0,0 +1,11 @@
|
||||
LIBRARY
|
||||
; libnatpmp library
|
||||
|
||||
EXPORTS
|
||||
initnatpmp
|
||||
closenatpmp
|
||||
sendpublicaddressrequest
|
||||
sendnewportmappingrequest
|
||||
getnatpmprequesttimeout
|
||||
readnatpmpresponseorretry
|
||||
strnatpmperr
|
219
ext/libnatpmp/natpmp.h
Normal file
219
ext/libnatpmp/natpmp.h
Normal file
@ -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
|
19
ext/libnatpmp/natpmpc.1
Normal file
19
ext/libnatpmp/natpmpc.1
Normal file
@ -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.
|
244
ext/libnatpmp/natpmpc.c
Normal file
244
ext/libnatpmp/natpmpc.c
Normal file
@ -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;
|
||||
}
|
||||
|
18
ext/libnatpmp/setup.py
Normal file
18
ext/libnatpmp/setup.py
Normal file
@ -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)]
|
||||
)]
|
||||
)
|
||||
|
17
ext/libnatpmp/setupmingw32.py
Normal file
17
ext/libnatpmp/setupmingw32.py
Normal file
@ -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)]
|
||||
)]
|
||||
)
|
||||
|
57
ext/libnatpmp/testgetgateway.c
Normal file
57
ext/libnatpmp/testgetgateway.c
Normal file
@ -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;
|
||||
}
|
||||
|
60
ext/libnatpmp/wingettimeofday.c
Normal file
60
ext/libnatpmp/wingettimeofday.c
Normal file
@ -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
|
||||
|
39
ext/libnatpmp/wingettimeofday.h
Normal file
39
ext/libnatpmp/wingettimeofday.h
Normal file
@ -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
|
@ -24,8 +24,6 @@
|
||||
#define OS_STRING "Win32"
|
||||
#define MINIUPNPC_VERSION_STRING "1.9"
|
||||
#define UPNP_VERSION_STRING "UPnP/1.1"
|
||||
#else
|
||||
#include "miniupnpcstrings.h"
|
||||
#endif
|
||||
|
||||
/* only for malloc */
|
||||
@ -126,5 +124,3 @@ int soapPostSubmit(int fd,
|
||||
#endif
|
||||
return httpWrite(fd, body, bodysize, headerbuf, headerssize);
|
||||
}
|
||||
|
||||
|
||||
|
@ -54,8 +54,6 @@
|
||||
#define OS_STRING "Win32"
|
||||
#define MINIUPNPC_VERSION_STRING "1.9"
|
||||
#define UPNP_VERSION_STRING "UPnP/1.1"
|
||||
#else
|
||||
#include "miniupnpcstrings.h"
|
||||
#endif
|
||||
#include "miniwget.h"
|
||||
#include "connecthostport.h"
|
||||
@ -630,4 +628,3 @@ miniwget_getaddr(const char * url, int * size,
|
||||
#endif
|
||||
return miniwget2(hostname, port, path, size, addr, addrlen, scope_id);
|
||||
}
|
||||
|
||||
|
@ -43,9 +43,8 @@ ifeq ($(ZT_OFFICIAL_RELEASE),1)
|
||||
endif
|
||||
|
||||
ifeq ($(ZT_USE_MINIUPNPC),1)
|
||||
DEFS+=-DZT_USE_MINIUPNPC
|
||||
LDLIBS+=ext/miniupnpc/libminiupnpc.a
|
||||
OBJS+=osdep/UPNPClient.o
|
||||
DEFS+=-DZT_USE_MINIUPNPC -DMINIUPNP_STATICLIB -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -DOS_STRING=\"Linux\" -DMINIUPNPC_VERSION_STRING=\"1.9\" -DUPNP_VERSION_STRING=\"UPnP/1.1\" -DENABLE_STRNATPMPERR
|
||||
OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o osdep/PortMapper.o
|
||||
endif
|
||||
|
||||
# Build with ZT_ENABLE_NETWORK_CONTROLLER=1 to build with the Sqlite network controller
|
||||
@ -65,8 +64,13 @@ ifeq ($(ZT_DEBUG),1)
|
||||
DEFS+=-DZT_TRACE
|
||||
CFLAGS+=-Wall -g -pthread $(INCLUDES) $(DEFS)
|
||||
CXXFLAGS+=-Wall -g -pthread $(INCLUDES) $(DEFS)
|
||||
<<<<<<< HEAD
|
||||
LDFLAGS=-ldl
|
||||
STRIP=echo
|
||||
=======
|
||||
LDFLAGS=
|
||||
STRIP?=echo
|
||||
>>>>>>> origin/dev
|
||||
# The following line enables optimization for the crypto code, since
|
||||
# C25519 in particular is almost UNUSABLE in -O0 even on a 3ghz box!
|
||||
ext/lz4/lz4.o node/Salsa20.o node/SHA512.o node/C25519.o node/Poly1305.o: CFLAGS = -Wall -O2 -g -pthread $(INCLUDES) $(DEFS)
|
||||
@ -74,9 +78,16 @@ else
|
||||
CFLAGS?=-O3 -fstack-protector
|
||||
CFLAGS+=-Wall -fPIE -fvisibility=hidden -pthread $(INCLUDES) -DNDEBUG $(DEFS)
|
||||
CXXFLAGS?=-O3 -fstack-protector
|
||||
<<<<<<< HEAD
|
||||
CXXFLAGS+=-Wall -Wreorder -fPIE -fvisibility=hidden -fno-rtti -pthread $(INCLUDES) -DNDEBUG $(DEFS)
|
||||
LDFLAGS=-ldl -pie -Wl,-z,relro,-z,now
|
||||
STRIP=strip --strip-all
|
||||
=======
|
||||
CXXFLAGS+=-Wall -fPIE -fvisibility=hidden -fno-rtti -pthread $(INCLUDES) -DNDEBUG $(DEFS)
|
||||
LDFLAGS=-pie -Wl,-z,relro,-z,now
|
||||
STRIP?=strip
|
||||
STRIP+=--strip-all
|
||||
>>>>>>> origin/dev
|
||||
endif
|
||||
|
||||
ifeq ($(ZT_TRACE),1)
|
||||
@ -92,9 +103,6 @@ endif
|
||||
all: one
|
||||
|
||||
one: $(OBJS) one.o
|
||||
ifeq ($(ZT_USE_MINIUPNPC),1)
|
||||
cd ext/miniupnpc ; make clean ; make 'CFLAGS=-O2 -fstack-protector -fPIE -fno-common -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600' -j 2 libminiupnpc.a
|
||||
endif
|
||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-one $(OBJS) one.o $(LDLIBS)
|
||||
$(STRIP) zerotier-one
|
||||
ln -sf zerotier-one zerotier-idtool
|
||||
@ -108,6 +116,7 @@ installer: one FORCE
|
||||
./ext/installfiles/linux/buildinstaller.sh
|
||||
|
||||
clean:
|
||||
<<<<<<< HEAD
|
||||
find ./ -type f -name '*.o' -delete
|
||||
find netcon/ -type f -name '*.so' -delete
|
||||
find netcon/ -type f -name '*.1.0' -delete
|
||||
@ -116,6 +125,9 @@ clean:
|
||||
find netcon/docker-test -name "zerotier-intercept" -type f -delete
|
||||
rm -rf zerotier-one zerotier-idtool zerotier-cli zerotier-selftest zerotier-netcon build-* ZeroTierOneInstaller-* *.deb *.rpm *.pkg *.tgz
|
||||
cd ext/miniupnpc ; make clean
|
||||
=======
|
||||
rm -rf *.o node/*.o controller/*.o osdep/*.o service/*.o ext/http-parser/*.o ext/lz4/*.o ext/json-parser/*.o $(OBJS) zerotier-one zerotier-idtool zerotier-cli zerotier-selftest build-* ZeroTierOneInstaller-* *.deb *.rpm
|
||||
>>>>>>> origin/dev
|
||||
|
||||
debug: FORCE
|
||||
make ZT_DEBUG=1 one
|
||||
|
11
make-mac.mk
11
make-mac.mk
@ -42,9 +42,8 @@ ifeq ($(ZT_AUTO_UPDATE),1)
|
||||
endif
|
||||
|
||||
ifeq ($(ZT_USE_MINIUPNPC),1)
|
||||
DEFS+=-DZT_USE_MINIUPNPC
|
||||
LIBS+=ext/miniupnpc/libminiupnpc.a
|
||||
OBJS+=osdep/UPNPClient.o
|
||||
DEFS+=-DMACOSX -DZT_USE_MINIUPNPC -DMINIUPNP_STATICLIB -D_DARWIN_C_SOURCE -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -DOS_STRING=\"Darwin/15.0.0\" -DMINIUPNPC_VERSION_STRING=\"1.9\" -DUPNP_VERSION_STRING=\"UPnP/1.1\" -DENABLE_STRNATPMPERR
|
||||
OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o osdep/PortMapper.o
|
||||
endif
|
||||
|
||||
# Build with ZT_ENABLE_NETWORK_CONTROLLER=1 to build with the Sqlite network controller
|
||||
@ -73,9 +72,6 @@ CXXFLAGS=$(CFLAGS) -fno-rtti
|
||||
all: one
|
||||
|
||||
one: $(OBJS) one.o
|
||||
ifeq ($(ZT_USE_MINIUPNPC),1)
|
||||
cd ext/miniupnpc ; make clean ; make 'CFLAGS=-D_DARWIN_C_SOURCE -O2 -fstack-protector -fPIE -flto -pthread -mmacosx-version-min=10.7 -fno-common -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE' -j 2 libminiupnpc.a
|
||||
endif
|
||||
$(CXX) $(CXXFLAGS) -o zerotier-one $(OBJS) one.o $(LIBS)
|
||||
$(STRIP) zerotier-one
|
||||
ln -sf zerotier-one zerotier-idtool
|
||||
@ -101,8 +97,7 @@ official: FORCE
|
||||
make ZT_OFFICIAL_RELEASE=1 mac-dist-pkg
|
||||
|
||||
clean:
|
||||
rm -rf *.dSYM build-* *.pkg *.dmg *.o node/*.o controller/*.o service/*.o osdep/*.o ext/http-parser/*.o ext/lz4/*.o ext/json-parser/*.o zerotier-one zerotier-idtool zerotier-selftest zerotier-cli ZeroTierOneInstaller-* mkworld
|
||||
cd ext/miniupnpc ; make clean
|
||||
rm -rf *.dSYM build-* *.pkg *.dmg *.o node/*.o controller/*.o service/*.o osdep/*.o ext/http-parser/*.o ext/lz4/*.o ext/json-parser/*.o $(OBJS) zerotier-one zerotier-idtool zerotier-selftest zerotier-cli ZeroTierOneInstaller-* mkworld
|
||||
|
||||
# For those building from source -- installs signed binary tap driver in system ZT home
|
||||
install-mac-tap: FORCE
|
||||
|
@ -343,7 +343,7 @@
|
||||
/**
|
||||
* Maximum number of paths per IP scope (e.g. global, link-local) and family (e.g. v4/v6)
|
||||
*/
|
||||
#define ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY 1
|
||||
#define ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY 4
|
||||
|
||||
/**
|
||||
* A test pseudo-network-ID that can be joined
|
||||
|
@ -210,8 +210,8 @@ static bool ___removeIp(const std::string &_dev,const InetAddress &ip)
|
||||
long cpid = (long)vfork();
|
||||
if (cpid == 0) {
|
||||
OSUtils::redirectUnixOutputs("/dev/null",(const char *)0);
|
||||
::execl("/sbin/ip","/sbin/ip","addr","del",ip.toString().c_str(),"dev",_dev.c_str(),(const char *)0);
|
||||
::execl("/usr/sbin/ip","/usr/sbin/ip","addr","del",ip.toString().c_str(),"dev",_dev.c_str(),(const char *)0);
|
||||
setenv("PATH", "/sbin:/bin:/usr/sbin:/usr/bin", 1);
|
||||
::execlp("ip","ip","addr","del",ip.toString().c_str(),"dev",_dev.c_str(),(const char *)0);
|
||||
::_exit(-1);
|
||||
} else {
|
||||
int exitcode = -1;
|
||||
@ -238,12 +238,11 @@ bool LinuxEthernetTap::addIp(const InetAddress &ip)
|
||||
long cpid = (long)vfork();
|
||||
if (cpid == 0) {
|
||||
OSUtils::redirectUnixOutputs("/dev/null",(const char *)0);
|
||||
setenv("PATH", "/sbin:/bin:/usr/sbin:/usr/bin", 1);
|
||||
if (ip.isV4()) {
|
||||
::execl("/sbin/ip","/sbin/ip","addr","add",ip.toString().c_str(),"broadcast",ip.broadcast().toIpString().c_str(),"dev",_dev.c_str(),(const char *)0);
|
||||
::execl("/usr/sbin/ip","/usr/sbin/ip","addr","add",ip.toString().c_str(),"broadcast",ip.broadcast().toIpString().c_str(),"dev",_dev.c_str(),(const char *)0);
|
||||
::execlp("ip","ip","addr","add",ip.toString().c_str(),"broadcast",ip.broadcast().toIpString().c_str(),"dev",_dev.c_str(),(const char *)0);
|
||||
} else {
|
||||
::execl("/sbin/ip","/sbin/ip","addr","add",ip.toString().c_str(),"dev",_dev.c_str(),(const char *)0);
|
||||
::execl("/usr/sbin/ip","/usr/sbin/ip","addr","add",ip.toString().c_str(),"dev",_dev.c_str(),(const char *)0);
|
||||
::execlp("ip","ip","addr","add",ip.toString().c_str(),"dev",_dev.c_str(),(const char *)0);
|
||||
}
|
||||
::_exit(-1);
|
||||
} else if (cpid > 0) {
|
||||
|
320
osdep/PortMapper.cpp
Normal file
320
osdep/PortMapper.cpp
Normal file
@ -0,0 +1,320 @@
|
||||
/*
|
||||
* 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() + 5000;
|
||||
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
|
||||
closenatpmp(&natpmp);
|
||||
break;
|
||||
}
|
||||
|
||||
sendnewportmappingrequest(&natpmp,NATPMP_PROTOCOL_UDP,localPort,tryPort,(ZT_PORTMAPPER_REFRESH_DELAY * 2) / 1000);
|
||||
myTimeout = OSUtils::now() + 10000;
|
||||
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.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;
|
||||
closenatpmp(&natpmp);
|
||||
break;
|
||||
} else {
|
||||
closenatpmp(&natpmp);
|
||||
// continue
|
||||
}
|
||||
}
|
||||
|
||||
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 = upnpDiscoverAll(5000,(const char *)0,(const char *)0,0,0,2,&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
|
@ -25,11 +25,11 @@
|
||||
* LLC. Start here: http://www.zerotier.com/
|
||||
*/
|
||||
|
||||
#ifndef ZT_UPNPCLIENT_HPP
|
||||
#define ZT_UPNPCLIENT_HPP
|
||||
|
||||
#ifdef ZT_USE_MINIUPNPC
|
||||
|
||||
#ifndef ZT_PORTMAPPER_HPP
|
||||
#define ZT_PORTMAPPER_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
@ -40,28 +40,29 @@
|
||||
/**
|
||||
* How frequently should we refresh our UPNP/NAT-PnP/whatever state?
|
||||
*/
|
||||
#define ZT_UPNP_CLIENT_REFRESH_DELAY 600000
|
||||
#define ZT_PORTMAPPER_REFRESH_DELAY 300000
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class UPNPClientImpl;
|
||||
class PortMapperImpl;
|
||||
|
||||
/**
|
||||
* UPnP/NAT-PnP daemon thread
|
||||
* UPnP/NAT-PnP port mapping "daemon"
|
||||
*/
|
||||
class UPNPClient
|
||||
class PortMapper
|
||||
{
|
||||
friend class UPNPClientImpl;
|
||||
friend class PortMapperImpl;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create and start UPNP client service
|
||||
* Create and start port mapper service
|
||||
*
|
||||
* @param localUdpPortToMap Port we want visible to the outside world
|
||||
* @param name Unique name of this endpoint (based on ZeroTier address)
|
||||
*/
|
||||
UPNPClient(int localUdpPortToMap);
|
||||
PortMapper(int localUdpPortToMap,const char *uniqueName);
|
||||
|
||||
~UPNPClient();
|
||||
~PortMapper();
|
||||
|
||||
/**
|
||||
* @return All current external mappings for our port
|
||||
@ -69,11 +70,11 @@ public:
|
||||
std::vector<InetAddress> get() const;
|
||||
|
||||
private:
|
||||
UPNPClientImpl *_impl;
|
||||
PortMapperImpl *_impl;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif // ZT_USE_MINIUPNPC
|
||||
|
||||
#endif
|
||||
|
||||
#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
|
11
selftest.cpp
11
selftest.cpp
@ -58,6 +58,8 @@
|
||||
#include "osdep/Phy.hpp"
|
||||
#include "osdep/Http.hpp"
|
||||
#include "osdep/BackgroundResolver.hpp"
|
||||
#include "osdep/PortMapper.hpp"
|
||||
#include "osdep/Thread.hpp"
|
||||
|
||||
#ifdef ZT_ENABLE_NETWORK_CONTROLLER
|
||||
#include "controller/SqliteNetworkController.hpp"
|
||||
@ -1094,6 +1096,7 @@ int main(int argc,char **argv)
|
||||
|
||||
srand((unsigned int)time(0));
|
||||
|
||||
/*
|
||||
r |= testSqliteNetworkController();
|
||||
r |= testOther();
|
||||
r |= testCrypto();
|
||||
@ -1103,9 +1106,17 @@ int main(int argc,char **argv)
|
||||
r |= testPhy();
|
||||
r |= testResolver();
|
||||
//r |= testHttp();
|
||||
*/
|
||||
|
||||
if (r)
|
||||
std::cout << std::endl << "SOMETHING FAILED!" << std::endl;
|
||||
|
||||
#ifdef ZT_USE_MINIUPNPC
|
||||
std::cout << std::endl;
|
||||
std::cout << "[portmapper] Starting port mapper and waiting forever... use CTRL+C to exit. (enable ZT_PORTMAPPER_TRACE in PortMapper.cpp for output)" << std::endl;
|
||||
PortMapper mapper(12345,"ZeroTier/__selftest");
|
||||
Thread::sleep(0xffffffff);
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -54,7 +54,7 @@
|
||||
#include "../osdep/OSUtils.hpp"
|
||||
#include "../osdep/Http.hpp"
|
||||
#include "../osdep/BackgroundResolver.hpp"
|
||||
#include "../osdep/UPNPClient.hpp"
|
||||
#include "../osdep/PortMapper.hpp"
|
||||
|
||||
#include "OneService.hpp"
|
||||
#include "ControlPlane.hpp"
|
||||
@ -467,7 +467,7 @@ public:
|
||||
,_port(0)
|
||||
#ifdef ZT_USE_MINIUPNPC
|
||||
,_v4UpnpUdpSocket((PhySocket *)0)
|
||||
,_upnpClient((UPNPClient *)0)
|
||||
,_portMapper((PortMapper *)0)
|
||||
#endif
|
||||
#ifdef ZT_ENABLE_CLUSTER
|
||||
,_clusterMessageSocket((PhySocket *)0)
|
||||
@ -523,22 +523,6 @@ public:
|
||||
char portstr[64];
|
||||
Utils::snprintf(portstr,sizeof(portstr),"%u",_port);
|
||||
OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S + "zerotier-one.port").c_str(),std::string(portstr));
|
||||
|
||||
#ifdef ZT_USE_MINIUPNPC
|
||||
// Bind a secondary port for use with uPnP, since some NAT routers
|
||||
// (cough Ubiquity Edge cough) barf up a lung if you do both conventional
|
||||
// NAT-t and uPnP from behind the same port. I think this is a bug, but
|
||||
// everyone else's router bugs are our problem. :P
|
||||
for(int k=0;k<512;++k) {
|
||||
const unsigned int upnport = 40000 + (((port + 1) * (k + 1)) % 25500);
|
||||
_v4UpnpLocalAddress = InetAddress(0,upnport);
|
||||
_v4UpnpUdpSocket = _phy.udpBind((const struct sockaddr *)&_v4UpnpLocalAddress,reinterpret_cast<void *>(&_v4UpnpLocalAddress),ZT_UDP_DESIRED_BUF_SIZE);
|
||||
if (_v4UpnpUdpSocket) {
|
||||
_upnpClient = new UPNPClient(upnport);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual ~OneServiceImpl()
|
||||
@ -552,7 +536,7 @@ public:
|
||||
#endif
|
||||
#ifdef ZT_USE_MINIUPNPC
|
||||
_phy.close(_v4UpnpUdpSocket);
|
||||
delete _upnpClient;
|
||||
delete _portMapper;
|
||||
#endif
|
||||
#ifdef ZT_ENABLE_NETWORK_CONTROLLER
|
||||
delete _controller;
|
||||
@ -595,73 +579,91 @@ public:
|
||||
SnodeVirtualNetworkConfigFunction,
|
||||
SnodeEventCallback);
|
||||
|
||||
#ifdef ZT_USE_MINIUPNPC
|
||||
// Bind a secondary port for use with uPnP, since some NAT routers
|
||||
// (cough Ubiquity Edge cough) barf up a lung if you do both conventional
|
||||
// NAT-t and uPnP from behind the same port. I think this is a bug, but
|
||||
// everyone else's router bugs are our problem. :P
|
||||
for(int k=0;k<512;++k) {
|
||||
unsigned int mapperPort = 40000 + (((_port + 1) * (k + 1)) % 25500);
|
||||
char uniqueName[64];
|
||||
_v4UpnpLocalAddress = InetAddress(0,mapperPort);
|
||||
_v4UpnpUdpSocket = _phy.udpBind((const struct sockaddr *)&_v4UpnpLocalAddress,reinterpret_cast<void *>(&_v4UpnpLocalAddress),ZT_UDP_DESIRED_BUF_SIZE);
|
||||
if (_v4UpnpUdpSocket) {
|
||||
Utils::snprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.16llx",_node->address());
|
||||
_portMapper = new PortMapper(mapperPort,uniqueName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ZT_ENABLE_NETWORK_CONTROLLER
|
||||
_controller = new SqliteNetworkController(_node,(_homePath + ZT_PATH_SEPARATOR_S + ZT_CONTROLLER_DB_PATH).c_str(),(_homePath + ZT_PATH_SEPARATOR_S + "circuitTestResults.d").c_str());
|
||||
_node->setNetconfMaster((void *)_controller);
|
||||
#endif
|
||||
|
||||
#ifdef ZT_ENABLE_CLUSTER
|
||||
if (OSUtils::fileExists((_homePath + ZT_PATH_SEPARATOR_S + "cluster").c_str())) {
|
||||
_clusterDefinition = new ClusterDefinition(_node->address(),(_homePath + ZT_PATH_SEPARATOR_S + "cluster").c_str());
|
||||
if (_clusterDefinition->size() > 0) {
|
||||
std::vector<ClusterDefinition::MemberDefinition> members(_clusterDefinition->members());
|
||||
for(std::vector<ClusterDefinition::MemberDefinition>::iterator m(members.begin());m!=members.end();++m) {
|
||||
PhySocket *cs = _phy.udpBind(reinterpret_cast<const struct sockaddr *>(&(m->clusterEndpoint)));
|
||||
if (cs) {
|
||||
if (_clusterMessageSocket) {
|
||||
_phy.close(_clusterMessageSocket,false);
|
||||
_phy.close(cs,false);
|
||||
|
||||
Mutex::Lock _l(_termReason_m);
|
||||
_termReason = ONE_UNRECOVERABLE_ERROR;
|
||||
_fatalErrorMessage = "Cluster: can't determine my cluster member ID: able to bind more than one cluster message socket IP/port!";
|
||||
return _termReason;
|
||||
}
|
||||
_clusterMessageSocket = cs;
|
||||
_clusterMemberId = m->id;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_clusterMessageSocket) {
|
||||
Mutex::Lock _l(_termReason_m);
|
||||
_termReason = ONE_UNRECOVERABLE_ERROR;
|
||||
_fatalErrorMessage = "Cluster: can't determine my cluster member ID: unable to bind to any cluster message socket IP/port.";
|
||||
return _termReason;
|
||||
}
|
||||
|
||||
if (OSUtils::fileExists((_homePath + ZT_PATH_SEPARATOR_S + "cluster-geo.exe").c_str()))
|
||||
_clusterGeoIpService = new ClusterGeoIpService((_homePath + ZT_PATH_SEPARATOR_S + "cluster-geo.exe").c_str());
|
||||
|
||||
const ClusterDefinition::MemberDefinition &me = (*_clusterDefinition)[_clusterMemberId];
|
||||
InetAddress endpoints[255];
|
||||
unsigned int numEndpoints = 0;
|
||||
for(std::vector<InetAddress>::const_iterator i(me.zeroTierEndpoints.begin());i!=me.zeroTierEndpoints.end();++i)
|
||||
endpoints[numEndpoints++] = *i;
|
||||
|
||||
if (_node->clusterInit(
|
||||
_clusterMemberId,
|
||||
reinterpret_cast<const struct sockaddr_storage *>(endpoints),
|
||||
numEndpoints,
|
||||
me.x,
|
||||
me.y,
|
||||
me.z,
|
||||
&SclusterSendFunction,
|
||||
this,
|
||||
(_clusterGeoIpService) ? &SclusterGeoIpFunction : 0,
|
||||
this) == ZT_RESULT_OK) {
|
||||
|
||||
if (OSUtils::fileExists((_homePath + ZT_PATH_SEPARATOR_S + "cluster").c_str())) {
|
||||
_clusterDefinition = new ClusterDefinition(_node->address(),(_homePath + ZT_PATH_SEPARATOR_S + "cluster").c_str());
|
||||
if (_clusterDefinition->size() > 0) {
|
||||
std::vector<ClusterDefinition::MemberDefinition> members(_clusterDefinition->members());
|
||||
for(std::vector<ClusterDefinition::MemberDefinition>::iterator m(members.begin());m!=members.end();++m) {
|
||||
if (m->id != _clusterMemberId)
|
||||
_node->clusterAddMember(m->id);
|
||||
PhySocket *cs = _phy.udpBind(reinterpret_cast<const struct sockaddr *>(&(m->clusterEndpoint)));
|
||||
if (cs) {
|
||||
if (_clusterMessageSocket) {
|
||||
_phy.close(_clusterMessageSocket,false);
|
||||
_phy.close(cs,false);
|
||||
|
||||
Mutex::Lock _l(_termReason_m);
|
||||
_termReason = ONE_UNRECOVERABLE_ERROR;
|
||||
_fatalErrorMessage = "Cluster: can't determine my cluster member ID: able to bind more than one cluster message socket IP/port!";
|
||||
return _termReason;
|
||||
}
|
||||
_clusterMessageSocket = cs;
|
||||
_clusterMemberId = m->id;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_clusterMessageSocket) {
|
||||
Mutex::Lock _l(_termReason_m);
|
||||
_termReason = ONE_UNRECOVERABLE_ERROR;
|
||||
_fatalErrorMessage = "Cluster: can't determine my cluster member ID: unable to bind to any cluster message socket IP/port.";
|
||||
return _termReason;
|
||||
}
|
||||
|
||||
if (OSUtils::fileExists((_homePath + ZT_PATH_SEPARATOR_S + "cluster-geo.exe").c_str()))
|
||||
_clusterGeoIpService = new ClusterGeoIpService((_homePath + ZT_PATH_SEPARATOR_S + "cluster-geo.exe").c_str());
|
||||
|
||||
const ClusterDefinition::MemberDefinition &me = (*_clusterDefinition)[_clusterMemberId];
|
||||
InetAddress endpoints[255];
|
||||
unsigned int numEndpoints = 0;
|
||||
for(std::vector<InetAddress>::const_iterator i(me.zeroTierEndpoints.begin());i!=me.zeroTierEndpoints.end();++i)
|
||||
endpoints[numEndpoints++] = *i;
|
||||
|
||||
if (_node->clusterInit(
|
||||
_clusterMemberId,
|
||||
reinterpret_cast<const struct sockaddr_storage *>(endpoints),
|
||||
numEndpoints,
|
||||
me.x,
|
||||
me.y,
|
||||
me.z,
|
||||
&SclusterSendFunction,
|
||||
this,
|
||||
(_clusterGeoIpService) ? &SclusterGeoIpFunction : 0,
|
||||
this) == ZT_RESULT_OK) {
|
||||
|
||||
std::vector<ClusterDefinition::MemberDefinition> members(_clusterDefinition->members());
|
||||
for(std::vector<ClusterDefinition::MemberDefinition>::iterator m(members.begin());m!=members.end();++m) {
|
||||
if (m->id != _clusterMemberId)
|
||||
_node->clusterAddMember(m->id);
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
delete _clusterDefinition;
|
||||
_clusterDefinition = (ClusterDefinition *)0;
|
||||
}
|
||||
} else {
|
||||
delete _clusterDefinition;
|
||||
_clusterDefinition = (ClusterDefinition *)0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
_controlPlane = new ControlPlane(this,_node,(_homePath + ZT_PATH_SEPARATOR_S + "ui").c_str());
|
||||
@ -689,7 +691,7 @@ public:
|
||||
_lastRestart = clockShouldBe;
|
||||
uint64_t lastTapMulticastGroupCheck = 0;
|
||||
uint64_t lastTcpFallbackResolve = 0;
|
||||
uint64_t lastLocalInterfaceAddressCheck = (OSUtils::now() - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give UPnP time to configure and other things time to settle
|
||||
uint64_t lastLocalInterfaceAddressCheck = (OSUtils::now() - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to configure and other things time to settle
|
||||
#ifdef ZT_AUTO_UPDATE
|
||||
uint64_t lastSoftwareUpdateCheck = 0;
|
||||
#endif // ZT_AUTO_UPDATE
|
||||
@ -757,8 +759,8 @@ public:
|
||||
_node->clearLocalInterfaceAddresses();
|
||||
|
||||
#ifdef ZT_USE_MINIUPNPC
|
||||
std::vector<InetAddress> upnpAddresses(_upnpClient->get());
|
||||
for(std::vector<InetAddress>::const_iterator ext(upnpAddresses.begin());ext!=upnpAddresses.end();++ext)
|
||||
std::vector<InetAddress> mappedAddresses(_portMapper->get());
|
||||
for(std::vector<InetAddress>::const_iterator ext(mappedAddresses.begin());ext!=mappedAddresses.end();++ext)
|
||||
_node->addLocalInterfaceAddress(reinterpret_cast<const struct sockaddr_storage *>(&(*ext)));
|
||||
#endif
|
||||
|
||||
@ -1162,11 +1164,13 @@ public:
|
||||
newAssignedIps.erase(std::unique(newAssignedIps.begin(),newAssignedIps.end()),newAssignedIps.end());
|
||||
for(std::vector<InetAddress>::iterator ip(newAssignedIps.begin());ip!=newAssignedIps.end();++ip) {
|
||||
if (!std::binary_search(assignedIps.begin(),assignedIps.end(),*ip))
|
||||
t->second->addIp(*ip);
|
||||
if (!t->second->addIp(*ip))
|
||||
fprintf(stderr,"ERROR: unable to add ip address %s"ZT_EOL_S, ip->toString().c_str());
|
||||
}
|
||||
for(std::vector<InetAddress>::iterator ip(assignedIps.begin());ip!=assignedIps.end();++ip) {
|
||||
if (!std::binary_search(newAssignedIps.begin(),newAssignedIps.end(),*ip))
|
||||
t->second->removeIp(*ip);
|
||||
if (!t->second->removeIp(*ip))
|
||||
fprintf(stderr,"ERROR: unable to remove ip address %s"ZT_EOL_S, ip->toString().c_str());
|
||||
}
|
||||
assignedIps.swap(newAssignedIps);
|
||||
} else {
|
||||
@ -1485,7 +1489,7 @@ public:
|
||||
#ifdef ZT_USE_MINIUPNPC
|
||||
InetAddress _v4UpnpLocalAddress;
|
||||
PhySocket *_v4UpnpUdpSocket;
|
||||
UPNPClient *_upnpClient;
|
||||
PortMapper *_portMapper;
|
||||
#endif
|
||||
|
||||
#ifdef ZT_ENABLE_CLUSTER
|
||||
|
Loading…
Reference in New Issue
Block a user