-doxygen
[oweals/gnunet.git] / src / util / service.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009, 2012 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file util/service.c
23  * @brief functions related to starting services
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_protocols.h"
29 #include "gnunet_directories.h"
30 #include "gnunet_resolver_service.h"
31
32 #if HAVE_MALLINFO
33 #include <malloc.h>
34 #include "gauger.h"
35 #endif
36
37
38 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
39
40 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
41
42 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
43
44
45 /* ******************* access control ******************** */
46
47 /**
48  * @brief IPV4 network in CIDR notation.
49  */
50 struct IPv4NetworkSet
51 {
52   /**
53    * IPv4 address.
54    */
55   struct in_addr network;
56
57   /**
58    * IPv4 netmask.
59    */
60   struct in_addr netmask;
61 };
62
63 /**
64
65  * @brief network in CIDR notation for IPV6.
66  */
67 struct IPv6NetworkSet
68 {
69   /**
70    * IPv6 address.
71    */
72   struct in6_addr network;
73
74   /**
75    * IPv6 netmask.
76    */
77   struct in6_addr netmask;
78 };
79
80
81 /**
82  * Start task that may speed up our system clock artificially
83  *
84  * @param cfg configuration to use
85  * @return GNUNET_OK on success, GNUNET_SYSERR if the speedup was not configured
86  */
87 int
88 GNUNET_SPEEDUP_start_ (const struct GNUNET_CONFIGURATION_Handle *cfg);
89
90 /**
91  * Stop tasks that modify clock behavior.
92  */
93 void
94 GNUNET_SPEEDUP_stop_ (void);
95
96
97 /**
98  * Parse a network specification. The argument specifies
99  * a list of networks. The format is
100  * <tt>[network/netmask;]*</tt> (no whitespace, must be terminated
101  * with a semicolon). The network must be given in dotted-decimal
102  * notation. The netmask can be given in CIDR notation (/16) or
103  * in dotted-decimal (/255.255.0.0).
104  *
105  * @param routeList a string specifying the forbidden networks
106  * @return the converted list, NULL if the synatx is flawed
107  */
108 static struct IPv4NetworkSet *
109 parse_ipv4_specification (const char *routeList)
110 {
111   unsigned int count;
112   unsigned int i;
113   unsigned int j;
114   unsigned int len;
115   int cnt;
116   unsigned int pos;
117   unsigned int temps[8];
118   int slash;
119   struct IPv4NetworkSet *result;
120
121   if (NULL == routeList)
122     return NULL;
123   len = strlen (routeList);
124   if (0 == len)
125     return NULL;
126   count = 0;
127   for (i = 0; i < len; i++)
128     if (routeList[i] == ';')
129       count++;
130   result = GNUNET_malloc (sizeof (struct IPv4NetworkSet) * (count + 1));
131   i = 0;
132   pos = 0;
133   while (i < count)
134   {
135     cnt =
136         SSCANF (&routeList[pos], "%u.%u.%u.%u/%u.%u.%u.%u;", &temps[0],
137                 &temps[1], &temps[2], &temps[3], &temps[4], &temps[5],
138                 &temps[6], &temps[7]);
139     if (8 == cnt)
140     {
141       for (j = 0; j < 8; j++)
142         if (temps[j] > 0xFF)
143         {
144           LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
145                &routeList[pos]);
146           GNUNET_free (result);
147           return NULL;
148         }
149       result[i].network.s_addr =
150           htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
151                  temps[3]);
152       result[i].netmask.s_addr =
153           htonl ((temps[4] << 24) + (temps[5] << 16) + (temps[6] << 8) +
154                  temps[7]);
155       while (routeList[pos] != ';')
156         pos++;
157       pos++;
158       i++;
159       continue;
160     }
161     /* try second notation */
162     cnt =
163         SSCANF (&routeList[pos], "%u.%u.%u.%u/%u;", &temps[0], &temps[1],
164                 &temps[2], &temps[3], &slash);
165     if (5 == cnt)
166     {
167       for (j = 0; j < 4; j++)
168         if (temps[j] > 0xFF)
169         {
170           LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
171                &routeList[pos]);
172           GNUNET_free (result);
173           return NULL;
174         }
175       result[i].network.s_addr =
176           htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
177                  temps[3]);
178       if ((slash <= 32) && (slash >= 0))
179       {
180         result[i].netmask.s_addr = 0;
181         while (slash > 0)
182         {
183           result[i].netmask.s_addr =
184               (result[i].netmask.s_addr >> 1) + 0x80000000;
185           slash--;
186         }
187         result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
188         while (';' != routeList[pos])
189           pos++;
190         pos++;
191         i++;
192         continue;
193       }
194       else
195       {
196         LOG (GNUNET_ERROR_TYPE_ERROR,
197              _("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."),
198              slash);
199         GNUNET_free (result);
200         return NULL;            /* error */
201       }
202     }
203     /* try third notation */
204     slash = 32;
205     cnt =
206         SSCANF (&routeList[pos], "%u.%u.%u.%u;", &temps[0], &temps[1],
207                 &temps[2], &temps[3]);
208     if (4 == cnt)
209     {
210       for (j = 0; j < 4; j++)
211         if (temps[j] > 0xFF)
212         {
213           LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
214                &routeList[pos]);
215           GNUNET_free (result);
216           return NULL;
217         }
218       result[i].network.s_addr =
219           htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
220                  temps[3]);
221       result[i].netmask.s_addr = 0;
222       while (slash > 0)
223       {
224         result[i].netmask.s_addr = (result[i].netmask.s_addr >> 1) + 0x80000000;
225         slash--;
226       }
227       result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
228       while (routeList[pos] != ';')
229         pos++;
230       pos++;
231       i++;
232       continue;
233     }
234     LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
235          &routeList[pos]);
236     GNUNET_free (result);
237     return NULL;                /* error */
238   }
239   if (pos < strlen (routeList))
240   {
241     LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"),
242          &routeList[pos]);
243     GNUNET_free (result);
244     return NULL;                /* oops */
245   }
246   return result;                /* ok */
247 }
248
249
250 /**
251  * Parse a network specification. The argument specifies
252  * a list of networks. The format is
253  * <tt>[network/netmask;]*</tt> (no whitespace, must be terminated
254  * with a semicolon). The network must be given in colon-hex
255  * notation.  The netmask must be given in CIDR notation (/16) or
256  * can be omitted to specify a single host.
257  *
258  * @param routeListX a string specifying the forbidden networks
259  * @return the converted list, NULL if the synatx is flawed
260  */
261 static struct IPv6NetworkSet *
262 parse_ipv6_specification (const char *routeListX)
263 {
264   unsigned int count;
265   unsigned int i;
266   unsigned int len;
267   unsigned int pos;
268   int start;
269   int slash;
270   int ret;
271   char *routeList;
272   struct IPv6NetworkSet *result;
273   unsigned int bits;
274   unsigned int off;
275   int save;
276
277   if (NULL == routeListX)
278     return NULL;
279   len = strlen (routeListX);
280   if (0 == len)
281     return NULL;
282   routeList = GNUNET_strdup (routeListX);
283   count = 0;
284   for (i = 0; i < len; i++)
285     if (';' == routeList[i])
286       count++;
287   if (';' != routeList[len - 1])
288   {
289     LOG (GNUNET_ERROR_TYPE_ERROR,
290          _("Invalid network notation (does not end with ';': `%s')\n"),
291          routeList);
292     GNUNET_free (routeList);
293     return NULL;
294   }
295
296   result = GNUNET_malloc (sizeof (struct IPv6NetworkSet) * (count + 1));
297   i = 0;
298   pos = 0;
299   while (i < count)
300   {
301     start = pos;
302     while (';' != routeList[pos])
303       pos++;
304     slash = pos;
305     while ((slash >= start) && (routeList[slash] != '/'))
306       slash--;
307     if (slash < start)
308     {
309       memset (&result[i].netmask, 0xFF, sizeof (struct in6_addr));
310       slash = pos;
311     }
312     else
313     {
314       routeList[pos] = '\0';
315       ret = inet_pton (AF_INET6, &routeList[slash + 1], &result[i].netmask);
316       if (ret <= 0)
317       {
318         save = errno;
319         if ((1 != SSCANF (&routeList[slash + 1], "%u", &bits)) || (bits >= 128))
320         {
321           if (0 == ret)
322             LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong format `%s' for netmask\n"),
323                  &routeList[slash + 1]);
324           else
325           {
326             errno = save;
327             LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "inet_pton");
328           }
329           GNUNET_free (result);
330           GNUNET_free (routeList);
331           return NULL;
332         }
333         off = 0;
334         while (bits > 8)
335         {
336           result[i].netmask.s6_addr[off++] = 0xFF;
337           bits -= 8;
338         }
339         while (bits > 0)
340         {
341           result[i].netmask.s6_addr[off] =
342               (result[i].netmask.s6_addr[off] >> 1) + 0x80;
343           bits--;
344         }
345       }
346     }
347     routeList[slash] = '\0';
348     ret = inet_pton (AF_INET6, &routeList[start], &result[i].network);
349     if (ret <= 0)
350     {
351       if (0 == ret)
352         LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong format `%s' for network\n"),
353              &routeList[slash + 1]);
354       else
355         LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "inet_pton");
356       GNUNET_free (result);
357       GNUNET_free (routeList);
358       return NULL;
359     }
360     pos++;
361     i++;
362   }
363   GNUNET_free (routeList);
364   return result;
365 }
366
367
368 /**
369  * Check if the given IP address is in the list of IP addresses.
370  *
371  * @param list a list of networks
372  * @param add the IP to check (in network byte order)
373  * @return GNUNET_NO if the IP is not in the list, GNUNET_YES if it it is
374  */
375 static int
376 check_ipv4_listed (const struct IPv4NetworkSet *list, const struct in_addr *add)
377 {
378   unsigned int i;
379
380   if (NULL == list)
381     return GNUNET_NO;
382   i = 0;
383   while ((list[i].network.s_addr != 0) || (list[i].netmask.s_addr != 0))
384   {
385     if ((add->s_addr & list[i].netmask.s_addr) ==
386         (list[i].network.s_addr & list[i].netmask.s_addr))
387       return GNUNET_YES;
388     i++;
389   }
390   return GNUNET_NO;
391 }
392
393
394 /**
395  * Check if the given IP address is in the list of IP addresses.
396  *
397  * @param list a list of networks
398  * @param ip the IP to check (in network byte order)
399  * @return GNUNET_NO if the IP is not in the list, GNUNET_YES if it it is
400  */
401 static int
402 check_ipv6_listed (const struct IPv6NetworkSet *list, const struct in6_addr *ip)
403 {
404   unsigned int i;
405   unsigned int j;
406   struct in6_addr zero;
407
408   if (NULL == list)
409     return GNUNET_NO;
410   memset (&zero, 0, sizeof (struct in6_addr));
411   i = 0;
412 NEXT:
413   while (0 != memcmp (&zero, &list[i].network, sizeof (struct in6_addr)))
414   {
415     for (j = 0; j < sizeof (struct in6_addr) / sizeof (int); j++)
416       if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) !=
417           (((int *) &list[i].network)[j] & ((int *) &list[i].netmask)[j]))
418       {
419         i++;
420         goto NEXT;
421       }
422     return GNUNET_YES;
423   }
424   return GNUNET_NO;
425 }
426
427
428 /* ****************** service struct ****************** */
429
430
431 /**
432  * Context for "service_task".
433  */
434 struct GNUNET_SERVICE_Context
435 {
436   /**
437    * Our configuration.
438    */
439   const struct GNUNET_CONFIGURATION_Handle *cfg;
440
441   /**
442    * Handle for the server.
443    */
444   struct GNUNET_SERVER_Handle *server;
445
446   /**
447    * NULL-terminated array of addresses to bind to, NULL if we got pre-bound
448    * listen sockets.
449    */
450   struct sockaddr **addrs;
451
452   /**
453    * Name of our service.
454    */
455   const char *service_name;
456
457   /**
458    * Main service-specific task to run.
459    */
460   GNUNET_SERVICE_Main task;
461
462   /**
463    * Closure for task.
464    */
465   void *task_cls;
466
467   /**
468    * IPv4 addresses that are not allowed to connect.
469    */
470   struct IPv4NetworkSet *v4_denied;
471
472   /**
473    * IPv6 addresses that are not allowed to connect.
474    */
475   struct IPv6NetworkSet *v6_denied;
476
477   /**
478    * IPv4 addresses that are allowed to connect (if not
479    * set, all are allowed).
480    */
481   struct IPv4NetworkSet *v4_allowed;
482
483   /**
484    * IPv6 addresses that are allowed to connect (if not
485    * set, all are allowed).
486    */
487   struct IPv6NetworkSet *v6_allowed;
488
489   /**
490    * My (default) message handlers.  Adjusted copy
491    * of "defhandlers".
492    */
493   struct GNUNET_SERVER_MessageHandler *my_handlers;
494
495   /**
496    * Array of the lengths of the entries in addrs.
497    */
498   socklen_t *addrlens;
499
500   /**
501    * NULL-terminated array of listen sockets we should take over.
502    */
503   struct GNUNET_NETWORK_Handle **lsocks;
504
505   /**
506    * Task ID of the shutdown task.
507    */
508   GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
509
510   /**
511    * Idle timeout for server.
512    */
513   struct GNUNET_TIME_Relative timeout;
514
515   /**
516    * Overall success/failure of the service start.
517    */
518   int ret;
519
520   /**
521    * If we are daemonizing, this FD is set to the
522    * pipe to the parent.  Send '.' if we started
523    * ok, '!' if not.  -1 if we are not daemonizing.
524    */
525   int ready_confirm_fd;
526
527   /**
528    * Do we close connections if we receive messages
529    * for which we have no handler?
530    */
531   int require_found;
532
533   /**
534    * Do we require a matching UID for UNIX domain socket connections?
535    * #GNUNET_NO means that the UID does not have to match (however,
536    * @e match_gid may still impose other access control checks).
537    */
538   int match_uid;
539
540   /**
541    * Do we require a matching GID for UNIX domain socket connections?
542    * Ignored if @e match_uid is #GNUNET_YES.  Note that this is about
543    * checking that the client's UID is in our group OR that the
544    * client's GID is our GID.  If both "match_gid" and @e match_uid are
545    * #GNUNET_NO, all users on the local system have access.
546    */
547   int match_gid;
548
549   /**
550    * Our options.
551    */
552   enum GNUNET_SERVICE_Options options;
553
554 };
555
556
557 /* ****************** message handlers ****************** */
558
559 /**
560  * Send a 'TEST' message back to the client.
561  *
562  * @param cls the 'struct GNUNET_SERVER_Client' to send TEST to
563  * @param size number of bytes available in 'buf'
564  * @param buf where to copy the message
565  * @return number of bytes written to 'buf'
566  */
567 static size_t
568 write_test (void *cls, size_t size, void *buf)
569 {
570   struct GNUNET_SERVER_Client *client = cls;
571   struct GNUNET_MessageHeader *msg;
572
573   if (size < sizeof (struct GNUNET_MessageHeader))
574   {
575     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
576     return 0;                   /* client disconnected */
577   }
578   msg = (struct GNUNET_MessageHeader *) buf;
579   msg->type = htons (GNUNET_MESSAGE_TYPE_TEST);
580   msg->size = htons (sizeof (struct GNUNET_MessageHeader));
581   GNUNET_SERVER_receive_done (client, GNUNET_OK);
582   return sizeof (struct GNUNET_MessageHeader);
583 }
584
585
586 /**
587  * Handler for TEST message.
588  *
589  * @param cls closure (refers to service)
590  * @param client identification of the client
591  * @param message the actual message
592  */
593 static void
594 handle_test (void *cls, struct GNUNET_SERVER_Client *client,
595              const struct GNUNET_MessageHeader *message)
596 {
597   /* simply bounce message back to acknowledge */
598   if (NULL ==
599       GNUNET_SERVER_notify_transmit_ready (client,
600                                            sizeof (struct GNUNET_MessageHeader),
601                                            GNUNET_TIME_UNIT_FOREVER_REL,
602                                            &write_test, client))
603     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
604 }
605
606
607 /**
608  * Default handlers for all services.  Will be copied and the
609  * "callback_cls" fields will be replaced with the specific service
610  * struct.
611  */
612 static const struct GNUNET_SERVER_MessageHandler defhandlers[] = {
613   {&handle_test, NULL, GNUNET_MESSAGE_TYPE_TEST,
614    sizeof (struct GNUNET_MessageHeader)},
615   {NULL, NULL, 0, 0}
616 };
617
618
619 /* ****************** service core routines ************** */
620
621
622 /**
623  * Check if access to the service is allowed from the given address.
624  *
625  * @param cls closure
626  * @param uc credentials, if available, otherwise NULL
627  * @param addr address
628  * @param addrlen length of address
629  * @return #GNUNET_YES to allow, #GNUNET_NO to deny, #GNUNET_SYSERR
630  *   for unknown address family (will be denied).
631  */
632 static int
633 check_access (void *cls, const struct GNUNET_CONNECTION_Credentials *uc,
634               const struct sockaddr *addr, socklen_t addrlen)
635 {
636   struct GNUNET_SERVICE_Context *sctx = cls;
637   const struct sockaddr_in *i4;
638   const struct sockaddr_in6 *i6;
639   int ret;
640
641   switch (addr->sa_family)
642   {
643   case AF_INET:
644     GNUNET_assert (addrlen == sizeof (struct sockaddr_in));
645     i4 = (const struct sockaddr_in *) addr;
646     ret = ((NULL == sctx->v4_allowed) ||
647            (check_ipv4_listed (sctx->v4_allowed, &i4->sin_addr))) &&
648         ((NULL == sctx->v4_denied) ||
649          (!check_ipv4_listed (sctx->v4_denied, &i4->sin_addr)));
650     break;
651   case AF_INET6:
652     GNUNET_assert (addrlen == sizeof (struct sockaddr_in6));
653     i6 = (const struct sockaddr_in6 *) addr;
654     ret = ((NULL == sctx->v6_allowed) ||
655            (check_ipv6_listed (sctx->v6_allowed, &i6->sin6_addr))) &&
656         ((NULL == sctx->v6_denied) ||
657          (!check_ipv6_listed (sctx->v6_denied, &i6->sin6_addr)));
658     break;
659 #ifndef WINDOWS
660   case AF_UNIX:
661     ret = GNUNET_OK;            /* controlled using file-system ACL now */
662     break;
663 #endif
664   default:
665     LOG (GNUNET_ERROR_TYPE_WARNING, _("Unknown address family %d\n"),
666          addr->sa_family);
667     return GNUNET_SYSERR;
668   }
669   if (GNUNET_OK != ret)
670   {
671     LOG (GNUNET_ERROR_TYPE_WARNING,
672          _("Access from `%s' denied to service `%s'\n"),
673          GNUNET_a2s (addr, addrlen),
674          sctx->service_name);
675   }
676   return ret;
677 }
678
679
680 /**
681  * Get the name of the file where we will
682  * write the PID of the service.
683  *
684  * @param sctx service context
685  * @return name of the file for the process ID
686  */
687 static char *
688 get_pid_file_name (struct GNUNET_SERVICE_Context *sctx)
689 {
690   char *pif;
691
692   if (GNUNET_OK !=
693       GNUNET_CONFIGURATION_get_value_filename (sctx->cfg, sctx->service_name,
694                                                "PIDFILE", &pif))
695     return NULL;
696   return pif;
697 }
698
699
700 /**
701  * Parse an IPv4 access control list.
702  *
703  * @param ret location where to write the ACL (set)
704  * @param sctx service context to use to get the configuration
705  * @param option name of the ACL option to parse
706  * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including
707  *         no ACL configured)
708  */
709 static int
710 process_acl4 (struct IPv4NetworkSet **ret, struct GNUNET_SERVICE_Context *sctx,
711               const char *option)
712 {
713   char *opt;
714
715   if (!GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name, option))
716   {
717     *ret = NULL;
718     return GNUNET_OK;
719   }
720   GNUNET_break (GNUNET_OK ==
721                 GNUNET_CONFIGURATION_get_value_string (sctx->cfg,
722                                                        sctx->service_name,
723                                                        option, &opt));
724   if (NULL == (*ret = parse_ipv4_specification (opt)))
725   {
726     LOG (GNUNET_ERROR_TYPE_WARNING,
727          _("Could not parse IPv4 network specification `%s' for `%s:%s'\n"),
728          opt, sctx->service_name, option);
729     GNUNET_free (opt);
730     return GNUNET_SYSERR;
731   }
732   GNUNET_free (opt);
733   return GNUNET_OK;
734 }
735
736
737 /**
738  * Parse an IPv6 access control list.
739  *
740  * @param ret location where to write the ACL (set)
741  * @param sctx service context to use to get the configuration
742  * @param option name of the ACL option to parse
743  * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including
744  *         no ACL configured)
745  */
746 static int
747 process_acl6 (struct IPv6NetworkSet **ret, struct GNUNET_SERVICE_Context *sctx,
748               const char *option)
749 {
750   char *opt;
751
752   if (!GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name, option))
753   {
754     *ret = NULL;
755     return GNUNET_OK;
756   }
757   GNUNET_break (GNUNET_OK ==
758                 GNUNET_CONFIGURATION_get_value_string (sctx->cfg,
759                                                        sctx->service_name,
760                                                        option, &opt));
761   if (NULL == (*ret = parse_ipv6_specification (opt)))
762   {
763     LOG (GNUNET_ERROR_TYPE_WARNING,
764          _("Could not parse IPv6 network specification `%s' for `%s:%s'\n"),
765          opt, sctx->service_name, option);
766     GNUNET_free (opt);
767     return GNUNET_SYSERR;
768   }
769   GNUNET_free (opt);
770   return GNUNET_OK;
771 }
772
773
774 /**
775  * Add the given UNIX domain path as an address to the
776  * list (as the first entry).
777  *
778  * @param saddrs array to update
779  * @param saddrlens where to store the address length
780  * @param unixpath path to add
781  */
782 static void
783 add_unixpath (struct sockaddr **saddrs, socklen_t * saddrlens,
784               const char *unixpath)
785 {
786 #ifdef AF_UNIX
787   struct sockaddr_un *un;
788
789   un = GNUNET_new (struct sockaddr_un);
790   un->sun_family = AF_UNIX;
791   strncpy (un->sun_path, unixpath, sizeof (un->sun_path) - 1);
792 #if HAVE_SOCKADDR_IN_SIN_LEN
793   un->sun_len = (u_char) sizeof (struct sockaddr_un);
794 #endif
795   *saddrs = (struct sockaddr *) un;
796   *saddrlens = sizeof (struct sockaddr_un);
797 #else
798   /* this function should never be called
799    * unless AF_UNIX is defined! */
800   GNUNET_assert (0);
801 #endif
802 }
803
804
805 /**
806  * Get the list of addresses that a server for the given service
807  * should bind to.
808  *
809  * @param service_name name of the service
810  * @param cfg configuration (which specifies the addresses)
811  * @param addrs set (call by reference) to an array of pointers to the
812  *              addresses the server should bind to and listen on; the
813  *              array will be NULL-terminated (on success)
814  * @param addr_lens set (call by reference) to an array of the lengths
815  *              of the respective 'struct sockaddr' struct in the 'addrs'
816  *              array (on success)
817  * @return number of addresses found on success,
818  *              #GNUNET_SYSERR if the configuration
819  *              did not specify reasonable finding information or
820  *              if it specified a hostname that could not be resolved;
821  *              #GNUNET_NO if the number of addresses configured is
822  *              zero (in this case, `*addrs` and `*addr_lens` will be
823  *              set to NULL).
824  */
825 int
826 GNUNET_SERVICE_get_server_addresses (const char *service_name,
827                                      const struct GNUNET_CONFIGURATION_Handle
828                                      *cfg, struct sockaddr ***addrs,
829                                      socklen_t ** addr_lens)
830 {
831   int disablev6;
832   struct GNUNET_NETWORK_Handle *desc;
833   unsigned long long port;
834   char *unixpath;
835   struct addrinfo hints;
836   struct addrinfo *res;
837   struct addrinfo *pos;
838   struct addrinfo *next;
839   unsigned int i;
840   int resi;
841   int ret;
842   struct sockaddr **saddrs;
843   socklen_t *saddrlens;
844   char *hostname;
845
846   *addrs = NULL;
847   *addr_lens = NULL;
848   desc = NULL;
849   if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "DISABLEV6"))
850   {
851     if (GNUNET_SYSERR ==
852         (disablev6 =
853          GNUNET_CONFIGURATION_get_value_yesno (cfg, service_name, "DISABLEV6")))
854       return GNUNET_SYSERR;
855   }
856   else
857     disablev6 = GNUNET_NO;
858
859   if (!disablev6)
860   {
861     /* probe IPv6 support */
862     desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
863     if (NULL == desc)
864     {
865       if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
866           (EACCES == errno))
867       {
868         LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
869         return GNUNET_SYSERR;
870       }
871       LOG (GNUNET_ERROR_TYPE_INFO,
872            _
873            ("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
874            service_name, STRERROR (errno));
875       disablev6 = GNUNET_YES;
876     }
877     else
878     {
879       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
880       desc = NULL;
881     }
882   }
883
884   port = 0;
885   if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT"))
886   {
887     if (GNUNET_OK !=
888         GNUNET_CONFIGURATION_get_value_number (cfg, service_name,
889                                                "PORT", &port))
890     {
891       LOG (GNUNET_ERROR_TYPE_ERROR,
892            _("Require valid port number for service `%s' in configuration!\n"),
893            service_name);
894     }
895     if (port > 65535)
896     {
897       LOG (GNUNET_ERROR_TYPE_ERROR,
898            _("Require valid port number for service `%s' in configuration!\n"),
899            service_name);
900       return GNUNET_SYSERR;
901     }
902   }
903
904   if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "BINDTO"))
905   {
906     GNUNET_break (GNUNET_OK ==
907                   GNUNET_CONFIGURATION_get_value_string (cfg, service_name,
908                                                          "BINDTO", &hostname));
909   }
910   else
911     hostname = NULL;
912
913   unixpath = NULL;
914 #ifdef AF_UNIX
915   if ((GNUNET_YES ==
916        GNUNET_CONFIGURATION_have_value (cfg, service_name, "UNIXPATH")) &&
917       (GNUNET_OK ==
918        GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH",
919                                               &unixpath)) &&
920       (0 < strlen (unixpath)))
921   {
922     /* probe UNIX support */
923     struct sockaddr_un s_un;
924
925     if (strlen (unixpath) >= sizeof (s_un.sun_path))
926     {
927       LOG (GNUNET_ERROR_TYPE_WARNING,
928            _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath,
929            (unsigned long long) sizeof (s_un.sun_path));
930       unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
931       LOG (GNUNET_ERROR_TYPE_INFO,
932            _("Using `%s' instead\n"), unixpath);
933     }
934     if (GNUNET_OK !=
935         GNUNET_DISK_directory_create_for_file (unixpath))
936       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
937                                 "mkdir",
938                                 unixpath);
939   }
940   if (NULL != unixpath)
941   {
942     desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
943     if (NULL == desc)
944     {
945       if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
946           (EACCES == errno))
947       {
948         LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
949         GNUNET_free_non_null (hostname);
950         GNUNET_free (unixpath);
951         return GNUNET_SYSERR;
952       }
953       LOG (GNUNET_ERROR_TYPE_INFO,
954            _("Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
955            service_name, STRERROR (errno));
956       GNUNET_free (unixpath);
957       unixpath = NULL;
958     }
959     else
960     {
961       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
962       desc = NULL;
963     }
964   }
965 #endif
966
967   if ((0 == port) && (NULL == unixpath))
968   {
969     LOG (GNUNET_ERROR_TYPE_ERROR,
970          _("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
971          service_name);
972     GNUNET_free_non_null (hostname);
973     return GNUNET_SYSERR;
974   }
975   if (0 == port)
976   {
977     saddrs = GNUNET_malloc (2 * sizeof (struct sockaddr *));
978     saddrlens = GNUNET_malloc (2 * sizeof (socklen_t));
979     add_unixpath (saddrs, saddrlens, unixpath);
980     GNUNET_free_non_null (unixpath);
981     GNUNET_free_non_null (hostname);
982     *addrs = saddrs;
983     *addr_lens = saddrlens;
984     return 1;
985   }
986
987   if (NULL != hostname)
988   {
989     LOG (GNUNET_ERROR_TYPE_DEBUG,
990          "Resolving `%s' since that is where `%s' will bind to.\n", hostname,
991          service_name);
992     memset (&hints, 0, sizeof (struct addrinfo));
993     if (disablev6)
994       hints.ai_family = AF_INET;
995     hints.ai_protocol = IPPROTO_TCP;
996     if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
997         (res == NULL))
998     {
999       LOG (GNUNET_ERROR_TYPE_ERROR, _("Failed to resolve `%s': %s\n"), hostname,
1000            gai_strerror (ret));
1001       GNUNET_free (hostname);
1002       GNUNET_free_non_null (unixpath);
1003       return GNUNET_SYSERR;
1004     }
1005     next = res;
1006     i = 0;
1007     while (NULL != (pos = next))
1008     {
1009       next = pos->ai_next;
1010       if ((disablev6) && (pos->ai_family == AF_INET6))
1011         continue;
1012       i++;
1013     }
1014     if (0 == i)
1015     {
1016       LOG (GNUNET_ERROR_TYPE_ERROR, _("Failed to find %saddress for `%s'.\n"),
1017            disablev6 ? "IPv4 " : "", hostname);
1018       freeaddrinfo (res);
1019       GNUNET_free (hostname);
1020       GNUNET_free_non_null (unixpath);
1021       return GNUNET_SYSERR;
1022     }
1023     resi = i;
1024     if (NULL != unixpath)
1025       resi++;
1026     saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
1027     saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
1028     i = 0;
1029     if (NULL != unixpath)
1030     {
1031       add_unixpath (saddrs, saddrlens, unixpath);
1032       i++;
1033     }
1034     next = res;
1035     while (NULL != (pos = next))
1036     {
1037       next = pos->ai_next;
1038       if ((disablev6) && (AF_INET6 == pos->ai_family))
1039         continue;
1040       if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
1041         continue;               /* not TCP */
1042       if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
1043         continue;               /* huh? */
1044       LOG (GNUNET_ERROR_TYPE_DEBUG, "Service `%s' will bind to `%s'\n",
1045            service_name, GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
1046       if (AF_INET == pos->ai_family)
1047       {
1048         GNUNET_assert (sizeof (struct sockaddr_in) == pos->ai_addrlen);
1049         saddrlens[i] = pos->ai_addrlen;
1050         saddrs[i] = GNUNET_malloc (saddrlens[i]);
1051         memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1052         ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1053       }
1054       else
1055       {
1056         GNUNET_assert (AF_INET6 == pos->ai_family);
1057         GNUNET_assert (sizeof (struct sockaddr_in6) == pos->ai_addrlen);
1058         saddrlens[i] = pos->ai_addrlen;
1059         saddrs[i] = GNUNET_malloc (saddrlens[i]);
1060         memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1061         ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1062       }
1063       i++;
1064     }
1065     GNUNET_free (hostname);
1066     freeaddrinfo (res);
1067     resi = i;
1068   }
1069   else
1070   {
1071     /* will bind against everything, just set port */
1072     if (disablev6)
1073     {
1074       /* V4-only */
1075       resi = 1;
1076       if (NULL != unixpath)
1077         resi++;
1078       i = 0;
1079       saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
1080       saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
1081       if (NULL != unixpath)
1082       {
1083         add_unixpath (saddrs, saddrlens, unixpath);
1084         i++;
1085       }
1086       saddrlens[i] = sizeof (struct sockaddr_in);
1087       saddrs[i] = GNUNET_malloc (saddrlens[i]);
1088 #if HAVE_SOCKADDR_IN_SIN_LEN
1089       ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
1090 #endif
1091       ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1092       ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1093     }
1094     else
1095     {
1096       /* dual stack */
1097       resi = 2;
1098       if (NULL != unixpath)
1099         resi++;
1100       saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
1101       saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
1102       i = 0;
1103       if (NULL != unixpath)
1104       {
1105         add_unixpath (saddrs, saddrlens, unixpath);
1106         i++;
1107       }
1108       saddrlens[i] = sizeof (struct sockaddr_in6);
1109       saddrs[i] = GNUNET_malloc (saddrlens[i]);
1110 #if HAVE_SOCKADDR_IN_SIN_LEN
1111       ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
1112 #endif
1113       ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
1114       ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1115       i++;
1116       saddrlens[i] = sizeof (struct sockaddr_in);
1117       saddrs[i] = GNUNET_malloc (saddrlens[i]);
1118 #if HAVE_SOCKADDR_IN_SIN_LEN
1119       ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
1120 #endif
1121       ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1122       ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1123     }
1124   }
1125   GNUNET_free_non_null (unixpath);
1126   *addrs = saddrs;
1127   *addr_lens = saddrlens;
1128   return resi;
1129 }
1130
1131
1132 #ifdef MINGW
1133 /**
1134  * Read listen sockets from the parent process (ARM).
1135  *
1136  * @param sctx service context to initialize
1137  * @return #GNUNET_YES if ok, #GNUNET_NO if not ok (must bind yourself),
1138  * and #GNUNET_SYSERR on error.
1139  */
1140 static int
1141 receive_sockets_from_parent (struct GNUNET_SERVICE_Context *sctx)
1142 {
1143   const char *env_buf;
1144   int fail;
1145   uint64_t count;
1146   uint64_t i;
1147   HANDLE lsocks_pipe;
1148
1149   env_buf = getenv ("GNUNET_OS_READ_LSOCKS");
1150   if ((NULL == env_buf) || (strlen (env_buf) <= 0))
1151     return GNUNET_NO;
1152   /* Using W32 API directly here, because this pipe will
1153    * never be used outside of this function, and it's just too much of a bother
1154    * to create a GNUnet API that boxes a HANDLE (the way it is done with socks)
1155    */
1156   lsocks_pipe = (HANDLE) strtoul (env_buf, NULL, 10);
1157   if ( (0 == lsocks_pipe) || (INVALID_HANDLE_VALUE == lsocks_pipe))
1158     return GNUNET_NO;
1159   fail = 1;
1160   do
1161   {
1162     int ret;
1163     int fail2;
1164     DWORD rd;
1165
1166     ret = ReadFile (lsocks_pipe, &count, sizeof (count), &rd, NULL);
1167     if ((0 == ret) || (sizeof (count) != rd) || (0 == count))
1168       break;
1169     sctx->lsocks =
1170         GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle *) * (count + 1));
1171
1172     fail2 = 1;
1173     for (i = 0; i < count; i++)
1174     {
1175       WSAPROTOCOL_INFOA pi;
1176       uint64_t size;
1177       SOCKET s;
1178
1179       ret = ReadFile (lsocks_pipe, &size, sizeof (size), &rd, NULL);
1180       if ( (0 == ret) || (sizeof (size) != rd) || (sizeof (pi) != size) )
1181         break;
1182       ret = ReadFile (lsocks_pipe, &pi, sizeof (pi), &rd, NULL);
1183       if ( (0 == ret) || (sizeof (pi) != rd))
1184         break;
1185       s = WSASocketA (pi.iAddressFamily, pi.iSocketType, pi.iProtocol, &pi, 0, WSA_FLAG_OVERLAPPED);
1186       sctx->lsocks[i] = GNUNET_NETWORK_socket_box_native (s);
1187       if (NULL == sctx->lsocks[i])
1188         break;
1189       else if (i == count - 1)
1190         fail2 = 0;
1191     }
1192     if (fail2)
1193       break;
1194     sctx->lsocks[count] = NULL;
1195     fail = 0;
1196   }
1197   while (fail);
1198
1199   CloseHandle (lsocks_pipe);
1200
1201   if (fail)
1202   {
1203     LOG (GNUNET_ERROR_TYPE_ERROR,
1204          _("Could not access a pre-bound socket, will try to bind myself\n"));
1205     for (i = 0; (i < count) && (NULL != sctx->lsocks[i]); i++)
1206       GNUNET_break (0 == GNUNET_NETWORK_socket_close (sctx->lsocks[i]));
1207     GNUNET_free_non_null (sctx->lsocks);
1208     sctx->lsocks = NULL;
1209     return GNUNET_NO;
1210   }
1211   return GNUNET_YES;
1212 }
1213 #endif
1214
1215
1216 /**
1217  * Setup addr, addrlen, idle_timeout
1218  * based on configuration!
1219  *
1220  * Configuration may specify:
1221  * - PORT (where to bind to for TCP)
1222  * - UNIXPATH (where to bind to for UNIX domain sockets)
1223  * - TIMEOUT (after how many ms does an inactive service timeout);
1224  * - DISABLEV6 (disable support for IPv6, otherwise we use dual-stack)
1225  * - BINDTO (hostname or IP address to bind to, otherwise we take everything)
1226  * - ACCEPT_FROM  (only allow connections from specified IPv4 subnets)
1227  * - ACCEPT_FROM6 (only allow connections from specified IPv6 subnets)
1228  * - REJECT_FROM  (disallow allow connections from specified IPv4 subnets)
1229  * - REJECT_FROM6 (disallow allow connections from specified IPv6 subnets)
1230  *
1231  * @param sctx service context to initialize
1232  * @return #GNUNET_OK if configuration succeeded
1233  */
1234 static int
1235 setup_service (struct GNUNET_SERVICE_Context *sctx)
1236 {
1237   struct GNUNET_TIME_Relative idleout;
1238   int tolerant;
1239
1240 #ifndef MINGW
1241   const char *nfds;
1242   unsigned int cnt;
1243   int flags;
1244 #endif
1245
1246   if (GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name, "TIMEOUT"))
1247   {
1248     if (GNUNET_OK !=
1249         GNUNET_CONFIGURATION_get_value_time (sctx->cfg, sctx->service_name,
1250                                              "TIMEOUT", &idleout))
1251     {
1252       LOG (GNUNET_ERROR_TYPE_ERROR,
1253            _("Specified value for `%s' of service `%s' is invalid\n"),
1254            "TIMEOUT", sctx->service_name);
1255       return GNUNET_SYSERR;
1256     }
1257     sctx->timeout = idleout;
1258   }
1259   else
1260     sctx->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1261
1262   if (GNUNET_CONFIGURATION_have_value
1263       (sctx->cfg, sctx->service_name, "TOLERANT"))
1264   {
1265     if (GNUNET_SYSERR ==
1266         (tolerant =
1267          GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, sctx->service_name,
1268                                                "TOLERANT")))
1269     {
1270       LOG (GNUNET_ERROR_TYPE_ERROR,
1271            _("Specified value for `%s' of service `%s' is invalid\n"),
1272            "TOLERANT", sctx->service_name);
1273       return GNUNET_SYSERR;
1274     }
1275   }
1276   else
1277     tolerant = GNUNET_NO;
1278
1279 #ifndef MINGW
1280   errno = 0;
1281   if ((NULL != (nfds = getenv ("LISTEN_FDS"))) &&
1282       (1 == SSCANF (nfds, "%u", &cnt)) && (cnt > 0) && (cnt < FD_SETSIZE) &&
1283       (cnt + 4 < FD_SETSIZE))
1284   {
1285     sctx->lsocks =
1286         GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle *) * (cnt + 1));
1287     while (0 < cnt--)
1288     {
1289       flags = fcntl (3 + cnt, F_GETFD);
1290       if ((flags < 0) || (0 != (flags & FD_CLOEXEC)) ||
1291           (NULL ==
1292            (sctx->lsocks[cnt] = GNUNET_NETWORK_socket_box_native (3 + cnt))))
1293       {
1294         LOG (GNUNET_ERROR_TYPE_ERROR,
1295              _
1296              ("Could not access pre-bound socket %u, will try to bind myself\n"),
1297              (unsigned int) 3 + cnt);
1298         cnt++;
1299         while (sctx->lsocks[cnt] != NULL)
1300           GNUNET_break (0 == GNUNET_NETWORK_socket_close (sctx->lsocks[cnt++]));
1301         GNUNET_free (sctx->lsocks);
1302         sctx->lsocks = NULL;
1303         break;
1304       }
1305     }
1306     unsetenv ("LISTEN_FDS");
1307   }
1308 #else
1309   if (getenv ("GNUNET_OS_READ_LSOCKS") != NULL)
1310   {
1311     receive_sockets_from_parent (sctx);
1312     putenv ("GNUNET_OS_READ_LSOCKS=");
1313   }
1314 #endif
1315
1316   if ((NULL == sctx->lsocks) &&
1317       (GNUNET_SYSERR ==
1318        GNUNET_SERVICE_get_server_addresses (sctx->service_name, sctx->cfg,
1319                                             &sctx->addrs, &sctx->addrlens)))
1320     return GNUNET_SYSERR;
1321   sctx->require_found = tolerant ? GNUNET_NO : GNUNET_YES;
1322   sctx->match_uid =
1323       GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, sctx->service_name,
1324                                             "UNIX_MATCH_UID");
1325   sctx->match_gid =
1326       GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, sctx->service_name,
1327                                             "UNIX_MATCH_GID");
1328   process_acl4 (&sctx->v4_denied, sctx, "REJECT_FROM");
1329   process_acl4 (&sctx->v4_allowed, sctx, "ACCEPT_FROM");
1330   process_acl6 (&sctx->v6_denied, sctx, "REJECT_FROM6");
1331   process_acl6 (&sctx->v6_allowed, sctx, "ACCEPT_FROM6");
1332
1333   return GNUNET_OK;
1334 }
1335
1336
1337 /**
1338  * Get the name of the user that'll be used
1339  * to provide the service.
1340  *
1341  * @param sctx service context
1342  * @return value of the 'USERNAME' option
1343  */
1344 static char *
1345 get_user_name (struct GNUNET_SERVICE_Context *sctx)
1346 {
1347   char *un;
1348
1349   if (GNUNET_OK !=
1350       GNUNET_CONFIGURATION_get_value_filename (sctx->cfg, sctx->service_name,
1351                                                "USERNAME", &un))
1352     return NULL;
1353   return un;
1354 }
1355
1356
1357 /**
1358  * Write PID file.
1359  *
1360  * @param sctx service context
1361  * @param pid PID to write (should be equal to 'getpid()'
1362  * @return  #GNUNET_OK on success (including no work to be done)
1363  */
1364 static int
1365 write_pid_file (struct GNUNET_SERVICE_Context *sctx, pid_t pid)
1366 {
1367   FILE *pidfd;
1368   char *pif;
1369   char *user;
1370   char *rdir;
1371   int len;
1372
1373   if (NULL == (pif = get_pid_file_name (sctx)))
1374     return GNUNET_OK;           /* no file desired */
1375   user = get_user_name (sctx);
1376   rdir = GNUNET_strdup (pif);
1377   len = strlen (rdir);
1378   while ((len > 0) && (rdir[len] != DIR_SEPARATOR))
1379     len--;
1380   rdir[len] = '\0';
1381   if (0 != ACCESS (rdir, F_OK))
1382   {
1383     /* we get to create a directory -- and claim it
1384      * as ours! */
1385     (void) GNUNET_DISK_directory_create (rdir);
1386     if ((NULL != user) && (0 < strlen (user)))
1387       GNUNET_DISK_file_change_owner (rdir, user);
1388   }
1389   if (0 != ACCESS (rdir, W_OK | X_OK))
1390   {
1391     LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", rdir);
1392     GNUNET_free (rdir);
1393     GNUNET_free_non_null (user);
1394     GNUNET_free (pif);
1395     return GNUNET_SYSERR;
1396   }
1397   GNUNET_free (rdir);
1398   pidfd = FOPEN (pif, "w");
1399   if (NULL == pidfd)
1400   {
1401     LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "fopen", pif);
1402     GNUNET_free (pif);
1403     GNUNET_free_non_null (user);
1404     return GNUNET_SYSERR;
1405   }
1406   if (0 > FPRINTF (pidfd, "%u", pid))
1407     LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fprintf", pif);
1408   GNUNET_break (0 == FCLOSE (pidfd));
1409   if ((NULL != user) && (0 < strlen (user)))
1410     GNUNET_DISK_file_change_owner (pif, user);
1411   GNUNET_free_non_null (user);
1412   GNUNET_free (pif);
1413   return GNUNET_OK;
1414 }
1415
1416
1417 /**
1418  * Task run during shutdown.  Stops the server/service.
1419  *
1420  * @param cls the `struct GNUNET_SERVICE_Context`
1421  * @param tc unused
1422  */
1423 static void
1424 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1425 {
1426   struct GNUNET_SERVICE_Context *service = cls;
1427   struct GNUNET_SERVER_Handle *server = service->server;
1428
1429   service->shutdown_task = GNUNET_SCHEDULER_NO_TASK;
1430   if (0 != (service->options & GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN))
1431     GNUNET_SERVER_stop_listening (server);
1432   else
1433     GNUNET_SERVER_destroy (server);
1434 }
1435
1436
1437 /**
1438  * Initial task for the service.
1439  *
1440  * @param cls service context
1441  * @param tc unused
1442  */
1443 static void
1444 service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1445 {
1446   struct GNUNET_SERVICE_Context *sctx = cls;
1447   unsigned int i;
1448
1449   if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
1450     return;
1451   (void) GNUNET_SPEEDUP_start_ (sctx->cfg);
1452   GNUNET_RESOLVER_connect (sctx->cfg);
1453   if (NULL != sctx->lsocks)
1454     sctx->server
1455       = GNUNET_SERVER_create_with_sockets (&check_access, sctx, sctx->lsocks,
1456                                            sctx->timeout, sctx->require_found);
1457   else
1458     sctx->server
1459       = GNUNET_SERVER_create (&check_access, sctx, sctx->addrs, sctx->addrlens,
1460                               sctx->timeout, sctx->require_found);
1461   if (NULL == sctx->server)
1462   {
1463     if (NULL != sctx->addrs)
1464       for (i = 0; NULL != sctx->addrs[i]; i++)
1465         LOG (GNUNET_ERROR_TYPE_INFO,
1466              _("Failed to start `%s' at `%s'\n"),
1467              sctx->service_name, GNUNET_a2s (sctx->addrs[i], sctx->addrlens[i]));
1468     sctx->ret = GNUNET_SYSERR;
1469     return;
1470   }
1471 #ifndef WINDOWS
1472   if (NULL != sctx->addrs)
1473     for (i = 0; NULL != sctx->addrs[i]; i++)
1474       if (AF_UNIX == sctx->addrs[i]->sa_family)
1475         GNUNET_DISK_fix_permissions (((const struct sockaddr_un *)sctx->addrs[i])->sun_path,
1476                                      sctx->match_uid,
1477                                      sctx->match_gid);
1478 #endif
1479
1480
1481   if (0 == (sctx->options & GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN))
1482   {
1483     /* install a task that will kill the server
1484      * process if the scheduler ever gets a shutdown signal */
1485     sctx->shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1486                                                         &shutdown_task,
1487                                                         sctx);
1488   }
1489   sctx->my_handlers = GNUNET_malloc (sizeof (defhandlers));
1490   memcpy (sctx->my_handlers, defhandlers, sizeof (defhandlers));
1491   i = 0;
1492   while (NULL != sctx->my_handlers[i].callback)
1493     sctx->my_handlers[i++].callback_cls = sctx;
1494   GNUNET_SERVER_add_handlers (sctx->server, sctx->my_handlers);
1495   if (-1 != sctx->ready_confirm_fd)
1496   {
1497     GNUNET_break (1 == WRITE (sctx->ready_confirm_fd, ".", 1));
1498     GNUNET_break (0 == CLOSE (sctx->ready_confirm_fd));
1499     sctx->ready_confirm_fd = -1;
1500     write_pid_file (sctx, getpid ());
1501   }
1502   if (NULL != sctx->addrs)
1503   {
1504     i = 0;
1505     while (NULL != sctx->addrs[i])
1506     {
1507       LOG (GNUNET_ERROR_TYPE_INFO, _("Service `%s' runs at %s\n"),
1508            sctx->service_name, GNUNET_a2s (sctx->addrs[i], sctx->addrlens[i]));
1509       i++;
1510     }
1511   }
1512   sctx->task (sctx->task_cls, sctx->server, sctx->cfg);
1513 }
1514
1515
1516 /**
1517  * Detach from terminal.
1518  *
1519  * @param sctx service context
1520  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1521  */
1522 static int
1523 detach_terminal (struct GNUNET_SERVICE_Context *sctx)
1524 {
1525 #ifndef MINGW
1526   pid_t pid;
1527   int nullfd;
1528   int filedes[2];
1529
1530   if (0 != PIPE (filedes))
1531   {
1532     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "pipe");
1533     return GNUNET_SYSERR;
1534   }
1535   pid = fork ();
1536   if (pid < 0)
1537   {
1538     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fork");
1539     return GNUNET_SYSERR;
1540   }
1541   if (0 != pid)
1542   {
1543     /* Parent */
1544     char c;
1545
1546     GNUNET_break (0 == CLOSE (filedes[1]));
1547     c = 'X';
1548     if (1 != READ (filedes[0], &c, sizeof (char)))
1549       LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "read");
1550     fflush (stdout);
1551     switch (c)
1552     {
1553     case '.':
1554       exit (0);
1555     case 'I':
1556       LOG (GNUNET_ERROR_TYPE_INFO, _("Service process failed to initialize\n"));
1557       break;
1558     case 'S':
1559       LOG (GNUNET_ERROR_TYPE_INFO,
1560            _("Service process could not initialize server function\n"));
1561       break;
1562     case 'X':
1563       LOG (GNUNET_ERROR_TYPE_INFO,
1564            _("Service process failed to report status\n"));
1565       break;
1566     }
1567     exit (1);                   /* child reported error */
1568   }
1569   GNUNET_break (0 == CLOSE (0));
1570   GNUNET_break (0 == CLOSE (1));
1571   GNUNET_break (0 == CLOSE (filedes[0]));
1572   nullfd = OPEN ("/dev/null", O_RDWR | O_APPEND);
1573   if (nullfd < 0)
1574     return GNUNET_SYSERR;
1575   /* set stdin/stdout to /dev/null */
1576   if ((dup2 (nullfd, 0) < 0) || (dup2 (nullfd, 1) < 0))
1577   {
1578     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "dup2");
1579     (void) CLOSE (nullfd);
1580     return GNUNET_SYSERR;
1581   }
1582   (void) CLOSE (nullfd);
1583   /* Detach from controlling terminal */
1584   pid = setsid ();
1585   if (-1 == pid)
1586     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "setsid");
1587   sctx->ready_confirm_fd = filedes[1];
1588 #else
1589   /* FIXME: we probably need to do something else
1590    * elsewhere in order to fork the process itself... */
1591   FreeConsole ();
1592 #endif
1593   return GNUNET_OK;
1594 }
1595
1596
1597 /**
1598  * Set user ID.
1599  *
1600  * @param sctx service context
1601  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1602  */
1603 static int
1604 set_user_id (struct GNUNET_SERVICE_Context *sctx)
1605 {
1606   char *user;
1607
1608   if (NULL == (user = get_user_name (sctx)))
1609     return GNUNET_OK;           /* keep */
1610 #ifndef MINGW
1611   struct passwd *pws;
1612
1613   errno = 0;
1614   pws = getpwnam (user);
1615   if (NULL == pws)
1616   {
1617     LOG (GNUNET_ERROR_TYPE_ERROR,
1618          _("Cannot obtain information about user `%s': %s\n"), user,
1619          errno == 0 ? _("No such user") : STRERROR (errno));
1620     GNUNET_free (user);
1621     return GNUNET_SYSERR;
1622   }
1623   if ((0 != setgid (pws->pw_gid)) || (0 != setegid (pws->pw_gid)) ||
1624 #if HAVE_INITGROUPS
1625       (0 != initgroups (user, pws->pw_gid)) ||
1626 #endif
1627       (0 != setuid (pws->pw_uid)) || (0 != seteuid (pws->pw_uid)))
1628   {
1629     if ((0 != setregid (pws->pw_gid, pws->pw_gid)) ||
1630         (0 != setreuid (pws->pw_uid, pws->pw_uid)))
1631     {
1632       LOG (GNUNET_ERROR_TYPE_ERROR, _("Cannot change user/group to `%s': %s\n"),
1633            user, STRERROR (errno));
1634       GNUNET_free (user);
1635       return GNUNET_SYSERR;
1636     }
1637   }
1638 #endif
1639   GNUNET_free (user);
1640   return GNUNET_OK;
1641 }
1642
1643
1644 /**
1645  * Delete the PID file that was created by our parent.
1646  *
1647  * @param sctx service context
1648  */
1649 static void
1650 pid_file_delete (struct GNUNET_SERVICE_Context *sctx)
1651 {
1652   char *pif = get_pid_file_name (sctx);
1653
1654   if (NULL == pif)
1655     return;                     /* no PID file */
1656   if (0 != UNLINK (pif))
1657     LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", pif);
1658   GNUNET_free (pif);
1659 }
1660
1661
1662 /**
1663  * Run a standard GNUnet service startup sequence (initialize loggers
1664  * and configuration, parse options).
1665  *
1666  * @param argc number of command line arguments
1667  * @param argv command line arguments
1668  * @param service_name our service name
1669  * @param options service options
1670  * @param task main task of the service
1671  * @param task_cls closure for @a task
1672  * @return #GNUNET_SYSERR on error, #GNUNET_OK
1673  *         if we shutdown nicely
1674  */
1675 int
1676 GNUNET_SERVICE_run (int argc, char *const *argv,
1677                     const char *service_name,
1678                     enum GNUNET_SERVICE_Options options,
1679                     GNUNET_SERVICE_Main task,
1680                     void *task_cls)
1681 {
1682 #define HANDLE_ERROR do { GNUNET_break (0); goto shutdown; } while (0)
1683
1684   int err;
1685   int ret;
1686   char *cfg_fn;
1687   char *opt_cfg_fn;
1688   char *loglev;
1689   char *logfile;
1690   int do_daemonize;
1691   unsigned int i;
1692   unsigned long long skew_offset;
1693   unsigned long long skew_variance;
1694   long long clock_offset;
1695   struct GNUNET_SERVICE_Context sctx;
1696   struct GNUNET_CONFIGURATION_Handle *cfg;
1697   const char *xdg;
1698
1699   struct GNUNET_GETOPT_CommandLineOption service_options[] = {
1700     GNUNET_GETOPT_OPTION_CFG_FILE (&opt_cfg_fn),
1701     {'d', "daemonize", NULL,
1702      gettext_noop ("do daemonize (detach from terminal)"), 0,
1703      GNUNET_GETOPT_set_one, &do_daemonize},
1704     GNUNET_GETOPT_OPTION_HELP (NULL),
1705     GNUNET_GETOPT_OPTION_LOGLEVEL (&loglev),
1706     GNUNET_GETOPT_OPTION_LOGFILE (&logfile),
1707     GNUNET_GETOPT_OPTION_VERSION (PACKAGE_VERSION " " VCS_VERSION),
1708     GNUNET_GETOPT_OPTION_END
1709   };
1710   err = 1;
1711   do_daemonize = 0;
1712   logfile = NULL;
1713   loglev = NULL;
1714   opt_cfg_fn = NULL;
1715   xdg = getenv ("XDG_CONFIG_HOME");
1716   if (NULL != xdg)
1717     GNUNET_asprintf (&cfg_fn,
1718                      "%s%s%s",
1719                      xdg,
1720                      DIR_SEPARATOR_STR,
1721                      "gnunet.conf");
1722   else
1723     cfg_fn = GNUNET_strdup (GNUNET_DEFAULT_USER_CONFIG_FILE);
1724   memset (&sctx, 0, sizeof (sctx));
1725   sctx.options = options;
1726   sctx.ready_confirm_fd = -1;
1727   sctx.ret = GNUNET_OK;
1728   sctx.timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1729   sctx.task = task;
1730   sctx.task_cls = task_cls;
1731   sctx.service_name = service_name;
1732   sctx.cfg = cfg = GNUNET_CONFIGURATION_create ();
1733
1734   /* setup subsystems */
1735   ret = GNUNET_GETOPT_run (service_name, service_options, argc, argv);
1736   if (GNUNET_SYSERR == ret)
1737     goto shutdown;
1738   if (GNUNET_NO == ret)
1739   {
1740     err = 0;
1741     goto shutdown;
1742   }
1743   if (GNUNET_OK != GNUNET_log_setup (service_name, loglev, logfile))
1744     HANDLE_ERROR;
1745   if (NULL == opt_cfg_fn)
1746     opt_cfg_fn = GNUNET_strdup (cfg_fn);
1747   if (GNUNET_YES ==
1748       GNUNET_DISK_file_test (opt_cfg_fn))
1749     (void) GNUNET_CONFIGURATION_load (cfg, opt_cfg_fn);
1750   else
1751   {
1752     (void) GNUNET_CONFIGURATION_load (cfg, NULL);
1753     if (0 != strcmp (opt_cfg_fn, cfg_fn))
1754       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1755                   _("Could not access configuration file `%s'\n"),
1756                   opt_cfg_fn);
1757   }
1758   if (GNUNET_OK != setup_service (&sctx))
1759     goto shutdown;
1760   if ((1 == do_daemonize) && (GNUNET_OK != detach_terminal (&sctx)))
1761     HANDLE_ERROR;
1762   if (GNUNET_OK != set_user_id (&sctx))
1763     goto shutdown;
1764   LOG (GNUNET_ERROR_TYPE_DEBUG,
1765        "Service `%s' runs with configuration from `%s'\n",
1766        service_name,
1767        opt_cfg_fn);
1768   if ((GNUNET_OK ==
1769        GNUNET_CONFIGURATION_get_value_number (sctx.cfg, "TESTING",
1770                                               "SKEW_OFFSET", &skew_offset)) &&
1771       (GNUNET_OK ==
1772        GNUNET_CONFIGURATION_get_value_number (sctx.cfg, "TESTING",
1773                                               "SKEW_VARIANCE", &skew_variance)))
1774   {
1775     clock_offset = skew_offset - skew_variance;
1776     GNUNET_TIME_set_offset (clock_offset);
1777     LOG (GNUNET_ERROR_TYPE_DEBUG, "Skewing clock by %dll ms\n", clock_offset);
1778   }
1779   /* actually run service */
1780   err = 0;
1781   GNUNET_SCHEDULER_run (&service_task, &sctx);
1782   /* shutdown */
1783   if ((1 == do_daemonize) && (NULL != sctx.server))
1784     pid_file_delete (&sctx);
1785   GNUNET_free_non_null (sctx.my_handlers);
1786
1787 shutdown:
1788   if (-1 != sctx.ready_confirm_fd)
1789   {
1790     if (1 != WRITE (sctx.ready_confirm_fd, err ? "I" : "S", 1))
1791       LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "write");
1792     GNUNET_break (0 == CLOSE (sctx.ready_confirm_fd));
1793   }
1794 #if HAVE_MALLINFO
1795   {
1796     char *counter;
1797
1798     if ( (GNUNET_YES ==
1799           GNUNET_CONFIGURATION_have_value (sctx.cfg, service_name,
1800                                            "GAUGER_HEAP")) &&
1801          (GNUNET_OK ==
1802           GNUNET_CONFIGURATION_get_value_string (sctx.cfg, service_name,
1803                                                  "GAUGER_HEAP",
1804                                                  &counter)) )
1805     {
1806       struct mallinfo mi;
1807
1808       mi = mallinfo ();
1809       GAUGER (service_name, counter, mi.usmblks, "blocks");
1810       GNUNET_free (counter);
1811     }
1812   }
1813 #endif
1814   GNUNET_SPEEDUP_stop_ ();
1815   GNUNET_CONFIGURATION_destroy (cfg);
1816   i = 0;
1817   if (NULL != sctx.addrs)
1818     while (NULL != sctx.addrs[i])
1819       GNUNET_free (sctx.addrs[i++]);
1820   GNUNET_free_non_null (sctx.addrs);
1821   GNUNET_free_non_null (sctx.addrlens);
1822   GNUNET_free_non_null (logfile);
1823   GNUNET_free_non_null (loglev);
1824   GNUNET_free (cfg_fn);
1825   GNUNET_free (opt_cfg_fn);
1826   GNUNET_free_non_null (sctx.v4_denied);
1827   GNUNET_free_non_null (sctx.v6_denied);
1828   GNUNET_free_non_null (sctx.v4_allowed);
1829   GNUNET_free_non_null (sctx.v6_allowed);
1830
1831   return err ? GNUNET_SYSERR : sctx.ret;
1832 }
1833
1834
1835 /**
1836  * Run a service startup sequence within an existing
1837  * initialized system.
1838  *
1839  * @param service_name our service name
1840  * @param cfg configuration to use
1841  * @param options service options
1842  * @return NULL on error, service handle
1843  */
1844 struct GNUNET_SERVICE_Context *
1845 GNUNET_SERVICE_start (const char *service_name,
1846                       const struct GNUNET_CONFIGURATION_Handle *cfg,
1847                       enum GNUNET_SERVICE_Options options)
1848 {
1849   int i;
1850   struct GNUNET_SERVICE_Context *sctx;
1851
1852   sctx = GNUNET_new (struct GNUNET_SERVICE_Context);
1853   sctx->ready_confirm_fd = -1;  /* no daemonizing */
1854   sctx->ret = GNUNET_OK;
1855   sctx->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1856   sctx->service_name = service_name;
1857   sctx->cfg = cfg;
1858   sctx->options = options;
1859
1860   /* setup subsystems */
1861   if (GNUNET_OK != setup_service (sctx))
1862   {
1863     GNUNET_SERVICE_stop (sctx);
1864     return NULL;
1865   }
1866   if (NULL != sctx->lsocks)
1867     sctx->server =
1868         GNUNET_SERVER_create_with_sockets (&check_access, sctx, sctx->lsocks,
1869                                            sctx->timeout, sctx->require_found);
1870   else
1871     sctx->server =
1872         GNUNET_SERVER_create (&check_access, sctx, sctx->addrs, sctx->addrlens,
1873                               sctx->timeout, sctx->require_found);
1874
1875   if (NULL == sctx->server)
1876   {
1877     GNUNET_SERVICE_stop (sctx);
1878     return NULL;
1879   }
1880 #ifndef WINDOWS
1881   if (NULL != sctx->addrs)
1882     for (i = 0; NULL != sctx->addrs[i]; i++)
1883       if (AF_UNIX == sctx->addrs[i]->sa_family)
1884         GNUNET_DISK_fix_permissions (((const struct sockaddr_un *)sctx->addrs[i])->sun_path,
1885                                      sctx->match_uid,
1886                                      sctx->match_gid);
1887 #endif
1888   sctx->my_handlers = GNUNET_malloc (sizeof (defhandlers));
1889   memcpy (sctx->my_handlers, defhandlers, sizeof (defhandlers));
1890   i = 0;
1891   while ((sctx->my_handlers[i].callback != NULL))
1892     sctx->my_handlers[i++].callback_cls = sctx;
1893   GNUNET_SERVER_add_handlers (sctx->server, sctx->my_handlers);
1894   return sctx;
1895 }
1896
1897
1898 /**
1899  * Obtain the server used by a service.  Note that the server must NOT
1900  * be destroyed by the caller.
1901  *
1902  * @param ctx the service context returned from the start function
1903  * @return handle to the server for this service, NULL if there is none
1904  */
1905 struct GNUNET_SERVER_Handle *
1906 GNUNET_SERVICE_get_server (struct GNUNET_SERVICE_Context *ctx)
1907 {
1908   return ctx->server;
1909 }
1910
1911
1912 /**
1913  * Stop a service that was started with "GNUNET_SERVICE_start".
1914  *
1915  * @param sctx the service context returned from the start function
1916  */
1917 void
1918 GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Context *sctx)
1919 {
1920   unsigned int i;
1921
1922 #if HAVE_MALLINFO
1923   {
1924     char *counter;
1925
1926     if ( (GNUNET_YES ==
1927           GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name,
1928                                            "GAUGER_HEAP")) &&
1929          (GNUNET_OK ==
1930           GNUNET_CONFIGURATION_get_value_string (sctx->cfg, sctx->service_name,
1931                                                  "GAUGER_HEAP",
1932                                                  &counter)) )
1933     {
1934       struct mallinfo mi;
1935
1936       mi = mallinfo ();
1937       GAUGER (sctx->service_name, counter, mi.usmblks, "blocks");
1938       GNUNET_free (counter);
1939     }
1940   }
1941 #endif
1942   if (GNUNET_SCHEDULER_NO_TASK != sctx->shutdown_task)
1943   {
1944     GNUNET_SCHEDULER_cancel (sctx->shutdown_task);
1945     sctx->shutdown_task = GNUNET_SCHEDULER_NO_TASK;
1946   }
1947   if (NULL != sctx->server)
1948     GNUNET_SERVER_destroy (sctx->server);
1949   GNUNET_free_non_null (sctx->my_handlers);
1950   if (NULL != sctx->addrs)
1951   {
1952     i = 0;
1953     while (NULL != sctx->addrs[i])
1954       GNUNET_free (sctx->addrs[i++]);
1955     GNUNET_free (sctx->addrs);
1956   }
1957   GNUNET_free_non_null (sctx->addrlens);
1958   GNUNET_free_non_null (sctx->v4_denied);
1959   GNUNET_free_non_null (sctx->v6_denied);
1960   GNUNET_free_non_null (sctx->v4_allowed);
1961   GNUNET_free_non_null (sctx->v6_allowed);
1962   GNUNET_free (sctx);
1963 }
1964
1965
1966 /* end of service.c */