From 60c6dfd1fe22a01a3f7723e7e2bb18d52895c527 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 2 Jan 2017 20:13:38 +0100 Subject: [PATCH] fixes for starting and stopping gnunet-helper-nat-server --- src/nat/gnunet-helper-nat-server.c | 115 +++++++++++++++++++++------- src/nat/gnunet-service-nat.c | 89 +++++++++++++-------- src/nat/gnunet-service-nat_helper.c | 65 ++++++++-------- 3 files changed, 175 insertions(+), 94 deletions(-) diff --git a/src/nat/gnunet-helper-nat-server.c b/src/nat/gnunet-helper-nat-server.c index 8c3df749d..ef8e97482 100644 --- a/src/nat/gnunet-helper-nat-server.c +++ b/src/nat/gnunet-helper-nat-server.c @@ -264,8 +264,11 @@ send_icmp_echo (const struct in_addr *my_ip) ip_pkt.src_ip = my_ip->s_addr; ip_pkt.dst_ip = dummy.s_addr; ip_pkt.checksum = - htons (calc_checksum ((uint16_t *) & ip_pkt, sizeof (struct ip_header))); - memcpy (&packet[off], &ip_pkt, sizeof (struct ip_header)); + htons (calc_checksum ((uint16_t *) & ip_pkt, + sizeof (struct ip_header))); + memcpy (&packet[off], + &ip_pkt, + sizeof (struct ip_header)); off += sizeof (struct ip_header); icmp_echo.type = ICMP_ECHO; @@ -273,9 +276,12 @@ send_icmp_echo (const struct in_addr *my_ip) icmp_echo.checksum = 0; icmp_echo.reserved = 0; icmp_echo.checksum = - htons (calc_checksum - ((uint16_t *) & icmp_echo, sizeof (struct icmp_echo_header))); - memcpy (&packet[off], &icmp_echo, sizeof (struct icmp_echo_header)); + htons (calc_checksum + ((uint16_t *) & icmp_echo, + sizeof (struct icmp_echo_header))); + memcpy (&packet[off], + &icmp_echo, + sizeof (struct icmp_echo_header)); off += sizeof (struct icmp_echo_header); memset (&dst, 0, sizeof (dst)); @@ -284,17 +290,24 @@ send_icmp_echo (const struct in_addr *my_ip) dst.sin_len = sizeof (struct sockaddr_in); #endif dst.sin_addr = dummy; - err = - sendto (rawsock, packet, off, 0, (struct sockaddr *) &dst, sizeof (dst)); + err = sendto (rawsock, + packet, + off, + 0, + (struct sockaddr *) &dst, + sizeof (dst)); if (err < 0) { #if VERBOSE - fprintf (stderr, "sendto failed: %s\n", strerror (errno)); + fprintf (stderr, + "sendto failed: %s\n", + strerror (errno)); #endif } else if (sizeof (packet) != err) { - fprintf (stderr, "Error: partial send of ICMP message\n"); + fprintf (stderr, + "Error: partial send of ICMP message\n"); } } @@ -315,16 +328,24 @@ send_udp () #endif dst.sin_addr = dummy; dst.sin_port = htons (NAT_TRAV_PORT); - err = sendto (udpsock, NULL, 0, 0, (struct sockaddr *) &dst, sizeof (dst)); + err = sendto (udpsock, + NULL, + 0, + 0, + (struct sockaddr *) &dst, + sizeof (dst)); if (err < 0) { #if VERBOSE - fprintf (stderr, "sendto failed: %s\n", strerror (errno)); + fprintf (stderr, + "sendto failed: %s\n", + strerror (errno)); #endif } else if (0 != err) { - fprintf (stderr, "Error: partial send of ICMP message\n"); + fprintf (stderr, + "Error: partial send of ICMP message\n"); } } @@ -348,11 +369,15 @@ process_icmp_response () have = read (icmpsock, buf, sizeof (buf)); if (-1 == have) { - fprintf (stderr, "Error reading raw socket: %s\n", strerror (errno)); + fprintf (stderr, + "Error reading raw socket: %s\n", + strerror (errno)); return; } #if VERBOSE - fprintf (stderr, "Received message of %u bytes\n", (unsigned int) have); + fprintf (stderr, + "Received message of %u bytes\n", + (unsigned int) have); #endif if (have < (ssize_t) (sizeof (struct ip_header) + @@ -433,15 +458,27 @@ setup_raw_socket () const int one = 1; if (-1 == - setsockopt (rawsock, SOL_SOCKET, SO_BROADCAST, (char *) &one, sizeof (one))) + setsockopt (rawsock, + SOL_SOCKET, + SO_BROADCAST, + (char *) &one, + sizeof (one))) { - fprintf (stderr, "setsockopt failed: %s\n", strerror (errno)); + fprintf (stderr, + "setsockopt failed: %s\n", + strerror (errno)); return -1; } if (-1 == - setsockopt (rawsock, IPPROTO_IP, IP_HDRINCL, (char *) &one, sizeof (one))) + setsockopt (rawsock, + IPPROTO_IP, + IP_HDRINCL, + (char *) &one, + sizeof (one))) { - fprintf (stderr, "setsockopt failed: %s\n", strerror (errno)); + fprintf (stderr, + "setsockopt failed: %s\n", + strerror (errno)); return -1; } return 0; @@ -492,7 +529,8 @@ make_udp_socket (const struct in_addr *my_ip) int -main (int argc, char *const *argv) +main (int argc, + char *const *argv) { struct in_addr external; fd_set rs; @@ -504,11 +542,15 @@ main (int argc, char *const *argv) int global_ret; /* Create an ICMP raw socket for reading (we'll check errors later) */ - icmpsock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); + icmpsock = socket (AF_INET, + SOCK_RAW, + IPPROTO_ICMP); icmp_eno = errno; /* Create an (ICMP) raw socket for writing (we'll check errors later) */ - rawsock = socket (AF_INET, SOCK_RAW, IPPROTO_RAW); + rawsock = socket (AF_INET, + SOCK_RAW, + IPPROTO_RAW); raw_eno = errno; udpsock = -1; @@ -517,14 +559,18 @@ main (int argc, char *const *argv) #ifdef HAVE_SETRESUID if (0 != setresuid (uid, uid, uid)) { - fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); + fprintf (stderr, + "Failed to setresuid: %s\n", + strerror (errno)); global_ret = 1; goto error_exit; } #else if (0 != (setuid (uid) | seteuid (uid))) { - fprintf (stderr, "Failed to setuid: %s\n", strerror (errno)); + fprintf (stderr, + "Failed to setuid: %s\n", + strerror (errno)); global_ret = 2; goto error_exit; } @@ -540,13 +586,16 @@ main (int argc, char *const *argv) } if (1 != inet_pton (AF_INET, argv[1], &external)) { - fprintf (stderr, "Error parsing IPv4 address: %s\n", strerror (errno)); + fprintf (stderr, + "Error parsing IPv4 address: %s\n", + strerror (errno)); global_ret = 4; goto error_exit; } if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy)) { - fprintf (stderr, "Internal error converting dummy IP to binary.\n"); + fprintf (stderr, + "Internal error converting dummy IP to binary.\n"); global_ret = 5; goto error_exit; } @@ -554,7 +603,9 @@ main (int argc, char *const *argv) /* error checking icmpsock */ if (-1 == icmpsock) { - fprintf (stderr, "Error opening RAW socket: %s\n", strerror (icmp_eno)); + fprintf (stderr, + "Error opening RAW socket: %s\n", + strerror (icmp_eno)); global_ret = 6; goto error_exit; } @@ -562,7 +613,9 @@ main (int argc, char *const *argv) { /* this could happen if we were started with a large number of already-open file descriptors... */ - fprintf (stderr, "Socket number too large (%d > %u)\n", icmpsock, + fprintf (stderr, + "Socket number too large (%d > %u)\n", + icmpsock, (unsigned int) FD_SETSIZE); global_ret = 7; goto error_exit; @@ -571,7 +624,9 @@ main (int argc, char *const *argv) /* error checking rawsock */ if (-1 == rawsock) { - fprintf (stderr, "Error opening RAW socket: %s\n", strerror (raw_eno)); + fprintf (stderr, + "Error opening RAW socket: %s\n", + strerror (raw_eno)); global_ret = 8; goto error_exit; } @@ -601,7 +656,9 @@ main (int argc, char *const *argv) { if (errno == EINTR) continue; - fprintf (stderr, "select failed: %s\n", strerror (errno)); + fprintf (stderr, + "select failed: %s\n", + strerror (errno)); break; } if (1 == getppid ()) /* Check the parent process id, if 1 the parent has died, so we should die too */ diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c index f432eca18..e29f37108 100644 --- a/src/nat/gnunet-service-nat.c +++ b/src/nat/gnunet-service-nat.c @@ -395,6 +395,31 @@ static struct GNUNET_NAT_ExternalHandle *probe_external_ip_op; static struct in_addr mini_external_ipv4; +/** + * Remove and free an entry from the #lal_head DLL. + * + * @param lal entry to free + */ +static void +free_lal (struct LocalAddressList *lal) +{ + GNUNET_CONTAINER_DLL_remove (lal_head, + lal_tail, + lal); + if (NULL != lal->hc) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Lost NATed local address %s, stopping NAT server\n", + GNUNET_a2s ((const struct sockaddr *) &lal->addr, + sizeof (struct sockaddr_in))); + + GN_stop_gnunet_nat_server_ (lal->hc); + lal->hc = NULL; + } + GNUNET_free (lal); +} + + /** * Free the DLL starting at #lal_head. */ @@ -404,17 +429,7 @@ destroy_lal () struct LocalAddressList *lal; while (NULL != (lal = lal_head)) - { - GNUNET_CONTAINER_DLL_remove (lal_head, - lal_tail, - lal); - if (NULL != lal->hc) - { - GN_stop_gnunet_nat_server_ (lal->hc); - lal->hc = NULL; - } - GNUNET_free (lal); - } + free_lal (lal); } @@ -1099,6 +1114,7 @@ run_scan (void *cls) struct IfcProcContext ifc_ctx; int found; int have_nat; + struct LocalAddressList *lnext; scan_task = GNUNET_SCHEDULER_add_delayed (SCAN_FREQ, &run_scan, @@ -1111,8 +1127,9 @@ run_scan (void *cls) /* remove addresses that disappeared */ for (struct LocalAddressList *lal = lal_head; NULL != lal; - lal = lal->next) + lal = lnext) { + lnext = lal->next; found = GNUNET_NO; for (struct LocalAddressList *pos = ifc_ctx.lal_head; NULL != pos; @@ -1126,20 +1143,21 @@ run_scan (void *cls) : sizeof (struct sockaddr_in6))) ) { found = GNUNET_YES; - pos->hc = lal->hc; - lal->hc = NULL; } } if (GNUNET_NO == found) + { notify_clients (lal, GNUNET_NO); + free_lal (lal); + } } /* add addresses that appeared */ have_nat = GNUNET_NO; for (struct LocalAddressList *pos = ifc_ctx.lal_head; NULL != pos; - pos = pos->next) + pos = ifc_ctx.lal_head) { found = GNUNET_NO; if (GNUNET_NAT_AC_LAN == (GNUNET_NAT_AC_LAN & pos->ac)) @@ -1156,19 +1174,34 @@ run_scan (void *cls) : sizeof (struct sockaddr_in6))) ) found = GNUNET_YES; } - if (GNUNET_NO == found) + GNUNET_CONTAINER_DLL_remove (ifc_ctx.lal_head, + ifc_ctx.lal_tail, + pos); + if (GNUNET_YES == found) + { + GNUNET_free (pos); + } + else + { notify_clients (pos, GNUNET_YES); - if ( (AF_INET == pos->af) && - (NULL == pos->hc) && - (0 != (GNUNET_NAT_AC_LAN & pos->ac)) ) - { - const struct sockaddr_in *s4 - = (const struct sockaddr_in *) &pos->addr; - - pos->hc = GN_start_gnunet_nat_server_ (&s4->sin_addr, - &reversal_callback, - pos); + GNUNET_CONTAINER_DLL_insert (lal_head, + lal_tail, + pos); + if ( (AF_INET == pos->af) && + (NULL == pos->hc) && + (0 != (GNUNET_NAT_AC_LAN & pos->ac)) ) + { + const struct sockaddr_in *s4 + = (const struct sockaddr_in *) &pos->addr; + + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Found NATed local address %s, starting NAT server\n", + GNUNET_a2s ((void *) &pos->addr, sizeof (*s4))); + pos->hc = GN_start_gnunet_nat_server_ (&s4->sin_addr, + &reversal_callback, + pos); + } } } if ( (GNUNET_YES == have_nat) && @@ -1194,10 +1227,6 @@ run_scan (void *cls) probe_external_ip_op = NULL; } } - - destroy_lal (); - lal_head = ifc_ctx.lal_head; - lal_tail = ifc_ctx.lal_tail; } diff --git a/src/nat/gnunet-service-nat_helper.c b/src/nat/gnunet-service-nat_helper.c index febc3c2dd..7e5051d65 100644 --- a/src/nat/gnunet-service-nat_helper.c +++ b/src/nat/gnunet-service-nat_helper.c @@ -28,7 +28,6 @@ #include "gnunet_util_lib.h" #include "gnunet-service-nat_helper.h" -#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__) /** * Information we keep per NAT helper process. @@ -133,11 +132,11 @@ nat_server_read (void *cls) sizeof (mybuf)); if (bytes < 1) { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Finished reading from server stdout with code: %d\n", - bytes); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Finished reading from server stdout with code: %d\n", + bytes); if (0 != GNUNET_OS_process_kill (h->server_proc, -- GNUNET_TERM_SIG)) + GNUNET_TERM_SIG)) GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, "nat", "kill"); @@ -183,10 +182,9 @@ nat_server_read (void *cls) &sin_addr.sin_addr))) { /* should we restart gnunet-helper-nat-server? */ - LOG (GNUNET_ERROR_TYPE_WARNING, - "nat", - _("gnunet-helper-nat-server generated malformed address `%s'\n"), - mybuf); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("gnunet-helper-nat-server generated malformed address `%s'\n"), + mybuf); h->server_read_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, h->server_stdout_handle, @@ -195,10 +193,10 @@ nat_server_read (void *cls) return; } sin_addr.sin_port = htons ((uint16_t) port); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "gnunet-helper-nat-server read: %s:%d\n", - mybuf, - port); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "gnunet-helper-nat-server read: %s:%d\n", + mybuf, + port); h->cb (h->cb_cls, &sin_addr); h->server_read_task @@ -238,10 +236,10 @@ restart_nat_server (void *cls) &h->internal_address, ia, sizeof (ia))); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Starting `%s' at `%s'\n", - "gnunet-helper-nat-server", - ia); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting `%s' at `%s'\n", + "gnunet-helper-nat-server", + ia); /* Start the server process */ binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server"); @@ -258,10 +256,9 @@ restart_nat_server (void *cls) GNUNET_free (binary); if (NULL == h->server_proc) { - LOG (GNUNET_ERROR_TYPE_WARNING, - "nat", - _("Failed to start %s\n"), - "gnunet-helper-nat-server"); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Failed to start %s\n"), + "gnunet-helper-nat-server"); GNUNET_DISK_pipe_close (h->server_stdout); h->server_stdout = NULL; try_again (h); @@ -301,6 +298,7 @@ GN_start_gnunet_nat_server_ (const struct in_addr *internal_address, h->cb = cb; h->cb_cls = cb_cls; h->internal_address = *internal_address; + restart_nat_server (h); if (NULL == h->server_stdout) { GN_stop_gnunet_nat_server_ (h); @@ -328,9 +326,8 @@ GN_stop_gnunet_nat_server_ (struct HelperContext *h) { if (0 != GNUNET_OS_process_kill (h->server_proc, GNUNET_TERM_SIG)) - GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, - "nat", - "kill"); + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, + "kill"); GNUNET_OS_process_wait (h->server_proc); GNUNET_OS_process_destroy (h->server_proc); h->server_proc = NULL; @@ -375,9 +372,8 @@ GN_request_connection_reversal (const struct in_addr *internal_address, intv4, INET_ADDRSTRLEN)) { - GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, - "nat", - "inet_ntop"); + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, + "inet_ntop"); return GNUNET_SYSERR; } if (NULL == inet_ntop (AF_INET, @@ -385,20 +381,19 @@ GN_request_connection_reversal (const struct in_addr *internal_address, remv4, INET_ADDRSTRLEN)) { - GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, - "nat", - "inet_ntop"); + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, + "inet_ntop"); return GNUNET_SYSERR; } GNUNET_snprintf (port_as_string, sizeof (port_as_string), "%d", internal_port); - LOG (GNUNET_ERROR_TYPE_DEBUG, - _("Running gnunet-helper-nat-client %s %s %u\n"), - intv4, - remv4, - internal_port); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + _("Running gnunet-helper-nat-client %s %s %u\n"), + intv4, + remv4, + internal_port); binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client"); proc -- 2.25.1