aboutsummaryrefslogtreecommitdiff
path: root/src/nat/nat_stun.c
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/nat_stun.c
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/nat_stun.c')
-rw-r--r--src/nat/nat_stun.c91
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,
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 */