/**
 * 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);
}
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);
}
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);
}
Beispiel #4
0
/**
 * 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;
}
static void
udp_ipv6_broadcast_send (void *cls)
{
  struct BroadcastAddress *baddr = cls;
  struct Plugin *plugin = baddr->plugin;
  ssize_t sent;
  uint16_t msg_size;
  char buf[65536] GNUNET_ALIGN;
  const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) baddr->addr;

  baddr->broadcast_task = NULL;

  msg_size = prepare_beacon(plugin, (struct UDP_Beacon_Message *) &buf);
  /* Note: unclear if this actually works to limit the multicast to
     the specified interface as we're not (necessarily) using a
     link-local multicast group and the kernel suggests that the
     scope ID is only respected for link-local addresses; however,
     if the scope ID is ignored, the kernel should just multicast
     on ALL interfaces, which is merely slightly less efficient;
     in that case, we might want to revert to only doing this
     once, and not per interface (hard to test...) */
  plugin->ipv6_multicast_address.sin6_scope_id = s6->sin6_scope_id;
  sent = GNUNET_NETWORK_socket_sendto (plugin->sockv6, &buf, msg_size,
                                    (const struct sockaddr *)
                                    &plugin->ipv6_multicast_address,
                                    sizeof (struct sockaddr_in6));
  plugin->ipv6_multicast_address.sin6_scope_id = 0;
  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 %d bytes to address %s\n",
         (int) sent,
         GNUNET_a2s ((const struct sockaddr *) &plugin->ipv6_multicast_address,
                     sizeof (struct sockaddr_in6)));
  }
#if LINUX
  /*
   * Cryogenic
   */
  if (NULL != baddr->cryogenic_fd)
  {
    baddr->cryogenic_times.delay_msecs = (plugin->broadcast_interval.rel_value_us/1000.0)*0.5;
    baddr->cryogenic_times.timeout_msecs = (plugin->broadcast_interval.rel_value_us/1000.0)*1.5;

    if (ioctl(baddr->cryogenic_fd->fd,
    		  PM_SET_DELAY_AND_TIMEOUT,
    		  &baddr->cryogenic_times) < 0)
    {
      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctl");
      baddr->broadcast_task =
          GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval,
                                        &udp_ipv6_broadcast_send, baddr);
    }
    else
      GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
    		                       baddr->cryogenic_fd,
                                       &udp_ipv6_broadcast_send,
                                       baddr);
  }
  else
#endif
    baddr->broadcast_task =
        GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval,
                                      &udp_ipv6_broadcast_send, baddr);
}
static void
udp_ipv4_broadcast_send (void *cls)
{
  struct BroadcastAddress *baddr = cls;
  struct Plugin *plugin = baddr->plugin;
  int sent;
  uint16_t msg_size;
  char buf[65536] GNUNET_ALIGN;

  baddr->broadcast_task = NULL;

  msg_size = prepare_beacon(plugin, (struct UDP_Beacon_Message *) &buf);
  if (0 != msg_size)
  {
    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));
    }
  }

#if LINUX
  /*
   * Cryogenic
   */
  if (NULL != baddr->cryogenic_fd)
  {
    baddr->cryogenic_times.delay_msecs = (plugin->broadcast_interval.rel_value_us/1000.0)*0.5;
    baddr->cryogenic_times.timeout_msecs = (plugin->broadcast_interval.rel_value_us/1000.0)*1.5;

    if (ioctl(baddr->cryogenic_fd->fd,
    		  PM_SET_DELAY_AND_TIMEOUT,
    		  &baddr->cryogenic_times) < 0)
    {
      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctl");
      baddr->broadcast_task =
          GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval,
      	                                &udp_ipv4_broadcast_send, baddr);
    }
    else
      GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
    		                           baddr->cryogenic_fd,
        		                       &udp_ipv4_broadcast_send,
        		                       baddr);

  }
  else
#endif
    baddr->broadcast_task =
        GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval,
	                                  &udp_ipv4_broadcast_send, baddr);
}
Beispiel #7
0
/**
 * Perform DNS resolution using our default IP from init.
 *
 * @param ctx stub resolver to use
 * @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_resolve2 (struct GNUNET_DNSSTUB_Context *ctx,
			 const void *request,
			 size_t request_len,
			 GNUNET_DNSSTUB_ResultCallback rc,
			 void *rc_cls)
{
  int af;
  struct sockaddr_in v4;
  struct sockaddr_in6 v6;
  struct sockaddr *sa;
  socklen_t salen;
  struct GNUNET_NETWORK_Handle *dnsout;
  struct GNUNET_DNSSTUB_RequestSocket *rs;

  memset (&v4, 0, sizeof (v4));
  memset (&v6, 0, sizeof (v6));
  if (1 == inet_pton (AF_INET, ctx->dns_exit, &v4.sin_addr))
  {
    salen = sizeof (v4);
    v4.sin_family = AF_INET;
    v4.sin_port = htons (53);
#if HAVE_SOCKADDR_IN_SIN_LEN
    v4.sin_len = (u_char) salen;
#endif
    sa = (struct sockaddr *) &v4;
    af = AF_INET;
  }
  else if (1 == inet_pton (AF_INET6, ctx->dns_exit, &v6.sin6_addr))
  {
    salen = sizeof (v6);
    v6.sin6_family = AF_INET6;
    v6.sin6_port = htons (53);
#if HAVE_SOCKADDR_IN_SIN_LEN
    v6.sin6_len = (u_char) salen;
#endif
    sa = (struct sockaddr *) &v6;
    af = AF_INET6;
  }  
  else
  {
    GNUNET_break (0);
    return NULL;
  }
  if (NULL == (rs = get_request_socket (ctx, af)))
    return NULL;
  if (NULL != rs->dnsout4)
    dnsout = rs->dnsout4;
  else
    dnsout = rs->dnsout6;
  if (NULL == dnsout)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
		_("Configured DNS exit `%s' is not working / valid.\n"),
		ctx->dns_exit);
    return NULL;
  }
  memcpy (&rs->addr,
	  sa,
	  salen);
  rs->addrlen = salen;
  rs->rc = rc;
  rs->rc_cls = rc_cls;
  if (GNUNET_SYSERR ==
      GNUNET_NETWORK_socket_sendto (dnsout,
				    request,
				    request_len, sa, salen))
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
		_("Failed to send DNS request to %s\n"),
		GNUNET_a2s (sa, salen));
  rs->timeout = GNUNET_TIME_relative_to_absolute (REQUEST_TIMEOUT);
  
  return rs;

}