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