aboutsummaryrefslogtreecommitdiff
path: root/src/nat
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2014-01-07 05:14:12 +0000
committerChristian Grothoff <christian@grothoff.org>2014-01-07 05:14:12 +0000
commit9e0744da3a82cc7b68a9043272044584be98db44 (patch)
tree0d66dcff21faddda56c57f6768f7fee49649366a /src/nat
parent1ab001d527da02fbf9a7212497c162a979aa8f6b (diff)
downloadgnunet-9e0744da3a82cc7b68a9043272044584be98db44.tar.gz
gnunet-9e0744da3a82cc7b68a9043272044584be98db44.zip
-modify NAT API to return error messages about problems detected
Diffstat (limited to 'src/nat')
-rw-r--r--src/nat/nat.c4
-rw-r--r--src/nat/nat_auto.c12
-rw-r--r--src/nat/nat_mini.c254
-rw-r--r--src/nat/nat_test.c23
-rw-r--r--src/nat/test_nat_mini.c18
-rw-r--r--src/nat/test_nat_test.c22
6 files changed, 230 insertions, 103 deletions
diff --git a/src/nat/nat.c b/src/nat/nat.c
index 69c60291c..ae40a2cd1 100644
--- a/src/nat/nat.c
+++ b/src/nat/nat.c
@@ -1011,12 +1011,14 @@ resolve_dns (void *cls,
1011 * the previous (now invalid) one 1011 * the previous (now invalid) one
1012 * @param addr either the previous or the new public IP address 1012 * @param addr either the previous or the new public IP address
1013 * @param addrlen actual lenght of @a addr 1013 * @param addrlen actual lenght of @a addr
1014 * @param emsg NULL on success, otherwise an error message
1014 */ 1015 */
1015static void 1016static void
1016upnp_add (void *cls, 1017upnp_add (void *cls,
1017 int add_remove, 1018 int add_remove,
1018 const struct sockaddr *addr, 1019 const struct sockaddr *addr,
1019 socklen_t addrlen) 1020 socklen_t addrlen,
1021 const char *emsg)
1020{ 1022{
1021 struct GNUNET_NAT_Handle *h = cls; 1023 struct GNUNET_NAT_Handle *h = cls;
1022 struct LocalAddressList *pos; 1024 struct LocalAddressList *pos;
diff --git a/src/nat/nat_auto.c b/src/nat/nat_auto.c
index 9e7ff23f2..070099b23 100644
--- a/src/nat/nat_auto.c
+++ b/src/nat/nat_auto.c
@@ -185,9 +185,12 @@ fail_timeout (void *cls,
185 * 185 *
186 * @param cls the auto handle 186 * @param cls the auto handle
187 * @param success currently always #GNUNET_OK 187 * @param success currently always #GNUNET_OK
188 * @param emsg NULL on success, otherwise an error message
188 */ 189 */
189static void 190static void
190result_callback (void *cls, int success) 191result_callback (void *cls,
192 int success,
193 const char *emsg)
191{ 194{
192 struct GNUNET_NAT_AutoHandle *ah = cls; 195 struct GNUNET_NAT_AutoHandle *ah = cls;
193 196
@@ -250,10 +253,12 @@ test_online (struct GNUNET_NAT_AutoHandle *ah)
250 * 253 *
251 * @param cls closure with our setup context 254 * @param cls closure with our setup context
252 * @param addr the address, NULL on errors 255 * @param addr the address, NULL on errors
256 * @param emsg NULL on success, otherwise an error message
253 */ 257 */
254static void 258static void
255set_external_ipv4 (void *cls, 259set_external_ipv4 (void *cls,
256 const struct in_addr *addr) 260 const struct in_addr *addr,
261 const char *emsg)
257{ 262{
258 struct GNUNET_NAT_AutoHandle *ah = cls; 263 struct GNUNET_NAT_AutoHandle *ah = cls;
259 char buf[INET_ADDRSTRLEN]; 264 char buf[INET_ADDRSTRLEN];
@@ -519,7 +524,8 @@ next_phase (struct GNUNET_NAT_AutoHandle *ah)
519 diff = GNUNET_CONFIGURATION_get_diff (ah->initial_cfg, 524 diff = GNUNET_CONFIGURATION_get_diff (ah->initial_cfg,
520 ah->cfg); 525 ah->cfg);
521 ah->fin_cb (ah->fin_cb_cls, 526 ah->fin_cb (ah->fin_cb_cls,
522 diff); 527 diff,
528 NULL);
523 GNUNET_CONFIGURATION_destroy (diff); 529 GNUNET_CONFIGURATION_destroy (diff);
524 GNUNET_NAT_autoconfig_cancel (ah); 530 GNUNET_NAT_autoconfig_cancel (ah);
525 return; 531 return;
diff --git a/src/nat/nat_mini.c b/src/nat/nat_mini.c
index 497371e86..a5ae4ad08 100644
--- a/src/nat/nat_mini.c
+++ b/src/nat/nat_mini.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2011 Christian Grothoff (and other contributing authors) 3 (C) 2011-2014 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
@@ -59,7 +59,7 @@ struct GNUNET_NAT_ExternalHandle
59 GNUNET_NAT_IPCallback cb; 59 GNUNET_NAT_IPCallback cb;
60 60
61 /** 61 /**
62 * Closure for 'cb'. 62 * Closure for @e cb.
63 */ 63 */
64 void *cb_cls; 64 void *cb_cls;
65 65
@@ -79,7 +79,7 @@ struct GNUNET_NAT_ExternalHandle
79 struct GNUNET_DISK_PipeHandle *opipe; 79 struct GNUNET_DISK_PipeHandle *opipe;
80 80
81 /** 81 /**
82 * Read handle of 'opipe'. 82 * Read handle of @e opipe.
83 */ 83 */
84 const struct GNUNET_DISK_FileHandle *r; 84 const struct GNUNET_DISK_FileHandle *r;
85 85
@@ -105,11 +105,12 @@ struct GNUNET_NAT_ExternalHandle
105 * Read the output of 'external-ip' into buf. When complete, parse the 105 * Read the output of 'external-ip' into buf. When complete, parse the
106 * address and call our callback. 106 * address and call our callback.
107 * 107 *
108 * @param cls the 'struct GNUNET_NAT_ExternalHandle' 108 * @param cls the `struct GNUNET_NAT_ExternalHandle`
109 * @param tc scheduler context 109 * @param tc scheduler context
110 */ 110 */
111static void 111static void
112read_external_ipv4 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 112read_external_ipv4 (void *cls,
113 const struct GNUNET_SCHEDULER_TaskContext *tc)
113{ 114{
114 struct GNUNET_NAT_ExternalHandle *eh = cls; 115 struct GNUNET_NAT_ExternalHandle *eh = cls;
115 ssize_t ret; 116 ssize_t ret;
@@ -139,24 +140,50 @@ read_external_ipv4 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
139 eh->buf[eh->off - 1] = '\0'; 140 eh->buf[eh->off - 1] = '\0';
140 if (1 == inet_pton (AF_INET, eh->buf, &addr)) 141 if (1 == inet_pton (AF_INET, eh->buf, &addr))
141 { 142 {
142 if (addr.s_addr == 0) 143 if (0 == addr.s_addr)
143 iret = GNUNET_NO; /* got 0.0.0.0 */ 144 iret = GNUNET_NO; /* got 0.0.0.0 */
144 else 145 else
145 iret = GNUNET_OK; 146 iret = GNUNET_OK;
146 } 147 }
147 } 148 }
148 eh->cb (eh->cb_cls, (iret == GNUNET_OK) ? &addr : NULL); 149 eh->cb (eh->cb_cls,
150 (GNUNET_OK == iret)
151 ? &addr :
152 NULL,
153 (GNUNET_OK == iret)
154 ? NULL
155 : _("no valid address was returned by `external-ip'"));
149 GNUNET_NAT_mini_get_external_ipv4_cancel (eh); 156 GNUNET_NAT_mini_get_external_ipv4_cancel (eh);
150} 157}
151 158
152 159
153/** 160/**
161 * (Asynchronously) signal error invoking "external-ip" to client.
162 *
163 * @param cls the `struct GNUNET_NAT_ExternalHandle` (freed)
164 * @param tc scheduler context
165 */
166static void
167signal_external_ip_error (void *cls,
168 const struct GNUNET_SCHEDULER_TaskContext *tc)
169{
170 struct GNUNET_NAT_ExternalHandle *eh = cls;
171
172 eh->task = GNUNET_SCHEDULER_NO_TASK;
173 eh->cb (eh->cb_cls,
174 NULL,
175 _("`external-ip' command not found"));
176 GNUNET_free (eh);
177}
178
179
180/**
154 * Try to get the external IPv4 address of this peer. 181 * Try to get the external IPv4 address of this peer.
155 * 182 *
156 * @param timeout when to fail 183 * @param timeout when to fail
157 * @param cb function to call with result 184 * @param cb function to call with result
158 * @param cb_cls closure for 'cb' 185 * @param cb_cls closure for @a cb
159 * @return handle for cancellation (can only be used until 'cb' is called), NULL on error 186 * @return handle for cancellation (can only be used until @a cb is called), NULL on error
160 */ 187 */
161struct GNUNET_NAT_ExternalHandle * 188struct GNUNET_NAT_ExternalHandle *
162GNUNET_NAT_mini_get_external_ipv4 (struct GNUNET_TIME_Relative timeout, 189GNUNET_NAT_mini_get_external_ipv4 (struct GNUNET_TIME_Relative timeout,
@@ -164,37 +191,45 @@ GNUNET_NAT_mini_get_external_ipv4 (struct GNUNET_TIME_Relative timeout,
164{ 191{
165 struct GNUNET_NAT_ExternalHandle *eh; 192 struct GNUNET_NAT_ExternalHandle *eh;
166 193
167 if (GNUNET_SYSERR == GNUNET_OS_check_helper_binary ("external-ip", GNUNET_NO, NULL)) 194 eh = GNUNET_new (struct GNUNET_NAT_ExternalHandle);
195 eh->cb = cb;
196 eh->cb_cls = cb_cls;
197 if (GNUNET_SYSERR ==
198 GNUNET_OS_check_helper_binary ("external-ip", GNUNET_NO, NULL))
168 { 199 {
169 LOG (GNUNET_ERROR_TYPE_INFO, 200 LOG (GNUNET_ERROR_TYPE_INFO,
170 _("`external-ip' command not found\n")); 201 _("`external-ip' command not found\n"));
171 return NULL; 202 eh->task = GNUNET_SCHEDULER_add_now (&signal_external_ip_error,
203 eh);
204 return eh;
172 } 205 }
173 LOG (GNUNET_ERROR_TYPE_DEBUG, 206 LOG (GNUNET_ERROR_TYPE_DEBUG,
174 "Running `external-ip' to determine our external IP\n"); 207 "Running `external-ip' to determine our external IP\n");
175 eh = GNUNET_new (struct GNUNET_NAT_ExternalHandle);
176 eh->cb = cb;
177 eh->cb_cls = cb_cls;
178 eh->opipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES); 208 eh->opipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES);
179 if (NULL == eh->opipe) 209 if (NULL == eh->opipe)
180 { 210 {
181 GNUNET_free (eh); 211 eh->task = GNUNET_SCHEDULER_add_now (&signal_external_ip_error,
182 return NULL; 212 eh);
213 return eh;
183 } 214 }
184 eh->eip = 215 eh->eip =
185 GNUNET_OS_start_process (GNUNET_NO, 0, NULL, eh->opipe, "external-ip", "external-ip", 216 GNUNET_OS_start_process (GNUNET_NO, 0, NULL, eh->opipe,
217 "external-ip", "external-ip",
186 NULL); 218 NULL);
187 if (NULL == eh->eip) 219 if (NULL == eh->eip)
188 { 220 {
189 GNUNET_DISK_pipe_close (eh->opipe); 221 GNUNET_DISK_pipe_close (eh->opipe);
190 GNUNET_free (eh); 222 eh->task = GNUNET_SCHEDULER_add_now (&signal_external_ip_error,
191 return NULL; 223 eh);
224 return eh;
192 } 225 }
193 GNUNET_DISK_pipe_close_end (eh->opipe, GNUNET_DISK_PIPE_END_WRITE); 226 GNUNET_DISK_pipe_close_end (eh->opipe, GNUNET_DISK_PIPE_END_WRITE);
194 eh->timeout = GNUNET_TIME_relative_to_absolute (timeout); 227 eh->timeout = GNUNET_TIME_relative_to_absolute (timeout);
195 eh->r = GNUNET_DISK_pipe_handle (eh->opipe, GNUNET_DISK_PIPE_END_READ); 228 eh->r = GNUNET_DISK_pipe_handle (eh->opipe, GNUNET_DISK_PIPE_END_READ);
196 eh->task = 229 eh->task =
197 GNUNET_SCHEDULER_add_read_file (timeout, eh->r, &read_external_ipv4, eh); 230 GNUNET_SCHEDULER_add_read_file (timeout,
231 eh->r,
232 &read_external_ipv4, eh);
198 return eh; 233 return eh;
199} 234}
200 235
@@ -207,9 +242,13 @@ GNUNET_NAT_mini_get_external_ipv4 (struct GNUNET_TIME_Relative timeout,
207void 242void
208GNUNET_NAT_mini_get_external_ipv4_cancel (struct GNUNET_NAT_ExternalHandle *eh) 243GNUNET_NAT_mini_get_external_ipv4_cancel (struct GNUNET_NAT_ExternalHandle *eh)
209{ 244{
210 (void) GNUNET_OS_process_kill (eh->eip, SIGKILL); 245 if (NULL != eh->eip)
211 GNUNET_OS_process_destroy (eh->eip); 246 {
212 GNUNET_DISK_pipe_close (eh->opipe); 247 (void) GNUNET_OS_process_kill (eh->eip, SIGKILL);
248 GNUNET_OS_process_destroy (eh->eip);
249 }
250 if (NULL != eh->opipe)
251 GNUNET_DISK_pipe_close (eh->opipe);
213 if (GNUNET_SCHEDULER_NO_TASK != eh->task) 252 if (GNUNET_SCHEDULER_NO_TASK != eh->task)
214 GNUNET_SCHEDULER_cancel (eh->task); 253 GNUNET_SCHEDULER_cancel (eh->task);
215 GNUNET_free (eh); 254 GNUNET_free (eh);
@@ -225,10 +264,10 @@ struct GNUNET_NAT_MiniHandle
225 /** 264 /**
226 * Function to call on mapping changes. 265 * Function to call on mapping changes.
227 */ 266 */
228 GNUNET_NAT_AddressCallback ac; 267 GNUNET_NAT_MiniAddressCallback ac;
229 268
230 /** 269 /**
231 * Closure for 'ac'. 270 * Closure for @e ac.
232 */ 271 */
233 void *ac_cls; 272 void *ac_cls;
234 273
@@ -282,9 +321,9 @@ struct GNUNET_NAT_MiniHandle
282 321
283 322
284/** 323/**
285 * Run upnpc -l to find out if our mapping changed. 324 * Run "upnpc -l" to find out if our mapping changed.
286 * 325 *
287 * @param cls the 'struct GNUNET_NAT_MiniHandle' 326 * @param cls the `struct GNUNET_NAT_MiniHandle`
288 * @param tc scheduler context 327 * @param tc scheduler context
289 */ 328 */
290static void 329static void
@@ -292,9 +331,9 @@ do_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
292 331
293 332
294/** 333/**
295 * Process the output from the 'upnpc -r' command. 334 * Process the output from the "upnpc -r" command.
296 * 335 *
297 * @param cls the 'struct GNUNET_NAT_MiniHandle' 336 * @param cls the `struct GNUNET_NAT_MiniHandle`
298 * @param line line of output, NULL at the end 337 * @param line line of output, NULL at the end
299 */ 338 */
300static void 339static void
@@ -302,10 +341,39 @@ process_map_output (void *cls, const char *line);
302 341
303 342
304/** 343/**
305 * Process the output from 'upnpc -l' to see if our 344 * Run "upnpc -r" to map our internal port.
345 *
346 * @param mini our handle
347 */
348static void
349run_upnpc_r (struct GNUNET_NAT_MiniHandle *mini)
350{
351 char pstr[6];
352
353 GNUNET_snprintf (pstr,
354 sizeof (pstr),
355 "%u",
356 (unsigned int) mini->port);
357 mini->map_cmd =
358 GNUNET_OS_command_run (&process_map_output, mini, MAP_TIMEOUT,
359 "upnpc", "upnpc", "-r", pstr,
360 mini->is_tcp ? "tcp" : "udp", NULL);
361 if (NULL == mini->map_cmd)
362 {
363 mini->ac (mini->ac_cls,
364 GNUNET_SYSERR,
365 NULL, 0,
366 _("Failed to run `upnpc` command"));
367 return;
368 }
369}
370
371
372/**
373 * Process the output from "upnpc -l" to see if our
306 * external mapping changed. If so, do the notifications. 374 * external mapping changed. If so, do the notifications.
307 * 375 *
308 * @param cls the 'struct GNUNET_NAT_MiniHandle' 376 * @param cls the `struct GNUNET_NAT_MiniHandle`
309 * @param line line of output, NULL at the end 377 * @param line line of output, NULL at the end
310 */ 378 */
311static void 379static void
@@ -321,26 +389,20 @@ process_refresh_output (void *cls, const char *line)
321 { 389 {
322 GNUNET_OS_command_stop (mini->refresh_cmd); 390 GNUNET_OS_command_stop (mini->refresh_cmd);
323 mini->refresh_cmd = NULL; 391 mini->refresh_cmd = NULL;
324 if (mini->found == GNUNET_NO) 392 if (GNUNET_NO == mini->found)
325 { 393 {
326 /* mapping disappeared, try to re-create */ 394 /* mapping disappeared, try to re-create */
327 if (mini->did_map) 395 if (GNUNET_YES == mini->did_map)
328 { 396 {
329 mini->ac (mini->ac_cls, GNUNET_NO, 397 mini->ac (mini->ac_cls,
398 GNUNET_NO,
330 (const struct sockaddr *) &mini->current_addr, 399 (const struct sockaddr *) &mini->current_addr,
331 sizeof (mini->current_addr)); 400 sizeof (mini->current_addr),
401 NULL);
332 mini->did_map = GNUNET_NO; 402 mini->did_map = GNUNET_NO;
333 } 403 }
334 GNUNET_snprintf (pstr, sizeof (pstr), "%u", (unsigned int) mini->port); 404 run_upnpc_r (mini);
335 mini->map_cmd =
336 GNUNET_OS_command_run (&process_map_output, mini, MAP_TIMEOUT,
337 "upnpc", "upnpc", "-r", pstr,
338 mini->is_tcp ? "tcp" : "udp", NULL);
339 if (NULL != mini->map_cmd)
340 return;
341 } 405 }
342 mini->refresh_task =
343 GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ, &do_refresh, mini);
344 return; 406 return;
345 } 407 }
346 if (!mini->did_map) 408 if (!mini->did_map)
@@ -360,11 +422,13 @@ process_refresh_output (void *cls, const char *line)
360 /* update mapping */ 422 /* update mapping */
361 mini->ac (mini->ac_cls, GNUNET_NO, 423 mini->ac (mini->ac_cls, GNUNET_NO,
362 (const struct sockaddr *) &mini->current_addr, 424 (const struct sockaddr *) &mini->current_addr,
363 sizeof (mini->current_addr)); 425 sizeof (mini->current_addr),
426 NULL);
364 mini->current_addr.sin_addr = exip; 427 mini->current_addr.sin_addr = exip;
365 mini->ac (mini->ac_cls, GNUNET_YES, 428 mini->ac (mini->ac_cls, GNUNET_YES,
366 (const struct sockaddr *) &mini->current_addr, 429 (const struct sockaddr *) &mini->current_addr,
367 sizeof (mini->current_addr)); 430 sizeof (mini->current_addr),
431 NULL);
368 return; 432 return;
369 } 433 }
370 /* 434 /*
@@ -395,16 +459,18 @@ process_refresh_output (void *cls, const char *line)
395 /* external port changed, update mapping */ 459 /* external port changed, update mapping */
396 mini->ac (mini->ac_cls, GNUNET_NO, 460 mini->ac (mini->ac_cls, GNUNET_NO,
397 (const struct sockaddr *) &mini->current_addr, 461 (const struct sockaddr *) &mini->current_addr,
398 sizeof (mini->current_addr)); 462 sizeof (mini->current_addr),
463 NULL);
399 mini->current_addr.sin_port = htons ((uint16_t) nport); 464 mini->current_addr.sin_port = htons ((uint16_t) nport);
400 mini->ac (mini->ac_cls, GNUNET_YES, 465 mini->ac (mini->ac_cls, GNUNET_YES,
401 (const struct sockaddr *) &mini->current_addr, 466 (const struct sockaddr *) &mini->current_addr,
402 sizeof (mini->current_addr)); 467 sizeof (mini->current_addr),
468 NULL);
403} 469}
404 470
405 471
406/** 472/**
407 * Run upnpc -l to find out if our mapping changed. 473 * Run "upnpc -l" to find out if our mapping changed.
408 * 474 *
409 * @param cls the 'struct GNUNET_NAT_MiniHandle' 475 * @param cls the 'struct GNUNET_NAT_MiniHandle'
410 * @param tc scheduler context 476 * @param tc scheduler context
@@ -413,25 +479,49 @@ static void
413do_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 479do_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
414{ 480{
415 struct GNUNET_NAT_MiniHandle *mini = cls; 481 struct GNUNET_NAT_MiniHandle *mini = cls;
482 int ac;
416 483
484 mini->refresh_task =
485 GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ,
486 &do_refresh, mini);
417 LOG (GNUNET_ERROR_TYPE_DEBUG, 487 LOG (GNUNET_ERROR_TYPE_DEBUG,
418 "Running `upnpc' to check if our mapping still exists\n"); 488 "Running `upnpc' to check if our mapping still exists\n");
419 mini->refresh_task = GNUNET_SCHEDULER_NO_TASK;
420 mini->found = GNUNET_NO; 489 mini->found = GNUNET_NO;
490 ac = GNUNET_NO;
491 if (NULL != mini->map_cmd)
492 {
493 /* took way too long, abort it! */
494 GNUNET_OS_command_stop (mini->map_cmd);
495 mini->map_cmd = NULL;
496 ac = GNUNET_YES;
497 }
498 if (NULL != mini->refresh_cmd)
499 {
500 /* took way too long, abort it! */
501 GNUNET_OS_command_stop (mini->refresh_cmd);
502 mini->refresh_cmd = NULL;
503 ac = GNUNET_YES;
504 }
421 mini->refresh_cmd = 505 mini->refresh_cmd =
422 GNUNET_OS_command_run (&process_refresh_output, mini, MAP_TIMEOUT, 506 GNUNET_OS_command_run (&process_refresh_output, mini, MAP_TIMEOUT,
423 "upnpc", "upnpc", "-l", NULL); 507 "upnpc", "upnpc", "-l", NULL);
508 if (GNUNET_YES == ac)
509 mini->ac (mini->ac_cls,
510 GNUNET_SYSERR,
511 NULL, 0,
512 _("`upnpc' command took too long, process killed"));
424} 513}
425 514
426 515
427/** 516/**
428 * Process the output from the 'upnpc -r' command. 517 * Process the output from the 'upnpc -r' command.
429 * 518 *
430 * @param cls the 'struct GNUNET_NAT_MiniHandle' 519 * @param cls the `struct GNUNET_NAT_MiniHandle`
431 * @param line line of output, NULL at the end 520 * @param line line of output, NULL at the end
432 */ 521 */
433static void 522static void
434process_map_output (void *cls, const char *line) 523process_map_output (void *cls,
524 const char *line)
435{ 525{
436 struct GNUNET_NAT_MiniHandle *mini = cls; 526 struct GNUNET_NAT_MiniHandle *mini = cls;
437 const char *ipaddr; 527 const char *ipaddr;
@@ -443,7 +533,13 @@ process_map_output (void *cls, const char *line)
443 { 533 {
444 GNUNET_OS_command_stop (mini->map_cmd); 534 GNUNET_OS_command_stop (mini->map_cmd);
445 mini->map_cmd = NULL; 535 mini->map_cmd = NULL;
446 mini->refresh_task = 536 if (GNUNET_YES != mini->did_map)
537 mini->ac (mini->ac_cls,
538 GNUNET_SYSERR,
539 NULL, 0,
540 _("`upnpc' command failed to establish port mapping"));
541 if (GNUNET_SCHEDULER_NO_TASK == mini->refresh_task)
542 mini->refresh_task =
447 GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ, &do_refresh, mini); 543 GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ, &do_refresh, mini);
448 return; 544 return;
449 } 545 }
@@ -475,34 +571,41 @@ process_map_output (void *cls, const char *line)
475 mini->did_map = GNUNET_YES; 571 mini->did_map = GNUNET_YES;
476 mini->ac (mini->ac_cls, GNUNET_YES, 572 mini->ac (mini->ac_cls, GNUNET_YES,
477 (const struct sockaddr *) &mini->current_addr, 573 (const struct sockaddr *) &mini->current_addr,
478 sizeof (mini->current_addr)); 574 sizeof (mini->current_addr),
575 NULL);
479} 576}
480 577
481 578
482/** 579/**
483 * Start mapping the given port using (mini)upnpc. This function 580 * Start mapping the given port using (mini)upnpc. This function
484 * should typically not be used directly (it is used within the 581 * should typically not be used directly (it is used within the
485 * general-purpose 'GNUNET_NAT_register' code). However, it can be 582 * general-purpose #GNUNET_NAT_register() code). However, it can be
486 * used if specifically UPnP-based NAT traversal is to be used or 583 * used if specifically UPnP-based NAT traversal is to be used or
487 * tested. 584 * tested.
488 * 585 *
489 * @param port port to map 586 * @param port port to map
490 * @param is_tcp GNUNET_YES to map TCP, GNUNET_NO for UDP 587 * @param is_tcp #GNUNET_YES to map TCP, #GNUNET_NO for UDP
491 * @param ac function to call with mapping result 588 * @param ac function to call with mapping result
492 * @param ac_cls closure for 'ac' 589 * @param ac_cls closure for @a ac
493 * @return NULL on error (no 'upnpc' installed) 590 * @return NULL on error (no 'upnpc' installed)
494 */ 591 */
495struct GNUNET_NAT_MiniHandle * 592struct GNUNET_NAT_MiniHandle *
496GNUNET_NAT_mini_map_start (uint16_t port, int is_tcp, 593GNUNET_NAT_mini_map_start (uint16_t port,
497 GNUNET_NAT_AddressCallback ac, void *ac_cls) 594 int is_tcp,
595 GNUNET_NAT_MiniAddressCallback ac,
596 void *ac_cls)
498{ 597{
499 struct GNUNET_NAT_MiniHandle *ret; 598 struct GNUNET_NAT_MiniHandle *ret;
500 char pstr[6];
501 599
502 if (GNUNET_SYSERR == GNUNET_OS_check_helper_binary ("upnpc", GNUNET_NO, NULL)) 600 if (GNUNET_SYSERR ==
601 GNUNET_OS_check_helper_binary ("upnpc", GNUNET_NO, NULL))
503 { 602 {
504 LOG (GNUNET_ERROR_TYPE_INFO, 603 LOG (GNUNET_ERROR_TYPE_INFO,
505 _("`upnpc' command not found\n")); 604 _("`upnpc' command not found\n"));
605 ac (ac_cls,
606 GNUNET_SYSERR,
607 NULL, 0,
608 _("`upnpc` command not found"));
506 return NULL; 609 return NULL;
507 } 610 }
508 LOG (GNUNET_ERROR_TYPE_DEBUG, 611 LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -512,15 +615,9 @@ GNUNET_NAT_mini_map_start (uint16_t port, int is_tcp,
512 ret->ac_cls = ac_cls; 615 ret->ac_cls = ac_cls;
513 ret->is_tcp = is_tcp; 616 ret->is_tcp = is_tcp;
514 ret->port = port; 617 ret->port = port;
515 GNUNET_snprintf (pstr, sizeof (pstr), "%u", (unsigned int) port);
516 ret->map_cmd =
517 GNUNET_OS_command_run (&process_map_output, ret, MAP_TIMEOUT, "upnpc",
518 "upnpc", "-r", pstr, is_tcp ? "tcp" : "udp", NULL);
519 if (NULL != ret->map_cmd)
520 return ret;
521 ret->refresh_task = 618 ret->refresh_task =
522 GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ, &do_refresh, ret); 619 GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ, &do_refresh, ret);
523 620 run_upnpc_r (ret);
524 return ret; 621 return ret;
525} 622}
526 623
@@ -538,7 +635,8 @@ process_unmap_output (void *cls, const char *line)
538 635
539 if (NULL == line) 636 if (NULL == line)
540 { 637 {
541 LOG (GNUNET_ERROR_TYPE_DEBUG, "UPnP unmap done\n"); 638 LOG (GNUNET_ERROR_TYPE_DEBUG,
639 "UPnP unmap done\n");
542 GNUNET_OS_command_stop (mini->unmap_cmd); 640 GNUNET_OS_command_stop (mini->unmap_cmd);
543 mini->unmap_cmd = NULL; 641 mini->unmap_cmd = NULL;
544 GNUNET_free (mini); 642 GNUNET_free (mini);
@@ -566,14 +664,14 @@ GNUNET_NAT_mini_map_stop (struct GNUNET_NAT_MiniHandle *mini)
566 GNUNET_SCHEDULER_cancel (mini->refresh_task); 664 GNUNET_SCHEDULER_cancel (mini->refresh_task);
567 mini->refresh_task = GNUNET_SCHEDULER_NO_TASK; 665 mini->refresh_task = GNUNET_SCHEDULER_NO_TASK;
568 } 666 }
569 if (mini->refresh_cmd != NULL) 667 if (NULL != mini->refresh_cmd)
570 { 668 {
571 GNUNET_OS_command_stop (mini->refresh_cmd); 669 GNUNET_OS_command_stop (mini->refresh_cmd);
572 mini->refresh_cmd = NULL; 670 mini->refresh_cmd = NULL;
573 } 671 }
574 if (!mini->did_map) 672 if (GNUNET_NO == mini->did_map)
575 { 673 {
576 if (mini->map_cmd != NULL) 674 if (NULL != mini->map_cmd)
577 { 675 {
578 GNUNET_OS_command_stop (mini->map_cmd); 676 GNUNET_OS_command_stop (mini->map_cmd);
579 mini->map_cmd = NULL; 677 mini->map_cmd = NULL;
@@ -583,13 +681,17 @@ GNUNET_NAT_mini_map_stop (struct GNUNET_NAT_MiniHandle *mini)
583 } 681 }
584 mini->ac (mini->ac_cls, GNUNET_NO, 682 mini->ac (mini->ac_cls, GNUNET_NO,
585 (const struct sockaddr *) &mini->current_addr, 683 (const struct sockaddr *) &mini->current_addr,
586 sizeof (mini->current_addr)); 684 sizeof (mini->current_addr),
685 NULL);
587 /* Note: oddly enough, deletion uses the external port whereas 686 /* Note: oddly enough, deletion uses the external port whereas
588 * addition uses the internal port; this rarely matters since they 687 * addition uses the internal port; this rarely matters since they
589 * often are the same, but it might... */ 688 * often are the same, but it might... */
590 GNUNET_snprintf (pstr, sizeof (pstr), "%u", 689 GNUNET_snprintf (pstr,
690 sizeof (pstr),
691 "%u",
591 (unsigned int) ntohs (mini->current_addr.sin_port)); 692 (unsigned int) ntohs (mini->current_addr.sin_port));
592 LOG (GNUNET_ERROR_TYPE_DEBUG, "Unmapping port %u with UPnP\n", 693 LOG (GNUNET_ERROR_TYPE_DEBUG,
694 "Unmapping port %u with UPnP\n",
593 ntohs (mini->current_addr.sin_port)); 695 ntohs (mini->current_addr.sin_port));
594 mini->unmap_cmd = 696 mini->unmap_cmd =
595 GNUNET_OS_command_run (&process_unmap_output, mini, UNMAP_TIMEOUT, 697 GNUNET_OS_command_run (&process_unmap_output, mini, UNMAP_TIMEOUT,
diff --git a/src/nat/nat_test.c b/src/nat/nat_test.c
index c7de96d2f..f3b2b41ef 100644
--- a/src/nat/nat_test.c
+++ b/src/nat/nat_test.c
@@ -177,7 +177,7 @@ reversal_cb (void *cls,
177 struct GNUNET_NAT_Test *h = cls; 177 struct GNUNET_NAT_Test *h = cls;
178 const struct sockaddr_in *sa; 178 const struct sockaddr_in *sa;
179 179
180 if (addrlen != sizeof (struct sockaddr_in)) 180 if (sizeof (struct sockaddr_in) != addrlen)
181 return; 181 return;
182 sa = (const struct sockaddr_in *) addr; 182 sa = (const struct sockaddr_in *) addr;
183 if (h->data != sa->sin_port) 183 if (h->data != sa->sin_port)
@@ -187,7 +187,7 @@ reversal_cb (void *cls,
187 return; /* wrong port */ 187 return; /* wrong port */
188 } 188 }
189 /* report success */ 189 /* report success */
190 h->report (h->report_cls, GNUNET_OK); 190 h->report (h->report_cls, GNUNET_OK, NULL);
191} 191}
192 192
193 193
@@ -199,7 +199,8 @@ reversal_cb (void *cls,
199 * @param tc scheduler context 199 * @param tc scheduler context
200 */ 200 */
201static void 201static void
202do_udp_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 202do_udp_read (void *cls,
203 const struct GNUNET_SCHEDULER_TaskContext *tc)
203{ 204{
204 struct GNUNET_NAT_Test *tst = cls; 205 struct GNUNET_NAT_Test *tst = cls;
205 uint16_t data; 206 uint16_t data;
@@ -214,7 +215,7 @@ do_udp_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
214 GNUNET_NETWORK_socket_recv (tst->lsock, &data, sizeof (data)))) 215 GNUNET_NETWORK_socket_recv (tst->lsock, &data, sizeof (data))))
215 { 216 {
216 if (data == tst->data) 217 if (data == tst->data)
217 tst->report (tst->report_cls, GNUNET_OK); 218 tst->report (tst->report_cls, GNUNET_OK, NULL);
218 else 219 else
219 LOG (GNUNET_ERROR_TYPE_DEBUG, 220 LOG (GNUNET_ERROR_TYPE_DEBUG,
220 "Received data mismatches expected value\n"); 221 "Received data mismatches expected value\n");
@@ -249,10 +250,10 @@ do_read (void *cls,
249 GNUNET_NETWORK_socket_recv (na->sock, &data, sizeof (data)))) 250 GNUNET_NETWORK_socket_recv (na->sock, &data, sizeof (data))))
250 { 251 {
251 if (data == tst->data) 252 if (data == tst->data)
252 tst->report (tst->report_cls, GNUNET_OK); 253 tst->report (tst->report_cls, GNUNET_OK, NULL);
253 else 254 else
254 LOG (GNUNET_ERROR_TYPE_DEBUG, 255 LOG (GNUNET_ERROR_TYPE_DEBUG,
255 "Received data mismatches expected value\n"); 256 "Received data does not match expected value\n");
256 } 257 }
257 else 258 else
258 LOG (GNUNET_ERROR_TYPE_DEBUG, 259 LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -295,8 +296,9 @@ do_accept (void *cls,
295 wl->sock = s; 296 wl->sock = s;
296 wl->h = tst; 297 wl->h = tst;
297 wl->rtask = 298 wl->rtask =
298 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, wl->sock, 299 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
299 &do_read, wl); 300 wl->sock,
301 &do_read, wl);
300 GNUNET_CONTAINER_DLL_insert (tst->na_head, tst->na_tail, wl); 302 GNUNET_CONTAINER_DLL_insert (tst->na_head, tst->na_tail, wl);
301} 303}
302 304
@@ -331,7 +333,8 @@ addr_cb (void *cls,
331 GNUNET_a2s (addr, addrlen)); 333 GNUNET_a2s (addr, addrlen));
332 return; /* ignore IPv6 here */ 334 return; /* ignore IPv6 here */
333 } 335 }
334 LOG (GNUNET_ERROR_TYPE_DEBUG, "Asking gnunet-nat-server to connect to `%s'\n", 336 LOG (GNUNET_ERROR_TYPE_DEBUG,
337 "Asking gnunet-nat-server to connect to `%s'\n",
335 GNUNET_a2s (addr, addrlen)); 338 GNUNET_a2s (addr, addrlen));
336 sa = (const struct sockaddr_in *) addr; 339 sa = (const struct sockaddr_in *) addr;
337 msg.header.size = htons (sizeof (struct GNUNET_NAT_TestMessage)); 340 msg.header.size = htons (sizeof (struct GNUNET_NAT_TestMessage));
@@ -398,7 +401,7 @@ GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
398 ret->adv_port = adv_port; 401 ret->adv_port = adv_port;
399 ret->report = report; 402 ret->report = report;
400 ret->report_cls = report_cls; 403 ret->report_cls = report_cls;
401 if (bnd_port == 0) 404 if (0 == bnd_port)
402 { 405 {
403 ret->nat = 406 ret->nat =
404 GNUNET_NAT_register (cfg, is_tcp, 0, 0, NULL, NULL, &addr_cb, 407 GNUNET_NAT_register (cfg, is_tcp, 0, 0, NULL, NULL, &addr_cb,
diff --git a/src/nat/test_nat_mini.c b/src/nat/test_nat_mini.c
index c503a837a..6fe4fd5b9 100644
--- a/src/nat/test_nat_mini.c
+++ b/src/nat/test_nat_mini.c
@@ -42,12 +42,17 @@
42 * believes to be valid for the transport. 42 * believes to be valid for the transport.
43 */ 43 */
44static void 44static void
45addr_callback (void *cls, int add_remove, const struct sockaddr *addr, 45addr_callback (void *cls, int add_remove,
46 socklen_t addrlen) 46 const struct sockaddr *addr,
47 socklen_t addrlen,
48 const char *emsg)
47{ 49{
48 fprintf (stderr, "Address changed: %s `%s' (%u bytes)\n", 50 fprintf (stderr,
49 add_remove == GNUNET_YES ? "added" : "removed", GNUNET_a2s (addr, 51 "Address changed: %s `%s' (%u bytes)\n",
50 addrlen), 52 add_remove == GNUNET_YES
53 ? "added" : "removed",
54 GNUNET_a2s (addr,
55 addrlen),
51 (unsigned int) addrlen); 56 (unsigned int) addrlen);
52} 57}
53 58
@@ -76,7 +81,8 @@ run (void *cls, char *const *args, const char *cfgfile,
76 struct GNUNET_NAT_MiniHandle *mini; 81 struct GNUNET_NAT_MiniHandle *mini;
77 82
78 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 83 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
79 "Requesting NAT redirection for port %u...\n", PORT); 84 "Requesting NAT redirection for port %u...\n",
85 PORT);
80 mini = GNUNET_NAT_mini_map_start (PORT, GNUNET_YES /* tcp */ , 86 mini = GNUNET_NAT_mini_map_start (PORT, GNUNET_YES /* tcp */ ,
81 &addr_callback, NULL); 87 &addr_callback, NULL);
82 if (NULL == mini) 88 if (NULL == mini)
diff --git a/src/nat/test_nat_test.c b/src/nat/test_nat_test.c
index 752c8f145..64425ab47 100644
--- a/src/nat/test_nat_test.c
+++ b/src/nat/test_nat_test.c
@@ -47,8 +47,11 @@ end_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
47 GNUNET_NAT_test_stop (tst); 47 GNUNET_NAT_test_stop (tst);
48} 48}
49 49
50
50static void 51static void
51report_success (void *cls, int success) 52report_success (void *cls,
53 int success,
54 const char *emsg)
52{ 55{
53 GNUNET_assert (GNUNET_OK == success); 56 GNUNET_assert (GNUNET_OK == success);
54 ret = 0; 57 ret = 0;
@@ -56,6 +59,7 @@ report_success (void *cls, int success)
56 end = GNUNET_SCHEDULER_add_now (&end_test, NULL); 59 end = GNUNET_SCHEDULER_add_now (&end_test, NULL);
57} 60}
58 61
62
59/** 63/**
60 * Main function run with scheduler. 64 * Main function run with scheduler.
61 */ 65 */
@@ -64,7 +68,8 @@ run (void *cls, char *const *args, const char *cfgfile,
64 const struct GNUNET_CONFIGURATION_Handle *cfg) 68 const struct GNUNET_CONFIGURATION_Handle *cfg)
65{ 69{
66 tst = 70 tst =
67 GNUNET_NAT_test_start (cfg, GNUNET_YES, 1285, 1285, &report_success, 71 GNUNET_NAT_test_start (cfg, GNUNET_YES, 1285, 1285,
72 &report_success,
68 NULL); 73 NULL);
69 if (NULL == tst) 74 if (NULL == tst)
70 return; 75 return;
@@ -100,10 +105,12 @@ main (int argc, char *const argv[])
100 return 0; 105 return 0;
101 } 106 }
102 107
103 gns = 108 gns = GNUNET_OS_start_process (GNUNET_YES,
104 GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "gnunet-nat-server", 109 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
105 "gnunet-nat-server", 110 NULL, NULL, "gnunet-nat-server",
106 "-c", "test_nat_test_data.conf", "12345", NULL); 111 "gnunet-nat-server",
112 "-c", "test_nat_test_data.conf",
113 "12345", NULL);
107 GNUNET_assert (NULL != gns); 114 GNUNET_assert (NULL != gns);
108 GNUNET_PROGRAM_run (3, argv_prog, "test-nat-test", "nohelp", options, &run, 115 GNUNET_PROGRAM_run (3, argv_prog, "test-nat-test", "nohelp", options, &run,
109 NULL); 116 NULL);
@@ -111,7 +118,8 @@ main (int argc, char *const argv[])
111 GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (gns)); 118 GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (gns));
112 GNUNET_OS_process_destroy (gns); 119 GNUNET_OS_process_destroy (gns);
113 if (0 != ret) 120 if (0 != ret)
114 fprintf (stderr, "NAT test failed to report success\n"); 121 fprintf (stderr,
122 "NAT test failed to report success\n");
115 return ret; 123 return ret;
116} 124}
117 125