/**
 * Setup our service record for the given section in the configuration file
 * (assuming the section is for a service).
 *
 * @param cls unused
 * @param section a section in the configuration file
 * @return GNUNET_OK (continue)
 */
static void
setup_service (void *cls, const char *section)
{
  struct ServiceList *sl;
  char *binary;
  char *config;
  struct stat sbuf;
  struct sockaddr **addrs;
  socklen_t *addr_lens;
  int ret;
  unsigned int i;

  if (strcasecmp (section, "arm") == 0)
    return;
  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_string (cfg, section, "BINARY", &binary))
    {
      /* not a service section */
      return;
    }
  sl = find_service (section);
  if (NULL != sl)
  {
    /* got the same section twice!? */
    GNUNET_break (0);
    return;
  }
  config = NULL;
  if ((GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_filename (cfg, section, "CONFIG",
						&config)) ||
      (0 != STAT (config, &sbuf)))
    {
      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
		  _
		  ("Configuration file `%s' for service `%s' not valid: %s\n"),
		  config, section,
		  (config == NULL) ? _("option missing") : STRERROR (errno));
      GNUNET_free (binary);
      GNUNET_free_non_null (config);
      return;
    }
  sl = GNUNET_malloc (sizeof (struct ServiceList));
  sl->name = GNUNET_strdup (section);
  sl->binary = binary;
  sl->config = config;
  sl->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
  sl->restart_at = GNUNET_TIME_UNIT_FOREVER_ABS;
#if WINDOWS
  sl->pipe_control = GNUNET_YES;
#else
  if (GNUNET_CONFIGURATION_have_value (cfg, section, "PIPECONTROL"))
    sl->pipe_control = GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "PIPECONTROL");
#endif  
  GNUNET_CONTAINER_DLL_insert (running_head, running_tail, sl);
  if (GNUNET_YES !=
      GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "AUTOSTART"))
    return;
  if (0 >= (ret = GNUNET_SERVICE_get_server_addresses (section, cfg,
						       &addrs, &addr_lens)))
    return;
  /* this will free (or capture) addrs[i] */
  for (i = 0; i < ret; i++)
    create_listen_socket (addrs[i], addr_lens[i], sl);
  GNUNET_free (addrs);
  GNUNET_free (addr_lens);
}
Exemple #2
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;
}