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