コード例 #1
0
ファイル: connection.c プロジェクト: h4ck3rm1k3/gnunet-debian
/**
 * 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;
}
コード例 #2
0
static int
iface_proc (void *cls, const char *name, int isDefault,
            const struct sockaddr *addr, const struct sockaddr *broadcast_addr,
            const struct sockaddr *netmask, socklen_t addrlen)
{
  struct Plugin *plugin = cls;

  if (addr != NULL)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "address %s for interface %s %p\n ",
                GNUNET_a2s (addr, addrlen), name, addr);
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "broadcast address %s for interface %s %p\n ",
                GNUNET_a2s (broadcast_addr, addrlen), name, broadcast_addr);
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "netmask %s for interface %s %p\n ",
                GNUNET_a2s (netmask, addrlen), name, netmask);

    /* Collecting broadcast addresses */
    if (broadcast_addr != NULL)
    {
      struct BroadcastAddress *ba =
          GNUNET_malloc (sizeof (struct BroadcastAddress));
      ba->addr = GNUNET_malloc (addrlen);
      memcpy (ba->addr, broadcast_addr, addrlen);
      ba->addrlen = addrlen;
      GNUNET_CONTAINER_DLL_insert (plugin->ipv4_broadcast_head,
                                   plugin->ipv4_broadcast_tail, ba);
    }
  }
  return GNUNET_OK;
}
コード例 #3
0
ファイル: connection.c プロジェクト: h4ck3rm1k3/gnunet-debian
/**
 * This function is called once we either timeout
 * or have data ready to read.
 *
 * @param cls connection to read from
 * @param tc scheduler context
 */
static void
receive_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct GNUNET_CONNECTION_Handle *connection = cls;
  char buffer[connection->max];
  ssize_t ret;
  GNUNET_CONNECTION_Receiver receiver;

  connection->read_task = GNUNET_SCHEDULER_NO_TASK;
  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
  {
    /* ignore shutdown request, go again immediately */
    connection->read_task =
        GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining
                                       (connection->receive_timeout), connection->sock,
                                       &receive_ready, connection);
    return;
  }
  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT))
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
	 "Receive from `%s' encounters error: timeout (%p)\n",
	 GNUNET_a2s (connection->addr, connection->addrlen),
	 GNUNET_TIME_absolute_get_duration (connection->receive_timeout).rel_value,
	 connection);
    signal_receive_timeout (connection);
    return;
  }
  if (NULL == connection->sock)
  {
    /* connect failed for good */
    signal_receive_error (connection, ECONNREFUSED);
    return;
  }
  GNUNET_assert (GNUNET_NETWORK_fdset_isset (tc->read_ready, connection->sock));
RETRY:
  ret = GNUNET_NETWORK_socket_recv (connection->sock, buffer, connection->max);
  if (-1 == ret)
  {
    if (EINTR == errno)
      goto RETRY;
    signal_receive_error (connection, errno);
    return;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "receive_ready read %u/%u bytes from `%s' (%p)!\n", (unsigned int) ret,
       connection->max, GNUNET_a2s (connection->addr, connection->addrlen), connection);
  GNUNET_assert (NULL != (receiver = connection->receiver));
  connection->receiver = NULL;
  receiver (connection->receiver_cls, buffer, ret, connection->addr, connection->addrlen, 0);
}
コード例 #4
0
ファイル: nat_test.c プロジェクト: tg-x/gnunet
/**
 * Address-callback, used to send message to gnunet-nat-server.
 *
 * @param cls closure
 * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
 *     the previous (now invalid) one
 * @param addr either the previous or the new public IP address
 * @param addrlen actual length of the @a addr
 */
static void
addr_cb (void *cls,
         int add_remove,
         const struct sockaddr *addr,
         socklen_t addrlen)
{
  struct GNUNET_NAT_Test *h = cls;
  struct ClientActivity *ca;
  struct GNUNET_CLIENT_Connection *client;
  struct GNUNET_NAT_TestMessage msg;
  const struct sockaddr_in *sa;

  if (GNUNET_YES != add_remove)
    return;
  if (addrlen != sizeof (struct sockaddr_in))
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
	 "NAT test ignores IPv6 address `%s' returned from NAT library\n",
	 GNUNET_a2s (addr, addrlen));
    return;                     /* ignore IPv6 here */
  }
  LOG (GNUNET_ERROR_TYPE_INFO,
       "Asking gnunet-nat-server to connect to `%s'\n",
       GNUNET_a2s (addr, addrlen));
  sa = (const struct sockaddr_in *) addr;
  msg.header.size = htons (sizeof (struct GNUNET_NAT_TestMessage));
  msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAT_TEST);
  msg.dst_ipv4 = sa->sin_addr.s_addr;
  msg.dport = sa->sin_port;
  msg.data = h->data;
  msg.is_tcp = htonl ((uint32_t) h->is_tcp);

  client = GNUNET_CLIENT_connect ("gnunet-nat-server", h->cfg);
  if (NULL == client)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                _("Failed to connect to `gnunet-nat-server'\n"));
    return;
  }
  ca = GNUNET_new (struct ClientActivity);
  ca->client = client;
  GNUNET_CONTAINER_DLL_insert (h->ca_head, h->ca_tail, ca);
  GNUNET_break (GNUNET_OK ==
                GNUNET_CLIENT_transmit_and_get_response (client, &msg.header,
                                                         NAT_SERVER_TIMEOUT,
                                                         GNUNET_YES, NULL,
                                                         NULL));
}
コード例 #5
0
ファイル: test_nat.c プロジェクト: tg-x/gnunet
/**
 * 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);
}
コード例 #6
0
/**
 * Create a HTTP address from a socketaddr
 *
 * @param protocol protocol
 * @param addr sockaddr * address
 * @param addrlen length of the address
 * @return the string
 */
char *
http_common_address_from_socket (const char *protocol, const struct sockaddr *addr, socklen_t addrlen)
{
  char *res;
  GNUNET_asprintf(&res, "%s://%s", protocol, GNUNET_a2s (addr, addrlen));
  return res;
}
コード例 #7
0
/**
 * Function that will be called to figure if an address is an loopback,
 * LAN, WAN etc. address
 *
 * @param cls closure
 * @param addr binary address
 * @param addrlen length of the address
 * @return ATS Information containing the network type
 */
static struct GNUNET_ATS_Information
plugin_env_address_to_type (void *cls,
                            const struct sockaddr *addr,
                            size_t addrlen)
{
  struct GNUNET_ATS_Information ats;
  ats.type = htonl (GNUNET_ATS_NETWORK_TYPE);
  ats.value = htonl (GNUNET_ATS_NET_UNSPECIFIED);
  if (GST_ats == NULL)
  {
    GNUNET_break (0);
    return ats;
  }
  if (((addr->sa_family != AF_INET) && (addrlen != sizeof (struct sockaddr_in))) &&
      ((addr->sa_family != AF_INET6) && (addrlen != sizeof (struct sockaddr_in6))) &&
      (addr->sa_family != AF_UNIX))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed address with length %u `%s'\n",
                addrlen,
                GNUNET_a2s(addr, addrlen));
    GNUNET_break (0);
    return (const struct GNUNET_ATS_Information) ats;
  }
  return GNUNET_ATS_address_get_type(GST_ats, addr, addrlen);
}
コード例 #8
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);
}
コード例 #9
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);
}
コード例 #10
0
ファイル: connection.c プロジェクト: h4ck3rm1k3/gnunet-debian
/**
 * We've succeeded in establishing a connection.
 *
 * @param connection the connection we tried to establish
 */
static void
connect_success_continuation (struct GNUNET_CONNECTION_Handle *connection)
{
  LOG (GNUNET_ERROR_TYPE_DEBUG, 
       "Connection to `%s' succeeded! (%p)\n",
       GNUNET_a2s (connection->addr, connection->addrlen), connection);
  /* trigger jobs that waited for the connection */
  if (NULL != connection->receiver)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Connection succeeded, starting with receiving data (%p)\n", 
	 connection);
    GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->read_task);
    connection->read_task =
      GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining
                                     (connection->receive_timeout), connection->sock,
                                     &receive_ready, connection);
  }
  if (NULL != connection->nth.notify_ready)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Connection succeeded, starting with sending data (%p)\n",
         connection);
    GNUNET_assert (connection->nth.timeout_task != GNUNET_SCHEDULER_NO_TASK);
    GNUNET_SCHEDULER_cancel (connection->nth.timeout_task);
    connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK;
    GNUNET_assert (connection->write_task == GNUNET_SCHEDULER_NO_TASK);
    connection->write_task =
        GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_absolute_get_remaining
                                        (connection->nth.transmit_timeout), connection->sock,
                                        &transmit_ready, connection);
  }
}
コード例 #11
0
static int
client_receive_mst_cb (void *cls, void *client,
                       const struct GNUNET_MessageHeader *message)
{
  struct Session *s = cls;
  struct GNUNET_TIME_Relative delay;

  if (GNUNET_YES != exist_session(p, s))
  {
    GNUNET_break (0);
    return GNUNET_OK;
  }

  delay = http_plugin_receive (s, &s->target, message, s, s->addr, s->addrlen);
  s->next_receive =
      GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), delay);

  if (GNUNET_TIME_absolute_get ().abs_value < s->next_receive.abs_value)
  {
    struct Plugin *plugin = s->plugin;

    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
                     "Client: peer `%s' address `%s' next read delayed for %llu ms\n",
                     GNUNET_i2s (&s->target), GNUNET_a2s (s->addr, s->addrlen),
                     delay);
  }
  return GNUNET_OK;
}
コード例 #12
0
void
udp_broadcast_receive (struct Plugin *plugin, const char * buf, ssize_t size, struct sockaddr *addr, size_t addrlen)
{
  struct GNUNET_ATS_Information ats;

  if ((GNUNET_YES == plugin->broadcast_ipv4) && (addrlen == sizeof (struct sockaddr_in)))
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Received IPv4 HELLO beacon broadcast with %i bytes from address %s\n",
         size, GNUNET_a2s ((const struct sockaddr *) addr, addrlen));
    struct Mstv4Context *mc;

    mc = GNUNET_malloc (sizeof (struct Mstv4Context));
    struct sockaddr_in *av4 = (struct sockaddr_in *) addr;

    mc->addr.ipv4_addr = av4->sin_addr.s_addr;
    mc->addr.u4_port = av4->sin_port;
    ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) addr, addrlen);
    mc->ats_address_network_type = ats.value;

    GNUNET_assert (NULL != plugin->broadcast_ipv4_mst);
    if (GNUNET_OK !=
        GNUNET_SERVER_mst_receive (plugin->broadcast_ipv4_mst, mc, buf, size,
                                   GNUNET_NO, GNUNET_NO))
      GNUNET_free (mc);
  }
  else if ((GNUNET_YES == plugin->broadcast_ipv4) && (addrlen == sizeof (struct sockaddr_in6)))
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Received IPv6 HELLO beacon broadcast with %i bytes from address %s\n",
         size, GNUNET_a2s ((const struct sockaddr *) &addr, addrlen));
    struct Mstv6Context *mc;

    mc = GNUNET_malloc (sizeof (struct Mstv6Context));
    struct sockaddr_in6 *av6 = (struct sockaddr_in6 *) addr;

    mc->addr.ipv6_addr = av6->sin6_addr;
    mc->addr.u6_port = av6->sin6_port;
    ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) addr, addrlen);
    mc->ats_address_network_type = ats.value;
    GNUNET_assert (NULL != plugin->broadcast_ipv4_mst);
    if (GNUNET_OK !=
        GNUNET_SERVER_mst_receive (plugin->broadcast_ipv6_mst, mc, buf, size,
                                   GNUNET_NO, GNUNET_NO))
      GNUNET_free (mc);
  }
}
コード例 #13
0
ファイル: test_nat.c プロジェクト: tg-x/gnunet
/**
 * Function called on each address that the NAT service
 * believes to be valid for the transport.
 */
static void
addr_callback (void *cls, int add_remove, const struct sockaddr *addr,
               socklen_t addrlen)
{
  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Address changed: %s `%s' (%u bytes)\n",
              add_remove == GNUNET_YES ? "added" : "removed", GNUNET_a2s (addr,
                                                                          addrlen),
              (unsigned int) addrlen);
}
コード例 #14
0
struct Session *
lookup_session_old (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
                struct Session *session, const void *addr, size_t addrlen,
                int force_address)
{
  struct Session *t;
  int e_peer;
  int e_addr;

  for (t = plugin->head; NULL != t; t = t->next)
  {
#if 0
    GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
                     "Comparing peer `%s' address `%s' len %i session %p to \n",
                     GNUNET_i2s (target), GNUNET_a2s (addr, addrlen), addrlen,
                     session);
    GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
                     "peer `%s' address `%s' len %i session %p \n\n",
                     GNUNET_i2s (&t->target), GNUNET_a2s (t->addr, t->addrlen),
                     t->addrlen, t);
    GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, "memcmp %i \n",
                     memcmp (addr, t->addr, addrlen));
#endif
    e_peer = GNUNET_NO;
    e_addr = GNUNET_NO;
    if (0 == memcmp (target, &t->target, sizeof (struct GNUNET_PeerIdentity)))
    {
      e_peer = GNUNET_YES;
      if ( (addrlen == t->addrlen) &&
	   (0 == memcmp (addr, t->addr, addrlen)) )
	e_addr = GNUNET_YES;    
      if ( (t == session) &&
	   (t->addrlen == session->addrlen) &&
	   (0 == memcmp (session->addr, t->addr, t->addrlen)) )
	e_addr = GNUNET_YES;
    }

    if ( ((e_peer == GNUNET_YES) && (force_address == GNUNET_NO)) ||
	 ((e_peer == GNUNET_YES) && (force_address == GNUNET_YES) && (e_addr == GNUNET_YES)) ||
	 ((e_peer == GNUNET_YES) && (force_address == GNUNET_SYSERR)) )
      return t;
  }
  return NULL;
}
コード例 #15
0
ファイル: gnunet-nat.c プロジェクト: GNUnet/gnunet
/**
 * Signature of the callback passed to #GNUNET_NAT_register().
 * for a function to call whenever someone asks us to do connection
 * reversal.
 *
 * @param cls closure, NULL
 * @param remote_addr public IP address of the other peer
 * @param remote_addrlen actual length of the @a remote_addr
 */
static void
reversal_cb (void *cls,
	     const struct sockaddr *remote_addr,
	     socklen_t remote_addrlen)
{
  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
	      "Connection reversal requested by %s\n",
	      GNUNET_a2s (remote_addr,
			  remote_addrlen));
}
コード例 #16
0
ファイル: dnsstub.c プロジェクト: amatus/gnunet-debian
/**
 * Perform DNS resolution.
 *
 * @param ctx stub resolver to use
 * @param sa the socket address
 * @param sa_len the socket length
 * @param request DNS request to transmit
 * @param request_len number of bytes in msg
 * @param rc function to call with result
 * @param rc_cls closure for 'rc'
 * @return socket used for the request, NULL on error
 */
struct GNUNET_DNSSTUB_RequestSocket *
GNUNET_DNSSTUB_resolve (struct GNUNET_DNSSTUB_Context *ctx,
			const struct sockaddr *sa,
			socklen_t sa_len,
			const void *request,
			size_t request_len,
			GNUNET_DNSSTUB_ResultCallback rc,
			void *rc_cls)
{
  struct GNUNET_DNSSTUB_RequestSocket *rs;
  struct GNUNET_NETWORK_Handle *ret;
  int af;

  af = sa->sa_family;
  if (NULL == (rs = get_request_socket (ctx, af)))
    return NULL;
  if (NULL != rs->dnsout4)
    ret = rs->dnsout4;
  else
    ret = rs->dnsout6;
  GNUNET_assert (NULL != ret);
  memcpy (&rs->addr,
	  sa,
	  sa_len);
  rs->addrlen = sa_len;
  rs->rc = rc;
  rs->rc_cls = rc_cls;
  if (GNUNET_SYSERR == 
      GNUNET_NETWORK_socket_sendto (ret,
				    request,
				    request_len,
				    sa,
				    sa_len))
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
		_("Failed to send DNS request to %s\n"),
		GNUNET_a2s (sa, sa_len));
  else
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
		_("Sent DNS request to %s\n"),
		GNUNET_a2s (sa, sa_len));
  return rs;
}
コード例 #17
0
static void
udp_ipv4_broadcast_send (void *cls,
                         const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct Plugin *plugin = cls;
  int sent;
  uint16_t msg_size;
  char buf[65536] GNUNET_ALIGN;
  struct BroadcastAddress *baddr;

  plugin->send_ipv4_broadcast_task = GNUNET_SCHEDULER_NO_TASK;

  msg_size = prepare_beacon(plugin, (struct UDP_Beacon_Message *) &buf);
  sent = 0;
  baddr = plugin->ipv4_broadcast_head;
  /* just IPv4 */
  while ((msg_size > 0) && (baddr != NULL) && (baddr->addrlen == sizeof (struct sockaddr_in)))
  {
    struct sockaddr_in *addr = (struct sockaddr_in *) baddr->addr;

    addr->sin_port = htons (plugin->port);

    sent = GNUNET_NETWORK_socket_sendto (plugin->sockv4, &buf, msg_size,
                                      (const struct sockaddr *) addr,
                                      baddr->addrlen);
    if (sent == GNUNET_SYSERR)
    {
      if ((ENETUNREACH == errno) || (ENETDOWN == errno))
      {
        /* "Network unreachable" or "Network down"
         *
         * This indicates that we just do not have network connectivity
         */
        GNUNET_log (GNUNET_ERROR_TYPE_BULK | GNUNET_ERROR_TYPE_WARNING,
            "Network connectivity is down, cannot send beacon!\n");
      }
      else
        GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
    }
    else
    {
      LOG (GNUNET_ERROR_TYPE_DEBUG,
           "Sent HELLO beacon broadcast with %i bytes to address %s\n", sent,
           GNUNET_a2s (baddr->addr, baddr->addrlen));
    }
    baddr = baddr->next;
  }

  plugin->send_ipv4_broadcast_task =
      GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval,
                                    &udp_ipv4_broadcast_send, plugin);
}
コード例 #18
0
ファイル: gnunet-nat.c プロジェクト: GNUnet/gnunet
/**
 * Signature of the callback passed to #GNUNET_NAT_register() for
 * a function to call whenever our set of 'valid' addresses changes.
 *
 * @param cls closure, NULL
 * @param add_remove #GNUNET_YES to add a new public IP address, 
 *                   #GNUNET_NO to remove a previous (now invalid) one
 * @param ac address class the address belongs to
 * @param addr either the previous or the new public IP address
 * @param addrlen actual length of the @a addr
 */
static void
address_cb (void *cls,
	    int add_remove,
	    enum GNUNET_NAT_AddressClass ac,
	    const struct sockaddr *addr,
	    socklen_t addrlen)
{
  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
	      "%s %s (%d)\n",
	      add_remove ? "+" : "-",
	      GNUNET_a2s (addr,
			  addrlen),
	      (int) ac);
}
コード例 #19
0
ファイル: connection.c プロジェクト: h4ck3rm1k3/gnunet-debian
/**
 * Task invoked by the scheduler when a call to transmit
 * is timing out (we never got enough buffer space to call
 * the callback function before the specified timeout
 * expired).
 *
 * This task notifies the client about the timeout.
 *
 * @param cls the 'struct GNUNET_CONNECTION_Handle'
 * @param tc scheduler context
 */
static void
transmit_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct GNUNET_CONNECTION_Handle *connection = cls;
  GNUNET_CONNECTION_TransmitReadyNotify notify;

  connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK;
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Transmit to `%s:%u/%s' fails, time out reached (%p).\n",
       connection->hostname,
       connection->port, GNUNET_a2s (connection->addr, connection->addrlen), connection);
  notify = connection->nth.notify_ready;
  GNUNET_assert (NULL != notify);
  connection->nth.notify_ready = NULL;
  notify (connection->nth.notify_ready_cls, 0, NULL);
}
コード例 #20
0
ファイル: service.c プロジェクト: tg-x/gnunet
/**
 * Check if access to the service is allowed from the given address.
 *
 * @param cls closure
 * @param uc credentials, if available, otherwise NULL
 * @param addr address
 * @param addrlen length of address
 * @return #GNUNET_YES to allow, #GNUNET_NO to deny, #GNUNET_SYSERR
 *   for unknown address family (will be denied).
 */
static int
check_access (void *cls, const struct GNUNET_CONNECTION_Credentials *uc,
              const struct sockaddr *addr, socklen_t addrlen)
{
  struct GNUNET_SERVICE_Context *sctx = cls;
  const struct sockaddr_in *i4;
  const struct sockaddr_in6 *i6;
  int ret;

  switch (addr->sa_family)
  {
  case AF_INET:
    GNUNET_assert (addrlen == sizeof (struct sockaddr_in));
    i4 = (const struct sockaddr_in *) addr;
    ret = ((NULL == sctx->v4_allowed) ||
           (check_ipv4_listed (sctx->v4_allowed, &i4->sin_addr))) &&
        ((NULL == sctx->v4_denied) ||
         (!check_ipv4_listed (sctx->v4_denied, &i4->sin_addr)));
    break;
  case AF_INET6:
    GNUNET_assert (addrlen == sizeof (struct sockaddr_in6));
    i6 = (const struct sockaddr_in6 *) addr;
    ret = ((NULL == sctx->v6_allowed) ||
           (check_ipv6_listed (sctx->v6_allowed, &i6->sin6_addr))) &&
        ((NULL == sctx->v6_denied) ||
         (!check_ipv6_listed (sctx->v6_denied, &i6->sin6_addr)));
    break;
#ifndef WINDOWS
  case AF_UNIX:
    ret = GNUNET_OK;            /* controlled using file-system ACL now */
    break;
#endif
  default:
    LOG (GNUNET_ERROR_TYPE_WARNING, _("Unknown address family %d\n"),
         addr->sa_family);
    return GNUNET_SYSERR;
  }
  if (GNUNET_OK != ret)
  {
    LOG (GNUNET_ERROR_TYPE_WARNING,
         _("Access from `%s' denied to service `%s'\n"),
	 GNUNET_a2s (addr, addrlen),
         sctx->service_name);
  }
  return ret;
}
コード例 #21
0
/**
 * Callback for message stream tokenizer
 *
 * @param cls the session
 * @param client not used
 * @param message the message received
 * @return always GNUNET_OK
 */
static int
client_receive_mst_cb (void *cls, void *client,
                       const struct GNUNET_MessageHeader *message)
{
  struct Session *s = cls;
  struct HTTP_Client_Plugin *plugin;
  struct GNUNET_TIME_Relative delay;
  struct GNUNET_ATS_Information atsi[2];
  char *stat_txt;
  if (GNUNET_YES != client_exist_session(p, s))
  {
    GNUNET_break (0);
    return GNUNET_OK;
  }
  plugin = s->plugin;

  atsi[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
  atsi[0].value = htonl (1);
  atsi[1].type = htonl (GNUNET_ATS_NETWORK_TYPE);
  atsi[1].value = s->ats_address_network_type;
  GNUNET_break (s->ats_address_network_type != ntohl (GNUNET_ATS_NET_UNSPECIFIED));

  delay = s->plugin->env->receive (plugin->env->cls, &s->target, message,
                                   (const struct GNUNET_ATS_Information *) &atsi, 2,
                                   s, s->addr, s->addrlen);

  GNUNET_asprintf (&stat_txt, "# bytes received via %s_client", plugin->protocol);
  GNUNET_STATISTICS_update (plugin->env->stats,
                            stat_txt, ntohs(message->size), GNUNET_NO);
  GNUNET_free (stat_txt);

  s->next_receive =
      GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), delay);

  if (GNUNET_TIME_absolute_get ().abs_value < s->next_receive.abs_value)
  {

    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
                     "Client: peer `%s' address `%s' next read delayed for %llu ms\n",
                     GNUNET_i2s (&s->target), GNUNET_a2s (s->addr, s->addrlen),
                     delay);
  }
  client_reschedule_session_timeout (s);
  return GNUNET_OK;
}
コード例 #22
0
static void
udp_ipv6_broadcast_send (void *cls,
                         const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct Plugin *plugin = cls;
  int sent;
  uint16_t msg_size;
  char buf[65536] GNUNET_ALIGN;

  plugin->send_ipv6_broadcast_task = GNUNET_SCHEDULER_NO_TASK;

  msg_size = prepare_beacon(plugin, (struct UDP_Beacon_Message *) &buf);
  sent = 0;
  sent = GNUNET_NETWORK_socket_sendto (plugin->sockv6, &buf, msg_size,
                                    (const struct sockaddr *)
                                    &plugin->ipv6_multicast_address,
                                    sizeof (struct sockaddr_in6));
  if (sent == GNUNET_SYSERR)
  {
    if ((ENETUNREACH == errno) || (ENETDOWN == errno))
    {
      /* "Network unreachable" or "Network down"
       *
       * This indicates that this system is IPv6 enabled, but does not
       * have a valid global IPv6 address assigned
       */
      GNUNET_log (GNUNET_ERROR_TYPE_BULK | GNUNET_ERROR_TYPE_WARNING,
          "Network connectivity is down, cannot send beacon!\n");
    }
    else
      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
  }
  else
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Sending IPv6 HELLO beacon broadcast with  %i bytes to address %s\n",
         sent,
         GNUNET_a2s ((const struct sockaddr *) &plugin->ipv6_multicast_address,
                     sizeof (struct sockaddr_in6)));
  }
  plugin->send_ipv6_broadcast_task =
      GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval,
                                    &udp_ipv6_broadcast_send, plugin);
}
コード例 #23
0
ファイル: test_nat_mini.c プロジェクト: GNUnet/gnunet
/**
 * Function called on each address that the NAT service
 * believes to be valid for the transport.
 */
static void
addr_callback (void *cls, int add_remove,
               const struct sockaddr *addr,
               socklen_t addrlen,
               enum GNUNET_NAT_StatusCode ret)
{
  if (GNUNET_NAT_ERROR_SUCCESS == ret)
  {
    fprintf (stderr,
           "Address changed: %s `%s' (%u bytes)\n",
           add_remove == GNUNET_YES
           ? "added" : "removed",
           GNUNET_a2s (addr,
                       addrlen),
           (unsigned int) addrlen);
  }
  else
    ;
    //TODO: proper error handling!
}
コード例 #24
0
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);
  }
}
コード例 #25
0
/**
 * Our external IP address/port mapping has changed.
 *
 * @param cls closure, the 'struct LocalAddrList'
 * @param add_remove GNUNET_YES to mean the new public IP address, GNUNET_NO to mean
 *     the previous (now invalid) one
 * @param addr either the previous or the new public IP address
 * @param addrlen actual lenght of the address
 */
static void
nat_port_map_callback (void *cls, int add_remove, const struct sockaddr *addr,
                       socklen_t addrlen)
{
  GNUNET_assert (cls != NULL);
  struct Plugin *plugin = cls;

  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
                   "NPMC called %s to address `%s'\n",
                   (add_remove == GNUNET_NO) ? "remove" : "add",
                   GNUNET_a2s (addr, addrlen));

  switch (add_remove)
  {
  case GNUNET_YES:
    nat_add_address (cls, add_remove, addr, addrlen);
    break;
  case GNUNET_NO:
    nat_remove_address (cls, add_remove, addr, addrlen);
    break;
  }
}
コード例 #26
0
ファイル: connection.c プロジェクト: h4ck3rm1k3/gnunet-debian
/**
 * 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);
}
コード例 #27
0
ファイル: connection.c プロジェクト: h4ck3rm1k3/gnunet-debian
/**
 * 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;
}
コード例 #28
0
ファイル: connection.c プロジェクト: h4ck3rm1k3/gnunet-debian
/**
 * We are ready to transmit (or got a timeout).
 *
 * @param cls our connection handle
 * @param tc task context describing why we are here
 */
static void
transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct GNUNET_CONNECTION_Handle *connection = cls;
  GNUNET_CONNECTION_TransmitReadyNotify notify;
  ssize_t ret;
  size_t have;

  LOG (GNUNET_ERROR_TYPE_DEBUG, "transmit_ready running (%p).\n", connection);
  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != connection->write_task);
  connection->write_task = GNUNET_SCHEDULER_NO_TASK;
  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->nth.timeout_task);
  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
  {
    if (NULL != connection->sock)
      goto SCHEDULE_WRITE;      /* ignore shutdown, go again immediately */
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Transmit to `%s' fails, shutdown happened (%p).\n",
         GNUNET_a2s (connection->addr, connection->addrlen), connection);
    notify = connection->nth.notify_ready;
    if (NULL != notify)
    {
      connection->nth.notify_ready = NULL;
      notify (connection->nth.notify_ready_cls, 0, NULL);
    }
    return;
  }
  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT))
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Transmit to `%s' fails, time out reached (%p).\n",
         GNUNET_a2s (connection->addr, connection->addrlen), connection);
    notify = connection->nth.notify_ready;
    GNUNET_assert (NULL != notify);
    connection->nth.notify_ready = NULL;
    notify (connection->nth.notify_ready_cls, 0, NULL);
    return;
  }
  GNUNET_assert (NULL != connection->sock);
  if (NULL == tc->write_ready) 
  {
    /* special circumstances (in particular, PREREQ_DONE after
     * connect): not yet ready to write, but no "fatal" error either.
     * Hence retry.  */
    goto SCHEDULE_WRITE;
  }
  if (!GNUNET_NETWORK_fdset_isset (tc->write_ready, connection->sock))
  {
    GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->write_task);
    /* special circumstances (in particular, shutdown): not yet ready
     * to write, but no "fatal" error either.  Hence retry.  */
    goto SCHEDULE_WRITE;
  }
  GNUNET_assert (connection->write_buffer_off >= connection->write_buffer_pos);
  if ((NULL != connection->nth.notify_ready) &&
      (connection->write_buffer_size < connection->nth.notify_size))
  {
    connection->write_buffer =
        GNUNET_realloc (connection->write_buffer, connection->nth.notify_size);
    connection->write_buffer_size = connection->nth.notify_size;
  }
  process_notify (connection);
  have = connection->write_buffer_off - connection->write_buffer_pos;
  if (0 == have)
  {
    /* no data ready for writing, terminate write loop */
    return;
  }
  GNUNET_assert (have <= connection->write_buffer_size);
  GNUNET_assert (have + connection->write_buffer_pos <= connection->write_buffer_size);
  GNUNET_assert (connection->write_buffer_pos <= connection->write_buffer_size);
RETRY:
  ret =
      GNUNET_NETWORK_socket_send (connection->sock,
				  &connection->write_buffer[connection->write_buffer_pos],
				  have);
  if (-1 == ret)
  {
    if (EINTR == errno)
      goto RETRY;
    if (GNUNET_SCHEDULER_NO_TASK != connection->write_task)
    {
      GNUNET_SCHEDULER_cancel (connection->write_task);
      connection->write_task = GNUNET_SCHEDULER_NO_TASK;
    }
    signal_transmit_error (connection, errno);
    return;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Connection transmitted %u/%u bytes to `%s' (%p)\n",
       (unsigned int) ret, have, GNUNET_a2s (connection->addr, connection->addrlen), connection);
  connection->write_buffer_pos += ret;
  if (connection->write_buffer_pos == connection->write_buffer_off)
  {
    /* transmitted all pending data */
    connection->write_buffer_pos = 0;
    connection->write_buffer_off = 0;
  }
  if ((0 == connection->write_buffer_off) && (NULL == connection->nth.notify_ready))
    return;                     /* all data sent! */
  /* not done writing, schedule more */
SCHEDULE_WRITE:
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Re-scheduling transmit_ready (more to do) (%p).\n", connection);
  have = connection->write_buffer_off - connection->write_buffer_pos;
  GNUNET_assert ((NULL != connection->nth.notify_ready) || (have > 0));
  if (GNUNET_SCHEDULER_NO_TASK == connection->write_task)
    connection->write_task =
        GNUNET_SCHEDULER_add_write_net ((connection->nth.notify_ready ==
                                         NULL) ? GNUNET_TIME_UNIT_FOREVER_REL :
                                        GNUNET_TIME_absolute_get_remaining
                                        (connection->nth.transmit_timeout),
                                        connection->sock, &transmit_ready, connection);
}
コード例 #29
0
ファイル: resolver_api.c プロジェクト: amatus/gnunet-debian
/**
 * Process response with a hostname for a DNS lookup.
 *
 * @param cls our "struct GNUNET_RESOLVER_RequestHandle" context
 * @param msg message with the hostname, NULL on error
 */
static void
handle_response (void *cls, const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_RESOLVER_RequestHandle *rh = cls;
  uint16_t size;

  LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving response from DNS service\n");
  if (msg == NULL)
  {
    char buf[INET6_ADDRSTRLEN];

    if (NULL != rh->name_callback)
      LOG (GNUNET_ERROR_TYPE_INFO,
           _("Timeout trying to resolve IP address `%s'.\n"),
           inet_ntop (rh->af, (const void *) &rh[1], buf, sizeof(buf)));
    else
      LOG (GNUNET_ERROR_TYPE_INFO,
           _("Timeout trying to resolve hostname `%s'.\n"),
           (const char *) &rh[1]);
    /* check if request was canceled */
    if (rh->was_transmitted != GNUNET_SYSERR)
    {
      if (NULL != rh->name_callback)
      {
        /* no reverse lookup was successful, return ip as string */
        if (rh->received_response == GNUNET_NO)
          rh->name_callback (rh->cls,
                             no_resolve (rh->af,
					 &rh[1],
                                         rh->data_len));
        /* at least one reverse lookup was successful */
        else
          rh->name_callback (rh->cls, NULL);
      }
      if (NULL != rh->addr_callback)
        rh->addr_callback (rh->cls, NULL, 0);
    }
    GNUNET_CONTAINER_DLL_remove (req_head, req_tail, rh);
    GNUNET_free (rh);
    GNUNET_CLIENT_disconnect (client);
    client = NULL;
    reconnect ();
    return;
  }
  if (GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE != ntohs (msg->type))
  {
    GNUNET_break (0);
    GNUNET_CLIENT_disconnect (client);
    client = NULL;
    reconnect ();
    return;
  }
  size = ntohs (msg->size);
  /* message contains not data, just header */
  if (size == sizeof (struct GNUNET_MessageHeader))
  {
    /* check if request was canceled */
    if (rh->was_transmitted != GNUNET_SYSERR)
    {
      if (NULL != rh->name_callback)
        rh->name_callback (rh->cls, NULL);
      if (NULL != rh->addr_callback)
        rh->addr_callback (rh->cls, NULL, 0);
    }
    GNUNET_CONTAINER_DLL_remove (req_head, req_tail, rh);
    GNUNET_free (rh);
    process_requests ();
    return;
  }
  /* return reverse lookup results to caller */
  if (NULL != rh->name_callback)
  {
    const char *hostname;

    hostname = (const char *) &msg[1];
    if (hostname[size - sizeof (struct GNUNET_MessageHeader) - 1] != '\0')
    {
      GNUNET_break (0);
      if (rh->was_transmitted != GNUNET_SYSERR)
        rh->name_callback (rh->cls, NULL);
      GNUNET_CONTAINER_DLL_remove (req_head, req_tail, rh);
      GNUNET_free (rh);
      GNUNET_CLIENT_disconnect (client);
      client = NULL;
      reconnect ();
      return;
    }
    LOG (GNUNET_ERROR_TYPE_DEBUG, "Resolver returns `%s' for IP `%s'.\n",
         hostname, GNUNET_a2s ((const void *) &rh[1], rh->data_len));
    if (rh->was_transmitted != GNUNET_SYSERR)
      rh->name_callback (rh->cls, hostname);
    rh->received_response = GNUNET_YES;
    GNUNET_CLIENT_receive (client, &handle_response, rh,
                           GNUNET_TIME_absolute_get_remaining (rh->timeout));
  }
  /* return lookup results to caller */
  if (NULL != rh->addr_callback)
  {
    struct sockaddr_in v4;
    struct sockaddr_in6 v6;
    const struct sockaddr *sa;
    socklen_t salen;
    const void *ip;
    size_t ip_len;

    ip = &msg[1];
    ip_len = size - sizeof (struct GNUNET_MessageHeader);
    if (ip_len == sizeof (struct in_addr))
    {
      memset (&v4, 0, sizeof (v4));
      v4.sin_family = AF_INET;
      v4.sin_addr = *(struct in_addr*) ip;
#if HAVE_SOCKADDR_IN_SIN_LEN
      v4.sin_len = sizeof (v4);
#endif
      salen = sizeof (v4);
      sa = (const struct sockaddr *) &v4;
    }
    else if (ip_len == sizeof (struct in6_addr))
    {
      memset (&v6, 0, sizeof (v6));
      v6.sin6_family = AF_INET6;
      v6.sin6_addr = *(struct in6_addr*) ip;
#if HAVE_SOCKADDR_IN_SIN_LEN
      v6.sin6_len = sizeof (v6);
#endif
      salen = sizeof (v6);
      sa = (const struct sockaddr *) &v6;
    }
    else
    {
      GNUNET_break (0);
      if (rh->was_transmitted != GNUNET_SYSERR)
        rh->addr_callback (rh->cls, NULL, 0);
      GNUNET_CONTAINER_DLL_remove (req_head, req_tail, rh);
      GNUNET_free (rh);
      GNUNET_CLIENT_disconnect (client);
      client = NULL;
      reconnect ();
      return;
    }
    rh->addr_callback (rh->cls, sa, salen);
    GNUNET_CLIENT_receive (client, &handle_response, rh,
                           GNUNET_TIME_absolute_get_remaining (rh->timeout));
  }
}
コード例 #30
0
/**
 * Callback function invoked for each interface found.
 *
 * @param cls closure with the `struct Plugin`
 * @param name name of the interface (can be NULL for unknown)
 * @param isDefault is this presumably the default interface
 * @param addr address of this interface (can be NULL for unknown or unassigned)
 * @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 length of the address
 * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort
 */
static int
iface_proc (void *cls,
            const char *name,
            int isDefault,
            const struct sockaddr *addr,
            const struct sockaddr *broadcast_addr,
            const struct sockaddr *netmask, socklen_t addrlen)
{
  struct Plugin *plugin = cls;
  struct BroadcastAddress *ba;
  enum GNUNET_ATS_Network_Type network;

  if (NULL == addr)
    return GNUNET_OK;
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "address %s for interface %s %p\n ",
              GNUNET_a2s (addr, addrlen), name, addr);
  if (NULL == broadcast_addr)
    return GNUNET_OK;
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "broadcast address %s for interface %s %p\n ",
              GNUNET_a2s (broadcast_addr, addrlen), name, broadcast_addr);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "netmask %s for interface %s %p\n ",
              GNUNET_a2s (netmask, addrlen), name, netmask);

  network = plugin->env->get_address_type (plugin->env->cls, broadcast_addr, addrlen);
  if (GNUNET_ATS_NET_LOOPBACK == network)
  {
    /* Broadcasting on loopback does not make sense */
    return GNUNET_YES;
  }

  ba = GNUNET_new (struct BroadcastAddress);
  ba->plugin = plugin;
  ba->addr = GNUNET_malloc (addrlen);
  GNUNET_memcpy (ba->addr, broadcast_addr, addrlen);
  ba->addrlen = addrlen;

  if ( (GNUNET_YES == plugin->enable_ipv4) &&
       (NULL != plugin->sockv4) &&
       (addrlen == sizeof (struct sockaddr_in)) )
  {
#if LINUX
    /*
     * setup Cryogenic FD for ipv4 broadcasting
     */
    char *filename;

    GNUNET_asprintf (&filename,
                     "/dev/cryogenic/%s",
                     name);
    if (0 == ACCESS (name, R_OK))
    {
      ba->cryogenic_fd =
        GNUNET_DISK_file_open (filename,
                               GNUNET_DISK_OPEN_WRITE,
                               GNUNET_DISK_PERM_NONE);
    }
    GNUNET_free (filename);
#endif
    ba->broadcast_task =
        GNUNET_SCHEDULER_add_now (&udp_ipv4_broadcast_send, ba);
  }
  if ((GNUNET_YES == plugin->enable_ipv6) &&
      (NULL != plugin->sockv6) &&
      (addrlen == sizeof (struct sockaddr_in6)))
  {
    /* Create IPv6 multicast request */
    struct ipv6_mreq multicastRequest;
    const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) broadcast_addr;

    multicastRequest.ipv6mr_multiaddr =
        plugin->ipv6_multicast_address.sin6_addr;
    /* http://tools.ietf.org/html/rfc2553#section-5.2:
     *
     * IPV6_JOIN_GROUP
     *
     * Join a multicast group on a specified local interface.  If the
     * interface index is specified as 0, the kernel chooses the local
     * interface.  For example, some kernels look up the multicast
     * group in the normal IPv6 routing table and using the resulting
     * interface; we do this for each interface, so no need to use
     * zero (anymore...).
     */
    multicastRequest.ipv6mr_interface = s6->sin6_scope_id;

    /* Join the multicast group */
    if (GNUNET_OK !=
        GNUNET_NETWORK_socket_setsockopt
        (plugin->sockv6, IPPROTO_IPV6, IPV6_JOIN_GROUP,
         &multicastRequest, sizeof (multicastRequest)))
    {
      LOG (GNUNET_ERROR_TYPE_WARNING,
      "Failed to join IPv6 multicast group: IPv6 broadcasting not running\n");
    }
    else
    {
#if LINUX
      /*
       * setup Cryogenic FD for ipv6 broadcasting
       */
      char *filename;

      GNUNET_asprintf (&filename,
                       "/dev/cryogenic/%s",
                       name);
      if (0 == ACCESS (name, R_OK))
      {
        ba->cryogenic_fd =
          GNUNET_DISK_file_open (filename,
                                 GNUNET_DISK_OPEN_WRITE,
                                 GNUNET_DISK_PERM_NONE);
      }
      GNUNET_free (filename);
#endif
      ba->broadcast_task =
          GNUNET_SCHEDULER_add_now (&udp_ipv6_broadcast_send, ba);
    }
  }
  GNUNET_CONTAINER_DLL_insert (plugin->broadcast_head,
                               plugin->broadcast_tail, ba);
  return GNUNET_OK;
}