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