diff options
author | Christian Grothoff <christian@grothoff.org> | 2015-10-07 10:11:29 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2015-10-07 10:11:29 +0000 |
commit | 6c83690184e6f258e61d8187ad5999f4f87f2e49 (patch) | |
tree | e64f62d92cd88b0fe5e663b1671934bd8f45f778 /src/nat | |
parent | c787d89df7c64eceb6145b0a8847736641ea73ca (diff) | |
download | gnunet-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.c | 74 | ||||
-rw-r--r-- | src/nat/nat_stun.c | 91 |
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 | */ |
1119 | static void | 1123 | static void |
1120 | stun_request_callback (void *cls, | 1124 | stun_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, | |||
154 | static const char * | 154 | static const char * |
155 | stun_msg2str(int msg) | 155 | stun_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 | */ |
203 | static const char * | 209 | static const char * |
204 | stun_attr2str(int msg) | 210 | stun_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 | */ |
244 | static void | 253 | static void |
245 | generate_request_id(struct stun_header *req) | 254 | generate_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 | */ |
422 | static void | 430 | void |
423 | clean (struct GNUNET_NAT_STUN_Handle *handle) | 431 | GNUNET_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 | */ |
508 | int | 527 | struct GNUNET_NAT_STUN_Handle * |
509 | GNUNET_NAT_stun_make_request (const char *server, | 528 | GNUNET_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 */ | ||