Ejemplo n.º 1
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);
}
Ejemplo n.º 2
0
/**
 * Create a connection handle by accepting on a listen socket.  This
 * function may block if the listen socket has no connection ready.
 *
 * @param access function to use to check if access is allowed
 * @param access_cls closure for access
 * @param lsock listen socket
 * @return the connection handle, NULL on error
 */
struct GNUNET_CONNECTION_Handle *
GNUNET_CONNECTION_create_from_accept (GNUNET_CONNECTION_AccessCheck access,
                                      void *access_cls,
                                      struct GNUNET_NETWORK_Handle *lsock)
{
  struct GNUNET_CONNECTION_Handle *connection;
  char addr[128];
  socklen_t addrlen;
  struct GNUNET_NETWORK_Handle *sock;
  int aret;
  struct sockaddr_in *v4;
  struct sockaddr_in6 *v6;
  struct sockaddr *sa;
  void *uaddr;
  struct GNUNET_CONNECTION_Credentials *gcp;
  struct GNUNET_CONNECTION_Credentials gc;
#ifdef SO_PEERCRED
  struct ucred uc;
  socklen_t olen;
#endif

  addrlen = sizeof (addr);
  sock =
      GNUNET_NETWORK_socket_accept (lsock, (struct sockaddr *) &addr, &addrlen);
  if (NULL == sock)
  {
    LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "accept");
    return NULL;
  }
  if ((addrlen > sizeof (addr)) || (addrlen < sizeof (sa_family_t)))
  {
    GNUNET_break (0);
    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
    return NULL;
  }

  sa = (struct sockaddr *) addr;
  v6 = (struct sockaddr_in6 *) addr;
  if ((AF_INET6 == sa->sa_family) && (IN6_IS_ADDR_V4MAPPED (&v6->sin6_addr)))
  {
    /* convert to V4 address */
    v4 = GNUNET_malloc (sizeof (struct sockaddr_in));
    memset (v4, 0, sizeof (struct sockaddr_in));
    v4->sin_family = AF_INET;
#if HAVE_SOCKADDR_IN_SIN_LEN
    v4->sin_len = (u_char) sizeof (struct sockaddr_in);
#endif
    memcpy (&v4->sin_addr,
            &((char *) &v6->sin6_addr)[sizeof (struct in6_addr) -
                                       sizeof (struct in_addr)],
            sizeof (struct in_addr));
    v4->sin_port = v6->sin6_port;
    uaddr = v4;
    addrlen = sizeof (struct sockaddr_in);
  }
  else
  {
    uaddr = GNUNET_malloc (addrlen);
    memcpy (uaddr, addr, addrlen);
  }
  gcp = NULL;
  gc.uid = 0;
  gc.gid = 0;
  if (AF_UNIX == sa->sa_family)
  {
#if HAVE_GETPEEREID
    /* most BSDs */
    if (0 == getpeereid (GNUNET_NETWORK_get_fd (sock), &gc.uid, &gc.gid))
      gcp = &gc;
#else
#ifdef SO_PEERCRED
    /* largely traditional GNU/Linux */
    olen = sizeof (uc);
    if ((0 ==
         getsockopt (GNUNET_NETWORK_get_fd (sock), SOL_SOCKET, SO_PEERCRED, &uc,
                     &olen)) && (olen == sizeof (uc)))
    {
      gc.uid = uc.uid;
      gc.gid = uc.gid;
      gcp = &gc;
    }
#else
#if HAVE_GETPEERUCRED
    /* this is for Solaris 10 */
    ucred_t *uc;

    uc = NULL;
    if (0 == getpeerucred (GNUNET_NETWORK_get_fd (sock), &uc))
    {
      gc.uid = ucred_geteuid (uc);
      gc.gid = ucred_getegid (uc);
      gcp = &gc;
    }
    ucred_free (uc);
#endif
#endif
#endif
  }

  if ((NULL != access) &&
      (GNUNET_YES != (aret = access (access_cls, gcp, uaddr, addrlen))))
  {
    if (GNUNET_NO == aret)
      LOG (GNUNET_ERROR_TYPE_INFO, _("Access denied to `%s'\n"),
           GNUNET_a2s (uaddr, addrlen));
    GNUNET_break (GNUNET_OK ==
                  GNUNET_NETWORK_socket_shutdown (sock, SHUT_RDWR));
    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
    GNUNET_free (uaddr);
    return NULL;
  }
  connection = GNUNET_malloc (sizeof (struct GNUNET_CONNECTION_Handle));
  connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE;
  connection->write_buffer = GNUNET_malloc (connection->write_buffer_size);
  connection->addr = uaddr;
  connection->addrlen = addrlen;
  connection->sock = sock;
  LOG (GNUNET_ERROR_TYPE_INFO, 
       _("Accepting connection from `%s': %p\n"),
       GNUNET_a2s (uaddr, addrlen), connection);
  return connection;
}
Ejemplo n.º 3
0
/**
 * Actually do the reading of a DNS packet from our UDP socket and see
 * if we have a valid, matching, pending request.
 *
 * @param rs request socket with callback details
 * @param dnsout socket to read from
 * @return GNUNET_OK on success, GNUNET_NO on drop, GNUNET_SYSERR on IO-errors (closed socket)
 */
static int
do_dns_read (struct GNUNET_DNSSTUB_RequestSocket *rs,
	     struct GNUNET_NETWORK_Handle *dnsout)
{
  struct sockaddr_storage addr;
  socklen_t addrlen;
  struct GNUNET_TUN_DnsHeader *dns;
  ssize_t r;
  int len;

#ifndef MINGW
  if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout), FIONREAD, &len))
  {
    /* conservative choice: */
    len = UINT16_MAX;
  }
#else
  /* port the code above? */
  len = UINT16_MAX;
#endif
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
	      "Receiving %d byte DNS reply\n",
	      len); 
  {
    unsigned char buf[len] GNUNET_ALIGN;

    addrlen = sizeof (addr);
    memset (&addr, 0, sizeof (addr));  
    r = GNUNET_NETWORK_socket_recvfrom (dnsout, 
					buf, sizeof (buf),
					(struct sockaddr*) &addr, &addrlen);
    if (-1 == r)
    {
      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "recvfrom");
      GNUNET_NETWORK_socket_close (dnsout);
      return GNUNET_SYSERR;
    }
    if (sizeof (struct GNUNET_TUN_DnsHeader) > r)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
		  _("Received DNS response that is too small (%u bytes)"),
		  r);
      return GNUNET_NO;
    }
    dns = (struct GNUNET_TUN_DnsHeader *) buf;
    if ( (addrlen != rs->addrlen) ||
	 (0 != memcmp (&rs->addr,
		       &addr,
		       addrlen)) ||	 
       (0 == GNUNET_TIME_absolute_get_remaining (rs->timeout).rel_value) )
    {
      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
		  "Request timeout or invalid sender address; ignoring reply\n"); 
      return GNUNET_NO;
    }
    if (NULL != rs->rc)
      rs->rc (rs->rc_cls,
	      rs,
	      dns,
	      r);
  }  
  return GNUNET_OK;
}