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