Example #1
0
/**
 * Main function run with scheduler.
 */
static void
run (void *cls, char *const *args, const char *cfgfile,
     const struct GNUNET_CONFIGURATION_Handle *cfg)
{
  struct GNUNET_NAT_Handle *nat;
  struct addr_cls data;
  struct sockaddr *addr;

  data.addr = NULL;
  GNUNET_OS_network_interfaces_list (process_if, &data);
  if (NULL == data.addr)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                "Could not find a valid interface address!\n");
    exit (77); /* marks test as skipped */
  }
  addr = data.addr;
  GNUNET_assert (addr->sa_family == AF_INET || addr->sa_family == AF_INET6);
  if (addr->sa_family == AF_INET)
    ((struct sockaddr_in *) addr)->sin_port = htons (2086);
  else
    ((struct sockaddr_in6 *) addr)->sin6_port = htons (2086);

  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
              "Requesting NAT redirection from address %s...\n",
              GNUNET_a2s (addr, data.addrlen));

  nat = GNUNET_NAT_register (cfg, GNUNET_YES /* tcp */ ,
                             2086, 1, (const struct sockaddr **) &addr,
                             &data.addrlen, &addr_callback, NULL, NULL, NULL);
  GNUNET_free (addr);
  GNUNET_SCHEDULER_add_delayed (TIMEOUT, &stop, nat);
}
static void
start_report_addresses (struct Plugin *plugin)
{
  int res = GNUNET_OK;
  struct sockaddr **addrs;
  socklen_t *addrlens;

  res =
      http_get_addresses (plugin, plugin->name, plugin->env->cfg, &addrs,
                          &addrlens);
  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
                   _("Found %u addresses to report to NAT service\n"), res);

  if (res != GNUNET_SYSERR)
  {
    plugin->nat =
        GNUNET_NAT_register (plugin->env->cfg, GNUNET_YES, plugin->port,
                             (unsigned int) res,
                             (const struct sockaddr **) addrs, addrlens,
                             &nat_port_map_callback, NULL, plugin);
    while (res > 0)
    {
      res--;
#if 0
      GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, _("FREEING %s\n"),
                       GNUNET_a2s (addrs[res], addrlens[res]));
#endif
      GNUNET_assert (addrs[res] != NULL);
      GNUNET_free (addrs[res]);
    }
    GNUNET_free_non_null (addrs);
    GNUNET_free_non_null (addrlens);
  }
  else
  {
    plugin->nat =
        GNUNET_NAT_register (plugin->env->cfg, GNUNET_YES, 0, 0, NULL, NULL,
                             NULL, NULL, plugin);
  }
}
/**
 * Try contacting the peer using autonomous
 * NAT traveral method.
 *
 * @param dst_ipv4 IPv4 address to send the fake ICMP message
 * @param dport destination port to include in ICMP message
 * @param is_tcp mark for TCP (GNUNET_YES)  or UDP (GNUNET_NO)
 */
static void
try_anat (uint32_t dst_ipv4, uint16_t dport, int is_tcp)
{
  struct GNUNET_NAT_Handle *h;
  struct sockaddr_in sa;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Asking for connection reversal with %x and code %u\n",
              (unsigned int) dst_ipv4, (unsigned int) dport);
  h = GNUNET_NAT_register (cfg, is_tcp, dport, 0, NULL, NULL, NULL, NULL, NULL);
  memset (&sa, 0, sizeof (sa));
  sa.sin_family = AF_INET;
#if HAVE_SOCKADDR_IN_SIN_LEN
  sa.sin_len = sizeof (sa);
#endif
  sa.sin_addr.s_addr = dst_ipv4;
  GNUNET_NAT_run_client (h, &sa);
  GNUNET_NAT_unregister (h);
}
Example #4
0
/**
 * Main function that will be run.
 *
 * @param cls closure
 * @param args remaining command-line arguments
 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
 * @param c configuration
 */
static void
run (void *cls,
     char *const *args,
     const char *cfgfile,
     const struct GNUNET_CONFIGURATION_Handle *c)
{
  uint8_t af;
  struct sockaddr *local_sa;
  struct sockaddr *remote_sa;
  socklen_t local_len;
  size_t remote_len;

  if (use_tcp && use_udp)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		"Cannot use TCP and UDP\n");
    global_ret = 1;
    return;
  }
  proto = 0;
  if (use_tcp)
    proto = IPPROTO_TCP;
  if (use_udp)
    proto = IPPROTO_UDP;

  GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
				 NULL);

  if (0 == proto)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		"Must specify either TCP or UDP\n");
    global_ret = 1;
    return;
  }
  if (NULL != local_addr)
  {
    local_len = (socklen_t) GNUNET_STRINGS_parse_socket_addr (local_addr,
							      &af,
							      &local_sa);
    if (0 == local_len)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		  "Invalid socket address `%s'\n",
		  local_addr);
      global_ret = 1;
      return;
    }
  }
  if (NULL != remote_addr)
  {
    remote_len = GNUNET_STRINGS_parse_socket_addr (remote_addr,
						   &af,
						   &remote_sa);
    if (0 == remote_len)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		  "Invalid socket address `%s'\n",
		  remote_addr);
      global_ret = 1;
      return;
    }
  }

  if (NULL != local_addr)
  {
    if (NULL == section_name)
      section_name = GNUNET_strdup ("undefined");
    nh = GNUNET_NAT_register (c,
			      section_name,
			      proto,
			      1,
			      (const struct sockaddr **) &local_sa,
			      &local_len,
			      &address_cb,
			      (listen_reversal) ? &reversal_cb : NULL,
			      NULL);
  }
  else if (listen_reversal)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		"Use of `-W` only effective in combination with `-i`\n");    
    global_ret = 1;
    GNUNET_SCHEDULER_shutdown ();
    return;
  }

  if (NULL != remote_addr)
  {
    int ret;
    
    if ( (NULL == nh) ||
	 (sizeof (struct sockaddr_in) != local_len) )
    {
      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		  "Require IPv4 local address to initiate connection reversal\n");
      global_ret = 1;
      GNUNET_SCHEDULER_shutdown ();
      return;
    }
    if (sizeof (struct sockaddr_in) != remote_len)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		  "Require IPv4 reversal target address\n");
      global_ret = 1;
      GNUNET_SCHEDULER_shutdown ();
      return;
    }
    GNUNET_assert (AF_INET == local_sa->sa_family);
    GNUNET_assert (AF_INET == remote_sa->sa_family);
    ret = GNUNET_NAT_request_reversal (nh,
				       (const struct sockaddr_in *) local_sa,
				       (const struct sockaddr_in *) remote_sa);
    switch (ret)
    {
    case GNUNET_SYSERR:
      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		  "Connection reversal internal error\n");
      break;
    case GNUNET_NO:
      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		  "Connection reversal unavailable\n");
      break;
    case GNUNET_OK:
      /* operation in progress */
      break;
    }
  }
  
  if (do_stun)
  {
    if (NULL == local_addr)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		  "Require local address to support STUN requests\n");
      global_ret = 1;
      GNUNET_SCHEDULER_shutdown ();
      return;
    }
    if (IPPROTO_UDP != proto)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		  "STUN only supported over UDP\n");
      global_ret = 1;
      GNUNET_SCHEDULER_shutdown ();
      return;
    }
    ls = GNUNET_NETWORK_socket_create (af,
				       SOCK_DGRAM,
				       IPPROTO_UDP);
    if (GNUNET_OK !=
	GNUNET_NETWORK_socket_bind (ls,
				    local_sa,
				    local_len))
    {
      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
		  "Failed to bind to %s: %s\n",
		  GNUNET_a2s (local_sa,
			      local_len),
		  STRERROR (errno));
      global_ret = 1;
      GNUNET_SCHEDULER_shutdown ();
      return;
    }
    rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
					   ls,
					   &stun_read_task,
					   NULL);
  }

  test_finished ();
}
Example #5
0
/**
 * Start testing if NAT traversal works using the
 * given configuration (IPv4-only).
 *
 * ALL failures are reported directly to the report callback
 *
 * @param cfg configuration for the NAT traversal
 * @param is_tcp #GNUNET_YES to test TCP, #GNUNET_NO to test UDP
 * @param bnd_port port to bind to, 0 for connection reversal
 * @param adv_port externally advertised port to use
 * @param timeout delay after which the test should be aborted
 * @param report function to call with the result of the test
 * @param report_cls closure for @a report
 * @return handle to cancel NAT test or NULL. The error is always indicated via the report callback
 */
struct GNUNET_NAT_Test *
GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
                       int is_tcp,
                       uint16_t bnd_port,
                       uint16_t adv_port,
                       struct GNUNET_TIME_Relative timeout,
                       GNUNET_NAT_TestCallback report,
                       void *report_cls)
{
  struct GNUNET_NAT_Test *nh;
  struct sockaddr_in sa;
  const struct sockaddr *addrs[] = { (const struct sockaddr *) &sa };
  const socklen_t addrlens[] = { sizeof (sa) };

  memset (&sa, 0, sizeof (sa));
  sa.sin_family = AF_INET;
  sa.sin_port = htons (bnd_port);
#if HAVE_SOCKADDR_IN_SIN_LEN
  sa.sin_len = sizeof (sa);
#endif

  nh = GNUNET_new (struct GNUNET_NAT_Test);
  nh->cfg = cfg;
  nh->is_tcp = is_tcp;
  nh->data = bnd_port;
  nh->adv_port = adv_port;
  nh->report = report;
  nh->report_cls = report_cls;
  nh->status = GNUNET_NAT_ERROR_SUCCESS;
  if (0 == bnd_port)
  {
    nh->nat 
      = GNUNET_NAT_register (cfg, is_tcp, 0, 0, 
			     NULL, NULL,
			     &addr_cb,
                             &reversal_cb, nh, NULL);
  }
  else
  {
    nh->lsock =
        GNUNET_NETWORK_socket_create (AF_INET,
                                      (is_tcp ==
                                       GNUNET_YES) ? SOCK_STREAM : SOCK_DGRAM,
                                      0);
    if ((nh->lsock == NULL) ||
        (GNUNET_OK !=
         GNUNET_NETWORK_socket_bind (nh->lsock, (const struct sockaddr *) &sa,
                                     sizeof (sa))))
    {
      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                  _("Failed to create listen socket bound to `%s' for NAT test: %s\n"),
                  GNUNET_a2s ((const struct sockaddr *) &sa, sizeof (sa)),
                  STRERROR (errno));
      if (NULL != nh->lsock)
      {
        GNUNET_NETWORK_socket_close (nh->lsock);
        nh->lsock = NULL;
      }
      nh->status = GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR;
      nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout, nh);
      return nh;
    }
    if (GNUNET_YES == is_tcp)
    {
      GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_listen (nh->lsock, 5));
      nh->ltask =
          GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
                                         nh->lsock, &do_accept, nh);
    }
    else
    {
      nh->ltask =
          GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
                                         nh->lsock, &do_udp_read, nh);
    }
    LOG (GNUNET_ERROR_TYPE_INFO,
	 "NAT test listens on port %u (%s)\n",
	 bnd_port,
	 (GNUNET_YES == is_tcp) ? "tcp" : "udp");
    nh->nat = GNUNET_NAT_register (cfg, is_tcp, adv_port, 1,
                                   addrs, addrlens,
                                   &addr_cb, NULL, nh, NULL);
    if (NULL == nh->nat)
    {
      LOG (GNUNET_ERROR_TYPE_INFO,
          _("NAT test failed to start NAT library\n"));
      if (NULL != nh->ltask)
      {
        GNUNET_SCHEDULER_cancel (nh->ltask);
        nh->ltask = NULL;
      }
      if (NULL != nh->lsock)
      {
        GNUNET_NETWORK_socket_close (nh->lsock);
        nh->lsock = NULL;
      }
      nh->status = GNUNET_NAT_ERROR_NAT_REGISTER_FAILED;
      nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout, nh);
      return nh;
    }
  }
  nh->ttask = GNUNET_SCHEDULER_add_delayed (timeout, &do_timeout, nh);
  return nh;
}