X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fnat%2Fnat.c;h=dd63224c0a425890bc9904a7a3d4e2c91f175af3;hb=70466ec3c34f9a920e9e798e3169f886e9486a59;hp=fc20fe54d25f7d2bfcdbed7ab6de0b9c6b718318;hpb=00a7f964e0696b80455fa8e0d217f29762f490c1;p=oweals%2Fgnunet.git diff --git a/src/nat/nat.c b/src/nat/nat.c index fc20fe54d..dd63224c0 100644 --- a/src/nat/nat.c +++ b/src/nat/nat.c @@ -31,6 +31,8 @@ #include "gnunet_nat_lib.h" #include "nat.h" +#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__) + /** * How often do we scan for changes in our IP address from our local * interfaces? @@ -332,6 +334,11 @@ struct GNUNET_NAT_Handle */ int use_localaddresses; + /** + * Should we return local addresses to clients + */ + int return_localaddress; + /** * Should we do a DNS lookup of our hostname to find out our own IP? */ @@ -415,12 +422,8 @@ add_to_address_list_as_is (struct GNUNET_NAT_Handle *h, lal->addrlen = arg_size; lal->source = src; GNUNET_CONTAINER_DLL_insert (h->lal_head, h->lal_tail, lal); -#if DEBUG_NAT - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "nat", - "Adding address `%s' from source %d\n", GNUNET_a2s (arg, - arg_size), - src); -#endif + LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding address `%s' from source %d\n", + GNUNET_a2s (arg, arg_size), src); if (NULL != h->address_callback) h->address_callback (h->callback_cls, GNUNET_YES, arg, arg_size); } @@ -624,12 +627,16 @@ process_hostname_ip (void *cls, const struct sockaddr *addr, socklen_t addrlen) * @param name name of the interface * @param isDefault do we think this may be our default interface * @param addr address of the interface + * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned) + * @param netmask the network mask (can be NULL for unknown or unassigned)) * @param addrlen number of bytes in addr * @return GNUNET_OK to continue iterating */ static int process_interfaces (void *cls, const char *name, int isDefault, - const struct sockaddr *addr, socklen_t addrlen) + const struct sockaddr *addr, + const struct sockaddr *broadcast_addr, + const struct sockaddr *netmask, socklen_t addrlen) { struct GNUNET_NAT_Handle *h = cls; const struct sockaddr_in *s4; @@ -642,9 +649,20 @@ process_interfaces (void *cls, const char *name, int isDefault, case AF_INET: s4 = (struct sockaddr_in *) addr; ip = &s4->sin_addr; + + /* Check if address is in 127.0.0.0/8 */ + uint32_t address = ntohl ((uint32_t) (s4->sin_addr.s_addr)); + uint32_t value = (address & 0xFF000000) ^ 0x7F000000; + + if ((h->return_localaddress == GNUNET_NO) && (value == 0)) + { + return GNUNET_OK; + } if (GNUNET_YES == h->use_localaddresses) + { add_ip_to_address_list (h, LAL_INTERFACE_ADDRESS, &s4->sin_addr, sizeof (struct in_addr)); + } break; case AF_INET6: s6 = (struct sockaddr_in6 *) addr; @@ -653,10 +671,17 @@ process_interfaces (void *cls, const char *name, int isDefault, /* skip link local addresses */ return GNUNET_OK; } + if ((h->return_localaddress == GNUNET_NO) && + (IN6_IS_ADDR_LOOPBACK (&((struct sockaddr_in6 *) addr)->sin6_addr))) + { + return GNUNET_OK; + } ip = &s6->sin6_addr; if (GNUNET_YES == h->use_localaddresses) + { add_ip_to_address_list (h, LAL_INTERFACE_ADDRESS, &s6->sin6_addr, sizeof (struct in6_addr)); + } break; default: GNUNET_break (0); @@ -723,25 +748,18 @@ nat_server_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_DISK_file_read (h->server_stdout_handle, mybuf, sizeof (mybuf)); if (bytes < 1) { -#if DEBUG_NAT - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "nat", - "Finished reading from server stdout with code: %d\n", - bytes); -#endif + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Finished reading from server stdout with code: %d\n", bytes); if (0 != GNUNET_OS_process_kill (h->server_proc, SIGTERM)) - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, "nat", "kill"); GNUNET_OS_process_wait (h->server_proc); - GNUNET_OS_process_close (h->server_proc); + GNUNET_OS_process_destroy (h->server_proc); h->server_proc = NULL; GNUNET_DISK_pipe_close (h->server_stdout); h->server_stdout = NULL; h->server_stdout_handle = NULL; /* now try to restart it */ - h->server_retry_delay = - GNUNET_TIME_relative_multiply (h->server_retry_delay, 2); - h->server_retry_delay = - GNUNET_TIME_relative_max (GNUNET_TIME_UNIT_HOURS, - h->server_retry_delay); + h->server_retry_delay = GNUNET_TIME_STD_BACKOFF (h->server_retry_delay); h->server_read_task = GNUNET_SCHEDULER_add_delayed (h->server_retry_delay, &restart_nat_server, h); @@ -769,14 +787,13 @@ nat_server_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) #if HAVE_SOCKADDR_IN_SIN_LEN sin_addr.sin_len = sizeof (sin_addr); #endif - if ((NULL == port_start) || (1 != sscanf (port_start, "%d", &port)) || + if ((NULL == port_start) || (1 != SSCANF (port_start, "%d", &port)) || (-1 == inet_pton (AF_INET, mybuf, &sin_addr.sin_addr))) { /* should we restart gnunet-helper-nat-server? */ - GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "nat", - _ - ("gnunet-helper-nat-server generated malformed address `%s'\n"), - mybuf); + LOG (GNUNET_ERROR_TYPE_WARNING, "nat", + _("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, @@ -784,10 +801,8 @@ nat_server_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) return; } sin_addr.sin_port = htons ((uint16_t) port); -#if DEBUG_NAT - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "nat", - "gnunet-helper-nat-server read: %s:%d\n", mybuf, port); -#endif + LOG (GNUNET_ERROR_TYPE_DEBUG, "gnunet-helper-nat-server read: %s:%d\n", mybuf, + port); h->reversal_callback (h->callback_cls, (const struct sockaddr *) &sin_addr, sizeof (sin_addr)); h->server_read_task = @@ -806,26 +821,28 @@ nat_server_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) static void start_gnunet_nat_server (struct GNUNET_NAT_Handle *h) { + char *binary; + if ((h->behind_nat == GNUNET_YES) && (h->enable_nat_server == GNUNET_YES) && (h->internal_address != NULL) && (NULL != (h->server_stdout = - GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES)))) + GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES)))) { -#if DEBUG_NAT - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "nat" "Starting %s at `%s'\n", - "gnunet-helper-nat-server", h->internal_address); -#endif + LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting `%s' at `%s'\n", + "gnunet-helper-nat-server", h->internal_address); /* Start the server process */ + binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server"); h->server_proc = - GNUNET_OS_start_process (NULL, h->server_stdout, - "gnunet-helper-nat-server", + GNUNET_OS_start_process (GNUNET_NO, 0, NULL, h->server_stdout, + binary, "gnunet-helper-nat-server", h->internal_address, NULL); + GNUNET_free (binary); if (h->server_proc == NULL) { - GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "nat", - _("Failed to start %s\n"), "gnunet-helper-nat-server"); + LOG (GNUNET_ERROR_TYPE_WARNING, "nat", _("Failed to start %s\n"), + "gnunet-helper-nat-server"); GNUNET_DISK_pipe_close (h->server_stdout); h->server_stdout = NULL; } @@ -1053,12 +1070,11 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, int is_tcp, struct GNUNET_NAT_Handle *h; struct in_addr in_addr; unsigned int i; + char *binary; -#if DEBUG_NAT - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "nat", - "Registered with NAT service at port %u with %u IP bound local addresses\n", - (unsigned int) adv_port, num_addrs); -#endif + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Registered with NAT service at port %u with %u IP bound local addresses\n", + (unsigned int) adv_port, num_addrs); h = GNUNET_malloc (sizeof (struct GNUNET_NAT_Handle)); h->server_retry_delay = GNUNET_TIME_UNIT_SECONDS; h->cfg = cfg; @@ -1092,9 +1108,9 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, int is_tcp, if ((h->internal_address != NULL) && (inet_pton (AF_INET, h->internal_address, &in_addr) != 1)) { - GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "nat", - _("Malformed %s `%s' given in configuration!\n"), - "INTERNAL_ADDRESS", h->internal_address); + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, + "nat", "INTERNAL_ADDRESS", + _("malformed")); GNUNET_free (h->internal_address); h->internal_address = NULL; } @@ -1111,13 +1127,17 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, int is_tcp, h->nat_punched = GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "PUNCHED_NAT"); h->enable_nat_client = - GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "ENABLE_NAT_CLIENT"); + GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "ENABLE_ICMP_CLIENT"); h->enable_nat_server = - GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "ENABLE_NAT_SERVER"); + GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "ENABLE_ICMP_SERVER"); h->enable_upnp = GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "ENABLE_UPNP"); h->use_localaddresses = GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "USE_LOCALADDR"); + h->return_localaddress = + GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", + "RETURN_LOCAL_ADDRESSES"); + h->use_hostname = GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "USE_HOSTNAME"); h->disable_ipv6 = @@ -1148,27 +1168,30 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, int is_tcp, } /* Test for SUID binaries */ + binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server"); if ((h->behind_nat == GNUNET_YES) && (GNUNET_YES == h->enable_nat_server) && (GNUNET_YES != - GNUNET_OS_check_helper_binary ("gnunet-helper-nat-server"))) + GNUNET_OS_check_helper_binary (binary))) { h->enable_nat_server = GNUNET_NO; - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ - ("Configuration requires `%s', but binary is not installed properly (SUID bit not set). Option disabled.\n"), - "gnunet-helper-nat-server"); + LOG (GNUNET_ERROR_TYPE_WARNING, + _ + ("Configuration requires `%s', but binary is not installed properly (SUID bit not set). Option disabled.\n"), + "gnunet-helper-nat-server"); } + GNUNET_free (binary); + binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client"); if ((GNUNET_YES == h->enable_nat_client) && (GNUNET_YES != - GNUNET_OS_check_helper_binary ("gnunet-helper-nat-client"))) + GNUNET_OS_check_helper_binary (binary))) { h->enable_nat_client = GNUNET_NO; - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ - ("Configuration requires `%s', but binary is not installed properly (SUID bit not set). Option disabled.\n"), - "gnunet-helper-nat-client"); + LOG (GNUNET_ERROR_TYPE_WARNING, + _ + ("Configuration requires `%s', but binary is not installed properly (SUID bit not set). Option disabled.\n"), + "gnunet-helper-nat-client"); } - + GNUNET_free (binary); start_gnunet_nat_server (h); /* FIXME: add support for UPnP, etc */ @@ -1242,9 +1265,9 @@ GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h) if (NULL != h->server_proc) { if (0 != GNUNET_OS_process_kill (h->server_proc, SIGTERM)) - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, "nat", "kill"); GNUNET_OS_process_wait (h->server_proc); - GNUNET_OS_process_close (h->server_proc); + GNUNET_OS_process_destroy (h->server_proc); h->server_proc = NULL; GNUNET_DISK_pipe_close (h->server_stdout); h->server_stdout = NULL; @@ -1279,49 +1302,54 @@ GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h) * gnunet-helper-nat-client to send dummy ICMP responses to cause * that peer to connect to us (connection reversal). * - * @param h NAT handle for us (largely used for configuration) - * @param sa the address of the peer (IPv4-only) + * @return GNUNET_SYSERR on error, GNUNET_NO if nat client is disabled, + * GNUNET_OK otherwise */ -void +int GNUNET_NAT_run_client (struct GNUNET_NAT_Handle *h, const struct sockaddr_in *sa) + + { char inet4[INET_ADDRSTRLEN]; char port_as_string[6]; struct GNUNET_OS_Process *proc; + char *binary; if (GNUNET_YES != h->enable_nat_client) - return; /* not permitted / possible */ + return GNUNET_NO; /* not permitted / possible */ if (h->internal_address == NULL) { - GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "nat", - _ - ("Internal IP address not known, cannot use ICMP NAT traversal method\n")); - return; + LOG (GNUNET_ERROR_TYPE_WARNING, "nat", + _ + ("Internal IP address not known, cannot use ICMP NAT traversal method\n")); + return GNUNET_SYSERR; } GNUNET_assert (sa->sin_family == AF_INET); if (NULL == inet_ntop (AF_INET, &sa->sin_addr, inet4, INET_ADDRSTRLEN)) { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "inet_ntop"); - return; + GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, "nat", "inet_ntop"); + return GNUNET_SYSERR; } GNUNET_snprintf (port_as_string, sizeof (port_as_string), "%d", h->adv_port); -#if DEBUG_NAT - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "nat", - _("Running gnunet-helper-nat-client %s %s %u\n"), - h->internal_address, inet4, (unsigned int) h->adv_port); -#endif + LOG (GNUNET_ERROR_TYPE_DEBUG, + _("Running gnunet-helper-nat-client %s %s %u\n"), h->internal_address, + inet4, (unsigned int) h->adv_port); + binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client"); proc = - GNUNET_OS_start_process (NULL, NULL, "gnunet-helper-nat-client", + GNUNET_OS_start_process (GNUNET_NO, 0, NULL, NULL, + binary, "gnunet-helper-nat-client", h->internal_address, inet4, port_as_string, NULL); + GNUNET_free (binary); if (NULL == proc) - return; + return GNUNET_SYSERR; /* we know that the gnunet-helper-nat-client will terminate virtually * instantly */ GNUNET_OS_process_wait (proc); - GNUNET_OS_process_close (proc); + GNUNET_OS_process_destroy (proc); + return GNUNET_OK; } @@ -1372,8 +1400,8 @@ GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *h, const void *addr, } pos = pos->next; } - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Asked to validate one of my addresses and validation failed!\n"); + LOG (GNUNET_ERROR_TYPE_WARNING, + "Asked to validate one of my addresses and validation failed!\n"); return GNUNET_NO; }