/**
 * Main function that will be run.
 *
 * @param cls closure
 * @param args remaining command-line arguments
 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
 * @param c configuration
 */
static void
run (void *cls, char *const *args, const char *cfgfile,
     const struct GNUNET_CONFIGURATION_Handle *c)
{
  static struct GNUNET_CORE_MessageHandler handlers[] = {
    {&handle_encrypted_hello, GNUNET_MESSAGE_TYPE_HELLO, 0},
    {NULL, 0, 0}
  };
  unsigned long long opt;

  cfg = c;
  stats = GNUNET_STATISTICS_create ("topology", cfg);
  friends_only =
      GNUNET_CONFIGURATION_get_value_yesno (cfg, "TOPOLOGY", "FRIENDS-ONLY");
  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_number (cfg, "TOPOLOGY", "MINIMUM-FRIENDS",
                                             &opt))
    opt = 0;
  minimum_friend_count = (unsigned int) opt;
  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_number (cfg, "TOPOLOGY",
                                             "TARGET-CONNECTION-COUNT", &opt))
    opt = 16;
  target_connection_count = (unsigned int) opt;
  peers = GNUNET_CONTAINER_multihashmap_create (target_connection_count * 2, GNUNET_NO);

  if ((friends_only == GNUNET_YES) || (minimum_friend_count > 0))
    read_friends_file (cfg);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Topology would like %u connections with at least %u friends\n",
              target_connection_count, minimum_friend_count);
  if ((friend_count < minimum_friend_count) && (blacklist == NULL))
    blacklist = GNUNET_TRANSPORT_blacklist (cfg, &blacklist_check, NULL);
  transport = GNUNET_TRANSPORT_connect (cfg, NULL, NULL, NULL, NULL, NULL);
  handle =
      GNUNET_CORE_connect (cfg, NULL, &core_init, &connect_notify,
                           &disconnect_notify, NULL, GNUNET_NO, NULL, GNUNET_NO,
                           handlers);
  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleaning_task,
                                NULL);
  if (NULL == transport)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                _("Failed to connect to `%s' service.\n"), "transport");
    GNUNET_SCHEDULER_shutdown ();
    return;
  }
  if (NULL == handle)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                _("Failed to connect to `%s' service.\n"), "core");
    GNUNET_SCHEDULER_shutdown ();
    return;
  }
}
/**
 * Setup broadcasting subsystem.
 *
 * @param plugin
 * @param server_addrv6
 * @param server_addrv4
 */
void
setup_broadcast (struct Plugin *plugin,
                 struct sockaddr_in6 *server_addrv6,
                 struct sockaddr_in *server_addrv4)
{
  if (GNUNET_YES ==
      GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg,
                                            "topology",
                                            "FRIENDS-ONLY"))
  {
    LOG (GNUNET_ERROR_TYPE_WARNING,
         _("Disabling HELLO broadcasting due to friend-to-friend only configuration!\n"));
    return;
  }

  /* always create tokenizers */
  plugin->broadcast_mst =
    GNUNET_SERVER_mst_create (&broadcast_mst_cb, plugin);

  if (GNUNET_YES != plugin->enable_broadcasting)
    return; /* We do not send, just receive */

  /* create IPv4 broadcast socket */
  if ((GNUNET_YES == plugin->enable_ipv4) && (NULL != plugin->sockv4))
  {
    static int yes = 1;

    if (GNUNET_NETWORK_socket_setsockopt
        (plugin->sockv4, SOL_SOCKET, SO_BROADCAST, &yes,
         sizeof (int)) != GNUNET_OK)
    {
      LOG (GNUNET_ERROR_TYPE_WARNING,
           _("Failed to set IPv4 broadcast option for broadcast socket on port %d\n"),
           ntohs (server_addrv4->sin_port));
    }
  }
  /* create IPv6 multicast socket */
  if ((GNUNET_YES == plugin->enable_ipv6) && (plugin->sockv6 != NULL))
  {
    memset (&plugin->ipv6_multicast_address, 0, sizeof (struct sockaddr_in6));
    GNUNET_assert (1 ==
                   inet_pton (AF_INET6, "FF05::13B",
                              &plugin->ipv6_multicast_address.sin6_addr));
    plugin->ipv6_multicast_address.sin6_family = AF_INET6;
    plugin->ipv6_multicast_address.sin6_port = htons (plugin->port);
  }
  GNUNET_OS_network_interfaces_list (&iface_proc, plugin);
}
예제 #3
0
파일: nat_auto.c 프로젝트: muggenhor/GNUnet
/**
 * Test if ICMP server is working
 *
 * @param ah auto setup context
 */
static void
test_icmp_server (struct GNUNET_NAT_AutoHandle *ah)
{

  int ext_ip;
  int nated;
  int binary;
  char *tmp;
  char *helper;
  ext_ip = GNUNET_NO;
  nated = GNUNET_NO;
  binary = GNUNET_NO;

  tmp = NULL;
  helper = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server");
  if ((GNUNET_OK ==
        GNUNET_CONFIGURATION_get_value_string (ah->cfg, "nat", "EXTERNAL_ADDRESS",
                                               &tmp)) && (0 < strlen (tmp))){
    ext_ip = GNUNET_OK;
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("test_icmp_server not possible, as we have no public IPv4 address\n"));
  }
  else
    goto err;

  if (GNUNET_YES ==
        GNUNET_CONFIGURATION_get_value_yesno (ah->cfg, "nat", "BEHIND_NAT")){
    nated = GNUNET_YES;
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("test_icmp_server not possible, as we are not behind NAT\n"));
  }
  else
    goto err;

  if (GNUNET_YES ==
        GNUNET_OS_check_helper_binary (helper, GNUNET_YES, "-d 127.0.0.1" )){
    binary = GNUNET_OK; // use localhost as source for that one udp-port, ok for testing
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("No working gnunet-helper-nat-server found\n"));
  }
err:
  GNUNET_free_non_null (tmp);
  GNUNET_free (helper);

  if (GNUNET_OK == ext_ip && GNUNET_YES == nated && GNUNET_OK == binary)
    ah->task = GNUNET_SCHEDULER_add_now (&reversal_test, ah);
  else
    next_phase (ah);

}
예제 #4
0
파일: nat_auto.c 프로젝트: muggenhor/GNUnet
/**
 * Test if ICMP client is working
 *
 * @param ah auto setup context
 */
static void
test_icmp_client (struct GNUNET_NAT_AutoHandle *ah)
{


  char *tmp;
  char *helper;

  tmp = NULL;
  helper = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client");
  if ((GNUNET_OK ==
        GNUNET_CONFIGURATION_get_value_string (ah->cfg, "nat", "INTERNAL_ADDRESS",
                                               &tmp)) && (0 < strlen (tmp)))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("test_icmp_client not possible, as we have no internal IPv4 address\n"));
  }
  else
    goto err;

  if (GNUNET_YES !=
      GNUNET_CONFIGURATION_get_value_yesno (ah->cfg, "nat", "BEHIND_NAT")){
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("test_icmp_server not possible, as we are not behind NAT\n"));
  }
  else
    goto err;

  if (GNUNET_YES ==
      GNUNET_OS_check_helper_binary (helper, GNUNET_YES, "-d 127.0.0.1 127.0.0.2 42")){
          // none of these parameters are actually used in privilege testing mode
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("No working gnunet-helper-nat-server found\n"));
  }
err:
  GNUNET_free_non_null (tmp);
  GNUNET_free (helper);

  next_phase (ah);

}
예제 #5
0
/**
 * Actually start the process for the given service.
 *
 * @param sl identifies service to start
 */
static void
start_process (struct ServiceList *sl)
{
  char *loprefix;
  char *options;
  char *optpos;
  char *optend;
  const char *next;
  int use_debug;
  char b;
  char *val;
  struct ServiceListeningInfo *sli;
  SOCKTYPE *lsocks;
  unsigned int ls;

  /* calculate listen socket list */
  lsocks = NULL;
  ls = 0;
  for (sli = sl->listen_head; NULL != sli; sli = sli->next)
    {
      GNUNET_array_append (lsocks, ls,
			   GNUNET_NETWORK_get_fd (sli->listen_socket));
      if (sli->accept_task != GNUNET_SCHEDULER_NO_TASK)
	{
	  GNUNET_SCHEDULER_cancel (sli->accept_task);
	  sli->accept_task = GNUNET_SCHEDULER_NO_TASK;
	}
    }
#if WINDOWS
  GNUNET_array_append (lsocks, ls, INVALID_SOCKET);
#else
  GNUNET_array_append (lsocks, ls, -1);
#endif

  /* obtain configuration */
  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_string (cfg, sl->name, "PREFIX",
					     &loprefix))
    loprefix = GNUNET_strdup (prefix_command);
  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_string (cfg, sl->name, "OPTIONS",
					     &options))
    {
      options = GNUNET_strdup (final_option);
      if (NULL == strstr (options, "%"))
	{
	  /* replace '{}' with service name */
	  while (NULL != (optpos = strstr (options, "{}")))
	    {
	      optpos[0] = '%';
	      optpos[1] = 's';
	      GNUNET_asprintf (&optpos, options, sl->name);
	      GNUNET_free (options);
	      options = optpos;
	    }
	  /* replace '$PATH' with value associated with "PATH" */
	  while (NULL != (optpos = strstr (options, "$")))
	    {
	      optend = optpos + 1;
	      while (isupper ((unsigned char) *optend))
		optend++;
	      b = *optend;
	      if ('\0' == b)
		next = "";
	      else
		next = optend + 1;
	      *optend = '\0';
	      if (GNUNET_OK !=
		  GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS",
							 optpos + 1, &val))
		val = GNUNET_strdup ("");
	      *optpos = '\0';
	      GNUNET_asprintf (&optpos, "%s%s%c%s", options, val, b, next);
	      GNUNET_free (options);
	      GNUNET_free (val);
	      options = optpos;
	    }
	}
    }
  use_debug = GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, "DEBUG");

  /* actually start process */
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
	      "Starting service `%s' using binary `%s' and configuration `%s'\n",
	      sl->name, sl->binary, sl->config);
  GNUNET_assert (NULL == sl->proc);
  if (GNUNET_YES == use_debug)
    sl->proc =
      do_start_process (sl->pipe_control,
			lsocks, loprefix, sl->binary, "-c", sl->config, "-L",
			"DEBUG", options, NULL);
  else
    sl->proc =
      do_start_process (sl->pipe_control,
			lsocks, loprefix, sl->binary, "-c", sl->config,
			options, NULL);
  if (sl->proc == NULL)
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to start service `%s'\n"),
		sl->name);
  else
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting service `%s'\n"),
		sl->name);
  /* clean up */
  GNUNET_free (loprefix);
  GNUNET_free (options);
  GNUNET_array_grow (lsocks, ls, 0);
}
예제 #6
0
/**
 * 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);
}
/**
 * Initialize address subsystem.
 *
 * @param cfg configuration to use
 * @param stats the statistics handle to use
 */
void
GAS_addresses_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
                    const struct GNUNET_STATISTICS_Handle *stats)
{
  int mode;

  char *quota_wan_in_str;
  char *quota_wan_out_str;

  running = GNUNET_NO;

  addresses = GNUNET_CONTAINER_multihashmap_create (128);
  GNUNET_assert (NULL != addresses);

  if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", "WAN_QUOTA_IN", &quota_wan_in_str))
  {
    if (0 == strcmp(quota_wan_in_str, "unlimited") ||
        (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_wan_in_str, &wan_quota_in)))
      wan_quota_in = (UINT32_MAX) /10;

    GNUNET_free (quota_wan_in_str);
    quota_wan_in_str = NULL;
  }
  else
  {
    wan_quota_in = (UINT32_MAX) /10;
  }

  if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", "WAN_QUOTA_OUT", &quota_wan_out_str))
  {
    if (0 == strcmp(quota_wan_out_str, "unlimited") ||
        (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_wan_out_str, &wan_quota_out)))
      wan_quota_out = (UINT32_MAX) /10;

    GNUNET_free (quota_wan_out_str);
    quota_wan_out_str = NULL;
  }
  else
  {
    wan_quota_out = (UINT32_MAX) /10;
  }

  mode = GNUNET_CONFIGURATION_get_value_yesno (cfg, "ats", "MLP");
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MLP mode %u", mode);
  switch (mode)
  {
    /* MLP = YES */
    case GNUNET_YES:
#if HAVE_LIBGLPK
      ats_mode = MLP;
      /* Init the MLP solver with default values */
      mlp = GAS_mlp_init (cfg, stats, MLP_MAX_EXEC_DURATION, MLP_MAX_ITERATIONS);
      if (NULL == mlp)
      {
        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "MLP mode was configured, but libglpk is not installed, switching to simple mode\n");
        GNUNET_STATISTICS_update (GSA_stats, "MLP mode enabled", 0, GNUNET_NO);
        break;
      }
      else
      {
        GNUNET_STATISTICS_update (GSA_stats, "MLP enabled", 1, GNUNET_NO);
        break;
      }
#else
      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "MLP mode was configured, but libglpk is not installed, switching to simple mode");
      GNUNET_STATISTICS_update (GSA_stats, "MLP enabled", 0, GNUNET_NO);
      ats_mode = SIMPLE;
      break;
#endif
    /* MLP = NO */
    case GNUNET_NO:
      GNUNET_STATISTICS_update (GSA_stats, "MLP enabled", 0, GNUNET_NO);
      ats_mode = SIMPLE;
      break;
    /* No configuration value */
    case GNUNET_SYSERR:
      GNUNET_STATISTICS_update (GSA_stats, "MLP enabled", 0, GNUNET_NO);
      ats_mode = SIMPLE;
      break;
    default:
      break;
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ATS started with %s mode\n", (SIMPLE == ats_mode) ? "SIMPLE" : "MLP");
  running = GNUNET_YES;
}
예제 #8
0
/**
 * Initialize the database connections and associated
 * data structures (create tables and indices
 * as needed as well).
 *
 * @param plugin the plugin context (state for this module)
 * @return GNUNET_OK on success
 */
static int
database_setup (struct Plugin *plugin)
{
  PGresult *res;

  plugin->dbh = GNUNET_POSTGRES_connect (plugin->cfg,
					 "namecache-postgres");
  if (NULL == plugin->dbh)
    return GNUNET_SYSERR;
  if (GNUNET_YES ==
      GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg,
					    "namecache-postgres",
					    "TEMPORARY_TABLE"))
  {
    res =
      PQexec (plugin->dbh,
              "CREATE TEMPORARY TABLE ns096blocks ("
	      " query BYTEA NOT NULL DEFAULT '',"
	      " block BYTEA NOT NULL DEFAULT '',"
	      " expiration_time BIGINT NOT NULL DEFAULT 0"
	      ")" "WITH OIDS");
  }
  else
  {
    res =
      PQexec (plugin->dbh,
              "CREATE TABLE ns096blocks ("
	      " query BYTEA NOT NULL DEFAULT '',"
	      " block BYTEA NOT NULL DEFAULT '',"
	      " expiration_time BIGINT NOT NULL DEFAULT 0"
	      ")" "WITH OIDS");
  }
  if ( (NULL == res) ||
       ((PQresultStatus (res) != PGRES_COMMAND_OK) &&
        (0 != strcmp ("42P07",    /* duplicate table */
                      PQresultErrorField
                      (res,
                       PG_DIAG_SQLSTATE)))))
  {
    (void) GNUNET_POSTGRES_check_result (plugin->dbh, res,
                                         PGRES_COMMAND_OK, "CREATE TABLE",
					 "ns096blocks");
    PQfinish (plugin->dbh);
    plugin->dbh = NULL;
    return GNUNET_SYSERR;
  }
  if (PQresultStatus (res) == PGRES_COMMAND_OK)
    create_indices (plugin->dbh);
  PQclear (res);

  if ((GNUNET_OK !=
       GNUNET_POSTGRES_prepare (plugin->dbh,
				"cache_block",
				"INSERT INTO ns096blocks (query, block, expiration_time) VALUES "
 				"($1, $2, $3)", 3)) ||
      (GNUNET_OK !=
       GNUNET_POSTGRES_prepare (plugin->dbh,
				"expire_blocks",
				"DELETE FROM ns096blocks WHERE expiration_time<$1", 1)) ||
      (GNUNET_OK !=
       GNUNET_POSTGRES_prepare (plugin->dbh,
				"delete_block",
				"DELETE FROM ns096blocks WHERE query=$1 AND expiration_time<=$2", 2)) ||
      (GNUNET_OK !=
       GNUNET_POSTGRES_prepare (plugin->dbh,
				"lookup_block",
				"SELECT block FROM ns096blocks WHERE query=$1"
				" ORDER BY expiration_time DESC LIMIT 1", 1)))
  {
    PQfinish (plugin->dbh);
    plugin->dbh = NULL;
    return GNUNET_SYSERR;
  }
  return GNUNET_OK;
}
예제 #9
0
파일: service.c 프로젝트: tg-x/gnunet
/**
 * Get the list of addresses that a server for the given service
 * should bind to.
 *
 * @param service_name name of the service
 * @param cfg configuration (which specifies the addresses)
 * @param addrs set (call by reference) to an array of pointers to the
 *              addresses the server should bind to and listen on; the
 *              array will be NULL-terminated (on success)
 * @param addr_lens set (call by reference) to an array of the lengths
 *              of the respective `struct sockaddr` struct in the @a addrs
 *              array (on success)
 * @return number of addresses found on success,
 *              #GNUNET_SYSERR if the configuration
 *              did not specify reasonable finding information or
 *              if it specified a hostname that could not be resolved;
 *              #GNUNET_NO if the number of addresses configured is
 *              zero (in this case, `*addrs` and `*addr_lens` will be
 *              set to NULL).
 */
int
GNUNET_SERVICE_get_server_addresses (const char *service_name,
                                     const struct GNUNET_CONFIGURATION_Handle *cfg,
                                     struct sockaddr ***addrs,
                                     socklen_t ** addr_lens)
{
  int disablev6;
  struct GNUNET_NETWORK_Handle *desc;
  unsigned long long port;
  char *unixpath;
  struct addrinfo hints;
  struct addrinfo *res;
  struct addrinfo *pos;
  struct addrinfo *next;
  unsigned int i;
  int resi;
  int ret;
  int abstract;
  struct sockaddr **saddrs;
  socklen_t *saddrlens;
  char *hostname;

  *addrs = NULL;
  *addr_lens = NULL;
  desc = NULL;
  if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "DISABLEV6"))
  {
    if (GNUNET_SYSERR ==
        (disablev6 =
         GNUNET_CONFIGURATION_get_value_yesno (cfg, service_name, "DISABLEV6")))
      return GNUNET_SYSERR;
  }
  else
    disablev6 = GNUNET_NO;

  if (! disablev6)
  {
    /* probe IPv6 support */
    desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
    if (NULL == desc)
    {
      if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
          (EACCES == errno))
      {
        LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
        return GNUNET_SYSERR;
      }
      LOG (GNUNET_ERROR_TYPE_INFO,
           _("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
           service_name, STRERROR (errno));
      disablev6 = GNUNET_YES;
    }
    else
    {
      GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
      desc = NULL;
    }
  }

  port = 0;
  if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT"))
  {
    if (GNUNET_OK !=
	GNUNET_CONFIGURATION_get_value_number (cfg, service_name,
					       "PORT", &port))
    {
      LOG (GNUNET_ERROR_TYPE_ERROR,
           _("Require valid port number for service `%s' in configuration!\n"),
           service_name);
    }
    if (port > 65535)
    {
      LOG (GNUNET_ERROR_TYPE_ERROR,
           _("Require valid port number for service `%s' in configuration!\n"),
           service_name);
      return GNUNET_SYSERR;
    }
  }

  if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "BINDTO"))
  {
    GNUNET_break (GNUNET_OK ==
                  GNUNET_CONFIGURATION_get_value_string (cfg, service_name,
                                                         "BINDTO", &hostname));
  }
  else
    hostname = NULL;

  unixpath = NULL;
  abstract = GNUNET_NO;
#ifdef AF_UNIX
  if ((GNUNET_YES ==
       GNUNET_CONFIGURATION_have_value (cfg, service_name, "UNIXPATH")) &&
      (GNUNET_OK ==
       GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH",
                                              &unixpath)) &&
      (0 < strlen (unixpath)))
  {
    /* probe UNIX support */
    struct sockaddr_un s_un;

    if (strlen (unixpath) >= sizeof (s_un.sun_path))
    {
      LOG (GNUNET_ERROR_TYPE_WARNING,
           _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath,
           (unsigned long long) sizeof (s_un.sun_path));
      unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
      LOG (GNUNET_ERROR_TYPE_INFO,
	   _("Using `%s' instead\n"),
           unixpath);
    }
#ifdef LINUX
    abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
                                                     "TESTING",
                                                     "USE_ABSTRACT_SOCKETS");
    if (GNUNET_SYSERR == abstract)
      abstract = GNUNET_NO;
#endif
    if ((GNUNET_YES != abstract)
        && (GNUNET_OK !=
            GNUNET_DISK_directory_create_for_file (unixpath)))
      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
				"mkdir",
				unixpath);
  }
  if (NULL != unixpath)
  {
    desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
    if (NULL == desc)
    {
      if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
          (EACCES == errno))
      {
        LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
        GNUNET_free_non_null (hostname);
        GNUNET_free (unixpath);
        return GNUNET_SYSERR;
      }
      LOG (GNUNET_ERROR_TYPE_INFO,
           _("Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
           service_name,
           STRERROR (errno));
      GNUNET_free (unixpath);
      unixpath = NULL;
    }
    else
    {
      GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
      desc = NULL;
    }
  }
#endif

  if ((0 == port) && (NULL == unixpath))
  {
    LOG (GNUNET_ERROR_TYPE_ERROR,
         _("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
         service_name);
    GNUNET_free_non_null (hostname);
    return GNUNET_SYSERR;
  }
  if (0 == port)
  {
    saddrs = GNUNET_malloc (2 * sizeof (struct sockaddr *));
    saddrlens = GNUNET_malloc (2 * sizeof (socklen_t));
    add_unixpath (saddrs, saddrlens, unixpath, abstract);
    GNUNET_free_non_null (unixpath);
    GNUNET_free_non_null (hostname);
    *addrs = saddrs;
    *addr_lens = saddrlens;
    return 1;
  }

  if (NULL != hostname)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Resolving `%s' since that is where `%s' will bind to.\n",
         hostname,
         service_name);
    memset (&hints, 0, sizeof (struct addrinfo));
    if (disablev6)
      hints.ai_family = AF_INET;
    hints.ai_protocol = IPPROTO_TCP;
    if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
        (NULL == res))
    {
      LOG (GNUNET_ERROR_TYPE_ERROR,
           _("Failed to resolve `%s': %s\n"),
           hostname,
           gai_strerror (ret));
      GNUNET_free (hostname);
      GNUNET_free_non_null (unixpath);
      return GNUNET_SYSERR;
    }
    next = res;
    i = 0;
    while (NULL != (pos = next))
    {
      next = pos->ai_next;
      if ((disablev6) && (pos->ai_family == AF_INET6))
        continue;
      i++;
    }
    if (0 == i)
    {
      LOG (GNUNET_ERROR_TYPE_ERROR,
           _("Failed to find %saddress for `%s'.\n"),
           disablev6 ? "IPv4 " : "",
           hostname);
      freeaddrinfo (res);
      GNUNET_free (hostname);
      GNUNET_free_non_null (unixpath);
      return GNUNET_SYSERR;
    }
    resi = i;
    if (NULL != unixpath)
      resi++;
    saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
    saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
    i = 0;
    if (NULL != unixpath)
    {
      add_unixpath (saddrs, saddrlens, unixpath, abstract);
      i++;
    }
    next = res;
    while (NULL != (pos = next))
    {
      next = pos->ai_next;
      if ((disablev6) && (AF_INET6 == pos->ai_family))
        continue;
      if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
        continue;               /* not TCP */
      if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
        continue;               /* huh? */
      LOG (GNUNET_ERROR_TYPE_DEBUG, "Service `%s' will bind to `%s'\n",
           service_name, GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
      if (AF_INET == pos->ai_family)
      {
        GNUNET_assert (sizeof (struct sockaddr_in) == pos->ai_addrlen);
        saddrlens[i] = pos->ai_addrlen;
        saddrs[i] = GNUNET_malloc (saddrlens[i]);
        memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
        ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
      }
      else
      {
        GNUNET_assert (AF_INET6 == pos->ai_family);
        GNUNET_assert (sizeof (struct sockaddr_in6) == pos->ai_addrlen);
        saddrlens[i] = pos->ai_addrlen;
        saddrs[i] = GNUNET_malloc (saddrlens[i]);
        memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
        ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
      }
      i++;
    }
    GNUNET_free (hostname);
    freeaddrinfo (res);
    resi = i;
  }
  else
  {
    /* will bind against everything, just set port */
    if (disablev6)
    {
      /* V4-only */
      resi = 1;
      if (NULL != unixpath)
        resi++;
      i = 0;
      saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
      saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
      if (NULL != unixpath)
      {
        add_unixpath (saddrs, saddrlens, unixpath, abstract);
        i++;
      }
      saddrlens[i] = sizeof (struct sockaddr_in);
      saddrs[i] = GNUNET_malloc (saddrlens[i]);
#if HAVE_SOCKADDR_IN_SIN_LEN
      ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
#endif
      ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
      ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
    }
    else
    {
      /* dual stack */
      resi = 2;
      if (NULL != unixpath)
        resi++;
      saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
      saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
      i = 0;
      if (NULL != unixpath)
      {
        add_unixpath (saddrs, saddrlens, unixpath, abstract);
        i++;
      }
      saddrlens[i] = sizeof (struct sockaddr_in6);
      saddrs[i] = GNUNET_malloc (saddrlens[i]);
#if HAVE_SOCKADDR_IN_SIN_LEN
      ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
#endif
      ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
      ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
      i++;
      saddrlens[i] = sizeof (struct sockaddr_in);
      saddrs[i] = GNUNET_malloc (saddrlens[i]);
#if HAVE_SOCKADDR_IN_SIN_LEN
      ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
#endif
      ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
      ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
    }
  }
  GNUNET_free_non_null (unixpath);
  *addrs = saddrs;
  *addr_lens = saddrlens;
  return resi;
}
예제 #10
0
파일: gnunet_gst.c 프로젝트: GNUnet/gnunet
/***
 * load gnunet configuration
 */
  void
gg_load_configuration(GNUNET_gstData * d)
{
  char *audiobackend_string;
  cfg =  GNUNET_CONFIGURATION_create();
  GNUNET_CONFIGURATION_load(cfg, "mediahelper.conf");

  char *section = "MEDIAHELPER";

  GNUNET_CONFIGURATION_get_value_string(cfg, "MEDIAHELPER", "JACK_PP_IN", &d->jack_pp_in);
  GNUNET_CONFIGURATION_get_value_string(cfg, "MEDIAHELPER", "JACK_PP_OUT", &d->jack_pp_out);

  GNUNET_CONFIGURATION_get_value_string(cfg, "MEDIAHELPER", "AUDIOBACKEND", &audiobackend_string);

 // printf("abstring: %s \n", audiobackend_string);

  if ( audiobackend_string == "AUTO" )
  {
    d->audiobackend = AUTO;
  } else if ( audiobackend_string = "JACK" )
  {
    d->audiobackend = JACK;
  } else if ( audiobackend_string = "ALSA" )
  {
    d->audiobackend = ALSA;
  } else if ( audiobackend_string = "FAKE" )
  {
    d->audiobackend = FAKE;
  } else if ( audiobackend_string = "TEST" )
  {
    d->audiobackend = TEST;
  } else
  {
    d->audiobackend = AUTO;
  }

  if (GNUNET_CONFIGURATION_get_value_yesno(cfg, "MEDIAHELPER", "REMOVESILENCE") == GNUNET_YES)
  {
    d->dropsilence = TRUE;
  } else {
    d->dropsilence = FALSE;
  }

  if (GNUNET_CONFIGURATION_get_value_yesno(cfg, "MEDIAHELPER", "NO_GN_HEADERS") == GNUNET_YES)
  {
    d->pure_ogg = TRUE;
  } else {
    d->pure_ogg = FALSE;
  }


  if (GNUNET_CONFIGURATION_get_value_yesno(cfg, "MEDIAHELPER", "USERTP") == GNUNET_YES)
  {
    d->usertp = TRUE;
  } else {
    d->usertp = FALSE;
  }

//  GNUNET_CONFIGURATION_write(cfg, "mediahelper.conf");

}
static int
configure_plugin (struct Plugin *plugin)
{
  int res = GNUNET_OK;

  /* Use IPv4? */
  if (GNUNET_CONFIGURATION_have_value
      (plugin->env->cfg, plugin->name, "USE_IPv4"))
  {
    plugin->ipv4 =
        GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, plugin->name,
                                              "USE_IPv4");
  }
  else
    plugin->ipv4 = GNUNET_YES;

  /* Use IPv6? */
  if (GNUNET_CONFIGURATION_have_value
      (plugin->env->cfg, plugin->name, "USE_IPv6"))
  {
    plugin->ipv6 =
        GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, plugin->name,
                                              "USE_IPv6");
  }
  else
    plugin->ipv6 = GNUNET_YES;

  if ((plugin->ipv4 == GNUNET_NO) && (plugin->ipv6 == GNUNET_NO))
  {
    GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
                     _
                     ("Neither IPv4 nor IPv6 are enabled! Fix in configuration\n"),
                     plugin->name);
    res = GNUNET_SYSERR;
  }

  /* Reading port number from config file */
  unsigned long long port;

  if ((GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_number (plugin->env->cfg, plugin->name,
                                              "PORT", &port)) || (port > 65535))
  {
    GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
                     _("Port is required! Fix in configuration\n"),
                     plugin->name);
    res = GNUNET_SYSERR;
    goto fail;
  }
  plugin->port = port;

  plugin->client_only = GNUNET_NO;
  if (plugin->port == 0)
  {
    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
                     _("Port 0, client only mode\n"));
    plugin->client_only = GNUNET_YES;
  }

  char *bind4_address = NULL;

  if ((plugin->ipv4 == GNUNET_YES) &&
      (GNUNET_YES ==
       GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, plugin->name,
                                              "BINDTO", &bind4_address)))
  {
    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
                     "Binding %s plugin to specific IPv4 address: `%s'\n",
                     plugin->protocol, bind4_address);
    plugin->server_addr_v4 = GNUNET_malloc (sizeof (struct sockaddr_in));
    if (1 !=
        inet_pton (AF_INET, bind4_address, &plugin->server_addr_v4->sin_addr))
    {
      GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
                       _
                       ("Specific IPv4 address `%s' for plugin %s in configuration file is invalid! Binding to all addresses!\n"),
                       bind4_address, plugin->protocol);
      GNUNET_free (plugin->server_addr_v4);
      plugin->server_addr_v4 = NULL;
    }
    else
    {
      plugin->server_addr_v4->sin_family = AF_INET;
      plugin->server_addr_v4->sin_port = htons (plugin->port);
    }
    GNUNET_free (bind4_address);
  }


  char *bind6_address = NULL;

  if ((plugin->ipv6 == GNUNET_YES) &&
      (GNUNET_YES ==
       GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, plugin->name,
                                              "BINDTO6", &bind6_address)))
  {
    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
                     "Binding %s plugin to specific IPv6 address: `%s'\n",
                     plugin->protocol, bind6_address);
    plugin->server_addr_v6 = GNUNET_malloc (sizeof (struct sockaddr_in6));
    if (1 !=
        inet_pton (AF_INET6, bind6_address, &plugin->server_addr_v6->sin6_addr))
    {
      GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
                       _
                       ("Specific IPv6 address `%s' for plugin %s in configuration file is invalid! Binding to all addresses!\n"),
                       bind6_address, plugin->protocol);
      GNUNET_free (plugin->server_addr_v6);
      plugin->server_addr_v6 = NULL;
    }
    else
    {
      plugin->server_addr_v6->sin6_family = AF_INET6;
      plugin->server_addr_v6->sin6_port = htons (plugin->port);
    }
    GNUNET_free (bind6_address);
  }


  /* Optional parameters */
  unsigned long long maxneigh;

  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_number (plugin->env->cfg, plugin->name,
                                             "MAX_CONNECTIONS", &maxneigh))
    maxneigh = 128;
  plugin->max_connections = maxneigh;

fail:
  return res;
}
예제 #12
0
/**
 * Main function that will be run.
 *
 * @param cls closure
 * @param args remaining command-line arguments
 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
 * @param c configuration
 */
static void
run (void *cls,
     char *const *args,
     const char *cfgfile,
     const struct GNUNET_CONFIGURATION_Handle *c)
{
  struct GNUNET_MQ_MessageHandler handlers[] = {
    GNUNET_MQ_hd_var_size (hello,
                           GNUNET_MESSAGE_TYPE_HELLO,
                           struct GNUNET_HELLO_Message,
                           NULL),
    GNUNET_MQ_handler_end ()
  };
  unsigned long long opt;

  cfg = c;
  stats = GNUNET_STATISTICS_create ("topology", cfg);
  friends_only =
      GNUNET_CONFIGURATION_get_value_yesno (cfg,
                                            "TOPOLOGY",
                                            "FRIENDS-ONLY");
  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_number (cfg,
                                             "TOPOLOGY",
                                             "MINIMUM-FRIENDS",
                                             &opt))
    opt = 0;
  minimum_friend_count = (unsigned int) opt;
  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_number (cfg,
                                             "TOPOLOGY",
                                             "TARGET-CONNECTION-COUNT",
                                             &opt))
    opt = 16;
  target_connection_count = (unsigned int) opt;
  peers = GNUNET_CONTAINER_multipeermap_create (target_connection_count * 2,
                                                GNUNET_NO);
  read_friends_file (cfg);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Topology would like %u connections with at least %u friends\n",
              target_connection_count,
              minimum_friend_count);
  if ( (friend_count < minimum_friend_count) &&
       (NULL == blacklist))
    blacklist = GNUNET_TRANSPORT_blacklist (cfg,
                                            &blacklist_check,
                                            NULL);
  ats = GNUNET_ATS_connectivity_init (cfg);
  handle = GNUNET_CORE_connect (cfg,
				NULL,
				&core_init,
				&connect_notify,
				&disconnect_notify,
				handlers);
  GNUNET_SCHEDULER_add_shutdown (&cleaning_task,
				 NULL);
  if (NULL == handle)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                _("Failed to connect to `%s' service.\n"),
                "core");
    GNUNET_SCHEDULER_shutdown ();
    return;
  }
}
예제 #13
0
/**
 * Create a data cache.
 *
 * @param cfg configuration to use
 * @param section section in the configuration that contains our options
 * @return handle to use to access the service
 */
struct GNUNET_DATACACHE_Handle *
GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
                         const char *section)
{
  unsigned int bf_size;
  unsigned long long quota;
  struct GNUNET_DATACACHE_Handle *ret;
  char *libname;
  char *name;

  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_size (cfg, section, "QUOTA", &quota))
  {
    LOG (GNUNET_ERROR_TYPE_ERROR,
         _("No `%s' specified for `%s' in configuration!\n"), "QUOTA", section);
    return NULL;
  }
  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_string (cfg, section, "DATABASE", &name))
  {
    LOG (GNUNET_ERROR_TYPE_ERROR,
         _("No `%s' specified for `%s' in configuration!\n"), "DATABASE",
         section);
    return NULL;
  }
  bf_size = quota / 32;         /* 8 bit per entry, 1 bit per 32 kb in DB */

  ret = GNUNET_malloc (sizeof (struct GNUNET_DATACACHE_Handle));
  
  if (GNUNET_YES !=
      GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "DISABLE_BF"))
  {
    if (GNUNET_YES !=
	GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "DISABLE_BF_RC"))
    {
      ret->bloom_name = GNUNET_DISK_mktemp ("gnunet-datacachebloom");
    }
    if (NULL != ret->bloom_name)
    {
      ret->filter = GNUNET_CONTAINER_bloomfilter_load (ret->bloom_name, quota / 1024,     /* 8 bit per entry in DB, expect 1k entries */
						       5); 
    }    
    if (NULL == ret->filter)
    {
	ret->filter = GNUNET_CONTAINER_bloomfilter_init (NULL, bf_size, 5); /* approx. 3% false positives at max use */
    }  
  }
  ret->stats = GNUNET_STATISTICS_create ("datacache", cfg);
  ret->section = GNUNET_strdup (section);
  ret->env.cfg = cfg;
  ret->env.delete_notify = &env_delete_notify;
  ret->env.section = ret->section;
  ret->env.cls = ret;
  ret->env.delete_notify = &env_delete_notify;
  ret->env.quota = quota;
  LOG (GNUNET_ERROR_TYPE_INFO, _("Loading `%s' datacache plugin\n"), name);
  GNUNET_asprintf (&libname, "libgnunet_plugin_datacache_%s", name);
  ret->short_name = name;
  ret->lib_name = libname;
  ret->api = GNUNET_PLUGIN_load (libname, &ret->env);
  if (ret->api == NULL)
  {
    LOG (GNUNET_ERROR_TYPE_ERROR,
         _("Failed to load datacache plugin for `%s'\n"), name);
    GNUNET_DATACACHE_destroy (ret);
    return NULL;
  }
  return ret;
}
예제 #14
0
파일: service.c 프로젝트: tg-x/gnunet
/**
 * 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;
}
예제 #15
0
파일: client.c 프로젝트: muggenhor/GNUnet
/**
 * Test if the service is running.  If we are given a UNIXPATH or a
 * local address, we do this NOT by trying to connect to the service,
 * but by trying to BIND to the same port.  If the BIND fails, we know
 * the service is running.
 *
 * @param service name of the service to wait for
 * @param cfg configuration to use
 * @param timeout how long to wait at most
 * @param cb function to call with the result
 * @param cb_cls closure for @a cb
 * @return handle to cancel the test
 */
struct GNUNET_CLIENT_TestHandle *
GNUNET_CLIENT_service_test (const char *service,
                            const struct GNUNET_CONFIGURATION_Handle *cfg,
                            struct GNUNET_TIME_Relative timeout,
                            GNUNET_CLIENT_TestResultCallback cb,
			    void *cb_cls)
{
  struct GNUNET_CLIENT_TestHandle *th;
  char *hostname;
  unsigned long long port;
  struct GNUNET_NETWORK_Handle *sock;

  th = GNUNET_new (struct GNUNET_CLIENT_TestHandle);
  th->cb = cb;
  th->cb_cls = cb_cls;
  th->test_deadline = GNUNET_TIME_relative_to_absolute (timeout);
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Testing if service `%s' is running.\n",
       service);
#ifdef AF_UNIX
  {
    /* probe UNIX support */
    struct sockaddr_un s_un;
    char *unixpath;
    int abstract;

    unixpath = NULL;
    if ((GNUNET_OK ==
	 GNUNET_CONFIGURATION_get_value_filename (cfg,
						  service,
						  "UNIXPATH",
						  &unixpath)) &&
	(0 < strlen (unixpath)))  /* We have a non-NULL unixpath, does that mean it's valid? */
    {
      if (strlen (unixpath) >= sizeof (s_un.sun_path))
      {
        LOG (GNUNET_ERROR_TYPE_WARNING,
             _("UNIXPATH `%s' too long, maximum length is %llu\n"),
	     unixpath,
             (unsigned long long) sizeof (s_un.sun_path));
	unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
        LOG (GNUNET_ERROR_TYPE_INFO,
             _("Using `%s' instead\n"), unixpath);
      }
    }
#ifdef LINUX
    abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
                                                     "TESTING",
                                                     "USE_ABSTRACT_SOCKETS");
#else
    abstract = GNUNET_NO;
#endif
    if ((NULL != unixpath) && (GNUNET_YES != abstract))
    {
      if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (unixpath))
        GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
                                  "mkdir", unixpath);
    }
    if (NULL != unixpath)
    {
      sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0);
      if (NULL != sock)
      {
	memset (&s_un, 0, sizeof (s_un));
	s_un.sun_family = AF_UNIX;
        strncpy (s_un.sun_path, unixpath, sizeof (s_un.sun_path) - 1);
        if (GNUNET_YES == abstract)
          s_un.sun_path[0] = '\0';
#if HAVE_SOCKADDR_IN_SIN_LEN
        s_un.sun_len = (u_char) sizeof (struct sockaddr_un);
#endif
	if (GNUNET_OK !=
	    GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_un,
					sizeof (struct sockaddr_un)))
        {
	  /* failed to bind => service must be running */
	  GNUNET_free (unixpath);
	  (void) GNUNET_NETWORK_socket_close (sock);
	  service_test_report (th, GNUNET_YES);
	  return th;
	}
	(void) GNUNET_NETWORK_socket_close (sock);
        /* let's try IP */
      }
    }
    GNUNET_free_non_null (unixpath);
  }
#endif

  hostname = NULL;
  if ((GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_number (cfg, service, "PORT", &port)) ||
      (port > 65535) ||
      (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (cfg, service, "HOSTNAME",
                                              &hostname)))
  {
    /* UNIXPATH failed (if possible) AND IP failed => error */
    service_test_report (th, GNUNET_SYSERR);
    return th;
  }

  if (0 == strcmp ("localhost", hostname)
#if !LINUX
      && 0
#endif
      )
  {
    /* can test using 'bind' */
    struct sockaddr_in s_in;

    memset (&s_in, 0, sizeof (s_in));
#if HAVE_SOCKADDR_IN_SIN_LEN
    s_in.sin_len = sizeof (struct sockaddr_in);
#endif
    s_in.sin_family = AF_INET;
    s_in.sin_port = htons (port);

    sock = GNUNET_NETWORK_socket_create (AF_INET, SOCK_STREAM, 0);
    if (NULL != sock)
    {
      if (GNUNET_OK !=
          GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_in,
                                      sizeof (s_in)))
      {
        /* failed to bind => service must be running */
        GNUNET_free (hostname);
        (void) GNUNET_NETWORK_socket_close (sock);
        service_test_report (th, GNUNET_YES);
        return th;
      }
      (void) GNUNET_NETWORK_socket_close (sock);
    }
  }

  if (0 == strcmp ("ip6-localhost", hostname)
#if !LINUX
      && 0
#endif
      )
  {
    /* can test using 'bind' */
    struct sockaddr_in6 s_in6;

    memset (&s_in6, 0, sizeof (s_in6));
#if HAVE_SOCKADDR_IN_SIN_LEN
    s_in6.sin6_len = sizeof (struct sockaddr_in6);
#endif
    s_in6.sin6_family = AF_INET6;
    s_in6.sin6_port = htons (port);

    sock = GNUNET_NETWORK_socket_create (AF_INET6, SOCK_STREAM, 0);
    if (NULL != sock)
    {
      if (GNUNET_OK !=
          GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_in6,
                                      sizeof (s_in6)))
      {
        /* failed to bind => service must be running */
        GNUNET_free (hostname);
        (void) GNUNET_NETWORK_socket_close (sock);
        service_test_report (th, GNUNET_YES);
        return th;
      }
      (void) GNUNET_NETWORK_socket_close (sock);
    }
  }

  if (((0 == strcmp ("localhost", hostname)) ||
       (0 == strcmp ("ip6-localhost", hostname)))
#if !LINUX
      && 0
#endif
      )
  {
    /* all binds succeeded => claim service not running right now */
    GNUNET_free_non_null (hostname);
    service_test_report (th, GNUNET_NO);
    return th;
  }
  GNUNET_free_non_null (hostname);

  /* non-localhost, try 'connect' method */
  th->client = GNUNET_CLIENT_connect (service, cfg);
  if (NULL == th->client)
  {
    LOG (GNUNET_ERROR_TYPE_INFO,
         _("Could not connect to service `%s', configuration broken.\n"),
         service);
    service_test_report (th, GNUNET_SYSERR);
    return th;
  }
  th->th = GNUNET_CLIENT_notify_transmit_ready (th->client,
						sizeof (struct GNUNET_MessageHeader),
						timeout, GNUNET_YES,
						&write_test, th);
  if (NULL == th->th)
  {
    LOG (GNUNET_ERROR_TYPE_WARNING,
         _("Failure to transmit request to service `%s'\n"), service);
    service_test_report (th, GNUNET_SYSERR);
    return th;
  }
  return th;
}
예제 #16
0
/**
 * Initiate transport service.
 *
 * @param cls closure
 * @param server the initialized server
 * @param c configuration to use
 */
static void
run (void *cls,
     struct GNUNET_SERVER_Handle *server,
     const struct GNUNET_CONFIGURATION_Handle *c)
{
  char *keyfile;
  struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
  long long unsigned int max_fd_cfg;
  int max_fd_rlimit;
  int max_fd;
  int friend_only;

  /* setup globals */
  GST_cfg = c;
  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_filename (c,
                                               "PEER",
                                               "PRIVATE_KEY",
                                               &keyfile))
  {
    GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
        _("Transport service is lacking key configuration settings. Exiting.\n"));
    GNUNET_SCHEDULER_shutdown ();
    return;
  }
  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_time (c,
                                           "transport",
                                           "HELLO_EXPIRATION",
                                           &hello_expiration))
  {
    hello_expiration = GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION;
  }
  GST_server = server;
  pk = GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile);
  GNUNET_free (keyfile);
  GNUNET_assert (NULL != pk);
  GST_my_private_key = pk;

  GST_stats = GNUNET_STATISTICS_create ("transport", GST_cfg);
  GST_peerinfo = GNUNET_PEERINFO_connect (GST_cfg);
  GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key,
                                      &GST_my_identity.public_key);
  GNUNET_assert(NULL != GST_my_private_key);

  GNUNET_log(GNUNET_ERROR_TYPE_INFO,
             "My identity is `%4s'\n",
             GNUNET_i2s_full (&GST_my_identity));

  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
                                &shutdown_task,
                                NULL);
  if (NULL == GST_peerinfo)
  {
    GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
        _("Could not access PEERINFO service.  Exiting.\n"));
    GNUNET_SCHEDULER_shutdown ();
    return;
  }

  max_fd_rlimit = 0;
  max_fd_cfg = 0;
#if HAVE_GETRLIMIT
  struct rlimit r_file;
  if (0 == getrlimit (RLIMIT_NOFILE, &r_file))
  {
    max_fd_rlimit = r_file.rlim_cur;
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
        "Maximum number of open files was: %u/%u\n",
        r_file.rlim_cur,
        r_file.rlim_max);
  }
  max_fd_rlimit = (9 * max_fd_rlimit) / 10; /* Keep 10% for rest of transport */
#endif
  GNUNET_CONFIGURATION_get_value_number (GST_cfg,
                                         "transport",
                                         "MAX_FD",
                                         &max_fd_cfg);

  if (max_fd_cfg > max_fd_rlimit)
    max_fd = max_fd_cfg;
  else
    max_fd = max_fd_rlimit;
  if (max_fd < DEFAULT_MAX_FDS)
    max_fd = DEFAULT_MAX_FDS;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Limiting number of sockets to %u: validation %u, neighbors: %u\n",
             max_fd, (max_fd / 3), (max_fd / 3) * 2);

  friend_only = GNUNET_CONFIGURATION_get_value_yesno (GST_cfg,
                                                      "topology",
                                                      "FRIENDS-ONLY");
  if (GNUNET_SYSERR == friend_only)
    friend_only = GNUNET_NO; /* According to topology defaults */
  /* start subsystems */
  GST_blacklist_start (GST_server,
                       GST_cfg,
                       &GST_my_identity);
  GST_is = GNUNET_ATS_scanner_init ();
  GST_ats_connect = GNUNET_ATS_connectivity_init (GST_cfg);
  GST_ats = GNUNET_ATS_scheduling_init (GST_cfg,
                                        &ats_request_address_change,
                                        NULL);
  GST_ats_init ();
  GST_manipulation_init ();
  GST_plugins_load (&GST_manipulation_recv,
                    &plugin_env_address_change_notification,
                    &plugin_env_session_start,
                    &plugin_env_session_end);
  GST_hello_start (friend_only,
                   &process_hello_update,
                   NULL);
  GST_neighbours_start ((max_fd / 3) * 2);
  GST_clients_start (GST_server);
  GST_validation_start ((max_fd / 3));
}
예제 #17
0
static int
testConfig ()
{
  char *c;
  unsigned long long l;

  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "test", "b", &c))
    return 1;
  if (0 != strcmp ("b", c))
  {
    FPRINTF (stderr, "Got `%s'\n", c);
    GNUNET_free (c);
    return 2;
  }
  GNUNET_free (c);
  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_number (cfg, "test", "five", &l))
  {
    GNUNET_break (0);
    return 3;
  }
  if (5 != l)
  {
    GNUNET_break (0);
    return 4;
  }
  GNUNET_CONFIGURATION_set_value_string (cfg, "more", "c", "YES");
  if (GNUNET_NO == GNUNET_CONFIGURATION_get_value_yesno (cfg, "more", "c"))
  {
    GNUNET_break (0);
    return 5;
  }
  GNUNET_CONFIGURATION_set_value_number (cfg, "NUMBERS", "TEN", 10);
  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_string (cfg, "NUMBERS", "TEN", &c))
  {
    GNUNET_break (0);
    return 6;
  }
  if (0 != strcmp (c, "10"))
  {
    GNUNET_free (c);
    GNUNET_break (0);
    return 7;
  }
  GNUNET_free (c);

  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_filename (cfg, "last", "test", &c))
  {
    GNUNET_break (0);
    return 8;
  }
#ifndef MINGW
  if (0 != strcmp (c, "/hello/world"))
#else
#define HI "\\hello\\world"
  if (strstr (c, HI) != c + strlen (c) - strlen (HI))
#endif
  {
    GNUNET_break (0);
    GNUNET_free (c);
    return 9;
  }
  GNUNET_free (c);

  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_size (cfg, "last", "size", &l))
  {
    GNUNET_break (0);
    return 10;
  }
  if (l != 512 * 1024)
  {
    GNUNET_break (0);
    return 11;
  }
  return 0;
}
예제 #18
0
/**
 * Process GNS requests.
 *
 * @param cls closure)
 * @param server the initialized server
 * @param c configuration to use
 */
static void
run (void *cls, struct GNUNET_SERVER_Handle *server,
     const struct GNUNET_CONFIGURATION_Handle *c)
{
  
  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Initializing GNS\n");
  
  char* keyfile;
  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
  unsigned long long max_parallel_bg_queries = 0;
  unsigned long long default_lookup_timeout_secs = 0;
  int ignore_pending = GNUNET_NO;

  static const struct GNUNET_SERVER_MessageHandler handlers[] = {
    {&handle_shorten, NULL, GNUNET_MESSAGE_TYPE_GNS_SHORTEN, 0},
    {&handle_lookup, NULL, GNUNET_MESSAGE_TYPE_GNS_LOOKUP, 0},
    {&handle_get_authority, NULL, GNUNET_MESSAGE_TYPE_GNS_GET_AUTH, 0}
  };

  GNS_cfg = c;

  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, "gns",
                                             "ZONEKEY", &keyfile))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                "No private key for root zone specified!\n");
    GNUNET_SCHEDULER_shutdown ();
    return;
  }

  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
             "Using keyfile %s for root zone.\n", keyfile);

  zone_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
  GNUNET_CRYPTO_rsa_key_get_public (zone_key, &pkey);

  GNUNET_CRYPTO_short_hash(&pkey,
                     sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
                     &zone_hash);
  GNUNET_free(keyfile);
  
  /**
   * handle to our local namestore
   */
  namestore_handle = GNUNET_NAMESTORE_connect(c);

  if (NULL == namestore_handle)
  {
    //FIXME do error handling;
    GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
               "Failed to connect to the namestore!\n");
    GNUNET_SCHEDULER_shutdown ();
    return;
  }
  
  

  auto_import_pkey = GNUNET_NO;

  if (GNUNET_YES ==
      GNUNET_CONFIGURATION_get_value_yesno (c, "gns",
                                            "AUTO_IMPORT_PKEY"))
  {
    GNUNET_log(GNUNET_ERROR_TYPE_INFO,
               "Automatic PKEY import is enabled.\n");
    auto_import_pkey = GNUNET_YES;

  }

  dht_max_update_interval = GNUNET_GNS_DHT_MAX_UPDATE_INTERVAL;

  if (GNUNET_OK ==
      GNUNET_CONFIGURATION_get_value_number (c, "gns",
                                             "ZONE_PUT_INTERVAL",
                                             &dht_max_update_interval))
  {
    GNUNET_log(GNUNET_ERROR_TYPE_INFO,
               "DHT zone update interval: %d\n",
               dht_max_update_interval);
  }
  
  max_record_put_interval = 1;

  if (GNUNET_OK ==
      GNUNET_CONFIGURATION_get_value_number (c, "gns",
                                             "RECORD_PUT_INTERVAL",
                                             &max_record_put_interval))
  {
    GNUNET_log(GNUNET_ERROR_TYPE_INFO,
               "Record put interval: %d\n",
               max_record_put_interval);
  }
  
  if (GNUNET_OK ==
      GNUNET_CONFIGURATION_get_value_number (c, "gns",
                                            "MAX_PARALLEL_BACKGROUND_QUERIES",
                                            &max_parallel_bg_queries))
  {
    GNUNET_log(GNUNET_ERROR_TYPE_INFO,
               "Number of allowed parallel background queries: %d\n",
               max_parallel_bg_queries);
  }

  if (GNUNET_YES ==
      GNUNET_CONFIGURATION_get_value_yesno (c, "gns",
                                            "AUTO_IMPORT_CONFIRMATION_REQ"))
  {
    GNUNET_log(GNUNET_ERROR_TYPE_INFO,
               "Auto import requires user confirmation\n");
    ignore_pending = GNUNET_YES;
  }

  if (GNUNET_OK ==
      GNUNET_CONFIGURATION_get_value_number(c, "gns",
                                            "DEFAULT_LOOKUP_TIMEOUT",
                                            &default_lookup_timeout_secs))
  {
    GNUNET_log(GNUNET_ERROR_TYPE_INFO,
               "Default lookup timeout: %ds\n", default_lookup_timeout_secs);
    default_lookup_timeout = GNUNET_TIME_relative_multiply(
                                            GNUNET_TIME_UNIT_SECONDS,
                                            default_lookup_timeout_secs);
  }
  
  /**
   * handle to the dht
   */
  dht_handle = GNUNET_DHT_connect(c,
                       //max_parallel_bg_queries); //FIXME get ht_len from cfg
                       1024);

  if (NULL == dht_handle)
  {
    GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Could not connect to DHT!\n");
  }
  
  if (gns_resolver_init(namestore_handle, dht_handle, zone_hash,
                        max_parallel_bg_queries,
                        ignore_pending)
      == GNUNET_SYSERR)
  {
    GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
               "Unable to initialize resolver!\n");
    GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
    return;
  }

  if (GNUNET_YES ==
      GNUNET_CONFIGURATION_get_value_yesno (c, "gns", "HIJACK_DNS"))
  {
    GNUNET_log(GNUNET_ERROR_TYPE_INFO,
               "DNS hijacking enabled... connecting to service.\n");

    if (gns_interceptor_init(zone_hash, zone_key, c) == GNUNET_SYSERR)
    {
      GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
               "Failed to enable the dns interceptor!\n");
    }
  }
  
  /**
   * Schedule periodic put
   * for our records
   * We have roughly an hour for all records;
   */
  record_put_interval = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS,
                                                      1);
  zone_update_taskid = GNUNET_SCHEDULER_add_now (&update_zone_dht_start, NULL);

  GNUNET_SERVER_add_handlers (server, handlers);
  
  //FIXME
  //GNUNET_SERVER_disconnect_notify (server,
  //                                 &client_disconnect_notification,
  //                                 NULL);

  nc = GNUNET_SERVER_notification_context_create (server, 1);

  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
                                NULL);
}
예제 #19
0
/**
 * A client specifically requested starting of ARM itself.
 * This function is called with information about whether
 * or not ARM is running; if it is, report success.  If
 * it is not, start the ARM process.
 *
 * @param cls the context for the request that we will report on (struct ARMControlMessage *)
 * @param result GNUNET_YES if ARM is running
 */
static void
arm_service_report (void *cls,
		    int result)
{
  struct ARMControlMessage *cm = cls;
  struct GNUNET_ARM_Handle *h;
  struct GNUNET_OS_Process *proc;
  unsigned char test_is_active;
  char *cbinary;
  char *binary;
  char *quotedbinary;
  char *config;
  char *loprefix;
  char *lopostfix;

  test_is_active = cm->h->service_test_is_active;
  if ((GNUNET_YES == test_is_active) &&
      (GNUNET_YES == result))
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
	 "Looks like `%s' is already running.\n",
	 "gnunet-service-arm");
    /* arm is running! */
    if (cm->result_cont)
      cm->result_cont (cm->cont_cls,
		       GNUNET_ARM_REQUEST_SENT_OK, "arm",
		       GNUNET_ARM_RESULT_IS_STARTED_ALREADY);
  }
  if (GNUNET_NO == test_is_active)
  {
    /* User disconnected & destroyed ARM handle in the middle of
     * the service test, so we kept the handle around until now.
     */
    GNUNET_CONFIGURATION_destroy (cm->h->cfg);
    GNUNET_free (cm->h);
  }
  if ((GNUNET_YES == result) ||
      (GNUNET_NO == test_is_active))
  {
    GNUNET_free (cm);
    return;
  }
  cm->h->service_test_is_active = GNUNET_NO;
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Looks like `%s' is not running, will start it.\n",
       "gnunet-service-arm");
  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (
      cm->h->cfg, "arm", "PREFIX", &loprefix))
    loprefix = GNUNET_strdup ("");
  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (
      cm->h->cfg, "arm", "OPTIONS", &lopostfix))
    lopostfix = GNUNET_strdup ("");
  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (
      cm->h->cfg, "arm", "BINARY", &cbinary))
  {
    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING, "arm", "BINARY");
    if (cm->result_cont)
      cm->result_cont (cm->cont_cls,
		       GNUNET_ARM_REQUEST_SENT_OK, "arm",
		       GNUNET_ARM_RESULT_IS_NOT_KNOWN);
    GNUNET_free (cm);
    GNUNET_free (loprefix);
    GNUNET_free (lopostfix);
    return;
  }
  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (
      cm->h->cfg, "arm", "CONFIG", &config))
    config = NULL;
  binary = GNUNET_OS_get_libexec_binary_path (cbinary);
  GNUNET_asprintf (&quotedbinary,
		   "\"%s\"",
		   binary);
  GNUNET_free (cbinary);
  if ((GNUNET_YES == GNUNET_CONFIGURATION_have_value (
          cm->h->cfg, "TESTING", "WEAKRANDOM")) &&
      (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (
          cm->h->cfg, "TESTING", "WEAKRANDOM")) &&
      (GNUNET_NO == GNUNET_CONFIGURATION_have_value (
          cm->h->cfg, "TESTING", "HOSTFILE")))
  {
    /* Means we are ONLY running locally */
    /* we're clearly running a test, don't daemonize */
    if (NULL == config)
      proc = GNUNET_OS_start_process_s (GNUNET_NO, cm->std_inheritance,
                                        NULL, loprefix, quotedbinary,
                                        /* no daemonization! */
                                        lopostfix, NULL);
    else
      proc = GNUNET_OS_start_process_s (GNUNET_NO, cm->std_inheritance,
			       NULL, loprefix, quotedbinary, "-c", config,
                                        /* no daemonization! */
                                        lopostfix, NULL);
  }
  else
  {
    if (NULL == config)
      proc = GNUNET_OS_start_process_s (GNUNET_NO, cm->std_inheritance,
                                        NULL, loprefix, quotedbinary,
                                        "-d", lopostfix, NULL);
    else
      proc = GNUNET_OS_start_process_s (GNUNET_NO, cm->std_inheritance,
                                        NULL, loprefix, quotedbinary, "-c",
                                        config,
                                        "-d", lopostfix, NULL);
  }
  GNUNET_free (binary);
  GNUNET_free (quotedbinary);
  GNUNET_free_non_null (config);
  GNUNET_free (loprefix);
  GNUNET_free (lopostfix);
  if (NULL == proc)
  {
    if (cm->result_cont)
      cm->result_cont (cm->cont_cls, GNUNET_ARM_REQUEST_SENT_OK, "arm",
          GNUNET_ARM_RESULT_START_FAILED);
    GNUNET_free (cm);
    return;
  }
  if (cm->result_cont)
    cm->result_cont (cm->cont_cls, GNUNET_ARM_REQUEST_SENT_OK, "arm",
        GNUNET_ARM_RESULT_STARTING);
  GNUNET_OS_process_destroy (proc);
  h = cm->h;
  GNUNET_free (cm);
  reconnect_arm (h);
}