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/nat_stun.c | |
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/nat_stun.c')
-rw-r--r-- | src/nat/nat_stun.c | 91 |
1 files changed, 56 insertions, 35 deletions
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 */ | ||