2 This file is part of GNUnet.
3 Copyright (C) 2016 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file util/service.c
23 * @brief functions related to starting services (redesign)
24 * @author Christian Grothoff
25 * @author Florian Dold
28 #include "gnunet_util_lib.h"
29 #include "gnunet_protocols.h"
30 #include "gnunet_constants.h"
31 #include "gnunet_resolver_service.h"
40 #define LOG(kind, ...) GNUNET_log_from (kind, "util-service", __VA_ARGS__)
42 #define LOG_STRERROR(kind, syscall) \
43 GNUNET_log_from_strerror (kind, "util-service", syscall)
45 #define LOG_STRERROR_FILE(kind, syscall, filename) \
46 GNUNET_log_from_strerror_file (kind, "util-service", syscall, filename)
50 * Information the service tracks per listen operation.
52 struct ServiceListenContext
58 struct ServiceListenContext *next;
63 struct ServiceListenContext *prev;
66 * Service this listen context belongs to.
68 struct GNUNET_SERVICE_Handle *sh;
71 * Socket we are listening on.
73 struct GNUNET_NETWORK_Handle *listen_socket;
76 * Task scheduled to do the listening.
78 struct GNUNET_SCHEDULER_Task *listen_task;
83 * Reasons why we might be suspended.
88 * We are running normally.
90 SUSPEND_STATE_NONE = 0,
93 * Application requested it.
95 SUSPEND_STATE_APP = 1,
98 * OS ran out of file descriptors.
100 SUSPEND_STATE_EMFILE = 2,
103 * Both reasons, APP and EMFILE apply.
105 SUSPEND_STATE_APP_AND_EMFILE = 3,
108 * Suspension because service was permanently shutdown.
110 SUSPEND_STATE_SHUTDOWN = 4
115 * Handle to a service.
117 struct GNUNET_SERVICE_Handle
122 const struct GNUNET_CONFIGURATION_Handle *cfg;
125 * Name of our service.
127 const char *service_name;
130 * Main service-specific task to run.
132 GNUNET_SERVICE_InitCallback service_init_cb;
135 * Function to call when clients connect.
137 GNUNET_SERVICE_ConnectHandler connect_cb;
140 * Function to call when clients disconnect / are disconnected.
142 GNUNET_SERVICE_DisconnectHandler disconnect_cb;
145 * Closure for @e service_init_cb, @e connect_cb, @e disconnect_cb.
150 * DLL of listen sockets used to accept new connections.
152 struct ServiceListenContext *slc_head;
155 * DLL of listen sockets used to accept new connections.
157 struct ServiceListenContext *slc_tail;
160 * Our clients, kept in a DLL.
162 struct GNUNET_SERVICE_Client *clients_head;
165 * Our clients, kept in a DLL.
167 struct GNUNET_SERVICE_Client *clients_tail;
170 * Message handlers to use for all clients.
172 struct GNUNET_MQ_MessageHandler *handlers;
175 * Closure for @e task.
180 * IPv4 addresses that are not allowed to connect.
182 struct GNUNET_STRINGS_IPv4NetworkPolicy *v4_denied;
185 * IPv6 addresses that are not allowed to connect.
187 struct GNUNET_STRINGS_IPv6NetworkPolicy *v6_denied;
190 * IPv4 addresses that are allowed to connect (if not
191 * set, all are allowed).
193 struct GNUNET_STRINGS_IPv4NetworkPolicy *v4_allowed;
196 * IPv6 addresses that are allowed to connect (if not
197 * set, all are allowed).
199 struct GNUNET_STRINGS_IPv6NetworkPolicy *v6_allowed;
202 * Do we require a matching UID for UNIX domain socket connections?
203 * #GNUNET_NO means that the UID does not have to match (however,
204 * @e match_gid may still impose other access control checks).
209 * Do we require a matching GID for UNIX domain socket connections?
210 * Ignored if @e match_uid is #GNUNET_YES. Note that this is about
211 * checking that the client's UID is in our group OR that the
212 * client's GID is our GID. If both "match_gid" and @e match_uid are
213 * #GNUNET_NO, all users on the local system have access.
218 * Are we suspended, and if so, why?
220 enum SuspendReason suspend_state;
225 enum GNUNET_SERVICE_Options options;
228 * If we are daemonizing, this FD is set to the
229 * pipe to the parent. Send '.' if we started
230 * ok, '!' if not. -1 if we are not daemonizing.
232 int ready_confirm_fd;
235 * Overall success/failure of the service start.
240 * If #GNUNET_YES, consider unknown message types an error where the
241 * client is disconnected.
248 * Handle to a client that is connected to a service.
250 struct GNUNET_SERVICE_Client
256 struct GNUNET_SERVICE_Client *next;
261 struct GNUNET_SERVICE_Client *prev;
264 * Service that this client belongs to.
266 struct GNUNET_SERVICE_Handle *sh;
269 * Socket of this client.
271 struct GNUNET_NETWORK_Handle *sock;
274 * Message queue for the client.
276 struct GNUNET_MQ_Handle *mq;
279 * Tokenizer we use for processing incoming data.
281 struct GNUNET_MessageStreamTokenizer *mst;
284 * Task that warns about missing calls to
285 * #GNUNET_SERVICE_client_continue().
287 struct GNUNET_SCHEDULER_Task *warn_task;
290 * Task run to finish dropping the client after the stack has
293 struct GNUNET_SCHEDULER_Task *drop_task;
296 * Task that receives data from the client to
297 * pass it to the handlers.
299 struct GNUNET_SCHEDULER_Task *recv_task;
302 * Task that transmit data to the client.
304 struct GNUNET_SCHEDULER_Task *send_task;
307 * Pointer to the message to be transmitted by @e send_task.
309 const struct GNUNET_MessageHeader *msg;
312 * User context value, value returned from
313 * the connect callback.
318 * Time when we last gave a message from this client
319 * to the application.
321 struct GNUNET_TIME_Absolute warn_start;
324 * Current position in @e msg at which we are transmitting.
329 * Persist the file handle for this client no matter what happens,
330 * force the OS to close once the process actually dies. Should only
331 * be used in special cases!
336 * Is this client a 'monitor' client that should not be counted
337 * when deciding on destroying the server during soft shutdown?
338 * (see also #GNUNET_SERVICE_start)
343 * Are we waiting for the application to call #GNUNET_SERVICE_client_continue()?
348 * Type of last message processed (for warn_no_receive_done).
355 * Check if any of the clients we have left are unrelated to
358 * @param sh service to check clients for
359 * @return #GNUNET_YES if we have non-monitoring clients left
362 have_non_monitor_clients (struct GNUNET_SERVICE_Handle *sh)
364 for (struct GNUNET_SERVICE_Client *client = sh->clients_head; NULL != client;
365 client = client->next)
367 if (client->is_monitor)
376 * Suspend accepting connections from the listen socket temporarily.
377 * Resume activity using #do_resume.
379 * @param sh service to stop accepting connections.
380 * @param sr reason for suspending accepting connections
383 do_suspend (struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
385 struct ServiceListenContext *slc;
387 GNUNET_assert (0 == (sh->suspend_state & sr));
388 sh->suspend_state |= sr;
389 for (slc = sh->slc_head; NULL != slc; slc = slc->next)
391 if (NULL != slc->listen_task)
393 GNUNET_SCHEDULER_cancel (slc->listen_task);
394 slc->listen_task = NULL;
401 * Shutdown task triggered when a service should be terminated.
402 * This considers active clients and the service options to see
403 * how this specific service is to be terminated, and depending
404 * on this proceeds with the shutdown logic.
406 * @param cls our `struct GNUNET_SERVICE_Handle`
409 service_shutdown (void *cls)
411 struct GNUNET_SERVICE_Handle *sh = cls;
415 case GNUNET_SERVICE_OPTION_NONE:
416 GNUNET_SERVICE_shutdown (sh);
418 case GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN:
419 /* This task should never be run if we are using
420 the manual shutdown. */
423 case GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN:
424 if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN))
425 do_suspend (sh, SUSPEND_STATE_SHUTDOWN);
426 if (GNUNET_NO == have_non_monitor_clients (sh))
427 GNUNET_SERVICE_shutdown (sh);
434 * Check if the given IP address is in the list of IP addresses.
436 * @param list a list of networks
437 * @param add the IP to check (in network byte order)
438 * @return #GNUNET_NO if the IP is not in the list, #GNUNET_YES if it it is
441 check_ipv4_listed (const struct GNUNET_STRINGS_IPv4NetworkPolicy *list,
442 const struct in_addr *add)
449 while ((0 != list[i].network.s_addr) || (0 != list[i].netmask.s_addr))
451 if ((add->s_addr & list[i].netmask.s_addr) ==
452 (list[i].network.s_addr & list[i].netmask.s_addr))
461 * Check if the given IP address is in the list of IP addresses.
463 * @param list a list of networks
464 * @param ip the IP to check (in network byte order)
465 * @return #GNUNET_NO if the IP is not in the list, #GNUNET_YES if it it is
468 check_ipv6_listed (const struct GNUNET_STRINGS_IPv6NetworkPolicy *list,
469 const struct in6_addr *ip)
478 while (0 != GNUNET_is_zero (&list[i].network))
480 for (j = 0; j < sizeof (struct in6_addr) / sizeof (int); j++)
481 if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) !=
482 (((int *) &list[i].network)[j] & ((int *) &list[i].netmask)[j]))
494 * Task run when we are ready to transmit data to the
497 * @param cls the `struct GNUNET_SERVICE_Client *` to send to
502 struct GNUNET_SERVICE_Client *client = cls;
507 LOG (GNUNET_ERROR_TYPE_DEBUG,
508 "service: sending message with type %u\n",
509 ntohs (client->msg->type));
512 client->send_task = NULL;
513 buf = (const char *) client->msg;
514 left = ntohs (client->msg->size) - client->msg_pos;
515 ret = GNUNET_NETWORK_socket_send (client->sock, &buf[client->msg_pos], left);
516 GNUNET_assert (ret <= (ssize_t) left);
519 LOG (GNUNET_ERROR_TYPE_DEBUG, "no data send");
520 GNUNET_MQ_inject_error (client->mq, GNUNET_MQ_ERROR_WRITE);
525 if ((EAGAIN == errno) || (EINTR == errno))
533 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "send");
534 LOG (GNUNET_ERROR_TYPE_DEBUG,
535 "socket send returned with error code %i",
537 GNUNET_MQ_inject_error (client->mq, GNUNET_MQ_ERROR_WRITE);
541 if (0 == client->msg_pos)
543 GNUNET_MQ_impl_send_in_flight (client->mq);
545 client->msg_pos += ret;
546 if (left > (size_t) ret)
548 GNUNET_assert (NULL == client->drop_task);
550 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
556 GNUNET_MQ_impl_send_continue (client->mq);
561 * Signature of functions implementing the sending functionality of a
564 * @param mq the message queue
565 * @param msg the message to send
566 * @param impl_state our `struct GNUNET_SERVICE_Client *`
569 service_mq_send (struct GNUNET_MQ_Handle *mq,
570 const struct GNUNET_MessageHeader *msg,
573 struct GNUNET_SERVICE_Client *client = impl_state;
576 if (NULL != client->drop_task)
577 return; /* we're going down right now, do not try to send */
578 GNUNET_assert (NULL == client->send_task);
579 LOG (GNUNET_ERROR_TYPE_DEBUG,
580 "Sending message of type %u and size %u to client\n",
586 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
594 * Implementation function that cancels the currently sent message.
596 * @param mq message queue
597 * @param impl_state state specific to the implementation
600 service_mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
602 struct GNUNET_SERVICE_Client *client = impl_state;
605 GNUNET_assert (0 == client->msg_pos);
607 GNUNET_SCHEDULER_cancel (client->send_task);
608 client->send_task = NULL;
613 * Generic error handler, called with the appropriate
614 * error code and the same closure specified at the creation of
616 * Not every message queue implementation supports an error handler.
618 * @param cls closure with our `struct GNUNET_SERVICE_Client`
619 * @param error error code
622 service_mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
624 struct GNUNET_SERVICE_Client *client = cls;
625 struct GNUNET_SERVICE_Handle *sh = client->sh;
627 if ((GNUNET_MQ_ERROR_NO_MATCH == error) && (GNUNET_NO == sh->require_found))
629 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
630 "No handler for message of type %u found\n",
631 (unsigned int) client->warn_type);
632 GNUNET_SERVICE_client_continue (client);
633 return; /* ignore error */
635 GNUNET_SERVICE_client_drop (client);
640 * Task run to warn about missing calls to #GNUNET_SERVICE_client_continue().
642 * @param cls our `struct GNUNET_SERVICE_Client *` to process more requests from
645 warn_no_client_continue (void *cls)
647 struct GNUNET_SERVICE_Client *client = cls;
651 client->warn_type); /* type should never be 0 here, as we don't use 0 */
652 client->warn_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
653 &warn_no_client_continue,
656 GNUNET_ERROR_TYPE_WARNING,
658 "Processing code for message of type %u did not call `GNUNET_SERVICE_client_continue' after %s\n"),
659 (unsigned int) client->warn_type,
660 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (
667 * Functions with this signature are called whenever a
668 * complete message is received by the tokenizer for a client.
670 * Do not call #GNUNET_MST_destroy() from within
671 * the scope of this callback.
673 * @param cls closure with the `struct GNUNET_SERVICE_Client *`
674 * @param message the actual message
675 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the client was dropped
678 service_client_mst_cb (void *cls, const struct GNUNET_MessageHeader *message)
680 struct GNUNET_SERVICE_Client *client = cls;
682 LOG (GNUNET_ERROR_TYPE_DEBUG,
683 "Received message of type %u and size %u from client\n",
684 ntohs (message->type),
685 ntohs (message->size));
686 GNUNET_assert (GNUNET_NO == client->needs_continue);
687 client->needs_continue = GNUNET_YES;
688 client->warn_type = ntohs (message->type);
689 client->warn_start = GNUNET_TIME_absolute_get ();
690 GNUNET_assert (NULL == client->warn_task);
691 client->warn_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
692 &warn_no_client_continue,
694 GNUNET_MQ_inject_message (client->mq, message);
695 if (NULL != client->drop_task)
696 return GNUNET_SYSERR;
702 * A client sent us data. Receive and process it. If we are done,
703 * reschedule this task.
705 * @param cls the `struct GNUNET_SERVICE_Client` that sent us data.
708 service_client_recv (void *cls)
710 struct GNUNET_SERVICE_Client *client = cls;
713 client->recv_task = NULL;
714 ret = GNUNET_MST_read (client->mst, client->sock, GNUNET_NO, GNUNET_YES);
715 if (GNUNET_SYSERR == ret)
717 /* client closed connection (or IO error) */
718 if (NULL == client->drop_task)
720 GNUNET_assert (GNUNET_NO == client->needs_continue);
721 GNUNET_SERVICE_client_drop (client);
725 if (GNUNET_NO == ret)
726 return; /* more messages in buffer, wait for application
727 to be done processing */
728 GNUNET_assert (GNUNET_OK == ret);
729 if (GNUNET_YES == client->needs_continue)
731 if (NULL != client->recv_task)
733 /* MST needs more data, re-schedule read job */
735 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
737 &service_client_recv,
743 * We have successfully accepted a connection from a client. Now
744 * setup the client (with the scheduler) and tell the application.
746 * @param sh service that accepted the client
747 * @param sock socket associated with the client
750 start_client (struct GNUNET_SERVICE_Handle *sh,
751 struct GNUNET_NETWORK_Handle *csock)
753 struct GNUNET_SERVICE_Client *client;
755 client = GNUNET_new (struct GNUNET_SERVICE_Client);
756 GNUNET_CONTAINER_DLL_insert (sh->clients_head, sh->clients_tail, client);
758 client->sock = csock;
759 client->mq = GNUNET_MQ_queue_for_callbacks (&service_mq_send,
764 &service_mq_error_handler,
766 client->mst = GNUNET_MST_create (&service_client_mst_cb, client);
767 if (NULL != sh->connect_cb)
768 client->user_context = sh->connect_cb (sh->cb_cls, client, client->mq);
769 GNUNET_MQ_set_handlers_closure (client->mq, client->user_context);
771 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
773 &service_client_recv,
779 * We have a client. Accept the incoming socket(s) (and reschedule
782 * @param cls the `struct ServiceListenContext` of the ready listen socket
785 accept_client (void *cls)
787 struct ServiceListenContext *slc = cls;
788 struct GNUNET_SERVICE_Handle *sh = slc->sh;
790 slc->listen_task = NULL;
793 struct GNUNET_NETWORK_Handle *sock;
794 const struct sockaddr_in *v4;
795 const struct sockaddr_in6 *v6;
796 struct sockaddr_storage sa;
800 addrlen = sizeof (sa);
801 sock = GNUNET_NETWORK_socket_accept (slc->listen_socket,
802 (struct sockaddr *) &sa,
807 do_suspend (sh, SUSPEND_STATE_EMFILE);
808 else if (EAGAIN != errno)
809 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "accept");
812 switch (sa.ss_family)
815 GNUNET_assert (addrlen == sizeof (struct sockaddr_in));
816 v4 = (const struct sockaddr_in *) &sa;
817 ok = (((NULL == sh->v4_allowed) ||
818 (check_ipv4_listed (sh->v4_allowed, &v4->sin_addr))) &&
819 ((NULL == sh->v4_denied) ||
820 (! check_ipv4_listed (sh->v4_denied, &v4->sin_addr))));
823 GNUNET_assert (addrlen == sizeof (struct sockaddr_in6));
824 v6 = (const struct sockaddr_in6 *) &sa;
825 ok = (((NULL == sh->v6_allowed) ||
826 (check_ipv6_listed (sh->v6_allowed, &v6->sin6_addr))) &&
827 ((NULL == sh->v6_denied) ||
828 (! check_ipv6_listed (sh->v6_denied, &v6->sin6_addr))));
832 ok = GNUNET_OK; /* controlled using file-system ACL now */
836 LOG (GNUNET_ERROR_TYPE_WARNING,
837 _ ("Unknown address family %d\n"),
843 LOG (GNUNET_ERROR_TYPE_DEBUG,
844 "Service rejected incoming connection from %s due to policy.\n",
845 GNUNET_a2s ((const struct sockaddr *) &sa, addrlen));
846 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
849 LOG (GNUNET_ERROR_TYPE_DEBUG,
850 "Service accepted incoming connection from %s.\n",
851 GNUNET_a2s ((const struct sockaddr *) &sa, addrlen));
852 start_client (slc->sh, sock);
854 if (0 != sh->suspend_state)
857 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
865 * Resume accepting connections from the listen socket.
867 * @param sh service to resume accepting connections.
868 * @param sr reason that is no longer causing the suspension,
869 * or #SUSPEND_STATE_NONE on first startup
872 do_resume (struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
874 struct ServiceListenContext *slc;
876 GNUNET_assert ((SUSPEND_STATE_NONE == sr) || (0 != (sh->suspend_state & sr)));
877 sh->suspend_state -= sr;
878 if (SUSPEND_STATE_NONE != sh->suspend_state)
880 for (slc = sh->slc_head; NULL != slc; slc = slc->next)
882 GNUNET_assert (NULL == slc->listen_task);
884 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
893 * First task run by any service. Initializes our shutdown task,
894 * starts the listening operation on our listen sockets and launches
895 * the custom logic of the application service.
897 * @param cls our `struct GNUNET_SERVICE_Handle`
900 service_main (void *cls)
902 struct GNUNET_SERVICE_Handle *sh = cls;
904 if (GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN != sh->options)
905 GNUNET_SCHEDULER_add_shutdown (&service_shutdown, sh);
906 do_resume (sh, SUSPEND_STATE_NONE);
908 if (-1 != sh->ready_confirm_fd)
910 GNUNET_break (1 == write (sh->ready_confirm_fd, ".", 1));
911 GNUNET_break (0 == close (sh->ready_confirm_fd));
912 sh->ready_confirm_fd = -1;
915 if (NULL != sh->service_init_cb)
916 sh->service_init_cb (sh->cb_cls, sh->cfg, sh);
921 * Parse an IPv4 access control list.
923 * @param ret location where to write the ACL (set)
924 * @param sh service context to use to get the configuration
925 * @param option name of the ACL option to parse
926 * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including
930 process_acl4 (struct GNUNET_STRINGS_IPv4NetworkPolicy **ret,
931 struct GNUNET_SERVICE_Handle *sh,
936 if (! GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
941 GNUNET_break (GNUNET_OK ==
942 GNUNET_CONFIGURATION_get_value_string (sh->cfg,
946 if (NULL == (*ret = GNUNET_STRINGS_parse_ipv4_policy (opt)))
948 LOG (GNUNET_ERROR_TYPE_WARNING,
949 _ ("Could not parse IPv4 network specification `%s' for `%s:%s'\n"),
954 return GNUNET_SYSERR;
962 * Parse an IPv6 access control list.
964 * @param ret location where to write the ACL (set)
965 * @param sh service context to use to get the configuration
966 * @param option name of the ACL option to parse
967 * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including
971 process_acl6 (struct GNUNET_STRINGS_IPv6NetworkPolicy **ret,
972 struct GNUNET_SERVICE_Handle *sh,
977 if (! GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
982 GNUNET_break (GNUNET_OK ==
983 GNUNET_CONFIGURATION_get_value_string (sh->cfg,
987 if (NULL == (*ret = GNUNET_STRINGS_parse_ipv6_policy (opt)))
989 LOG (GNUNET_ERROR_TYPE_WARNING,
990 _ ("Could not parse IPv6 network specification `%s' for `%s:%s'\n"),
995 return GNUNET_SYSERR;
1003 * Add the given UNIX domain path as an address to the
1004 * list (as the first entry).
1006 * @param saddrs array to update
1007 * @param saddrlens where to store the address length
1008 * @param unixpath path to add
1009 * @param abstract #GNUNET_YES to add an abstract UNIX domain socket. This
1010 * parameter is ignore on systems other than LINUX
1013 add_unixpath (struct sockaddr **saddrs,
1014 socklen_t *saddrlens,
1015 const char *unixpath,
1019 struct sockaddr_un *un;
1021 un = GNUNET_new (struct sockaddr_un);
1022 un->sun_family = AF_UNIX;
1023 GNUNET_strlcpy (un->sun_path, unixpath, sizeof (un->sun_path));
1025 if (GNUNET_YES == abstract)
1026 un->sun_path[0] = '\0';
1028 #if HAVE_SOCKADDR_UN_SUN_LEN
1029 un->sun_len = (u_char) sizeof (struct sockaddr_un);
1031 *saddrs = (struct sockaddr *) un;
1032 *saddrlens = sizeof (struct sockaddr_un);
1034 /* this function should never be called
1035 * unless AF_UNIX is defined! */
1042 * Get the list of addresses that a server for the given service
1045 * @param service_name name of the service
1046 * @param cfg configuration (which specifies the addresses)
1047 * @param addrs set (call by reference) to an array of pointers to the
1048 * addresses the server should bind to and listen on; the
1049 * array will be NULL-terminated (on success)
1050 * @param addr_lens set (call by reference) to an array of the lengths
1051 * of the respective `struct sockaddr` struct in the @a addrs
1052 * array (on success)
1053 * @return number of addresses found on success,
1054 * #GNUNET_SYSERR if the configuration
1055 * did not specify reasonable finding information or
1056 * if it specified a hostname that could not be resolved;
1057 * #GNUNET_NO if the number of addresses configured is
1058 * zero (in this case, `*addrs` and `*addr_lens` will be
1062 get_server_addresses (const char *service_name,
1063 const struct GNUNET_CONFIGURATION_Handle *cfg,
1064 struct sockaddr ***addrs,
1065 socklen_t **addr_lens)
1068 struct GNUNET_NETWORK_Handle *desc;
1069 unsigned long long port;
1071 struct addrinfo hints;
1072 struct addrinfo *res;
1073 struct addrinfo *pos;
1074 struct addrinfo *next;
1079 struct sockaddr **saddrs;
1080 socklen_t *saddrlens;
1086 disablev6 = GNUNET_NO;
1087 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
1089 GNUNET_CONFIGURATION_get_value_yesno (cfg, service_name, "DISABLEV6")))
1090 disablev6 = GNUNET_YES;
1093 if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT"))
1095 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg,
1100 LOG (GNUNET_ERROR_TYPE_ERROR,
1101 _ ("Require valid port number for service `%s' in configuration!\n"),
1106 LOG (GNUNET_ERROR_TYPE_ERROR,
1107 _ ("Require valid port number for service `%s' in configuration!\n"),
1109 return GNUNET_SYSERR;
1113 if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "BINDTO"))
1115 GNUNET_break (GNUNET_OK ==
1116 GNUNET_CONFIGURATION_get_value_string (cfg,
1125 abstract = GNUNET_NO;
1128 GNUNET_CONFIGURATION_have_value (cfg, service_name, "UNIXPATH")) &&
1129 (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg,
1133 (0 < strlen (unixpath)))
1135 /* probe UNIX support */
1136 struct sockaddr_un s_un;
1138 if (strlen (unixpath) >= sizeof (s_un.sun_path))
1140 LOG (GNUNET_ERROR_TYPE_WARNING,
1141 _ ("UNIXPATH `%s' too long, maximum length is %llu\n"),
1143 (unsigned long long) sizeof (s_un.sun_path));
1144 unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
1145 LOG (GNUNET_ERROR_TYPE_INFO, _ ("Using `%s' instead\n"), unixpath);
1148 abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
1150 "USE_ABSTRACT_SOCKETS");
1151 if (GNUNET_SYSERR == abstract)
1152 abstract = GNUNET_NO;
1154 if ((GNUNET_YES != abstract) &&
1155 (GNUNET_OK != GNUNET_DISK_directory_create_for_file (unixpath)))
1156 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "mkdir", unixpath);
1158 if (NULL != unixpath)
1160 desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
1163 if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
1166 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
1167 GNUNET_free_non_null (hostname);
1168 GNUNET_free (unixpath);
1169 return GNUNET_SYSERR;
1171 LOG (GNUNET_ERROR_TYPE_INFO,
1173 "Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
1176 GNUNET_free (unixpath);
1181 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
1187 if ((0 == port) && (NULL == unixpath))
1189 LOG (GNUNET_ERROR_TYPE_ERROR,
1191 "Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
1193 GNUNET_free_non_null (hostname);
1194 return GNUNET_SYSERR;
1198 saddrs = GNUNET_new_array (2, struct sockaddr *);
1199 saddrlens = GNUNET_new_array (2, socklen_t);
1200 add_unixpath (saddrs, saddrlens, unixpath, abstract);
1201 GNUNET_free_non_null (unixpath);
1202 GNUNET_free_non_null (hostname);
1204 *addr_lens = saddrlens;
1208 if (NULL != hostname)
1210 LOG (GNUNET_ERROR_TYPE_DEBUG,
1211 "Resolving `%s' since that is where `%s' will bind to.\n",
1214 memset (&hints, 0, sizeof (struct addrinfo));
1216 hints.ai_family = AF_INET;
1217 hints.ai_protocol = IPPROTO_TCP;
1218 if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
1221 LOG (GNUNET_ERROR_TYPE_ERROR,
1222 _ ("Failed to resolve `%s': %s\n"),
1224 gai_strerror (ret));
1225 GNUNET_free (hostname);
1226 GNUNET_free_non_null (unixpath);
1227 return GNUNET_SYSERR;
1231 while (NULL != (pos = next))
1233 next = pos->ai_next;
1234 if ((disablev6) && (pos->ai_family == AF_INET6))
1240 LOG (GNUNET_ERROR_TYPE_ERROR,
1241 _ ("Failed to find %saddress for `%s'.\n"),
1242 disablev6 ? "IPv4 " : "",
1245 GNUNET_free (hostname);
1246 GNUNET_free_non_null (unixpath);
1247 return GNUNET_SYSERR;
1250 if (NULL != unixpath)
1252 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1253 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1255 if (NULL != unixpath)
1257 add_unixpath (saddrs, saddrlens, unixpath, abstract);
1261 while (NULL != (pos = next))
1263 next = pos->ai_next;
1264 if ((disablev6) && (AF_INET6 == pos->ai_family))
1266 if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
1267 continue; /* not TCP */
1268 if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
1269 continue; /* huh? */
1270 LOG (GNUNET_ERROR_TYPE_DEBUG,
1271 "Service `%s' will bind to `%s'\n",
1273 GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
1274 if (AF_INET == pos->ai_family)
1276 GNUNET_assert (sizeof (struct sockaddr_in) == pos->ai_addrlen);
1277 saddrlens[i] = pos->ai_addrlen;
1278 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1279 GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1280 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1284 GNUNET_assert (AF_INET6 == pos->ai_family);
1285 GNUNET_assert (sizeof (struct sockaddr_in6) == pos->ai_addrlen);
1286 saddrlens[i] = pos->ai_addrlen;
1287 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1288 GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1289 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1293 GNUNET_free (hostname);
1299 /* will bind against everything, just set port */
1304 if (NULL != unixpath)
1307 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1308 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1309 if (NULL != unixpath)
1311 add_unixpath (saddrs, saddrlens, unixpath, abstract);
1314 saddrlens[i] = sizeof (struct sockaddr_in);
1315 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1316 #if HAVE_SOCKADDR_IN_SIN_LEN
1317 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
1319 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1320 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1326 if (NULL != unixpath)
1328 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1329 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1331 if (NULL != unixpath)
1333 add_unixpath (saddrs, saddrlens, unixpath, abstract);
1336 saddrlens[i] = sizeof (struct sockaddr_in6);
1337 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1338 #if HAVE_SOCKADDR_IN_SIN_LEN
1339 ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
1341 ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
1342 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1344 saddrlens[i] = sizeof (struct sockaddr_in);
1345 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1346 #if HAVE_SOCKADDR_IN_SIN_LEN
1347 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
1349 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1350 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1353 GNUNET_free_non_null (unixpath);
1355 *addr_lens = saddrlens;
1362 * Read listen sockets from the parent process (ARM).
1364 * @param sh service context to initialize
1365 * @return NULL-terminated array of sockets on success,
1366 * NULL if not ok (must bind yourself)
1368 static struct GNUNET_NETWORK_Handle **
1369 receive_sockets_from_parent (struct GNUNET_SERVICE_Handle *sh)
1371 static struct GNUNET_NETWORK_Handle **lsocks;
1372 const char *env_buf;
1378 env_buf = getenv ("GNUNET_OS_READ_LSOCKS");
1379 if ((NULL == env_buf) || (strlen (env_buf) <= 0))
1381 /* Using W32 API directly here, because this pipe will
1382 * never be used outside of this function, and it's just too much of a bother
1383 * to create a GNUnet API that boxes a HANDLE (the way it is done with socks)
1385 lsocks_pipe = (HANDLE) strtoul (env_buf, NULL, 10);
1386 if ((0 == lsocks_pipe) || (INVALID_HANDLE_VALUE == lsocks_pipe))
1395 ret = ReadFile (lsocks_pipe, &count, sizeof (count), &rd, NULL);
1396 if ((0 == ret) || (sizeof (count) != rd) || (0 == count))
1398 lsocks = GNUNET_new_array (count + 1, struct GNUNET_NETWORK_Handle *);
1401 for (i = 0; i < count; i++)
1403 WSAPROTOCOL_INFOA pi;
1407 ret = ReadFile (lsocks_pipe, &size, sizeof (size), &rd, NULL);
1408 if ((0 == ret) || (sizeof (size) != rd) || (sizeof (pi) != size))
1410 ret = ReadFile (lsocks_pipe, &pi, sizeof (pi), &rd, NULL);
1411 if ((0 == ret) || (sizeof (pi) != rd))
1413 s = WSASocketA (pi.iAddressFamily,
1418 WSA_FLAG_OVERLAPPED);
1419 lsocks[i] = GNUNET_NETWORK_socket_box_native (s);
1420 if (NULL == lsocks[i])
1422 else if (i == count - 1)
1427 lsocks[count] = NULL;
1430 CloseHandle (lsocks_pipe);
1434 LOG (GNUNET_ERROR_TYPE_ERROR,
1435 _ ("Could not access a pre-bound socket, will try to bind myself\n"));
1436 for (i = 0; (i < count) && (NULL != lsocks[i]); i++)
1437 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (lsocks[i]));
1438 GNUNET_free (lsocks);
1447 * Create and initialize a listen socket for the server.
1449 * @param server_addr address to listen on
1450 * @param socklen length of @a server_addr
1451 * @return NULL on error, otherwise the listen socket
1453 static struct GNUNET_NETWORK_Handle *
1454 open_listen_socket (const struct sockaddr *server_addr, socklen_t socklen)
1456 struct GNUNET_NETWORK_Handle *sock;
1460 switch (server_addr->sa_family)
1463 port = ntohs (((const struct sockaddr_in *) server_addr)->sin_port);
1466 port = ntohs (((const struct sockaddr_in6 *) server_addr)->sin6_port);
1476 sock = GNUNET_NETWORK_socket_create (server_addr->sa_family, SOCK_STREAM, 0);
1479 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
1483 /* bind the socket */
1484 if (GNUNET_OK != GNUNET_NETWORK_socket_bind (sock, server_addr, socklen))
1487 if (EADDRINUSE != errno)
1489 /* we don't log 'EADDRINUSE' here since an IPv4 bind may
1490 * fail if we already took the port on IPv6; if both IPv4 and
1491 * IPv6 binds fail, then our caller will log using the
1492 * errno preserved in 'eno' */
1494 LOG (GNUNET_ERROR_TYPE_ERROR,
1495 _ ("`%s' failed for port %d (%s).\n"),
1498 (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
1500 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "bind");
1506 LOG (GNUNET_ERROR_TYPE_WARNING,
1507 _ ("`%s' failed for port %d (%s): address already in use\n"),
1510 (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
1511 else if (AF_UNIX == server_addr->sa_family)
1513 LOG (GNUNET_ERROR_TYPE_WARNING,
1514 _ ("`%s' failed for `%s': address already in use\n"),
1516 GNUNET_a2s (server_addr, socklen));
1519 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
1523 if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
1525 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "listen");
1526 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
1531 LOG (GNUNET_ERROR_TYPE_DEBUG,
1532 "Server starts to listen on port %u.\n",
1539 * Setup service handle
1541 * Configuration may specify:
1542 * - PORT (where to bind to for TCP)
1543 * - UNIXPATH (where to bind to for UNIX domain sockets)
1544 * - DISABLEV6 (disable support for IPv6, otherwise we use dual-stack)
1545 * - BINDTO (hostname or IP address to bind to, otherwise we take everything)
1546 * - ACCEPT_FROM (only allow connections from specified IPv4 subnets)
1547 * - ACCEPT_FROM6 (only allow connections from specified IPv6 subnets)
1548 * - REJECT_FROM (disallow allow connections from specified IPv4 subnets)
1549 * - REJECT_FROM6 (disallow allow connections from specified IPv6 subnets)
1551 * @param sh service context to initialize
1552 * @return #GNUNET_OK if configuration succeeded
1555 setup_service (struct GNUNET_SERVICE_Handle *sh)
1558 struct GNUNET_NETWORK_Handle **lsocks;
1566 if (GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, "TOLERANT"))
1568 if (GNUNET_SYSERR ==
1569 (tolerant = GNUNET_CONFIGURATION_get_value_yesno (sh->cfg,
1573 LOG (GNUNET_ERROR_TYPE_ERROR,
1574 _ ("Specified value for `%s' of service `%s' is invalid\n"),
1577 return GNUNET_SYSERR;
1581 tolerant = GNUNET_NO;
1586 if ((NULL != (nfds = getenv ("LISTEN_FDS"))) &&
1587 (1 == sscanf (nfds, "%u%1s", &cnt, dummy)) && (cnt > 0) &&
1588 (cnt < FD_SETSIZE) && (cnt + 4 < FD_SETSIZE))
1590 lsocks = GNUNET_new_array (cnt + 1, struct GNUNET_NETWORK_Handle *);
1593 flags = fcntl (3 + cnt, F_GETFD);
1594 if ((flags < 0) || (0 != (flags & FD_CLOEXEC)) ||
1595 (NULL == (lsocks[cnt] = GNUNET_NETWORK_socket_box_native (3 + cnt))))
1597 LOG (GNUNET_ERROR_TYPE_ERROR,
1599 "Could not access pre-bound socket %u, will try to bind myself\n"),
1600 (unsigned int) 3 + cnt);
1602 while (NULL != lsocks[cnt])
1603 GNUNET_break (GNUNET_OK ==
1604 GNUNET_NETWORK_socket_close (lsocks[cnt++]));
1605 GNUNET_free (lsocks);
1610 unsetenv ("LISTEN_FDS");
1613 if (NULL != getenv ("GNUNET_OS_READ_LSOCKS"))
1615 lsocks = receive_sockets_from_parent (sh);
1616 putenv ("GNUNET_OS_READ_LSOCKS=");
1622 /* listen only on inherited sockets if we have any */
1623 struct GNUNET_NETWORK_Handle **ls;
1625 for (ls = lsocks; NULL != *ls; ls++)
1627 struct ServiceListenContext *slc;
1629 slc = GNUNET_new (struct ServiceListenContext);
1631 slc->listen_socket = *ls;
1632 GNUNET_CONTAINER_DLL_insert (sh->slc_head, sh->slc_tail, slc);
1634 GNUNET_free (lsocks);
1638 struct sockaddr **addrs;
1639 socklen_t *addrlens;
1642 num = get_server_addresses (sh->service_name, sh->cfg, &addrs, &addrlens);
1643 if (GNUNET_SYSERR == num)
1644 return GNUNET_SYSERR;
1646 for (int i = 0; i < num; i++)
1648 struct ServiceListenContext *slc;
1650 slc = GNUNET_new (struct ServiceListenContext);
1652 slc->listen_socket = open_listen_socket (addrs[i], addrlens[i]);
1653 GNUNET_free (addrs[i]);
1654 if (NULL == slc->listen_socket)
1656 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
1660 GNUNET_CONTAINER_DLL_insert (sh->slc_head, sh->slc_tail, slc);
1662 GNUNET_free_non_null (addrlens);
1663 GNUNET_free_non_null (addrs);
1664 if ((0 != num) && (NULL == sh->slc_head))
1666 /* All attempts to bind failed, hard failure */
1668 GNUNET_ERROR_TYPE_ERROR,
1670 "Could not bind to any of the ports I was supposed to, refusing to run!\n"));
1671 return GNUNET_SYSERR;
1675 sh->require_found = tolerant ? GNUNET_NO : GNUNET_YES;
1676 sh->match_uid = GNUNET_CONFIGURATION_get_value_yesno (sh->cfg,
1679 sh->match_gid = GNUNET_CONFIGURATION_get_value_yesno (sh->cfg,
1682 process_acl4 (&sh->v4_denied, sh, "REJECT_FROM");
1683 process_acl4 (&sh->v4_allowed, sh, "ACCEPT_FROM");
1684 process_acl6 (&sh->v6_denied, sh, "REJECT_FROM6");
1685 process_acl6 (&sh->v6_allowed, sh, "ACCEPT_FROM6");
1691 * Get the name of the user that'll be used
1692 * to provide the service.
1694 * @param sh service context
1695 * @return value of the 'USERNAME' option
1698 get_user_name (struct GNUNET_SERVICE_Handle *sh)
1702 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (sh->cfg,
1714 * @param sh service context
1715 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1718 set_user_id (struct GNUNET_SERVICE_Handle *sh)
1722 if (NULL == (user = get_user_name (sh)))
1723 return GNUNET_OK; /* keep */
1728 pws = getpwnam (user);
1731 LOG (GNUNET_ERROR_TYPE_ERROR,
1732 _ ("Cannot obtain information about user `%s': %s\n"),
1734 errno == 0 ? _ ("No such user") : strerror (errno));
1736 return GNUNET_SYSERR;
1738 if ((0 != setgid (pws->pw_gid)) || (0 != setegid (pws->pw_gid)) ||
1740 (0 != initgroups (user, pws->pw_gid)) ||
1742 (0 != setuid (pws->pw_uid)) || (0 != seteuid (pws->pw_uid)))
1744 if ((0 != setregid (pws->pw_gid, pws->pw_gid)) ||
1745 (0 != setreuid (pws->pw_uid, pws->pw_uid)))
1747 LOG (GNUNET_ERROR_TYPE_ERROR,
1748 _ ("Cannot change user/group to `%s': %s\n"),
1752 return GNUNET_SYSERR;
1762 * Get the name of the file where we will
1763 * write the PID of the service.
1765 * @param sh service context
1766 * @return name of the file for the process ID
1769 get_pid_file_name (struct GNUNET_SERVICE_Handle *sh)
1773 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (sh->cfg,
1783 * Delete the PID file that was created by our parent.
1785 * @param sh service context
1788 pid_file_delete (struct GNUNET_SERVICE_Handle *sh)
1790 char *pif = get_pid_file_name (sh);
1793 return; /* no PID file */
1794 if (0 != unlink (pif))
1795 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", pif);
1801 * Detach from terminal.
1803 * @param sh service context
1804 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1807 detach_terminal (struct GNUNET_SERVICE_Handle *sh)
1814 if (0 != pipe (filedes))
1816 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "pipe");
1817 return GNUNET_SYSERR;
1822 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fork");
1823 return GNUNET_SYSERR;
1830 GNUNET_break (0 == close (filedes[1]));
1832 if (1 != read (filedes[0], &c, sizeof (char)))
1833 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "read");
1840 LOG (GNUNET_ERROR_TYPE_INFO,
1841 _ ("Service process failed to initialize\n"));
1844 LOG (GNUNET_ERROR_TYPE_INFO,
1845 _ ("Service process could not initialize server function\n"));
1848 LOG (GNUNET_ERROR_TYPE_INFO,
1849 _ ("Service process failed to report status\n"));
1852 exit (1); /* child reported error */
1854 GNUNET_break (0 == close (0));
1855 GNUNET_break (0 == close (1));
1856 GNUNET_break (0 == close (filedes[0]));
1857 nullfd = open ("/dev/null", O_RDWR | O_APPEND);
1859 return GNUNET_SYSERR;
1860 /* set stdin/stdout to /dev/null */
1861 if ((dup2 (nullfd, 0) < 0) || (dup2 (nullfd, 1) < 0))
1863 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "dup2");
1864 (void) close (nullfd);
1865 return GNUNET_SYSERR;
1867 (void) close (nullfd);
1868 /* Detach from controlling terminal */
1871 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "setsid");
1872 sh->ready_confirm_fd = filedes[1];
1874 /* FIXME: we probably need to do something else
1875 * elsewhere in order to fork the process itself... */
1883 * Tear down the service, closing the listen sockets and
1886 * @param sh handle to the service to tear down.
1889 teardown_service (struct GNUNET_SERVICE_Handle *sh)
1891 struct ServiceListenContext *slc;
1893 GNUNET_free_non_null (sh->v4_denied);
1894 GNUNET_free_non_null (sh->v6_denied);
1895 GNUNET_free_non_null (sh->v4_allowed);
1896 GNUNET_free_non_null (sh->v6_allowed);
1897 while (NULL != (slc = sh->slc_head))
1899 GNUNET_CONTAINER_DLL_remove (sh->slc_head, sh->slc_tail, slc);
1900 if (NULL != slc->listen_task)
1901 GNUNET_SCHEDULER_cancel (slc->listen_task);
1902 GNUNET_break (GNUNET_OK ==
1903 GNUNET_NETWORK_socket_close (slc->listen_socket));
1910 * Function to return link to AGPL source upon request.
1912 * @param cls closure with the identification of the client
1913 * @param msg AGPL request
1916 return_agpl (void *cls, const struct GNUNET_MessageHeader *msg)
1918 struct GNUNET_SERVICE_Client *client = cls;
1919 struct GNUNET_MQ_Handle *mq;
1920 struct GNUNET_MQ_Envelope *env;
1921 struct GNUNET_MessageHeader *res;
1925 slen = strlen (GNUNET_AGPL_URL) + 1;
1926 env = GNUNET_MQ_msg_extra (res, GNUNET_MESSAGE_TYPE_RESPONSE_AGPL, slen);
1927 memcpy (&res[1], GNUNET_AGPL_URL, slen);
1928 mq = GNUNET_SERVICE_client_get_mq (client);
1929 GNUNET_MQ_send (mq, env);
1930 GNUNET_SERVICE_client_continue (client);
1935 * Low-level function to start a service if the scheduler
1936 * is already running. Should only be used directly in
1939 * The function will launch the service with the name @a service_name
1940 * using the @a service_options to configure its shutdown
1941 * behavior. When clients connect or disconnect, the respective
1942 * @a connect_cb or @a disconnect_cb functions will be called. For
1943 * messages received from the clients, the respective @a handlers will
1944 * be invoked; for the closure of the handlers we use the return value
1945 * from the @a connect_cb invocation of the respective client.
1947 * Each handler MUST call #GNUNET_SERVICE_client_continue() after each
1948 * message to receive further messages from this client. If
1949 * #GNUNET_SERVICE_client_continue() is not called within a short
1950 * time, a warning will be logged. If delays are expected, services
1951 * should call #GNUNET_SERVICE_client_disable_continue_warning() to
1952 * disable the warning.
1954 * Clients sending invalid messages (based on @a handlers) will be
1955 * dropped. Additionally, clients can be dropped at any time using
1956 * #GNUNET_SERVICE_client_drop().
1958 * The service must be stopped using #GNUNET_SERVICE_stop().
1960 * @param service_name name of the service to run
1961 * @param cfg configuration to use
1962 * @param connect_cb function to call whenever a client connects
1963 * @param disconnect_cb function to call whenever a client disconnects
1964 * @param cls closure argument for @a connect_cb and @a disconnect_cb
1965 * @param handlers NULL-terminated array of message handlers for the service,
1966 * the closure will be set to the value returned by
1967 * the @a connect_cb for the respective connection
1968 * @return NULL on error
1970 struct GNUNET_SERVICE_Handle *
1971 GNUNET_SERVICE_start (const char *service_name,
1972 const struct GNUNET_CONFIGURATION_Handle *cfg,
1973 GNUNET_SERVICE_ConnectHandler connect_cb,
1974 GNUNET_SERVICE_DisconnectHandler disconnect_cb,
1976 const struct GNUNET_MQ_MessageHandler *handlers)
1978 struct GNUNET_SERVICE_Handle *sh;
1980 sh = GNUNET_new (struct GNUNET_SERVICE_Handle);
1981 sh->service_name = service_name;
1983 sh->connect_cb = connect_cb;
1984 sh->disconnect_cb = disconnect_cb;
1986 sh->handlers = GNUNET_MQ_copy_handlers2 (handlers, &return_agpl, NULL);
1987 if (GNUNET_OK != setup_service (sh))
1989 GNUNET_free_non_null (sh->handlers);
1993 do_resume (sh, SUSPEND_STATE_NONE);
1999 * Stops a service that was started with #GNUNET_SERVICE_start().
2001 * @param srv service to stop
2004 GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Handle *srv)
2006 struct GNUNET_SERVICE_Client *client;
2008 GNUNET_SERVICE_suspend (srv);
2009 while (NULL != (client = srv->clients_head))
2010 GNUNET_SERVICE_client_drop (client);
2011 teardown_service (srv);
2012 GNUNET_free_non_null (srv->handlers);
2018 * Creates the "main" function for a GNUnet service. You
2019 * should almost always use the #GNUNET_SERVICE_MAIN macro
2020 * instead of calling this function directly (except
2021 * for ARM, which should call this function directly).
2023 * The function will launch the service with the name @a service_name
2024 * using the @a service_options to configure its shutdown
2025 * behavior. Once the service is ready, the @a init_cb will be called
2026 * for service-specific initialization. @a init_cb will be given the
2027 * service handler which can be used to control the service's
2028 * availability. When clients connect or disconnect, the respective
2029 * @a connect_cb or @a disconnect_cb functions will be called. For
2030 * messages received from the clients, the respective @a handlers will
2031 * be invoked; for the closure of the handlers we use the return value
2032 * from the @a connect_cb invocation of the respective client.
2034 * Each handler MUST call #GNUNET_SERVICE_client_continue() after each
2035 * message to receive further messages from this client. If
2036 * #GNUNET_SERVICE_client_continue() is not called within a short
2037 * time, a warning will be logged. If delays are expected, services
2038 * should call #GNUNET_SERVICE_client_disable_continue_warning() to
2039 * disable the warning.
2041 * Clients sending invalid messages (based on @a handlers) will be
2042 * dropped. Additionally, clients can be dropped at any time using
2043 * #GNUNET_SERVICE_client_drop().
2045 * @param argc number of command-line arguments in @a argv
2046 * @param argv array of command-line arguments
2047 * @param service_name name of the service to run
2048 * @param options options controlling shutdown of the service
2049 * @param service_init_cb function to call once the service is ready
2050 * @param connect_cb function to call whenever a client connects
2051 * @param disconnect_cb function to call whenever a client disconnects
2052 * @param cls closure argument for @a service_init_cb, @a connect_cb and @a disconnect_cb
2053 * @param handlers NULL-terminated array of message handlers for the service,
2054 * the closure will be set to the value returned by
2055 * the @a connect_cb for the respective connection
2056 * @return 0 on success, non-zero on error
2059 GNUNET_SERVICE_run_ (int argc,
2061 const char *service_name,
2062 enum GNUNET_SERVICE_Options options,
2063 GNUNET_SERVICE_InitCallback service_init_cb,
2064 GNUNET_SERVICE_ConnectHandler connect_cb,
2065 GNUNET_SERVICE_DisconnectHandler disconnect_cb,
2067 const struct GNUNET_MQ_MessageHandler *handlers)
2069 struct GNUNET_SERVICE_Handle sh;
2071 char *opt_cfg_filename;
2076 unsigned long long skew_offset;
2077 unsigned long long skew_variance;
2078 long long clock_offset;
2079 struct GNUNET_CONFIGURATION_Handle *cfg;
2083 struct GNUNET_GETOPT_CommandLineOption service_options[] =
2084 {GNUNET_GETOPT_option_cfgfile (&opt_cfg_filename),
2085 GNUNET_GETOPT_option_flag ('d',
2088 "do daemonize (detach from terminal)"),
2090 GNUNET_GETOPT_option_help (NULL),
2091 GNUNET_GETOPT_option_loglevel (&loglev),
2092 GNUNET_GETOPT_option_logfile (&logfile),
2093 GNUNET_GETOPT_option_version (PACKAGE_VERSION " " VCS_VERSION),
2094 GNUNET_GETOPT_OPTION_END};
2097 memset (&sh, 0, sizeof (sh));
2098 xdg = getenv ("XDG_CONFIG_HOME");
2100 GNUNET_asprintf (&cfg_filename,
2104 GNUNET_OS_project_data_get ()->config_file);
2107 GNUNET_strdup (GNUNET_OS_project_data_get ()->user_config_file);
2108 sh.ready_confirm_fd = -1;
2109 sh.options = options;
2110 sh.cfg = cfg = GNUNET_CONFIGURATION_create ();
2111 sh.service_init_cb = service_init_cb;
2112 sh.connect_cb = connect_cb;
2113 sh.disconnect_cb = disconnect_cb;
2115 sh.handlers = GNUNET_MQ_copy_handlers (handlers);
2116 sh.service_name = service_name;
2118 /* setup subsystems */
2121 opt_cfg_filename = NULL;
2123 ret = GNUNET_GETOPT_run (service_name, service_options, argc, argv);
2124 if (GNUNET_SYSERR == ret)
2126 if (GNUNET_NO == ret)
2131 if (GNUNET_OK != GNUNET_log_setup (service_name, loglev, logfile))
2136 if (NULL != opt_cfg_filename)
2138 if ((GNUNET_YES != GNUNET_DISK_file_test (opt_cfg_filename)) ||
2139 (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, opt_cfg_filename)))
2141 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2142 _ ("Malformed configuration file `%s', exit ...\n"),
2149 if (GNUNET_YES == GNUNET_DISK_file_test (cfg_filename))
2151 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, cfg_filename))
2153 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2154 _ ("Malformed configuration file `%s', exit ...\n"),
2161 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, NULL))
2163 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2164 _ ("Malformed configuration, exit ...\n"));
2169 if (GNUNET_OK != setup_service (&sh))
2171 if ((1 == do_daemonize) && (GNUNET_OK != detach_terminal (&sh)))
2176 if (GNUNET_OK != set_user_id (&sh))
2178 LOG (GNUNET_ERROR_TYPE_DEBUG,
2179 "Service `%s' runs with configuration from `%s'\n",
2181 (NULL != opt_cfg_filename) ? opt_cfg_filename : cfg_filename);
2182 if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (sh.cfg,
2186 (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (sh.cfg,
2191 clock_offset = skew_offset - skew_variance;
2192 GNUNET_TIME_set_offset (clock_offset);
2193 LOG (GNUNET_ERROR_TYPE_DEBUG, "Skewing clock by %dll ms\n", clock_offset);
2195 GNUNET_RESOLVER_connect (sh.cfg);
2197 /* actually run service */
2199 GNUNET_SCHEDULER_run (&service_main, &sh);
2201 if (1 == do_daemonize)
2202 pid_file_delete (&sh);
2205 if (-1 != sh.ready_confirm_fd)
2207 if (1 != write (sh.ready_confirm_fd, err ? "I" : "S", 1))
2208 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "write");
2209 GNUNET_break (0 == close (sh.ready_confirm_fd));
2215 if ((GNUNET_YES == GNUNET_CONFIGURATION_have_value (sh.cfg,
2218 (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (sh.cfg,
2226 GAUGER (service_name, counter, mi.usmblks, "blocks");
2227 GNUNET_free (counter);
2231 teardown_service (&sh);
2232 GNUNET_free_non_null (sh.handlers);
2233 GNUNET_SPEEDUP_stop_ ();
2234 GNUNET_CONFIGURATION_destroy (cfg);
2235 GNUNET_free_non_null (logfile);
2236 GNUNET_free_non_null (loglev);
2237 GNUNET_free (cfg_filename);
2238 GNUNET_free_non_null (opt_cfg_filename);
2240 return err ? GNUNET_SYSERR : sh.ret;
2245 * Suspend accepting connections from the listen socket temporarily.
2246 * Resume activity using #GNUNET_SERVICE_resume.
2248 * @param sh service to stop accepting connections.
2251 GNUNET_SERVICE_suspend (struct GNUNET_SERVICE_Handle *sh)
2253 do_suspend (sh, SUSPEND_STATE_APP);
2258 * Resume accepting connections from the listen socket.
2260 * @param sh service to resume accepting connections.
2263 GNUNET_SERVICE_resume (struct GNUNET_SERVICE_Handle *sh)
2265 do_resume (sh, SUSPEND_STATE_APP);
2270 * Task run to resume receiving data from the client after
2271 * the client called #GNUNET_SERVICE_client_continue().
2273 * @param cls our `struct GNUNET_SERVICE_Client`
2276 resume_client_receive (void *cls)
2278 struct GNUNET_SERVICE_Client *c = cls;
2281 c->recv_task = NULL;
2282 /* first, check if there is still something in the buffer */
2283 ret = GNUNET_MST_next (c->mst, GNUNET_YES);
2284 if (GNUNET_SYSERR == ret)
2286 if (NULL == c->drop_task)
2287 GNUNET_SERVICE_client_drop (c);
2290 if (GNUNET_NO == ret)
2291 return; /* done processing, wait for more later */
2292 GNUNET_assert (GNUNET_OK == ret);
2293 if (GNUNET_YES == c->needs_continue)
2294 return; /* #GNUNET_MST_next() did give a message to the client */
2295 /* need to receive more data from the network first */
2296 if (NULL != c->recv_task)
2298 c->recv_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
2300 &service_client_recv,
2306 * Continue receiving further messages from the given client.
2307 * Must be called after each message received.
2309 * @param c the client to continue receiving from
2312 GNUNET_SERVICE_client_continue (struct GNUNET_SERVICE_Client *c)
2314 GNUNET_assert (NULL == c->drop_task);
2315 GNUNET_assert (GNUNET_YES == c->needs_continue);
2316 GNUNET_assert (NULL == c->recv_task);
2317 c->needs_continue = GNUNET_NO;
2318 if (NULL != c->warn_task)
2320 GNUNET_SCHEDULER_cancel (c->warn_task);
2321 c->warn_task = NULL;
2323 c->recv_task = GNUNET_SCHEDULER_add_now (&resume_client_receive, c);
2328 * Disable the warning the server issues if a message is not
2329 * acknowledged in a timely fashion. Use this call if a client is
2330 * intentionally delayed for a while. Only applies to the current
2333 * @param c client for which to disable the warning
2336 GNUNET_SERVICE_client_disable_continue_warning (struct GNUNET_SERVICE_Client *c)
2338 GNUNET_break (NULL != c->warn_task);
2339 if (NULL != c->warn_task)
2341 GNUNET_SCHEDULER_cancel (c->warn_task);
2342 c->warn_task = NULL;
2348 * Asynchronously finish dropping the client.
2350 * @param cls the `struct GNUNET_SERVICE_Client`.
2353 finish_client_drop (void *cls)
2355 struct GNUNET_SERVICE_Client *c = cls;
2356 struct GNUNET_SERVICE_Handle *sh = c->sh;
2358 c->drop_task = NULL;
2359 GNUNET_assert (NULL == c->send_task);
2360 GNUNET_assert (NULL == c->recv_task);
2361 GNUNET_assert (NULL == c->warn_task);
2362 GNUNET_MST_destroy (c->mst);
2363 GNUNET_MQ_destroy (c->mq);
2364 if (GNUNET_NO == c->persist)
2366 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (c->sock));
2367 if ((0 != (SUSPEND_STATE_EMFILE & sh->suspend_state)) &&
2368 (0 == (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)))
2369 do_resume (sh, SUSPEND_STATE_EMFILE);
2373 GNUNET_NETWORK_socket_free_memory_only_ (c->sock);
2376 if ((0 != (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)) &&
2377 (GNUNET_NO == have_non_monitor_clients (sh)))
2378 GNUNET_SERVICE_shutdown (sh);
2383 * Ask the server to disconnect from the given client. This is the
2384 * same as returning #GNUNET_SYSERR within the check procedure when
2385 * handling a message, wexcept that it allows dropping of a client even
2386 * when not handling a message from that client. The `disconnect_cb`
2387 * will be called on @a c even if the application closes the connection
2388 * using this function.
2390 * @param c client to disconnect now
2393 GNUNET_SERVICE_client_drop (struct GNUNET_SERVICE_Client *c)
2395 struct GNUNET_SERVICE_Handle *sh = c->sh;
2397 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2398 "Client dropped: %p (MQ: %p)\n",
2403 void *backtrace_array[MAX_TRACE_DEPTH];
2404 int num_backtrace_strings = backtrace (backtrace_array, MAX_TRACE_DEPTH);
2405 char **backtrace_strings =
2406 backtrace_symbols (backtrace_array, t->num_backtrace_strings);
2407 for (unsigned int i = 0; i < num_backtrace_strings; i++)
2408 LOG (GNUNET_ERROR_TYPE_DEBUG,
2409 "client drop trace %u: %s\n",
2411 backtrace_strings[i]);
2414 if (NULL != c->drop_task)
2416 /* asked to drop twice! */
2420 GNUNET_CONTAINER_DLL_remove (sh->clients_head, sh->clients_tail, c);
2421 if (NULL != sh->disconnect_cb)
2422 sh->disconnect_cb (sh->cb_cls, c, c->user_context);
2423 if (NULL != c->warn_task)
2425 GNUNET_SCHEDULER_cancel (c->warn_task);
2426 c->warn_task = NULL;
2428 if (NULL != c->recv_task)
2430 GNUNET_SCHEDULER_cancel (c->recv_task);
2431 c->recv_task = NULL;
2433 if (NULL != c->send_task)
2435 GNUNET_SCHEDULER_cancel (c->send_task);
2436 c->send_task = NULL;
2438 c->drop_task = GNUNET_SCHEDULER_add_now (&finish_client_drop, c);
2443 * Explicitly stops the service.
2445 * @param sh server to shutdown
2448 GNUNET_SERVICE_shutdown (struct GNUNET_SERVICE_Handle *sh)
2450 struct GNUNET_SERVICE_Client *client;
2452 if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN))
2453 do_suspend (sh, SUSPEND_STATE_SHUTDOWN);
2454 while (NULL != (client = sh->clients_head))
2455 GNUNET_SERVICE_client_drop (client);
2460 * Set the 'monitor' flag on this client. Clients which have been
2461 * marked as 'monitors' won't prevent the server from shutting down
2462 * once #GNUNET_SERVICE_stop_listening() has been invoked. The idea is
2463 * that for "normal" clients we likely want to allow them to process
2464 * their requests; however, monitor-clients are likely to 'never'
2465 * disconnect during shutdown and thus will not be considered when
2466 * determining if the server should continue to exist after
2467 * shutdown has been triggered.
2469 * @param c client to mark as a monitor
2472 GNUNET_SERVICE_client_mark_monitor (struct GNUNET_SERVICE_Client *c)
2474 c->is_monitor = GNUNET_YES;
2475 if (((0 != (SUSPEND_STATE_SHUTDOWN & c->sh->suspend_state)) &&
2476 (GNUNET_NO == have_non_monitor_clients (c->sh))))
2477 GNUNET_SERVICE_shutdown (c->sh);
2482 * Set the persist option on this client. Indicates that the
2483 * underlying socket or fd should never really be closed. Used for
2484 * indicating process death.
2486 * @param c client to persist the socket (never to be closed)
2489 GNUNET_SERVICE_client_persist (struct GNUNET_SERVICE_Client *c)
2491 c->persist = GNUNET_YES;
2496 * Obtain the message queue of @a c. Convenience function.
2498 * @param c the client to continue receiving from
2499 * @return the message queue of @a c
2501 struct GNUNET_MQ_Handle *
2502 GNUNET_SERVICE_client_get_mq (struct GNUNET_SERVICE_Client *c)
2508 /* end of service_new.c */