+{
+ char inet4[INET_ADDRSTRLEN];
+ char port_as_string[6];
+ struct GNUNET_OS_Process *proc;
+ char *binary;
+
+ if (GNUNET_YES != h->enable_nat_client)
+ return GNUNET_NO; /* not permitted / possible */
+
+ if (h->internal_address == NULL)
+ {
+ 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_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);
+ 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 (GNUNET_NO, 0, NULL, NULL, NULL,
+ binary,
+ "gnunet-helper-nat-client",
+ h->internal_address,
+ inet4, port_as_string, NULL);
+ GNUNET_free (binary);
+ if (NULL == proc)
+ return GNUNET_SYSERR;
+ /* we know that the gnunet-helper-nat-client will terminate virtually
+ * instantly */
+ GNUNET_OS_process_wait (proc);
+ GNUNET_OS_process_destroy (proc);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Test if the given address is (currently) a plausible IP address for this peer.
+ *
+ * @param h the handle returned by register
+ * @param addr IP address to test (IPv4 or IPv6)
+ * @param addrlen number of bytes in @a addr
+ * @return #GNUNET_YES if the address is plausible,
+ * #GNUNET_NO if the address is not plausible,
+ * #GNUNET_SYSERR if the address is malformed
+ */
+int
+GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *h,
+ const void *addr,
+ socklen_t addrlen)
+{
+ struct LocalAddressList *pos;
+ const struct sockaddr_in *in4;
+ const struct sockaddr_in6 *in6;
+
+ if ((addrlen != sizeof (struct in_addr)) &&
+ (addrlen != sizeof (struct in6_addr)))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ for (pos = h->lal_head; NULL != pos; pos = pos->next)
+ {
+ if (pos->addrlen == sizeof (struct sockaddr_in))
+ {
+ in4 = (struct sockaddr_in *) &pos[1];
+ if ((addrlen == sizeof (struct in_addr)) &&
+ (0 == memcmp (&in4->sin_addr, addr, sizeof (struct in_addr))))
+ return GNUNET_YES;
+ }
+ else if (pos->addrlen == sizeof (struct sockaddr_in6))
+ {
+ in6 = (struct sockaddr_in6 *) &pos[1];
+ if ((addrlen == sizeof (struct in6_addr)) &&
+ (0 == memcmp (&in6->sin6_addr, addr, sizeof (struct in6_addr))))
+ return GNUNET_YES;
+ }
+ else
+ {
+ GNUNET_assert (0);
+ }
+ }
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ "Asked to validate one of my addresses and validation failed!\n");
+ return GNUNET_NO;
+}
+
+/**
+ * Converts enum GNUNET_NAT_StatusCode to a string
+ *
+ * @param err error code to resolve to a string
+ * @return pointer to a static string containing the error code
+ */
+const char *
+GNUNET_NAT_status2string (enum GNUNET_NAT_StatusCode err)
+{
+ switch (err)
+ {
+ case GNUNET_NAT_ERROR_SUCCESS:
+ return _ ("Operation Successful");
+ case GNUNET_NAT_ERROR_IPC_FAILURE:
+ return _ ("Internal Failure (IPC, ...)");
+ case GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR:
+ return _ ("Failure in network subsystem, check permissions.");
+ case GNUNET_NAT_ERROR_TIMEOUT:
+ return _ ("Encountered timeout while performing operation");
+ case GNUNET_NAT_ERROR_NOT_ONLINE:
+ return _ ("detected that we are offline");
+ case GNUNET_NAT_ERROR_UPNPC_NOT_FOUND:
+ return _ ("`upnpc` command not found");
+ case GNUNET_NAT_ERROR_UPNPC_FAILED:
+ return _ ("Failed to run `upnpc` command");
+ case GNUNET_NAT_ERROR_UPNPC_TIMEOUT:
+ return _ ("`upnpc' command took too long, process killed");
+ case GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED:
+ return _ ("`upnpc' command failed to establish port mapping");
+ case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND:
+ return _ ("`external-ip' command not found");
+ case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED:
+ return _ ("Failed to run `external-ip` command");
+ case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID:
+ return _ ("`external-ip' command output invalid");
+ case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID:
+ return _ ("no valid address was returned by `external-ip'");
+ case GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO:
+ return _ ("Could not determine interface with internal/local network address");
+ case GNUNET_NAT_ERROR_HELPER_NAT_SERVER_NOT_FOUND:
+ return _ ("No functioning gnunet-helper-nat-server installation found");
+ case GNUNET_NAT_ERROR_NAT_TEST_START_FAILED:
+ return _ ("NAT test could not be initialized");
+ case GNUNET_NAT_ERROR_NAT_TEST_TIMEOUT:
+ return _ ("NAT test timeout reached");
+ case GNUNET_NAT_ERROR_NAT_REGISTER_FAILED:
+ return _ ("could not register NAT");
+ case GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND:
+ return _ ("No working gnunet-helper-nat-client installation found");
+/* case:
+ return _ ("");*/
+ default:
+ return "unknown status code";
+ }