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