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