Ejemplo n.º 1
0
/**
 * Stop an active NAT test.
 *
 * @param tst test to stop.
 */
void
GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst)
{
  struct NatActivity *pos;
  struct ClientActivity *cpos;

  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Stopping NAT test\n");
  while (NULL != (cpos = tst->ca_head))
  {
    GNUNET_CONTAINER_DLL_remove (tst->ca_head, tst->ca_tail, cpos);
    GNUNET_CLIENT_disconnect (cpos->client);
    GNUNET_free (cpos);
  }
  while (NULL != (pos = tst->na_head))
  {
    GNUNET_CONTAINER_DLL_remove (tst->na_head, tst->na_tail, pos);
    GNUNET_SCHEDULER_cancel (pos->rtask);
    GNUNET_NETWORK_socket_close (pos->sock);
    GNUNET_free (pos);
  }
  if (NULL != tst->ttask)
    GNUNET_SCHEDULER_cancel (tst->ttask);
  if (NULL != tst->ltask)
    GNUNET_SCHEDULER_cancel (tst->ltask);
  if (NULL != tst->lsock)
    GNUNET_NETWORK_socket_close (tst->lsock);
  if (NULL != tst->nat)
    GNUNET_NAT_unregister (tst->nat);
  GNUNET_free (tst);
}
Ejemplo n.º 2
0
/**
 * Close the connection and free associated resources.  There must
 * not be any pending requests for reading or writing to the
 * connection at this time.
 *
 * @param connection connection to destroy
 */
void
GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection)
{
  struct AddressProbe *pos;

  LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down connection (%p)\n", connection);
  GNUNET_assert (NULL == connection->nth.notify_ready);
  GNUNET_assert (NULL == connection->receiver);
  if (GNUNET_SCHEDULER_NO_TASK != connection->write_task)
  {
    GNUNET_SCHEDULER_cancel (connection->write_task);
    connection->write_task = GNUNET_SCHEDULER_NO_TASK;
    connection->write_buffer_off = 0;
  }
  if (GNUNET_SCHEDULER_NO_TASK != connection->read_task)
  {
    GNUNET_SCHEDULER_cancel (connection->read_task);
    connection->read_task = GNUNET_SCHEDULER_NO_TASK;
  }
  if (GNUNET_SCHEDULER_NO_TASK != connection->nth.timeout_task)
  {
    GNUNET_SCHEDULER_cancel (connection->nth.timeout_task);
    connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK;
  }
  connection->nth.notify_ready = NULL;
  if (NULL != connection->dns_active)
  {
    GNUNET_RESOLVER_request_cancel (connection->dns_active);
    connection->dns_active = NULL;
  }
  while (NULL != (pos = connection->ap_head))
  {
    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pos->sock));
    GNUNET_SCHEDULER_cancel (pos->task);
    GNUNET_CONTAINER_DLL_remove (connection->ap_head, connection->ap_tail, pos);
    GNUNET_free (pos);
  }
  if ( (NULL != connection->sock) &&
       (GNUNET_YES != connection->persist) )
  {
    if ((GNUNET_YES != GNUNET_NETWORK_socket_shutdown (connection->sock, SHUT_RDWR)) && 
	(ENOTCONN != errno) && 
	(ECONNRESET != errno) )
      LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "shutdown");    
  }
  if (NULL != connection->sock)
  {
    if (GNUNET_YES != connection->persist)
      GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (connection->sock));
    else
      GNUNET_free (connection->sock); /* at least no memory leak (we deliberately
				       * leak the socket in this special case) ... */
  }
  GNUNET_free_non_null (connection->addr);
  GNUNET_free_non_null (connection->hostname);
  GNUNET_free (connection->write_buffer);
  GNUNET_free (connection);
}
Ejemplo n.º 3
0
/**
 * Activity on our incoming socket.  Read data from the
 * incoming connection.
 *
 * @param cls the `struct NatActivity`
 * @param tc scheduler context
 */
static void
do_read (void *cls,
         const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct NatActivity *na = cls;
  struct GNUNET_NAT_Test *tst;
  uint16_t data;

  na->rtask = NULL;
  tst = na->h;
  GNUNET_CONTAINER_DLL_remove (tst->na_head, tst->na_tail, na);
  if ((NULL != tc->write_ready) &&
      (GNUNET_NETWORK_fdset_isset (tc->read_ready, na->sock)) &&
      (sizeof (data) ==
       GNUNET_NETWORK_socket_recv (na->sock, &data, sizeof (data))))
  {
    if (data == tst->data)
      tst->report (tst->report_cls, GNUNET_NAT_ERROR_SUCCESS);
    else
      LOG (GNUNET_ERROR_TYPE_DEBUG,
           "Received data does not match expected value\n");
  }
  else
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Failed to receive data from inbound connection\n");
  GNUNET_NETWORK_socket_close (na->sock);
  GNUNET_free (na);
}
void
http_check_ipv6 (struct Plugin *plugin)
{
  struct GNUNET_NETWORK_Handle *desc = NULL;

  if (plugin->ipv6 == GNUNET_YES)
  {
    /* probe IPv6 support */
    desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
    if (NULL == desc)
    {
      if ((errno == ENOBUFS) || (errno == ENOMEM) || (errno == ENFILE) ||
          (errno == EACCES))
      {
        GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
      }
      GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, plugin->name,
                       _
                       ("Disabling IPv6 since it is not supported on this system!\n"));
      plugin->ipv6 = GNUNET_NO;
    }
    else
    {
      GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
      desc = NULL;
    }

    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
                     "Testing IPv6 on this system: %s\n",
                     (plugin->ipv6 == GNUNET_YES) ? "successful" : "failed");
  }
}
Ejemplo n.º 5
0
/**
 * Try to send 'data' to the
 * IP 'dst_ipv4' at port 'dport' via UDP.
 *
 * @param dst_ipv4 target IP
 * @param dport target port
 * @param data data to send
 */
static void
try_send_udp (uint32_t dst_ipv4, uint16_t dport, uint16_t data)
{
  struct GNUNET_NETWORK_Handle *s;
  struct sockaddr_in sa;

  s = GNUNET_NETWORK_socket_create (AF_INET, SOCK_DGRAM, 0);
  if (NULL == s)
  {
    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket");
    return;
  }
  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;
  sa.sin_port = htons (dport);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending UDP packet to `%s'\n",
              GNUNET_a2s ((struct sockaddr *) &sa, sizeof (sa)));
  if (-1 ==
      GNUNET_NETWORK_socket_sendto (s, &data, sizeof (data),
                                    (const struct sockaddr *) &sa, sizeof (sa)))
    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "sendto");
  GNUNET_NETWORK_socket_close (s);
}
Ejemplo n.º 6
0
/**
 * Try to send 'data' to the
 * IP 'dst_ipv4' at port 'dport' via TCP.
 *
 * @param dst_ipv4 target IP
 * @param dport target port
 * @param data data to send
 */
static void
try_send_tcp (uint32_t dst_ipv4, uint16_t dport, uint16_t data)
{
  struct GNUNET_NETWORK_Handle *s;
  struct sockaddr_in sa;
  struct TcpContext *ctx;

  s = GNUNET_NETWORK_socket_create (AF_INET, SOCK_STREAM, 0);
  if (NULL == s)
  {
    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket");
    return;
  }
  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;
  sa.sin_port = htons (dport);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TCP message to `%s'\n",
              GNUNET_a2s ((struct sockaddr *) &sa, sizeof (sa)));
  if ((GNUNET_OK !=
       GNUNET_NETWORK_socket_connect (s, (const struct sockaddr *) &sa,
                                      sizeof (sa))) && (errno != EINPROGRESS))
  {
    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "connect");
    GNUNET_NETWORK_socket_close (s);
    return;
  }
  ctx = GNUNET_malloc (sizeof (struct TcpContext));
  ctx->s = s;
  ctx->data = data;
  GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_SECONDS, s, &tcp_send, ctx);
}
Ejemplo n.º 7
0
/**
 * Create an IPv4 listen socket bound to our port.
 *
 * @return NULL on error
 */
static struct GNUNET_NETWORK_Handle *
bind_v4 ()
{
  struct GNUNET_NETWORK_Handle *ls;
  struct sockaddr_in sa4;
  int eno;

  memset (&sa4, 0, sizeof (sa4));
  sa4.sin_family = AF_INET;
  sa4.sin_port = htons (port);
#if HAVE_SOCKADDR_IN_SIN_LEN
  sa4.sin_len = sizeof (sa4);
#endif
  ls = GNUNET_NETWORK_socket_create (AF_INET,
                                     SOCK_DGRAM,
                                     0);
  if (NULL == ls)
    return NULL;
  if (GNUNET_OK !=
      GNUNET_NETWORK_socket_bind (ls,
                                  (const struct sockaddr *) &sa4,
                                  sizeof (sa4)))
  {
    eno = errno;
    GNUNET_NETWORK_socket_close (ls);
    errno = eno;
    return NULL;
  }
  return ls;
}
Ejemplo n.º 8
0
int
main (int argc, char *argv[])
{
  int ret = 0;
  struct GNUNET_NETWORK_Handle *s = NULL;

  GNUNET_log_setup ("test-service",
                    "WARNING",
                    NULL);
  ret += check ();
  ret += check ();
  // FIXME
#ifndef MINGW
  s = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
#endif
  if (NULL == s)
  {
    if ((errno == ENOBUFS) || (errno == ENOMEM) || (errno == ENFILE) ||
        (errno == EACCES))
    {
      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
      return 1;
    }
    FPRINTF (stderr,
             "IPv6 support seems to not be available (%s), not testing it!\n",
             strerror (errno));
  }
  else
  {
    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (s));
    ret += check6 ();
  }
  ret += check_start_stop ();
  return ret;
}
Ejemplo n.º 9
0
/**
 * We failed to transmit data to the service, signal the error.
 *
 * @param connection handle that had trouble
 * @param ecode error code (errno)
 */
static void
signal_transmit_error (struct GNUNET_CONNECTION_Handle *connection,
		       int ecode)
{
  GNUNET_CONNECTION_TransmitReadyNotify notify;

  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Transmission encounterd error (%s), connection closed (%p)\n",
       STRERROR (ecode),
       connection);
  if (NULL != connection->sock)
  {
    GNUNET_NETWORK_socket_shutdown (connection->sock, SHUT_RDWR);
    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (connection->sock));
    connection->sock = NULL;
    GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->write_task);
  }
  if (GNUNET_SCHEDULER_NO_TASK != connection->read_task)
  {
    /* send errors trigger read errors... */
    GNUNET_SCHEDULER_cancel (connection->read_task);
    connection->read_task = GNUNET_SCHEDULER_NO_TASK;
    signal_receive_timeout (connection);
    return;
  }
  if (NULL == connection->nth.notify_ready)
    return;                     /* nobody to tell about it */
  notify = connection->nth.notify_ready;
  connection->nth.notify_ready = NULL;
  notify (connection->nth.notify_ready_cls, 0, NULL);
}
Ejemplo n.º 10
0
/**
 * Create a connection handle by (asynchronously) connecting to a host.
 * This function returns immediately, even if the connection has not
 * yet been established.  This function only creates TCP connections.
 *
 * @param af_family address family to use
 * @param serv_addr server address
 * @param addrlen length of server address
 * @return the connection handle
 */
struct GNUNET_CONNECTION_Handle *
GNUNET_CONNECTION_create_from_sockaddr (int af_family,
                                        const struct sockaddr *serv_addr,
                                        socklen_t addrlen)
{
  struct GNUNET_NETWORK_Handle *s;
  struct GNUNET_CONNECTION_Handle *connection;

  s = GNUNET_NETWORK_socket_create (af_family, SOCK_STREAM, 0);
  if (NULL == s)
  {
    LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, "socket");
    return NULL;
  }
  if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (s, serv_addr, addrlen)) &&
      (EINPROGRESS != errno))
  {
    /* maybe refused / unsupported address, try next */
    LOG_STRERROR (GNUNET_ERROR_TYPE_INFO, "connect");
    LOG (GNUNET_ERROR_TYPE_INFO, _("Attempt to connect to `%s' failed\n"),
         GNUNET_a2s (serv_addr, addrlen));
    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (s));
    return NULL;
  }
  connection = GNUNET_CONNECTION_create_from_existing (s);
  connection->addr = GNUNET_malloc (addrlen);
  memcpy (connection->addr, serv_addr, addrlen);
  connection->addrlen = addrlen;
  LOG (GNUNET_ERROR_TYPE_INFO, _("Trying to connect to `%s' (%p)\n"),
       GNUNET_a2s (serv_addr, addrlen), connection);
  return connection;
}
Ejemplo n.º 11
0
/**
 * Create a connection handle by accepting on a listen socket.  This
 * function may block if the listen socket has no connection ready.
 *
 * @param access_cb function to use to check if access is allowed
 * @param access_cb_cls closure for @a access_cb
 * @param lsock listen socket
 * @return the connection handle, NULL on error
 */
struct GNUNET_CONNECTION_Handle *
GNUNET_CONNECTION_create_from_accept (GNUNET_CONNECTION_AccessCheck access_cb,
                                      void *access_cb_cls,
                                      struct GNUNET_NETWORK_Handle *lsock)
{
  struct GNUNET_CONNECTION_Handle *connection;
  char addr[128];
  socklen_t addrlen;
  struct GNUNET_NETWORK_Handle *sock;
  int aret;
  struct sockaddr_in *v4;
  struct sockaddr_in6 *v6;
  struct sockaddr *sa;
  void *uaddr;
  struct GNUNET_CONNECTION_Credentials *gcp;
  struct GNUNET_CONNECTION_Credentials gc;
#ifdef SO_PEERCRED
  struct ucred uc;
  socklen_t olen;
#endif

  addrlen = sizeof (addr);
  sock =
      GNUNET_NETWORK_socket_accept (lsock,
				    (struct sockaddr *) &addr,
				    &addrlen);
  if (NULL == sock)
  {
    if (EAGAIN != errno)
      LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "accept");
    return NULL;
  }
  if ((addrlen > sizeof (addr)) || (addrlen < sizeof (sa_family_t)))
  {
    GNUNET_break (0);
    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
    return NULL;
  }

  sa = (struct sockaddr *) addr;
  v6 = (struct sockaddr_in6 *) addr;
  if ( (AF_INET6 == sa->sa_family) &&
       (IN6_IS_ADDR_V4MAPPED (&v6->sin6_addr)) )
  {
    /* convert to V4 address */
    v4 = GNUNET_new (struct sockaddr_in);
    memset (v4, 0, sizeof (struct sockaddr_in));
    v4->sin_family = AF_INET;
#if HAVE_SOCKADDR_IN_SIN_LEN
    v4->sin_len = (u_char) sizeof (struct sockaddr_in);
#endif
    GNUNET_memcpy (&v4->sin_addr,
            &((char *) &v6->sin6_addr)[sizeof (struct in6_addr) -
                                       sizeof (struct in_addr)],
            sizeof (struct in_addr));
    v4->sin_port = v6->sin6_port;
    uaddr = v4;
    addrlen = sizeof (struct sockaddr_in);
  }
Ejemplo n.º 12
0
/**
 * We're done with a GNUNET_DNSSTUB_RequestSocket, close it for now.
 *
 * @param rs request socket to clean up
 */
static void
cleanup_rs (struct GNUNET_DNSSTUB_RequestSocket *rs)
{
  if (NULL != rs->dnsout4)
  {
    GNUNET_NETWORK_socket_close (rs->dnsout4);
    rs->dnsout4 = NULL;
  }
  if (NULL != rs->dnsout6)
  {
    GNUNET_NETWORK_socket_close (rs->dnsout6);
    rs->dnsout6 = NULL;
  }
  if (GNUNET_SCHEDULER_NO_TASK != rs->read_task)
  {
    GNUNET_SCHEDULER_cancel (rs->read_task);
    rs->read_task = GNUNET_SCHEDULER_NO_TASK;
  }
}
Ejemplo n.º 13
0
/**
 * Scheduler let us know that we're either ready to write on the
 * socket OR connect timed out.  Do the right thing.
 *
 * @param cls the "struct AddressProbe*" with the address that we are probing
 * @param tc success or failure info about the connect attempt.
 */
static void
connect_probe_continuation (void *cls,
                            const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct AddressProbe *ap = cls;
  struct GNUNET_CONNECTION_Handle *connection = ap->connection;
  struct AddressProbe *pos;
  int error;
  socklen_t len;

  GNUNET_assert (NULL != ap->sock);
  GNUNET_CONTAINER_DLL_remove (connection->ap_head, connection->ap_tail, ap);
  len = sizeof (error);
  errno = 0;
  error = 0;
  if ((0 == (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) ||
      (GNUNET_OK !=
       GNUNET_NETWORK_socket_getsockopt (ap->sock, SOL_SOCKET, SO_ERROR, &error,
                                         &len)) || (0 != error))
  {
    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ap->sock));
    GNUNET_free (ap);
    if ((NULL == connection->ap_head) && (GNUNET_NO == connection->dns_active))
      connect_fail_continuation (connection);
    return;
  }
  GNUNET_assert (NULL == connection->sock);
  connection->sock = ap->sock;
  GNUNET_assert (NULL == connection->addr);
  connection->addr = GNUNET_malloc (ap->addrlen);
  memcpy (connection->addr, ap->addr, ap->addrlen);
  connection->addrlen = ap->addrlen;
  GNUNET_free (ap);
  /* cancel all other attempts */
  while (NULL != (pos = connection->ap_head))
  {
    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pos->sock));
    GNUNET_SCHEDULER_cancel (pos->task);
    GNUNET_CONTAINER_DLL_remove (connection->ap_head, connection->ap_tail, pos);
    GNUNET_free (pos);
  }
  connect_success_continuation (connection);
}
Ejemplo n.º 14
0
/**
 * Create a connection handle by connecting to a UNIX domain service.
 * This function returns immediately, even if the connection has not
 * yet been established.  This function only creates UNIX connections.
 *
 * @param cfg configuration to use
 * @param unixpath path to connect to
 * @return the connection handle, NULL on systems without UNIX support
 */
struct GNUNET_CONNECTION_Handle *
GNUNET_CONNECTION_create_from_connect_to_unixpath (const struct
                                                   GNUNET_CONFIGURATION_Handle
                                                   *cfg, const char *unixpath)
{
#ifdef AF_UNIX
  struct GNUNET_CONNECTION_Handle *connection;
  struct sockaddr_un *un;
  size_t slen;

  GNUNET_assert (0 < strlen (unixpath));        /* sanity check */
  un = GNUNET_malloc (sizeof (struct sockaddr_un));
  un->sun_family = AF_UNIX;
  slen = strlen (unixpath);
  if (slen >= sizeof (un->sun_path))
    slen = sizeof (un->sun_path) - 1;
  memcpy (un->sun_path, unixpath, slen);
  un->sun_path[slen] = '\0';
  slen = sizeof (struct sockaddr_un);
#if HAVE_SOCKADDR_IN_SIN_LEN
  un->sun_len = (u_char) slen;
#endif
#if LINUX
  un->sun_path[0] = '\0';
#endif
  connection = GNUNET_malloc (sizeof (struct GNUNET_CONNECTION_Handle));
  connection->cfg = cfg;
  connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE;
  connection->write_buffer = GNUNET_malloc (connection->write_buffer_size);
  connection->port = 0;
  connection->hostname = NULL;
  connection->addr = (struct sockaddr *) un;
  connection->addrlen = slen;
  connection->sock = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
  if (NULL == connection->sock)
  {
    GNUNET_free (connection->addr);
    GNUNET_free (connection->write_buffer);
    GNUNET_free (connection);
    return NULL;
  }
  if (GNUNET_OK !=
      GNUNET_NETWORK_socket_connect (connection->sock, connection->addr, connection->addrlen))
  {
    /* Just return; we expect everything to work eventually so don't fail HARD */
    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (connection->sock));
    connection->sock = NULL;
    return connection;
  }
  connect_success_continuation (connection);
  return connection;
#else
  return NULL;
#endif
}
Ejemplo n.º 15
0
/**
 * Activity on our incoming socket.  Read data from the
 * incoming connection.
 *
 * @param cls
 * @param tc scheduler context
 */
static void
do_udp_read (void *cls,
             const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct GNUNET_NAT_AutoHandle *ah = cls;
  unsigned char reply_buf[1024];
  ssize_t rlen;
  struct sockaddr_in answer;


  if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
      (GNUNET_NETWORK_fdset_isset (tc->read_ready,
                                   lsock4)))
  {
    rlen = GNUNET_NETWORK_socket_recv (lsock4, reply_buf, sizeof (reply_buf));

    //Lets handle the packet
    memset(&answer, 0, sizeof(struct sockaddr_in));
    if(ah->phase == AUTO_NAT_PUNCHED)
    {
      //Destroy the connection
      GNUNET_NETWORK_socket_close (lsock4);
      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                  "The external server was able to connect back");
      ah->connected_back = GNUNET_YES;
      next_phase (ah);
    }
    else
    {
      if (GNUNET_OK == GNUNET_NAT_stun_handle_packet (reply_buf, rlen, &answer))
      {
        //Process the answer
        process_stun_reply (&answer, ah);
      }
      else
      {
        next_phase (ah);
      }
    }
  }
  else
  {
    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                "TIMEOUT while waiting for an answer\n");
    if (ah->phase == AUTO_NAT_PUNCHED)
    {
      stop_stun();
    }

    next_phase (ah);
  }



}
Ejemplo n.º 16
0
/**
 * Task run for shutdown.
 *
 * @param cls closure, NULL if we need to self-restart
 * @param tc context
 */
static void
shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct ServiceList *pos;
  struct ServiceList *nxt;
  struct ServiceListeningInfo *sli;

  if (GNUNET_SCHEDULER_NO_TASK != child_restart_task)
  {
    GNUNET_SCHEDULER_cancel (child_restart_task);
    child_restart_task = GNUNET_SCHEDULER_NO_TASK;
  }
  in_shutdown = GNUNET_YES;
  /* first, stop listening */
  for (pos = running_head; NULL != pos; pos = pos->next)
  {
    while (NULL != (sli = pos->listen_head))
      {
	GNUNET_CONTAINER_DLL_remove (pos->listen_head,
				     pos->listen_tail, sli);
	if (sli->accept_task != GNUNET_SCHEDULER_NO_TASK)
	  {
	    GNUNET_SCHEDULER_cancel (sli->accept_task);
	    sli->accept_task = GNUNET_SCHEDULER_NO_TASK;
	  }
	GNUNET_break (GNUNET_OK ==
		      GNUNET_NETWORK_socket_close (sli->listen_socket));
	GNUNET_free (sli->service_addr);
	GNUNET_free (sli);
      }
  }
  /* then, shutdown all existing service processes */
  nxt = running_head;
  while (NULL != (pos = nxt))
  {
    nxt = pos->next;
    if (pos->proc != NULL)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping service `%s'\n",
		  pos->name);
      pos->killed_at = GNUNET_TIME_absolute_get ();
      if (0 != GNUNET_OS_process_kill (pos->proc, SIGTERM))
	GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
    }
    else
    {
      free_service (pos);
    }
  }
  /* finally, should all service processes be already gone, terminate for real */
  if (running_head == NULL)
    do_shutdown ();
}
Ejemplo n.º 17
0
/**
 * Open source port for sending DNS requests
 *
 * @param af AF_INET or AF_INET6
 * @return GNUNET_OK on success
 */ 
static struct GNUNET_NETWORK_Handle *
open_socket (int af)
{
  struct sockaddr_in a4;
  struct sockaddr_in6 a6;
  struct sockaddr *sa;
  socklen_t alen;
  struct GNUNET_NETWORK_Handle *ret;

  ret = GNUNET_NETWORK_socket_create (af, SOCK_DGRAM, 0);
  if (NULL == ret)
    return NULL;
  switch (af)
  {
  case AF_INET:
    memset (&a4, 0, alen = sizeof (struct sockaddr_in));
    sa = (struct sockaddr *) &a4;
    break;
  case AF_INET6:
    memset (&a6, 0, alen = sizeof (struct sockaddr_in6));
    sa = (struct sockaddr *) &a6;
    break;
  default:
    GNUNET_break (0);
    GNUNET_NETWORK_socket_close (ret);
    return NULL;
  }
  sa->sa_family = af;
  if (GNUNET_OK != GNUNET_NETWORK_socket_bind (ret,
					       sa, 
					       alen))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
		_("Could not bind to any port: %s\n"),
		STRERROR (errno));
    GNUNET_NETWORK_socket_close (ret);
    return NULL;
  }
  return ret;
}
Ejemplo n.º 18
0
/**
 * Task called by the scheduler once we can do the TCP send
 * (or once we failed to connect...).
 *
 * @param cls the 'struct TcpContext'
 * @param tc scheduler context
 */
static void
tcp_send (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct TcpContext *ctx = cls;

  if ((NULL != tc->write_ready) &&
      (GNUNET_NETWORK_fdset_isset (tc->write_ready, ctx->s)))
  {
    if (-1 ==
        GNUNET_NETWORK_socket_send (ctx->s, &ctx->data, sizeof (ctx->data)))
    {
      GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "send");
    }
    GNUNET_NETWORK_socket_shutdown (ctx->s, SHUT_RDWR);
  }
  GNUNET_NETWORK_socket_close (ctx->s);
  GNUNET_free (ctx);
}
Ejemplo n.º 19
0
/**
 * Task run on shutdown.
 *
 * @param cls NULL
 */
static void
do_shutdown (void *cls)
{
  if (NULL != nh)
  {
    GNUNET_NAT_unregister (nh);
    nh = NULL;
  }
  if (NULL != ls)
  {
    GNUNET_NETWORK_socket_close (ls);
    ls = NULL;
  }
  if (NULL != rtask)
  {
    GNUNET_SCHEDULER_cancel (rtask);
    rtask = NULL;
  }
}
Ejemplo n.º 20
0
/**
 * Function that terminates the test.
 */
static void
stop_stun ()
{
  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping STUN and quitting...\n");

  /* Clean task */
  if(NULL != ltask4)
  {
    GNUNET_SCHEDULER_cancel (ltask4);
    ltask4 = NULL;
  }

  /* Clean socket */
  if(NULL != lsock4)
  {
    GNUNET_NETWORK_socket_close (lsock4);
    lsock4 = NULL;
  }
}
Ejemplo n.º 21
0
/**
 * Function that terminates the test.
 */
static void
stop ()
{
  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
              "Stopping NAT and quitting...\n");
  if (NULL != ltask4)
  {
    GNUNET_SCHEDULER_cancel (ltask4);
    ltask4 = NULL;
  }
  if(NULL != lsock4)
  {
    GNUNET_NETWORK_socket_close(lsock4);
    lsock4 = NULL;
  }
  if (NULL != rh)
  {
    GNUNET_NAT_stun_make_request_cancel (rh);
    rh = NULL;
  }
}
Ejemplo n.º 22
0
/**
 * Try to establish a connection given the specified address.
 * This function is called by the resolver once we have a DNS reply.
 *
 * @param cls our "struct GNUNET_CONNECTION_Handle *"
 * @param addr address to try, NULL for "last call"
 * @param addrlen length of addr
 */
static void
try_connect_using_address (void *cls, const struct sockaddr *addr,
                           socklen_t addrlen)
{
  struct GNUNET_CONNECTION_Handle *connection = cls;
  struct AddressProbe *ap;
  struct GNUNET_TIME_Relative delay;

  if (NULL == addr)
  {
    connection->dns_active = NULL;
    if ((NULL == connection->ap_head) && (NULL == connection->sock))
      connect_fail_continuation (connection);
    return;
  }
  if (NULL != connection->sock)
    return;                     /* already connected */
  GNUNET_assert (NULL == connection->addr);
  /* try to connect */
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Trying to connect using address `%s:%u/%s:%u'\n", connection->hostname, connection->port,
       GNUNET_a2s (addr, addrlen), connection->port);
  ap = GNUNET_malloc (sizeof (struct AddressProbe) + addrlen);
  ap->addr = (const struct sockaddr *) &ap[1];
  memcpy (&ap[1], addr, addrlen);
  ap->addrlen = addrlen;
  ap->connection = connection;

  switch (ap->addr->sa_family)
  {
  case AF_INET:
    ((struct sockaddr_in *) ap->addr)->sin_port = htons (connection->port);
    break;
  case AF_INET6:
    ((struct sockaddr_in6 *) ap->addr)->sin6_port = htons (connection->port);
    break;
  default:
    GNUNET_break (0);
    GNUNET_free (ap);
    return;                     /* not supported by us */
  }
  ap->sock = GNUNET_NETWORK_socket_create (ap->addr->sa_family, SOCK_STREAM, 0);
  if (NULL == ap->sock)
  {
    GNUNET_free (ap);
    return;                     /* not supported by OS */
  }
  LOG (GNUNET_ERROR_TYPE_INFO, _("Trying to connect to `%s' (%p)\n"),
       GNUNET_a2s (ap->addr, ap->addrlen), connection);
  if ((GNUNET_OK !=
       GNUNET_NETWORK_socket_connect (ap->sock, ap->addr, ap->addrlen)) &&
      (EINPROGRESS != errno))
  {
    /* maybe refused / unsupported address, try next */
    LOG_STRERROR (GNUNET_ERROR_TYPE_INFO, "connect");
#if 0
    LOG (GNUNET_ERROR_TYPE_INFO, _("Failed to connect to `%s' (%p)\n"),
         GNUNET_a2s (ap->addr, ap->addrlen), connection);
#endif
    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ap->sock));
    GNUNET_free (ap);
    return;
  }
  GNUNET_CONTAINER_DLL_insert (connection->ap_head, connection->ap_tail, ap);
  delay = GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT;
  if (NULL != connection->nth.notify_ready)
    delay =
        GNUNET_TIME_relative_min (delay,
                                  GNUNET_TIME_absolute_get_remaining (connection->
                                                                      nth.transmit_timeout));
  if (NULL != connection->receiver)
    delay =
        GNUNET_TIME_relative_min (delay,
                                  GNUNET_TIME_absolute_get_remaining
                                  (connection->receive_timeout));
  ap->task =
      GNUNET_SCHEDULER_add_write_net (delay, ap->sock,
                                      &connect_probe_continuation, ap);
}
Ejemplo n.º 23
0
/**
 * Get the list of addresses that a server for the given service
 * should bind to.
 *
 * @param service_name name of the service
 * @param cfg configuration (which specifies the addresses)
 * @param addrs set (call by reference) to an array of pointers to the
 *              addresses the server should bind to and listen on; the
 *              array will be NULL-terminated (on success)
 * @param addr_lens set (call by reference) to an array of the lengths
 *              of the respective `struct sockaddr` struct in the @a addrs
 *              array (on success)
 * @return number of addresses found on success,
 *              #GNUNET_SYSERR if the configuration
 *              did not specify reasonable finding information or
 *              if it specified a hostname that could not be resolved;
 *              #GNUNET_NO if the number of addresses configured is
 *              zero (in this case, `*addrs` and `*addr_lens` will be
 *              set to NULL).
 */
int
GNUNET_SERVICE_get_server_addresses (const char *service_name,
                                     const struct GNUNET_CONFIGURATION_Handle *cfg,
                                     struct sockaddr ***addrs,
                                     socklen_t ** addr_lens)
{
  int disablev6;
  struct GNUNET_NETWORK_Handle *desc;
  unsigned long long port;
  char *unixpath;
  struct addrinfo hints;
  struct addrinfo *res;
  struct addrinfo *pos;
  struct addrinfo *next;
  unsigned int i;
  int resi;
  int ret;
  int abstract;
  struct sockaddr **saddrs;
  socklen_t *saddrlens;
  char *hostname;

  *addrs = NULL;
  *addr_lens = NULL;
  desc = NULL;
  if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "DISABLEV6"))
  {
    if (GNUNET_SYSERR ==
        (disablev6 =
         GNUNET_CONFIGURATION_get_value_yesno (cfg, service_name, "DISABLEV6")))
      return GNUNET_SYSERR;
  }
  else
    disablev6 = GNUNET_NO;

  if (! disablev6)
  {
    /* probe IPv6 support */
    desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
    if (NULL == desc)
    {
      if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
          (EACCES == errno))
      {
        LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
        return GNUNET_SYSERR;
      }
      LOG (GNUNET_ERROR_TYPE_INFO,
           _("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
           service_name, STRERROR (errno));
      disablev6 = GNUNET_YES;
    }
    else
    {
      GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
      desc = NULL;
    }
  }

  port = 0;
  if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT"))
  {
    if (GNUNET_OK !=
	GNUNET_CONFIGURATION_get_value_number (cfg, service_name,
					       "PORT", &port))
    {
      LOG (GNUNET_ERROR_TYPE_ERROR,
           _("Require valid port number for service `%s' in configuration!\n"),
           service_name);
    }
    if (port > 65535)
    {
      LOG (GNUNET_ERROR_TYPE_ERROR,
           _("Require valid port number for service `%s' in configuration!\n"),
           service_name);
      return GNUNET_SYSERR;
    }
  }

  if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "BINDTO"))
  {
    GNUNET_break (GNUNET_OK ==
                  GNUNET_CONFIGURATION_get_value_string (cfg, service_name,
                                                         "BINDTO", &hostname));
  }
  else
    hostname = NULL;

  unixpath = NULL;
  abstract = GNUNET_NO;
#ifdef AF_UNIX
  if ((GNUNET_YES ==
       GNUNET_CONFIGURATION_have_value (cfg, service_name, "UNIXPATH")) &&
      (GNUNET_OK ==
       GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH",
                                              &unixpath)) &&
      (0 < strlen (unixpath)))
  {
    /* probe UNIX support */
    struct sockaddr_un s_un;

    if (strlen (unixpath) >= sizeof (s_un.sun_path))
    {
      LOG (GNUNET_ERROR_TYPE_WARNING,
           _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath,
           (unsigned long long) sizeof (s_un.sun_path));
      unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
      LOG (GNUNET_ERROR_TYPE_INFO,
	   _("Using `%s' instead\n"),
           unixpath);
    }
#ifdef LINUX
    abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
                                                     "TESTING",
                                                     "USE_ABSTRACT_SOCKETS");
    if (GNUNET_SYSERR == abstract)
      abstract = GNUNET_NO;
#endif
    if ((GNUNET_YES != abstract)
        && (GNUNET_OK !=
            GNUNET_DISK_directory_create_for_file (unixpath)))
      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
				"mkdir",
				unixpath);
  }
  if (NULL != unixpath)
  {
    desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
    if (NULL == desc)
    {
      if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
          (EACCES == errno))
      {
        LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
        GNUNET_free_non_null (hostname);
        GNUNET_free (unixpath);
        return GNUNET_SYSERR;
      }
      LOG (GNUNET_ERROR_TYPE_INFO,
           _("Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
           service_name,
           STRERROR (errno));
      GNUNET_free (unixpath);
      unixpath = NULL;
    }
    else
    {
      GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
      desc = NULL;
    }
  }
#endif

  if ((0 == port) && (NULL == unixpath))
  {
    LOG (GNUNET_ERROR_TYPE_ERROR,
         _("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
         service_name);
    GNUNET_free_non_null (hostname);
    return GNUNET_SYSERR;
  }
  if (0 == port)
  {
    saddrs = GNUNET_malloc (2 * sizeof (struct sockaddr *));
    saddrlens = GNUNET_malloc (2 * sizeof (socklen_t));
    add_unixpath (saddrs, saddrlens, unixpath, abstract);
    GNUNET_free_non_null (unixpath);
    GNUNET_free_non_null (hostname);
    *addrs = saddrs;
    *addr_lens = saddrlens;
    return 1;
  }

  if (NULL != hostname)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Resolving `%s' since that is where `%s' will bind to.\n",
         hostname,
         service_name);
    memset (&hints, 0, sizeof (struct addrinfo));
    if (disablev6)
      hints.ai_family = AF_INET;
    hints.ai_protocol = IPPROTO_TCP;
    if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
        (NULL == res))
    {
      LOG (GNUNET_ERROR_TYPE_ERROR,
           _("Failed to resolve `%s': %s\n"),
           hostname,
           gai_strerror (ret));
      GNUNET_free (hostname);
      GNUNET_free_non_null (unixpath);
      return GNUNET_SYSERR;
    }
    next = res;
    i = 0;
    while (NULL != (pos = next))
    {
      next = pos->ai_next;
      if ((disablev6) && (pos->ai_family == AF_INET6))
        continue;
      i++;
    }
    if (0 == i)
    {
      LOG (GNUNET_ERROR_TYPE_ERROR,
           _("Failed to find %saddress for `%s'.\n"),
           disablev6 ? "IPv4 " : "",
           hostname);
      freeaddrinfo (res);
      GNUNET_free (hostname);
      GNUNET_free_non_null (unixpath);
      return GNUNET_SYSERR;
    }
    resi = i;
    if (NULL != unixpath)
      resi++;
    saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
    saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
    i = 0;
    if (NULL != unixpath)
    {
      add_unixpath (saddrs, saddrlens, unixpath, abstract);
      i++;
    }
    next = res;
    while (NULL != (pos = next))
    {
      next = pos->ai_next;
      if ((disablev6) && (AF_INET6 == pos->ai_family))
        continue;
      if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
        continue;               /* not TCP */
      if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
        continue;               /* huh? */
      LOG (GNUNET_ERROR_TYPE_DEBUG, "Service `%s' will bind to `%s'\n",
           service_name, GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
      if (AF_INET == pos->ai_family)
      {
        GNUNET_assert (sizeof (struct sockaddr_in) == pos->ai_addrlen);
        saddrlens[i] = pos->ai_addrlen;
        saddrs[i] = GNUNET_malloc (saddrlens[i]);
        memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
        ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
      }
      else
      {
        GNUNET_assert (AF_INET6 == pos->ai_family);
        GNUNET_assert (sizeof (struct sockaddr_in6) == pos->ai_addrlen);
        saddrlens[i] = pos->ai_addrlen;
        saddrs[i] = GNUNET_malloc (saddrlens[i]);
        memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
        ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
      }
      i++;
    }
    GNUNET_free (hostname);
    freeaddrinfo (res);
    resi = i;
  }
  else
  {
    /* will bind against everything, just set port */
    if (disablev6)
    {
      /* V4-only */
      resi = 1;
      if (NULL != unixpath)
        resi++;
      i = 0;
      saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
      saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
      if (NULL != unixpath)
      {
        add_unixpath (saddrs, saddrlens, unixpath, abstract);
        i++;
      }
      saddrlens[i] = sizeof (struct sockaddr_in);
      saddrs[i] = GNUNET_malloc (saddrlens[i]);
#if HAVE_SOCKADDR_IN_SIN_LEN
      ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
#endif
      ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
      ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
    }
    else
    {
      /* dual stack */
      resi = 2;
      if (NULL != unixpath)
        resi++;
      saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
      saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
      i = 0;
      if (NULL != unixpath)
      {
        add_unixpath (saddrs, saddrlens, unixpath, abstract);
        i++;
      }
      saddrlens[i] = sizeof (struct sockaddr_in6);
      saddrs[i] = GNUNET_malloc (saddrlens[i]);
#if HAVE_SOCKADDR_IN_SIN_LEN
      ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
#endif
      ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
      ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
      i++;
      saddrlens[i] = sizeof (struct sockaddr_in);
      saddrs[i] = GNUNET_malloc (saddrlens[i]);
#if HAVE_SOCKADDR_IN_SIN_LEN
      ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
#endif
      ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
      ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
    }
  }
  GNUNET_free_non_null (unixpath);
  *addrs = saddrs;
  *addr_lens = saddrlens;
  return resi;
}
Ejemplo n.º 24
0
/**
 * Create a connection handle by accepting on a listen socket.  This
 * function may block if the listen socket has no connection ready.
 *
 * @param access function to use to check if access is allowed
 * @param access_cls closure for access
 * @param lsock listen socket
 * @return the connection handle, NULL on error
 */
struct GNUNET_CONNECTION_Handle *
GNUNET_CONNECTION_create_from_accept (GNUNET_CONNECTION_AccessCheck access,
                                      void *access_cls,
                                      struct GNUNET_NETWORK_Handle *lsock)
{
  struct GNUNET_CONNECTION_Handle *connection;
  char addr[128];
  socklen_t addrlen;
  struct GNUNET_NETWORK_Handle *sock;
  int aret;
  struct sockaddr_in *v4;
  struct sockaddr_in6 *v6;
  struct sockaddr *sa;
  void *uaddr;
  struct GNUNET_CONNECTION_Credentials *gcp;
  struct GNUNET_CONNECTION_Credentials gc;
#ifdef SO_PEERCRED
  struct ucred uc;
  socklen_t olen;
#endif

  addrlen = sizeof (addr);
  sock =
      GNUNET_NETWORK_socket_accept (lsock, (struct sockaddr *) &addr, &addrlen);
  if (NULL == sock)
  {
    LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "accept");
    return NULL;
  }
  if ((addrlen > sizeof (addr)) || (addrlen < sizeof (sa_family_t)))
  {
    GNUNET_break (0);
    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
    return NULL;
  }

  sa = (struct sockaddr *) addr;
  v6 = (struct sockaddr_in6 *) addr;
  if ((AF_INET6 == sa->sa_family) && (IN6_IS_ADDR_V4MAPPED (&v6->sin6_addr)))
  {
    /* convert to V4 address */
    v4 = GNUNET_malloc (sizeof (struct sockaddr_in));
    memset (v4, 0, sizeof (struct sockaddr_in));
    v4->sin_family = AF_INET;
#if HAVE_SOCKADDR_IN_SIN_LEN
    v4->sin_len = (u_char) sizeof (struct sockaddr_in);
#endif
    memcpy (&v4->sin_addr,
            &((char *) &v6->sin6_addr)[sizeof (struct in6_addr) -
                                       sizeof (struct in_addr)],
            sizeof (struct in_addr));
    v4->sin_port = v6->sin6_port;
    uaddr = v4;
    addrlen = sizeof (struct sockaddr_in);
  }
  else
  {
    uaddr = GNUNET_malloc (addrlen);
    memcpy (uaddr, addr, addrlen);
  }
  gcp = NULL;
  gc.uid = 0;
  gc.gid = 0;
  if (AF_UNIX == sa->sa_family)
  {
#if HAVE_GETPEEREID
    /* most BSDs */
    if (0 == getpeereid (GNUNET_NETWORK_get_fd (sock), &gc.uid, &gc.gid))
      gcp = &gc;
#else
#ifdef SO_PEERCRED
    /* largely traditional GNU/Linux */
    olen = sizeof (uc);
    if ((0 ==
         getsockopt (GNUNET_NETWORK_get_fd (sock), SOL_SOCKET, SO_PEERCRED, &uc,
                     &olen)) && (olen == sizeof (uc)))
    {
      gc.uid = uc.uid;
      gc.gid = uc.gid;
      gcp = &gc;
    }
#else
#if HAVE_GETPEERUCRED
    /* this is for Solaris 10 */
    ucred_t *uc;

    uc = NULL;
    if (0 == getpeerucred (GNUNET_NETWORK_get_fd (sock), &uc))
    {
      gc.uid = ucred_geteuid (uc);
      gc.gid = ucred_getegid (uc);
      gcp = &gc;
    }
    ucred_free (uc);
#endif
#endif
#endif
  }

  if ((NULL != access) &&
      (GNUNET_YES != (aret = access (access_cls, gcp, uaddr, addrlen))))
  {
    if (GNUNET_NO == aret)
      LOG (GNUNET_ERROR_TYPE_INFO, _("Access denied to `%s'\n"),
           GNUNET_a2s (uaddr, addrlen));
    GNUNET_break (GNUNET_OK ==
                  GNUNET_NETWORK_socket_shutdown (sock, SHUT_RDWR));
    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
    GNUNET_free (uaddr);
    return NULL;
  }
  connection = GNUNET_malloc (sizeof (struct GNUNET_CONNECTION_Handle));
  connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE;
  connection->write_buffer = GNUNET_malloc (connection->write_buffer_size);
  connection->addr = uaddr;
  connection->addrlen = addrlen;
  connection->sock = sock;
  LOG (GNUNET_ERROR_TYPE_INFO, 
       _("Accepting connection from `%s': %p\n"),
       GNUNET_a2s (uaddr, addrlen), connection);
  return connection;
}
Ejemplo n.º 25
0
/**
 * Read listen sockets from the parent process (ARM).
 *
 * @param sctx service context to initialize
 * @return #GNUNET_YES if ok, #GNUNET_NO if not ok (must bind yourself),
 * and #GNUNET_SYSERR on error.
 */
static int
receive_sockets_from_parent (struct GNUNET_SERVICE_Context *sctx)
{
  const char *env_buf;
  int fail;
  uint64_t count;
  uint64_t i;
  HANDLE lsocks_pipe;

  env_buf = getenv ("GNUNET_OS_READ_LSOCKS");
  if ((NULL == env_buf) || (strlen (env_buf) <= 0))
    return GNUNET_NO;
  /* Using W32 API directly here, because this pipe will
   * never be used outside of this function, and it's just too much of a bother
   * to create a GNUnet API that boxes a HANDLE (the way it is done with socks)
   */
  lsocks_pipe = (HANDLE) strtoul (env_buf, NULL, 10);
  if ( (0 == lsocks_pipe) || (INVALID_HANDLE_VALUE == lsocks_pipe))
    return GNUNET_NO;
  fail = 1;
  do
  {
    int ret;
    int fail2;
    DWORD rd;

    ret = ReadFile (lsocks_pipe, &count, sizeof (count), &rd, NULL);
    if ((0 == ret) || (sizeof (count) != rd) || (0 == count))
      break;
    sctx->lsocks =
        GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle *) * (count + 1));

    fail2 = 1;
    for (i = 0; i < count; i++)
    {
      WSAPROTOCOL_INFOA pi;
      uint64_t size;
      SOCKET s;

      ret = ReadFile (lsocks_pipe, &size, sizeof (size), &rd, NULL);
      if ( (0 == ret) || (sizeof (size) != rd) || (sizeof (pi) != size) )
        break;
      ret = ReadFile (lsocks_pipe, &pi, sizeof (pi), &rd, NULL);
      if ( (0 == ret) || (sizeof (pi) != rd))
        break;
      s = WSASocketA (pi.iAddressFamily, pi.iSocketType, pi.iProtocol, &pi, 0, WSA_FLAG_OVERLAPPED);
      sctx->lsocks[i] = GNUNET_NETWORK_socket_box_native (s);
      if (NULL == sctx->lsocks[i])
        break;
      else if (i == count - 1)
        fail2 = 0;
    }
    if (fail2)
      break;
    sctx->lsocks[count] = NULL;
    fail = 0;
  }
  while (fail);

  CloseHandle (lsocks_pipe);

  if (fail)
  {
    LOG (GNUNET_ERROR_TYPE_ERROR,
         _("Could not access a pre-bound socket, will try to bind myself\n"));
    for (i = 0; (i < count) && (NULL != sctx->lsocks[i]); i++)
      GNUNET_break (0 == GNUNET_NETWORK_socket_close (sctx->lsocks[i]));
    GNUNET_free_non_null (sctx->lsocks);
    sctx->lsocks = NULL;
    return GNUNET_NO;
  }
  return GNUNET_YES;
}
Ejemplo n.º 26
0
/**
 * Test if the service is running.  If we are given a UNIXPATH or a local address,
 * we do this NOT by trying to connect to the service, but by trying to BIND to
 * the same port.  If the BIND fails, we know the service is running.
 *
 * @param service name of the service to wait for
 * @param cfg configuration to use
 * @param timeout how long to wait at most
 * @param task task to run if service is running
 *        (reason will be "PREREQ_DONE" (service running)
 *         or "TIMEOUT" (service not known to be running))
 * @param task_cls closure for task
 */
void
GNUNET_CLIENT_service_test (const char *service,
                            const struct GNUNET_CONFIGURATION_Handle *cfg,
                            struct GNUNET_TIME_Relative timeout,
                            GNUNET_SCHEDULER_Task task, void *task_cls)
{
  char *hostname;
  unsigned long long port;
  struct GNUNET_NETWORK_Handle *sock;
  struct GNUNET_CLIENT_Connection *client;

  LOG (GNUNET_ERROR_TYPE_DEBUG, "Testing if service `%s' is running.\n",
       service);
#ifdef AF_UNIX
  {
    /* probe UNIX support */
    struct sockaddr_un s_un;
    size_t slen;
    char *unixpath;

    unixpath = NULL;
    if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, service, "UNIXPATH", &unixpath)) && (0 < strlen (unixpath)))  /* We have a non-NULL unixpath, does that mean it's valid? */
    {
      if (strlen (unixpath) >= sizeof (s_un.sun_path))
      {
        LOG (GNUNET_ERROR_TYPE_WARNING,
             _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath,
             (unsigned long long) sizeof (s_un.sun_path));
	unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
        LOG (GNUNET_ERROR_TYPE_INFO,
             _("Using `%s' instead\n"), unixpath);
      }
    }
    if (NULL != unixpath)
    {
      sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0);
      if (NULL != sock)
      {
	memset (&s_un, 0, sizeof (s_un));
	s_un.sun_family = AF_UNIX;
	slen = strlen (unixpath) + 1;
	if (slen >= sizeof (s_un.sun_path))
	  slen = sizeof (s_un.sun_path) - 1;
	memcpy (s_un.sun_path, unixpath, slen);
	s_un.sun_path[slen] = '\0';
	slen = sizeof (struct sockaddr_un);
#if LINUX
	s_un.sun_path[0] = '\0';
#endif
#if HAVE_SOCKADDR_IN_SIN_LEN
	s_un.sun_len = (u_char) slen;
#endif
	if (GNUNET_OK !=
	    GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_un,
					slen))
        {
	  /* failed to bind => service must be running */
	  GNUNET_free (unixpath);
	  (void) GNUNET_NETWORK_socket_close (sock);
	  GNUNET_SCHEDULER_add_continuation (task, task_cls,
					     GNUNET_SCHEDULER_REASON_PREREQ_DONE);
	  return;
	}
	(void) GNUNET_NETWORK_socket_close (sock);        
        /* let's try IP */
      }
    }
    GNUNET_free_non_null (unixpath);
  }
#endif

  hostname = NULL;
  if ((GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_number (cfg, service, "PORT", &port)) ||
      (port > 65535) ||
      (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (cfg, service, "HOSTNAME",
                                              &hostname)))
  {
    /* UNIXPATH failed (if possible) AND IP failed => error */
    service_test_error (task, task_cls);
    return;
  }

  if (0 == strcmp ("localhost", hostname)
#if !LINUX
      && 0
#endif
      )
  {
    /* can test using 'bind' */
    struct sockaddr_in s_in;

    memset (&s_in, 0, sizeof (s_in));
#if HAVE_SOCKADDR_IN_SIN_LEN
    s_in.sin_len = sizeof (struct sockaddr_in);
#endif
    s_in.sin_family = AF_INET;
    s_in.sin_port = htons (port);

    sock = GNUNET_NETWORK_socket_create (AF_INET, SOCK_STREAM, 0);
    if (NULL != sock)
    {
      if (GNUNET_OK !=
          GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_in,
                                      sizeof (s_in)))
      {
        /* failed to bind => service must be running */
        GNUNET_free (hostname);
        (void) GNUNET_NETWORK_socket_close (sock);
        GNUNET_SCHEDULER_add_continuation (task, task_cls,
                                           GNUNET_SCHEDULER_REASON_PREREQ_DONE);
        return;
      }
      (void) GNUNET_NETWORK_socket_close (sock);
    }
  }

  if (0 == strcmp ("ip6-localhost", hostname)
#if !LINUX
      && 0
#endif
      )
  {
    /* can test using 'bind' */
    struct sockaddr_in6 s_in6;

    memset (&s_in6, 0, sizeof (s_in6));
#if HAVE_SOCKADDR_IN_SIN_LEN
    s_in6.sin6_len = sizeof (struct sockaddr_in6);
#endif
    s_in6.sin6_family = AF_INET6;
    s_in6.sin6_port = htons (port);

    sock = GNUNET_NETWORK_socket_create (AF_INET6, SOCK_STREAM, 0);
    if (NULL != sock)
    {
      if (GNUNET_OK !=
          GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_in6,
                                      sizeof (s_in6)))
      {
        /* failed to bind => service must be running */
        GNUNET_free (hostname);
        (void) GNUNET_NETWORK_socket_close (sock);
        GNUNET_SCHEDULER_add_continuation (task, task_cls,
                                           GNUNET_SCHEDULER_REASON_PREREQ_DONE);
        return;
      }
      (void) GNUNET_NETWORK_socket_close (sock);
    }
  }

  if (((0 == strcmp ("localhost", hostname)) ||
       (0 == strcmp ("ip6-localhost", hostname)))
#if !LINUX
      && 0
#endif
      )
  {
    /* all binds succeeded => claim service not running right now */
    GNUNET_free_non_null (hostname);
    service_test_error (task, task_cls);
    return;
  }
  GNUNET_free_non_null (hostname);

  /* non-localhost, try 'connect' method */
  client = GNUNET_CLIENT_connect (service, cfg);
  if (NULL == client)
  {
    LOG (GNUNET_ERROR_TYPE_INFO,
         _("Could not connect to service `%s', must not be running.\n"),
         service);
    service_test_error (task, task_cls);
    return;
  }
  client->test_cb = task;
  client->test_cb_cls = task_cls;
  client->test_deadline = GNUNET_TIME_relative_to_absolute (timeout);
  if (NULL == GNUNET_CLIENT_notify_transmit_ready (client,
						   sizeof (struct GNUNET_MessageHeader),
						   timeout, GNUNET_YES, &write_test,
						   client))
  {
    LOG (GNUNET_ERROR_TYPE_WARNING,
         _("Failure to transmit request to service `%s'\n"), service);
    service_test_error (task, task_cls);
    GNUNET_CLIENT_disconnect (client);
    return;
  }
}
Ejemplo n.º 27
0
/**
 * Creating a listening socket for each of the service's addresses and
 * wait for the first incoming connection to it
 *
 * @param sa address associated with the service
 * @param addr_len length of sa
 * @param sl service entry for the service in question
 */
static void
create_listen_socket (struct sockaddr *sa, socklen_t addr_len,
		      struct ServiceList *sl)
{
  static int on = 1;
  struct GNUNET_NETWORK_Handle *sock;
  struct ServiceListeningInfo *sli;

  switch (sa->sa_family)
    {
    case AF_INET:
      sock = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0);
      break;
    case AF_INET6:
      sock = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
      break;
    case AF_UNIX:
      if (strcmp (GNUNET_a2s (sa, addr_len), "@") == 0)	/* Do not bind to blank UNIX path! */
	return;
      sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0);
      break;
    default:
      GNUNET_break (0);
      sock = NULL;
      errno = EAFNOSUPPORT;
      break;
    }
  if (NULL == sock)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
		  _("Unable to create socket for service `%s': %s\n"),
		  sl->name, STRERROR (errno));
      GNUNET_free (sa);
      return;
    }
  if (GNUNET_NETWORK_socket_setsockopt
      (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK)
    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
			 "setsockopt");
#ifdef IPV6_V6ONLY
  if ((sa->sa_family == AF_INET6) &&
      (GNUNET_NETWORK_socket_setsockopt
       (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)) != GNUNET_OK))
    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
			 "setsockopt");
#endif

  if (GNUNET_NETWORK_socket_bind
      (sock, (const struct sockaddr *) sa, addr_len) != GNUNET_OK)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
		  _
		  ("Unable to bind listening socket for service `%s' to address `%s': %s\n"),
		  sl->name, GNUNET_a2s (sa, addr_len), STRERROR (errno));
      GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
      GNUNET_free (sa);
      return;
    }
  if (GNUNET_NETWORK_socket_listen (sock, 5) != GNUNET_OK)
    {
      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen");
      GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
      GNUNET_free (sa);
      return;
    }
  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
	      _("ARM now monitors connections to service `%s' at `%s'\n"),
	      sl->name, GNUNET_a2s (sa, addr_len));
  sli = GNUNET_malloc (sizeof (struct ServiceListeningInfo));
  sli->service_addr = sa;
  sli->service_addr_len = addr_len;
  sli->listen_socket = sock;
  sli->sl = sl;
  sli->accept_task =
    GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, sock,
				   &accept_connection, sli);
  GNUNET_CONTAINER_DLL_insert (sl->listen_head, sl->listen_tail, sli);
}
Ejemplo n.º 28
0
/**
 * Setup addr, addrlen, idle_timeout
 * based on configuration!
 *
 * Configuration may specify:
 * - PORT (where to bind to for TCP)
 * - UNIXPATH (where to bind to for UNIX domain sockets)
 * - TIMEOUT (after how many ms does an inactive service timeout);
 * - DISABLEV6 (disable support for IPv6, otherwise we use dual-stack)
 * - BINDTO (hostname or IP address to bind to, otherwise we take everything)
 * - ACCEPT_FROM  (only allow connections from specified IPv4 subnets)
 * - ACCEPT_FROM6 (only allow connections from specified IPv6 subnets)
 * - REJECT_FROM  (disallow allow connections from specified IPv4 subnets)
 * - REJECT_FROM6 (disallow allow connections from specified IPv6 subnets)
 *
 * @param sctx service context to initialize
 * @return #GNUNET_OK if configuration succeeded
 */
static int
setup_service (struct GNUNET_SERVICE_Context *sctx)
{
  struct GNUNET_TIME_Relative idleout;
  int tolerant;

#ifndef MINGW
  const char *nfds;
  unsigned int cnt;
  int flags;
#endif

  if (GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name, "TIMEOUT"))
  {
    if (GNUNET_OK !=
        GNUNET_CONFIGURATION_get_value_time (sctx->cfg, sctx->service_name,
                                             "TIMEOUT", &idleout))
    {
      LOG (GNUNET_ERROR_TYPE_ERROR,
           _("Specified value for `%s' of service `%s' is invalid\n"),
           "TIMEOUT", sctx->service_name);
      return GNUNET_SYSERR;
    }
    sctx->timeout = idleout;
  }
  else
    sctx->timeout = GNUNET_TIME_UNIT_FOREVER_REL;

  if (GNUNET_CONFIGURATION_have_value
      (sctx->cfg, sctx->service_name, "TOLERANT"))
  {
    if (GNUNET_SYSERR ==
        (tolerant =
         GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, sctx->service_name,
                                               "TOLERANT")))
    {
      LOG (GNUNET_ERROR_TYPE_ERROR,
           _("Specified value for `%s' of service `%s' is invalid\n"),
           "TOLERANT", sctx->service_name);
      return GNUNET_SYSERR;
    }
  }
  else
    tolerant = GNUNET_NO;

#ifndef MINGW
  errno = 0;
  if ((NULL != (nfds = getenv ("LISTEN_FDS"))) &&
      (1 == SSCANF (nfds, "%u", &cnt)) && (cnt > 0) && (cnt < FD_SETSIZE) &&
      (cnt + 4 < FD_SETSIZE))
  {
    sctx->lsocks =
        GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle *) * (cnt + 1));
    while (0 < cnt--)
    {
      flags = fcntl (3 + cnt, F_GETFD);
      if ((flags < 0) || (0 != (flags & FD_CLOEXEC)) ||
          (NULL ==
           (sctx->lsocks[cnt] = GNUNET_NETWORK_socket_box_native (3 + cnt))))
      {
        LOG (GNUNET_ERROR_TYPE_ERROR,
             _
             ("Could not access pre-bound socket %u, will try to bind myself\n"),
             (unsigned int) 3 + cnt);
        cnt++;
        while (sctx->lsocks[cnt] != NULL)
          GNUNET_break (0 == GNUNET_NETWORK_socket_close (sctx->lsocks[cnt++]));
        GNUNET_free (sctx->lsocks);
        sctx->lsocks = NULL;
        break;
      }
    }
    unsetenv ("LISTEN_FDS");
  }
#else
  if (getenv ("GNUNET_OS_READ_LSOCKS") != NULL)
  {
    receive_sockets_from_parent (sctx);
    putenv ("GNUNET_OS_READ_LSOCKS=");
  }
#endif

  if ((NULL == sctx->lsocks) &&
      (GNUNET_SYSERR ==
       GNUNET_SERVICE_get_server_addresses (sctx->service_name, sctx->cfg,
                                            &sctx->addrs, &sctx->addrlens)))
    return GNUNET_SYSERR;
  sctx->require_found = tolerant ? GNUNET_NO : GNUNET_YES;
  sctx->match_uid =
      GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, sctx->service_name,
                                            "UNIX_MATCH_UID");
  sctx->match_gid =
      GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, sctx->service_name,
                                            "UNIX_MATCH_GID");
  process_acl4 (&sctx->v4_denied, sctx, "REJECT_FROM");
  process_acl4 (&sctx->v4_allowed, sctx, "ACCEPT_FROM");
  process_acl6 (&sctx->v6_denied, sctx, "REJECT_FROM6");
  process_acl6 (&sctx->v6_allowed, sctx, "ACCEPT_FROM6");

  return GNUNET_OK;
}
Ejemplo n.º 29
0
/**
 * Test if the service is running.  If we are given a UNIXPATH or a
 * local address, we do this NOT by trying to connect to the service,
 * but by trying to BIND to the same port.  If the BIND fails, we know
 * the service is running.
 *
 * @param service name of the service to wait for
 * @param cfg configuration to use
 * @param timeout how long to wait at most
 * @param cb function to call with the result
 * @param cb_cls closure for @a cb
 * @return handle to cancel the test
 */
struct GNUNET_CLIENT_TestHandle *
GNUNET_CLIENT_service_test (const char *service,
                            const struct GNUNET_CONFIGURATION_Handle *cfg,
                            struct GNUNET_TIME_Relative timeout,
                            GNUNET_CLIENT_TestResultCallback cb,
			    void *cb_cls)
{
  struct GNUNET_CLIENT_TestHandle *th;
  char *hostname;
  unsigned long long port;
  struct GNUNET_NETWORK_Handle *sock;

  th = GNUNET_new (struct GNUNET_CLIENT_TestHandle);
  th->cb = cb;
  th->cb_cls = cb_cls;
  th->test_deadline = GNUNET_TIME_relative_to_absolute (timeout);
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Testing if service `%s' is running.\n",
       service);
#ifdef AF_UNIX
  {
    /* probe UNIX support */
    struct sockaddr_un s_un;
    char *unixpath;
    int abstract;

    unixpath = NULL;
    if ((GNUNET_OK ==
	 GNUNET_CONFIGURATION_get_value_filename (cfg,
						  service,
						  "UNIXPATH",
						  &unixpath)) &&
	(0 < strlen (unixpath)))  /* We have a non-NULL unixpath, does that mean it's valid? */
    {
      if (strlen (unixpath) >= sizeof (s_un.sun_path))
      {
        LOG (GNUNET_ERROR_TYPE_WARNING,
             _("UNIXPATH `%s' too long, maximum length is %llu\n"),
	     unixpath,
             (unsigned long long) sizeof (s_un.sun_path));
	unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
        LOG (GNUNET_ERROR_TYPE_INFO,
             _("Using `%s' instead\n"), unixpath);
      }
    }
#ifdef LINUX
    abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
                                                     "TESTING",
                                                     "USE_ABSTRACT_SOCKETS");
#else
    abstract = GNUNET_NO;
#endif
    if ((NULL != unixpath) && (GNUNET_YES != abstract))
    {
      if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (unixpath))
        GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
                                  "mkdir", unixpath);
    }
    if (NULL != unixpath)
    {
      sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0);
      if (NULL != sock)
      {
	memset (&s_un, 0, sizeof (s_un));
	s_un.sun_family = AF_UNIX;
        strncpy (s_un.sun_path, unixpath, sizeof (s_un.sun_path) - 1);
        if (GNUNET_YES == abstract)
          s_un.sun_path[0] = '\0';
#if HAVE_SOCKADDR_IN_SIN_LEN
        s_un.sun_len = (u_char) sizeof (struct sockaddr_un);
#endif
	if (GNUNET_OK !=
	    GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_un,
					sizeof (struct sockaddr_un)))
        {
	  /* failed to bind => service must be running */
	  GNUNET_free (unixpath);
	  (void) GNUNET_NETWORK_socket_close (sock);
	  service_test_report (th, GNUNET_YES);
	  return th;
	}
	(void) GNUNET_NETWORK_socket_close (sock);
        /* let's try IP */
      }
    }
    GNUNET_free_non_null (unixpath);
  }
#endif

  hostname = NULL;
  if ((GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_number (cfg, service, "PORT", &port)) ||
      (port > 65535) ||
      (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (cfg, service, "HOSTNAME",
                                              &hostname)))
  {
    /* UNIXPATH failed (if possible) AND IP failed => error */
    service_test_report (th, GNUNET_SYSERR);
    return th;
  }

  if (0 == strcmp ("localhost", hostname)
#if !LINUX
      && 0
#endif
      )
  {
    /* can test using 'bind' */
    struct sockaddr_in s_in;

    memset (&s_in, 0, sizeof (s_in));
#if HAVE_SOCKADDR_IN_SIN_LEN
    s_in.sin_len = sizeof (struct sockaddr_in);
#endif
    s_in.sin_family = AF_INET;
    s_in.sin_port = htons (port);

    sock = GNUNET_NETWORK_socket_create (AF_INET, SOCK_STREAM, 0);
    if (NULL != sock)
    {
      if (GNUNET_OK !=
          GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_in,
                                      sizeof (s_in)))
      {
        /* failed to bind => service must be running */
        GNUNET_free (hostname);
        (void) GNUNET_NETWORK_socket_close (sock);
        service_test_report (th, GNUNET_YES);
        return th;
      }
      (void) GNUNET_NETWORK_socket_close (sock);
    }
  }

  if (0 == strcmp ("ip6-localhost", hostname)
#if !LINUX
      && 0
#endif
      )
  {
    /* can test using 'bind' */
    struct sockaddr_in6 s_in6;

    memset (&s_in6, 0, sizeof (s_in6));
#if HAVE_SOCKADDR_IN_SIN_LEN
    s_in6.sin6_len = sizeof (struct sockaddr_in6);
#endif
    s_in6.sin6_family = AF_INET6;
    s_in6.sin6_port = htons (port);

    sock = GNUNET_NETWORK_socket_create (AF_INET6, SOCK_STREAM, 0);
    if (NULL != sock)
    {
      if (GNUNET_OK !=
          GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_in6,
                                      sizeof (s_in6)))
      {
        /* failed to bind => service must be running */
        GNUNET_free (hostname);
        (void) GNUNET_NETWORK_socket_close (sock);
        service_test_report (th, GNUNET_YES);
        return th;
      }
      (void) GNUNET_NETWORK_socket_close (sock);
    }
  }

  if (((0 == strcmp ("localhost", hostname)) ||
       (0 == strcmp ("ip6-localhost", hostname)))
#if !LINUX
      && 0
#endif
      )
  {
    /* all binds succeeded => claim service not running right now */
    GNUNET_free_non_null (hostname);
    service_test_report (th, GNUNET_NO);
    return th;
  }
  GNUNET_free_non_null (hostname);

  /* non-localhost, try 'connect' method */
  th->client = GNUNET_CLIENT_connect (service, cfg);
  if (NULL == th->client)
  {
    LOG (GNUNET_ERROR_TYPE_INFO,
         _("Could not connect to service `%s', configuration broken.\n"),
         service);
    service_test_report (th, GNUNET_SYSERR);
    return th;
  }
  th->th = GNUNET_CLIENT_notify_transmit_ready (th->client,
						sizeof (struct GNUNET_MessageHeader),
						timeout, GNUNET_YES,
						&write_test, th);
  if (NULL == th->th)
  {
    LOG (GNUNET_ERROR_TYPE_WARNING,
         _("Failure to transmit request to service `%s'\n"), service);
    service_test_report (th, GNUNET_SYSERR);
    return th;
  }
  return th;
}
Ejemplo n.º 30
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;
}