- GNUNET_CONTAINER_DLL_insert (plugin->probe_head,
- plugin->probe_tail,
- tcp_probe_ctx);
- tcp_probe_ctx->transmit_handle
- = GNUNET_CONNECTION_notify_transmit_ready (sock,
- ntohs (tcp_probe_ctx->message.header.size),
- GNUNET_TIME_UNIT_FOREVER_REL,
- ¬ify_send_probe, tcp_probe_ctx);
-
- plugin->server_read_task =
- GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
- plugin->server_stdout_handle,
- &tcp_plugin_server_read,
- plugin);
-}
-
-
-/**
- * Start the gnunet-nat-server process for users behind NAT.
- *
- * @param plugin the transport plugin
- * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
- */
-static int
-tcp_transport_start_nat_server (struct Plugin *plugin)
-{
- if (plugin->internal_address == NULL)
- return GNUNET_SYSERR;
- plugin->server_stdout = GNUNET_DISK_pipe (GNUNET_YES,
- GNUNET_NO,
- GNUNET_YES);
- if (plugin->server_stdout == NULL)
- return GNUNET_SYSERR;
-#if DEBUG_TCP_NAT
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
- "tcp"
- "Starting %s %s\n", "gnunet-nat-server", plugin->internal_address);
-#endif
- /* Start the server process */
- plugin->server_proc = GNUNET_OS_start_process (NULL,
- plugin->server_stdout,
- "gnunet-nat-server",
- "gnunet-nat-server",
- plugin->internal_address,
- NULL);
- if (plugin->server_proc == NULL)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
- "tcp",
- _("Failed to start %s\n"),
- "gnunet-nat-server");
- GNUNET_DISK_pipe_close (plugin->server_stdout);
- plugin->server_stdout = NULL;
- return GNUNET_SYSERR;
- }
- /* Close the write end of the read pipe */
- GNUNET_DISK_pipe_close_end(plugin->server_stdout,
- GNUNET_DISK_PIPE_END_WRITE);
- plugin->server_stdout_handle
- = GNUNET_DISK_pipe_handle (plugin->server_stdout,
- GNUNET_DISK_PIPE_END_READ);
- plugin->server_read_task
- = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
- plugin->server_stdout_handle,
- &tcp_plugin_server_read,
- plugin);
- return GNUNET_YES;
-}
-
-
-/**
- * Return the actual path to a file found in the current
- * PATH environment variable.
- *
- * @param binary the name of the file to find
- * @return path to binary, NULL if not found
- */
-static char *
-get_path_from_PATH (const char *binary)
-{
- char *path;
- char *pos;
- char *end;
- char *buf;
- const char *p;
-
- p = getenv ("PATH");
- if (p == NULL)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
- "tcp",
- _("PATH environment variable is unset.\n"));
- return NULL;
- }
- path = GNUNET_strdup (p); /* because we write on it */
- buf = GNUNET_malloc (strlen (path) + 20);
- pos = path;
-
- while (NULL != (end = strchr (pos, PATH_SEPARATOR)))
- {
- *end = '\0';
- sprintf (buf, "%s/%s", pos, binary);
- if (GNUNET_DISK_file_test (buf) == GNUNET_YES)
- {
- GNUNET_free (path);
- return buf;
- }
- pos = end + 1;
- }
- sprintf (buf, "%s/%s", pos, binary);
- if (GNUNET_DISK_file_test (buf) == GNUNET_YES)
- {
- GNUNET_free (path);
- return buf;
- }
- GNUNET_free (buf);
- GNUNET_free (path);
- return NULL;
-}
-
-
-/**
- * Check whether the suid bit is set on a file.
- * Attempts to find the file using the current
- * PATH environment variable as a search path.
- *
- * @param binary the name of the file to check
- * @return GNUNET_YES if the file is SUID,
- * GNUNET_NO if not,
- * GNUNET_SYSERR on error
- */
-static int
-check_gnunet_nat_binary (const char *binary)
-{
- struct stat statbuf;
- char *p;
-#ifdef MINGW
- SOCKET rawsock;
- char *binaryexe;
-
- GNUNET_asprintf (&binaryexe, "%s.exe", binary);
- p = get_path_from_PATH (binaryexe);
- free (binaryexe);
-#else
- p = get_path_from_PATH (binary);
-#endif
- if (p == NULL)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
- "tcp",
- _("Could not find binary `%s' in PATH!\n"),
- binary);
- return GNUNET_NO;
- }
- if (0 != STAT (p, &statbuf))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("stat (%s) failed: %s\n"),
- p,
- STRERROR (errno));
- GNUNET_free (p);
- return GNUNET_SYSERR;
- }
- GNUNET_free (p);
-#ifndef MINGW
- if ( (0 != (statbuf.st_mode & S_ISUID)) &&
- (statbuf.st_uid == 0) )
- return GNUNET_YES;
- return GNUNET_NO;
-#else
- rawsock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
- if (INVALID_SOCKET == rawsock)
- {
- DWORD err = GetLastError ();
- GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
- "tcp",
- "socket (AF_INET, SOCK_RAW, IPPROTO_ICMP) failed! GLE = %d\n", err);
- return GNUNET_NO; /* not running as administrator */
- }
- closesocket (rawsock);
- return GNUNET_YES;
-#endif
-}
-
-
-/**
- * Our (external) hostname was resolved.
- *
- * @param cls the 'struct Plugin'
- * @param addr NULL on error, otherwise result of DNS lookup
- * @param addrlen number of bytes in addr
- */
-static void
-process_external_ip (void *cls,
- const struct sockaddr *addr,
- socklen_t addrlen)
-{
- struct Plugin *plugin = cls;
- const struct sockaddr_in *s;
- struct IPv4TcpAddress t4;
- char buf[INET_ADDRSTRLEN];
-
- plugin->ext_dns = NULL;
- if (addr == NULL)
- return;
- GNUNET_assert (addrlen == sizeof (struct sockaddr_in));
- s = (const struct sockaddr_in *) addr;
- t4.ipv4_addr = s->sin_addr.s_addr;
- if ( (plugin->behind_nat == GNUNET_YES) &&
- (plugin->enable_nat_server == GNUNET_YES) )
- {
- t4.t_port = htons(0);
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
- "tcp",
- "Notifying transport of address %s:%d\n",
- plugin->external_address,
- 0);
- }
- else
- {
- t4.t_port = htons(plugin->adv_port);
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
- "tcp",
- "Notifying transport of address %s:%d\n",
- plugin->external_address,
- (int) plugin->adv_port);
- }
-
- if ((plugin->bind_address != NULL) && (plugin->behind_nat == GNUNET_NO))
- {
- GNUNET_assert (NULL != inet_ntop(AF_INET,
- &t4.ipv4_addr,
- buf,
- sizeof (buf)));
- if (0 != strcmp (plugin->bind_address, buf))
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
- "tcp",
- "NAT is not enabled and specific bind address `%s' differs from external address `%s'! Not notifying about external address `%s'\n",
- plugin->bind_address,
- plugin->external_address,
- plugin->external_address);
- return;
- }
- }
-
- add_to_address_list (plugin,
- &t4.ipv4_addr,
- sizeof (struct in_addr));