-remove find() forking, we pretty much should not need this anymore, and it confused...
[oweals/gnunet.git] / src / util / service.c
index b5711972bfaaadeac03baab86bf25adf32be0823..8f8cca36daaa8e06228e5b5f2f4b20a0b77993be 100644 (file)
@@ -1,10 +1,10 @@
 /*
      This file is part of GNUnet.
 /*
      This file is part of GNUnet.
-     (C) 2009 Christian Grothoff (and other contributing authors)
+     (C) 2009, 2012 Christian Grothoff (and other contributing authors)
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
  * @author Christian Grothoff
  */
 #include "platform.h"
  * @author Christian Grothoff
  */
 #include "platform.h"
-#include "gnunet_common.h"
-#include "gnunet_configuration_lib.h"
-#include "gnunet_crypto_lib.h"
-#include "gnunet_directories.h"
-#include "gnunet_disk_lib.h"
-#include "gnunet_getopt_lib.h"
-#include "gnunet_os_lib.h"
+#include "gnunet_util_lib.h"
 #include "gnunet_protocols.h"
 #include "gnunet_protocols.h"
+#include "gnunet_directories.h"
 #include "gnunet_resolver_service.h"
 #include "gnunet_resolver_service.h"
-#include "gnunet_server_lib.h"
-#include "gnunet_service_lib.h"
+
+#if HAVE_MALLINFO
+#include <malloc.h>
+#include "gauger.h"
+#endif
+
 
 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
 
 
 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
 
 
 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
 
 
 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
 
-#define DEBUG_SERVICE GNUNET_EXTRA_LOGGING
 
 /* ******************* access control ******************** */
 
 /**
 
 /* ******************* access control ******************** */
 
 /**
- * @brief IPV4 network in CIDR notation.
- */
-struct IPv4NetworkSet
-{
-  struct in_addr network;
-  struct in_addr netmask;
-};
-
-/**
- * @brief network in CIDR notation for IPV6.
- */
-struct IPv6NetworkSet
-{
-  struct in6_addr network;
-  struct in6_addr netmask;
-};
-
-
-/**
- * Parse a network specification. The argument specifies
- * a list of networks. The format is
- * <tt>[network/netmask;]*</tt> (no whitespace, must be terminated
- * with a semicolon). The network must be given in dotted-decimal
- * notation. The netmask can be given in CIDR notation (/16) or
- * in dotted-decimal (/255.255.0.0).
- * <p>
- * @param routeList a string specifying the forbidden networks
- * @return the converted list, NULL if the synatx is flawed
+ * Start task that may speed up our system clock artificially
+ *
+ * @param cfg configuration to use
+ * @return GNUNET_OK on success, GNUNET_SYSERR if the speedup was not configured
  */
  */
-static struct IPv4NetworkSet *
-parse_ipv4_specification (const char *routeList)
-{
-  unsigned int count;
-  unsigned int i;
-  unsigned int j;
-  unsigned int len;
-  int cnt;
-  unsigned int pos;
-  unsigned int temps[8];
-  int slash;
-  struct IPv4NetworkSet *result;
-
-  if (routeList == NULL)
-    return NULL;
-  len = strlen (routeList);
-  if (len == 0)
-    return NULL;
-  count = 0;
-  for (i = 0; i < len; i++)
-    if (routeList[i] == ';')
-      count++;
-  result = GNUNET_malloc (sizeof (struct IPv4NetworkSet) * (count + 1));
-  /* add termination */
-  memset (result, 0, sizeof (struct IPv4NetworkSet) * (count + 1));
-  i = 0;
-  pos = 0;
-  while (i < count)
-  {
-    cnt =
-        sscanf (&routeList[pos], "%u.%u.%u.%u/%u.%u.%u.%u;", &temps[0],
-                &temps[1], &temps[2], &temps[3], &temps[4], &temps[5],
-                &temps[6], &temps[7]);
-    if (cnt == 8)
-    {
-      for (j = 0; j < 8; j++)
-        if (temps[j] > 0xFF)
-        {
-          LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
-               &routeList[pos]);
-          GNUNET_free (result);
-          return NULL;
-        }
-      result[i].network.s_addr =
-          htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
-                 temps[3]);
-      result[i].netmask.s_addr =
-          htonl ((temps[4] << 24) + (temps[5] << 16) + (temps[6] << 8) +
-                 temps[7]);
-      while (routeList[pos] != ';')
-        pos++;
-      pos++;
-      i++;
-      continue;
-    }
-    /* try second notation */
-    cnt =
-        sscanf (&routeList[pos], "%u.%u.%u.%u/%u;", &temps[0], &temps[1],
-                &temps[2], &temps[3], &slash);
-    if (cnt == 5)
-    {
-      for (j = 0; j < 4; j++)
-        if (temps[j] > 0xFF)
-        {
-          LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
-               &routeList[pos]);
-          GNUNET_free (result);
-          return NULL;
-        }
-      result[i].network.s_addr =
-          htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
-                 temps[3]);
-      if ((slash <= 32) && (slash >= 0))
-      {
-        result[i].netmask.s_addr = 0;
-        while (slash > 0)
-        {
-          result[i].netmask.s_addr =
-              (result[i].netmask.s_addr >> 1) + 0x80000000;
-          slash--;
-        }
-        result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
-        while (routeList[pos] != ';')
-          pos++;
-        pos++;
-        i++;
-        continue;
-      }
-      else
-      {
-        LOG (GNUNET_ERROR_TYPE_ERROR,
-             _("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."),
-             slash);
-        GNUNET_free (result);
-        return NULL;            /* error */
-      }
-    }
-    /* try third notation */
-    slash = 32;
-    cnt =
-        sscanf (&routeList[pos], "%u.%u.%u.%u;", &temps[0], &temps[1],
-                &temps[2], &temps[3]);
-    if (cnt == 4)
-    {
-      for (j = 0; j < 4; j++)
-        if (temps[j] > 0xFF)
-        {
-          LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
-               &routeList[pos]);
-          GNUNET_free (result);
-          return NULL;
-        }
-      result[i].network.s_addr =
-          htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
-                 temps[3]);
-      result[i].netmask.s_addr = 0;
-      while (slash > 0)
-      {
-        result[i].netmask.s_addr = (result[i].netmask.s_addr >> 1) + 0x80000000;
-        slash--;
-      }
-      result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
-      while (routeList[pos] != ';')
-        pos++;
-      pos++;
-      i++;
-      continue;
-    }
-    LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
-         &routeList[pos]);
-    GNUNET_free (result);
-    return NULL;                /* error */
-  }
-  if (pos < strlen (routeList))
-  {
-    LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
-         &routeList[pos]);
-    GNUNET_free (result);
-    return NULL;                /* oops */
-  }
-  return result;                /* ok */
-}
-
+int
+GNUNET_SPEEDUP_start_ (const struct GNUNET_CONFIGURATION_Handle *cfg);
 
 /**
 
 /**
- * Parse a network specification. The argument specifies
- * a list of networks. The format is
- * <tt>[network/netmask;]*</tt> (no whitespace, must be terminated
- * with a semicolon). The network must be given in colon-hex
- * notation.  The netmask must be given in CIDR notation (/16) or
- * can be omitted to specify a single host.
- * <p>
- * @param routeListX a string specifying the forbidden networks
- * @return the converted list, NULL if the synatx is flawed
+ * Stop tasks that modify clock behavior.
  */
  */
-static struct IPv6NetworkSet *
-parse_ipv6_specification (const char *routeListX)
-{
-  unsigned int count;
-  unsigned int i;
-  unsigned int len;
-  unsigned int pos;
-  int start;
-  int slash;
-  int ret;
-  char *routeList;
-  struct IPv6NetworkSet *result;
-  unsigned int bits;
-  unsigned int off;
-  int save;
-
-  if (routeListX == NULL)
-    return NULL;
-  len = strlen (routeListX);
-  if (len == 0)
-    return NULL;
-  routeList = GNUNET_strdup (routeListX);
-  count = 0;
-  for (i = 0; i < len; i++)
-    if (routeList[i] == ';')
-      count++;
-  if (routeList[len - 1] != ';')
-  {
-    LOG (GNUNET_ERROR_TYPE_ERROR,
-         _("Invalid network notation (does not end with ';': `%s')\n"),
-         routeList);
-    GNUNET_free (routeList);
-    return NULL;
-  }
-
-  result = GNUNET_malloc (sizeof (struct IPv6NetworkSet) * (count + 1));
-  memset (result, 0, sizeof (struct IPv6NetworkSet) * (count + 1));
-  i = 0;
-  pos = 0;
-  while (i < count)
-  {
-    start = pos;
-    while (routeList[pos] != ';')
-      pos++;
-    slash = pos;
-    while ((slash >= start) && (routeList[slash] != '/'))
-      slash--;
-    if (slash < start)
-    {
-      memset (&result[i].netmask, 0xFF, sizeof (struct in6_addr));
-      slash = pos;
-    }
-    else
-    {
-      routeList[pos] = '\0';
-      ret = inet_pton (AF_INET6, &routeList[slash + 1], &result[i].netmask);
-      if (ret <= 0)
-      {
-        save = errno;
-        if ((1 != SSCANF (&routeList[slash + 1], "%u", &bits)) || (bits >= 128))
-        {
-          if (ret == 0)
-            LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong format `%s' for netmask\n"),
-                 &routeList[slash + 1]);
-          else
-          {
-            errno = save;
-            LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "inet_pton");
-          }
-          GNUNET_free (result);
-          GNUNET_free (routeList);
-          return NULL;
-        }
-        off = 0;
-        while (bits > 8)
-        {
-          result[i].netmask.s6_addr[off++] = 0xFF;
-          bits -= 8;
-        }
-        while (bits > 0)
-        {
-          result[i].netmask.s6_addr[off] =
-              (result[i].netmask.s6_addr[off] >> 1) + 0x80;
-          bits--;
-        }
-      }
-    }
-    routeList[slash] = '\0';
-    ret = inet_pton (AF_INET6, &routeList[start], &result[i].network);
-    if (ret <= 0)
-    {
-      if (ret == 0)
-        LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong format `%s' for network\n"),
-             &routeList[slash + 1]);
-      else
-        LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "inet_pton");
-      GNUNET_free (result);
-      GNUNET_free (routeList);
-      return NULL;
-    }
-    pos++;
-    i++;
-  }
-  GNUNET_free (routeList);
-  return result;
-}
+void
+GNUNET_SPEEDUP_stop_ (void);
 
 
 /**
 
 
 /**
@@ -344,17 +65,17 @@ parse_ipv6_specification (const char *routeListX)
  *
  * @param list a list of networks
  * @param add the IP to check (in network byte order)
  *
  * @param list a list of networks
  * @param add the IP to check (in network byte order)
- * @return GNUNET_NO if the IP is not in the list, GNUNET_YES if it it is
+ * @return #GNUNET_NO if the IP is not in the list, #GNUNET_YES if it it is
  */
 static int
  */
 static int
-check_ipv4_listed (const struct IPv4NetworkSet *list, const struct in_addr *add)
+check_ipv4_listed (const struct GNUNET_STRINGS_IPv4NetworkPolicy *list,
+                   const struct in_addr *add)
 {
 {
-  int i;
+  unsigned int i;
 
 
-  i = 0;
-  if (list == NULL)
+  if (NULL == list)
     return GNUNET_NO;
     return GNUNET_NO;
-
+  i = 0;
   while ((list[i].network.s_addr != 0) || (list[i].netmask.s_addr != 0))
   {
     if ((add->s_addr & list[i].netmask.s_addr) ==
   while ((list[i].network.s_addr != 0) || (list[i].netmask.s_addr != 0))
   {
     if ((add->s_addr & list[i].netmask.s_addr) ==
@@ -365,27 +86,28 @@ check_ipv4_listed (const struct IPv4NetworkSet *list, const struct in_addr *add)
   return GNUNET_NO;
 }
 
   return GNUNET_NO;
 }
 
+
 /**
  * Check if the given IP address is in the list of IP addresses.
  *
  * @param list a list of networks
  * @param ip the IP to check (in network byte order)
 /**
  * Check if the given IP address is in the list of IP addresses.
  *
  * @param list a list of networks
  * @param ip the IP to check (in network byte order)
- * @return GNUNET_NO if the IP is not in the list, GNUNET_YES if it it is
+ * @return #GNUNET_NO if the IP is not in the list, #GNUNET_YES if it it is
  */
 static int
  */
 static int
-check_ipv6_listed (const struct IPv6NetworkSet *list, const struct in6_addr *ip)
+check_ipv6_listed (const struct GNUNET_STRINGS_IPv6NetworkPolicy *list,
+                   const struct in6_addr *ip)
 {
   unsigned int i;
   unsigned int j;
   struct in6_addr zero;
 
 {
   unsigned int i;
   unsigned int j;
   struct in6_addr zero;
 
-  if (list == NULL)
+  if (NULL == list)
     return GNUNET_NO;
     return GNUNET_NO;
-
   memset (&zero, 0, sizeof (struct in6_addr));
   i = 0;
 NEXT:
   memset (&zero, 0, sizeof (struct in6_addr));
   i = 0;
 NEXT:
-  while (memcmp (&zero, &list[i].network, sizeof (struct in6_addr)) != 0)
+  while (0 != memcmp (&zero, &list[i].network, sizeof (struct in6_addr)))
   {
     for (j = 0; j < sizeof (struct in6_addr) / sizeof (int); j++)
       if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) !=
   {
     for (j = 0; j < sizeof (struct in6_addr) / sizeof (int); j++)
       if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) !=
@@ -427,7 +149,7 @@ struct GNUNET_SERVICE_Context
   /**
    * Name of our service.
    */
   /**
    * Name of our service.
    */
-  const char *serviceName;
+  const char *service_name;
 
   /**
    * Main service-specific task to run.
 
   /**
    * Main service-specific task to run.
@@ -442,24 +164,24 @@ struct GNUNET_SERVICE_Context
   /**
    * IPv4 addresses that are not allowed to connect.
    */
   /**
    * IPv4 addresses that are not allowed to connect.
    */
-  struct IPv4NetworkSet *v4_denied;
+  struct GNUNET_STRINGS_IPv4NetworkPolicy *v4_denied;
 
   /**
    * IPv6 addresses that are not allowed to connect.
    */
 
   /**
    * IPv6 addresses that are not allowed to connect.
    */
-  struct IPv6NetworkSet *v6_denied;
+  struct GNUNET_STRINGS_IPv6NetworkPolicy *v6_denied;
 
   /**
    * IPv4 addresses that are allowed to connect (if not
    * set, all are allowed).
    */
 
   /**
    * IPv4 addresses that are allowed to connect (if not
    * set, all are allowed).
    */
-  struct IPv4NetworkSet *v4_allowed;
+  struct GNUNET_STRINGS_IPv4NetworkPolicy *v4_allowed;
 
   /**
    * IPv6 addresses that are allowed to connect (if not
    * set, all are allowed).
    */
 
   /**
    * IPv6 addresses that are allowed to connect (if not
    * set, all are allowed).
    */
-  struct IPv6NetworkSet *v6_allowed;
+  struct GNUNET_STRINGS_IPv6NetworkPolicy *v6_allowed;
 
   /**
    * My (default) message handlers.  Adjusted copy
 
   /**
    * My (default) message handlers.  Adjusted copy
@@ -477,6 +199,11 @@ struct GNUNET_SERVICE_Context
    */
   struct GNUNET_NETWORK_Handle **lsocks;
 
    */
   struct GNUNET_NETWORK_Handle **lsocks;
 
+  /**
+   * Task ID of the shutdown task.
+   */
+  GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
+
   /**
    * Idle timeout for server.
    */
   /**
    * Idle timeout for server.
    */
@@ -501,14 +228,18 @@ struct GNUNET_SERVICE_Context
   int require_found;
 
   /**
   int require_found;
 
   /**
-   * Do we require a matching UID for UNIX domain socket
-   * connections?
+   * Do we require a matching UID for UNIX domain socket connections?
+   * #GNUNET_NO means that the UID does not have to match (however,
+   * @e match_gid may still impose other access control checks).
    */
   int match_uid;
 
   /**
    */
   int match_uid;
 
   /**
-   * Do we require a matching GID for UNIX domain socket
-   * connections?
+   * Do we require a matching GID for UNIX domain socket connections?
+   * Ignored if @e match_uid is #GNUNET_YES.  Note that this is about
+   * checking that the client's UID is in our group OR that the
+   * client's GID is our GID.  If both "match_gid" and @e match_uid are
+   * #GNUNET_NO, all users on the local system have access.
    */
   int match_gid;
 
    */
   int match_gid;
 
@@ -522,6 +253,14 @@ struct GNUNET_SERVICE_Context
 
 /* ****************** message handlers ****************** */
 
 
 /* ****************** message handlers ****************** */
 
+/**
+ * Send a 'TEST' message back to the client.
+ *
+ * @param cls the 'struct GNUNET_SERVER_Client' to send TEST to
+ * @param size number of bytes available in 'buf'
+ * @param buf where to copy the message
+ * @return number of bytes written to 'buf'
+ */
 static size_t
 write_test (void *cls, size_t size, void *buf)
 {
 static size_t
 write_test (void *cls, size_t size, void *buf)
 {
@@ -540,6 +279,7 @@ write_test (void *cls, size_t size, void *buf)
   return sizeof (struct GNUNET_MessageHeader);
 }
 
   return sizeof (struct GNUNET_MessageHeader);
 }
 
+
 /**
  * Handler for TEST message.
  *
 /**
  * Handler for TEST message.
  *
@@ -573,7 +313,6 @@ static const struct GNUNET_SERVER_MessageHandler defhandlers[] = {
 };
 
 
 };
 
 
-
 /* ****************** service core routines ************** */
 
 
 /* ****************** service core routines ************** */
 
 
@@ -584,7 +323,7 @@ static const struct GNUNET_SERVER_MessageHandler defhandlers[] = {
  * @param uc credentials, if available, otherwise NULL
  * @param addr address
  * @param addrlen length of address
  * @param uc credentials, if available, otherwise NULL
  * @param addr address
  * @param addrlen length of address
- * @return GNUNET_YES to allow, GNUNET_NO to deny, GNUNET_SYSERR
+ * @return #GNUNET_YES to allow, #GNUNET_NO to deny, #GNUNET_SYSERR
  *   for unknown address family (will be denied).
  */
 static int
  *   for unknown address family (will be denied).
  */
 static int
@@ -601,33 +340,22 @@ check_access (void *cls, const struct GNUNET_CONNECTION_Credentials *uc,
   case AF_INET:
     GNUNET_assert (addrlen == sizeof (struct sockaddr_in));
     i4 = (const struct sockaddr_in *) addr;
   case AF_INET:
     GNUNET_assert (addrlen == sizeof (struct sockaddr_in));
     i4 = (const struct sockaddr_in *) addr;
-    ret = ((sctx->v4_allowed == NULL) ||
+    ret = ((NULL == sctx->v4_allowed) ||
            (check_ipv4_listed (sctx->v4_allowed, &i4->sin_addr))) &&
            (check_ipv4_listed (sctx->v4_allowed, &i4->sin_addr))) &&
-        ((sctx->v4_denied == NULL) ||
+        ((NULL == sctx->v4_denied) ||
          (!check_ipv4_listed (sctx->v4_denied, &i4->sin_addr)));
     break;
   case AF_INET6:
     GNUNET_assert (addrlen == sizeof (struct sockaddr_in6));
     i6 = (const struct sockaddr_in6 *) addr;
          (!check_ipv4_listed (sctx->v4_denied, &i4->sin_addr)));
     break;
   case AF_INET6:
     GNUNET_assert (addrlen == sizeof (struct sockaddr_in6));
     i6 = (const struct sockaddr_in6 *) addr;
-    ret = ((sctx->v6_allowed == NULL) ||
+    ret = ((NULL == sctx->v6_allowed) ||
            (check_ipv6_listed (sctx->v6_allowed, &i6->sin6_addr))) &&
            (check_ipv6_listed (sctx->v6_allowed, &i6->sin6_addr))) &&
-        ((sctx->v6_denied == NULL) ||
+        ((NULL == sctx->v6_denied) ||
          (!check_ipv6_listed (sctx->v6_denied, &i6->sin6_addr)));
     break;
 #ifndef WINDOWS
   case AF_UNIX:
          (!check_ipv6_listed (sctx->v6_denied, &i6->sin6_addr)));
     break;
 #ifndef WINDOWS
   case AF_UNIX:
-    ret = GNUNET_OK;            /* always OK for now */
-    if ((sctx->match_uid == GNUNET_YES) || (sctx->match_gid == GNUNET_YES))
-      ret = GNUNET_NO;
-    if ((uc != NULL) &&
-        ((sctx->match_uid != GNUNET_YES) || (uc->uid == geteuid ()) ||
-         (uc->uid == getuid ())) && ((sctx->match_gid != GNUNET_YES) ||
-                                     (uc->gid == getegid ()) ||
-                                     (uc->gid == getgid ())))
-      ret = GNUNET_YES;
-    else
-      LOG (GNUNET_ERROR_TYPE_WARNING, _("Access denied to UID %d / GID %d\n"),
-           (uc == NULL) ? -1 : uc->uid, (uc == NULL) ? -1 : uc->gid);
+    ret = GNUNET_OK;            /* controlled using file-system ACL now */
     break;
 #endif
   default:
     break;
 #endif
   default:
@@ -635,12 +363,12 @@ check_access (void *cls, const struct GNUNET_CONNECTION_Credentials *uc,
          addr->sa_family);
     return GNUNET_SYSERR;
   }
          addr->sa_family);
     return GNUNET_SYSERR;
   }
-  if (ret != GNUNET_OK)
+  if (GNUNET_OK != ret)
   {
     LOG (GNUNET_ERROR_TYPE_WARNING,
   {
     LOG (GNUNET_ERROR_TYPE_WARNING,
-         _("Access from `%s' denied to service `%s'\n"), GNUNET_a2s (addr,
-                                                                     addrlen),
-         sctx->serviceName);
+         _("Access from `%s' denied to service `%s'\n"),
+        GNUNET_a2s (addr, addrlen),
+         sctx->service_name);
   }
   return ret;
 }
   }
   return ret;
 }
@@ -649,15 +377,17 @@ check_access (void *cls, const struct GNUNET_CONNECTION_Credentials *uc,
 /**
  * Get the name of the file where we will
  * write the PID of the service.
 /**
  * Get the name of the file where we will
  * write the PID of the service.
+ *
+ * @param sctx service context
+ * @return name of the file for the process ID
  */
 static char *
 get_pid_file_name (struct GNUNET_SERVICE_Context *sctx)
 {
  */
 static char *
 get_pid_file_name (struct GNUNET_SERVICE_Context *sctx)
 {
-
   char *pif;
 
   if (GNUNET_OK !=
   char *pif;
 
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_filename (sctx->cfg, sctx->serviceName,
+      GNUNET_CONFIGURATION_get_value_filename (sctx->cfg, sctx->service_name,
                                                "PIDFILE", &pif))
     return NULL;
   return pif;
                                                "PIDFILE", &pif))
     return NULL;
   return pif;
@@ -666,24 +396,33 @@ get_pid_file_name (struct GNUNET_SERVICE_Context *sctx)
 
 /**
  * Parse an IPv4 access control list.
 
 /**
  * Parse an IPv4 access control list.
+ *
+ * @param ret location where to write the ACL (set)
+ * @param sctx service context to use to get the configuration
+ * @param option name of the ACL option to parse
+ * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including
+ *         no ACL configured)
  */
 static int
  */
 static int
-process_acl4 (struct IPv4NetworkSet **ret, struct GNUNET_SERVICE_Context *sctx,
+process_acl4 (struct GNUNET_STRINGS_IPv4NetworkPolicy **ret, struct GNUNET_SERVICE_Context *sctx,
               const char *option)
 {
   char *opt;
 
               const char *option)
 {
   char *opt;
 
-  if (!GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->serviceName, option))
+  if (!GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name, option))
+  {
+    *ret = NULL;
     return GNUNET_OK;
     return GNUNET_OK;
+  }
   GNUNET_break (GNUNET_OK ==
                 GNUNET_CONFIGURATION_get_value_string (sctx->cfg,
   GNUNET_break (GNUNET_OK ==
                 GNUNET_CONFIGURATION_get_value_string (sctx->cfg,
-                                                       sctx->serviceName,
+                                                       sctx->service_name,
                                                        option, &opt));
                                                        option, &opt));
-  if (NULL == (*ret = parse_ipv4_specification (opt)))
+  if (NULL == (*ret = GNUNET_STRINGS_parse_ipv4_policy (opt)))
   {
     LOG (GNUNET_ERROR_TYPE_WARNING,
          _("Could not parse IPv4 network specification `%s' for `%s:%s'\n"),
   {
     LOG (GNUNET_ERROR_TYPE_WARNING,
          _("Could not parse IPv4 network specification `%s' for `%s:%s'\n"),
-         opt, sctx->serviceName, option);
+         opt, sctx->service_name, option);
     GNUNET_free (opt);
     return GNUNET_SYSERR;
   }
     GNUNET_free (opt);
     return GNUNET_SYSERR;
   }
@@ -693,25 +432,34 @@ process_acl4 (struct IPv4NetworkSet **ret, struct GNUNET_SERVICE_Context *sctx,
 
 
 /**
 
 
 /**
- * Parse an IPv4 access control list.
+ * Parse an IPv6 access control list.
+ *
+ * @param ret location where to write the ACL (set)
+ * @param sctx service context to use to get the configuration
+ * @param option name of the ACL option to parse
+ * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including
+ *         no ACL configured)
  */
 static int
  */
 static int
-process_acl6 (struct IPv6NetworkSet **ret, struct GNUNET_SERVICE_Context *sctx,
+process_acl6 (struct GNUNET_STRINGS_IPv6NetworkPolicy **ret, struct GNUNET_SERVICE_Context *sctx,
               const char *option)
 {
   char *opt;
 
               const char *option)
 {
   char *opt;
 
-  if (!GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->serviceName, option))
+  if (!GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name, option))
+  {
+    *ret = NULL;
     return GNUNET_OK;
     return GNUNET_OK;
+  }
   GNUNET_break (GNUNET_OK ==
                 GNUNET_CONFIGURATION_get_value_string (sctx->cfg,
   GNUNET_break (GNUNET_OK ==
                 GNUNET_CONFIGURATION_get_value_string (sctx->cfg,
-                                                       sctx->serviceName,
+                                                       sctx->service_name,
                                                        option, &opt));
                                                        option, &opt));
-  if (NULL == (*ret = parse_ipv6_specification (opt)))
+  if (NULL == (*ret = GNUNET_STRINGS_parse_ipv6_policy (opt)))
   {
     LOG (GNUNET_ERROR_TYPE_WARNING,
          _("Could not parse IPv6 network specification `%s' for `%s:%s'\n"),
   {
     LOG (GNUNET_ERROR_TYPE_WARNING,
          _("Could not parse IPv6 network specification `%s' for `%s:%s'\n"),
-         opt, sctx->serviceName, option);
+         opt, sctx->service_name, option);
     GNUNET_free (opt);
     return GNUNET_SYSERR;
   }
     GNUNET_free (opt);
     return GNUNET_SYSERR;
   }
@@ -719,6 +467,7 @@ process_acl6 (struct IPv6NetworkSet **ret, struct GNUNET_SERVICE_Context *sctx,
   return GNUNET_OK;
 }
 
   return GNUNET_OK;
 }
 
+
 /**
  * Add the given UNIX domain path as an address to the
  * list (as the first entry).
 /**
  * Add the given UNIX domain path as an address to the
  * list (as the first entry).
@@ -733,24 +482,15 @@ add_unixpath (struct sockaddr **saddrs, socklen_t * saddrlens,
 {
 #ifdef AF_UNIX
   struct sockaddr_un *un;
 {
 #ifdef AF_UNIX
   struct sockaddr_un *un;
-  size_t slen;
 
 
-  un = GNUNET_malloc (sizeof (struct sockaddr_un));
+  un = GNUNET_new (struct sockaddr_un);
   un->sun_family = AF_UNIX;
   un->sun_family = AF_UNIX;
-  slen = strlen (unixpath) + 1;
-  if (slen >= sizeof (un->sun_path))
-    slen = sizeof (un->sun_path) - 1;
-  memcpy (un->sun_path, unixpath, slen);
-  un->sun_path[slen] = '\0';
-  slen = sizeof (struct sockaddr_un);
-#if LINUX
-  un->sun_path[0] = '\0';
-#endif
+  strncpy (un->sun_path, unixpath, sizeof (un->sun_path) - 1);
 #if HAVE_SOCKADDR_IN_SIN_LEN
 #if HAVE_SOCKADDR_IN_SIN_LEN
-  un->sun_len = (u_char) slen;
+  un->sun_len = (u_char) sizeof (struct sockaddr_un);
 #endif
   *saddrs = (struct sockaddr *) un;
 #endif
   *saddrs = (struct sockaddr *) un;
-  *saddrlens = slen;
+  *saddrlens = sizeof (struct sockaddr_un);
 #else
   /* this function should never be called
    * unless AF_UNIX is defined! */
 #else
   /* this function should never be called
    * unless AF_UNIX is defined! */
@@ -763,7 +503,7 @@ add_unixpath (struct sockaddr **saddrs, socklen_t * saddrlens,
  * Get the list of addresses that a server for the given service
  * should bind to.
  *
  * Get the list of addresses that a server for the given service
  * should bind to.
  *
- * @param serviceName name of the service
+ * @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
  * @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
@@ -772,15 +512,15 @@ add_unixpath (struct sockaddr **saddrs, socklen_t * saddrlens,
  *              of the respective 'struct sockaddr' struct in the 'addrs'
  *              array (on success)
  * @return number of addresses found on success,
  *              of the respective 'struct sockaddr' struct in the 'addrs'
  *              array (on success)
  * @return number of addresses found on success,
- *              GNUNET_SYSERR if the configuration
+ *              #GNUNET_SYSERR if the configuration
  *              did not specify reasonable finding information or
  *              if it specified a hostname that could not be resolved;
  *              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
+ *              #GNUNET_NO if the number of addresses configured is
+ *              zero (in this case, `*addrs` and `*addr_lens` will be
  *              set to NULL).
  */
 int
  *              set to NULL).
  */
 int
-GNUNET_SERVICE_get_server_addresses (const char *serviceName,
+GNUNET_SERVICE_get_server_addresses (const char *service_name,
                                      const struct GNUNET_CONFIGURATION_Handle
                                      *cfg, struct sockaddr ***addrs,
                                      socklen_t ** addr_lens)
                                      const struct GNUNET_CONFIGURATION_Handle
                                      *cfg, struct sockaddr ***addrs,
                                      socklen_t ** addr_lens)
@@ -803,11 +543,11 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName,
   *addrs = NULL;
   *addr_lens = NULL;
   desc = NULL;
   *addrs = NULL;
   *addr_lens = NULL;
   desc = NULL;
-  if (GNUNET_CONFIGURATION_have_value (cfg, serviceName, "DISABLEV6"))
+  if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "DISABLEV6"))
   {
     if (GNUNET_SYSERR ==
         (disablev6 =
   {
     if (GNUNET_SYSERR ==
         (disablev6 =
-         GNUNET_CONFIGURATION_get_value_yesno (cfg, serviceName, "DISABLEV6")))
+         GNUNET_CONFIGURATION_get_value_yesno (cfg, service_name, "DISABLEV6")))
       return GNUNET_SYSERR;
   }
   else
       return GNUNET_SYSERR;
   }
   else
@@ -819,8 +559,8 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName,
     desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
     if (NULL == desc)
     {
     desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
     if (NULL == desc)
     {
-      if ((errno == ENOBUFS) || (errno == ENOMEM) || (errno == ENFILE) ||
-          (errno == EACCES))
+      if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
+          (EACCES == errno))
       {
         LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
         return GNUNET_SYSERR;
       {
         LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
         return GNUNET_SYSERR;
@@ -828,7 +568,7 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName,
       LOG (GNUNET_ERROR_TYPE_INFO,
            _
            ("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
       LOG (GNUNET_ERROR_TYPE_INFO,
            _
            ("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
-           serviceName, STRERROR (errno));
+           service_name, STRERROR (errno));
       disablev6 = GNUNET_YES;
     }
     else
       disablev6 = GNUNET_YES;
     }
     else
@@ -839,24 +579,29 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName,
   }
 
   port = 0;
   }
 
   port = 0;
-  if (GNUNET_CONFIGURATION_have_value (cfg, serviceName, "PORT"))
+  if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT"))
   {
   {
-    GNUNET_break (GNUNET_OK ==
-                  GNUNET_CONFIGURATION_get_value_number (cfg, serviceName,
-                                                         "PORT", &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"),
     if (port > 65535)
     {
       LOG (GNUNET_ERROR_TYPE_ERROR,
            _("Require valid port number for service `%s' in configuration!\n"),
-           serviceName);
+           service_name);
       return GNUNET_SYSERR;
     }
   }
 
       return GNUNET_SYSERR;
     }
   }
 
-  if (GNUNET_CONFIGURATION_have_value (cfg, serviceName, "BINDTO"))
+  if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "BINDTO"))
   {
     GNUNET_break (GNUNET_OK ==
   {
     GNUNET_break (GNUNET_OK ==
-                  GNUNET_CONFIGURATION_get_value_string (cfg, serviceName,
+                  GNUNET_CONFIGURATION_get_value_string (cfg, service_name,
                                                          "BINDTO", &hostname));
   }
   else
                                                          "BINDTO", &hostname));
   }
   else
@@ -865,9 +610,9 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName,
   unixpath = NULL;
 #ifdef AF_UNIX
   if ((GNUNET_YES ==
   unixpath = NULL;
 #ifdef AF_UNIX
   if ((GNUNET_YES ==
-       GNUNET_CONFIGURATION_have_value (cfg, serviceName, "UNIXPATH")) &&
+       GNUNET_CONFIGURATION_have_value (cfg, service_name, "UNIXPATH")) &&
       (GNUNET_OK ==
       (GNUNET_OK ==
-       GNUNET_CONFIGURATION_get_value_string (cfg, serviceName, "UNIXPATH",
+       GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH",
                                               &unixpath)) &&
       (0 < strlen (unixpath)))
   {
                                               &unixpath)) &&
       (0 < strlen (unixpath)))
   {
@@ -878,17 +623,24 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName,
     {
       LOG (GNUNET_ERROR_TYPE_WARNING,
            _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath,
     {
       LOG (GNUNET_ERROR_TYPE_WARNING,
            _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath,
-           sizeof (s_un.sun_path));
-      GNUNET_free_non_null (hostname);
-      GNUNET_free (unixpath);
-      return GNUNET_SYSERR;
+           (unsigned long long) sizeof (s_un.sun_path));
+      unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
+      LOG (GNUNET_ERROR_TYPE_INFO,
+          _("Using `%s' instead\n"), unixpath);
     }
     }
-
+    if (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)
     {
     desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
     if (NULL == desc)
     {
-      if ((errno == ENOBUFS) || (errno == ENOMEM) || (errno == ENFILE) ||
-          (errno == EACCES))
+      if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
+          (EACCES == errno))
       {
         LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
         GNUNET_free_non_null (hostname);
       {
         LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
         GNUNET_free_non_null (hostname);
@@ -896,9 +648,8 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName,
         return GNUNET_SYSERR;
       }
       LOG (GNUNET_ERROR_TYPE_INFO,
         return GNUNET_SYSERR;
       }
       LOG (GNUNET_ERROR_TYPE_INFO,
-           _
-           ("Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
-           serviceName, STRERROR (errno));
+           _("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;
     }
       GNUNET_free (unixpath);
       unixpath = NULL;
     }
@@ -910,16 +661,15 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName,
   }
 #endif
 
   }
 #endif
 
-  if ((port == 0) && (unixpath == NULL))
+  if ((0 == port) && (NULL == unixpath))
   {
     LOG (GNUNET_ERROR_TYPE_ERROR,
   {
     LOG (GNUNET_ERROR_TYPE_ERROR,
-         _
-         ("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
-         serviceName);
+         _("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
+         service_name);
     GNUNET_free_non_null (hostname);
     return GNUNET_SYSERR;
   }
     GNUNET_free_non_null (hostname);
     return GNUNET_SYSERR;
   }
-  if (port == 0)
+  if (0 == port)
   {
     saddrs = GNUNET_malloc (2 * sizeof (struct sockaddr *));
     saddrlens = GNUNET_malloc (2 * sizeof (socklen_t));
   {
     saddrs = GNUNET_malloc (2 * sizeof (struct sockaddr *));
     saddrlens = GNUNET_malloc (2 * sizeof (socklen_t));
@@ -931,16 +681,15 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName,
     return 1;
   }
 
     return 1;
   }
 
-  if (hostname != NULL)
+  if (NULL != hostname)
   {
   {
-#if DEBUG_SERVICE
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Resolving `%s' since that is where `%s' will bind to.\n", hostname,
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Resolving `%s' since that is where `%s' will bind to.\n", hostname,
-         serviceName);
-#endif
+         service_name);
     memset (&hints, 0, sizeof (struct addrinfo));
     if (disablev6)
       hints.ai_family = AF_INET;
     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))) ||
         (res == NULL))
     {
     if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
         (res == NULL))
     {
@@ -983,19 +732,17 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName,
     while (NULL != (pos = next))
     {
       next = pos->ai_next;
     while (NULL != (pos = next))
     {
       next = pos->ai_next;
-      if ((disablev6) && (pos->ai_family == AF_INET6))
+      if ((disablev6) && (AF_INET6 == pos->ai_family))
         continue;
         continue;
-      if ((pos->ai_protocol != IPPROTO_TCP) && (pos->ai_protocol != 0))
+      if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
         continue;               /* not TCP */
         continue;               /* not TCP */
-      if ((pos->ai_socktype != SOCK_STREAM) && (pos->ai_socktype != 0))
+      if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
         continue;               /* huh? */
         continue;               /* huh? */
-#if DEBUG_SERVICE
       LOG (GNUNET_ERROR_TYPE_DEBUG, "Service `%s' will bind to `%s'\n",
       LOG (GNUNET_ERROR_TYPE_DEBUG, "Service `%s' will bind to `%s'\n",
-           serviceName, GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
-#endif
-      if (pos->ai_family == AF_INET)
+           service_name, GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
+      if (AF_INET == pos->ai_family)
       {
       {
-        GNUNET_assert (pos->ai_addrlen == sizeof (struct sockaddr_in));
+        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]);
         saddrlens[i] = pos->ai_addrlen;
         saddrs[i] = GNUNET_malloc (saddrlens[i]);
         memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
@@ -1003,8 +750,8 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName,
       }
       else
       {
       }
       else
       {
-        GNUNET_assert (pos->ai_family == AF_INET6);
-        GNUNET_assert (pos->ai_addrlen == sizeof (struct sockaddr_in6));
+        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]);
         saddrlens[i] = pos->ai_addrlen;
         saddrs[i] = GNUNET_malloc (saddrlens[i]);
         memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
@@ -1079,6 +826,90 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName,
 }
 
 
 }
 
 
+#ifdef MINGW
+/**
+ * Read listen sockets from the parent process (ARM).
+ *
+ * @param sctx service context to initialize
+ * @return #GNUNET_YES if ok, #GNUNET_NO if not ok (must bind yourself),
+ * and #GNUNET_SYSERR on error.
+ */
+static int
+receive_sockets_from_parent (struct GNUNET_SERVICE_Context *sctx)
+{
+  const char *env_buf;
+  int fail;
+  uint64_t count;
+  uint64_t i;
+  HANDLE lsocks_pipe;
+
+  env_buf = getenv ("GNUNET_OS_READ_LSOCKS");
+  if ((NULL == env_buf) || (strlen (env_buf) <= 0))
+    return GNUNET_NO;
+  /* Using W32 API directly here, because this pipe will
+   * never be used outside of this function, and it's just too much of a bother
+   * to create a GNUnet API that boxes a HANDLE (the way it is done with socks)
+   */
+  lsocks_pipe = (HANDLE) strtoul (env_buf, NULL, 10);
+  if ( (0 == lsocks_pipe) || (INVALID_HANDLE_VALUE == lsocks_pipe))
+    return GNUNET_NO;
+  fail = 1;
+  do
+  {
+    int ret;
+    int fail2;
+    DWORD rd;
+
+    ret = ReadFile (lsocks_pipe, &count, sizeof (count), &rd, NULL);
+    if ((0 == ret) || (sizeof (count) != rd) || (0 == count))
+      break;
+    sctx->lsocks =
+        GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle *) * (count + 1));
+
+    fail2 = 1;
+    for (i = 0; i < count; i++)
+    {
+      WSAPROTOCOL_INFOA pi;
+      uint64_t size;
+      SOCKET s;
+
+      ret = ReadFile (lsocks_pipe, &size, sizeof (size), &rd, NULL);
+      if ( (0 == ret) || (sizeof (size) != rd) || (sizeof (pi) != size) )
+        break;
+      ret = ReadFile (lsocks_pipe, &pi, sizeof (pi), &rd, NULL);
+      if ( (0 == ret) || (sizeof (pi) != rd))
+        break;
+      s = WSASocketA (pi.iAddressFamily, pi.iSocketType, pi.iProtocol, &pi, 0, WSA_FLAG_OVERLAPPED);
+      sctx->lsocks[i] = GNUNET_NETWORK_socket_box_native (s);
+      if (NULL == sctx->lsocks[i])
+        break;
+      else if (i == count - 1)
+        fail2 = 0;
+    }
+    if (fail2)
+      break;
+    sctx->lsocks[count] = NULL;
+    fail = 0;
+  }
+  while (fail);
+
+  CloseHandle (lsocks_pipe);
+
+  if (fail)
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         _("Could not access a pre-bound socket, will try to bind myself\n"));
+    for (i = 0; (i < count) && (NULL != sctx->lsocks[i]); i++)
+      GNUNET_break (0 == GNUNET_NETWORK_socket_close (sctx->lsocks[i]));
+    GNUNET_free_non_null (sctx->lsocks);
+    sctx->lsocks = NULL;
+    return GNUNET_NO;
+  }
+  return GNUNET_YES;
+}
+#endif
+
+
 /**
  * Setup addr, addrlen, idle_timeout
  * based on configuration!
 /**
  * Setup addr, addrlen, idle_timeout
  * based on configuration!
@@ -1094,7 +925,8 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName,
  * - REJECT_FROM  (disallow allow connections from specified IPv4 subnets)
  * - REJECT_FROM6 (disallow allow connections from specified IPv6 subnets)
  *
  * - REJECT_FROM  (disallow allow connections from specified IPv4 subnets)
  * - REJECT_FROM6 (disallow allow connections from specified IPv6 subnets)
  *
- * @return GNUNET_OK if configuration succeeded
+ * @param sctx service context to initialize
+ * @return #GNUNET_OK if configuration succeeded
  */
 static int
 setup_service (struct GNUNET_SERVICE_Context *sctx)
  */
 static int
 setup_service (struct GNUNET_SERVICE_Context *sctx)
@@ -1103,22 +935,20 @@ setup_service (struct GNUNET_SERVICE_Context *sctx)
   int tolerant;
 
 #ifndef MINGW
   int tolerant;
 
 #ifndef MINGW
-  const char *lpid;
-  unsigned int pid;
   const char *nfds;
   unsigned int cnt;
   int flags;
 #endif
 
   const char *nfds;
   unsigned int cnt;
   int flags;
 #endif
 
-  if (GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->serviceName, "TIMEOUT"))
+  if (GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name, "TIMEOUT"))
   {
     if (GNUNET_OK !=
   {
     if (GNUNET_OK !=
-        GNUNET_CONFIGURATION_get_value_time (sctx->cfg, sctx->serviceName,
+        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", &idleout))
     {
       LOG (GNUNET_ERROR_TYPE_ERROR,
            _("Specified value for `%s' of service `%s' is invalid\n"),
-           "TIMEOUT", sctx->serviceName);
+           "TIMEOUT", sctx->service_name);
       return GNUNET_SYSERR;
     }
     sctx->timeout = idleout;
       return GNUNET_SYSERR;
     }
     sctx->timeout = idleout;
@@ -1127,16 +957,16 @@ setup_service (struct GNUNET_SERVICE_Context *sctx)
     sctx->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
 
   if (GNUNET_CONFIGURATION_have_value
     sctx->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
 
   if (GNUNET_CONFIGURATION_have_value
-      (sctx->cfg, sctx->serviceName, "TOLERANT"))
+      (sctx->cfg, sctx->service_name, "TOLERANT"))
   {
     if (GNUNET_SYSERR ==
         (tolerant =
   {
     if (GNUNET_SYSERR ==
         (tolerant =
-         GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, sctx->serviceName,
+         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")))
     {
       LOG (GNUNET_ERROR_TYPE_ERROR,
            _("Specified value for `%s' of service `%s' is invalid\n"),
-           "TOLERANT", sctx->serviceName);
+           "TOLERANT", sctx->service_name);
       return GNUNET_SYSERR;
     }
   }
       return GNUNET_SYSERR;
     }
   }
@@ -1145,10 +975,8 @@ setup_service (struct GNUNET_SERVICE_Context *sctx)
 
 #ifndef MINGW
   errno = 0;
 
 #ifndef MINGW
   errno = 0;
-  if ((NULL != (lpid = getenv ("LISTEN_PID"))) &&
-      (1 == sscanf (lpid, "%u", &pid)) && (getpid () == (pid_t) pid) &&
-      (NULL != (nfds = getenv ("LISTEN_FDS"))) &&
-      (1 == sscanf (nfds, "%u", &cnt)) && (cnt > 0) && (cnt < FD_SETSIZE) &&
+  if ((NULL != (nfds = getenv ("LISTEN_FDS"))) &&
+      (1 == SSCANF (nfds, "%u", &cnt)) && (cnt > 0) && (cnt < FD_SETSIZE) &&
       (cnt + 4 < FD_SETSIZE))
   {
     sctx->lsocks =
       (cnt + 4 < FD_SETSIZE))
   {
     sctx->lsocks =
@@ -1172,22 +1000,27 @@ setup_service (struct GNUNET_SERVICE_Context *sctx)
         break;
       }
     }
         break;
       }
     }
-    unsetenv ("LISTEN_PID");
     unsetenv ("LISTEN_FDS");
   }
     unsetenv ("LISTEN_FDS");
   }
+#else
+  if (getenv ("GNUNET_OS_READ_LSOCKS") != NULL)
+  {
+    receive_sockets_from_parent (sctx);
+    putenv ("GNUNET_OS_READ_LSOCKS=");
+  }
 #endif
 
 #endif
 
-  if ((sctx->lsocks == NULL) &&
+  if ((NULL == sctx->lsocks) &&
       (GNUNET_SYSERR ==
       (GNUNET_SYSERR ==
-       GNUNET_SERVICE_get_server_addresses (sctx->serviceName, sctx->cfg,
+       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 =
                                             &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->serviceName,
+      GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, sctx->service_name,
                                             "UNIX_MATCH_UID");
   sctx->match_gid =
                                             "UNIX_MATCH_UID");
   sctx->match_gid =
-      GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, sctx->serviceName,
+      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");
                                             "UNIX_MATCH_GID");
   process_acl4 (&sctx->v4_denied, sctx, "REJECT_FROM");
   process_acl4 (&sctx->v4_allowed, sctx, "ACCEPT_FROM");
@@ -1201,22 +1034,29 @@ setup_service (struct GNUNET_SERVICE_Context *sctx)
 /**
  * Get the name of the user that'll be used
  * to provide the service.
 /**
  * Get the name of the user that'll be used
  * to provide the service.
+ *
+ * @param sctx service context
+ * @return value of the 'USERNAME' option
  */
 static char *
 get_user_name (struct GNUNET_SERVICE_Context *sctx)
 {
  */
 static char *
 get_user_name (struct GNUNET_SERVICE_Context *sctx)
 {
-
   char *un;
 
   if (GNUNET_OK !=
   char *un;
 
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_filename (sctx->cfg, sctx->serviceName,
+      GNUNET_CONFIGURATION_get_value_filename (sctx->cfg, sctx->service_name,
                                                "USERNAME", &un))
     return NULL;
   return un;
 }
 
                                                "USERNAME", &un))
     return NULL;
   return un;
 }
 
+
 /**
  * Write PID file.
 /**
  * Write PID file.
+ *
+ * @param sctx service context
+ * @param pid PID to write (should be equal to 'getpid()'
+ * @return  #GNUNET_OK on success (including no work to be done)
  */
 static int
 write_pid_file (struct GNUNET_SERVICE_Context *sctx, pid_t pid)
  */
 static int
 write_pid_file (struct GNUNET_SERVICE_Context *sctx, pid_t pid)
@@ -1239,8 +1079,8 @@ write_pid_file (struct GNUNET_SERVICE_Context *sctx, pid_t pid)
   {
     /* we get to create a directory -- and claim it
      * as ours! */
   {
     /* we get to create a directory -- and claim it
      * as ours! */
-    GNUNET_DISK_directory_create (rdir);
-    if ((user != NULL) && (0 < strlen (user)))
+    (void) GNUNET_DISK_directory_create (rdir);
+    if ((NULL != user) && (0 < strlen (user)))
       GNUNET_DISK_file_change_owner (rdir, user);
   }
   if (0 != ACCESS (rdir, W_OK | X_OK))
       GNUNET_DISK_file_change_owner (rdir, user);
   }
   if (0 != ACCESS (rdir, W_OK | X_OK))
@@ -1253,7 +1093,7 @@ write_pid_file (struct GNUNET_SERVICE_Context *sctx, pid_t pid)
   }
   GNUNET_free (rdir);
   pidfd = FOPEN (pif, "w");
   }
   GNUNET_free (rdir);
   pidfd = FOPEN (pif, "w");
-  if (pidfd == NULL)
+  if (NULL == pidfd)
   {
     LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "fopen", pif);
     GNUNET_free (pif);
   {
     LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "fopen", pif);
     GNUNET_free (pif);
@@ -1262,8 +1102,8 @@ write_pid_file (struct GNUNET_SERVICE_Context *sctx, pid_t pid)
   }
   if (0 > FPRINTF (pidfd, "%u", pid))
     LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fprintf", pif);
   }
   if (0 > FPRINTF (pidfd, "%u", pid))
     LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fprintf", pif);
-  GNUNET_break (0 == fclose (pidfd));
-  if ((user != NULL) && (0 < strlen (user)))
+  GNUNET_break (0 == FCLOSE (pidfd));
+  if ((NULL != user) && (0 < strlen (user)))
     GNUNET_DISK_file_change_owner (pif, user);
   GNUNET_free_non_null (user);
   GNUNET_free (pif);
     GNUNET_DISK_file_change_owner (pif, user);
   GNUNET_free_non_null (user);
   GNUNET_free (pif);
@@ -1272,22 +1112,30 @@ write_pid_file (struct GNUNET_SERVICE_Context *sctx, pid_t pid)
 
 
 /**
 
 
 /**
- * Task run during shutdown.
+ * Task run during shutdown.  Stops the server/service.
  *
  *
- * @param cls unused
+ * @param cls the `struct GNUNET_SERVICE_Context`
  * @param tc unused
  */
 static void
 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
  * @param tc unused
  */
 static void
 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  struct GNUNET_SERVER_Handle *server = cls;
+  struct GNUNET_SERVICE_Context *service = cls;
+  struct GNUNET_SERVER_Handle *server = service->server;
 
 
-  GNUNET_SERVER_destroy (server);
+  service->shutdown_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (service->options & GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN))
+    GNUNET_SERVER_stop_listening (server);
+  else
+    GNUNET_SERVER_destroy (server);
 }
 
 
 /**
  * Initial task for the service.
 }
 
 
 /**
  * Initial task for the service.
+ *
+ * @param cls service context
+ * @param tc unused
  */
 static void
 service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  */
 static void
 service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
@@ -1295,57 +1143,66 @@ service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   struct GNUNET_SERVICE_Context *sctx = cls;
   unsigned int i;
 
   struct GNUNET_SERVICE_Context *sctx = cls;
   unsigned int i;
 
+  if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
+    return;
+  (void) GNUNET_SPEEDUP_start_ (sctx->cfg);
   GNUNET_RESOLVER_connect (sctx->cfg);
   GNUNET_RESOLVER_connect (sctx->cfg);
-  if (sctx->lsocks != NULL)
-    sctx->server =
-        GNUNET_SERVER_create_with_sockets (&check_access, sctx, sctx->lsocks,
+  if (NULL != sctx->lsocks)
+    sctx->server
+      = GNUNET_SERVER_create_with_sockets (&check_access, sctx, sctx->lsocks,
                                            sctx->timeout, sctx->require_found);
   else
                                            sctx->timeout, sctx->require_found);
   else
-    sctx->server =
-        GNUNET_SERVER_create (&check_access, sctx, sctx->addrs, sctx->addrlens,
+    sctx->server
+      = GNUNET_SERVER_create (&check_access, sctx, sctx->addrs, sctx->addrlens,
                               sctx->timeout, sctx->require_found);
                               sctx->timeout, sctx->require_found);
-  if (sctx->server == NULL)
+  if (NULL == sctx->server)
   {
   {
-    if (sctx->addrs != NULL)
-    {
-      i = 0;
-      while (sctx->addrs[i] != NULL)
-      {
-        LOG (GNUNET_ERROR_TYPE_INFO, _("Failed to start `%s' at `%s'\n"),
-             sctx->serviceName, GNUNET_a2s (sctx->addrs[i], sctx->addrlens[i]));
-        i++;
-      }
-    }
+    if (NULL != sctx->addrs)
+      for (i = 0; NULL != sctx->addrs[i]; i++)
+        LOG (GNUNET_ERROR_TYPE_INFO,
+             _("Failed to start `%s' at `%s'\n"),
+             sctx->service_name, GNUNET_a2s (sctx->addrs[i], sctx->addrlens[i]));
     sctx->ret = GNUNET_SYSERR;
     return;
   }
     sctx->ret = GNUNET_SYSERR;
     return;
   }
+#ifndef WINDOWS
+  if (NULL != sctx->addrs)
+    for (i = 0; NULL != sctx->addrs[i]; i++)
+      if (AF_UNIX == sctx->addrs[i]->sa_family)
+        GNUNET_DISK_fix_permissions (((const struct sockaddr_un *)sctx->addrs[i])->sun_path,
+                                     sctx->match_uid,
+                                     sctx->match_gid);
+#endif
+
+
   if (0 == (sctx->options & GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN))
   {
     /* install a task that will kill the server
      * process if the scheduler ever gets a shutdown signal */
   if (0 == (sctx->options & GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN))
   {
     /* install a task that will kill the server
      * process if the scheduler ever gets a shutdown signal */
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
-                                  sctx->server);
+    sctx->shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
+                                                        &shutdown_task,
+                                                       sctx);
   }
   sctx->my_handlers = GNUNET_malloc (sizeof (defhandlers));
   memcpy (sctx->my_handlers, defhandlers, sizeof (defhandlers));
   i = 0;
   }
   sctx->my_handlers = GNUNET_malloc (sizeof (defhandlers));
   memcpy (sctx->my_handlers, defhandlers, sizeof (defhandlers));
   i = 0;
-  while ((sctx->my_handlers[i].callback != NULL))
+  while (NULL != sctx->my_handlers[i].callback)
     sctx->my_handlers[i++].callback_cls = sctx;
   GNUNET_SERVER_add_handlers (sctx->server, sctx->my_handlers);
     sctx->my_handlers[i++].callback_cls = sctx;
   GNUNET_SERVER_add_handlers (sctx->server, sctx->my_handlers);
-  if (sctx->ready_confirm_fd != -1)
+  if (-1 != sctx->ready_confirm_fd)
   {
     GNUNET_break (1 == WRITE (sctx->ready_confirm_fd, ".", 1));
     GNUNET_break (0 == CLOSE (sctx->ready_confirm_fd));
     sctx->ready_confirm_fd = -1;
     write_pid_file (sctx, getpid ());
   }
   {
     GNUNET_break (1 == WRITE (sctx->ready_confirm_fd, ".", 1));
     GNUNET_break (0 == CLOSE (sctx->ready_confirm_fd));
     sctx->ready_confirm_fd = -1;
     write_pid_file (sctx, getpid ());
   }
-  if (sctx->addrs != NULL)
+  if (NULL != sctx->addrs)
   {
     i = 0;
   {
     i = 0;
-    while (sctx->addrs[i] != NULL)
+    while (NULL != sctx->addrs[i])
     {
       LOG (GNUNET_ERROR_TYPE_INFO, _("Service `%s' runs at %s\n"),
     {
       LOG (GNUNET_ERROR_TYPE_INFO, _("Service `%s' runs at %s\n"),
-           sctx->serviceName, GNUNET_a2s (sctx->addrs[i], sctx->addrlens[i]));
+           sctx->service_name, GNUNET_a2s (sctx->addrs[i], sctx->addrlens[i]));
       i++;
     }
   }
       i++;
     }
   }
@@ -1355,6 +1212,9 @@ service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 
 /**
  * Detach from terminal.
 
 /**
  * Detach from terminal.
+ *
+ * @param sctx service context
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 static int
 detach_terminal (struct GNUNET_SERVICE_Context *sctx)
  */
 static int
 detach_terminal (struct GNUNET_SERVICE_Context *sctx)
@@ -1375,7 +1235,7 @@ detach_terminal (struct GNUNET_SERVICE_Context *sctx)
     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fork");
     return GNUNET_SYSERR;
   }
     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fork");
     return GNUNET_SYSERR;
   }
-  if (pid != 0)
+  if (0 != pid)
   {
     /* Parent */
     char c;
   {
     /* Parent */
     char c;
@@ -1419,7 +1279,7 @@ detach_terminal (struct GNUNET_SERVICE_Context *sctx)
   (void) CLOSE (nullfd);
   /* Detach from controlling terminal */
   pid = setsid ();
   (void) CLOSE (nullfd);
   /* Detach from controlling terminal */
   pid = setsid ();
-  if (pid == -1)
+  if (-1 == pid)
     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "setsid");
   sctx->ready_confirm_fd = filedes[1];
 #else
     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "setsid");
   sctx->ready_confirm_fd = filedes[1];
 #else
@@ -1433,6 +1293,9 @@ detach_terminal (struct GNUNET_SERVICE_Context *sctx)
 
 /**
  * Set user ID.
 
 /**
  * Set user ID.
+ *
+ * @param sctx service context
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 static int
 set_user_id (struct GNUNET_SERVICE_Context *sctx)
  */
 static int
 set_user_id (struct GNUNET_SERVICE_Context *sctx)
@@ -1446,7 +1309,7 @@ set_user_id (struct GNUNET_SERVICE_Context *sctx)
 
   errno = 0;
   pws = getpwnam (user);
 
   errno = 0;
   pws = getpwnam (user);
-  if (pws == NULL)
+  if (NULL == pws)
   {
     LOG (GNUNET_ERROR_TYPE_ERROR,
          _("Cannot obtain information about user `%s': %s\n"), user,
   {
     LOG (GNUNET_ERROR_TYPE_ERROR,
          _("Cannot obtain information about user `%s': %s\n"), user,
@@ -1477,13 +1340,15 @@ set_user_id (struct GNUNET_SERVICE_Context *sctx)
 
 /**
  * Delete the PID file that was created by our parent.
 
 /**
  * Delete the PID file that was created by our parent.
+ *
+ * @param sctx service context
  */
 static void
 pid_file_delete (struct GNUNET_SERVICE_Context *sctx)
 {
   char *pif = get_pid_file_name (sctx);
 
  */
 static void
 pid_file_delete (struct GNUNET_SERVICE_Context *sctx)
 {
   char *pif = get_pid_file_name (sctx);
 
-  if (pif == NULL)
+  if (NULL == pif)
     return;                     /* no PID file */
   if (0 != UNLINK (pif))
     LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", pif);
     return;                     /* no PID file */
   if (0 != UNLINK (pif))
     LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", pif);
@@ -1497,22 +1362,26 @@ pid_file_delete (struct GNUNET_SERVICE_Context *sctx)
  *
  * @param argc number of command line arguments
  * @param argv command line arguments
  *
  * @param argc number of command line arguments
  * @param argv command line arguments
- * @param serviceName our service name
- * @param opt service options
+ * @param service_name our service name
+ * @param options service options
  * @param task main task of the service
  * @param task main task of the service
- * @param task_cls closure for task
- * @return GNUNET_SYSERR on error, GNUNET_OK
+ * @param task_cls closure for @a task
+ * @return #GNUNET_SYSERR on error, #GNUNET_OK
  *         if we shutdown nicely
  */
 int
  *         if we shutdown nicely
  */
 int
-GNUNET_SERVICE_run (int argc, char *const *argv, const char *serviceName,
-                    enum GNUNET_SERVICE_Options opt, GNUNET_SERVICE_Main task,
+GNUNET_SERVICE_run (int argc, char *const *argv,
+                    const char *service_name,
+                    enum GNUNET_SERVICE_Options options,
+                    GNUNET_SERVICE_Main task,
                     void *task_cls)
 {
 #define HANDLE_ERROR do { GNUNET_break (0); goto shutdown; } while (0)
 
   int err;
                     void *task_cls)
 {
 #define HANDLE_ERROR do { GNUNET_break (0); goto shutdown; } while (0)
 
   int err;
+  int ret;
   char *cfg_fn;
   char *cfg_fn;
+  char *opt_cfg_fn;
   char *loglev;
   char *logfile;
   int do_daemonize;
   char *loglev;
   char *logfile;
   int do_daemonize;
@@ -1522,90 +1391,135 @@ GNUNET_SERVICE_run (int argc, char *const *argv, const char *serviceName,
   long long clock_offset;
   struct GNUNET_SERVICE_Context sctx;
   struct GNUNET_CONFIGURATION_Handle *cfg;
   long long clock_offset;
   struct GNUNET_SERVICE_Context sctx;
   struct GNUNET_CONFIGURATION_Handle *cfg;
+  const char *xdg;
 
   struct GNUNET_GETOPT_CommandLineOption service_options[] = {
 
   struct GNUNET_GETOPT_CommandLineOption service_options[] = {
-    GNUNET_GETOPT_OPTION_CFG_FILE (&cfg_fn),
+    GNUNET_GETOPT_OPTION_CFG_FILE (&opt_cfg_fn),
     {'d', "daemonize", NULL,
      gettext_noop ("do daemonize (detach from terminal)"), 0,
      GNUNET_GETOPT_set_one, &do_daemonize},
     {'d', "daemonize", NULL,
      gettext_noop ("do daemonize (detach from terminal)"), 0,
      GNUNET_GETOPT_set_one, &do_daemonize},
-    GNUNET_GETOPT_OPTION_HELP (serviceName),
+    GNUNET_GETOPT_OPTION_HELP (NULL),
     GNUNET_GETOPT_OPTION_LOGLEVEL (&loglev),
     GNUNET_GETOPT_OPTION_LOGFILE (&logfile),
     GNUNET_GETOPT_OPTION_LOGLEVEL (&loglev),
     GNUNET_GETOPT_OPTION_LOGFILE (&logfile),
-    GNUNET_GETOPT_OPTION_VERSION (PACKAGE_VERSION),
+    GNUNET_GETOPT_OPTION_VERSION (PACKAGE_VERSION " " VCS_VERSION),
     GNUNET_GETOPT_OPTION_END
   };
   err = 1;
   do_daemonize = 0;
   logfile = NULL;
   loglev = NULL;
     GNUNET_GETOPT_OPTION_END
   };
   err = 1;
   do_daemonize = 0;
   logfile = NULL;
   loglev = NULL;
-  cfg_fn = GNUNET_strdup (GNUNET_DEFAULT_USER_CONFIG_FILE);
+  opt_cfg_fn = NULL;
+  xdg = getenv ("XDG_CONFIG_HOME");
+  if (NULL != xdg)
+    GNUNET_asprintf (&cfg_fn,
+                     "%s%s%s",
+                     xdg,
+                     DIR_SEPARATOR_STR,
+                     "gnunet.conf");
+  else
+    cfg_fn = GNUNET_strdup (GNUNET_DEFAULT_USER_CONFIG_FILE);
   memset (&sctx, 0, sizeof (sctx));
   memset (&sctx, 0, sizeof (sctx));
-  sctx.options = opt;
+  sctx.options = options;
   sctx.ready_confirm_fd = -1;
   sctx.ret = GNUNET_OK;
   sctx.timeout = GNUNET_TIME_UNIT_FOREVER_REL;
   sctx.task = task;
   sctx.task_cls = task_cls;
   sctx.ready_confirm_fd = -1;
   sctx.ret = GNUNET_OK;
   sctx.timeout = GNUNET_TIME_UNIT_FOREVER_REL;
   sctx.task = task;
   sctx.task_cls = task_cls;
-  sctx.serviceName = serviceName;
+  sctx.service_name = service_name;
   sctx.cfg = cfg = GNUNET_CONFIGURATION_create ();
   sctx.cfg = cfg = GNUNET_CONFIGURATION_create ();
+
   /* setup subsystems */
   /* setup subsystems */
-  if (GNUNET_SYSERR ==
-      GNUNET_GETOPT_run (serviceName, service_options, argc, argv))
+  ret = GNUNET_GETOPT_run (service_name, service_options, argc, argv);
+  if (GNUNET_SYSERR == ret)
     goto shutdown;
     goto shutdown;
-  if (GNUNET_OK != GNUNET_log_setup (serviceName, loglev, logfile))
-    HANDLE_ERROR;
-  if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfg_fn))
+  if (GNUNET_NO == ret)
+  {
+    err = 0;
     goto shutdown;
     goto shutdown;
+  }
+  if (GNUNET_OK != GNUNET_log_setup (service_name, loglev, logfile))
+    HANDLE_ERROR;
+  if (NULL == opt_cfg_fn)
+    opt_cfg_fn = GNUNET_strdup (cfg_fn);
+  if (GNUNET_YES ==
+      GNUNET_DISK_file_test (opt_cfg_fn))
+    (void) GNUNET_CONFIGURATION_load (cfg, opt_cfg_fn);
+  else
+  {
+    (void) GNUNET_CONFIGURATION_load (cfg, NULL);
+    if (0 != strcmp (opt_cfg_fn, cfg_fn))
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                 _("Could not access configuration file `%s'\n"),
+                 opt_cfg_fn);
+  }
   if (GNUNET_OK != setup_service (&sctx))
     goto shutdown;
   if (GNUNET_OK != setup_service (&sctx))
     goto shutdown;
-  if ((do_daemonize == 1) && (GNUNET_OK != detach_terminal (&sctx)))
+  if ((1 == do_daemonize) && (GNUNET_OK != detach_terminal (&sctx)))
     HANDLE_ERROR;
   if (GNUNET_OK != set_user_id (&sctx))
     goto shutdown;
     HANDLE_ERROR;
   if (GNUNET_OK != set_user_id (&sctx))
     goto shutdown;
-#if DEBUG_SERVICE
   LOG (GNUNET_ERROR_TYPE_DEBUG,
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Service `%s' runs with configuration from `%s'\n", serviceName, cfg_fn);
-#endif
-  if ( (GNUNET_OK ==
-       GNUNET_CONFIGURATION_get_value_number (sctx.cfg, "TESTING", "SKEW_OFFSET",
-                                              &skew_offset)) &&
-       (GNUNET_OK ==
-       GNUNET_CONFIGURATION_get_value_number (sctx.cfg, "TESTING",
-                                              "SKEW_VARIANCE", &skew_variance)) )
+       "Service `%s' runs with configuration from `%s'\n",
+       service_name,
+       opt_cfg_fn);
+  if ((GNUNET_OK ==
+       GNUNET_CONFIGURATION_get_value_number (sctx.cfg, "TESTING",
+                                              "SKEW_OFFSET", &skew_offset)) &&
+      (GNUNET_OK ==
+       GNUNET_CONFIGURATION_get_value_number (sctx.cfg, "TESTING",
+                                              "SKEW_VARIANCE", &skew_variance)))
   {
     clock_offset = skew_offset - skew_variance;
     GNUNET_TIME_set_offset (clock_offset);
   {
     clock_offset = skew_offset - skew_variance;
     GNUNET_TIME_set_offset (clock_offset);
-#if DEBUG_SERVICE
     LOG (GNUNET_ERROR_TYPE_DEBUG, "Skewing clock by %dll ms\n", clock_offset);
     LOG (GNUNET_ERROR_TYPE_DEBUG, "Skewing clock by %dll ms\n", clock_offset);
-#endif
   }
   /* actually run service */
   err = 0;
   GNUNET_SCHEDULER_run (&service_task, &sctx);
   }
   /* actually run service */
   err = 0;
   GNUNET_SCHEDULER_run (&service_task, &sctx);
-
   /* shutdown */
   /* shutdown */
-  if ((do_daemonize == 1) && (sctx.server != NULL))
+  if ((1 == do_daemonize) && (NULL != sctx.server))
     pid_file_delete (&sctx);
   GNUNET_free_non_null (sctx.my_handlers);
 
 shutdown:
     pid_file_delete (&sctx);
   GNUNET_free_non_null (sctx.my_handlers);
 
 shutdown:
-  if (sctx.ready_confirm_fd != -1)
+  if (-1 != sctx.ready_confirm_fd)
   {
     if (1 != WRITE (sctx.ready_confirm_fd, err ? "I" : "S", 1))
       LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "write");
     GNUNET_break (0 == CLOSE (sctx.ready_confirm_fd));
   }
   {
     if (1 != WRITE (sctx.ready_confirm_fd, err ? "I" : "S", 1))
       LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "write");
     GNUNET_break (0 == CLOSE (sctx.ready_confirm_fd));
   }
+#if HAVE_MALLINFO
+  {
+    char *counter;
+
+    if ( (GNUNET_YES ==
+         GNUNET_CONFIGURATION_have_value (sctx.cfg, service_name,
+                                          "GAUGER_HEAP")) &&
+        (GNUNET_OK ==
+         GNUNET_CONFIGURATION_get_value_string (sctx.cfg, service_name,
+                                                "GAUGER_HEAP",
+                                                &counter)) )
+    {
+      struct mallinfo mi;
 
 
+      mi = mallinfo ();
+      GAUGER (service_name, counter, mi.usmblks, "blocks");
+      GNUNET_free (counter);
+    }
+  }
+#endif
+  GNUNET_SPEEDUP_stop_ ();
   GNUNET_CONFIGURATION_destroy (cfg);
   i = 0;
   GNUNET_CONFIGURATION_destroy (cfg);
   i = 0;
-  if (sctx.addrs != NULL)
-    while (sctx.addrs[i] != NULL)
+  if (NULL != sctx.addrs)
+    while (NULL != sctx.addrs[i])
       GNUNET_free (sctx.addrs[i++]);
   GNUNET_free_non_null (sctx.addrs);
   GNUNET_free_non_null (sctx.addrlens);
   GNUNET_free_non_null (logfile);
   GNUNET_free_non_null (loglev);
   GNUNET_free (cfg_fn);
       GNUNET_free (sctx.addrs[i++]);
   GNUNET_free_non_null (sctx.addrs);
   GNUNET_free_non_null (sctx.addrlens);
   GNUNET_free_non_null (logfile);
   GNUNET_free_non_null (loglev);
   GNUNET_free (cfg_fn);
+  GNUNET_free (opt_cfg_fn);
   GNUNET_free_non_null (sctx.v4_denied);
   GNUNET_free_non_null (sctx.v6_denied);
   GNUNET_free_non_null (sctx.v4_allowed);
   GNUNET_free_non_null (sctx.v4_denied);
   GNUNET_free_non_null (sctx.v6_denied);
   GNUNET_free_non_null (sctx.v4_allowed);
@@ -1619,23 +1533,26 @@ shutdown:
  * Run a service startup sequence within an existing
  * initialized system.
  *
  * Run a service startup sequence within an existing
  * initialized system.
  *
- * @param serviceName our service name
+ * @param service_name our service name
  * @param cfg configuration to use
  * @param cfg configuration to use
+ * @param options service options
  * @return NULL on error, service handle
  */
 struct GNUNET_SERVICE_Context *
  * @return NULL on error, service handle
  */
 struct GNUNET_SERVICE_Context *
-GNUNET_SERVICE_start (const char *serviceName,
-                      const struct GNUNET_CONFIGURATION_Handle *cfg)
+GNUNET_SERVICE_start (const char *service_name,
+                      const struct GNUNET_CONFIGURATION_Handle *cfg,
+                     enum GNUNET_SERVICE_Options options)
 {
   int i;
   struct GNUNET_SERVICE_Context *sctx;
 
 {
   int i;
   struct GNUNET_SERVICE_Context *sctx;
 
-  sctx = GNUNET_malloc (sizeof (struct GNUNET_SERVICE_Context));
+  sctx = GNUNET_new (struct GNUNET_SERVICE_Context);
   sctx->ready_confirm_fd = -1;  /* no daemonizing */
   sctx->ret = GNUNET_OK;
   sctx->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
   sctx->ready_confirm_fd = -1;  /* no daemonizing */
   sctx->ret = GNUNET_OK;
   sctx->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
-  sctx->serviceName = serviceName;
+  sctx->service_name = service_name;
   sctx->cfg = cfg;
   sctx->cfg = cfg;
+  sctx->options = options;
 
   /* setup subsystems */
   if (GNUNET_OK != setup_service (sctx))
 
   /* setup subsystems */
   if (GNUNET_OK != setup_service (sctx))
@@ -1643,7 +1560,7 @@ GNUNET_SERVICE_start (const char *serviceName,
     GNUNET_SERVICE_stop (sctx);
     return NULL;
   }
     GNUNET_SERVICE_stop (sctx);
     return NULL;
   }
-  if (sctx->lsocks != NULL)
+  if (NULL != sctx->lsocks)
     sctx->server =
         GNUNET_SERVER_create_with_sockets (&check_access, sctx, sctx->lsocks,
                                            sctx->timeout, sctx->require_found);
     sctx->server =
         GNUNET_SERVER_create_with_sockets (&check_access, sctx, sctx->lsocks,
                                            sctx->timeout, sctx->require_found);
@@ -1657,6 +1574,14 @@ GNUNET_SERVICE_start (const char *serviceName,
     GNUNET_SERVICE_stop (sctx);
     return NULL;
   }
     GNUNET_SERVICE_stop (sctx);
     return NULL;
   }
+#ifndef WINDOWS
+  if (NULL != sctx->addrs)
+    for (i = 0; NULL != sctx->addrs[i]; i++)
+      if (AF_UNIX == sctx->addrs[i]->sa_family)
+        GNUNET_DISK_fix_permissions (((const struct sockaddr_un *)sctx->addrs[i])->sun_path,
+                                     sctx->match_uid,
+                                     sctx->match_gid);
+#endif
   sctx->my_handlers = GNUNET_malloc (sizeof (defhandlers));
   memcpy (sctx->my_handlers, defhandlers, sizeof (defhandlers));
   i = 0;
   sctx->my_handlers = GNUNET_malloc (sizeof (defhandlers));
   memcpy (sctx->my_handlers, defhandlers, sizeof (defhandlers));
   i = 0;
@@ -1666,6 +1591,7 @@ GNUNET_SERVICE_start (const char *serviceName,
   return sctx;
 }
 
   return sctx;
 }
 
+
 /**
  * Obtain the server used by a service.  Note that the server must NOT
  * be destroyed by the caller.
 /**
  * Obtain the server used by a service.  Note that the server must NOT
  * be destroyed by the caller.
@@ -1690,13 +1616,38 @@ GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Context *sctx)
 {
   unsigned int i;
 
 {
   unsigned int i;
 
+#if HAVE_MALLINFO
+  {
+    char *counter;
+
+    if ( (GNUNET_YES ==
+         GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name,
+                                          "GAUGER_HEAP")) &&
+        (GNUNET_OK ==
+         GNUNET_CONFIGURATION_get_value_string (sctx->cfg, sctx->service_name,
+                                                "GAUGER_HEAP",
+                                                &counter)) )
+    {
+      struct mallinfo mi;
+
+      mi = mallinfo ();
+      GAUGER (sctx->service_name, counter, mi.usmblks, "blocks");
+      GNUNET_free (counter);
+    }
+  }
+#endif
+  if (GNUNET_SCHEDULER_NO_TASK != sctx->shutdown_task)
+  {
+    GNUNET_SCHEDULER_cancel (sctx->shutdown_task);
+    sctx->shutdown_task = GNUNET_SCHEDULER_NO_TASK;
+  }
   if (NULL != sctx->server)
     GNUNET_SERVER_destroy (sctx->server);
   GNUNET_free_non_null (sctx->my_handlers);
   if (NULL != sctx->server)
     GNUNET_SERVER_destroy (sctx->server);
   GNUNET_free_non_null (sctx->my_handlers);
-  if (sctx->addrs != NULL)
+  if (NULL != sctx->addrs)
   {
     i = 0;
   {
     i = 0;
-    while (sctx->addrs[i] != NULL)
+    while (NULL != sctx->addrs[i])
       GNUNET_free (sctx->addrs[i++]);
     GNUNET_free (sctx->addrs);
   }
       GNUNET_free (sctx->addrs[i++]);
     GNUNET_free (sctx->addrs);
   }