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