aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac2
-rw-r--r--src/include/gnunet_nat_lib.h52
-rw-r--r--src/nat/Makefile.am12
-rw-r--r--src/nat/libnatpmp/Makefile.am16
-rw-r--r--src/nat/libnatpmp/README4
-rw-r--r--src/nat/libnatpmp/declspec.h14
-rw-r--r--src/nat/libnatpmp/getgateway.c531
-rw-r--r--src/nat/libnatpmp/getgateway.h32
-rw-r--r--src/nat/libnatpmp/natpmp.c409
-rw-r--r--src/nat/libnatpmp/natpmp.h202
-rw-r--r--src/nat/miniupnp/Makefile.am31
-rw-r--r--src/nat/miniupnp/README3
-rw-r--r--src/nat/miniupnp/bsdqueue.h531
-rw-r--r--src/nat/miniupnp/codelength.h23
-rw-r--r--src/nat/miniupnp/declspec.h14
-rw-r--r--src/nat/miniupnp/igd_desc_parse.c126
-rw-r--r--src/nat/miniupnp/igd_desc_parse.h47
-rw-r--r--src/nat/miniupnp/minisoap.c106
-rw-r--r--src/nat/miniupnp/minisoap.h14
-rw-r--r--src/nat/miniupnp/minissdpc.c111
-rw-r--r--src/nat/miniupnp/minissdpc.h14
-rw-r--r--src/nat/miniupnp/miniupnpc.c901
-rw-r--r--src/nat/miniupnp/miniupnpc.h120
-rw-r--r--src/nat/miniupnp/miniupnpcstrings.h14
-rw-r--r--src/nat/miniupnp/miniwget.c224
-rw-r--r--src/nat/miniupnp/miniwget.h28
-rw-r--r--src/nat/miniupnp/minixml.c200
-rw-r--r--src/nat/miniupnp/minixml.h37
-rw-r--r--src/nat/miniupnp/upnpcommands.c605
-rw-r--r--src/nat/miniupnp/upnpcommands.h189
-rw-r--r--src/nat/miniupnp/upnpreplyparse.c122
-rw-r--r--src/nat/miniupnp/upnpreplyparse.h60
-rw-r--r--src/nat/nat.c293
-rw-r--r--src/nat/natpmp.h17
-rw-r--r--src/nat/upnp.c27
-rw-r--r--src/nat/upnp.h21
36 files changed, 217 insertions, 4935 deletions
diff --git a/configure.ac b/configure.ac
index 8742605d2..22133e07d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -753,8 +753,6 @@ src/include/gnunet_directories.h
753src/hostlist/Makefile 753src/hostlist/Makefile
754src/monkey/Makefile 754src/monkey/Makefile
755src/nat/Makefile 755src/nat/Makefile
756src/nat/libnatpmp/Makefile
757src/nat/miniupnp/Makefile
758src/peerinfo/Makefile 756src/peerinfo/Makefile
759src/peerinfo-tool/Makefile 757src/peerinfo-tool/Makefile
760src/statistics/Makefile 758src/statistics/Makefile
diff --git a/src/include/gnunet_nat_lib.h b/src/include/gnunet_nat_lib.h
index 868edbee1..9c6e171b6 100644
--- a/src/include/gnunet_nat_lib.h
+++ b/src/include/gnunet_nat_lib.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2007, 2008, 2009 Christian Grothoff (and other contributing authors) 3 (C) 2007, 2008, 2009, 2010 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -27,28 +27,9 @@
27 */ 27 */
28 28
29#ifndef GNUNET_NAT_LIB_H 29#ifndef GNUNET_NAT_LIB_H
30#define GNUNET_NAT_LIB_H 1 30#define GNUNET_NAT_LIB_H
31 31
32#include "platform.h"
33#include "gnunet_util_lib.h" 32#include "gnunet_util_lib.h"
34#include "upnp.h"
35#include "natpmp.h"
36
37#include <inttypes.h>
38
39/**
40 * Used to communicate with the UPnP and NAT-PMP plugins
41 * FIXME: move to src/nat/common.h
42 */
43enum GNUNET_NAT_port_forwarding
44 {
45 GNUNET_NAT_PORT_ERROR,
46 GNUNET_NAT_PORT_UNMAPPED,
47 GNUNET_NAT_PORT_UNMAPPING,
48 GNUNET_NAT_PORT_MAPPING,
49 GNUNET_NAT_PORT_MAPPED
50 };
51
52 33
53/** 34/**
54 * Signature of the callback passed to GNUNET_NAT_register. 35 * Signature of the callback passed to GNUNET_NAT_register.
@@ -59,10 +40,12 @@ enum GNUNET_NAT_port_forwarding
59 * @param addr either the previous or the new public IP address 40 * @param addr either the previous or the new public IP address
60 * @param addrlen actual lenght of the address 41 * @param addrlen actual lenght of the address
61 */ 42 */
62typedef void (*GNUNET_NAT_AddressCallback) (void *cls, int add_remove, 43typedef void (*GNUNET_NAT_AddressCallback) (void *cls,
44 int add_remove,
63 const struct sockaddr * addr, 45 const struct sockaddr * addr,
64 socklen_t addrlen); 46 socklen_t addrlen);
65 47
48
66/** 49/**
67 * Handle for active NAT registrations. 50 * Handle for active NAT registrations.
68 */ 51 */
@@ -81,12 +64,13 @@ struct GNUNET_NAT_Handle;
81 * @param callback_cls closure for callback 64 * @param callback_cls closure for callback
82 * @return NULL on error, otherwise handle that can be used to unregister 65 * @return NULL on error, otherwise handle that can be used to unregister
83 */ 66 */
84struct GNUNET_NAT_Handle *GNUNET_NAT_register (struct GNUNET_SCHEDULER_Handle 67struct GNUNET_NAT_Handle *
85 *sched, 68GNUNET_NAT_register (struct GNUNET_SCHEDULER_Handle *sched,
86 const struct sockaddr *addr, 69 const struct sockaddr *addr,
87 socklen_t addrlen, 70 socklen_t addrlen,
88 GNUNET_NAT_AddressCallback 71 GNUNET_NAT_AddressCallback callback,
89 callback, void *callback_cls); 72 void *callback_cls);
73
90 74
91/** 75/**
92 * Stop port redirection and public IP address detection for the given handle. 76 * Stop port redirection and public IP address detection for the given handle.
@@ -96,18 +80,6 @@ struct GNUNET_NAT_Handle *GNUNET_NAT_register (struct GNUNET_SCHEDULER_Handle
96 */ 80 */
97void GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h); 81void GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h);
98 82
99/**
100 * Compare the sin(6)_addr fields of AF_INET or AF_INET(6) sockaddr.
101 * FIXME: move to src/nat/common.h or so.
102 *
103 * @param a first sockaddr
104 * @param b second sockaddr
105 * @return 0 if addresses are equal, non-null value otherwise
106 */
107int GNUNET_NAT_cmp_addr (const struct sockaddr *a,
108 const struct sockaddr *b);
109
110
111#endif 83#endif
112 84
113/* end of gnunet_nat_lib.h */ 85/* end of gnunet_nat_lib.h */
diff --git a/src/nat/Makefile.am b/src/nat/Makefile.am
index 14a4d4e92..c47348b7c 100644
--- a/src/nat/Makefile.am
+++ b/src/nat/Makefile.am
@@ -1,4 +1,4 @@
1SUBDIRS = miniupnp libnatpmp 1SUBDIRS = .
2 2
3INCLUDES = -I$(top_srcdir)/src/include 3INCLUDES = -I$(top_srcdir)/src/include
4 4
@@ -12,7 +12,9 @@ endif
12 12
13if !MINGW 13if !MINGW
14 14
15if HAVE_EXPERIMENTAL
15lib_LTLIBRARIES = libgnunetnat.la 16lib_LTLIBRARIES = libgnunetnat.la
17endif
16 18
17libgnunetnat_la_SOURCES = \ 19libgnunetnat_la_SOURCES = \
18 upnp.c upnp.h \ 20 upnp.c upnp.h \
@@ -24,16 +26,16 @@ libgnunetnat_la_CFLAGS = \
24 26
25libgnunetnat_la_LIBADD = \ 27libgnunetnat_la_LIBADD = \
26 $(top_builddir)/src/util/libgnunetutil.la \ 28 $(top_builddir)/src/util/libgnunetutil.la \
27 $(top_builddir)/src/nat/miniupnp/libminiupnp.la \ 29 $(GN_LIBINTL) @EXT_LIBS@
28 $(top_builddir)/src/nat/libnatpmp/libnatpmp.la \
29 $(GN_LIBINTL) @EXT_LIBS@
30 30
31libgnunetnat_la_LDFLAGS = \ 31libgnunetnat_la_LDFLAGS = \
32 $(GN_LIB_LDFLAGS) $(WINFLAGS) \ 32 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
33 -version-info 0:0:0 33 -version-info 0:0:0
34 34
35if HAVE_EXPERIMENTAL
35check_PROGRAMS = \ 36check_PROGRAMS = \
36 test-nat 37 test-nat
38endif
37 39
38if !DISABLE_TEST_RUN 40if !DISABLE_TEST_RUN
39TESTS = $(check_PROGRAMS) 41TESTS = $(check_PROGRAMS)
@@ -46,4 +48,4 @@ test_nat_LDADD = \
46 $(top_builddir)/src/nat/libgnunetnat.la \ 48 $(top_builddir)/src/nat/libgnunetnat.la \
47 $(top_builddir)/src/util/libgnunetutil.la 49 $(top_builddir)/src/util/libgnunetutil.la
48 50
49endif \ No newline at end of file 51endif
diff --git a/src/nat/libnatpmp/Makefile.am b/src/nat/libnatpmp/Makefile.am
deleted file mode 100644
index 472bcabae..000000000
--- a/src/nat/libnatpmp/Makefile.am
+++ /dev/null
@@ -1,16 +0,0 @@
1noinst_LTLIBRARIES = libnatpmp.la
2
3AM_CPPFLAGS = -DENABLE_STRNATPMPERR
4
5libnatpmp_la_SOURCES = \
6 getgateway.c \
7 natpmp.c
8
9noinst_HEADERS = \
10 declspec.h \
11 getgateway.h \
12 natpmp.h
13
14extra_DIST = \
15 README \
16 LICENSE
diff --git a/src/nat/libnatpmp/README b/src/nat/libnatpmp/README
deleted file mode 100644
index 50fdd1093..000000000
--- a/src/nat/libnatpmp/README
+++ /dev/null
@@ -1,4 +0,0 @@
1libnatpmp is written by Thomas Bernard.
2Its homepage is http://miniupnp.tuxfamily.org/libnatpmp.html
3This code is from the libnatpmp-20090310 snapshot
4
diff --git a/src/nat/libnatpmp/declspec.h b/src/nat/libnatpmp/declspec.h
deleted file mode 100644
index 6c817977a..000000000
--- a/src/nat/libnatpmp/declspec.h
+++ /dev/null
@@ -1,14 +0,0 @@
1#ifndef __DECLSPEC_H__
2#define __DECLSPEC_H__
3
4#if defined(WIN32) && !defined(STATICLIB)
5#ifdef NATPMP_EXPORTS
6#define LIBSPEC __declspec(dllexport)
7#else
8#define LIBSPEC __declspec(dllimport)
9#endif
10#else
11#define LIBSPEC
12#endif
13
14#endif
diff --git a/src/nat/libnatpmp/getgateway.c b/src/nat/libnatpmp/getgateway.c
deleted file mode 100644
index d948669ec..000000000
--- a/src/nat/libnatpmp/getgateway.c
+++ /dev/null
@@ -1,531 +0,0 @@
1/* $Id: getgateway.c,v 1.13 2009/03/10 10:15:31 nanard Exp $ */
2/* libnatpmp
3 * Copyright (c) 2007-2008, Thomas BERNARD <miniupnp@free.fr>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
16#include <stdio.h>
17#include <ctype.h>
18#include <string.h>
19#ifndef WIN32
20#include <netinet/in.h>
21#endif
22#include <sys/param.h>
23/* There is no portable method to get the default route gateway.
24 * So below are three differents functions implementing this.
25 * Parsing /proc/net/route is for linux.
26 * sysctl is the way to access such informations on BSD systems.
27 * Many systems should provide route information through raw PF_ROUTE
28 * sockets. */
29#ifdef __linux__
30#define USE_PROC_NET_ROUTE
31#undef USE_SOCKET_ROUTE
32#undef USE_SYSCTL_NET_ROUTE
33#endif
34
35#ifdef BSD
36#undef USE_PROC_NET_ROUTE
37#define USE_SOCKET_ROUTE
38#undef USE_SYSCTL_NET_ROUTE
39#endif
40
41#ifdef __APPLE__
42#undef USE_PROC_NET_ROUTE
43#undef USE_SOCKET_ROUTE
44#define USE_SYSCTL_NET_ROUTE
45#endif
46
47#if (defined(sun) && defined(__SVR4))
48#undef USE_PROC_NET_ROUTE
49#define USE_SOCKET_ROUTE
50#undef USE_SYSCTL_NET_ROUTE
51#endif
52
53#ifdef WIN32
54#undef USE_PROC_NET_ROUTE
55#undef USE_SOCKET_ROUTE
56#undef USE_SYSCTL_NET_ROUTE
57#define USE_WIN32_CODE
58#endif
59
60#ifdef USE_PROC_NET_ROUTE
61#include <arpa/inet.h>
62#endif
63#ifdef USE_SYSCTL_NET_ROUTE
64#include <stdlib.h>
65#include <sys/sysctl.h>
66#include <sys/socket.h>
67#include <net/route.h>
68#endif
69#ifdef USE_SOCKET_ROUTE
70#include <unistd.h>
71#include <string.h>
72#include <sys/socket.h>
73#include <net/if.h>
74#include <net/route.h>
75#endif
76#ifdef WIN32
77#include <unknwn.h>
78#include <winreg.h>
79#define MAX_KEY_LENGTH 255
80#define MAX_VALUE_LENGTH 16383
81#endif
82#include "getgateway.h"
83
84#ifndef WIN32
85#define SUCCESS (0)
86#define FAILED (-1)
87#endif
88
89#ifdef USE_PROC_NET_ROUTE
90int
91getdefaultgateway (int *af, uint8_t addr[16])
92{
93 unsigned int tmp;
94 uint8_t d[16];
95 char buf[256];
96 int line = 0;
97 FILE *f;
98 char *p;
99 int i;
100 f = fopen ("/proc/net/route", "r");
101 if (!f)
102 return FAILED;
103 while (fgets (buf, sizeof (buf), f))
104 {
105 if (line > 0)
106 {
107 p = buf;
108 while (*p && !isspace ( (unsigned char) *p))
109 p++;
110 while (*p && isspace ( (unsigned char) *p))
111 p++;
112 for (i = 0; i < 16; i++)
113 {
114 if (sscanf (p, "%2X", &tmp) < 1)
115 d[i] = tmp;
116 else
117 break;
118 }
119
120 if (i == 8) /* IPv4 address on 8 hex chars */
121 {
122 /* Move the 32 bits address to the end of the array */
123 for (i = 4; i < 16; i++)
124 d[i] = 0;
125
126 for (i = 0; i < 4; i++)
127 {
128 d[i+12] = d[i];
129 d[i] = 0;
130 }
131 memcpy (addr, d, 16 * sizeof (uint8_t));
132 *af = AF_INET;
133 fclose (f);
134 return SUCCESS;
135 }
136 else if (i == 16) /* IPv6 address on 16 hex chars,
137 * or IPv4 address padded with 0 */
138 {
139 memcpy (addr, d, 16 * sizeof (uint8_t));
140 /* Check at what byte the actual address starts */
141 for (i = 0; i <= 12; i++)
142 if (addr[i]) break;
143
144 if (i == 12)
145 {
146 *af = AF_INET;
147 fclose (f);
148 return SUCCESS;
149 }
150 else if (i == 0)
151 {
152 *af = AF_INET6;
153 fclose (f);
154 return SUCCESS;
155 }
156 }
157 }
158 line++;
159 }
160 /* default route not found ! */
161 if (f)
162 fclose (f);
163 return FAILED;
164}
165#endif /* #ifdef USE_PROC_NET_ROUTE */
166
167
168#ifdef USE_SYSCTL_NET_ROUTE
169
170#define ROUNDUP(a) \
171 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
172
173int
174getdefaultgateway (int *af, uint8_t addr[16])
175{
176#if 0
177 /* net.route.0.inet.dump.0.0 ? */
178 int mib[] = { CTL_NET, PF_ROUTE, 0, AF_INET,
179 NET_RT_DUMP, 0, 0 /*tableid */
180 };
181#endif
182 /* net.route.0.inet.flags.gateway */
183 int mib[] = { CTL_NET, PF_ROUTE, 0, AF_INET,
184 NET_RT_FLAGS, RTF_GATEWAY
185 };
186 size_t l;
187 char *buf, *p;
188 struct rt_msghdr *rt;
189 struct sockaddr *sa;
190 struct sockaddr *sa_tab[RTAX_MAX];
191 int i;
192 int r = FAILED;
193 if (sysctl (mib, sizeof (mib) / sizeof (int), 0, &l, 0, 0) < 0)
194 {
195 return FAILED;
196 }
197 if (l > 0)
198 {
199 buf = malloc (l);
200 if (sysctl (mib, sizeof (mib) / sizeof (int), buf, &l, 0, 0) < 0)
201 {
202 free (buf);
203 return FAILED;
204 }
205 for (p = buf; p < buf + l; p += rt->rtm_msglen)
206 {
207 rt = (struct rt_msghdr *) p;
208 sa = (struct sockaddr *) (rt + 1);
209 for (i = 0; i < RTAX_MAX; i++)
210 {
211 if (rt->rtm_addrs & (1 << i))
212 {
213 sa_tab[i] = sa;
214 sa =
215 (struct sockaddr *) ((char *) sa + ROUNDUP (sa->sa_len));
216 }
217 else
218 {
219 sa_tab[i] = NULL;
220 }
221 }
222 if (((rt->rtm_addrs & (RTA_DST | RTA_GATEWAY)) ==
223 (RTA_DST | RTA_GATEWAY))
224 && sa_tab[RTAX_DST]->sa_family == AF_INET
225 && sa_tab[RTAX_GATEWAY]->sa_family == AF_INET)
226 {
227 if (((struct sockaddr_in *) sa_tab[RTAX_DST])->sin_addr.
228 s_addr == 0)
229 {
230 *addr =
231 ((struct sockaddr_in *) (sa_tab[RTAX_GATEWAY]))->sin_addr.
232 s_addr;
233 *af = AF_INET;
234 r = SUCCESS;
235 }
236 }
237 else if (((rt->rtm_addrs & (RTA_DST | RTA_GATEWAY)) ==
238 (RTA_DST | RTA_GATEWAY))
239 && sa_tab[RTAX_DST]->sa_family == AF_INET6
240 && sa_tab[RTAX_GATEWAY]->sa_family == AF_INET6)
241 {
242 if (IN6_IS_ADDR_UNSPECIFIED (&(((struct sockaddr_in6 *)
243 sa_tab[RTAX_DST])->sin6_addr)))
244 {
245 *(struct in6_addr *)addr =
246 ((struct sockaddr_in6 *) (sa_tab[RTAX_GATEWAY]))->sin6_addr;
247 *af = AF_INET6;
248 r = SUCCESS;
249 }
250 }
251 }
252 free (buf);
253 }
254 return r;
255}
256#endif /* #ifdef USE_SYSCTL_NET_ROUTE */
257
258
259#ifdef USE_SOCKET_ROUTE
260/* Thanks to Darren Kenny for this code */
261#define NEXTADDR(w, u) \
262 if (rtm_addrs & (w)) {\
263 l = sizeof(struct sockaddr); memmove(cp, &(u), l); cp += l;\
264 }
265
266#define rtm m_rtmsg.m_rtm
267
268struct
269{
270 struct rt_msghdr m_rtm;
271 char m_space[512];
272} m_rtmsg;
273
274int
275getdefaultgateway (int *af, uint8_t addr[16])
276{
277 int s, seq, l, rtm_addrs, i;
278 pid_t pid;
279 struct sockaddr so_dst, so_mask;
280 char *cp = m_rtmsg.m_space;
281 struct sockaddr *gate = NULL, *sa;
282 struct rt_msghdr *msg_hdr;
283
284 pid = getpid ();
285 seq = 0;
286 rtm_addrs = RTA_DST | RTA_NETMASK;
287
288 memset (&so_dst, 0, sizeof (so_dst));
289 memset (&so_mask, 0, sizeof (so_mask));
290 memset (&rtm, 0, sizeof (struct rt_msghdr));
291
292 rtm.rtm_type = RTM_GET;
293 rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
294 rtm.rtm_version = RTM_VERSION;
295 rtm.rtm_seq = ++seq;
296 rtm.rtm_addrs = rtm_addrs;
297
298 so_dst.sa_family = AF_INET;
299 so_mask.sa_family = AF_INET;
300
301 NEXTADDR (RTA_DST, so_dst);
302 NEXTADDR (RTA_NETMASK, so_mask);
303
304 rtm.rtm_msglen = l = cp - (char *) &m_rtmsg;
305
306 s = socket (PF_ROUTE, SOCK_RAW, 0);
307
308 if (write (s, (char *) &m_rtmsg, l) < 0)
309 {
310 close (s);
311 return FAILED;
312 }
313
314 do
315 {
316 l = read (s, (char *) &m_rtmsg, sizeof (m_rtmsg));
317 }
318 while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
319
320 close (s);
321
322 msg_hdr = &rtm;
323
324 cp = ((char *) (msg_hdr + 1));
325 if (msg_hdr->rtm_addrs)
326 {
327 for (i = 1; i; i <<= 1)
328 if (i & msg_hdr->rtm_addrs)
329 {
330 sa = (struct sockaddr *) cp;
331 if (i == RTA_GATEWAY)
332 gate = sa;
333
334 cp += sizeof (struct sockaddr);
335 }
336 }
337 else
338 {
339 return FAILED;
340 }
341
342
343 if (gate != NULL && gate->sa_family == AF_INET)
344 {
345 *addr = ((struct sockaddr_in *) gate)->sin_addr.s_addr;
346 *af = AF_INET;
347 return SUCCESS;
348 }
349 else if (gate != NULL && gate->sa_family == AF_INET6)
350 {
351 memcpy (addr, ((struct sockaddr_in6 *) gate)->sin6_addr.s6_addr, 16 * sizeof (uint8_t));
352 *af = AF_INET6;
353 return SUCCESS;
354 }
355 else
356 {
357 return FAILED;
358 }
359}
360#endif /* #ifdef USE_SOCKET_ROUTE */
361
362#ifdef USE_WIN32_CODE
363int
364getdefaultgateway (int *af, uint8_t addr[16])
365{
366 HKEY networkCardsKey;
367 HKEY networkCardKey;
368 HKEY interfacesKey;
369 HKEY interfaceKey;
370 DWORD i = 0;
371 DWORD numSubKeys = 0;
372 TCHAR keyName[MAX_KEY_LENGTH];
373 DWORD keyNameLength = MAX_KEY_LENGTH;
374 TCHAR keyValue[MAX_VALUE_LENGTH];
375 DWORD keyValueLength = MAX_VALUE_LENGTH;
376 DWORD keyValueType = REG_SZ;
377 TCHAR gatewayValue[MAX_VALUE_LENGTH];
378 DWORD gatewayValueLength = MAX_VALUE_LENGTH;
379 DWORD gatewayValueType = REG_MULTI_SZ;
380 int done = 0;
381
382 char networkCardsPath[] =
383 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards";
384 char interfacesPath[] =
385 "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces";
386
387 // The windows registry lists its primary network devices in the following location:
388 // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards
389 //
390 // Each network device has its own subfolder, named with an index, with various properties:
391 // -NetworkCards
392 // -5
393 // -Description = Broadcom 802.11n Network Adapter
394 // -ServiceName = {E35A72F8-5065-4097-8DFE-C7790774EE4D}
395 // -8
396 // -Description = Marvell Yukon 88E8058 PCI-E Gigabit Ethernet Controller
397 // -ServiceName = {86226414-5545-4335-A9D1-5BD7120119AD}
398 //
399 // The above service name is the name of a subfolder within:
400 // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces
401 //
402 // There may be more subfolders in this interfaces path than listed in the network cards path above:
403 // -Interfaces
404 // -{3a539854-6a70-11db-887c-806e6f6e6963}
405 // -DhcpIPAddress = 0.0.0.0
406 // -[more]
407 // -{E35A72F8-5065-4097-8DFE-C7790774EE4D}
408 // -DhcpIPAddress = 10.0.1.4
409 // -DhcpDefaultGateway = 10.0.1.1
410 // -[more]
411 // -{86226414-5545-4335-A9D1-5BD7120119AD}
412 // -DhcpIpAddress = 10.0.1.5
413 // -DhcpDefaultGateay = 10.0.1.1
414 // -[more]
415 //
416 // In order to extract this information, we enumerate each network card, and extract the ServiceName value.
417 // This is then used to open the interface subfolder, and attempt to extract a DhcpDefaultGateway value.
418 // Once one is found, we're done.
419 //
420 // It may be possible to simply enumerate the interface folders until we find one with a DhcpDefaultGateway value.
421 // However, the technique used is the technique most cited on the web, and we assume it to be more correct.
422
423 if (ERROR_SUCCESS != RegOpenKeyEx (HKEY_LOCAL_MACHINE, // Open registry key or predifined key
424 networkCardsPath, // Name of registry subkey to open
425 0, // Reserved - must be zero
426 KEY_READ, // Mask - desired access rights
427 &networkCardsKey)) // Pointer to output key
428 {
429 // Unable to open network cards keys
430 return -1;
431 }
432
433 if (ERROR_SUCCESS != RegOpenKeyEx (HKEY_LOCAL_MACHINE, // Open registry key or predefined key
434 interfacesPath, // Name of registry subkey to open
435 0, // Reserved - must be zero
436 KEY_READ, // Mask - desired access rights
437 &interfacesKey)) // Pointer to output key
438 {
439 // Unable to open interfaces key
440 RegCloseKey (networkCardsKey);
441 return -1;
442 }
443
444 // Figure out how many subfolders are within the NetworkCards folder
445 RegQueryInfoKey (networkCardsKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL,
446 NULL, NULL, NULL, NULL, NULL);
447
448 //printf( "Number of subkeys: %u\n", (unsigned int)numSubKeys);
449
450 // Enumrate through each subfolder within the NetworkCards folder
451 for (i = 0; i < numSubKeys && !done; i++)
452 {
453 keyNameLength = MAX_KEY_LENGTH;
454 if (ERROR_SUCCESS == RegEnumKeyEx (networkCardsKey, // Open registry key
455 i, // Index of subkey to retrieve
456 keyName, // Buffer that receives the name of the subkey
457 &keyNameLength, // Variable that receives the size of the above buffer
458 NULL, // Reserved - must be NULL
459 NULL, // Buffer that receives the class string
460 NULL, // Variable that receives the size of the above buffer
461 NULL)) // Variable that receives the last write time of subkey
462 {
463 if (RegOpenKeyEx
464 (networkCardsKey, keyName, 0, KEY_READ,
465 &networkCardKey) == ERROR_SUCCESS)
466 {
467 keyValueLength = MAX_VALUE_LENGTH;
468 if (ERROR_SUCCESS == RegQueryValueEx (networkCardKey, // Open registry key
469 "ServiceName", // Name of key to query
470 NULL, // Reserved - must be NULL
471 &keyValueType, // Receives value type
472 keyValue, // Receives value
473 &keyValueLength)) // Receives value length in bytes
474 {
475 //printf("keyValue: %s\n", keyValue);
476
477 if (RegOpenKeyEx
478 (interfacesKey, keyValue, 0, KEY_READ,
479 &interfaceKey) == ERROR_SUCCESS)
480 {
481 gatewayValueLength = MAX_VALUE_LENGTH;
482 if (ERROR_SUCCESS == RegQueryValueEx (interfaceKey, // Open registry key
483 "DhcpDefaultGateway", // Name of key to query
484 NULL, // Reserved - must be NULL
485 &gatewayValueType, // Receives value type
486 gatewayValue, // Receives value
487 &gatewayValueLength)) // Receives value length in bytes
488 {
489 // Check to make sure it's a string
490 if (gatewayValueType == REG_MULTI_SZ
491 || gatewayValueType == REG_SZ)
492 {
493 //printf("gatewayValue: %s\n", gatewayValue);
494 done = 1;
495 }
496 }
497 else if (ERROR_SUCCESS == RegQueryValueEx (interfaceKey, // Open registry key
498 "DefaultGateway", // Name of key to query
499 NULL, // Reserved - must be NULL
500 &gatewayValueType, // Receives value type
501 gatewayValue, // Receives value
502 &gatewayValueLength)) // Receives value length in bytes
503 {
504 // Check to make sure it's a string
505 if (gatewayValueType == REG_MULTI_SZ
506 || gatewayValueType == REG_SZ)
507 {
508 //printf("gatewayValue: %s\n", gatewayValue);
509 done = 1;
510 }
511 }
512 RegCloseKey (interfaceKey);
513 }
514 }
515 RegCloseKey (networkCardKey);
516 }
517 }
518 }
519
520 RegCloseKey (interfacesKey);
521 RegCloseKey (networkCardsKey);
522
523 if (done)
524 {
525 *addr = inet_addr (gatewayValue);
526 return 0;
527 }
528
529 return -1;
530}
531#endif /* #ifdef USE_WIN32_CODE */
diff --git a/src/nat/libnatpmp/getgateway.h b/src/nat/libnatpmp/getgateway.h
deleted file mode 100644
index 35dc1e93a..000000000
--- a/src/nat/libnatpmp/getgateway.h
+++ /dev/null
@@ -1,32 +0,0 @@
1/* $Id: getgateway.h,v 1.3 2008/07/02 22:33:06 nanard Exp $ */
2/* libnatpmp
3 * Copyright (c) 2007, Thomas BERNARD <miniupnp@free.fr>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
16#ifndef __GETGATEWAY_H__
17#define __GETGATEWAY_H__
18
19#ifdef WIN32
20#include <stdint.h>
21#define in_addr_t uint32_t
22#endif
23#include "declspec.h"
24
25/* getdefaultgateway() :
26 * addr must point to an array of at least 16 u_int8 elements
27 * return value :
28 * 0 : success
29 * -1 : failure */
30LIBSPEC int getdefaultgateway (int *af, uint8_t addr[16]);
31
32#endif
diff --git a/src/nat/libnatpmp/natpmp.c b/src/nat/libnatpmp/natpmp.c
deleted file mode 100644
index 12526df8e..000000000
--- a/src/nat/libnatpmp/natpmp.c
+++ /dev/null
@@ -1,409 +0,0 @@
1/* $Id: natpmp.c,v 1.8 2008/07/02 22:33:06 nanard Exp $ */
2/* libnatpmp
3 * Copyright (c) 2007-2008, Thomas BERNARD <miniupnp@free.fr>
4 * http://miniupnp.free.fr/libnatpmp.html
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
17#include <string.h>
18#include <time.h>
19#include <sys/time.h>
20#ifdef WIN32
21#include <winsock2.h>
22#include <Ws2tcpip.h>
23#include <io.h>
24#define EWOULDBLOCK WSAEWOULDBLOCK
25#define ECONNREFUSED WSAECONNREFUSED
26#else
27#include <errno.h>
28#include <unistd.h>
29#include <fcntl.h>
30#include <sys/types.h>
31#include <sys/socket.h>
32#define closesocket close
33#endif
34#include "natpmp.h"
35#include "getgateway.h"
36
37int
38initnatpmp (natpmp_t * p)
39{
40#ifdef WIN32
41 u_long ioctlArg = 1;
42#else
43 int flags;
44#endif
45 int domain = AF_INET;
46 int gw_domain;
47 struct sockaddr_in addr;
48 struct sockaddr_in6 addr6;
49
50 if (!p)
51 return NATPMP_ERR_INVALIDARGS;
52
53 if (p->addr)
54 domain = (p->addr->sa_family == AF_INET) ? PF_INET : PF_INET6;
55
56 memset (p, 0, sizeof (natpmp_t));
57 p->s = socket (domain, SOCK_DGRAM, 0);
58 if (p->s < 0)
59 return NATPMP_ERR_SOCKETERROR;
60 /* If addr has been set, use it, else get the default from connect() */
61 if (p->addr && bind (p->s, p->addr, p->addrlen) < 0)
62 return NATPMP_ERR_BINDERROR;
63#ifdef WIN32
64 if (ioctlsocket (p->s, FIONBIO, &ioctlArg) == SOCKET_ERROR)
65 return NATPMP_ERR_FCNTLERROR;
66#else
67 if ((flags = fcntl (p->s, F_GETFL, 0)) < 0)
68 return NATPMP_ERR_FCNTLERROR;
69 if (fcntl (p->s, F_SETFL, flags | O_NONBLOCK) < 0)
70 return NATPMP_ERR_FCNTLERROR;
71#endif
72
73 if (getdefaultgateway (&gw_domain, p->gateway) < 0)
74 return NATPMP_ERR_CANNOTGETGATEWAY;
75
76 if (domain != gw_domain)
77 return NATPMP_ERR_ADDRERROR;
78
79 if (domain == AF_INET)
80 {
81 memset (&addr, 0, sizeof (addr));
82 addr.sin_family = AF_INET;
83 addr.sin_port = htons (NATPMP_PORT);
84 memcpy (&addr.sin_addr.s_addr, p->gateway, 4 * sizeof (uint8_t));
85#ifdef HAVE_SOCKADDR_IN_SIN_LEN
86 addr.sin_len = sizeof (addr);
87#endif
88 if (connect (p->s, (struct sockaddr *) &addr, sizeof (addr)) < 0)
89 return NATPMP_ERR_CONNECTERR;
90 }
91 else
92 {
93 memset (&addr6, 0, sizeof (addr6));
94 addr6.sin6_family = AF_INET6;
95 addr6.sin6_port = htons (NATPMP_PORT);
96 memcpy (addr6.sin6_addr.s6_addr, p->gateway, 16 * sizeof (uint8_t));
97#ifdef HAVE_SOCKADDR_IN_SIN_LEN
98 addr6.sin6_len = sizeof (addr6);
99#endif
100 if (connect (p->s, (struct sockaddr *) &addr6, sizeof (addr6)) < 0)
101 return NATPMP_ERR_CONNECTERR;
102 }
103
104 return 0;
105}
106
107int
108closenatpmp (natpmp_t * p)
109{
110 if (!p)
111 return NATPMP_ERR_INVALIDARGS;
112 if (closesocket (p->s) < 0)
113 return NATPMP_ERR_CLOSEERR;
114 return 0;
115}
116
117static int
118sendpendingrequest (natpmp_t * p)
119{
120 int r;
121/* struct sockaddr_in addr;*/
122 if (!p)
123 return NATPMP_ERR_INVALIDARGS;
124/* memset(&addr, 0, sizeof(addr));
125 addr.sin_family = AF_INET;
126 addr.sin_port = htons(NATPMP_PORT);
127 addr.sin_addr.s_addr = p->gateway;
128 r = (int)sendto(p->s, p->pending_request, p->pending_request_len, 0,
129 (struct sockaddr *)&addr, sizeof(addr));*/
130 r = (int) send (p->s, p->pending_request, p->pending_request_len, 0);
131 return (r < 0) ? NATPMP_ERR_SENDERR : r;
132}
133
134static int
135sendnatpmprequest (natpmp_t * p)
136{
137 int n;
138 if (!p)
139 return NATPMP_ERR_INVALIDARGS;
140 /* TODO : check if no request is allready pending */
141 p->has_pending_request = 1;
142 p->try_number = 1;
143 n = sendpendingrequest (p);
144 gettimeofday (&p->retry_time, NULL); // check errors !
145 p->retry_time.tv_usec += 250000; /* add 250ms */
146 if (p->retry_time.tv_usec >= 1000000)
147 {
148 p->retry_time.tv_usec -= 1000000;
149 p->retry_time.tv_sec++;
150 }
151 return n;
152}
153
154int
155getnatpmprequesttimeout (natpmp_t * p, struct timeval *timeout)
156{
157 struct timeval now;
158 if (!p || !timeout)
159 return NATPMP_ERR_INVALIDARGS;
160 if (!p->has_pending_request)
161 return NATPMP_ERR_NOPENDINGREQ;
162 if (gettimeofday (&now, NULL) < 0)
163 return NATPMP_ERR_GETTIMEOFDAYERR;
164 timeout->tv_sec = p->retry_time.tv_sec - now.tv_sec;
165 timeout->tv_usec = p->retry_time.tv_usec - now.tv_usec;
166 if (timeout->tv_usec < 0)
167 {
168 timeout->tv_usec += 1000000;
169 timeout->tv_sec--;
170 }
171 return 0;
172}
173
174int
175sendpublicaddressrequest (natpmp_t * p)
176{
177 if (!p)
178 return NATPMP_ERR_INVALIDARGS;
179 //static const unsigned char request[] = { 0, 0 };
180 p->pending_request[0] = 0;
181 p->pending_request[1] = 0;
182 p->pending_request_len = 2;
183 // TODO: return 0 instead of sizeof(request) ??
184 return sendnatpmprequest (p);
185}
186
187int
188sendnewportmappingrequest (natpmp_t * p, int protocol,
189 uint16_t privateport, uint16_t publicport,
190 uint32_t lifetime)
191{
192 if (!p
193 || (protocol != NATPMP_PROTOCOL_TCP && protocol != NATPMP_PROTOCOL_UDP))
194 return NATPMP_ERR_INVALIDARGS;
195 p->pending_request[0] = 0;
196 p->pending_request[1] = protocol;
197 p->pending_request[2] = 0;
198 p->pending_request[3] = 0;
199 *((uint16_t *) (p->pending_request + 4)) = htons (privateport);
200 *((uint16_t *) (p->pending_request + 6)) = htons (publicport);
201 *((uint32_t *) (p->pending_request + 8)) = htonl (lifetime);
202 p->pending_request_len = 12;
203 return sendnatpmprequest (p);
204}
205
206static int
207readnatpmpresponse (natpmp_t * p, natpmpresp_t * response)
208{
209 unsigned char buf[16];
210 struct sockaddr_storage addr;
211 socklen_t addrlen = sizeof (addr);
212 int n;
213 if (!p)
214 return NATPMP_ERR_INVALIDARGS;
215 n = recvfrom (p->s, buf, sizeof (buf), 0,
216 (struct sockaddr *) &addr, &addrlen);
217 if (n < 0)
218 switch (errno)
219 {
220 /*case EAGAIN: */
221 case EWOULDBLOCK:
222 n = NATPMP_TRYAGAIN;
223 break;
224 case ECONNREFUSED:
225 n = NATPMP_ERR_NOGATEWAYSUPPORT;
226 break;
227 default:
228 n = NATPMP_ERR_RECVFROM;
229 }
230 /* check that addr is correct (= gateway) */
231 else if (addr.ss_family == AF_INET && memcmp (&((struct sockaddr_in *) &addr)->sin_addr.s_addr, p->gateway, 4 * sizeof (uint8_t)) == 0)
232 n = NATPMP_ERR_WRONGPACKETSOURCE;
233 else if (addr.ss_family == AF_INET6 && memcmp (((struct sockaddr_in6 *) &addr)->sin6_addr.s6_addr, p->gateway, 16 * sizeof (uint8_t)) == 0)
234 n = NATPMP_ERR_WRONGPACKETSOURCE;
235 else
236 {
237 response->resultcode = ntohs (*((uint16_t *) (buf + 2)));
238 response->epoch = ntohl (*((uint32_t *) (buf + 4)));
239 if (buf[0] != 0)
240 n = NATPMP_ERR_UNSUPPORTEDVERSION;
241 else if (buf[1] < 128 || buf[1] > 130)
242 n = NATPMP_ERR_UNSUPPORTEDOPCODE;
243 else if (response->resultcode != 0)
244 {
245 switch (response->resultcode)
246 {
247 case 1:
248 n = NATPMP_ERR_UNSUPPORTEDVERSION;
249 break;
250 case 2:
251 n = NATPMP_ERR_NOTAUTHORIZED;
252 break;
253 case 3:
254 n = NATPMP_ERR_NETWORKFAILURE;
255 break;
256 case 4:
257 n = NATPMP_ERR_OUTOFRESOURCES;
258 break;
259 case 5:
260 n = NATPMP_ERR_UNSUPPORTEDOPCODE;
261 break;
262 default:
263 n = NATPMP_ERR_UNDEFINEDERROR;
264 }
265 }
266 else
267 {
268 response->type = buf[1] & 0x7f;
269 if (buf[1] == 128)
270 {
271 response->pnu.publicaddress.family = AF_INET;
272 memset (&response->pnu.publicaddress.addr6.s6_addr, 0, sizeof (struct in6_addr));
273 response->pnu.publicaddress.addr.s_addr =
274 *((uint32_t *) (buf + 8));
275 /* FIXME: support IPv6 address */
276 }
277 else
278 {
279 response->pnu.newportmapping.privateport =
280 ntohs (*((uint16_t *) (buf + 8)));
281 response->pnu.newportmapping.mappedpublicport =
282 ntohs (*((uint16_t *) (buf + 10)));
283 response->pnu.newportmapping.lifetime =
284 ntohl (*((uint32_t *) (buf + 12)));
285 }
286 n = 0;
287 }
288 }
289 return n;
290}
291
292int
293readnatpmpresponseorretry (natpmp_t * p, natpmpresp_t * response)
294{
295 int n;
296 if (!p || !response)
297 return NATPMP_ERR_INVALIDARGS;
298 if (!p->has_pending_request)
299 return NATPMP_ERR_NOPENDINGREQ;
300 n = readnatpmpresponse (p, response);
301 if (n < 0)
302 {
303 if (n == NATPMP_TRYAGAIN)
304 {
305 struct timeval now;
306 gettimeofday (&now, NULL); // check errors !
307 if (timercmp (&now, &p->retry_time, >=))
308 {
309 int delay, r;
310 if (p->try_number >= 9)
311 {
312 return NATPMP_ERR_NOGATEWAYSUPPORT;
313 }
314 /*printf("retry! %d\n", p->try_number); */
315 delay = 250 * (1 << p->try_number); // ms
316 /*for(i=0; i<p->try_number; i++)
317 delay += delay; */
318 p->retry_time.tv_sec += (delay / 1000);
319 p->retry_time.tv_usec += (delay % 1000) * 1000;
320 if (p->retry_time.tv_usec >= 1000000)
321 {
322 p->retry_time.tv_usec -= 1000000;
323 p->retry_time.tv_sec++;
324 }
325 p->try_number++;
326 r = sendpendingrequest (p);
327 if (r < 0)
328 return r;
329 }
330 }
331 }
332 else
333 {
334 p->has_pending_request = 0;
335 }
336 return n;
337}
338
339#ifdef ENABLE_STRNATPMPERR
340const char *
341strnatpmperr (int r)
342{
343 const char *s;
344 switch (r)
345 {
346 case NATPMP_ERR_INVALIDARGS:
347 s = "invalid arguments";
348 break;
349 case NATPMP_ERR_SOCKETERROR:
350 s = "socket() failed";
351 break;
352 case NATPMP_ERR_CANNOTGETGATEWAY:
353 s = "cannot get default gateway ip address";
354 break;
355 case NATPMP_ERR_CLOSEERR:
356#ifdef WIN32
357 s = "closesocket() failed";
358#else
359 s = "close() failed";
360#endif
361 break;
362 case NATPMP_ERR_RECVFROM:
363 s = "recvfrom() failed";
364 break;
365 case NATPMP_ERR_NOPENDINGREQ:
366 s = "no pending request";
367 break;
368 case NATPMP_ERR_NOGATEWAYSUPPORT:
369 s = "the gateway does not support nat-pmp";
370 break;
371 case NATPMP_ERR_CONNECTERR:
372 s = "connect() failed";
373 break;
374 case NATPMP_ERR_WRONGPACKETSOURCE:
375 s = "packet not received from the default gateway";
376 break;
377 case NATPMP_ERR_SENDERR:
378 s = "send() failed";
379 break;
380 case NATPMP_ERR_FCNTLERROR:
381 s = "fcntl() failed";
382 break;
383 case NATPMP_ERR_GETTIMEOFDAYERR:
384 s = "gettimeofday() failed";
385 break;
386 case NATPMP_ERR_UNSUPPORTEDVERSION:
387 s = "unsupported nat-pmp version error from server";
388 break;
389 case NATPMP_ERR_UNSUPPORTEDOPCODE:
390 s = "unsupported nat-pmp opcode error from server";
391 break;
392 case NATPMP_ERR_UNDEFINEDERROR:
393 s = "undefined nat-pmp server error";
394 break;
395 case NATPMP_ERR_NOTAUTHORIZED:
396 s = "not authorized";
397 break;
398 case NATPMP_ERR_NETWORKFAILURE:
399 s = "network failure";
400 break;
401 case NATPMP_ERR_OUTOFRESOURCES:
402 s = "nat-pmp server out of resources";
403 break;
404 default:
405 s = "Unknown libnatpmp error";
406 }
407 return s;
408}
409#endif
diff --git a/src/nat/libnatpmp/natpmp.h b/src/nat/libnatpmp/natpmp.h
deleted file mode 100644
index 976bad06f..000000000
--- a/src/nat/libnatpmp/natpmp.h
+++ /dev/null
@@ -1,202 +0,0 @@
1/* $Id: natpmp.h,v 1.11 2009/02/27 22:38:05 nanard Exp $ */
2/* libnatpmp
3 * Copyright (c) 2007-2008, Thomas BERNARD <miniupnp@free.fr>
4 * http://miniupnp.free.fr/libnatpmp.html
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
17#ifndef __NATPMP_H__
18#define __NATPMP_H__
19
20/* NAT-PMP Port as defined by the NAT-PMP draft */
21#define NATPMP_PORT (5351)
22
23#include <stdint.h>
24#include <time.h>
25#include <sys/time.h>
26#ifdef WIN32
27#include <winsock2.h>
28#include <stdint.h>
29#define in_addr_t uint32_t
30#include "declspec.h"
31#else
32#define LIBSPEC
33#include <netinet/in.h>
34#include <sys/socket.h>
35#endif
36
37typedef struct
38{
39 int s; /* socket */
40 struct sockaddr *addr;
41 socklen_t addrlen;
42 uint8_t gateway[16]; /* default gateway (IPv4 or IPv6) */
43 int has_pending_request;
44 unsigned char pending_request[12];
45 int pending_request_len;
46 int try_number;
47 struct timeval retry_time;
48} natpmp_t;
49
50typedef struct
51{
52 uint16_t type; /* NATPMP_RESPTYPE_* */
53 uint16_t resultcode; /* NAT-PMP response code */
54 uint32_t epoch; /* Seconds since start of epoch */
55 union
56 {
57 struct
58 {
59 int family;
60 struct in_addr addr;
61 struct in6_addr addr6;
62 } publicaddress;
63 struct
64 {
65 uint16_t privateport;
66 uint16_t mappedpublicport;
67 uint32_t lifetime;
68 } newportmapping;
69 } pnu;
70} natpmpresp_t;
71
72/* possible values for type field of natpmpresp_t */
73#define NATPMP_RESPTYPE_PUBLICADDRESS (0)
74#define NATPMP_RESPTYPE_UDPPORTMAPPING (1)
75#define NATPMP_RESPTYPE_TCPPORTMAPPING (2)
76
77/* Values to pass to sendnewportmappingrequest() */
78#define NATPMP_PROTOCOL_UDP (1)
79#define NATPMP_PROTOCOL_TCP (2)
80
81/* return values */
82/* NATPMP_ERR_INVALIDARGS : invalid arguments passed to the function */
83#define NATPMP_ERR_INVALIDARGS (-1)
84/* NATPMP_ERR_SOCKETERROR : socket() failed. check errno for details */
85#define NATPMP_ERR_SOCKETERROR (-2)
86/* NATPMP_ERR_CANNOTGETGATEWAY : can't get default gateway IP */
87#define NATPMP_ERR_CANNOTGETGATEWAY (-3)
88/* NATPMP_ERR_CLOSEERR : close() failed. check errno for details */
89#define NATPMP_ERR_CLOSEERR (-4)
90/* NATPMP_ERR_RECVFROM : recvfrom() failed. check errno for details */
91#define NATPMP_ERR_RECVFROM (-5)
92/* NATPMP_ERR_NOPENDINGREQ : readnatpmpresponseorretry() called while
93 * no NAT-PMP request was pending */
94#define NATPMP_ERR_NOPENDINGREQ (-6)
95/* NATPMP_ERR_NOGATEWAYSUPPORT : the gateway does not support NAT-PMP */
96#define NATPMP_ERR_NOGATEWAYSUPPORT (-7)
97/* NATPMP_ERR_CONNECTERR : connect() failed. check errno for details */
98#define NATPMP_ERR_CONNECTERR (-8)
99/* NATPMP_ERR_WRONGPACKETSOURCE : packet not received from the network gateway */
100#define NATPMP_ERR_WRONGPACKETSOURCE (-9)
101/* NATPMP_ERR_SENDERR : send() failed. check errno for details */
102#define NATPMP_ERR_SENDERR (-10)
103/* NATPMP_ERR_FCNTLERROR : fcntl() failed. check errno for details */
104#define NATPMP_ERR_FCNTLERROR (-11)
105/* NATPMP_ERR_GETTIMEOFDAYERR : gettimeofday() failed. check errno for details */
106#define NATPMP_ERR_GETTIMEOFDAYERR (-12)
107/* NATPMP_ERR_BINDERROR : bind() failed. check errno for details */
108#define NATPMP_ERR_BINDERROR (-13)
109/* NATPMP_ERR_ADDRERROR : gateway does not use the same inet protocol as the passed address */
110#define NATPMP_ERR_ADDRERROR (-14)
111
112/* */
113#define NATPMP_ERR_UNSUPPORTEDVERSION (-15)
114#define NATPMP_ERR_UNSUPPORTEDOPCODE (-16)
115
116/* Errors from the server : */
117#define NATPMP_ERR_UNDEFINEDERROR (-49)
118#define NATPMP_ERR_NOTAUTHORIZED (-51)
119#define NATPMP_ERR_NETWORKFAILURE (-52)
120#define NATPMP_ERR_OUTOFRESOURCES (-53)
121
122/* NATPMP_TRYAGAIN : no data available for the moment. try again later */
123#define NATPMP_TRYAGAIN (-100)
124
125/* initnatpmp()
126 * initialize a natpmp_t object
127 * Return values :
128 * 0 = OK
129 * NATPMP_ERR_INVALIDARGS
130 * NATPMP_ERR_SOCKETERROR
131 * NATPMP_ERR_FCNTLERROR
132 * NATPMP_ERR_CANNOTGETGATEWAY
133 * NATPMP_ERR_CONNECTERR */
134LIBSPEC int initnatpmp (natpmp_t * p);
135
136/* closenatpmp()
137 * close resources associated with a natpmp_t object
138 * Return values :
139 * 0 = OK
140 * NATPMP_ERR_INVALIDARGS
141 * NATPMP_ERR_CLOSEERR */
142LIBSPEC int closenatpmp (natpmp_t * p);
143
144/* sendpublicaddressrequest()
145 * send a public address NAT-PMP request to the network gateway
146 * Return values :
147 * 2 = OK (size of the request)
148 * NATPMP_ERR_INVALIDARGS
149 * NATPMP_ERR_SENDERR */
150LIBSPEC int sendpublicaddressrequest (natpmp_t * p);
151
152/* sendnewportmappingrequest()
153 * send a new port mapping NAT-PMP request to the network gateway
154 * Arguments :
155 * protocol is either NATPMP_PROTOCOL_TCP or NATPMP_PROTOCOL_UDP,
156 * lifetime is in seconds.
157 * To remove a port mapping, set lifetime to zero.
158 * To remove all port mappings to the host, set lifetime and both ports
159 * to zero.
160 * Return values :
161 * 12 = OK (size of the request)
162 * NATPMP_ERR_INVALIDARGS
163 * NATPMP_ERR_SENDERR */
164LIBSPEC int sendnewportmappingrequest (natpmp_t * p, int protocol,
165 uint16_t privateport,
166 uint16_t publicport,
167 uint32_t lifetime);
168
169/* getnatpmprequesttimeout()
170 * fills the timeval structure with the timeout duration of the
171 * currently pending NAT-PMP request.
172 * Return values :
173 * 0 = OK
174 * NATPMP_ERR_INVALIDARGS
175 * NATPMP_ERR_GETTIMEOFDAYERR
176 * NATPMP_ERR_NOPENDINGREQ */
177LIBSPEC int getnatpmprequesttimeout (natpmp_t * p, struct timeval *timeout);
178
179/* readnatpmpresponseorretry()
180 * fills the natpmpresp_t structure if possible
181 * Return values :
182 * 0 = OK
183 * NATPMP_TRYAGAIN
184 * NATPMP_ERR_INVALIDARGS
185 * NATPMP_ERR_NOPENDINGREQ
186 * NATPMP_ERR_NOGATEWAYSUPPORT
187 * NATPMP_ERR_RECVFROM
188 * NATPMP_ERR_WRONGPACKETSOURCE
189 * NATPMP_ERR_UNSUPPORTEDVERSION
190 * NATPMP_ERR_UNSUPPORTEDOPCODE
191 * NATPMP_ERR_NOTAUTHORIZED
192 * NATPMP_ERR_NETWORKFAILURE
193 * NATPMP_ERR_OUTOFRESOURCES
194 * NATPMP_ERR_UNSUPPORTEDOPCODE
195 * NATPMP_ERR_UNDEFINEDERROR */
196LIBSPEC int readnatpmpresponseorretry (natpmp_t * p, natpmpresp_t * response);
197
198#ifdef ENABLE_STRNATPMPERR
199LIBSPEC const char *strnatpmperr (int t);
200#endif
201
202#endif
diff --git a/src/nat/miniupnp/Makefile.am b/src/nat/miniupnp/Makefile.am
deleted file mode 100644
index 731c41a84..000000000
--- a/src/nat/miniupnp/Makefile.am
+++ /dev/null
@@ -1,31 +0,0 @@
1noinst_LTLIBRARIES = libminiupnp.la
2
3AM_CPPFLAGS = -DNDEBUG
4
5libminiupnp_la_SOURCES = \
6 igd_desc_parse.c \
7 minisoap.c \
8 minissdpc.c \
9 miniupnpc.c \
10 miniwget.c \
11 minixml.c \
12 upnpcommands.c \
13 upnpreplyparse.c
14
15noinst_HEADERS = \
16 bsdqueue.h \
17 codelength.h \
18 declspec.h \
19 igd_desc_parse.h \
20 minisoap.h \
21 minissdpc.h \
22 miniupnpc.h \
23 miniupnpcstrings.h \
24 miniwget.h \
25 minixml.h \
26 upnpcommands.h \
27 upnpreplyparse.h
28
29extra_DIST = \
30 README \
31 LICENSE
diff --git a/src/nat/miniupnp/README b/src/nat/miniupnp/README
deleted file mode 100644
index 45aec9084..000000000
--- a/src/nat/miniupnp/README
+++ /dev/null
@@ -1,3 +0,0 @@
1MiniUPnP is written by Thomas Bernard.
2Its homepage is http://miniupnp.free.fr/
3This is from miniupnpc-1.3.tar.gz
diff --git a/src/nat/miniupnp/bsdqueue.h b/src/nat/miniupnp/bsdqueue.h
deleted file mode 100644
index f763172c4..000000000
--- a/src/nat/miniupnp/bsdqueue.h
+++ /dev/null
@@ -1,531 +0,0 @@
1/* $OpenBSD: queue.h,v 1.31 2005/11/25 08:06:25 otto Exp $ */
2/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
3
4/*
5 * Copyright (c) 1991, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * @(#)queue.h 8.5 (Berkeley) 8/20/94
33 */
34
35#ifndef _SYS_QUEUE_H_
36#define _SYS_QUEUE_H_
37
38/*
39 * This file defines five types of data structures: singly-linked lists,
40 * lists, simple queues, tail queues, and circular queues.
41 *
42 *
43 * A singly-linked list is headed by a single forward pointer. The elements
44 * are singly linked for minimum space and pointer manipulation overhead at
45 * the expense of O(n) removal for arbitrary elements. New elements can be
46 * added to the list after an existing element or at the head of the list.
47 * Elements being removed from the head of the list should use the explicit
48 * macro for this purpose for optimum efficiency. A singly-linked list may
49 * only be traversed in the forward direction. Singly-linked lists are ideal
50 * for applications with large datasets and few or no removals or for
51 * implementing a LIFO queue.
52 *
53 * A list is headed by a single forward pointer (or an array of forward
54 * pointers for a hash table header). The elements are doubly linked
55 * so that an arbitrary element can be removed without a need to
56 * traverse the list. New elements can be added to the list before
57 * or after an existing element or at the head of the list. A list
58 * may only be traversed in the forward direction.
59 *
60 * A simple queue is headed by a pair of pointers, one the head of the
61 * list and the other to the tail of the list. The elements are singly
62 * linked to save space, so elements can only be removed from the
63 * head of the list. New elements can be added to the list before or after
64 * an existing element, at the head of the list, or at the end of the
65 * list. A simple queue may only be traversed in the forward direction.
66 *
67 * A tail queue is headed by a pair of pointers, one to the head of the
68 * list and the other to the tail of the list. The elements are doubly
69 * linked so that an arbitrary element can be removed without a need to
70 * traverse the list. New elements can be added to the list before or
71 * after an existing element, at the head of the list, or at the end of
72 * the list. A tail queue may be traversed in either direction.
73 *
74 * A circle queue is headed by a pair of pointers, one to the head of the
75 * list and the other to the tail of the list. The elements are doubly
76 * linked so that an arbitrary element can be removed without a need to
77 * traverse the list. New elements can be added to the list before or after
78 * an existing element, at the head of the list, or at the end of the list.
79 * A circle queue may be traversed in either direction, but has a more
80 * complex end of list detection.
81 *
82 * For details on the use of these macros, see the queue(3) manual page.
83 */
84
85#ifdef QUEUE_MACRO_DEBUG
86#define _Q_INVALIDATE(a) (a) = ((void *)-1)
87#else
88#define _Q_INVALIDATE(a)
89#endif
90
91/*
92 * Singly-linked List definitions.
93 */
94#define SLIST_HEAD(name, type) \
95struct name { \
96 struct type *slh_first; /* first element */ \
97}
98
99#define SLIST_HEAD_INITIALIZER(head) \
100 { NULL }
101
102#ifdef SLIST_ENTRY
103#undef SLIST_ENTRY
104#endif
105
106#define SLIST_ENTRY(type) \
107struct { \
108 struct type *sle_next; /* next element */ \
109}
110
111/*
112 * Singly-linked List access methods.
113 */
114#define SLIST_FIRST(head) ((head)->slh_first)
115#define SLIST_END(head) NULL
116#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
117#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
118
119#define SLIST_FOREACH(var, head, field) \
120 for((var) = SLIST_FIRST(head); \
121 (var) != SLIST_END(head); \
122 (var) = SLIST_NEXT(var, field))
123
124#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
125 for ((varp) = &SLIST_FIRST((head)); \
126 ((var) = *(varp)) != SLIST_END(head); \
127 (varp) = &SLIST_NEXT((var), field))
128
129/*
130 * Singly-linked List functions.
131 */
132#define SLIST_INIT(head) { \
133 SLIST_FIRST(head) = SLIST_END(head); \
134}
135
136#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
137 (elm)->field.sle_next = (slistelm)->field.sle_next; \
138 (slistelm)->field.sle_next = (elm); \
139} while (0)
140
141#define SLIST_INSERT_HEAD(head, elm, field) do { \
142 (elm)->field.sle_next = (head)->slh_first; \
143 (head)->slh_first = (elm); \
144} while (0)
145
146#define SLIST_REMOVE_NEXT(head, elm, field) do { \
147 (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \
148} while (0)
149
150#define SLIST_REMOVE_HEAD(head, field) do { \
151 (head)->slh_first = (head)->slh_first->field.sle_next; \
152} while (0)
153
154#define SLIST_REMOVE(head, elm, type, field) do { \
155 if ((head)->slh_first == (elm)) { \
156 SLIST_REMOVE_HEAD((head), field); \
157 } else { \
158 struct type *curelm = (head)->slh_first; \
159 \
160 while (curelm->field.sle_next != (elm)) \
161 curelm = curelm->field.sle_next; \
162 curelm->field.sle_next = \
163 curelm->field.sle_next->field.sle_next; \
164 _Q_INVALIDATE((elm)->field.sle_next); \
165 } \
166} while (0)
167
168/*
169 * List definitions.
170 */
171#define LIST_HEAD(name, type) \
172struct name { \
173 struct type *lh_first; /* first element */ \
174}
175
176#define LIST_HEAD_INITIALIZER(head) \
177 { NULL }
178
179#define LIST_ENTRY(type) \
180struct { \
181 struct type *le_next; /* next element */ \
182 struct type **le_prev; /* address of previous next element */ \
183}
184
185/*
186 * List access methods
187 */
188#define LIST_FIRST(head) ((head)->lh_first)
189#define LIST_END(head) NULL
190#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))
191#define LIST_NEXT(elm, field) ((elm)->field.le_next)
192
193#define LIST_FOREACH(var, head, field) \
194 for((var) = LIST_FIRST(head); \
195 (var)!= LIST_END(head); \
196 (var) = LIST_NEXT(var, field))
197
198/*
199 * List functions.
200 */
201#define LIST_INIT(head) do { \
202 LIST_FIRST(head) = LIST_END(head); \
203} while (0)
204
205#define LIST_INSERT_AFTER(listelm, elm, field) do { \
206 if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
207 (listelm)->field.le_next->field.le_prev = \
208 &(elm)->field.le_next; \
209 (listelm)->field.le_next = (elm); \
210 (elm)->field.le_prev = &(listelm)->field.le_next; \
211} while (0)
212
213#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
214 (elm)->field.le_prev = (listelm)->field.le_prev; \
215 (elm)->field.le_next = (listelm); \
216 *(listelm)->field.le_prev = (elm); \
217 (listelm)->field.le_prev = &(elm)->field.le_next; \
218} while (0)
219
220#define LIST_INSERT_HEAD(head, elm, field) do { \
221 if (((elm)->field.le_next = (head)->lh_first) != NULL) \
222 (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
223 (head)->lh_first = (elm); \
224 (elm)->field.le_prev = &(head)->lh_first; \
225} while (0)
226
227#define LIST_REMOVE(elm, field) do { \
228 if ((elm)->field.le_next != NULL) \
229 (elm)->field.le_next->field.le_prev = \
230 (elm)->field.le_prev; \
231 *(elm)->field.le_prev = (elm)->field.le_next; \
232 _Q_INVALIDATE((elm)->field.le_prev); \
233 _Q_INVALIDATE((elm)->field.le_next); \
234} while (0)
235
236#define LIST_REPLACE(elm, elm2, field) do { \
237 if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
238 (elm2)->field.le_next->field.le_prev = \
239 &(elm2)->field.le_next; \
240 (elm2)->field.le_prev = (elm)->field.le_prev; \
241 *(elm2)->field.le_prev = (elm2); \
242 _Q_INVALIDATE((elm)->field.le_prev); \
243 _Q_INVALIDATE((elm)->field.le_next); \
244} while (0)
245
246/*
247 * Simple queue definitions.
248 */
249#define SIMPLEQ_HEAD(name, type) \
250struct name { \
251 struct type *sqh_first; /* first element */ \
252 struct type **sqh_last; /* addr of last next element */ \
253}
254
255#define SIMPLEQ_HEAD_INITIALIZER(head) \
256 { NULL, &(head).sqh_first }
257
258#define SIMPLEQ_ENTRY(type) \
259struct { \
260 struct type *sqe_next; /* next element */ \
261}
262
263/*
264 * Simple queue access methods.
265 */
266#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
267#define SIMPLEQ_END(head) NULL
268#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
269#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
270
271#define SIMPLEQ_FOREACH(var, head, field) \
272 for((var) = SIMPLEQ_FIRST(head); \
273 (var) != SIMPLEQ_END(head); \
274 (var) = SIMPLEQ_NEXT(var, field))
275
276/*
277 * Simple queue functions.
278 */
279#define SIMPLEQ_INIT(head) do { \
280 (head)->sqh_first = NULL; \
281 (head)->sqh_last = &(head)->sqh_first; \
282} while (0)
283
284#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
285 if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
286 (head)->sqh_last = &(elm)->field.sqe_next; \
287 (head)->sqh_first = (elm); \
288} while (0)
289
290#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
291 (elm)->field.sqe_next = NULL; \
292 *(head)->sqh_last = (elm); \
293 (head)->sqh_last = &(elm)->field.sqe_next; \
294} while (0)
295
296#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
297 if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
298 (head)->sqh_last = &(elm)->field.sqe_next; \
299 (listelm)->field.sqe_next = (elm); \
300} while (0)
301
302#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
303 if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
304 (head)->sqh_last = &(head)->sqh_first; \
305} while (0)
306
307/*
308 * Tail queue definitions.
309 */
310#define TAILQ_HEAD(name, type) \
311struct name { \
312 struct type *tqh_first; /* first element */ \
313 struct type **tqh_last; /* addr of last next element */ \
314}
315
316#define TAILQ_HEAD_INITIALIZER(head) \
317 { NULL, &(head).tqh_first }
318
319#define TAILQ_ENTRY(type) \
320struct { \
321 struct type *tqe_next; /* next element */ \
322 struct type **tqe_prev; /* address of previous next element */ \
323}
324
325/*
326 * tail queue access methods
327 */
328#define TAILQ_FIRST(head) ((head)->tqh_first)
329#define TAILQ_END(head) NULL
330#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
331#define TAILQ_LAST(head, headname) \
332 (*(((struct headname *)((head)->tqh_last))->tqh_last))
333/* XXX */
334#define TAILQ_PREV(elm, headname, field) \
335 (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
336#define TAILQ_EMPTY(head) \
337 (TAILQ_FIRST(head) == TAILQ_END(head))
338
339#define TAILQ_FOREACH(var, head, field) \
340 for((var) = TAILQ_FIRST(head); \
341 (var) != TAILQ_END(head); \
342 (var) = TAILQ_NEXT(var, field))
343
344#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
345 for((var) = TAILQ_LAST(head, headname); \
346 (var) != TAILQ_END(head); \
347 (var) = TAILQ_PREV(var, headname, field))
348
349/*
350 * Tail queue functions.
351 */
352#define TAILQ_INIT(head) do { \
353 (head)->tqh_first = NULL; \
354 (head)->tqh_last = &(head)->tqh_first; \
355} while (0)
356
357#define TAILQ_INSERT_HEAD(head, elm, field) do { \
358 if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
359 (head)->tqh_first->field.tqe_prev = \
360 &(elm)->field.tqe_next; \
361 else \
362 (head)->tqh_last = &(elm)->field.tqe_next; \
363 (head)->tqh_first = (elm); \
364 (elm)->field.tqe_prev = &(head)->tqh_first; \
365} while (0)
366
367#define TAILQ_INSERT_TAIL(head, elm, field) do { \
368 (elm)->field.tqe_next = NULL; \
369 (elm)->field.tqe_prev = (head)->tqh_last; \
370 *(head)->tqh_last = (elm); \
371 (head)->tqh_last = &(elm)->field.tqe_next; \
372} while (0)
373
374#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
375 if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
376 (elm)->field.tqe_next->field.tqe_prev = \
377 &(elm)->field.tqe_next; \
378 else \
379 (head)->tqh_last = &(elm)->field.tqe_next; \
380 (listelm)->field.tqe_next = (elm); \
381 (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
382} while (0)
383
384#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
385 (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
386 (elm)->field.tqe_next = (listelm); \
387 *(listelm)->field.tqe_prev = (elm); \
388 (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
389} while (0)
390
391#define TAILQ_REMOVE(head, elm, field) do { \
392 if (((elm)->field.tqe_next) != NULL) \
393 (elm)->field.tqe_next->field.tqe_prev = \
394 (elm)->field.tqe_prev; \
395 else \
396 (head)->tqh_last = (elm)->field.tqe_prev; \
397 *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
398 _Q_INVALIDATE((elm)->field.tqe_prev); \
399 _Q_INVALIDATE((elm)->field.tqe_next); \
400} while (0)
401
402#define TAILQ_REPLACE(head, elm, elm2, field) do { \
403 if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
404 (elm2)->field.tqe_next->field.tqe_prev = \
405 &(elm2)->field.tqe_next; \
406 else \
407 (head)->tqh_last = &(elm2)->field.tqe_next; \
408 (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
409 *(elm2)->field.tqe_prev = (elm2); \
410 _Q_INVALIDATE((elm)->field.tqe_prev); \
411 _Q_INVALIDATE((elm)->field.tqe_next); \
412} while (0)
413
414/*
415 * Circular queue definitions.
416 */
417#define CIRCLEQ_HEAD(name, type) \
418struct name { \
419 struct type *cqh_first; /* first element */ \
420 struct type *cqh_last; /* last element */ \
421}
422
423#define CIRCLEQ_HEAD_INITIALIZER(head) \
424 { CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
425
426#define CIRCLEQ_ENTRY(type) \
427struct { \
428 struct type *cqe_next; /* next element */ \
429 struct type *cqe_prev; /* previous element */ \
430}
431
432/*
433 * Circular queue access methods
434 */
435#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
436#define CIRCLEQ_LAST(head) ((head)->cqh_last)
437#define CIRCLEQ_END(head) ((void *)(head))
438#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
439#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
440#define CIRCLEQ_EMPTY(head) \
441 (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))
442
443#define CIRCLEQ_FOREACH(var, head, field) \
444 for((var) = CIRCLEQ_FIRST(head); \
445 (var) != CIRCLEQ_END(head); \
446 (var) = CIRCLEQ_NEXT(var, field))
447
448#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
449 for((var) = CIRCLEQ_LAST(head); \
450 (var) != CIRCLEQ_END(head); \
451 (var) = CIRCLEQ_PREV(var, field))
452
453/*
454 * Circular queue functions.
455 */
456#define CIRCLEQ_INIT(head) do { \
457 (head)->cqh_first = CIRCLEQ_END(head); \
458 (head)->cqh_last = CIRCLEQ_END(head); \
459} while (0)
460
461#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
462 (elm)->field.cqe_next = (listelm)->field.cqe_next; \
463 (elm)->field.cqe_prev = (listelm); \
464 if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \
465 (head)->cqh_last = (elm); \
466 else \
467 (listelm)->field.cqe_next->field.cqe_prev = (elm); \
468 (listelm)->field.cqe_next = (elm); \
469} while (0)
470
471#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
472 (elm)->field.cqe_next = (listelm); \
473 (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
474 if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \
475 (head)->cqh_first = (elm); \
476 else \
477 (listelm)->field.cqe_prev->field.cqe_next = (elm); \
478 (listelm)->field.cqe_prev = (elm); \
479} while (0)
480
481#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
482 (elm)->field.cqe_next = (head)->cqh_first; \
483 (elm)->field.cqe_prev = CIRCLEQ_END(head); \
484 if ((head)->cqh_last == CIRCLEQ_END(head)) \
485 (head)->cqh_last = (elm); \
486 else \
487 (head)->cqh_first->field.cqe_prev = (elm); \
488 (head)->cqh_first = (elm); \
489} while (0)
490
491#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
492 (elm)->field.cqe_next = CIRCLEQ_END(head); \
493 (elm)->field.cqe_prev = (head)->cqh_last; \
494 if ((head)->cqh_first == CIRCLEQ_END(head)) \
495 (head)->cqh_first = (elm); \
496 else \
497 (head)->cqh_last->field.cqe_next = (elm); \
498 (head)->cqh_last = (elm); \
499} while (0)
500
501#define CIRCLEQ_REMOVE(head, elm, field) do { \
502 if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \
503 (head)->cqh_last = (elm)->field.cqe_prev; \
504 else \
505 (elm)->field.cqe_next->field.cqe_prev = \
506 (elm)->field.cqe_prev; \
507 if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \
508 (head)->cqh_first = (elm)->field.cqe_next; \
509 else \
510 (elm)->field.cqe_prev->field.cqe_next = \
511 (elm)->field.cqe_next; \
512 _Q_INVALIDATE((elm)->field.cqe_prev); \
513 _Q_INVALIDATE((elm)->field.cqe_next); \
514} while (0)
515
516#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \
517 if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \
518 CIRCLEQ_END(head)) \
519 (head).cqh_last = (elm2); \
520 else \
521 (elm2)->field.cqe_next->field.cqe_prev = (elm2); \
522 if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \
523 CIRCLEQ_END(head)) \
524 (head).cqh_first = (elm2); \
525 else \
526 (elm2)->field.cqe_prev->field.cqe_next = (elm2); \
527 _Q_INVALIDATE((elm)->field.cqe_prev); \
528 _Q_INVALIDATE((elm)->field.cqe_next); \
529} while (0)
530
531#endif /* !_SYS_QUEUE_H_ */
diff --git a/src/nat/miniupnp/codelength.h b/src/nat/miniupnp/codelength.h
deleted file mode 100644
index 8a5f49517..000000000
--- a/src/nat/miniupnp/codelength.h
+++ /dev/null
@@ -1,23 +0,0 @@
1/* $Id: codelength.h,v 1.1 2008/10/06 22:04:06 nanard Exp $ */
2/* Project : miniupnp
3 * Author : Thomas BERNARD
4 * copyright (c) 2005-2008 Thomas Bernard
5 * This software is subjet to the conditions detailed in the
6 * provided LICENCE file. */
7#ifndef __CODELENGTH_H__
8#define __CODELENGTH_H__
9
10/* Encode length by using 7bit per Byte :
11 * Most significant bit of each byte specifies that the
12 * following byte is part of the code */
13#define DECODELENGTH(n, p) n = 0; \
14 do { n = (n << 7) | (*p & 0x7f); } \
15 while(*(p++)&0x80);
16
17#define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \
18 if(n>=2097152) *(p++) = (n >> 21) | 0x80; \
19 if(n>=16384) *(p++) = (n >> 14) | 0x80; \
20 if(n>=128) *(p++) = (n >> 7) | 0x80; \
21 *(p++) = n & 0x7f;
22
23#endif
diff --git a/src/nat/miniupnp/declspec.h b/src/nat/miniupnp/declspec.h
deleted file mode 100644
index c064bded2..000000000
--- a/src/nat/miniupnp/declspec.h
+++ /dev/null
@@ -1,14 +0,0 @@
1#ifndef __DECLSPEC_H__
2#define __DECLSPEC_H__
3
4#if defined(WIN32) && !defined(STATICLIB)
5#ifdef MINIUPNP_EXPORTS
6#define LIBSPEC __declspec(dllexport)
7#else
8#define LIBSPEC __declspec(dllimport)
9#endif
10#else
11#define LIBSPEC
12#endif
13
14#endif
diff --git a/src/nat/miniupnp/igd_desc_parse.c b/src/nat/miniupnp/igd_desc_parse.c
deleted file mode 100644
index deb53152c..000000000
--- a/src/nat/miniupnp/igd_desc_parse.c
+++ /dev/null
@@ -1,126 +0,0 @@
1/* $Id: igd_desc_parse.c,v 1.8 2008/04/23 11:51:06 nanard Exp $ */
2/* Project : miniupnp
3 * http://miniupnp.free.fr/
4 * Author : Thomas Bernard
5 * Copyright (c) 2005-2008 Thomas Bernard
6 * This software is subject to the conditions detailed in the
7 * LICENCE file provided in this distribution.
8 * */
9#include "igd_desc_parse.h"
10#include <stdio.h>
11#include <string.h>
12
13/* TODO : rewrite this code so it correctly handle descriptions with
14 * both WANIPConnection and/or WANPPPConnection */
15
16/* Start element handler :
17 * update nesting level counter and copy element name */
18void
19IGDstartelt (void *d, const char *name, int l)
20{
21 struct IGDdatas *datas = (struct IGDdatas *) d;
22 memcpy (datas->cureltname, name, l);
23 datas->cureltname[l] = '\0';
24 datas->level++;
25 if ((l == 7) && !memcmp (name, "service", l))
26 {
27 datas->controlurl_tmp[0] = '\0';
28 datas->eventsuburl_tmp[0] = '\0';
29 datas->scpdurl_tmp[0] = '\0';
30 datas->servicetype_tmp[0] = '\0';
31 }
32}
33
34/* End element handler :
35 * update nesting level counter and update parser state if
36 * service element is parsed */
37void
38IGDendelt (void *d, const char *name, int l)
39{
40 struct IGDdatas *datas = (struct IGDdatas *) d;
41 datas->level--;
42 /*printf("endelt %2d %.*s\n", datas->level, l, name); */
43 if ((l == 7) && !memcmp (name, "service", l))
44 {
45 /*
46 if( datas->state < 1
47 && !strcmp(datas->servicetype,
48 // "urn:schemas-upnp-org:service:WANIPConnection:1") )
49 "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"))
50 datas->state ++;
51 */
52 if (0 == strcmp (datas->servicetype_tmp,
53 "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"))
54 {
55 memcpy (datas->controlurl_CIF, datas->controlurl_tmp,
56 MINIUPNPC_URL_MAXSIZE);
57 memcpy (datas->eventsuburl_CIF, datas->eventsuburl_tmp,
58 MINIUPNPC_URL_MAXSIZE);
59 memcpy (datas->scpdurl_CIF, datas->scpdurl_tmp,
60 MINIUPNPC_URL_MAXSIZE);
61 memcpy (datas->servicetype_CIF, datas->servicetype_tmp,
62 MINIUPNPC_URL_MAXSIZE);
63 }
64 else if (0 == strcmp (datas->servicetype_tmp,
65 "urn:schemas-upnp-org:service:WANIPConnection:1")
66 || 0 == strcmp (datas->servicetype_tmp,
67 "urn:schemas-upnp-org:service:WANPPPConnection:1"))
68 {
69 memcpy (datas->controlurl, datas->controlurl_tmp,
70 MINIUPNPC_URL_MAXSIZE);
71 memcpy (datas->eventsuburl, datas->eventsuburl_tmp,
72 MINIUPNPC_URL_MAXSIZE);
73 memcpy (datas->scpdurl, datas->scpdurl_tmp, MINIUPNPC_URL_MAXSIZE);
74 memcpy (datas->servicetype, datas->servicetype_tmp,
75 MINIUPNPC_URL_MAXSIZE);
76 }
77 }
78}
79
80/* Data handler :
81 * copy data depending on the current element name and state */
82void
83IGDdata (void *d, const char *data, int l)
84{
85 struct IGDdatas *datas = (struct IGDdatas *) d;
86 char *dstmember = 0;
87 /*printf("%2d %s : %.*s\n",
88 datas->level, datas->cureltname, l, data); */
89 if (!strcmp (datas->cureltname, "URLBase"))
90 dstmember = datas->urlbase;
91 else if (!strcmp (datas->cureltname, "serviceType"))
92 dstmember = datas->servicetype_tmp;
93 else if (!strcmp (datas->cureltname, "controlURL"))
94 dstmember = datas->controlurl_tmp;
95 else if (!strcmp (datas->cureltname, "eventSubURL"))
96 dstmember = datas->eventsuburl_tmp;
97 else if (!strcmp (datas->cureltname, "SCPDURL"))
98 dstmember = datas->scpdurl_tmp;
99/* else if( !strcmp(datas->cureltname, "deviceType") )
100 dstmember = datas->devicetype_tmp;*/
101 if (dstmember)
102 {
103 if (l >= MINIUPNPC_URL_MAXSIZE)
104 l = MINIUPNPC_URL_MAXSIZE - 1;
105 memcpy (dstmember, data, l);
106 dstmember[l] = '\0';
107 }
108}
109
110void
111printIGD (struct IGDdatas *d)
112{
113 printf ("urlbase = %s\n", d->urlbase);
114 printf ("WAN Device (Common interface config) :\n");
115 /*printf(" deviceType = %s\n", d->devicetype_CIF); */
116 printf (" serviceType = %s\n", d->servicetype_CIF);
117 printf (" controlURL = %s\n", d->controlurl_CIF);
118 printf (" eventSubURL = %s\n", d->eventsuburl_CIF);
119 printf (" SCPDURL = %s\n", d->scpdurl_CIF);
120 printf ("WAN Connection Device (IP or PPP Connection):\n");
121 /*printf(" deviceType = %s\n", d->devicetype); */
122 printf (" servicetype = %s\n", d->servicetype);
123 printf (" controlURL = %s\n", d->controlurl);
124 printf (" eventSubURL = %s\n", d->eventsuburl);
125 printf (" SCPDURL = %s\n", d->scpdurl);
126}
diff --git a/src/nat/miniupnp/igd_desc_parse.h b/src/nat/miniupnp/igd_desc_parse.h
deleted file mode 100644
index 5e7e24b86..000000000
--- a/src/nat/miniupnp/igd_desc_parse.h
+++ /dev/null
@@ -1,47 +0,0 @@
1/* $Id: igd_desc_parse.h,v 1.6 2008/04/23 11:51:07 nanard Exp $ */
2/* Project : miniupnp
3 * http://miniupnp.free.fr/
4 * Author : Thomas Bernard
5 * Copyright (c) 2005-2008 Thomas Bernard
6 * This software is subject to the conditions detailed in the
7 * LICENCE file provided in this distribution.
8 * */
9#ifndef __IGD_DESC_PARSE_H__
10#define __IGD_DESC_PARSE_H__
11
12/* Structure to store the result of the parsing of UPnP
13 * descriptions of Internet Gateway Devices */
14#define MINIUPNPC_URL_MAXSIZE (128)
15struct IGDdatas
16{
17 char cureltname[MINIUPNPC_URL_MAXSIZE];
18 char urlbase[MINIUPNPC_URL_MAXSIZE];
19 int level;
20 /*int state; */
21 /* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */
22 char controlurl_CIF[MINIUPNPC_URL_MAXSIZE];
23 char eventsuburl_CIF[MINIUPNPC_URL_MAXSIZE];
24 char scpdurl_CIF[MINIUPNPC_URL_MAXSIZE];
25 char servicetype_CIF[MINIUPNPC_URL_MAXSIZE];
26 /*char devicetype_CIF[MINIUPNPC_URL_MAXSIZE]; */
27 /* "urn:schemas-upnp-org:service:WANIPConnection:1"
28 * "urn:schemas-upnp-org:service:WANPPPConnection:1" */
29 char controlurl[MINIUPNPC_URL_MAXSIZE];
30 char eventsuburl[MINIUPNPC_URL_MAXSIZE];
31 char scpdurl[MINIUPNPC_URL_MAXSIZE];
32 char servicetype[MINIUPNPC_URL_MAXSIZE];
33 /*char devicetype[MINIUPNPC_URL_MAXSIZE]; */
34 /* tmp */
35 char controlurl_tmp[MINIUPNPC_URL_MAXSIZE];
36 char eventsuburl_tmp[MINIUPNPC_URL_MAXSIZE];
37 char scpdurl_tmp[MINIUPNPC_URL_MAXSIZE];
38 char servicetype_tmp[MINIUPNPC_URL_MAXSIZE];
39 /*char devicetype_tmp[MINIUPNPC_URL_MAXSIZE]; */
40};
41
42void IGDstartelt (void *, const char *, int);
43void IGDendelt (void *, const char *, int);
44void IGDdata (void *, const char *, int);
45void printIGD (struct IGDdatas *);
46
47#endif
diff --git a/src/nat/miniupnp/minisoap.c b/src/nat/miniupnp/minisoap.c
deleted file mode 100644
index a020f9a64..000000000
--- a/src/nat/miniupnp/minisoap.c
+++ /dev/null
@@ -1,106 +0,0 @@
1/* $Id: minisoap.c,v 1.16 2008/10/11 16:39:29 nanard Exp $ */
2/* Project : miniupnp
3 * Author : Thomas Bernard
4 * Copyright (c) 2005 Thomas Bernard
5 * This software is subject to the conditions detailed in the
6 * LICENCE file provided in this distribution.
7 *
8 * Minimal SOAP implementation for UPnP protocol.
9 */
10#include <stdio.h>
11#include <string.h>
12#ifdef WIN32
13#include <io.h>
14#include <winsock2.h>
15#define snprintf _snprintf
16#else
17#include <unistd.h>
18#include <sys/types.h>
19#include <sys/socket.h>
20#endif
21#include "minisoap.h"
22#include "miniupnpcstrings.h"
23
24/* only for malloc */
25#include <stdlib.h>
26
27#ifdef WIN32
28#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
29#else
30#define PRINT_SOCKET_ERROR(x) perror(x)
31#endif
32
33/* httpWrite sends the headers and the body to the socket
34 * and returns the number of bytes sent */
35static int
36httpWrite (int fd, const char *body, int bodysize,
37 const char *headers, int headerssize)
38{
39 int n = 0;
40 /*n = write(fd, headers, headerssize); */
41 /*if(bodysize>0)
42 n += write(fd, body, bodysize); */
43 /* Note : my old linksys router only took into account
44 * soap request that are sent into only one packet */
45 char *p;
46 /* TODO: AVOID MALLOC */
47 p = malloc (headerssize + bodysize);
48 if (!p)
49 return 0;
50 memcpy (p, headers, headerssize);
51 memcpy (p + headerssize, body, bodysize);
52 /*n = write(fd, p, headerssize+bodysize); */
53 n = send (fd, p, headerssize + bodysize, 0);
54 if (n < 0)
55 {
56 PRINT_SOCKET_ERROR ("send");
57 }
58 /* disable send on the socket */
59 /* draytek routers dont seems to like that... */
60#if 0
61#ifdef WIN32
62 if (shutdown (fd, SD_SEND) < 0)
63 {
64#else
65 if (shutdown (fd, SHUT_WR) < 0)
66 { /*SD_SEND */
67#endif
68 PRINT_SOCKET_ERROR ("shutdown");
69 }
70#endif
71 free (p);
72 return n;
73}
74
75/* self explanatory */
76int
77soapPostSubmit (int fd,
78 const char *url,
79 const char *host,
80 unsigned short port, const char *action, const char *body)
81{
82 int bodysize;
83 char headerbuf[512];
84 int headerssize;
85 char portstr[8];
86 bodysize = (int) strlen (body);
87 /* We are not using keep-alive HTTP connections.
88 * HTTP/1.1 needs the header Connection: close to do that.
89 * This is the default with HTTP/1.0 */
90 /* Connection: Close is normally there only in HTTP/1.1 but who knows */
91 portstr[0] = '\0';
92 if (port != 80)
93 snprintf (portstr, sizeof (portstr), ":%hu", port);
94 headerssize = snprintf (headerbuf, sizeof (headerbuf),
95 "POST %s HTTP/1.1\r\n"
96/* "POST %s HTTP/1.0\r\n"*/
97 "Host: %s%s\r\n" "User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n" "Content-Length: %d\r\n" "Content-Type: text/xml\r\n" "SOAPAction: \"%s\"\r\n" "Connection: Close\r\n" "Cache-Control: no-cache\r\n" /* ??? */
98 "Pragma: no-cache\r\n"
99 "\r\n", url, host, portstr, bodysize, action);
100#ifdef DEBUG
101 printf ("SOAP request : headersize=%d bodysize=%d\n",
102 headerssize, bodysize);
103 /*printf("%s", headerbuf); */
104#endif
105 return httpWrite (fd, body, bodysize, headerbuf, headerssize);
106}
diff --git a/src/nat/miniupnp/minisoap.h b/src/nat/miniupnp/minisoap.h
deleted file mode 100644
index 2505e4c20..000000000
--- a/src/nat/miniupnp/minisoap.h
+++ /dev/null
@@ -1,14 +0,0 @@
1/* $Id: minisoap.h,v 1.3 2006/11/19 22:32:34 nanard Exp $ */
2/* Project : miniupnp
3 * Author : Thomas Bernard
4 * Copyright (c) 2005 Thomas Bernard
5 * This software is subject to the conditions detailed in the
6 * LICENCE file provided in this distribution. */
7#ifndef __MINISOAP_H__
8#define __MINISOAP_H__
9
10/*int httpWrite(int, const char *, int, const char *);*/
11int soapPostSubmit (int, const char *, const char *, unsigned short,
12 const char *, const char *);
13
14#endif
diff --git a/src/nat/miniupnp/minissdpc.c b/src/nat/miniupnp/minissdpc.c
deleted file mode 100644
index 3fe89ef94..000000000
--- a/src/nat/miniupnp/minissdpc.c
+++ /dev/null
@@ -1,111 +0,0 @@
1/* $Id: minissdpc.c,v 1.7 2008/12/18 17:45:48 nanard Exp $ */
2/* Project : miniupnp
3 * Author : Thomas BERNARD
4 * copyright (c) 2005-2008 Thomas Bernard
5 * This software is subjet to the conditions detailed in the
6 * provided LICENCE file. */
7/*#include <syslog.h>*/
8#include <stdio.h>
9#include <string.h>
10#include <stdlib.h>
11#include <unistd.h>
12#include <sys/types.h>
13#ifdef WIN32
14#include <winsock2.h>
15#include <Ws2tcpip.h>
16#include <io.h>
17#else
18#include <sys/socket.h>
19#include <sys/un.h>
20#endif
21
22#include "minissdpc.h"
23#include "miniupnpc.h"
24
25#include "codelength.h"
26
27struct UPNPDev *
28getDevicesFromMiniSSDPD (const char *devtype, const char *socketpath)
29{
30 struct UPNPDev *tmp;
31 struct UPNPDev *devlist = NULL;
32 unsigned char buffer[2048];
33 ssize_t n;
34 unsigned char *p;
35 unsigned char *url;
36 unsigned int i;
37 unsigned int urlsize, stsize, usnsize, l;
38 int s;
39 struct sockaddr_un addr;
40
41 s = socket (AF_UNIX, SOCK_STREAM, 0);
42 if (s < 0)
43 {
44 /*syslog(LOG_ERR, "socket(unix): %m"); */
45 perror ("socket(unix)");
46 return NULL;
47 }
48 addr.sun_family = AF_UNIX;
49 strncpy (addr.sun_path, socketpath, sizeof (addr.sun_path));
50 if (connect (s, (struct sockaddr *) &addr, sizeof (struct sockaddr_un)) < 0)
51 {
52 /*syslog(LOG_WARNING, "connect(\"%s\"): %m", socketpath); */
53 close (s);
54 return NULL;
55 }
56 stsize = strlen (devtype);
57 buffer[0] = 1; /* request type 1 : request devices/services by type */
58 p = buffer + 1;
59 l = stsize;
60 CODELENGTH (l, p);
61 memcpy (p, devtype, stsize);
62 p += stsize;
63 if (write (s, buffer, p - buffer) < 0)
64 {
65 /*syslog(LOG_ERR, "write(): %m"); */
66 perror ("minissdpc.c: write()");
67 close (s);
68 return NULL;
69 }
70 n = read (s, buffer, sizeof (buffer));
71 if (n <= 0)
72 {
73 perror ("minissdpc.c: read()");
74 close (s);
75 return NULL;
76 }
77 p = buffer + 1;
78 for (i = 0; i < buffer[0]; i++)
79 {
80 if (p + 2 >= buffer + sizeof (buffer))
81 break;
82 DECODELENGTH (urlsize, p);
83 if (p + urlsize + 2 >= buffer + sizeof (buffer))
84 break;
85 url = p;
86 p += urlsize;
87 DECODELENGTH (stsize, p);
88 if (p + stsize + 2 >= buffer + sizeof (buffer))
89 break;
90 tmp =
91 (struct UPNPDev *) malloc (sizeof (struct UPNPDev) + urlsize +
92 stsize);
93 tmp->pNext = devlist;
94 tmp->descURL = tmp->buffer;
95 tmp->st = tmp->buffer + 1 + urlsize;
96 memcpy (tmp->buffer, url, urlsize);
97 tmp->buffer[urlsize] = '\0';
98 memcpy (tmp->buffer + urlsize + 1, p, stsize);
99 p += stsize;
100 tmp->buffer[urlsize + 1 + stsize] = '\0';
101 devlist = tmp;
102 /* added for compatibility with recent versions of MiniSSDPd
103 * >= 2007/12/19 */
104 DECODELENGTH (usnsize, p);
105 p += usnsize;
106 if (p > buffer + sizeof (buffer))
107 break;
108 }
109 close (s);
110 return devlist;
111}
diff --git a/src/nat/miniupnp/minissdpc.h b/src/nat/miniupnp/minissdpc.h
deleted file mode 100644
index f6c7db547..000000000
--- a/src/nat/miniupnp/minissdpc.h
+++ /dev/null
@@ -1,14 +0,0 @@
1/* $Id: minissdpc.h,v 1.1 2007/08/31 15:15:33 nanard Exp $ */
2/* Project: miniupnp
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * Author: Thomas Bernard
5 * Copyright (c) 2005-2007 Thomas Bernard
6 * This software is subjects to the conditions detailed
7 * in the LICENCE file provided within this distribution */
8#ifndef __MINISSDPC_H__
9#define __MINISSDPC_H__
10
11struct UPNPDev *getDevicesFromMiniSSDPD (const char *devtype,
12 const char *socketpath);
13
14#endif
diff --git a/src/nat/miniupnp/miniupnpc.c b/src/nat/miniupnp/miniupnpc.c
deleted file mode 100644
index 34bae0ad8..000000000
--- a/src/nat/miniupnp/miniupnpc.c
+++ /dev/null
@@ -1,901 +0,0 @@
1/* $Id: miniupnpc.c,v 1.57 2008/12/18 17:46:36 nanard Exp $ */
2/* Project : miniupnp
3 * Author : Thomas BERNARD
4 * copyright (c) 2005-2007 Thomas Bernard
5 * This software is subjet to the conditions detailed in the
6 * provided LICENCE file. */
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#ifdef WIN32
11/* Win32 Specific includes and defines */
12#include <winsock2.h>
13#include <Ws2tcpip.h>
14#include <Iphlpapi.h>
15#include <io.h>
16#define snprintf _snprintf
17#if defined(_MSC_VER) && (_MSC_VER >= 1400)
18#define strncasecmp _memicmp
19#else
20#define strncasecmp memicmp
21#endif
22#define MAXHOSTNAMELEN 64
23#else
24/* Standard POSIX includes */
25#include <unistd.h>
26#include <sys/socket.h>
27#include <sys/types.h>
28#include <sys/param.h>
29#include <netinet/in.h>
30#include <net/if.h>
31#include <arpa/inet.h>
32#include <poll.h>
33#include <netdb.h>
34#define closesocket close
35#endif
36#include "miniupnpc.h"
37#include "minissdpc.h"
38#include "miniwget.h"
39#include "minisoap.h"
40#include "minixml.h"
41#include "upnpcommands.h"
42
43#ifdef WIN32
44#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
45#else
46#define PRINT_SOCKET_ERROR(x) perror(x)
47#endif
48
49#define SOAPPREFIX "s"
50#define SERVICEPREFIX "u"
51#define SERVICEPREFIX2 'u'
52
53/* root description parsing */
54void
55parserootdesc (const char *buffer, int bufsize, struct IGDdatas *data)
56{
57 struct xmlparser parser;
58 /* xmlparser object */
59 parser.xmlstart = buffer;
60 parser.xmlsize = bufsize;
61 parser.data = data;
62 parser.starteltfunc = IGDstartelt;
63 parser.endeltfunc = IGDendelt;
64 parser.datafunc = IGDdata;
65 parser.attfunc = 0;
66 parsexml (&parser);
67#ifdef DEBUG
68 printIGD (data);
69#endif
70}
71
72/* Content-length: nnn */
73static int
74getcontentlenfromline (const char *p, int n)
75{
76 static const char contlenstr[] = "content-length";
77 const char *p2 = contlenstr;
78 int a = 0;
79 while (*p2)
80 {
81 if (n == 0)
82 return -1;
83 if (*p2 != *p && *p2 != (*p + 32))
84 return -1;
85 p++;
86 p2++;
87 n--;
88 }
89 if (n == 0)
90 return -1;
91 if (*p != ':')
92 return -1;
93 p++;
94 n--;
95 while (*p == ' ')
96 {
97 if (n == 0)
98 return -1;
99 p++;
100 n--;
101 }
102 while (*p >= '0' && *p <= '9')
103 {
104 if (n == 0)
105 return -1;
106 a = (a * 10) + (*p - '0');
107 p++;
108 n--;
109 }
110 return a;
111}
112
113static void
114getContentLengthAndHeaderLength (char *p, int n,
115 int *contentlen, int *headerlen)
116{
117 char *line;
118 int linelen;
119 int r;
120 line = p;
121 while (line < p + n)
122 {
123 linelen = 0;
124 while (line[linelen] != '\r' && line[linelen] != '\r')
125 {
126 if (line + linelen >= p + n)
127 return;
128 linelen++;
129 }
130 r = getcontentlenfromline (line, linelen);
131 if (r > 0)
132 *contentlen = r;
133 line = line + linelen + 2;
134 if (line[0] == '\r' && line[1] == '\n')
135 {
136 *headerlen = (line - p) + 2;
137 return;
138 }
139 }
140}
141
142/* simpleUPnPcommand :
143 * not so simple !
144 * return values :
145 * 0 - OK
146 * -1 - error */
147int
148simpleUPnPcommand (int s, const char *url, const char *service,
149 const char *action, struct UPNParg *args,
150 char *buffer, int *bufsize)
151{
152 struct sockaddr_in dest;
153 struct sockaddr_in6 dest6;
154 char hostname[MAXHOSTNAMELEN + 1];
155 unsigned short port = 0;
156 char *path;
157 char soapact[128];
158 char soapbody[2048];
159 char *buf;
160 int buffree;
161 int n;
162 int err;
163 int contentlen, headerlen; /* for the response */
164 snprintf (soapact, sizeof (soapact), "%s#%s", service, action);
165 if (args == NULL)
166 {
167 /*soapbodylen = */ snprintf (soapbody, sizeof (soapbody),
168 "<?xml version=\"1.0\"?>\r\n"
169 "<" SOAPPREFIX ":Envelope "
170 "xmlns:" SOAPPREFIX
171 "=\"http://schemas.xmlsoap.org/soap/envelope/\" "
172 SOAPPREFIX
173 ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
174 "<" SOAPPREFIX ":Body>" "<" SERVICEPREFIX
175 ":%s xmlns:" SERVICEPREFIX "=\"%s\">" "</"
176 SERVICEPREFIX ":%s>" "</" SOAPPREFIX
177 ":Body></" SOAPPREFIX ":Envelope>" "\r\n",
178 action, service, action);
179 }
180 else
181 {
182 char *p;
183 const char *pe, *pv;
184 int soapbodylen;
185 soapbodylen = snprintf (soapbody, sizeof (soapbody),
186 "<?xml version=\"1.0\"?>\r\n"
187 "<" SOAPPREFIX ":Envelope "
188 "xmlns:" SOAPPREFIX
189 "=\"http://schemas.xmlsoap.org/soap/envelope/\" "
190 SOAPPREFIX
191 ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
192 "<" SOAPPREFIX ":Body>" "<" SERVICEPREFIX
193 ":%s xmlns:" SERVICEPREFIX "=\"%s\">", action,
194 service);
195 p = soapbody + soapbodylen;
196 while (args->elt)
197 {
198 /* check that we are never overflowing the string... */
199 if (soapbody + sizeof (soapbody) <= p + 100)
200 {
201 /* we keep a margin of at least 100 bytes */
202 *bufsize = 0;
203 return -1;
204 }
205 *(p++) = '<';
206 pe = args->elt;
207 while (*pe)
208 *(p++) = *(pe++);
209 *(p++) = '>';
210 if ((pv = args->val))
211 {
212 while (*pv)
213 *(p++) = *(pv++);
214 }
215 *(p++) = '<';
216 *(p++) = '/';
217 pe = args->elt;
218 while (*pe)
219 *(p++) = *(pe++);
220 *(p++) = '>';
221 args++;
222 }
223 *(p++) = '<';
224 *(p++) = '/';
225 *(p++) = SERVICEPREFIX2;
226 *(p++) = ':';
227 pe = action;
228 while (*pe)
229 *(p++) = *(pe++);
230 strncpy (p, "></" SOAPPREFIX ":Body></" SOAPPREFIX ":Envelope>\r\n",
231 soapbody + sizeof (soapbody) - p);
232 }
233 if (!parseURL (url, hostname, &port, &path))
234 return -1;
235
236 if (s < 0)
237 {
238 /* Test IPv4 address, else use IPv6 */
239 if (inet_pton (AF_INET, hostname, &dest.sin_addr) == 1)
240 {
241 memset (&dest, 0, sizeof (dest));
242 dest.sin_family = AF_INET;
243 dest.sin_port = htons (port);
244#ifdef HAVE_SOCKADDR_IN_SIN_LEN
245 dest.sin_len = sizeof (dest);
246#endif
247 if ((s = socket (PF_INET, SOCK_STREAM, 0)) < 0)
248 {
249 PRINT_SOCKET_ERROR ("socket");
250 *bufsize = 0;
251 return -1;
252 }
253 err = connect (s, (struct sockaddr *) &dest, sizeof (dest));
254 }
255 else if (inet_pton (AF_INET6, hostname, &dest6.sin6_addr) == 1)
256 {
257 memset (&dest6, 0, sizeof (dest6));
258 dest6.sin6_family = AF_INET6;
259 dest6.sin6_port = htons (port);
260#ifdef HAVE_SOCKADDR_IN_SIN_LEN
261 dest6.sin6_len = sizeof (dest6);
262#endif
263 if ((s = socket (PF_INET6, SOCK_STREAM, 0)) < 0)
264 {
265 PRINT_SOCKET_ERROR ("socket");
266 *bufsize = 0;
267 return -1;
268 }
269 err = connect (s, (struct sockaddr *) &dest6, sizeof (dest6));
270 }
271 else
272 {
273 PRINT_SOCKET_ERROR ("inet_pton");
274 if (s > 0)
275 closesocket (s);
276
277 *bufsize = 0;
278 return -1;
279 }
280
281 if (err < 0)
282 {
283 PRINT_SOCKET_ERROR ("connect");
284 closesocket (s);
285 *bufsize = 0;
286 return -1;
287 }
288 }
289 n = soapPostSubmit (s, path, hostname, port, soapact, soapbody);
290 if (n <= 0)
291 {
292#ifdef DEBUG
293 printf ("Error sending SOAP request\n");
294#endif
295 closesocket (s);
296 return -1;
297 }
298
299 contentlen = -1;
300 headerlen = -1;
301 buf = buffer;
302 buffree = *bufsize;
303 *bufsize = 0;
304 while ((n = ReceiveData (s, buf, buffree, 5000)) > 0)
305 {
306 buffree -= n;
307 buf += n;
308 *bufsize += n;
309 getContentLengthAndHeaderLength (buffer, *bufsize,
310 &contentlen, &headerlen);
311#ifdef DEBUG
312 printf ("received n=%dbytes bufsize=%d ContLen=%d HeadLen=%d\n",
313 n, *bufsize, contentlen, headerlen);
314#endif
315 /* break if we received everything */
316 if (contentlen > 0 && headerlen > 0
317 && *bufsize >= contentlen + headerlen)
318 break;
319 }
320
321 closesocket (s);
322 return 0;
323}
324
325/* parseMSEARCHReply()
326 * the last 4 arguments are filled during the parsing :
327 * - location/locationsize : "location:" field of the SSDP reply packet
328 * - st/stsize : "st:" field of the SSDP reply packet.
329 * The strings are NOT null terminated */
330static void
331parseMSEARCHReply (const char *reply, int size,
332 const char **location, int *locationsize,
333 const char **st, int *stsize)
334{
335 int a, b, i;
336 i = 0;
337 a = i; /* start of the line */
338 b = 0;
339 while (i < size)
340 {
341 switch (reply[i])
342 {
343 case ':':
344 if (b == 0)
345 {
346 b = i; /* end of the "header" */
347 /*for(j=a; j<b; j++)
348 {
349 putchar(reply[j]);
350 }
351 */
352 }
353 break;
354 case '\x0a':
355 case '\x0d':
356 if (b != 0)
357 {
358 /*for(j=b+1; j<i; j++)
359 {
360 putchar(reply[j]);
361 }
362 putchar('\n'); */
363 do
364 {
365 b++;
366 }
367 while (reply[b] == ' ');
368 if (0 == strncasecmp (reply + a, "location", 8))
369 {
370 *location = reply + b;
371 *locationsize = i - b;
372 }
373 else if (0 == strncasecmp (reply + a, "st", 2))
374 {
375 *st = reply + b;
376 *stsize = i - b;
377 }
378 b = 0;
379 }
380 a = i + 1;
381 break;
382 default:
383 break;
384 }
385 i++;
386 }
387}
388
389/* port upnp discover : SSDP protocol */
390#define PORT 1900
391#define XSTR(s) STR(s)
392#define STR(s) #s
393#define UPNP_MCAST_ADDR "239.255.255.250"
394#define UPNP_MCAST_ADDR6 "FF02:0:0:0:0:0:0:F"
395
396/* upnpDiscover() :
397 * return a chained list of all devices found or NULL if
398 * no devices was found.
399 * It is up to the caller to free the chained list
400 * delay is in millisecond (poll) */
401struct UPNPDev *
402upnpDiscover (int delay, const char *multicastif,
403 const struct sockaddr *addr,
404 const char *minissdpdsock, int sameport)
405{
406 struct UPNPDev *tmp;
407 struct UPNPDev *devlist = 0;
408 int opt = 1;
409 static const char MSearchMsgFmt[] =
410 "M-SEARCH * HTTP/1.1\r\n"
411 "HOST: " UPNP_MCAST_ADDR ":" XSTR (PORT) "\r\n"
412 "ST: %s\r\n" "MAN: \"ssdp:discover\"\r\n" "MX: 3\r\n" "\r\n";
413 static const char *const deviceList[] = {
414 "urn:schemas-upnp-org:device:InternetGatewayDevice:1",
415 "urn:schemas-upnp-org:service:WANIPConnection:1",
416 "urn:schemas-upnp-org:service:WANPPPConnection:1",
417 "upnp:rootdevice",
418 0
419 };
420 int deviceIndex = 0;
421 char bufr[1536]; /* reception and emission buffer */
422 int sudp;
423 int n;
424 int domain = PF_INET;
425 int if_index;
426 struct in6_addr any_addr = IN6ADDR_ANY_INIT;
427 struct sockaddr_in sockudp_r, sockudp_w;
428 struct sockaddr_in6 sockudp6_r, sockudp6_w;
429
430#ifndef WIN32
431 /* first try to get infos from minissdpd ! */
432 if (!minissdpdsock)
433 minissdpdsock = "/var/run/minissdpd.sock";
434 while (!devlist && deviceList[deviceIndex])
435 {
436 devlist = getDevicesFromMiniSSDPD (deviceList[deviceIndex],
437 minissdpdsock);
438 /* We return what we have found if it was not only a rootdevice */
439 if (devlist && !strstr (deviceList[deviceIndex], "rootdevice"))
440 return devlist;
441 deviceIndex++;
442 }
443 deviceIndex = 0;
444#endif
445
446 if (addr && addr->sa_family == AF_INET)
447 domain = PF_INET;
448 else if (addr && addr->sa_family == AF_INET6)
449 domain = PF_INET6;
450 else if (addr)
451 return NULL;
452
453 /* fallback to direct discovery */
454#ifdef WIN32
455 sudp = socket (domain, SOCK_DGRAM, IPPROTO_UDP);
456#else
457 sudp = socket (domain, SOCK_DGRAM, 0);
458#endif
459 if (sudp < 0)
460 {
461 PRINT_SOCKET_ERROR ("socket");
462 return NULL;
463 }
464
465 if (domain == PF_INET)
466 {
467 /* receive */
468 memset (&sockudp_r, 0, sizeof (struct sockaddr_in));
469 sockudp_r.sin_family = AF_INET;
470#ifdef HAVE_SOCKADDR_IN_SIN_LEN
471 sockudp_r.sin_len = sizeof (struct sockaddr_in);
472#endif
473 if (sameport)
474 sockudp_r.sin_port = htons (PORT);
475 sockudp_r.sin_addr.s_addr = INADDR_ANY;
476 /* send */
477 memset (&sockudp_w, 0, sizeof (struct sockaddr_in));
478 sockudp_w.sin_family = AF_INET;
479 sockudp_w.sin_port = htons (PORT);
480 sockudp_w.sin_addr.s_addr = inet_addr (UPNP_MCAST_ADDR);
481#ifdef HAVE_SOCKADDR_IN_SIN_LEN
482 sockudp_w.sin_len = sizeof (struct sockaddr_in);
483#endif
484 }
485 else
486 {
487 /* receive */
488 memcpy (&sockudp6_r, addr, sizeof (struct sockaddr_in6));
489 if (sameport)
490 sockudp6_r.sin6_port = htons (PORT);
491 else
492 sockudp6_r.sin6_port = 0;
493 sockudp6_r.sin6_addr = any_addr;
494#ifdef HAVE_SOCKADDR_IN_SIN_LEN
495 sockudp6_r.sin6_len = sizeof (struct sockaddr_in6);
496#endif
497 /* send */
498 memset (&sockudp6_w, 0, sizeof (struct sockaddr_in6));
499 sockudp6_w.sin6_family = AF_INET6;
500 sockudp6_w.sin6_port = htons (PORT);
501 if (inet_pton (AF_INET6, UPNP_MCAST_ADDR6, &sockudp6_w.sin6_addr) != 1)
502 {
503 PRINT_SOCKET_ERROR ("inet_pton");
504 return NULL;
505 }
506#ifdef HAVE_SOCKADDR_IN_SIN_LEN
507 sockudp6_w.sin6_len = sizeof (struct sockaddr_in6);
508#endif
509 }
510
511#ifdef WIN32
512 if (setsockopt
513 (sudp, SOL_SOCKET, SO_REUSEADDR, (const char *) &opt, sizeof (opt)) < 0)
514#else
515 if (setsockopt (sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0)
516#endif
517 {
518 PRINT_SOCKET_ERROR ("setsockopt");
519 return NULL;
520 }
521
522 if (addr)
523 {
524 if (domain == PF_INET)
525 {
526 sockudp_r.sin_addr.s_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
527 if (setsockopt
528 (sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *) &sockudp_r.sin_addr,
529 sizeof (struct in_addr)) < 0)
530 {
531 PRINT_SOCKET_ERROR ("setsockopt");
532 }
533
534 /* Bind to receive response before sending packet */
535 if (bind (sudp, (struct sockaddr *) &sockudp_r, sizeof (struct sockaddr_in))
536 != 0)
537 {
538 PRINT_SOCKET_ERROR ("bind");
539 closesocket (sudp);
540 return NULL;
541 }
542 }
543 else
544 {
545 if (multicastif)
546 {
547 if_index = if_nametoindex (multicastif);
548 if (!if_index)
549 PRINT_SOCKET_ERROR ("if_nametoindex");
550
551 if (setsockopt
552 (sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &if_index, sizeof (if_index)) < 0)
553 {
554 PRINT_SOCKET_ERROR ("setsockopt");
555 }
556 }
557
558 /* Bind to receive response before sending packet */
559 memcpy (&sockudp6_r.sin6_addr, &((struct sockaddr_in6 *) addr)->sin6_addr,
560 sizeof (sockudp6_r.sin6_addr));
561 if (bind (sudp, (struct sockaddr *) &sockudp6_r, sizeof (struct sockaddr_in6))
562 != 0)
563 {
564 PRINT_SOCKET_ERROR ("bind");
565 closesocket (sudp);
566 return NULL;
567 }
568 }
569 }
570
571 /* receiving SSDP response packet */
572 for (n = 0;;)
573 {
574 if (n == 0)
575 {
576 /* sending the SSDP M-SEARCH packet */
577 n = snprintf (bufr, sizeof (bufr),
578 MSearchMsgFmt, deviceList[deviceIndex++]);
579 /*printf("Sending %s", bufr); */
580 if (domain == PF_INET)
581 n = sendto (sudp, bufr, n, 0,
582 (struct sockaddr *) &sockudp_w,
583 sizeof (struct sockaddr_in));
584 else
585 n = sendto (sudp, bufr, n, 0,
586 (struct sockaddr *) &sockudp6_w,
587 sizeof (struct sockaddr_in6));
588
589 if (n < 0)
590 {
591 PRINT_SOCKET_ERROR ("sendto");
592 closesocket (sudp);
593 return devlist;
594 }
595 }
596 /* Waiting for SSDP REPLY packet to M-SEARCH */
597 n = ReceiveData (sudp, bufr, sizeof (bufr), delay);
598
599 if (n < 0)
600 {
601 /* error */
602 closesocket (sudp);
603 return devlist;
604 }
605 else if (n == 0)
606 {
607 /* no data or Time Out */
608 if (devlist || (deviceList[deviceIndex] == 0))
609 {
610 /* no more device type to look for... */
611 closesocket (sudp);
612 return devlist;
613 }
614 }
615 else
616 {
617 const char *descURL = NULL;
618 int urlsize = 0;
619 const char *st = NULL;
620 int stsize = 0;
621 /*printf("%d byte(s) :\n%s\n", n, bufr); *//* affichage du message */
622 parseMSEARCHReply (bufr, n, &descURL, &urlsize, &st, &stsize);
623 if (st && descURL)
624 {
625 /*printf("M-SEARCH Reply:\nST: %.*s\nLocation: %.*s\n",
626 stsize, st, urlsize, descURL); */
627 tmp =
628 (struct UPNPDev *) malloc (sizeof (struct UPNPDev) + urlsize +
629 stsize);
630 tmp->pNext = devlist;
631 tmp->descURL = tmp->buffer;
632 tmp->st = tmp->buffer + 1 + urlsize;
633 memcpy (tmp->buffer, descURL, urlsize);
634 tmp->buffer[urlsize] = '\0';
635 memcpy (tmp->buffer + urlsize + 1, st, stsize);
636 tmp->buffer[urlsize + 1 + stsize] = '\0';
637 devlist = tmp;
638 }
639 }
640 }
641}
642
643/* freeUPNPDevlist() should be used to
644 * free the chained list returned by upnpDiscover() */
645void
646freeUPNPDevlist (struct UPNPDev *devlist)
647{
648 struct UPNPDev *next;
649 while (devlist)
650 {
651 next = devlist->pNext;
652 free (devlist);
653 devlist = next;
654 }
655}
656
657static void
658url_cpy_or_cat (char *dst, const char *src, int n)
659{
660 if ((src[0] == 'h')
661 && (src[1] == 't')
662 && (src[2] == 't')
663 && (src[3] == 'p')
664 && (src[4] == ':') && (src[5] == '/') && (src[6] == '/'))
665 {
666 strncpy (dst, src, n);
667 }
668 else
669 {
670 int l = strlen (dst);
671 if (src[0] != '/')
672 dst[l++] = '/';
673 if (l <= n)
674 strncpy (dst + l, src, n - l);
675 }
676}
677
678/* Prepare the Urls for usage...
679 */
680void
681GetUPNPUrls (struct UPNPUrls *urls, struct IGDdatas *data,
682 const char *descURL)
683{
684 char *p;
685 int n1, n2, n3;
686 n1 = strlen (data->urlbase);
687 if (n1 == 0)
688 n1 = strlen (descURL);
689 n1 += 2; /* 1 byte more for Null terminator, 1 byte for '/' if needed */
690 n2 = n1;
691 n3 = n1;
692 n1 += strlen (data->scpdurl);
693 n2 += strlen (data->controlurl);
694 n3 += strlen (data->controlurl_CIF);
695
696 urls->ipcondescURL = (char *) malloc (n1);
697 urls->controlURL = (char *) malloc (n2);
698 urls->controlURL_CIF = (char *) malloc (n3);
699 /* maintenant on chope la desc du WANIPConnection */
700 if (data->urlbase[0] != '\0')
701 strncpy (urls->ipcondescURL, data->urlbase, n1);
702 else
703 strncpy (urls->ipcondescURL, descURL, n1);
704 p = strchr (urls->ipcondescURL + 7, '/');
705 if (p)
706 p[0] = '\0';
707 strncpy (urls->controlURL, urls->ipcondescURL, n2);
708 strncpy (urls->controlURL_CIF, urls->ipcondescURL, n3);
709
710 url_cpy_or_cat (urls->ipcondescURL, data->scpdurl, n1);
711
712 url_cpy_or_cat (urls->controlURL, data->controlurl, n2);
713
714 url_cpy_or_cat (urls->controlURL_CIF, data->controlurl_CIF, n3);
715
716#ifdef DEBUG
717 printf ("urls->ipcondescURL='%s' %d n1=%d\n", urls->ipcondescURL,
718 strlen (urls->ipcondescURL), n1);
719 printf ("urls->controlURL='%s' %d n2=%d\n", urls->controlURL,
720 strlen (urls->controlURL), n2);
721 printf ("urls->controlURL_CIF='%s' %d n3=%d\n", urls->controlURL_CIF,
722 strlen (urls->controlURL_CIF), n3);
723#endif
724}
725
726void
727FreeUPNPUrls (struct UPNPUrls *urls)
728{
729 if (!urls)
730 return;
731 free (urls->controlURL);
732 urls->controlURL = 0;
733 free (urls->ipcondescURL);
734 urls->ipcondescURL = 0;
735 free (urls->controlURL_CIF);
736 urls->controlURL_CIF = 0;
737}
738
739
740int
741ReceiveData (int socket, char *data, int length, int timeout)
742{
743 int n;
744#ifndef WIN32
745 struct pollfd fds[1]; /* for the poll */
746 fds[0].fd = socket;
747 fds[0].events = POLLIN;
748 n = poll (fds, 1, timeout);
749 if (n < 0)
750 {
751 PRINT_SOCKET_ERROR ("poll");
752 return -1;
753 }
754 else if (n == 0)
755 {
756 return 0;
757 }
758#else
759 fd_set socketSet;
760 TIMEVAL timeval;
761 FD_ZERO (&socketSet);
762 FD_SET (socket, &socketSet);
763 timeval.tv_sec = timeout / 1000;
764 timeval.tv_usec = (timeout % 1000) * 1000;
765 /*n = select(0, &socketSet, NULL, NULL, &timeval); */
766 n = select (FD_SETSIZE, &socketSet, NULL, NULL, &timeval);
767 if (n < 0)
768 {
769 PRINT_SOCKET_ERROR ("select");
770 return -1;
771 }
772 else if (n == 0)
773 {
774 return 0;
775 }
776#endif
777 n = recv (socket, data, length, 0);
778 if (n < 0)
779 {
780 PRINT_SOCKET_ERROR ("recv");
781 }
782 return n;
783}
784
785int
786UPNPIGD_IsConnected (struct UPNPUrls *urls, struct IGDdatas *data)
787{
788 char status[64];
789 unsigned int uptime;
790 status[0] = '\0';
791 UPNP_GetStatusInfo (urls->controlURL, data->servicetype,
792 status, &uptime, NULL);
793 if (0 == strcmp ("Connected", status))
794 {
795 return 1;
796 }
797 else
798 return 0;
799}
800
801
802/* UPNP_GetValidIGD() :
803 * return values :
804 * 0 = NO IGD found
805 * 1 = A valid connected IGD has been found
806 * 2 = A valid IGD has been found but it reported as
807 * not connected
808 * 3 = an UPnP device has been found but was not recognized as an IGD
809 *
810 * In any non zero return case, the urls and data structures
811 * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
812 * free allocated memory.
813 */
814int
815UPNP_GetValidIGD (struct UPNPDev *devlist,
816 struct UPNPUrls *urls,
817 struct IGDdatas *data, char *lanaddr, int lanaddrlen)
818{
819 char *descXML;
820 int descXMLsize = 0;
821 struct UPNPDev *dev;
822 int ndev = 0;
823 int state; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */
824 if (!devlist)
825 {
826#ifdef DEBUG
827 printf ("Empty devlist\n");
828#endif
829 return 0;
830 }
831 for (state = 1; state <= 3; state++)
832 {
833 for (dev = devlist; dev; dev = dev->pNext)
834 {
835 /* we should choose an internet gateway device.
836 * with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */
837 descXML = miniwget_getaddr (dev->descURL, &descXMLsize,
838 lanaddr, lanaddrlen);
839 if (descXML)
840 {
841 ndev++;
842 memset (data, 0, sizeof (struct IGDdatas));
843 memset (urls, 0, sizeof (struct UPNPUrls));
844 parserootdesc (descXML, descXMLsize, data);
845 free (descXML);
846 descXML = NULL;
847 if (0 == strcmp (data->servicetype_CIF,
848 "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")
849 || state >= 3)
850 {
851 GetUPNPUrls (urls, data, dev->descURL);
852
853#ifdef DEBUG
854 printf ("UPNPIGD_IsConnected(%s) = %d\n",
855 urls->controlURL, UPNPIGD_IsConnected (urls, data));
856#endif
857 if ((state >= 2) || UPNPIGD_IsConnected (urls, data))
858 return state;
859 FreeUPNPUrls (urls);
860 }
861 memset (data, 0, sizeof (struct IGDdatas));
862 }
863#ifdef DEBUG
864 else
865 {
866 printf ("error getting XML description %s\n", dev->descURL);
867 }
868#endif
869 }
870 }
871 return 0;
872}
873
874/* UPNP_GetIGDFromUrl()
875 * Used when skipping the discovery process.
876 * return value :
877 * 0 - Not ok
878 * 1 - OK */
879int
880UPNP_GetIGDFromUrl (const char *rootdescurl,
881 struct UPNPUrls *urls,
882 struct IGDdatas *data, char *lanaddr, int lanaddrlen)
883{
884 char *descXML;
885 int descXMLsize = 0;
886 descXML = miniwget_getaddr (rootdescurl, &descXMLsize, lanaddr, lanaddrlen);
887 if (descXML)
888 {
889 memset (data, 0, sizeof (struct IGDdatas));
890 memset (urls, 0, sizeof (struct UPNPUrls));
891 parserootdesc (descXML, descXMLsize, data);
892 free (descXML);
893 descXML = NULL;
894 GetUPNPUrls (urls, data, rootdescurl);
895 return 1;
896 }
897 else
898 {
899 return 0;
900 }
901}
diff --git a/src/nat/miniupnp/miniupnpc.h b/src/nat/miniupnp/miniupnpc.h
deleted file mode 100644
index 8aa047b64..000000000
--- a/src/nat/miniupnp/miniupnpc.h
+++ /dev/null
@@ -1,120 +0,0 @@
1/* $Id: miniupnpc.h,v 1.18 2008/09/25 18:02:50 nanard Exp $ */
2/* Project: miniupnp
3 * http://miniupnp.free.fr/
4 * Author: Thomas Bernard
5 * Copyright (c) 2005-2006 Thomas Bernard
6 * This software is subjects to the conditions detailed
7 * in the LICENCE file provided within this distribution */
8#ifndef __MINIUPNPC_H__
9#define __MINIUPNPC_H__
10
11#include "declspec.h"
12#include "igd_desc_parse.h"
13
14#ifdef WIN32
15#include <winsock2.h>
16#else
17#include <sys/socket.h>
18#endif
19
20#ifdef __cplusplus
21extern "C"
22{
23#endif
24
25/* Structures definitions : */
26 struct UPNParg
27 {
28 const char *elt;
29 const char *val;
30 };
31
32 int simpleUPnPcommand (int s, const char *, const char *,
33 const char *, struct UPNParg *, char *, int *);
34
35 struct UPNPDev
36 {
37 struct UPNPDev *pNext;
38 char *descURL;
39 char *st;
40 char buffer[2];
41 };
42
43/* upnpDiscover()
44 * discover UPnP devices on the network.
45 * The discovered devices are returned as a chained list.
46 * It is up to the caller to free the list with freeUPNPDevlist().
47 * delay (in millisecond) is the maximum time for waiting any device
48 * response.
49 * If available, device list will be obtained from MiniSSDPd.
50 * Default path for minissdpd socket will be used if minissdpdsock argument
51 * is NULL.
52 * If multicastif is not NULL, it will be used instead of the default
53 * multicast interface for sending SSDP discover packets.
54 * If sameport is not null, SSDP packets will be sent from the source port
55 * 1900 (same as destination port) otherwise system assign a source port. */
56 LIBSPEC struct UPNPDev *upnpDiscover (int delay, const char *multicastif, const struct sockaddr *addr,
57 const char *minissdpdsock, int sameport);
58/* freeUPNPDevlist()
59 * free list returned by upnpDiscover() */
60 LIBSPEC void freeUPNPDevlist (struct UPNPDev *devlist);
61
62/* parserootdesc() :
63 * parse root XML description of a UPnP device and fill the IGDdatas
64 * structure. */
65 LIBSPEC void parserootdesc (const char *, int, struct IGDdatas *);
66
67/* structure used to get fast access to urls
68 * controlURL: controlURL of the WANIPConnection
69 * ipcondescURL: url of the description of the WANIPConnection
70 * controlURL_CIF: controlURL of the WANCommonInterfaceConfig
71 */
72 struct UPNPUrls
73 {
74 char *controlURL;
75 char *ipcondescURL;
76 char *controlURL_CIF;
77 };
78
79/* UPNP_GetValidIGD() :
80 * return values :
81 * 0 = NO IGD found
82 * 1 = A valid connected IGD has been found
83 * 2 = A valid IGD has been found but it reported as
84 * not connected
85 * 3 = an UPnP device has been found but was not recognized as an IGD
86 *
87 * In any non zero return case, the urls and data structures
88 * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
89 * free allocated memory.
90 */
91 LIBSPEC int
92 UPNP_GetValidIGD (struct UPNPDev *devlist,
93 struct UPNPUrls *urls,
94 struct IGDdatas *data, char *lanaddr, int lanaddrlen);
95
96/* UPNP_GetIGDFromUrl()
97 * Used when skipping the discovery process.
98 * return value :
99 * 0 - Not ok
100 * 1 - OK */
101 LIBSPEC int
102 UPNP_GetIGDFromUrl (const char *rootdescurl,
103 struct UPNPUrls *urls,
104 struct IGDdatas *data, char *lanaddr, int lanaddrlen);
105
106 LIBSPEC void GetUPNPUrls (struct UPNPUrls *, struct IGDdatas *,
107 const char *);
108
109 LIBSPEC void FreeUPNPUrls (struct UPNPUrls *);
110
111/* Reads data from the specified socket.
112 * Returns the number of bytes read if successful, zero if no bytes were
113 * read or if we timed out. Returns negative if there was an error. */
114 int ReceiveData (int socket, char *data, int length, int timeout);
115
116#ifdef __cplusplus
117}
118#endif
119
120#endif
diff --git a/src/nat/miniupnp/miniupnpcstrings.h b/src/nat/miniupnp/miniupnpcstrings.h
deleted file mode 100644
index 3245e1f69..000000000
--- a/src/nat/miniupnp/miniupnpcstrings.h
+++ /dev/null
@@ -1,14 +0,0 @@
1/* $Id: miniupnpcstrings.h,v 1.2 2008/10/14 17:39:04 nanard Exp $ */
2/* Project: miniupnp
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * Author: Thomas Bernard
5 * Copyright (c) 2005-2008 Thomas Bernard
6 * This software is subjects to the conditions detailed
7 * in the LICENCE file provided within this distribution */
8#ifndef __MINIUPNPCSTRINGS_H__
9#define __MINIUPNPCSTRINGS_H__
10
11#define OS_STRING "Debian/4.0"
12#define MINIUPNPC_VERSION_STRING "1.2"
13
14#endif
diff --git a/src/nat/miniupnp/miniwget.c b/src/nat/miniupnp/miniwget.c
deleted file mode 100644
index 38d5610d8..000000000
--- a/src/nat/miniupnp/miniwget.c
+++ /dev/null
@@ -1,224 +0,0 @@
1/* $Id: miniwget.c,v 1.22 2009/02/28 10:36:35 nanard Exp $ */
2/* Project : miniupnp
3 * Author : Thomas Bernard
4 * Copyright (c) 2005 Thomas Bernard
5 * This software is subject to the conditions detailed in the
6 * LICENCE file provided in this distribution.
7 * */
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include "miniupnpc.h"
12#ifdef WIN32
13#include <winsock2.h>
14#include <io.h>
15#define MAXHOSTNAMELEN 64
16#define MIN(x,y) (((x)<(y))?(x):(y))
17#define snprintf _snprintf
18#define herror
19#define socklen_t int
20#else
21#include <unistd.h>
22#include <sys/param.h>
23#include <sys/socket.h>
24#include <netdb.h>
25#include <netinet/in.h>
26#include <arpa/inet.h>
27#define closesocket close
28#endif
29#if defined(__sun) || defined(sun)
30#define MIN(x,y) (((x)<(y))?(x):(y))
31#endif
32
33#include "miniupnpcstrings.h"
34
35/* miniwget2() :
36 * */
37static void *
38miniwget2 (const char *url, const char *host,
39 unsigned short port, const char *path,
40 int *size, char *addr_str, int addr_str_len)
41{
42 char buf[2048];
43 int s;
44 struct sockaddr_in dest;
45 struct hostent *hp;
46 *size = 0;
47 hp = gethostbyname (host);
48 if (hp == NULL)
49 {
50 herror (host);
51 return NULL;
52 }
53 /* memcpy((char *)&dest.sin_addr, hp->h_addr, hp->h_length); */
54 memcpy (&dest.sin_addr, hp->h_addr, sizeof (dest.sin_addr));
55 memset (dest.sin_zero, 0, sizeof (dest.sin_zero));
56 s = socket (PF_INET, SOCK_STREAM, 0);
57 if (s < 0)
58 {
59 perror ("socket");
60 return NULL;
61 }
62 dest.sin_family = AF_INET;
63 dest.sin_port = htons (port);
64 if (connect (s, (struct sockaddr *) &dest, sizeof (struct sockaddr_in)) < 0)
65 {
66 perror ("connect");
67 closesocket (s);
68 return NULL;
69 }
70
71 /* get address for caller ! */
72 if (addr_str)
73 {
74 struct sockaddr_in saddr;
75 socklen_t len;
76
77 len = sizeof (saddr);
78 getsockname (s, (struct sockaddr *) &saddr, &len);
79#ifndef WIN32
80 inet_ntop (AF_INET, &saddr.sin_addr, addr_str, addr_str_len);
81#else
82 /* using INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD);
83 * But his function make a string with the port : nn.nn.nn.nn:port */
84/* if(WSAAddressToStringA((SOCKADDR *)&saddr, sizeof(saddr),
85 NULL, addr_str, (DWORD *)&addr_str_len))
86 {
87 printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError());
88 }*/
89 strncpy (addr_str, inet_ntoa (saddr.sin_addr), addr_str_len);
90#endif
91#ifdef DEBUG
92 printf ("address miniwget : %s\n", addr_str);
93#endif
94 }
95
96 snprintf (buf, sizeof (buf),
97 "GET %s HTTP/1.1\r\n"
98 "Host: %s:%d\r\n"
99 "Connection: Close\r\n"
100 "User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/"
101 MINIUPNPC_VERSION_STRING "\r\n" "\r\n", path, host, port);
102 /*write(s, buf, strlen(buf)); */
103 send (s, buf, strlen (buf), 0);
104 {
105 int n, headers = 1;
106 char *respbuffer = NULL;
107 int allreadyread = 0;
108 /*while((n = recv(s, buf, 2048, 0)) > 0) */
109 while ((n = ReceiveData (s, buf, 2048, 5000)) > 0)
110 {
111 if (headers)
112 {
113 int i = 0;
114 while (i < n - 3)
115 {
116 if (buf[i] == '\r' && buf[i + 1] == '\n'
117 && buf[i + 2] == '\r' && buf[i + 3] == '\n')
118 {
119 headers = 0; /* end */
120 if (i < n - 4)
121 {
122 respbuffer = (char *) realloc ((void *) respbuffer,
123 allreadyread + (n - i -
124 4));
125 memcpy (respbuffer + allreadyread, buf + i + 4,
126 n - i - 4);
127 allreadyread += (n - i - 4);
128 }
129 break;
130 }
131 i++;
132 }
133 }
134 else
135 {
136 respbuffer = (char *) realloc ((void *) respbuffer,
137 allreadyread + n);
138 memcpy (respbuffer + allreadyread, buf, n);
139 allreadyread += n;
140 }
141 }
142 *size = allreadyread;
143#ifdef DEBUG
144 printf ("%d bytes read\n", *size);
145#endif
146 closesocket (s);
147 return respbuffer;
148 }
149}
150
151/* parseURL()
152 * arguments :
153 * url : source string not modified
154 * hostname : hostname destination string (size of MAXHOSTNAMELEN+1)
155 * port : port (destination)
156 * path : pointer to the path part of the URL
157 *
158 * Return values :
159 * 0 - Failure
160 * 1 - Success */
161int
162parseURL (const char *url, char *hostname, unsigned short *port, char **path)
163{
164 char *p1, *p2, *p3;
165 p1 = strstr (url, "://");
166 if (!p1)
167 return 0;
168 p1 += 3;
169 if ((url[0] != 'h') || (url[1] != 't')
170 || (url[2] != 't') || (url[3] != 'p'))
171 return 0;
172 p2 = strchr (p1, ':');
173 p3 = strchr (p1, '/');
174 if (!p3)
175 return 0;
176 memset (hostname, 0, MAXHOSTNAMELEN + 1);
177 if (!p2 || (p2 > p3))
178 {
179 strncpy (hostname, p1, MIN (MAXHOSTNAMELEN, (int) (p3 - p1)));
180 *port = 80;
181 }
182 else
183 {
184 strncpy (hostname, p1, MIN (MAXHOSTNAMELEN, (int) (p2 - p1)));
185 *port = 0;
186 p2++;
187 while ((*p2 >= '0') && (*p2 <= '9'))
188 {
189 *port *= 10;
190 *port += (unsigned short) (*p2 - '0');
191 p2++;
192 }
193 }
194 *path = p3;
195 return 1;
196}
197
198void *
199miniwget (const char *url, int *size)
200{
201 unsigned short port;
202 char *path;
203 /* protocol://host:port/chemin */
204 char hostname[MAXHOSTNAMELEN + 1];
205 *size = 0;
206 if (!parseURL (url, hostname, &port, &path))
207 return NULL;
208 return miniwget2 (url, hostname, port, path, size, 0, 0);
209}
210
211void *
212miniwget_getaddr (const char *url, int *size, char *addr, int addrlen)
213{
214 unsigned short port;
215 char *path;
216 /* protocol://host:port/chemin */
217 char hostname[MAXHOSTNAMELEN + 1];
218 *size = 0;
219 if (addr)
220 addr[0] = '\0';
221 if (!parseURL (url, hostname, &port, &path))
222 return NULL;
223 return miniwget2 (url, hostname, port, path, size, addr, addrlen);
224}
diff --git a/src/nat/miniupnp/miniwget.h b/src/nat/miniupnp/miniwget.h
deleted file mode 100644
index 04e91df64..000000000
--- a/src/nat/miniupnp/miniwget.h
+++ /dev/null
@@ -1,28 +0,0 @@
1/* $Id: miniwget.h,v 1.5 2007/01/29 20:27:23 nanard Exp $ */
2/* Project : miniupnp
3 * Author : Thomas Bernard
4 * Copyright (c) 2005 Thomas Bernard
5 * This software is subject to the conditions detailed in the
6 * LICENCE file provided in this distribution.
7 * */
8#ifndef __MINIWGET_H__
9#define __MINIWGET_H__
10
11#include "declspec.h"
12
13#ifdef __cplusplus
14extern "C"
15{
16#endif
17
18 LIBSPEC void *miniwget (const char *, int *);
19
20 LIBSPEC void *miniwget_getaddr (const char *, int *, char *, int);
21
22 int parseURL (const char *, char *, unsigned short *, char **);
23
24#ifdef __cplusplus
25}
26#endif
27
28#endif
diff --git a/src/nat/miniupnp/minixml.c b/src/nat/miniupnp/minixml.c
deleted file mode 100644
index 094118cfa..000000000
--- a/src/nat/miniupnp/minixml.c
+++ /dev/null
@@ -1,200 +0,0 @@
1/* $Id: minixml.c,v 1.6 2007/05/15 18:14:08 nanard Exp $ */
2/* minixml.c : the minimum size a xml parser can be ! */
3/* Project : miniupnp
4 * webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
5 * Author : Thomas Bernard
6
7Copyright (c) 2005-2007, Thomas BERNARD
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 * Redistributions of source code must retain the above copyright notice,
14 this list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 this list of conditions and the following disclaimer in the documentation
17 and/or other materials provided with the distribution.
18 * The name of the author may not be used to endorse or promote products
19 derived from this software without specific prior written permission.
20
21THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31POSSIBILITY OF SUCH DAMAGE.
32*/
33#include "minixml.h"
34
35/* parseatt : used to parse the argument list
36 * return 0 (false) in case of success and -1 (true) if the end
37 * of the xmlbuffer is reached. */
38int
39parseatt (struct xmlparser *p)
40{
41 const char *attname;
42 int attnamelen;
43 const char *attvalue;
44 int attvaluelen;
45 while (p->xml < p->xmlend)
46 {
47 if (*p->xml == '/' || *p->xml == '>')
48 return 0;
49 if (!IS_WHITE_SPACE (*p->xml))
50 {
51 char sep;
52 attname = p->xml;
53 attnamelen = 0;
54 while (*p->xml != '=' && !IS_WHITE_SPACE (*p->xml))
55 {
56 attnamelen++;
57 p->xml++;
58 if (p->xml >= p->xmlend)
59 return -1;
60 }
61 while (*(p->xml++) != '=')
62 {
63 if (p->xml >= p->xmlend)
64 return -1;
65 }
66 while (IS_WHITE_SPACE (*p->xml))
67 {
68 p->xml++;
69 if (p->xml >= p->xmlend)
70 return -1;
71 }
72 sep = *p->xml;
73 if (sep == '\'' || sep == '\"')
74 {
75 p->xml++;
76 if (p->xml >= p->xmlend)
77 return -1;
78 attvalue = p->xml;
79 attvaluelen = 0;
80 while (*p->xml != sep)
81 {
82 attvaluelen++;
83 p->xml++;
84 if (p->xml >= p->xmlend)
85 return -1;
86 }
87 }
88 else
89 {
90 attvalue = p->xml;
91 attvaluelen = 0;
92 while (!IS_WHITE_SPACE (*p->xml)
93 && *p->xml != '>' && *p->xml != '/')
94 {
95 attvaluelen++;
96 p->xml++;
97 if (p->xml >= p->xmlend)
98 return -1;
99 }
100 }
101 /*printf("%.*s='%.*s'\n",
102 attnamelen, attname, attvaluelen, attvalue); */
103 if (p->attfunc)
104 p->attfunc (p->data, attname, attnamelen, attvalue, attvaluelen);
105 }
106 p->xml++;
107 }
108 return -1;
109}
110
111/* parseelt parse the xml stream and
112 * call the callback functions when needed... */
113void
114parseelt (struct xmlparser *p)
115{
116 int i;
117 const char *elementname;
118 while (p->xml < (p->xmlend - 1))
119 {
120 if ((p->xml)[0] == '<' && (p->xml)[1] != '?')
121 {
122 i = 0;
123 elementname = ++p->xml;
124 while (!IS_WHITE_SPACE (*p->xml)
125 && (*p->xml != '>') && (*p->xml != '/'))
126 {
127 i++;
128 p->xml++;
129 if (p->xml >= p->xmlend)
130 return;
131 /* to ignore namespace : */
132 if (*p->xml == ':')
133 {
134 i = 0;
135 elementname = ++p->xml;
136 }
137 }
138 if (i > 0)
139 {
140 if (p->starteltfunc)
141 p->starteltfunc (p->data, elementname, i);
142 if (parseatt (p))
143 return;
144 if (*p->xml != '/')
145 {
146 const char *data;
147 i = 0;
148 data = ++p->xml;
149 if (p->xml >= p->xmlend)
150 return;
151 while (IS_WHITE_SPACE (*p->xml))
152 {
153 p->xml++;
154 if (p->xml >= p->xmlend)
155 return;
156 }
157 while (*p->xml != '<')
158 {
159 i++;
160 p->xml++;
161 if (p->xml >= p->xmlend)
162 return;
163 }
164 if (i > 0 && p->datafunc)
165 p->datafunc (p->data, data, i);
166 }
167 }
168 else if (*p->xml == '/')
169 {
170 i = 0;
171 elementname = ++p->xml;
172 if (p->xml >= p->xmlend)
173 return;
174 while ((*p->xml != '>'))
175 {
176 i++;
177 p->xml++;
178 if (p->xml >= p->xmlend)
179 return;
180 }
181 if (p->endeltfunc)
182 p->endeltfunc (p->data, elementname, i);
183 p->xml++;
184 }
185 }
186 else
187 {
188 p->xml++;
189 }
190 }
191}
192
193/* the parser must be initialized before calling this function */
194void
195parsexml (struct xmlparser *parser)
196{
197 parser->xml = parser->xmlstart;
198 parser->xmlend = parser->xmlstart + parser->xmlsize;
199 parseelt (parser);
200}
diff --git a/src/nat/miniupnp/minixml.h b/src/nat/miniupnp/minixml.h
deleted file mode 100644
index 6ffb987ac..000000000
--- a/src/nat/miniupnp/minixml.h
+++ /dev/null
@@ -1,37 +0,0 @@
1/* $Id: minixml.h,v 1.6 2006/11/30 11:47:21 nanard Exp $ */
2/* minimal xml parser
3 *
4 * Project : miniupnp
5 * Website : http://miniupnp.free.fr/
6 * Author : Thomas Bernard
7 * Copyright (c) 2005 Thomas Bernard
8 * This software is subject to the conditions detailed in the
9 * LICENCE file provided in this distribution.
10 * */
11#ifndef __MINIXML_H__
12#define __MINIXML_H__
13#define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n'))
14
15/* if a callback function pointer is set to NULL,
16 * the function is not called */
17struct xmlparser
18{
19 const char *xmlstart;
20 const char *xmlend;
21 const char *xml; /* pointer to current character */
22 int xmlsize;
23 void *data;
24 void (*starteltfunc) (void *, const char *, int);
25 void (*endeltfunc) (void *, const char *, int);
26 void (*datafunc) (void *, const char *, int);
27 void (*attfunc) (void *, const char *, int, const char *, int);
28};
29
30/* parsexml()
31 * the xmlparser structure must be initialized before the call
32 * the following structure members have to be initialized :
33 * xmlstart, xmlsize, data, *func
34 * xml is for internal usage, xmlend is computed automatically */
35void parsexml (struct xmlparser *);
36
37#endif
diff --git a/src/nat/miniupnp/upnpcommands.c b/src/nat/miniupnp/upnpcommands.c
deleted file mode 100644
index 8b59bc7cc..000000000
--- a/src/nat/miniupnp/upnpcommands.c
+++ /dev/null
@@ -1,605 +0,0 @@
1/* $Id: upnpcommands.c,v 1.24 2009/04/17 21:21:19 nanard Exp $ */
2/* Project : miniupnp
3 * Author : Thomas Bernard
4 * Copyright (c) 2005-2009 Thomas Bernard
5 * This software is subject to the conditions detailed in the
6 * LICENCE file provided in this distribution.
7 * */
8#include <stdlib.h>
9#include <stdio.h>
10#include <string.h>
11#include "upnpcommands.h"
12#include "miniupnpc.h"
13
14static UNSIGNED_INTEGER
15my_atoui (const char *s)
16{
17 return s ? ((UNSIGNED_INTEGER) STRTOUI (s, NULL, 0)) : 0;
18}
19
20/*
21 * */
22UNSIGNED_INTEGER
23UPNP_GetTotalBytesSent (const char *controlURL, const char *servicetype)
24{
25 struct NameValueParserData pdata;
26 char buffer[4096];
27 int bufsize = 4096;
28 unsigned int r = 0;
29 char *p;
30 simpleUPnPcommand (-1, controlURL, servicetype, "GetTotalBytesSent", 0,
31 buffer, &bufsize);
32 ParseNameValue (buffer, bufsize, &pdata);
33 /*DisplayNameValueList(buffer, bufsize); */
34 p = GetValueFromNameValueList (&pdata, "NewTotalBytesSent");
35 r = my_atoui (p);
36 ClearNameValueList (&pdata);
37 return r;
38}
39
40/*
41 * */
42UNSIGNED_INTEGER
43UPNP_GetTotalBytesReceived (const char *controlURL, const char *servicetype)
44{
45 struct NameValueParserData pdata;
46 char buffer[4096];
47 int bufsize = 4096;
48 unsigned int r = 0;
49 char *p;
50 simpleUPnPcommand (-1, controlURL, servicetype, "GetTotalBytesReceived", 0,
51 buffer, &bufsize);
52 ParseNameValue (buffer, bufsize, &pdata);
53 /*DisplayNameValueList(buffer, bufsize); */
54 p = GetValueFromNameValueList (&pdata, "NewTotalBytesReceived");
55 r = my_atoui (p);
56 ClearNameValueList (&pdata);
57 return r;
58}
59
60/*
61 * */
62UNSIGNED_INTEGER
63UPNP_GetTotalPacketsSent (const char *controlURL, const char *servicetype)
64{
65 struct NameValueParserData pdata;
66 char buffer[4096];
67 int bufsize = 4096;
68 unsigned int r = 0;
69 char *p;
70 simpleUPnPcommand (-1, controlURL, servicetype, "GetTotalPacketsSent", 0,
71 buffer, &bufsize);
72 ParseNameValue (buffer, bufsize, &pdata);
73 /*DisplayNameValueList(buffer, bufsize); */
74 p = GetValueFromNameValueList (&pdata, "NewTotalPacketsSent");
75 r = my_atoui (p);
76 ClearNameValueList (&pdata);
77 return r;
78}
79
80/*
81 * */
82UNSIGNED_INTEGER
83UPNP_GetTotalPacketsReceived (const char *controlURL, const char *servicetype)
84{
85 struct NameValueParserData pdata;
86 char buffer[4096];
87 int bufsize = 4096;
88 unsigned int r = 0;
89 char *p;
90 simpleUPnPcommand (-1, controlURL, servicetype, "GetTotalPacketsReceived",
91 0, buffer, &bufsize);
92 ParseNameValue (buffer, bufsize, &pdata);
93 /*DisplayNameValueList(buffer, bufsize); */
94 p = GetValueFromNameValueList (&pdata, "NewTotalPacketsReceived");
95 r = my_atoui (p);
96 ClearNameValueList (&pdata);
97 return r;
98}
99
100/* UPNP_GetStatusInfo() call the corresponding UPNP method
101 * returns the current status and uptime */
102int
103UPNP_GetStatusInfo (const char *controlURL,
104 const char *servicetype,
105 char *status, unsigned int *uptime, char *lastconnerror)
106{
107 struct NameValueParserData pdata;
108 char buffer[4096];
109 int bufsize = 4096;
110 char *p;
111 char *up;
112 char *err;
113 int ret = UPNPCOMMAND_UNKNOWN_ERROR;
114
115 if (!status && !uptime)
116 return UPNPCOMMAND_INVALID_ARGS;
117
118 simpleUPnPcommand (-1, controlURL, servicetype, "GetStatusInfo", 0, buffer,
119 &bufsize);
120 ParseNameValue (buffer, bufsize, &pdata);
121 /*DisplayNameValueList(buffer, bufsize); */
122 up = GetValueFromNameValueList (&pdata, "NewUptime");
123 p = GetValueFromNameValueList (&pdata, "NewConnectionStatus");
124 err = GetValueFromNameValueList (&pdata, "NewLastConnectionError");
125 if (p && up)
126 ret = UPNPCOMMAND_SUCCESS;
127
128 if (status)
129 {
130 if (p)
131 {
132 strncpy (status, p, 64);
133 status[63] = '\0';
134 }
135 else
136 status[0] = '\0';
137 }
138
139 if (uptime)
140 {
141 if (up)
142 sscanf (up, "%u", uptime);
143 else
144 uptime = 0;
145 }
146
147 if (lastconnerror)
148 {
149 if (err)
150 {
151 strncpy (lastconnerror, err, 64);
152 lastconnerror[63] = '\0';
153 }
154 else
155 lastconnerror[0] = '\0';
156 }
157
158 p = GetValueFromNameValueList (&pdata, "errorCode");
159 if (p)
160 {
161 ret = UPNPCOMMAND_UNKNOWN_ERROR;
162 sscanf (p, "%d", &ret);
163 }
164 ClearNameValueList (&pdata);
165 return ret;
166}
167
168/* UPNP_GetConnectionTypeInfo() call the corresponding UPNP method
169 * returns the connection type */
170int
171UPNP_GetConnectionTypeInfo (const char *controlURL,
172 const char *servicetype, char *connectionType)
173{
174 struct NameValueParserData pdata;
175 char buffer[4096];
176 int bufsize = 4096;
177 char *p;
178 int ret = UPNPCOMMAND_UNKNOWN_ERROR;
179
180 if (!connectionType)
181 return UPNPCOMMAND_INVALID_ARGS;
182
183 simpleUPnPcommand (-1, controlURL, servicetype,
184 "GetConnectionTypeInfo", 0, buffer, &bufsize);
185 ParseNameValue (buffer, bufsize, &pdata);
186 p = GetValueFromNameValueList (&pdata, "NewConnectionType");
187 /*p = GetValueFromNameValueList(&pdata, "NewPossibleConnectionTypes"); */
188 /* PossibleConnectionTypes will have several values.... */
189 if (p)
190 {
191 strncpy (connectionType, p, 64);
192 connectionType[63] = '\0';
193 ret = UPNPCOMMAND_SUCCESS;
194 }
195 else
196 connectionType[0] = '\0';
197 p = GetValueFromNameValueList (&pdata, "errorCode");
198 if (p)
199 {
200 ret = UPNPCOMMAND_UNKNOWN_ERROR;
201 sscanf (p, "%d", &ret);
202 }
203 ClearNameValueList (&pdata);
204 return ret;
205}
206
207/* UPNP_GetLinkLayerMaxBitRate() call the corresponding UPNP method.
208 * Returns 2 values: Downloadlink bandwidth and Uplink bandwidth.
209 * One of the values can be null
210 * Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only
211 * We can use the GetCommonLinkProperties from WANCommonInterfaceConfig:1 */
212int
213UPNP_GetLinkLayerMaxBitRates (const char *controlURL, const char *servicetype,
214 unsigned int *bitrateDown,
215 unsigned int *bitrateUp)
216{
217 struct NameValueParserData pdata;
218 char buffer[4096];
219 int bufsize = 4096;
220 int ret = UPNPCOMMAND_UNKNOWN_ERROR;
221 char *down;
222 char *up;
223 char *p;
224
225 if (!bitrateDown && !bitrateUp)
226 return UPNPCOMMAND_INVALID_ARGS;
227
228 /* shouldn't we use GetCommonLinkProperties ? */
229 simpleUPnPcommand (-1, controlURL, servicetype,
230 "GetCommonLinkProperties", 0, buffer, &bufsize);
231 /*"GetLinkLayerMaxBitRates", 0, buffer, &bufsize); */
232 /*DisplayNameValueList(buffer, bufsize); */
233 ParseNameValue (buffer, bufsize, &pdata);
234 /*down = GetValueFromNameValueList(&pdata, "NewDownstreamMaxBitRate"); */
235 /*up = GetValueFromNameValueList(&pdata, "NewUpstreamMaxBitRate"); */
236 down = GetValueFromNameValueList (&pdata, "NewLayer1DownstreamMaxBitRate");
237 up = GetValueFromNameValueList (&pdata, "NewLayer1UpstreamMaxBitRate");
238 /*GetValueFromNameValueList(&pdata, "NewWANAccessType"); */
239 /*GetValueFromNameValueList(&pdata, "NewPhysicalLinkSatus"); */
240 if (down && up)
241 ret = UPNPCOMMAND_SUCCESS;
242
243 if (bitrateDown)
244 {
245 if (down)
246 sscanf (down, "%u", bitrateDown);
247 else
248 *bitrateDown = 0;
249 }
250
251 if (bitrateUp)
252 {
253 if (up)
254 sscanf (up, "%u", bitrateUp);
255 else
256 *bitrateUp = 0;
257 }
258 p = GetValueFromNameValueList (&pdata, "errorCode");
259 if (p)
260 {
261 ret = UPNPCOMMAND_UNKNOWN_ERROR;
262 sscanf (p, "%d", &ret);
263 }
264 ClearNameValueList (&pdata);
265 return ret;
266}
267
268
269/* UPNP_GetExternalIPAddress() call the corresponding UPNP method.
270 * if the third arg is not null the value is copied to it.
271 * at least 128 bytes must be available
272 *
273 * Return values :
274 * 0 : SUCCESS
275 * NON ZERO : ERROR Either an UPnP error code or an unknown error.
276 *
277 * 402 Invalid Args - See UPnP Device Architecture section on Control.
278 * 501 Action Failed - See UPnP Device Architecture section on Control.
279 */
280int
281UPNP_GetExternalIPAddress (const char *controlURL,
282 const char *servicetype, char *extIpAdd)
283{
284 struct NameValueParserData pdata;
285 char buffer[4096];
286 int bufsize = 4096;
287 char *p;
288 int ret = UPNPCOMMAND_UNKNOWN_ERROR;
289
290 if (!extIpAdd || !controlURL || !servicetype)
291 return UPNPCOMMAND_INVALID_ARGS;
292
293 simpleUPnPcommand (-1, controlURL, servicetype, "GetExternalIPAddress", 0,
294 buffer, &bufsize);
295 /*DisplayNameValueList(buffer, bufsize); */
296 ParseNameValue (buffer, bufsize, &pdata);
297 /*printf("external ip = %s\n", GetValueFromNameValueList(&pdata, "NewExternalIPAddress") ); */
298 p = GetValueFromNameValueList (&pdata, "NewExternalIPAddress");
299 if (p)
300 {
301 strncpy (extIpAdd, p, 128);
302 extIpAdd[127] = '\0';
303 ret = UPNPCOMMAND_SUCCESS;
304 }
305 else
306 extIpAdd[0] = '\0';
307
308 p = GetValueFromNameValueList (&pdata, "errorCode");
309 if (p)
310 {
311 ret = UPNPCOMMAND_UNKNOWN_ERROR;
312 sscanf (p, "%d", &ret);
313 }
314
315 ClearNameValueList (&pdata);
316 return ret;
317}
318
319int
320UPNP_AddPortMapping (const char *controlURL, const char *servicetype,
321 const char *extPort,
322 const char *inPort,
323 const char *inClient,
324 const char *desc,
325 const char *proto, const char *remoteHost)
326{
327 struct UPNParg *AddPortMappingArgs;
328 char buffer[4096];
329 int bufsize = 4096;
330 struct NameValueParserData pdata;
331 const char *resVal;
332 int ret;
333
334 if (!inPort || !inClient || !proto || !extPort)
335 return UPNPCOMMAND_INVALID_ARGS;
336
337 AddPortMappingArgs = calloc (9, sizeof (struct UPNParg));
338 AddPortMappingArgs[0].elt = "NewRemoteHost";
339 AddPortMappingArgs[0].val = remoteHost;
340 AddPortMappingArgs[1].elt = "NewExternalPort";
341 AddPortMappingArgs[1].val = extPort;
342 AddPortMappingArgs[2].elt = "NewProtocol";
343 AddPortMappingArgs[2].val = proto;
344 AddPortMappingArgs[3].elt = "NewInternalPort";
345 AddPortMappingArgs[3].val = inPort;
346 AddPortMappingArgs[4].elt = "NewInternalClient";
347 AddPortMappingArgs[4].val = inClient;
348 AddPortMappingArgs[5].elt = "NewEnabled";
349 AddPortMappingArgs[5].val = "1";
350 AddPortMappingArgs[6].elt = "NewPortMappingDescription";
351 AddPortMappingArgs[6].val = desc ? desc : "libminiupnpc";
352 AddPortMappingArgs[7].elt = "NewLeaseDuration";
353 AddPortMappingArgs[7].val = "0";
354 simpleUPnPcommand (-1, controlURL, servicetype, "AddPortMapping",
355 AddPortMappingArgs, buffer, &bufsize);
356 /*DisplayNameValueList(buffer, bufsize); */
357 /*buffer[bufsize] = '\0'; */
358 /*puts(buffer); */
359 ParseNameValue (buffer, bufsize, &pdata);
360 resVal = GetValueFromNameValueList (&pdata, "errorCode");
361 if (resVal)
362 {
363 /* printf("AddPortMapping errorCode = '%s'\n", resVal); */
364 ret = UPNPCOMMAND_UNKNOWN_ERROR;
365 sscanf (resVal, "%d", &ret);
366 }
367 else
368 {
369 ret = UPNPCOMMAND_SUCCESS;
370 }
371 ClearNameValueList (&pdata);
372 free (AddPortMappingArgs);
373 return ret;
374}
375
376int
377UPNP_DeletePortMapping (const char *controlURL, const char *servicetype,
378 const char *extPort, const char *proto,
379 const char *remoteHost)
380{
381 /*struct NameValueParserData pdata; */
382 struct UPNParg *DeletePortMappingArgs;
383 char buffer[4096];
384 int bufsize = 4096;
385 struct NameValueParserData pdata;
386 const char *resVal;
387 int ret;
388
389 if (!extPort || !proto)
390 return UPNPCOMMAND_INVALID_ARGS;
391
392 DeletePortMappingArgs = calloc (4, sizeof (struct UPNParg));
393 DeletePortMappingArgs[0].elt = "NewRemoteHost";
394 DeletePortMappingArgs[0].val = remoteHost;
395 DeletePortMappingArgs[1].elt = "NewExternalPort";
396 DeletePortMappingArgs[1].val = extPort;
397 DeletePortMappingArgs[2].elt = "NewProtocol";
398 DeletePortMappingArgs[2].val = proto;
399 simpleUPnPcommand (-1, controlURL, servicetype,
400 "DeletePortMapping",
401 DeletePortMappingArgs, buffer, &bufsize);
402 /*DisplayNameValueList(buffer, bufsize); */
403 ParseNameValue (buffer, bufsize, &pdata);
404 resVal = GetValueFromNameValueList (&pdata, "errorCode");
405 if (resVal)
406 {
407 ret = UPNPCOMMAND_UNKNOWN_ERROR;
408 sscanf (resVal, "%d", &ret);
409 }
410 else
411 {
412 ret = UPNPCOMMAND_SUCCESS;
413 }
414 ClearNameValueList (&pdata);
415 free (DeletePortMappingArgs);
416 return ret;
417}
418
419int
420UPNP_GetGenericPortMappingEntry (const char *controlURL,
421 const char *servicetype,
422 const char *index,
423 char *extPort,
424 char *intClient,
425 char *intPort,
426 char *protocol,
427 char *desc,
428 char *enabled, char *rHost, char *duration)
429{
430 struct NameValueParserData pdata;
431 struct UPNParg *GetPortMappingArgs;
432 char buffer[4096];
433 int bufsize = 4096;
434 char *p;
435 int r = UPNPCOMMAND_UNKNOWN_ERROR;
436 if (!index)
437 return UPNPCOMMAND_INVALID_ARGS;
438
439 GetPortMappingArgs = calloc (2, sizeof (struct UPNParg));
440 GetPortMappingArgs[0].elt = "NewPortMappingIndex";
441 GetPortMappingArgs[0].val = index;
442 simpleUPnPcommand (-1, controlURL, servicetype,
443 "GetGenericPortMappingEntry",
444 GetPortMappingArgs, buffer, &bufsize);
445 ParseNameValue (buffer, bufsize, &pdata);
446 p = GetValueFromNameValueList (&pdata, "NewRemoteHost");
447 if (p && rHost)
448 {
449 strncpy (rHost, p, 64);
450 rHost[63] = '\0';
451 }
452 p = GetValueFromNameValueList (&pdata, "NewExternalPort");
453 if (p && extPort)
454 {
455 strncpy (extPort, p, 6);
456 extPort[5] = '\0';
457 r = UPNPCOMMAND_SUCCESS;
458 }
459 p = GetValueFromNameValueList (&pdata, "NewProtocol");
460 if (p && protocol)
461 {
462 strncpy (protocol, p, 4);
463 protocol[3] = '\0';
464 }
465 p = GetValueFromNameValueList (&pdata, "NewInternalClient");
466 if (p && intClient)
467 {
468 strncpy (intClient, p, 128);
469 intClient[127] = '\0';
470 r = 0;
471 }
472 p = GetValueFromNameValueList (&pdata, "NewInternalPort");
473 if (p && intPort)
474 {
475 strncpy (intPort, p, 6);
476 intPort[5] = '\0';
477 }
478 p = GetValueFromNameValueList (&pdata, "NewEnabled");
479 if (p && enabled)
480 {
481 strncpy (enabled, p, 4);
482 enabled[3] = '\0';
483 }
484 p = GetValueFromNameValueList (&pdata, "NewPortMappingDescription");
485 if (p && desc)
486 {
487 strncpy (desc, p, 80);
488 desc[79] = '\0';
489 }
490 p = GetValueFromNameValueList (&pdata, "NewLeaseDuration");
491 if (p && duration)
492 {
493 strncpy (duration, p, 16);
494 duration[15] = '\0';
495 }
496 p = GetValueFromNameValueList (&pdata, "errorCode");
497 if (p)
498 {
499 r = UPNPCOMMAND_UNKNOWN_ERROR;
500 sscanf (p, "%d", &r);
501 }
502 ClearNameValueList (&pdata);
503 free (GetPortMappingArgs);
504 return r;
505}
506
507int
508UPNP_GetPortMappingNumberOfEntries (const char *controlURL,
509 const char *servicetype,
510 unsigned int *numEntries)
511{
512 struct NameValueParserData pdata;
513 char buffer[4096];
514 int bufsize = 4096;
515 char *p;
516 int ret = UPNPCOMMAND_UNKNOWN_ERROR;
517 simpleUPnPcommand (-1, controlURL, servicetype,
518 "GetPortMappingNumberOfEntries", 0, buffer, &bufsize);
519#ifdef DEBUG
520 DisplayNameValueList (buffer, bufsize);
521#endif
522 ParseNameValue (buffer, bufsize, &pdata);
523
524 p = GetValueFromNameValueList (&pdata, "NewPortMappingNumberOfEntries");
525 if (numEntries && p)
526 {
527 *numEntries = 0;
528 sscanf (p, "%u", numEntries);
529 ret = UPNPCOMMAND_SUCCESS;
530 }
531
532 p = GetValueFromNameValueList (&pdata, "errorCode");
533 if (p)
534 {
535 ret = UPNPCOMMAND_UNKNOWN_ERROR;
536 sscanf (p, "%d", &ret);
537 }
538
539 ClearNameValueList (&pdata);
540 return ret;
541}
542
543/* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping
544 * the result is returned in the intClient and intPort strings
545 * please provide 128 and 6 bytes of data */
546int
547UPNP_GetSpecificPortMappingEntry (const char *controlURL,
548 const char *servicetype,
549 const char *extPort,
550 const char *proto,
551 char *intClient, char *intPort)
552{
553 struct NameValueParserData pdata;
554 struct UPNParg *GetPortMappingArgs;
555 char buffer[4096];
556 int bufsize = 4096;
557 char *p;
558 int ret = UPNPCOMMAND_UNKNOWN_ERROR;
559
560 if (!intPort || !intClient || !extPort || !proto)
561 return UPNPCOMMAND_INVALID_ARGS;
562
563 GetPortMappingArgs = calloc (4, sizeof (struct UPNParg));
564 GetPortMappingArgs[0].elt = "NewRemoteHost";
565 GetPortMappingArgs[1].elt = "NewExternalPort";
566 GetPortMappingArgs[1].val = extPort;
567 GetPortMappingArgs[2].elt = "NewProtocol";
568 GetPortMappingArgs[2].val = proto;
569 simpleUPnPcommand (-1, controlURL, servicetype,
570 "GetSpecificPortMappingEntry",
571 GetPortMappingArgs, buffer, &bufsize);
572 /*fd = simpleUPnPcommand(fd, controlURL, data.servicetype, "GetSpecificPortMappingEntry", AddPortMappingArgs, buffer, &bufsize); */
573 /*DisplayNameValueList(buffer, bufsize); */
574 ParseNameValue (buffer, bufsize, &pdata);
575
576 p = GetValueFromNameValueList (&pdata, "NewInternalClient");
577 if (p)
578 {
579 strncpy (intClient, p, 128);
580 intClient[127] = '\0';
581 ret = UPNPCOMMAND_SUCCESS;
582 }
583 else
584 intClient[0] = '\0';
585
586 p = GetValueFromNameValueList (&pdata, "NewInternalPort");
587 if (p)
588 {
589 strncpy (intPort, p, 6);
590 intPort[5] = '\0';
591 }
592 else
593 intPort[0] = '\0';
594
595 p = GetValueFromNameValueList (&pdata, "errorCode");
596 if (p)
597 {
598 ret = UPNPCOMMAND_UNKNOWN_ERROR;
599 sscanf (p, "%d", &ret);
600 }
601
602 ClearNameValueList (&pdata);
603 free (GetPortMappingArgs);
604 return ret;
605}
diff --git a/src/nat/miniupnp/upnpcommands.h b/src/nat/miniupnp/upnpcommands.h
deleted file mode 100644
index fa1d604ae..000000000
--- a/src/nat/miniupnp/upnpcommands.h
+++ /dev/null
@@ -1,189 +0,0 @@
1/* $Id: upnpcommands.h,v 1.17 2009/04/17 21:21:19 nanard Exp $ */
2/* Miniupnp project : http://miniupnp.free.fr/
3 * Author : Thomas Bernard
4 * Copyright (c) 2005-2008 Thomas Bernard
5 * This software is subject to the conditions detailed in the
6 * LICENCE file provided within this distribution */
7#ifndef __UPNPCOMMANDS_H__
8#define __UPNPCOMMANDS_H__
9
10#include "upnpreplyparse.h"
11#include "declspec.h"
12
13/* MiniUPnPc return codes : */
14#define UPNPCOMMAND_SUCCESS (0)
15#define UPNPCOMMAND_UNKNOWN_ERROR (-1)
16#define UPNPCOMMAND_INVALID_ARGS (-2)
17
18#ifdef __cplusplus
19extern "C"
20{
21#endif
22
23#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
24#define UNSIGNED_INTEGER unsigned long long
25#define STRTOUI strtoull
26#else
27#define UNSIGNED_INTEGER unsigned int
28#define STRTOUI strtoul
29#endif
30
31 LIBSPEC UNSIGNED_INTEGER
32 UPNP_GetTotalBytesSent (const char *controlURL, const char *servicetype);
33
34 LIBSPEC UNSIGNED_INTEGER
35 UPNP_GetTotalBytesReceived (const char *controlURL,
36 const char *servicetype);
37
38 LIBSPEC UNSIGNED_INTEGER
39 UPNP_GetTotalPacketsSent (const char *controlURL,
40 const char *servicetype);
41
42 LIBSPEC UNSIGNED_INTEGER
43 UPNP_GetTotalPacketsReceived (const char *controlURL,
44 const char *servicetype);
45
46/* UPNP_GetStatusInfo()
47 * status and lastconnerror are 64 byte buffers
48 * Return values :
49 * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
50 * or a UPnP Error code */
51 LIBSPEC int
52 UPNP_GetStatusInfo (const char *controlURL,
53 const char *servicetype,
54 char *status,
55 unsigned int *uptime, char *lastconnerror);
56
57/* UPNP_GetConnectionTypeInfo()
58 * argument connectionType is a 64 character buffer
59 * Return Values :
60 * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
61 * or a UPnP Error code */
62 LIBSPEC int
63 UPNP_GetConnectionTypeInfo (const char *controlURL,
64 const char *servicetype,
65 char *connectionType);
66
67/* UPNP_GetExternalIPAddress() call the corresponding UPNP method.
68 * if the third arg is not null the value is copied to it.
69 * at least 128 bytes must be available
70 *
71 * Return values :
72 * 0 : SUCCESS
73 * NON ZERO : ERROR Either an UPnP error code or an unknown error.
74 *
75 * possible UPnP Errors :
76 * 402 Invalid Args - See UPnP Device Architecture section on Control.
77 * 501 Action Failed - See UPnP Device Architecture section on Control. */
78 LIBSPEC int
79 UPNP_GetExternalIPAddress (const char *controlURL,
80 const char *servicetype, char *extIpAdd);
81
82/* UPNP_GetLinkLayerMaxBitRates()
83 * call WANCommonInterfaceConfig:1#GetCommonLinkProperties
84 *
85 * return values :
86 * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
87 * or a UPnP Error Code. */
88 LIBSPEC int
89 UPNP_GetLinkLayerMaxBitRates (const char *controlURL,
90 const char *servicetype,
91 unsigned int *bitrateDown,
92 unsigned int *bitrateUp);
93
94/* UPNP_AddPortMapping()
95 * if desc is NULL, it will be defaulted to "libminiupnpc"
96 * remoteHost is usually NULL because IGD don't support it.
97 *
98 * Return values :
99 * 0 : SUCCESS
100 * NON ZERO : ERROR. Either an UPnP error code or an unknown error.
101 *
102 * List of possible UPnP errors for AddPortMapping :
103 * errorCode errorDescription (short) - Description (long)
104 * 402 Invalid Args - See UPnP Device Architecture section on Control.
105 * 501 Action Failed - See UPnP Device Architecture section on Control.
106 * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be
107 * wild-carded
108 * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded
109 * 718 ConflictInMappingEntry - The port mapping entry specified conflicts
110 * with a mapping assigned previously to another client
111 * 724 SamePortValuesRequired - Internal and External port values
112 * must be the same
113 * 725 OnlyPermanentLeasesSupported - The NAT implementation only supports
114 * permanent lease times on port mappings
115 * 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard
116 * and cannot be a specific IP address or DNS name
117 * 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and
118 * cannot be a specific port value */
119 LIBSPEC int
120 UPNP_AddPortMapping (const char *controlURL, const char *servicetype,
121 const char *extPort,
122 const char *inPort,
123 const char *inClient,
124 const char *desc,
125 const char *proto, const char *remoteHost);
126
127/* UPNP_DeletePortMapping()
128 * Use same argument values as what was used for AddPortMapping().
129 * remoteHost is usually NULL because IGD don't support it.
130 * Return Values :
131 * 0 : SUCCESS
132 * NON ZERO : error. Either an UPnP error code or an undefined error.
133 *
134 * List of possible UPnP errors for DeletePortMapping :
135 * 402 Invalid Args - See UPnP Device Architecture section on Control.
136 * 714 NoSuchEntryInArray - The specified value does not exist in the array */
137 LIBSPEC int
138 UPNP_DeletePortMapping (const char *controlURL, const char *servicetype,
139 const char *extPort, const char *proto,
140 const char *remoteHost);
141
142/* UPNP_GetPortMappingNumberOfEntries()
143 * not supported by all routers */
144 LIBSPEC int
145 UPNP_GetPortMappingNumberOfEntries (const char *controlURL,
146 const char *servicetype,
147 unsigned int *num);
148
149/* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping
150 * the result is returned in the intClient and intPort strings
151 * please provide 128 and 6 bytes of data
152 *
153 * return value :
154 * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
155 * or a UPnP Error Code. */
156 LIBSPEC int
157 UPNP_GetSpecificPortMappingEntry (const char *controlURL,
158 const char *servicetype,
159 const char *extPort,
160 const char *proto,
161 char *intClient, char *intPort);
162
163/* UPNP_GetGenericPortMappingEntry()
164 *
165 * return value :
166 * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
167 * or a UPnP Error Code.
168 *
169 * Possible UPNP Error codes :
170 * 402 Invalid Args - See UPnP Device Architecture section on Control.
171 * 713 SpecifiedArrayIndexInvalid - The specified array index is out of bounds
172 */
173 LIBSPEC int
174 UPNP_GetGenericPortMappingEntry (const char *controlURL,
175 const char *servicetype,
176 const char *index,
177 char *extPort,
178 char *intClient,
179 char *intPort,
180 char *protocol,
181 char *desc,
182 char *enabled,
183 char *rHost, char *duration);
184
185#ifdef __cplusplus
186}
187#endif
188
189#endif
diff --git a/src/nat/miniupnp/upnpreplyparse.c b/src/nat/miniupnp/upnpreplyparse.c
deleted file mode 100644
index 9aa895d1d..000000000
--- a/src/nat/miniupnp/upnpreplyparse.c
+++ /dev/null
@@ -1,122 +0,0 @@
1/* $Id: upnpreplyparse.c,v 1.10 2008/02/21 13:05:27 nanard Exp $ */
2/* MiniUPnP project
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006 Thomas Bernard
5 * This software is subject to the conditions detailed
6 * in the LICENCE file provided within the distribution */
7
8#include <stdlib.h>
9#include <string.h>
10#include <stdio.h>
11
12#include "upnpreplyparse.h"
13#include "minixml.h"
14
15static void
16NameValueParserStartElt (void *d, const char *name, int l)
17{
18 struct NameValueParserData *data = (struct NameValueParserData *) d;
19 if (l > 63)
20 l = 63;
21 memcpy (data->curelt, name, l);
22 data->curelt[l] = '\0';
23}
24
25static void
26NameValueParserGetData (void *d, const char *datas, int l)
27{
28 struct NameValueParserData *data = (struct NameValueParserData *) d;
29 struct NameValue *nv;
30 nv = malloc (sizeof (struct NameValue));
31 if (l > 63)
32 l = 63;
33 strncpy (nv->name, data->curelt, 64);
34 nv->name[63] = '\0';
35 memcpy (nv->value, datas, l);
36 nv->value[l] = '\0';
37 LIST_INSERT_HEAD (&(data->head), nv, entries);
38}
39
40void
41ParseNameValue (const char *buffer, int bufsize,
42 struct NameValueParserData *data)
43{
44 struct xmlparser parser;
45 LIST_INIT (&(data->head));
46 /* init xmlparser object */
47 parser.xmlstart = buffer;
48 parser.xmlsize = bufsize;
49 parser.data = data;
50 parser.starteltfunc = NameValueParserStartElt;
51 parser.endeltfunc = 0;
52 parser.datafunc = NameValueParserGetData;
53 parser.attfunc = 0;
54 parsexml (&parser);
55}
56
57void
58ClearNameValueList (struct NameValueParserData *pdata)
59{
60 struct NameValue *nv;
61 while ((nv = pdata->head.lh_first) != NULL)
62 {
63 LIST_REMOVE (nv, entries);
64 free (nv);
65 }
66}
67
68char *
69GetValueFromNameValueList (struct NameValueParserData *pdata,
70 const char *Name)
71{
72 struct NameValue *nv;
73 char *p = NULL;
74 for (nv = pdata->head.lh_first;
75 (nv != NULL) && (p == NULL); nv = nv->entries.le_next)
76 {
77 if (strcmp (nv->name, Name) == 0)
78 p = nv->value;
79 }
80 return p;
81}
82
83#if 0
84/* useless now that minixml ignores namespaces by itself */
85char *
86GetValueFromNameValueListIgnoreNS (struct NameValueParserData *pdata,
87 const char *Name)
88{
89 struct NameValue *nv;
90 char *p = NULL;
91 char *pname;
92 for (nv = pdata->head.lh_first;
93 (nv != NULL) && (p == NULL); nv = nv->entries.le_next)
94 {
95 pname = strrchr (nv->name, ':');
96 if (pname)
97 pname++;
98 else
99 pname = nv->name;
100 if (strcmp (pname, Name) == 0)
101 p = nv->value;
102 }
103 return p;
104}
105#endif
106
107/* debug all-in-one function
108 * do parsing then display to stdout */
109#ifdef DEBUG
110void
111DisplayNameValueList (char *buffer, int bufsize)
112{
113 struct NameValueParserData pdata;
114 struct NameValue *nv;
115 ParseNameValue (buffer, bufsize, &pdata);
116 for (nv = pdata.head.lh_first; nv != NULL; nv = nv->entries.le_next)
117 {
118 printf ("%s = %s\n", nv->name, nv->value);
119 }
120 ClearNameValueList (&pdata);
121}
122#endif
diff --git a/src/nat/miniupnp/upnpreplyparse.h b/src/nat/miniupnp/upnpreplyparse.h
deleted file mode 100644
index a1c8a9431..000000000
--- a/src/nat/miniupnp/upnpreplyparse.h
+++ /dev/null
@@ -1,60 +0,0 @@
1/* $Id: upnpreplyparse.h,v 1.8 2008/02/21 13:05:27 nanard Exp $ */
2/* MiniUPnP project
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006 Thomas Bernard
5 * This software is subject to the conditions detailed
6 * in the LICENCE file provided within the distribution */
7
8#ifndef __UPNPREPLYPARSE_H__
9#define __UPNPREPLYPARSE_H__
10
11#if defined(NO_SYS_QUEUE_H) || defined(WIN32)
12#include "bsdqueue.h"
13#else
14#include <sys/queue.h>
15#endif
16
17#ifdef __cplusplus
18extern "C"
19{
20#endif
21
22 struct NameValue
23 {
24 LIST_ENTRY (NameValue) entries;
25 char name[64];
26 char value[64];
27 };
28
29 struct NameValueParserData
30 {
31 LIST_HEAD (listhead, NameValue) head;
32 char curelt[64];
33 };
34
35/* ParseNameValue() */
36 void
37 ParseNameValue (const char *buffer, int bufsize,
38 struct NameValueParserData *data);
39
40/* ClearNameValueList() */
41 void ClearNameValueList (struct NameValueParserData *pdata);
42
43/* GetValueFromNameValueList() */
44 char *GetValueFromNameValueList (struct NameValueParserData *pdata,
45 const char *Name);
46
47/* GetValueFromNameValueListIgnoreNS() */
48 char *GetValueFromNameValueListIgnoreNS (struct NameValueParserData *pdata,
49 const char *Name);
50
51/* DisplayNameValueList() */
52#ifdef DEBUG
53 void DisplayNameValueList (char *buffer, int bufsize);
54#endif
55
56#ifdef __cplusplus
57}
58#endif
59
60#endif
diff --git a/src/nat/nat.c b/src/nat/nat.c
index 1df0da81a..cb031d35d 100644
--- a/src/nat/nat.c
+++ b/src/nat/nat.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors) 3 (C) 2009, 2010 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -31,152 +31,161 @@
31 * 31 *
32 * @author Milan Bouchet-Valat 32 * @author Milan Bouchet-Valat
33 */ 33 */
34#include <errno.h>
35#include <string.h>
36#include <stdio.h>
37
38#include <sys/types.h>
39
40#include "platform.h" 34#include "platform.h"
41#include "gnunet_common.h"
42#include "gnunet_util_lib.h" 35#include "gnunet_util_lib.h"
43#include "gnunet_nat_lib.h" 36#include "gnunet_nat_lib.h"
37#include "nat.h"
44#include "natpmp.h" 38#include "natpmp.h"
45#include "upnp.h" 39#include "upnp.h"
46 40
47/* Component name for logging */ 41/**
48#define COMP_NAT _("NAT") 42 * Handle for active NAT registrations.
49#define DEBUG 43 */
50
51struct GNUNET_NAT_Handle 44struct GNUNET_NAT_Handle
52{ 45{
53 int is_enabled; 46 /**
54 47 * Handle for UPnP operations.
55 enum GNUNET_NAT_port_forwarding natpmp_status; 48 */
56 enum GNUNET_NAT_port_forwarding upnp_status;
57
58 int should_change;
59 u_short public_port;
60
61 GNUNET_NAT_UPNP_Handle *upnp; 49 GNUNET_NAT_UPNP_Handle *upnp;
50
51 /**
52 * Handle for NAT PMP operations.
53 */
62 GNUNET_NAT_NATPMP_Handle *natpmp; 54 GNUNET_NAT_NATPMP_Handle *natpmp;
63 55
56 /**
57 * Scheduler.
58 */
64 struct GNUNET_SCHEDULER_Handle *sched; 59 struct GNUNET_SCHEDULER_Handle *sched;
65 GNUNET_SCHEDULER_TaskIdentifier pulse_timer;
66 60
67 struct sockaddr *local_addr; /* LAN address as passed by the caller */ 61 /**
68 struct sockaddr *ext_addr; /* External address as reported by NAT box */ 62 * LAN address as passed by the caller
69 struct sockaddr *contact_addr; /* External address and port where paquets are redirected*/ 63 */
64 struct sockaddr *local_addr;
65
66 /**
67 * External address as reported by NAT box
68 */
69 struct sockaddr *ext_addr;
70
71 /**
72 * External address and port where packets are redirected
73 */
74 struct sockaddr *contact_addr;
75
70 GNUNET_NAT_AddressCallback callback; 76 GNUNET_NAT_AddressCallback callback;
77
78 /**
79 * Closure for 'callback'.
80 */
71 void *callback_cls; 81 void *callback_cls;
82
83 GNUNET_SCHEDULER_TaskIdentifier pulse_timer;
84
85 enum GNUNET_NAT_PortState natpmp_status;
86
87 enum GNUNET_NAT_PortState upnp_status;
88
89 int is_enabled;
90
91 int should_change;
92
93 int port_mapped;
94
95 int did_warn;
96
97 uint16_t public_port;
98
72}; 99};
73 100
74#ifdef DEBUG 101#ifdef DEBUG
75static const char * 102static const char *
76get_nat_state_str (int state) 103get_nat_state_str (enum GNUNET_NAT_PortState state)
77{ 104{
78 switch (state) 105 switch (state)
79 { 106 {
80 /* we're in the process of trying to set up port forwarding */
81 case GNUNET_NAT_PORT_MAPPING: 107 case GNUNET_NAT_PORT_MAPPING:
82 return "Starting"; 108 return "Starting";
83
84 /* we've successfully forwarded the port */
85 case GNUNET_NAT_PORT_MAPPED: 109 case GNUNET_NAT_PORT_MAPPED:
86 return "Forwarded"; 110 return "Forwarded";
87
88 /* we're cancelling the port forwarding */
89 case GNUNET_NAT_PORT_UNMAPPING: 111 case GNUNET_NAT_PORT_UNMAPPING:
90 return "Stopping"; 112 return "Stopping";
91
92 /* the port isn't forwarded */
93 case GNUNET_NAT_PORT_UNMAPPED: 113 case GNUNET_NAT_PORT_UNMAPPED:
94 return "Not forwarded"; 114 return "Not forwarded";
95
96 case GNUNET_NAT_PORT_ERROR: 115 case GNUNET_NAT_PORT_ERROR:
97 return "Redirection failed"; 116 return "Redirection failed";
117 default:
118 return "not found";
98 } 119 }
99
100 return "notfound";
101} 120}
102#endif 121#endif
103 122
123
104static int 124static int
105get_traversal_status (const struct GNUNET_NAT_Handle * s) 125get_traversal_status (const struct GNUNET_NAT_Handle * s)
106{ 126{
107 return MAX (s->natpmp_status, s->upnp_status); 127 return MAX (s->natpmp_status, s->upnp_status);
108} 128}
109 129
130
110/** 131/**
111 * Compare the sin(6)_addr fields of AF_INET or AF_INET(6) sockaddr. 132 * Compare the sin(6)_addr fields of AF_INET or AF_INET(6) sockaddr.
112 * @param a first sockaddr 133 * @param a first sockaddr
113 * @param b second sockaddr 134 * @param b second sockaddr
114 * @return 0 if addresses are equal, non-null value otherwise */ 135 * @return 0 if addresses are equal, non-null value otherwise */
115int 136int
116GNUNET_NAT_cmp_addr (const struct sockaddr *a, const struct sockaddr *b) 137GNUNET_NAT_cmp_addr (const struct sockaddr *a,
138 const struct sockaddr *b)
117{ 139{
118 if (!(a && b)) 140 if (!(a && b))
119 return -1; 141 return -1;
120 142 if ( (a->sa_family == AF_INET) && (b->sa_family == AF_INET) )
121 if (a->sa_family == AF_INET && b->sa_family == AF_INET)
122 return memcmp (&(((struct sockaddr_in *) a)->sin_addr), 143 return memcmp (&(((struct sockaddr_in *) a)->sin_addr),
123 &(((struct sockaddr_in *) b)->sin_addr), 144 &(((struct sockaddr_in *) b)->sin_addr),
124 sizeof (struct in_addr)); 145 sizeof (struct in_addr));
125 else if (a->sa_family == AF_INET6 && b->sa_family == AF_INET6) 146 if ( (a->sa_family == AF_INET6) && (b->sa_family == AF_INET6) )
126 return memcmp (&(((struct sockaddr_in6 *) a)->sin6_addr), 147 return memcmp (&(((struct sockaddr_in6 *) a)->sin6_addr),
127 &(((struct sockaddr_in6 *) b)->sin6_addr), 148 &(((struct sockaddr_in6 *) b)->sin6_addr),
128 sizeof (struct in6_addr)); 149 sizeof (struct in6_addr));
129 else 150 return -1;
130 return -1;
131} 151}
132 152
133/* Deal with a new IP address or port redirection: 153
154/**
155 * Deal with a new IP address or port redirection:
134 * Send signals with the appropriate sockaddr (IP and port), free and changes 156 * Send signals with the appropriate sockaddr (IP and port), free and changes
135 * or nullify the previous sockaddr. Change the port if needed. 157 * or nullify the previous sockaddr. Change the port if needed.
136 */ 158 */
137static void 159static void
138notify_change (struct GNUNET_NAT_Handle *nat, struct sockaddr *addr, int new_port_mapped) 160notify_change (struct GNUNET_NAT_Handle *nat,
161 struct sockaddr *addr,
162 size_t addrlen,
163 int new_port_mapped)
139{ 164{
140 static int port_mapped = GNUNET_NO; 165 if (new_port_mapped == nat->port_mapped)
141
142 /* Nothing to do. We already check in nat_pulse() that addr has changed */
143 if (new_port_mapped == port_mapped)
144 return; 166 return;
145 167 nat->port_mapped = new_port_mapped;
146 port_mapped = new_port_mapped; 168
147 169 if ( (NULL != nat->contact_addr) &&
148 if (nat->contact_addr && nat->callback) 170 (NULL != nat->callback) )
149 (*nat->callback) (nat->callback_cls, GNUNET_NO, (struct sockaddr *) &nat->contact_addr, 171 nat->callback (nat->callback_cls,
150 sizeof (nat->contact_addr)); 172 GNUNET_NO,
151 173 nat->contact_addr,
152 /* At this point, we're sure contact_addr has changed */ 174 sizeof (nat->contact_addr));
153 if (nat->contact_addr) 175 GNUNET_free_non_null (nat->contact_addr);
154 { 176 nat->contact_addr = NULL;
155 GNUNET_free (nat->contact_addr); 177 GNUNET_free_non_null (nat->ext_addr);
156 nat->contact_addr = NULL; 178 nat->ext_addr = NULL;
157 } 179 if (NULL == addr)
158 180 return;
159 /* No address, don't signal a new one */ 181 nat->ext_addr = GNUNET_malloc (addrlen);
160 if (!addr) 182 memcpy (nat->ext_addr, addr, addrlen);
161 {
162 if (nat->ext_addr)
163 GNUNET_free (nat->ext_addr);
164 nat->ext_addr = NULL;
165 return;
166 }
167 /* Copy the new address and use it */
168 else if (addr != nat->ext_addr)
169 {
170 if (nat->ext_addr)
171 GNUNET_free (nat->ext_addr);
172 nat->ext_addr = GNUNET_malloc (sizeof (*addr));
173 memcpy (nat->ext_addr, addr, sizeof (*addr));
174 }
175 183
176 /* Recreate the ext_addr:public_port bogus address to pass to the callback */ 184 /* Recreate the ext_addr:public_port bogus address to pass to the callback */
177 if (nat->ext_addr->sa_family == AF_INET) 185 if (nat->ext_addr->sa_family == AF_INET)
178 { 186 {
179 struct sockaddr_in *tmp_addr; 187 struct sockaddr_in tmp_addr;
188
180 tmp_addr = GNUNET_malloc (sizeof (struct sockaddr_in)); 189 tmp_addr = GNUNET_malloc (sizeof (struct sockaddr_in));
181 tmp_addr->sin_family = AF_INET; 190 tmp_addr->sin_family = AF_INET;
182#ifdef HAVE_SOCKADDR_IN_SIN_LEN 191#ifdef HAVE_SOCKADDR_IN_SIN_LEN
@@ -185,13 +194,16 @@ notify_change (struct GNUNET_NAT_Handle *nat, struct sockaddr *addr, int new_por
185 tmp_addr->sin_port = port_mapped ? htons (nat->public_port) : 0; 194 tmp_addr->sin_port = port_mapped ? htons (nat->public_port) : 0;
186 tmp_addr->sin_addr = ((struct sockaddr_in *) nat->ext_addr)->sin_addr; 195 tmp_addr->sin_addr = ((struct sockaddr_in *) nat->ext_addr)->sin_addr;
187 nat->contact_addr = (struct sockaddr *) tmp_addr; 196 nat->contact_addr = (struct sockaddr *) tmp_addr;
188 if (nat->callback) 197 if (NULL != nat->callback)
189 (*nat->callback) (nat->callback_cls, GNUNET_YES, nat->contact_addr, 198 nat->callback (nat->callback_cls,
190 sizeof (struct sockaddr_in)); 199 GNUNET_YES,
200 nat->contact_addr,
201 sizeof (struct sockaddr_in));
191 } 202 }
192 else if (nat->ext_addr->sa_family == AF_INET6) 203 else if (nat->ext_addr->sa_family == AF_INET6)
193 { 204 {
194 struct sockaddr_in6 *tmp_addr; 205 struct sockaddr_in6 *tmp_addr;
206
195 tmp_addr = GNUNET_malloc (sizeof (struct sockaddr_in6)); 207 tmp_addr = GNUNET_malloc (sizeof (struct sockaddr_in6));
196 tmp_addr->sin6_family = AF_INET6; 208 tmp_addr->sin6_family = AF_INET6;
197#ifdef HAVE_SOCKADDR_IN_SIN_LEN 209#ifdef HAVE_SOCKADDR_IN_SIN_LEN
@@ -200,23 +212,31 @@ notify_change (struct GNUNET_NAT_Handle *nat, struct sockaddr *addr, int new_por
200 tmp_addr->sin6_port = port_mapped ? htons (nat->public_port) : 0; 212 tmp_addr->sin6_port = port_mapped ? htons (nat->public_port) : 0;
201 tmp_addr->sin6_addr = ((struct sockaddr_in6 *) nat->ext_addr)->sin6_addr; 213 tmp_addr->sin6_addr = ((struct sockaddr_in6 *) nat->ext_addr)->sin6_addr;
202 nat->contact_addr = (struct sockaddr *) tmp_addr; 214 nat->contact_addr = (struct sockaddr *) tmp_addr;
203 if (nat->callback) 215 if (NULL != nat->callback)
204 (*nat->callback) (nat->callback_cls, GNUNET_YES, nat->contact_addr, 216 nat->callback (nat->callback_cls,
205 sizeof (struct sockaddr_in6)); 217 GNUNET_YES,
218 nat->contact_addr,
219 sizeof (struct sockaddr_in6));
220 }
221 else
222 {
223 GNUNET_break (0);
206 } 224 }
207} 225}
208 226
227
209static void 228static void
210nat_pulse (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 229nat_pulse (void *cls,
230 const struct GNUNET_SCHEDULER_TaskContext *tc)
211{ 231{
212 struct GNUNET_NAT_Handle *nat = cls; 232 struct GNUNET_NAT_Handle *nat = cls;
213 static int first_warning = GNUNET_YES;
214 int old_status; 233 int old_status;
215 int new_status; 234 int new_status;
216 int port_mapped; 235 int port_mapped;
217 struct sockaddr *ext_addr_upnp = NULL; 236 struct sockaddr *ext_addr_upnp = NULL;
218 struct sockaddr *ext_addr_natpmp = NULL; 237 struct sockaddr *ext_addr_natpmp = NULL;
219 238
239 nat->pulse_timer = GNUNET_SCHEDULER_NO_TASK;
220 old_status = get_traversal_status (nat); 240 old_status = get_traversal_status (nat);
221 241
222 /* Only update the protocol that has been successful until now */ 242 /* Only update the protocol that has been successful until now */
@@ -230,6 +250,7 @@ nat_pulse (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
230 &ext_addr_natpmp); 250 &ext_addr_natpmp);
231 else 251 else
232 { 252 {
253 /* try both */
233 nat->upnp_status = 254 nat->upnp_status =
234 GNUNET_NAT_UPNP_pulse (nat->upnp, nat->is_enabled, GNUNET_YES, 255 GNUNET_NAT_UPNP_pulse (nat->upnp, nat->is_enabled, GNUNET_YES,
235 &ext_addr_upnp); 256 &ext_addr_upnp);
@@ -237,18 +258,17 @@ nat_pulse (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
237 GNUNET_NAT_NATPMP_pulse (nat->natpmp, nat->is_enabled, 258 GNUNET_NAT_NATPMP_pulse (nat->natpmp, nat->is_enabled,
238 &ext_addr_natpmp); 259 &ext_addr_natpmp);
239 } 260 }
240
241 new_status = get_traversal_status (nat); 261 new_status = get_traversal_status (nat);
242 262 if ( (old_status != new_status) &&
243 if (old_status != new_status && 263 ( (new_status == GNUNET_NAT_PORT_UNMAPPED) ||
244 (new_status == GNUNET_NAT_PORT_UNMAPPED || new_status == GNUNET_NAT_PORT_ERROR)) 264 (new_status == GNUNET_NAT_PORT_ERROR) ) )
245 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, COMP_NAT, 265 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
266 "NAT",
246 _("Port redirection failed: no UPnP or NAT-PMP routers supporting this feature found\n")); 267 _("Port redirection failed: no UPnP or NAT-PMP routers supporting this feature found\n"));
247
248#ifdef DEBUG 268#ifdef DEBUG
249 if (new_status != old_status) 269 if (new_status != old_status)
250 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, COMP_NAT, 270 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "NAT",
251 _("State changed from \"%s\" to \"%s\"\n"), 271 _("State changed from `%s' to `%s'\n"),
252 get_nat_state_str (old_status), 272 get_nat_state_str (old_status),
253 get_nat_state_str (new_status)); 273 get_nat_state_str (new_status));
254#endif 274#endif
@@ -257,53 +277,64 @@ nat_pulse (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
257 if (!(ext_addr_upnp || ext_addr_natpmp)) 277 if (!(ext_addr_upnp || ext_addr_natpmp))
258 { 278 {
259 /* Address has just changed and we could not get it, or it's the first try */ 279 /* Address has just changed and we could not get it, or it's the first try */
260 if (nat->ext_addr || first_warning) 280 if ( (NULL != nat->ext_addr) ||
281 (GNUNET_NO == nat->did_warn) )
261 { 282 {
262 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, COMP_NAT, 283 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
263 _("Could not determine external IP address\n")); 284 "NAT",
264 first_warning = GNUNET_NO; 285 _("Could not determine external IP address\n"));
286 nat->did_warn = GNUNET_YES;
265 } 287 }
266
267 notify_change (nat, NULL, port_mapped); 288 notify_change (nat, NULL, port_mapped);
268 } 289 }
269 else if (ext_addr_upnp && GNUNET_NAT_cmp_addr (nat->ext_addr, ext_addr_upnp) != 0) 290 else if (ext_addr_upnp && GNUNET_NAT_cmp_addr (nat->ext_addr, ext_addr_upnp) != 0)
270 { 291 {
271 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, COMP_NAT, 292 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
272 _("External IP address changed from %s to %s\n"), 293 "NAT",
273 GNUNET_a2s (nat->ext_addr, sizeof (nat->ext_addr)), 294 _("External IP address changed to %s\n"),
274 GNUNET_a2s (ext_addr_upnp, sizeof (ext_addr_upnp))); 295 GNUNET_a2s (ext_addr_upnp, sizeof (ext_addr_upnp)));
275
276 notify_change (nat, ext_addr_upnp, port_mapped); 296 notify_change (nat, ext_addr_upnp, port_mapped);
277 } 297 }
278 else if (ext_addr_natpmp && GNUNET_NAT_cmp_addr (nat->ext_addr, ext_addr_natpmp) != 0) 298 else if (ext_addr_natpmp && GNUNET_NAT_cmp_addr (nat->ext_addr, ext_addr_natpmp) != 0)
279 { 299 {
280 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, COMP_NAT, 300 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "NAT",
281 _("External IP address changed from %s to %s\n"), 301 _("External IP address changed to `%s'\n"),
282 GNUNET_a2s (nat->ext_addr, sizeof (nat->ext_addr)), 302 GNUNET_a2s (ext_addr_natpmp, sizeof (ext_addr_natpmp)));
283 GNUNET_a2s (ext_addr_natpmp, sizeof (ext_addr_natpmp)));
284
285 notify_change (nat, ext_addr_natpmp, port_mapped); 303 notify_change (nat, ext_addr_natpmp, port_mapped);
286 } 304 }
287
288 nat->pulse_timer = GNUNET_SCHEDULER_add_delayed (nat->sched, 305 nat->pulse_timer = GNUNET_SCHEDULER_add_delayed (nat->sched,
289 GNUNET_TIME_UNIT_SECONDS, 306 GNUNET_TIME_UNIT_SECONDS,
290 &nat_pulse, nat); 307 &nat_pulse, nat);
291} 308}
292 309
310
311/**
312 * Attempt to enable port redirection and detect public IP address contacting
313 * UPnP or NAT-PMP routers on the local network. Use addr to specify to which
314 * of the local host's addresses should the external port be mapped. The port
315 * is taken from the corresponding sockaddr_in[6] field.
316 *
317 * @param sched the sheduler used in the program
318 * @param addr the local address packets should be redirected to
319 * @param addrlen actual lenght of the address
320 * @param callback function to call everytime the public IP address changes
321 * @param callback_cls closure for callback
322 * @return NULL on error, otherwise handle that can be used to unregister
323 */
293struct GNUNET_NAT_Handle * 324struct GNUNET_NAT_Handle *
294GNUNET_NAT_register (struct GNUNET_SCHEDULER_Handle *sched, 325GNUNET_NAT_register (struct GNUNET_SCHEDULER_Handle *sched,
295 const struct sockaddr *addr, socklen_t addrlen, 326 const struct sockaddr *addr, socklen_t addrlen,
296 GNUNET_NAT_AddressCallback callback, void *callback_cls) 327 GNUNET_NAT_AddressCallback callback, void *callback_cls)
297{ 328{
298 struct GNUNET_NAT_Handle *nat = GNUNET_malloc (sizeof (struct GNUNET_NAT_Handle)); 329 struct GNUNET_NAT_Handle *nat;
299 330
331 nat = GNUNET_malloc (sizeof (struct GNUNET_NAT_Handle));
300 if (addr) 332 if (addr)
301 { 333 {
302 GNUNET_assert (addr->sa_family == AF_INET 334 GNUNET_assert ( (addr->sa_family == AF_INET) ||
303 || addr->sa_family == AF_INET6); 335 (addr->sa_family == AF_INET6) );
304 nat->local_addr = GNUNET_malloc (addrlen); 336 nat->local_addr = GNUNET_malloc (addrlen);
305 memcpy (nat->local_addr, addr, addrlen); 337 memcpy (nat->local_addr, addr, addrlen);
306
307 if (addr->sa_family == AF_INET) 338 if (addr->sa_family == AF_INET)
308 { 339 {
309 nat->public_port = ntohs (((struct sockaddr_in *) addr)->sin_port); 340 nat->public_port = ntohs (((struct sockaddr_in *) addr)->sin_port);
@@ -315,12 +346,6 @@ GNUNET_NAT_register (struct GNUNET_SCHEDULER_Handle *sched,
315 ((struct sockaddr_in6 *) nat->local_addr)->sin6_port = 0; 346 ((struct sockaddr_in6 *) nat->local_addr)->sin6_port = 0;
316 } 347 }
317 } 348 }
318 else
319 {
320 nat->local_addr = NULL;
321 nat->public_port = 0;
322 }
323
324 nat->should_change = GNUNET_YES; 349 nat->should_change = GNUNET_YES;
325 nat->sched = sched; 350 nat->sched = sched;
326 nat->is_enabled = GNUNET_YES; 351 nat->is_enabled = GNUNET_YES;
@@ -328,37 +353,41 @@ GNUNET_NAT_register (struct GNUNET_SCHEDULER_Handle *sched,
328 nat->natpmp_status = GNUNET_NAT_PORT_UNMAPPED; 353 nat->natpmp_status = GNUNET_NAT_PORT_UNMAPPED;
329 nat->callback = callback; 354 nat->callback = callback;
330 nat->callback_cls = callback_cls; 355 nat->callback_cls = callback_cls;
331 nat->ext_addr = NULL;
332 nat->contact_addr = NULL;
333 nat->natpmp = GNUNET_NAT_NATPMP_init (nat->local_addr, addrlen, nat->public_port); 356 nat->natpmp = GNUNET_NAT_NATPMP_init (nat->local_addr, addrlen, nat->public_port);
334 nat->upnp = GNUNET_NAT_UPNP_init (nat->local_addr, addrlen, nat->public_port); 357 nat->upnp = GNUNET_NAT_UPNP_init (nat->local_addr, addrlen, nat->public_port);
335
336 nat->pulse_timer = GNUNET_SCHEDULER_add_delayed (sched, 358 nat->pulse_timer = GNUNET_SCHEDULER_add_delayed (sched,
337 GNUNET_TIME_UNIT_SECONDS, 359 GNUNET_TIME_UNIT_SECONDS,
338 &nat_pulse, nat); 360 &nat_pulse, nat);
339
340 return nat; 361 return nat;
341} 362}
342 363
364
365/**
366 * Stop port redirection and public IP address detection for the given handle.
367 * This frees the handle, after having sent the needed commands to close open ports.
368 *
369 * @param h the handle to stop
370 */
343void 371void
344GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *nat) 372GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *nat)
345{ 373{
346 struct sockaddr *addr; 374 struct sockaddr *addr;
347 GNUNET_SCHEDULER_cancel (nat->sched, nat->pulse_timer);
348 375
376 GNUNET_SCHEDULER_cancel (nat->sched,
377 nat->pulse_timer);
349 nat->upnp_status = 378 nat->upnp_status =
350 GNUNET_NAT_UPNP_pulse (nat->upnp, GNUNET_NO, GNUNET_NO, 379 GNUNET_NAT_UPNP_pulse (nat->upnp,
380 GNUNET_NO, GNUNET_NO,
351 &addr); 381 &addr);
352 nat->natpmp_status = 382 nat->natpmp_status =
353 GNUNET_NAT_NATPMP_pulse (nat->natpmp, GNUNET_NO, 383 GNUNET_NAT_NATPMP_pulse (nat->natpmp, GNUNET_NO,
354 &addr); 384 &addr);
355
356 GNUNET_NAT_NATPMP_close (nat->natpmp); 385 GNUNET_NAT_NATPMP_close (nat->natpmp);
357 GNUNET_NAT_UPNP_close (nat->upnp); 386 GNUNET_NAT_UPNP_close (nat->upnp);
358 387 GNUNET_free_non_null (nat->local_addr);
359 if (nat->local_addr) 388 GNUNET_free_non_null (nat->ext_addr);
360 GNUNET_free (nat->local_addr);
361 if (nat->ext_addr)
362 GNUNET_free (nat->ext_addr);
363 GNUNET_free (nat); 389 GNUNET_free (nat);
364} 390}
391
392/* end of nat.c */
393
diff --git a/src/nat/natpmp.h b/src/nat/natpmp.h
index 54afbf5f1..8e1531cee 100644
--- a/src/nat/natpmp.h
+++ b/src/nat/natpmp.h
@@ -30,15 +30,18 @@
30 30
31#include "platform.h" 31#include "platform.h"
32 32
33typedef struct GNUNET_NAT_NATPMP_Handle GNUNET_NAT_NATPMP_Handle; 33struct GNUNET_NAT_NATPMP_Handle;
34 34
35GNUNET_NAT_NATPMP_Handle *GNUNET_NAT_NATPMP_init (const struct sockaddr *addr, 35struct GNUNET_NAT_NATPMP_Handle *
36 socklen_t addrlen, 36GNUNET_NAT_NATPMP_init (const struct sockaddr *addr,
37 unsigned short port); 37 socklen_t addrlen,
38 unsigned short port);
38 39
39void GNUNET_NAT_NATPMP_close (GNUNET_NAT_NATPMP_Handle * nat); 40void GNUNET_NAT_NATPMP_close (struct GNUNET_NAT_NATPMP_Handle * nat);
40 41
41int GNUNET_NAT_NATPMP_pulse (GNUNET_NAT_NATPMP_Handle * nat, int is_enabled, 42int GNUNET_NAT_NATPMP_pulse (struct GNUNET_NAT_NATPMP_Handle * nat,
43 int is_enabled,
42 struct sockaddr **ext_addr); 44 struct sockaddr **ext_addr);
43 45
44#endif /* NATPMP_H */ 46#endif
47/* NATPMP_H */
diff --git a/src/nat/upnp.c b/src/nat/upnp.c
index 8fc5f7e04..84abe339d 100644
--- a/src/nat/upnp.c
+++ b/src/nat/upnp.c
@@ -46,15 +46,14 @@
46/* Component name for logging */ 46/* Component name for logging */
47#define COMP_NAT_UPNP _("NAT (UPnP)") 47#define COMP_NAT_UPNP _("NAT (UPnP)")
48 48
49typedef enum 49enum UPNP_State
50{ 50{
51 UPNP_IDLE, 51 UPNP_IDLE,
52 UPNP_ERR, 52 UPNP_ERR,
53 UPNP_DISCOVER, 53 UPNP_DISCOVER,
54 UPNP_MAP, 54 UPNP_MAP,
55 UPNP_UNMAP 55 UPNP_UNMAP
56} 56};
57UPNP_state;
58 57
59struct GNUNET_NAT_UPNP_Handle 58struct GNUNET_NAT_UPNP_Handle
60{ 59{
@@ -65,7 +64,7 @@ struct GNUNET_NAT_UPNP_Handle
65 const struct sockaddr *addr; 64 const struct sockaddr *addr;
66 socklen_t addrlen; 65 socklen_t addrlen;
67 unsigned int is_mapped; 66 unsigned int is_mapped;
68 UPNP_state state; 67 enum UPNP_State state;
69 struct sockaddr *ext_addr; 68 struct sockaddr *ext_addr;
70 const char *iface; 69 const char *iface;
71}; 70};
@@ -81,35 +80,37 @@ process_if (void *cls,
81 80
82 if (addr && GNUNET_NAT_cmp_addr (upnp->addr, addr) == 0) 81 if (addr && GNUNET_NAT_cmp_addr (upnp->addr, addr) == 0)
83 { 82 {
84 upnp->iface = name; 83 upnp->iface = name; // BADNESS!
85 return GNUNET_SYSERR; 84 return GNUNET_SYSERR;
86 } 85 }
87 86
88 return GNUNET_OK; 87 return GNUNET_OK;
89} 88}
90 89
90
91GNUNET_NAT_UPNP_Handle * 91GNUNET_NAT_UPNP_Handle *
92GNUNET_NAT_UPNP_init (const struct sockaddr *addr, socklen_t addrlen, 92GNUNET_NAT_UPNP_init (const struct sockaddr *addr,
93 socklen_t addrlen,
93 u_short port) 94 u_short port)
94{ 95{
95 GNUNET_NAT_UPNP_Handle *upnp = 96 GNUNET_NAT_UPNP_Handle *upnp;
96 GNUNET_malloc (sizeof (GNUNET_NAT_UPNP_Handle));
97 97
98 upnp = GNUNET_malloc (sizeof (GNUNET_NAT_UPNP_Handle));
98 upnp->state = UPNP_DISCOVER; 99 upnp->state = UPNP_DISCOVER;
99 upnp->addr = addr; 100 upnp->addr = addr;
100 upnp->addrlen = addrlen; 101 upnp->addrlen = addrlen;
101 upnp->port = port; 102 upnp->port = port;
102
103 /* Find the interface corresponding to the address, 103 /* Find the interface corresponding to the address,
104 * on which we should broadcast call for routers */ 104 * on which we should broadcast call for routers */
105 upnp->iface = NULL; 105 GNUNET_OS_network_interfaces_list (&process_if, upnp);
106 GNUNET_OS_network_interfaces_list (process_if, upnp);
107 if (!upnp->iface) 106 if (!upnp->iface)
108 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, COMP_NAT_UPNP, "Could not find an interface matching the wanted address.\n"); 107 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
109 108 COMP_NAT_UPNP,
109 "Could not find an interface matching the wanted address.\n");
110 return upnp; 110 return upnp;
111} 111}
112 112
113
113void 114void
114GNUNET_NAT_UPNP_close (GNUNET_NAT_UPNP_Handle * handle) 115GNUNET_NAT_UPNP_close (GNUNET_NAT_UPNP_Handle * handle)
115{ 116{
diff --git a/src/nat/upnp.h b/src/nat/upnp.h
index 8fd44a8f1..ccb04ed00 100644
--- a/src/nat/upnp.h
+++ b/src/nat/upnp.h
@@ -30,14 +30,19 @@
30 30
31#include "platform.h" 31#include "platform.h"
32 32
33typedef struct GNUNET_NAT_UPNP_Handle GNUNET_NAT_UPNP_Handle; 33struct GNUNET_NAT_UPNP_Handle;
34 34
35GNUNET_NAT_UPNP_Handle *GNUNET_NAT_UPNP_init (const struct sockaddr *addr, 35struct GNUNET_NAT_UPNP_Handle *
36 socklen_t addrlen, 36GNUNET_NAT_UPNP_init (const struct sockaddr *addr,
37 unsigned short port); 37 socklen_t addrlen,
38 unsigned short port);
38 39
39void GNUNET_NAT_UPNP_close (GNUNET_NAT_UPNP_Handle *); 40void GNUNET_NAT_UPNP_close (struct GNUNET_NAT_UPNP_Handle * h);
40 41
41int GNUNET_NAT_UPNP_pulse (GNUNET_NAT_UPNP_Handle *, int is_enabled, 42int GNUNET_NAT_UPNP_pulse (struct GNUNET_NAT_UPNP_Handle *h,
42 int do_port_check, struct sockaddr **ext_addr); 43 int is_enabled,
43#endif /* UPNP_H */ 44 int do_port_check,
45 struct sockaddr **ext_addr);
46
47#endif
48/* UPNP_H */