aboutsummaryrefslogtreecommitdiff
path: root/src/nat
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-10-07 10:11:29 +0000
committerChristian Grothoff <christian@grothoff.org>2015-10-07 10:11:29 +0000
commit6c83690184e6f258e61d8187ad5999f4f87f2e49 (patch)
treee64f62d92cd88b0fe5e663b1671934bd8f45f778 /src/nat
parentc787d89df7c64eceb6145b0a8847736641ea73ca (diff)
downloadgnunet-6c83690184e6f258e61d8187ad5999f4f87f2e49.tar.gz
gnunet-6c83690184e6f258e61d8187ad5999f4f87f2e49.zip
enable clean up of NAT STUN state, prevents test_plugin_udp from segfaulting
Diffstat (limited to 'src/nat')
-rw-r--r--src/nat/nat.c74
-rw-r--r--src/nat/nat_stun.c91
2 files changed, 101 insertions, 64 deletions
diff --git a/src/nat/nat.c b/src/nat/nat.c
index 3573ec497..b0ec4fe19 100644
--- a/src/nat/nat.c
+++ b/src/nat/nat.c
@@ -270,17 +270,17 @@ struct GNUNET_NAT_Handle
270 /** 270 /**
271 * ID of select gnunet-helper-nat-server stdout read task 271 * ID of select gnunet-helper-nat-server stdout read task
272 */ 272 */
273 struct GNUNET_SCHEDULER_Task * server_read_task; 273 struct GNUNET_SCHEDULER_Task *server_read_task;
274 274
275 /** 275 /**
276 * ID of interface IP-scan task 276 * ID of interface IP-scan task
277 */ 277 */
278 struct GNUNET_SCHEDULER_Task * ifc_task; 278 struct GNUNET_SCHEDULER_Task *ifc_task;
279 279
280 /** 280 /**
281 * ID of hostname DNS lookup task 281 * ID of hostname DNS lookup task
282 */ 282 */
283 struct GNUNET_SCHEDULER_Task * hostname_task; 283 struct GNUNET_SCHEDULER_Task *hostname_task;
284 284
285 /** 285 /**
286 * ID of DynDNS lookup task 286 * ID of DynDNS lookup task
@@ -288,6 +288,11 @@ struct GNUNET_NAT_Handle
288 struct GNUNET_SCHEDULER_Task *dns_task; 288 struct GNUNET_SCHEDULER_Task *dns_task;
289 289
290 /** 290 /**
291 * Active STUN request, if any.
292 */
293 struct GNUNET_NAT_STUN_Handle *stun_request;
294
295 /**
291 * How often do we scan for changes in our IP address from our local 296 * How often do we scan for changes in our IP address from our local
292 * interfaces? 297 * interfaces?
293 */ 298 */
@@ -1109,12 +1114,11 @@ list_interfaces (void *cls,
1109} 1114}
1110 1115
1111 1116
1112
1113/** 1117/**
1114 * Callback if the STun request have a error 1118 * Callback with the result from the STUN request.
1115 * 1119 *
1116 * @param cls the NAT handle 1120 * @param cls the NAT handle
1117 * @param result , the status 1121 * @param result the status
1118 */ 1122 */
1119static void 1123static void
1120stun_request_callback (void *cls, 1124stun_request_callback (void *cls,
@@ -1122,14 +1126,15 @@ stun_request_callback (void *cls,
1122{ 1126{
1123 struct GNUNET_NAT_Handle *h = cls; 1127 struct GNUNET_NAT_Handle *h = cls;
1124 1128
1125 if (NULL == h) 1129 h->stun_request = NULL;
1126 return; 1130 if (GNUNET_NAT_ERROR_SUCCESS != result)
1127 h->waiting_stun = GNUNET_NO;
1128
1129 if(result != GNUNET_OK)
1130 { 1131 {
1131 LOG (GNUNET_ERROR_TYPE_WARNING, 1132 LOG (GNUNET_ERROR_TYPE_WARNING,
1132 "Error processing a STUN request"); 1133 "Error processing a STUN request");
1134 }
1135 else
1136 {
1137 h->waiting_stun = GNUNET_YES;
1133 } 1138 }
1134} 1139}
1135 1140
@@ -1153,7 +1158,7 @@ GNUNET_NAT_is_valid_stun_packet (void *cls,
1153 struct sockaddr_in answer; 1158 struct sockaddr_in answer;
1154 1159
1155 /* We are not expecting a STUN message */ 1160 /* We are not expecting a STUN message */
1156 if (! h->waiting_stun) 1161 if (GNUNET_YES != h->waiting_stun)
1157 return GNUNET_NO; 1162 return GNUNET_NO;
1158 1163
1159 /* We dont have STUN installed */ 1164 /* We dont have STUN installed */
@@ -1166,14 +1171,14 @@ GNUNET_NAT_is_valid_stun_packet (void *cls,
1166 sizeof(struct sockaddr_in)); 1171 sizeof(struct sockaddr_in));
1167 1172
1168 /*Lets handle the packet*/ 1173 /*Lets handle the packet*/
1169 int valid = GNUNET_NAT_stun_handle_packet (data, 1174 if (GNUNET_NO ==
1170 len, 1175 GNUNET_NAT_stun_handle_packet (data,
1171 &answer); 1176 len,
1172 if (! valid) 1177 &answer))
1173 return GNUNET_NO; 1178 return GNUNET_NO;
1174 1179
1175 LOG (GNUNET_ERROR_TYPE_INFO, 1180 LOG (GNUNET_ERROR_TYPE_INFO,
1176 "Stun server returned %s:%d\n", 1181 "STUN server returned %s:%d\n",
1177 inet_ntoa (answer.sin_addr), 1182 inet_ntoa (answer.sin_addr),
1178 ntohs (answer.sin_port)); 1183 ntohs (answer.sin_port));
1179 /* Remove old IPs from previous STUN calls */ 1184 /* Remove old IPs from previous STUN calls */
@@ -1208,16 +1213,19 @@ process_stun (void *cls,
1208 "I will request the stun server %s:%i\n", 1213 "I will request the stun server %s:%i\n",
1209 elem->address, 1214 elem->address,
1210 elem->port); 1215 elem->port);
1211 if (GNUNET_OK == 1216 if (NULL != h->stun_request)
1212 GNUNET_NAT_stun_make_request (elem->address, 1217 {
1218 GNUNET_NAT_stun_make_request_cancel (h->stun_request);
1219 h->stun_request = NULL;
1220 }
1221 h->waiting_stun = GNUNET_NO;
1222 h->stun_request
1223 = GNUNET_NAT_stun_make_request (elem->address,
1213 elem->port, 1224 elem->port,
1214 h->socket, 1225 h->socket,
1215 &stun_request_callback, 1226 &stun_request_callback,
1216 NULL)) 1227 h);
1217 { 1228 if (NULL == h->stun_request)
1218 h->waiting_stun = GNUNET_YES;
1219 }
1220 else
1221 { 1229 {
1222 LOG (GNUNET_ERROR_TYPE_ERROR, 1230 LOG (GNUNET_ERROR_TYPE_ERROR,
1223 "STUN request to %s:%i failed\n", 1231 "STUN request to %s:%i failed\n",
@@ -1226,7 +1234,8 @@ process_stun (void *cls,
1226 } 1234 }
1227 h->stun_task = 1235 h->stun_task =
1228 GNUNET_SCHEDULER_add_delayed (h->stun_frequency, 1236 GNUNET_SCHEDULER_add_delayed (h->stun_frequency,
1229 &process_stun, h); 1237 &process_stun,
1238 h);
1230 1239
1231 /* Set actual Server*/ 1240 /* Set actual Server*/
1232 if (NULL != elem->next) 1241 if (NULL != elem->next)
@@ -1709,7 +1718,6 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
1709 /* Set the actual STUN server*/ 1718 /* Set the actual STUN server*/
1710 h->actual_stun_server = h->stun_servers_head; 1719 h->actual_stun_server = h->stun_servers_head;
1711 } 1720 }
1712
1713 h->stun_task = GNUNET_SCHEDULER_add_now (&process_stun, 1721 h->stun_task = GNUNET_SCHEDULER_add_now (&process_stun,
1714 h); 1722 h);
1715 } 1723 }
@@ -1821,10 +1829,18 @@ GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h)
1821 GNUNET_SCHEDULER_cancel (h->stun_task); 1829 GNUNET_SCHEDULER_cancel (h->stun_task);
1822 h->stun_task = NULL; 1830 h->stun_task = NULL;
1823 } 1831 }
1832 if (NULL != h->stun_request)
1833 {
1834 GNUNET_NAT_stun_make_request_cancel (h->stun_request);
1835 h->stun_request = NULL;
1836 }
1824 if (NULL != h->server_proc) 1837 if (NULL != h->server_proc)
1825 { 1838 {
1826 if (0 != GNUNET_OS_process_kill (h->server_proc, GNUNET_TERM_SIG)) 1839 if (0 != GNUNET_OS_process_kill (h->server_proc,
1827 GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, "nat", "kill"); 1840 GNUNET_TERM_SIG))
1841 GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING,
1842 "nat",
1843 "kill");
1828 GNUNET_OS_process_wait (h->server_proc); 1844 GNUNET_OS_process_wait (h->server_proc);
1829 GNUNET_OS_process_destroy (h->server_proc); 1845 GNUNET_OS_process_destroy (h->server_proc);
1830 h->server_proc = NULL; 1846 h->server_proc = NULL;
diff --git a/src/nat/nat_stun.c b/src/nat/nat_stun.c
index 2ed78030f..e97b0016b 100644
--- a/src/nat/nat_stun.c
+++ b/src/nat/nat_stun.c
@@ -154,14 +154,20 @@ encode_message (enum StunClasses msg_class,
154static const char * 154static const char *
155stun_msg2str(int msg) 155stun_msg2str(int msg)
156{ 156{
157 static const struct { enum StunClasses value; const char *name; } classes[] = { 157 static const struct {
158 enum StunClasses value;
159 const char *name;
160 } classes[] = {
158 { STUN_REQUEST, "Request" }, 161 { STUN_REQUEST, "Request" },
159 { STUN_INDICATION, "Indication" }, 162 { STUN_INDICATION, "Indication" },
160 { STUN_RESPONSE, "Response" }, 163 { STUN_RESPONSE, "Response" },
161 { STUN_ERROR_RESPONSE, "Error Response" }, 164 { STUN_ERROR_RESPONSE, "Error Response" },
162 { 0, NULL } 165 { 0, NULL }
163 }; 166 };
164 static const struct { enum StunMethods value; const char *name; } methods[] = { 167 static const struct {
168 enum StunMethods value;
169 const char *name;
170 } methods[] = {
165 { STUN_BINDING, "Binding" }, 171 { STUN_BINDING, "Binding" },
166 { 0, NULL } 172 { 0, NULL }
167 }; 173 };
@@ -201,9 +207,12 @@ stun_msg2str(int msg)
201 * @return string with the attribute name 207 * @return string with the attribute name
202 */ 208 */
203static const char * 209static const char *
204stun_attr2str(int msg) 210stun_attr2str (int msg)
205{ 211{
206 const struct { enum StunAttributes value; const char *name; } attrs[] = { 212 static const struct {
213 enum StunAttributes value;
214 const char *name;
215 } attrs[] = {
207 { STUN_MAPPED_ADDRESS, "Mapped Address" }, 216 { STUN_MAPPED_ADDRESS, "Mapped Address" },
208 { STUN_RESPONSE_ADDRESS, "Response Address" }, 217 { STUN_RESPONSE_ADDRESS, "Response Address" },
209 { STUN_CHANGE_ADDRESS, "Change Address" }, 218 { STUN_CHANGE_ADDRESS, "Change Address" },
@@ -242,7 +251,7 @@ stun_attr2str(int msg)
242 * @param req, stun header to be filled 251 * @param req, stun header to be filled
243 */ 252 */
244static void 253static void
245generate_request_id(struct stun_header *req) 254generate_request_id (struct stun_header *req)
246{ 255{
247 unsigned int x; 256 unsigned int x;
248 257
@@ -292,7 +301,8 @@ stun_get_mapped (struct StunState *st,
292 default: 301 default:
293 return 1; 302 return 1;
294 } 303 }
295 if (ntohs(attr->len) < 8 && returned_addr->family != 1) 304 if ( (ntohs(attr->len) < 8) &&
305 (returned_addr->family != 1) )
296 { 306 {
297 return 1; 307 return 1;
298 } 308 }
@@ -371,10 +381,7 @@ GNUNET_NAT_stun_handle_packet (const void *data,
371 (int)len); 381 (int)len);
372 return GNUNET_NO; 382 return GNUNET_NO;
373 } 383 }
374 else 384 len = advertised_message_size;
375 {
376 len = advertised_message_size;
377 }
378 memset (&st,0, sizeof(st)); 385 memset (&st,0, sizeof(st));
379 386
380 while (len > 0) 387 while (len > 0)
@@ -415,15 +422,21 @@ GNUNET_NAT_stun_handle_packet (const void *data,
415 422
416 423
417/** 424/**
418 * Clean-up used memory 425 * Cancel active STUN request. Frees associated resources
426 * and ensures that the callback is no longer invoked.
419 * 427 *
420 * @param handle handle to release memory for 428 * @param rh request to cancel
421 */ 429 */
422static void 430void
423clean (struct GNUNET_NAT_STUN_Handle *handle) 431GNUNET_NAT_stun_make_request_cancel (struct GNUNET_NAT_STUN_Handle *rh)
424{ 432{
425 GNUNET_free (handle->stun_server); 433 if (NULL != rh->dns_active)
426 GNUNET_free (handle); 434 {
435 GNUNET_RESOLVER_request_cancel (rh->dns_active);
436 rh->dns_active = NULL;
437 }
438 GNUNET_free (rh->stun_server);
439 GNUNET_free (rh);
427} 440}
428 441
429 442
@@ -439,32 +452,35 @@ stun_dns_callback (void *cls,
439 const struct sockaddr *addr, 452 const struct sockaddr *addr,
440 socklen_t addrlen) 453 socklen_t addrlen)
441{ 454{
442 struct GNUNET_NAT_STUN_Handle *request = cls; 455 struct GNUNET_NAT_STUN_Handle *rh = cls;
443 struct stun_header *req; 456 struct stun_header *req;
444 uint8_t reqdata[1024]; 457 uint8_t reqdata[1024];
445 int reqlen; 458 int reqlen;
446 struct sockaddr_in server; 459 struct sockaddr_in server;
447 460
461 rh->dns_active = NULL;
448 if (NULL == addr) 462 if (NULL == addr)
449 { 463 {
450 request->dns_active = NULL; 464 if (GNUNET_NO == rh->dns_success)
451 if (GNUNET_NO == request->dns_success)
452 { 465 {
453 LOG (GNUNET_ERROR_TYPE_INFO, 466 LOG (GNUNET_ERROR_TYPE_INFO,
454 "Error resolving host %s\n", 467 "Error resolving host %s\n",
455 request->stun_server); 468 rh->stun_server);
456 request->cb (request->cb_cls, 469 rh->cb (rh->cb_cls,
457 GNUNET_NAT_ERROR_NOT_ONLINE); 470 GNUNET_NAT_ERROR_NOT_ONLINE);
458 clean (request); 471 GNUNET_NAT_stun_make_request_cancel (rh);
459 } 472 }
460 return; 473 return;
461 } 474 }
462 475
463 request->dns_success= GNUNET_YES; 476 rh->dns_success = GNUNET_YES;
464 memset(&server,0, sizeof(server)); 477 memset (&server,0, sizeof(server));
465 server.sin_family = AF_INET; 478 server.sin_family = AF_INET;
466 server.sin_addr = ((struct sockaddr_in *)addr)->sin_addr; 479 server.sin_addr = ((struct sockaddr_in *)addr)->sin_addr;
467 server.sin_port = htons(request->stun_port); 480 server.sin_port = htons(rh->stun_port);
481#if HAVE_SOCKADDR_IN_SIN_LEN
482 server.sin_len = (u_char) sizeof (struct sockaddr_in);
483#endif
468 484
469 /*Craft the simplest possible STUN packet. A request binding*/ 485 /*Craft the simplest possible STUN packet. A request binding*/
470 req = (struct stun_header *)reqdata; 486 req = (struct stun_header *)reqdata;
@@ -476,7 +492,7 @@ stun_dns_callback (void *cls,
476 req->msgtype = htons(encode_message(STUN_REQUEST, STUN_BINDING)); 492 req->msgtype = htons(encode_message(STUN_REQUEST, STUN_BINDING));
477 493
478 /* Send the packet */ 494 /* Send the packet */
479 if (-1 == GNUNET_NETWORK_socket_sendto (request->sock, 495 if (-1 == GNUNET_NETWORK_socket_sendto (rh->sock,
480 req, 496 req,
481 ntohs(req->msglen) + sizeof(*req), 497 ntohs(req->msglen) + sizeof(*req),
482 (const struct sockaddr *) &server, 498 (const struct sockaddr *) &server,
@@ -484,11 +500,14 @@ stun_dns_callback (void *cls,
484 { 500 {
485 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, 501 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
486 "Fail to sendto"); 502 "Fail to sendto");
487 request->cb (request->cb_cls, 503 rh->cb (rh->cb_cls,
488 GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR); 504 GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR);
489 clean (request); 505 GNUNET_NAT_stun_make_request_cancel (rh);
490 return; 506 return;
491 } 507 }
508 /* sending STUN request done, let's wait for replies... */
509 rh->cb (rh->cb_cls,
510 GNUNET_NAT_ERROR_SUCCESS);
492} 511}
493 512
494 513
@@ -503,9 +522,9 @@ stun_dns_callback (void *cls,
503 * @param sock the socket used to send the request 522 * @param sock the socket used to send the request
504 * @param cb callback in case of error 523 * @param cb callback in case of error
505 * @param cb_cls closure for @a cb 524 * @param cb_cls closure for @a cb
506 * @return #GNUNET_OK success, #GNUNET_NO on error. 525 * @return NULL on error
507 */ 526 */
508int 527struct GNUNET_NAT_STUN_Handle *
509GNUNET_NAT_stun_make_request (const char *server, 528GNUNET_NAT_stun_make_request (const char *server,
510 uint16_t port, 529 uint16_t port,
511 struct GNUNET_NETWORK_Handle *sock, 530 struct GNUNET_NETWORK_Handle *sock,
@@ -529,8 +548,10 @@ GNUNET_NAT_stun_make_request (const char *server,
529 { 548 {
530 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, 549 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
531 "Failed DNS"); 550 "Failed DNS");
532 clean (rh); 551 GNUNET_NAT_stun_make_request_cancel (rh);
533 return GNUNET_NO; 552 return NULL;
534 } 553 }
535 return GNUNET_OK; 554 return rh;
536} 555}
556
557/* end of nat_stun.c */