2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
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.
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.
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.
22 * @file util/service.c
23 * @brief functions related to starting services
24 * @author Christian Grothoff
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"
39 #define DEBUG_SERVICE GNUNET_NO
41 /* ******************* access control ******************** */
44 * @brief IPV4 network in CIDR notation.
48 struct in_addr network;
49 struct in_addr netmask;
53 * @brief network in CIDR notation for IPV6.
57 struct in6_addr network;
58 struct in6_addr netmask;
63 * Parse a network specification. The argument specifies
64 * a list of networks. The format is
65 * <tt>[network/netmask;]*</tt> (no whitespace, must be terminated
66 * with a semicolon). The network must be given in dotted-decimal
67 * notation. The netmask can be given in CIDR notation (/16) or
68 * in dotted-decimal (/255.255.0.0).
70 * @param routeList a string specifying the forbidden networks
71 * @return the converted list, NULL if the synatx is flawed
73 static struct IPv4NetworkSet *
74 parse_ipv4_specification (const char *routeList)
82 unsigned int temps[8];
84 struct IPv4NetworkSet *result;
86 if (routeList == NULL)
88 len = strlen (routeList);
92 for (i = 0; i < len; i++)
93 if (routeList[i] == ';')
95 result = GNUNET_malloc (sizeof (struct IPv4NetworkSet) * (count + 1));
97 memset (result, 0, sizeof (struct IPv4NetworkSet) * (count + 1));
102 cnt = sscanf (&routeList[pos],
103 "%u.%u.%u.%u/%u.%u.%u.%u;",
107 &temps[3], &temps[4], &temps[5], &temps[6], &temps[7]);
110 for (j = 0; j < 8; j++)
113 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
114 _("Invalid format for IP: `%s'\n"), &routeList[pos]);
115 GNUNET_free (result);
118 result[i].network.s_addr
120 htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
122 result[i].netmask.s_addr =
123 htonl ((temps[4] << 24) + (temps[5] << 16) + (temps[6] << 8) +
125 while (routeList[pos] != ';')
131 /* try second notation */
132 cnt = sscanf (&routeList[pos],
134 &temps[0], &temps[1], &temps[2], &temps[3], &slash);
137 for (j = 0; j < 4; j++)
140 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
141 _("Invalid format for IP: `%s'\n"), &routeList[pos]);
142 GNUNET_free (result);
145 result[i].network.s_addr
147 htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
149 if ((slash <= 32) && (slash >= 0))
151 result[i].netmask.s_addr = 0;
154 result[i].netmask.s_addr
155 = (result[i].netmask.s_addr >> 1) + 0x80000000;
158 result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
159 while (routeList[pos] != ';')
167 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
169 ("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."),
171 GNUNET_free (result);
172 return NULL; /* error */
175 /* try third notation */
177 cnt = sscanf (&routeList[pos],
178 "%u.%u.%u.%u;", &temps[0], &temps[1], &temps[2], &temps[3]);
181 for (j = 0; j < 4; j++)
184 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
185 _("Invalid format for IP: `%s'\n"), &routeList[pos]);
186 GNUNET_free (result);
189 result[i].network.s_addr
191 htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
193 result[i].netmask.s_addr = 0;
196 result[i].netmask.s_addr = (result[i].netmask.s_addr >> 1) + 0x80000000;
199 result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
200 while (routeList[pos] != ';')
206 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
207 _("Invalid format for IP: `%s'\n"), &routeList[pos]);
208 GNUNET_free (result);
209 return NULL; /* error */
211 if (pos < strlen (routeList))
213 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
214 _("Invalid format for IP: `%s'\n"), &routeList[pos]);
215 GNUNET_free (result);
216 return NULL; /* oops */
218 return result; /* ok */
223 * Parse a network specification. The argument specifies
224 * a list of networks. The format is
225 * <tt>[network/netmask;]*</tt> (no whitespace, must be terminated
226 * with a semicolon). The network must be given in colon-hex
227 * notation. The netmask must be given in CIDR notation (/16) or
228 * can be omitted to specify a single host.
230 * @param routeListX a string specifying the forbidden networks
231 * @return the converted list, NULL if the synatx is flawed
233 static struct IPv6NetworkSet *
234 parse_ipv6_specification (const char *routeListX)
244 struct IPv6NetworkSet *result;
249 if (routeListX == NULL)
251 len = strlen (routeListX);
254 routeList = GNUNET_strdup (routeListX);
256 for (i = 0; i < len; i++)
257 if (routeList[i] == ';')
259 if (routeList[len - 1] != ';')
261 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
263 ("Invalid network notation (does not end with ';': `%s')\n"),
265 GNUNET_free (routeList);
269 result = GNUNET_malloc (sizeof (struct IPv6NetworkSet) * (count + 1));
270 memset (result, 0, sizeof (struct IPv6NetworkSet) * (count + 1));
276 while (routeList[pos] != ';')
279 while ((slash >= start) && (routeList[slash] != '/'))
283 memset (&result[i].netmask, 0xFF, sizeof (struct in6_addr));
288 routeList[pos] = '\0';
289 ret = inet_pton (AF_INET6, &routeList[slash + 1], &result[i].netmask);
293 if ((1 != SSCANF (&routeList[slash + 1], "%u", &bits)) || (bits >= 128))
296 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
297 _("Wrong format `%s' for netmask\n"),
298 &routeList[slash + 1]);
302 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "inet_pton");
304 GNUNET_free (result);
305 GNUNET_free (routeList);
311 result[i].netmask.s6_addr[off++] = 0xFF;
316 result[i].netmask.s6_addr[off]
317 = (result[i].netmask.s6_addr[off] >> 1) + 0x80;
322 routeList[slash] = '\0';
323 ret = inet_pton (AF_INET6, &routeList[start], &result[i].network);
327 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
328 _("Wrong format `%s' for network\n"),
329 &routeList[slash + 1]);
331 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "inet_pton");
332 GNUNET_free (result);
333 GNUNET_free (routeList);
339 GNUNET_free (routeList);
345 * Check if the given IP address is in the list of IP addresses.
347 * @param list a list of networks
348 * @param add the IP to check (in network byte order)
349 * @return GNUNET_NO if the IP is not in the list, GNUNET_YES if it it is
352 check_ipv4_listed (const struct IPv4NetworkSet *list, const struct in_addr *add)
360 while ((list[i].network.s_addr != 0) || (list[i].netmask.s_addr != 0))
362 if ((add->s_addr & list[i].netmask.s_addr) ==
363 (list[i].network.s_addr & list[i].netmask.s_addr))
371 * Check if the given IP address is in the list of IP addresses.
373 * @param list a list of networks
374 * @param ip the IP to check (in network byte order)
375 * @return GNUNET_NO if the IP is not in the list, GNUNET_YES if it it is
378 check_ipv6_listed (const struct IPv6NetworkSet *list, const struct in6_addr *ip)
382 struct in6_addr zero;
387 memset (&zero, 0, sizeof (struct in6_addr));
390 while (memcmp (&zero, &list[i].network, sizeof (struct in6_addr)) != 0)
392 for (j = 0; j < sizeof (struct in6_addr) / sizeof (int); j++)
393 if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) !=
394 (((int *) &list[i].network)[j] & ((int *) &list[i].netmask)[j]))
405 /* ****************** service struct ****************** */
409 * Context for "service_task".
411 struct GNUNET_SERVICE_Context
416 const struct GNUNET_CONFIGURATION_Handle *cfg;
419 * Handle for the server.
421 struct GNUNET_SERVER_Handle *server;
424 * NULL-terminated array of addresses to bind to, NULL if we got pre-bound
427 struct sockaddr **addrs;
430 * Name of our service.
432 const char *serviceName;
435 * Main service-specific task to run.
437 GNUNET_SERVICE_Main task;
445 * IPv4 addresses that are not allowed to connect.
447 struct IPv4NetworkSet *v4_denied;
450 * IPv6 addresses that are not allowed to connect.
452 struct IPv6NetworkSet *v6_denied;
455 * IPv4 addresses that are allowed to connect (if not
456 * set, all are allowed).
458 struct IPv4NetworkSet *v4_allowed;
461 * IPv6 addresses that are allowed to connect (if not
462 * set, all are allowed).
464 struct IPv6NetworkSet *v6_allowed;
467 * My (default) message handlers. Adjusted copy
470 struct GNUNET_SERVER_MessageHandler *my_handlers;
473 * Array of the lengths of the entries in addrs.
478 * NULL-terminated array of listen sockets we should take over.
480 struct GNUNET_NETWORK_Handle **lsocks;
483 * Idle timeout for server.
485 struct GNUNET_TIME_Relative timeout;
488 * Overall success/failure of the service start.
493 * If we are daemonizing, this FD is set to the
494 * pipe to the parent. Send '.' if we started
495 * ok, '!' if not. -1 if we are not daemonizing.
497 int ready_confirm_fd;
500 * Do we close connections if we receive messages
501 * for which we have no handler?
506 * Do we require a matching UID for UNIX domain socket
512 * Do we require a matching GID for UNIX domain socket
520 enum GNUNET_SERVICE_Options options;
525 /* ****************** message handlers ****************** */
528 write_test (void *cls, size_t size, void *buf)
530 struct GNUNET_SERVER_Client *client = cls;
531 struct GNUNET_MessageHeader *msg;
533 if (size < sizeof (struct GNUNET_MessageHeader))
535 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
536 return 0; /* client disconnected */
538 msg = (struct GNUNET_MessageHeader *) buf;
539 msg->type = htons (GNUNET_MESSAGE_TYPE_TEST);
540 msg->size = htons (sizeof (struct GNUNET_MessageHeader));
541 GNUNET_SERVER_receive_done (client, GNUNET_OK);
542 return sizeof (struct GNUNET_MessageHeader);
546 * Handler for TEST message.
548 * @param cls closure (refers to service)
549 * @param client identification of the client
550 * @param message the actual message
553 handle_test (void *cls,
554 struct GNUNET_SERVER_Client *client,
555 const struct GNUNET_MessageHeader *message)
557 /* simply bounce message back to acknowledge */
558 if (NULL == GNUNET_SERVER_notify_transmit_ready (client,
560 GNUNET_MessageHeader),
561 GNUNET_TIME_UNIT_FOREVER_REL,
562 &write_test, client))
563 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
568 * Default handlers for all services. Will be copied and the
569 * "callback_cls" fields will be replaced with the specific service
572 static const struct GNUNET_SERVER_MessageHandler defhandlers[] = {
573 {&handle_test, NULL, GNUNET_MESSAGE_TYPE_TEST,
574 sizeof (struct GNUNET_MessageHeader)},
580 /* ****************** service core routines ************** */
584 * Check if access to the service is allowed from the given address.
587 * @param uc credentials, if available, otherwise NULL
588 * @param addr address
589 * @param addrlen length of address
590 * @return GNUNET_YES to allow, GNUNET_NO to deny, GNUNET_SYSERR
591 * for unknown address family (will be denied).
594 check_access (void *cls,
595 const struct GNUNET_CONNECTION_Credentials *uc,
596 const struct sockaddr *addr, socklen_t addrlen)
598 struct GNUNET_SERVICE_Context *sctx = cls;
599 const struct sockaddr_in *i4;
600 const struct sockaddr_in6 *i6;
603 switch (addr->sa_family)
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,
611 && ((sctx->v4_denied == NULL) ||
612 (!check_ipv4_listed (sctx->v4_denied, &i4->sin_addr)));
615 GNUNET_assert (addrlen == sizeof (struct sockaddr_in6));
616 i6 = (const struct sockaddr_in6 *) addr;
617 ret = ((sctx->v6_allowed == NULL) ||
618 (check_ipv6_listed (sctx->v6_allowed,
620 && ((sctx->v6_denied == NULL) ||
621 (!check_ipv6_listed (sctx->v6_denied, &i6->sin6_addr)));
625 ret = GNUNET_OK; /* always OK for now */
626 if ((sctx->match_uid == GNUNET_YES) || (sctx->match_gid == GNUNET_YES))
629 ((sctx->match_uid != GNUNET_YES) ||
630 (uc->uid == geteuid ()) ||
631 (uc->uid == getuid ())) &&
632 ((sctx->match_gid != GNUNET_YES) ||
633 (uc->gid == getegid ()) || (uc->gid == getgid ())))
636 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
637 _("Access denied to UID %d / GID %d\n"),
638 (uc == NULL) ? -1 : uc->uid, (uc == NULL) ? -1 : uc->gid);
642 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
643 _("Unknown address family %d\n"), addr->sa_family);
644 return GNUNET_SYSERR;
646 if (ret != GNUNET_OK)
648 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
649 _("Access from `%s' denied to service `%s'\n"),
650 GNUNET_a2s (addr, addrlen), sctx->serviceName);
657 * Get the name of the file where we will
658 * write the PID of the service.
661 get_pid_file_name (struct GNUNET_SERVICE_Context *sctx)
667 GNUNET_CONFIGURATION_get_value_filename (sctx->cfg,
676 * Parse an IPv4 access control list.
679 process_acl4 (struct IPv4NetworkSet **ret,
680 struct GNUNET_SERVICE_Context *sctx, const char *option)
684 if (!GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->serviceName, option))
686 GNUNET_break (GNUNET_OK ==
687 GNUNET_CONFIGURATION_get_value_string (sctx->cfg,
690 if (NULL == (*ret = parse_ipv4_specification (opt)))
692 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
694 ("Could not parse IPv4 network specification `%s' for `%s:%s'\n"),
695 opt, sctx->serviceName, option);
697 return GNUNET_SYSERR;
705 * Parse an IPv4 access control list.
708 process_acl6 (struct IPv6NetworkSet **ret,
709 struct GNUNET_SERVICE_Context *sctx, const char *option)
713 if (!GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->serviceName, option))
715 GNUNET_break (GNUNET_OK ==
716 GNUNET_CONFIGURATION_get_value_string (sctx->cfg,
719 if (NULL == (*ret = parse_ipv6_specification (opt)))
721 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
723 ("Could not parse IPv6 network specification `%s' for `%s:%s'\n"),
724 opt, sctx->serviceName, option);
726 return GNUNET_SYSERR;
733 * Add the given UNIX domain path as an address to the
734 * list (as the first entry).
736 * @param saddrs array to update
737 * @param saddrlens where to store the address length
738 * @param unixpath path to add
741 add_unixpath (struct sockaddr **saddrs,
742 socklen_t * saddrlens, const char *unixpath)
745 struct sockaddr_un *un;
748 un = GNUNET_malloc (sizeof (struct sockaddr_un));
749 un->sun_family = AF_UNIX;
750 slen = strlen (unixpath) + 1;
751 if (slen >= sizeof (un->sun_path))
752 slen = sizeof (un->sun_path) - 1;
753 memcpy (un->sun_path, unixpath, slen);
754 un->sun_path[slen] = '\0';
755 slen = sizeof (struct sockaddr_un);
757 un->sun_path[0] = '\0';
759 #if HAVE_SOCKADDR_IN_SIN_LEN
760 un->sun_len = (u_char) slen;
762 *saddrs = (struct sockaddr *) un;
765 /* this function should never be called
766 * unless AF_UNIX is defined! */
773 * Get the list of addresses that a server for the given service
776 * @param serviceName name of the service
777 * @param cfg configuration (which specifies the addresses)
778 * @param addrs set (call by reference) to an array of pointers to the
779 * addresses the server should bind to and listen on; the
780 * array will be NULL-terminated (on success)
781 * @param addr_lens set (call by reference) to an array of the lengths
782 * of the respective 'struct sockaddr' struct in the 'addrs'
784 * @return number of addresses found on success,
785 * GNUNET_SYSERR if the configuration
786 * did not specify reasonable finding information or
787 * if it specified a hostname that could not be resolved;
788 * GNUNET_NO if the number of addresses configured is
789 * zero (in this case, '*addrs' and '*addr_lens' will be
793 GNUNET_SERVICE_get_server_addresses (const char *serviceName,
794 const struct GNUNET_CONFIGURATION_Handle
795 *cfg, struct sockaddr ***addrs,
796 socklen_t ** addr_lens)
799 struct GNUNET_NETWORK_Handle *desc;
800 unsigned long long port;
802 struct addrinfo hints;
803 struct addrinfo *res;
804 struct addrinfo *pos;
805 struct addrinfo *next;
809 struct sockaddr **saddrs;
810 socklen_t *saddrlens;
816 if (GNUNET_CONFIGURATION_have_value (cfg, serviceName, "DISABLEV6"))
819 (disablev6 = GNUNET_CONFIGURATION_get_value_yesno (cfg,
822 return GNUNET_SYSERR;
825 disablev6 = GNUNET_NO;
829 /* probe IPv6 support */
830 desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
833 if ((errno == ENOBUFS) ||
834 (errno == ENOMEM) || (errno == ENFILE) || (errno == EACCES))
836 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
837 return GNUNET_SYSERR;
839 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
841 ("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
842 serviceName, STRERROR (errno));
843 disablev6 = GNUNET_YES;
847 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
853 if (GNUNET_CONFIGURATION_have_value (cfg, serviceName, "PORT"))
855 GNUNET_break (GNUNET_OK ==
856 GNUNET_CONFIGURATION_get_value_number (cfg,
861 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
863 ("Require valid port number for service `%s' in configuration!\n"),
865 return GNUNET_SYSERR;
869 if (GNUNET_CONFIGURATION_have_value (cfg, serviceName, "BINDTO"))
871 GNUNET_break (GNUNET_OK ==
872 GNUNET_CONFIGURATION_get_value_string (cfg,
874 "BINDTO", &hostname));
881 if ((GNUNET_YES == GNUNET_CONFIGURATION_have_value (cfg,
882 serviceName, "UNIXPATH"))
884 GNUNET_CONFIGURATION_get_value_string (cfg, serviceName, "UNIXPATH",
886 (0 < strlen (unixpath)))
888 /* probe UNIX support */
889 struct sockaddr_un s_un;
891 if (strlen (unixpath) >= sizeof (s_un.sun_path))
893 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
894 _("UNIXPATH `%s' too long, maximum length is %llu\n"),
895 unixpath, sizeof (s_un.sun_path));
896 GNUNET_free_non_null (hostname);
897 GNUNET_free (unixpath);
898 return GNUNET_SYSERR;
901 desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
904 if ((errno == ENOBUFS) ||
905 (errno == ENOMEM) || (errno == ENFILE) || (errno == EACCES))
907 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
908 GNUNET_free_non_null (hostname);
909 GNUNET_free (unixpath);
910 return GNUNET_SYSERR;
912 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
914 ("Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
915 serviceName, STRERROR (errno));
916 GNUNET_free (unixpath);
921 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
927 if ((port == 0) && (unixpath == NULL))
929 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
931 ("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
933 GNUNET_free_non_null (hostname);
934 return GNUNET_SYSERR;
938 saddrs = GNUNET_malloc (2 * sizeof (struct sockaddr *));
939 saddrlens = GNUNET_malloc (2 * sizeof (socklen_t));
940 add_unixpath (saddrs, saddrlens, unixpath);
941 GNUNET_free_non_null (unixpath);
942 GNUNET_free_non_null (hostname);
944 *addr_lens = saddrlens;
948 if (hostname != NULL)
951 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
952 "Resolving `%s' since that is where `%s' will bind to.\n",
953 hostname, serviceName);
955 memset (&hints, 0, sizeof (struct addrinfo));
957 hints.ai_family = AF_INET;
958 if ((0 != (ret = getaddrinfo (hostname,
959 NULL, &hints, &res))) || (res == NULL))
961 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
962 _("Failed to resolve `%s': %s\n"),
963 hostname, gai_strerror (ret));
964 GNUNET_free (hostname);
965 GNUNET_free_non_null (unixpath);
966 return GNUNET_SYSERR;
970 while (NULL != (pos = next))
973 if ((disablev6) && (pos->ai_family == AF_INET6))
979 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
980 _("Failed to find %saddress for `%s'.\n"),
981 disablev6 ? "IPv4 " : "", hostname);
983 GNUNET_free (hostname);
984 GNUNET_free_non_null (unixpath);
985 return GNUNET_SYSERR;
988 if (NULL != unixpath)
990 saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
991 saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
993 if (NULL != unixpath)
995 add_unixpath (saddrs, saddrlens, unixpath);
999 while (NULL != (pos = next))
1001 next = pos->ai_next;
1002 if ((disablev6) && (pos->ai_family == AF_INET6))
1004 if ((pos->ai_protocol != IPPROTO_TCP) && (pos->ai_protocol != 0))
1005 continue; /* not TCP */
1006 if ((pos->ai_socktype != SOCK_STREAM) && (pos->ai_socktype != 0))
1007 continue; /* huh? */
1009 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1010 "Service `%s' will bind to `%s'\n",
1011 serviceName, GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
1013 if (pos->ai_family == AF_INET)
1015 GNUNET_assert (pos->ai_addrlen == sizeof (struct sockaddr_in));
1016 saddrlens[i] = pos->ai_addrlen;
1017 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1018 memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1019 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1023 GNUNET_assert (pos->ai_family == AF_INET6);
1024 GNUNET_assert (pos->ai_addrlen == sizeof (struct sockaddr_in6));
1025 saddrlens[i] = pos->ai_addrlen;
1026 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1027 memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1028 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1032 GNUNET_free (hostname);
1038 /* will bind against everything, just set port */
1043 if (NULL != unixpath)
1046 saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
1047 saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
1048 if (NULL != unixpath)
1050 add_unixpath (saddrs, saddrlens, unixpath);
1053 saddrlens[i] = sizeof (struct sockaddr_in);
1054 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1055 #if HAVE_SOCKADDR_IN_SIN_LEN
1056 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
1058 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1059 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1065 if (NULL != unixpath)
1067 saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
1068 saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
1070 if (NULL != unixpath)
1072 add_unixpath (saddrs, saddrlens, unixpath);
1075 saddrlens[i] = sizeof (struct sockaddr_in6);
1076 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1077 #if HAVE_SOCKADDR_IN_SIN_LEN
1078 ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
1080 ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
1081 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1083 saddrlens[i] = sizeof (struct sockaddr_in);
1084 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1085 #if HAVE_SOCKADDR_IN_SIN_LEN
1086 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
1088 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1089 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1092 GNUNET_free_non_null (unixpath);
1094 *addr_lens = saddrlens;
1100 * Setup addr, addrlen, idle_timeout
1101 * based on configuration!
1103 * Configuration may specify:
1104 * - PORT (where to bind to for TCP)
1105 * - UNIXPATH (where to bind to for UNIX domain sockets)
1106 * - TIMEOUT (after how many ms does an inactive service timeout);
1107 * - DISABLEV6 (disable support for IPv6, otherwise we use dual-stack)
1108 * - BINDTO (hostname or IP address to bind to, otherwise we take everything)
1109 * - ACCEPT_FROM (only allow connections from specified IPv4 subnets)
1110 * - ACCEPT_FROM6 (only allow connections from specified IPv6 subnets)
1111 * - REJECT_FROM (disallow allow connections from specified IPv4 subnets)
1112 * - REJECT_FROM6 (disallow allow connections from specified IPv6 subnets)
1114 * @return GNUNET_OK if configuration succeeded
1117 setup_service (struct GNUNET_SERVICE_Context *sctx)
1119 struct GNUNET_TIME_Relative idleout;
1130 if (GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->serviceName, "TIMEOUT"))
1133 GNUNET_CONFIGURATION_get_value_time (sctx->cfg,
1135 "TIMEOUT", &idleout))
1137 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1138 _("Specified value for `%s' of service `%s' is invalid\n"),
1139 "TIMEOUT", sctx->serviceName);
1140 return GNUNET_SYSERR;
1142 sctx->timeout = idleout;
1145 sctx->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1147 if (GNUNET_CONFIGURATION_have_value (sctx->cfg,
1148 sctx->serviceName, "TOLERANT"))
1150 if (GNUNET_SYSERR ==
1151 (tolerant = GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg,
1155 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1156 _("Specified value for `%s' of service `%s' is invalid\n"),
1157 "TOLERANT", sctx->serviceName);
1158 return GNUNET_SYSERR;
1162 tolerant = GNUNET_NO;
1166 if ((NULL != (lpid = getenv ("LISTEN_PID"))) &&
1167 (1 == sscanf (lpid, "%u", &pid)) &&
1168 (getpid () == (pid_t) pid) &&
1169 (NULL != (nfds = getenv ("LISTEN_FDS"))) &&
1170 (1 == sscanf (nfds, "%u", &cnt)) &&
1171 (cnt > 0) && (cnt < FD_SETSIZE) && (cnt + 4 < FD_SETSIZE))
1174 GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle *) * (cnt + 1));
1177 flags = fcntl (3 + cnt, F_GETFD);
1179 (0 != (flags & FD_CLOEXEC)) ||
1181 (sctx->lsocks[cnt] = GNUNET_NETWORK_socket_box_native (3 + cnt))))
1183 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1185 ("Could not access pre-bound socket %u, will try to bind myself\n"),
1186 (unsigned int) 3 + cnt);
1188 while (sctx->lsocks[cnt] != NULL)
1189 GNUNET_break (0 == GNUNET_NETWORK_socket_close (sctx->lsocks[cnt++]));
1190 GNUNET_free (sctx->lsocks);
1191 sctx->lsocks = NULL;
1195 unsetenv ("LISTEN_PID");
1196 unsetenv ("LISTEN_FDS");
1200 if ((sctx->lsocks == NULL) &&
1202 GNUNET_SERVICE_get_server_addresses (sctx->serviceName,
1204 &sctx->addrs, &sctx->addrlens)))
1205 return GNUNET_SYSERR;
1206 sctx->require_found = tolerant ? GNUNET_NO : GNUNET_YES;
1207 sctx->match_uid = GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg,
1210 sctx->match_gid = GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg,
1213 process_acl4 (&sctx->v4_denied, sctx, "REJECT_FROM");
1214 process_acl4 (&sctx->v4_allowed, sctx, "ACCEPT_FROM");
1215 process_acl6 (&sctx->v6_denied, sctx, "REJECT_FROM6");
1216 process_acl6 (&sctx->v6_allowed, sctx, "ACCEPT_FROM6");
1223 * Get the name of the user that'll be used
1224 * to provide the service.
1227 get_user_name (struct GNUNET_SERVICE_Context *sctx)
1233 GNUNET_CONFIGURATION_get_value_filename (sctx->cfg,
1244 write_pid_file (struct GNUNET_SERVICE_Context *sctx, pid_t pid)
1252 if (NULL == (pif = get_pid_file_name (sctx)))
1253 return GNUNET_OK; /* no file desired */
1254 user = get_user_name (sctx);
1255 rdir = GNUNET_strdup (pif);
1256 len = strlen (rdir);
1257 while ((len > 0) && (rdir[len] != DIR_SEPARATOR))
1260 if (0 != ACCESS (rdir, F_OK))
1262 /* we get to create a directory -- and claim it
1264 GNUNET_DISK_directory_create (rdir);
1265 if ((user != NULL) && (0 < strlen (user)))
1266 GNUNET_DISK_file_change_owner (rdir, user);
1268 if (0 != ACCESS (rdir, W_OK | X_OK))
1270 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "access", rdir);
1272 GNUNET_free_non_null (user);
1274 return GNUNET_SYSERR;
1277 pidfd = FOPEN (pif, "w");
1280 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "fopen", pif);
1282 GNUNET_free_non_null (user);
1283 return GNUNET_SYSERR;
1285 if (0 > FPRINTF (pidfd, "%u", pid))
1286 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "fprintf", pif);
1287 GNUNET_break (0 == fclose (pidfd));
1288 if ((user != NULL) && (0 < strlen (user)))
1289 GNUNET_DISK_file_change_owner (pif, user);
1290 GNUNET_free_non_null (user);
1297 * Task run during shutdown.
1303 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1305 struct GNUNET_SERVER_Handle *server = cls;
1307 GNUNET_SERVER_destroy (server);
1312 * Initial task for the service.
1315 service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1317 struct GNUNET_SERVICE_Context *sctx = cls;
1320 GNUNET_RESOLVER_connect (sctx->cfg);
1321 if (sctx->lsocks != NULL)
1322 sctx->server = GNUNET_SERVER_create_with_sockets (&check_access,
1326 sctx->require_found);
1328 sctx->server = GNUNET_SERVER_create (&check_access,
1332 sctx->timeout, sctx->require_found);
1333 if (sctx->server == NULL)
1335 if (sctx->addrs != NULL)
1338 while (sctx->addrs[i] != NULL)
1340 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1341 _("Failed to start `%s' at `%s'\n"),
1343 GNUNET_a2s (sctx->addrs[i], sctx->addrlens[i]));
1347 sctx->ret = GNUNET_SYSERR;
1350 if (0 == (sctx->options & GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN))
1352 /* install a task that will kill the server
1353 * process if the scheduler ever gets a shutdown signal */
1354 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1355 &shutdown_task, sctx->server);
1357 sctx->my_handlers = GNUNET_malloc (sizeof (defhandlers));
1358 memcpy (sctx->my_handlers, defhandlers, sizeof (defhandlers));
1360 while ((sctx->my_handlers[i].callback != NULL))
1361 sctx->my_handlers[i++].callback_cls = sctx;
1362 GNUNET_SERVER_add_handlers (sctx->server, sctx->my_handlers);
1363 if (sctx->ready_confirm_fd != -1)
1365 GNUNET_break (1 == WRITE (sctx->ready_confirm_fd, ".", 1));
1366 GNUNET_break (0 == CLOSE (sctx->ready_confirm_fd));
1367 sctx->ready_confirm_fd = -1;
1368 write_pid_file (sctx, getpid ());
1370 if (sctx->addrs != NULL)
1373 while (sctx->addrs[i] != NULL)
1375 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1376 _("Service `%s' runs at %s\n"),
1378 GNUNET_a2s (sctx->addrs[i], sctx->addrlens[i]));
1382 sctx->task (sctx->task_cls, sctx->server, sctx->cfg);
1387 * Detach from terminal.
1390 detach_terminal (struct GNUNET_SERVICE_Context *sctx)
1397 if (0 != PIPE (filedes))
1399 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "pipe");
1400 return GNUNET_SYSERR;
1405 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fork");
1406 return GNUNET_SYSERR;
1413 GNUNET_break (0 == CLOSE (filedes[1]));
1415 if (1 != READ (filedes[0], &c, sizeof (char)))
1416 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "read");
1423 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1424 _("Service process failed to initialize\n"));
1427 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1428 _("Service process could not initialize server function\n"));
1431 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1432 _("Service process failed to report status\n"));
1435 exit (1); /* child reported error */
1437 GNUNET_break (0 == CLOSE (0));
1438 GNUNET_break (0 == CLOSE (1));
1439 GNUNET_break (0 == CLOSE (filedes[0]));
1440 nullfd = OPEN ("/dev/null", O_RDWR | O_APPEND);
1442 return GNUNET_SYSERR;
1443 /* set stdin/stdout to /dev/null */
1444 if ((dup2 (nullfd, 0) < 0) || (dup2 (nullfd, 1) < 0))
1446 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "dup2");
1447 (void) CLOSE (nullfd);
1448 return GNUNET_SYSERR;
1450 (void) CLOSE (nullfd);
1451 /* Detach from controlling terminal */
1454 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "setsid");
1455 sctx->ready_confirm_fd = filedes[1];
1457 /* FIXME: we probably need to do something else
1458 * elsewhere in order to fork the process itself... */
1469 set_user_id (struct GNUNET_SERVICE_Context *sctx)
1473 if (NULL == (user = get_user_name (sctx)))
1474 return GNUNET_OK; /* keep */
1479 pws = getpwnam (user);
1482 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1483 _("Cannot obtain information about user `%s': %s\n"),
1484 user, errno == 0 ? _("No such user") : STRERROR (errno));
1486 return GNUNET_SYSERR;
1488 if ((0 != setgid (pws->pw_gid)) || (0 != setegid (pws->pw_gid)) ||
1490 (0 != initgroups (user, pws->pw_gid)) ||
1492 (0 != setuid (pws->pw_uid)) || (0 != seteuid (pws->pw_uid)))
1494 if ((0 != setregid (pws->pw_gid, pws->pw_gid)) ||
1495 (0 != setreuid (pws->pw_uid, pws->pw_uid)))
1497 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1498 _("Cannot change user/group to `%s': %s\n"), user,
1501 return GNUNET_SYSERR;
1511 * Delete the PID file that was created by our parent.
1514 pid_file_delete (struct GNUNET_SERVICE_Context *sctx)
1516 char *pif = get_pid_file_name (sctx);
1519 return; /* no PID file */
1520 if (0 != UNLINK (pif))
1521 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", pif);
1527 * Run a standard GNUnet service startup sequence (initialize loggers
1528 * and configuration, parse options).
1530 * @param argc number of command line arguments
1531 * @param argv command line arguments
1532 * @param serviceName our service name
1533 * @param opt service options
1534 * @param task main task of the service
1535 * @param task_cls closure for task
1536 * @return GNUNET_SYSERR on error, GNUNET_OK
1537 * if we shutdown nicely
1540 GNUNET_SERVICE_run (int argc,
1542 const char *serviceName,
1543 enum GNUNET_SERVICE_Options opt,
1544 GNUNET_SERVICE_Main task, void *task_cls)
1546 #define HANDLE_ERROR do { err = 1; GNUNET_break (0); goto shutdown; } while (0)
1554 unsigned long long skew_offset;
1555 unsigned long long skew_variance;
1556 long long clock_offset;
1557 struct GNUNET_SERVICE_Context sctx;
1558 struct GNUNET_CONFIGURATION_Handle *cfg;
1560 struct GNUNET_GETOPT_CommandLineOption service_options[] = {
1561 GNUNET_GETOPT_OPTION_CFG_FILE (&cfg_fn),
1562 {'d', "daemonize", NULL,
1563 gettext_noop ("do daemonize (detach from terminal)"), 0,
1564 GNUNET_GETOPT_set_one, &do_daemonize},
1565 GNUNET_GETOPT_OPTION_HELP (serviceName),
1566 GNUNET_GETOPT_OPTION_LOGLEVEL (&loglev),
1567 GNUNET_GETOPT_OPTION_LOGFILE (&logfile),
1568 GNUNET_GETOPT_OPTION_VERSION (PACKAGE_VERSION),
1569 GNUNET_GETOPT_OPTION_END
1574 loglev = GNUNET_strdup ("WARNING");
1575 cfg_fn = GNUNET_strdup (GNUNET_DEFAULT_USER_CONFIG_FILE);
1576 memset (&sctx, 0, sizeof (sctx));
1578 sctx.ready_confirm_fd = -1;
1579 sctx.ret = GNUNET_OK;
1580 sctx.timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1582 sctx.task_cls = task_cls;
1583 sctx.serviceName = serviceName;
1584 sctx.cfg = cfg = GNUNET_CONFIGURATION_create ();
1585 /* setup subsystems */
1586 if (GNUNET_SYSERR == GNUNET_GETOPT_run (serviceName, service_options, argc,
1589 if (GNUNET_OK != GNUNET_log_setup (serviceName, loglev, logfile))
1591 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfg_fn))
1593 if (GNUNET_OK != setup_service (&sctx))
1595 if ((do_daemonize == 1) && (GNUNET_OK != detach_terminal (&sctx)))
1597 if (GNUNET_OK != set_user_id (&sctx))
1600 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1601 "Service `%s' runs with configuration from `%s'\n",
1602 serviceName, cfg_fn);
1605 GNUNET_CONFIGURATION_get_value_number (sctx.cfg, "testing", "skew_offset",
1608 GNUNET_CONFIGURATION_get_value_number (sctx.cfg, "testing",
1609 "skew_variance", &skew_variance)))
1611 clock_offset = skew_offset - skew_variance;
1612 GNUNET_TIME_set_offset (clock_offset);
1614 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Skewing clock by %dll\n",
1618 /* actually run service */
1619 GNUNET_SCHEDULER_run (&service_task, &sctx);
1622 if ((do_daemonize == 1) && (sctx.server != NULL))
1623 pid_file_delete (&sctx);
1624 GNUNET_free_non_null (sctx.my_handlers);
1627 if (sctx.ready_confirm_fd != -1)
1629 if (1 != WRITE (sctx.ready_confirm_fd, err ? "I" : "S", 1))
1630 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "write");
1631 GNUNET_break (0 == CLOSE (sctx.ready_confirm_fd));
1634 GNUNET_CONFIGURATION_destroy (cfg);
1636 if (sctx.addrs != NULL)
1637 while (sctx.addrs[i] != NULL)
1638 GNUNET_free (sctx.addrs[i++]);
1639 GNUNET_free_non_null (sctx.addrs);
1640 GNUNET_free_non_null (sctx.addrlens);
1641 GNUNET_free_non_null (logfile);
1642 GNUNET_free (loglev);
1643 GNUNET_free (cfg_fn);
1644 GNUNET_free_non_null (sctx.v4_denied);
1645 GNUNET_free_non_null (sctx.v6_denied);
1646 GNUNET_free_non_null (sctx.v4_allowed);
1647 GNUNET_free_non_null (sctx.v6_allowed);
1649 return err ? GNUNET_SYSERR : sctx.ret;
1654 * Run a service startup sequence within an existing
1655 * initialized system.
1657 * @param serviceName our service name
1658 * @param cfg configuration to use
1659 * @return NULL on error, service handle
1661 struct GNUNET_SERVICE_Context *
1662 GNUNET_SERVICE_start (const char *serviceName,
1663 const struct GNUNET_CONFIGURATION_Handle *cfg)
1666 struct GNUNET_SERVICE_Context *sctx;
1668 sctx = GNUNET_malloc (sizeof (struct GNUNET_SERVICE_Context));
1669 sctx->ready_confirm_fd = -1; /* no daemonizing */
1670 sctx->ret = GNUNET_OK;
1671 sctx->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1672 sctx->serviceName = serviceName;
1675 /* setup subsystems */
1676 if (GNUNET_OK != setup_service (sctx))
1678 GNUNET_SERVICE_stop (sctx);
1681 if (sctx->lsocks != NULL)
1682 sctx->server = GNUNET_SERVER_create_with_sockets (&check_access,
1686 sctx->require_found);
1688 sctx->server = GNUNET_SERVER_create (&check_access,
1692 sctx->timeout, sctx->require_found);
1694 if (NULL == sctx->server)
1696 GNUNET_SERVICE_stop (sctx);
1699 sctx->my_handlers = GNUNET_malloc (sizeof (defhandlers));
1700 memcpy (sctx->my_handlers, defhandlers, sizeof (defhandlers));
1702 while ((sctx->my_handlers[i].callback != NULL))
1703 sctx->my_handlers[i++].callback_cls = sctx;
1704 GNUNET_SERVER_add_handlers (sctx->server, sctx->my_handlers);
1709 * Obtain the server used by a service. Note that the server must NOT
1710 * be destroyed by the caller.
1712 * @param ctx the service context returned from the start function
1713 * @return handle to the server for this service, NULL if there is none
1715 struct GNUNET_SERVER_Handle *
1716 GNUNET_SERVICE_get_server (struct GNUNET_SERVICE_Context *ctx)
1723 * Stop a service that was started with "GNUNET_SERVICE_start".
1725 * @param sctx the service context returned from the start function
1728 GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Context *sctx)
1732 if (NULL != sctx->server)
1733 GNUNET_SERVER_destroy (sctx->server);
1734 GNUNET_free_non_null (sctx->my_handlers);
1735 if (sctx->addrs != NULL)
1738 while (sctx->addrs[i] != NULL)
1739 GNUNET_free (sctx->addrs[i++]);
1740 GNUNET_free (sctx->addrs);
1742 GNUNET_free_non_null (sctx->addrlens);
1743 GNUNET_free_non_null (sctx->v4_denied);
1744 GNUNET_free_non_null (sctx->v6_denied);
1745 GNUNET_free_non_null (sctx->v4_allowed);
1746 GNUNET_free_non_null (sctx->v6_allowed);
1751 /* end of service.c */