aboutsummaryrefslogtreecommitdiff
path: root/src/nat/nat.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-09-01 13:36:01 +0000
committerChristian Grothoff <christian@grothoff.org>2010-09-01 13:36:01 +0000
commit75bf71e92c81b966df11ad3c00228658f46a6e8f (patch)
tree610fecea7e6ce4b4bfda0f3a205f355dd0ef30be /src/nat/nat.c
parentc09f6eb6d32f57778cf8f8baf0456cbe7158eb79 (diff)
downloadgnunet-75bf71e92c81b966df11ad3c00228658f46a6e8f.tar.gz
gnunet-75bf71e92c81b966df11ad3c00228658f46a6e8f.zip
starting NAT code cleanup
Diffstat (limited to 'src/nat/nat.c')
-rw-r--r--src/nat/nat.c293
1 files changed, 161 insertions, 132 deletions
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