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);
}
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);
}