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 {
56 struct ServiceListenContext *next;
61 struct ServiceListenContext *prev;
64 * Service this listen context belongs to.
66 struct GNUNET_SERVICE_Handle *sh;
69 * Socket we are listening on.
71 struct GNUNET_NETWORK_Handle *listen_socket;
74 * Task scheduled to do the listening.
76 struct GNUNET_SCHEDULER_Task *listen_task;
81 * Reasons why we might be suspended.
85 * We are running normally.
87 SUSPEND_STATE_NONE = 0,
90 * Application requested it.
92 SUSPEND_STATE_APP = 1,
95 * OS ran out of file descriptors.
97 SUSPEND_STATE_EMFILE = 2,
100 * Both reasons, APP and EMFILE apply.
102 SUSPEND_STATE_APP_AND_EMFILE = 3,
105 * Suspension because service was permanently shutdown.
107 SUSPEND_STATE_SHUTDOWN = 4
112 * Handle to a service.
114 struct GNUNET_SERVICE_Handle {
118 const struct GNUNET_CONFIGURATION_Handle *cfg;
121 * Name of our service.
123 const char *service_name;
126 * Main service-specific task to run.
128 GNUNET_SERVICE_InitCallback service_init_cb;
131 * Function to call when clients connect.
133 GNUNET_SERVICE_ConnectHandler connect_cb;
136 * Function to call when clients disconnect / are disconnected.
138 GNUNET_SERVICE_DisconnectHandler disconnect_cb;
141 * Closure for @e service_init_cb, @e connect_cb, @e disconnect_cb.
146 * DLL of listen sockets used to accept new connections.
148 struct ServiceListenContext *slc_head;
151 * DLL of listen sockets used to accept new connections.
153 struct ServiceListenContext *slc_tail;
156 * Our clients, kept in a DLL.
158 struct GNUNET_SERVICE_Client *clients_head;
161 * Our clients, kept in a DLL.
163 struct GNUNET_SERVICE_Client *clients_tail;
166 * Message handlers to use for all clients.
168 struct GNUNET_MQ_MessageHandler *handlers;
171 * Closure for @e task.
176 * IPv4 addresses that are not allowed to connect.
178 struct GNUNET_STRINGS_IPv4NetworkPolicy *v4_denied;
181 * IPv6 addresses that are not allowed to connect.
183 struct GNUNET_STRINGS_IPv6NetworkPolicy *v6_denied;
186 * IPv4 addresses that are allowed to connect (if not
187 * set, all are allowed).
189 struct GNUNET_STRINGS_IPv4NetworkPolicy *v4_allowed;
192 * IPv6 addresses that are allowed to connect (if not
193 * set, all are allowed).
195 struct GNUNET_STRINGS_IPv6NetworkPolicy *v6_allowed;
198 * Do we require a matching UID for UNIX domain socket connections?
199 * #GNUNET_NO means that the UID does not have to match (however,
200 * @e match_gid may still impose other access control checks).
205 * Do we require a matching GID for UNIX domain socket connections?
206 * Ignored if @e match_uid is #GNUNET_YES. Note that this is about
207 * checking that the client's UID is in our group OR that the
208 * client's GID is our GID. If both "match_gid" and @e match_uid are
209 * #GNUNET_NO, all users on the local system have access.
214 * Are we suspended, and if so, why?
216 enum SuspendReason suspend_state;
221 enum GNUNET_SERVICE_Options options;
224 * If we are daemonizing, this FD is set to the
225 * pipe to the parent. Send '.' if we started
226 * ok, '!' if not. -1 if we are not daemonizing.
228 int ready_confirm_fd;
231 * Overall success/failure of the service start.
236 * If #GNUNET_YES, consider unknown message types an error where the
237 * client is disconnected.
244 * Handle to a client that is connected to a service.
246 struct GNUNET_SERVICE_Client {
250 struct GNUNET_SERVICE_Client *next;
255 struct GNUNET_SERVICE_Client *prev;
258 * Service that this client belongs to.
260 struct GNUNET_SERVICE_Handle *sh;
263 * Socket of this client.
265 struct GNUNET_NETWORK_Handle *sock;
268 * Message queue for the client.
270 struct GNUNET_MQ_Handle *mq;
273 * Tokenizer we use for processing incoming data.
275 struct GNUNET_MessageStreamTokenizer *mst;
278 * Task that warns about missing calls to
279 * #GNUNET_SERVICE_client_continue().
281 struct GNUNET_SCHEDULER_Task *warn_task;
284 * Task run to finish dropping the client after the stack has
287 struct GNUNET_SCHEDULER_Task *drop_task;
290 * Task that receives data from the client to
291 * pass it to the handlers.
293 struct GNUNET_SCHEDULER_Task *recv_task;
296 * Task that transmit data to the client.
298 struct GNUNET_SCHEDULER_Task *send_task;
301 * Pointer to the message to be transmitted by @e send_task.
303 const struct GNUNET_MessageHeader *msg;
306 * User context value, value returned from
307 * the connect callback.
312 * Time when we last gave a message from this client
313 * to the application.
315 struct GNUNET_TIME_Absolute warn_start;
318 * Current position in @e msg at which we are transmitting.
323 * Persist the file handle for this client no matter what happens,
324 * force the OS to close once the process actually dies. Should only
325 * be used in special cases!
330 * Is this client a 'monitor' client that should not be counted
331 * when deciding on destroying the server during soft shutdown?
332 * (see also #GNUNET_SERVICE_start)
337 * Are we waiting for the application to call #GNUNET_SERVICE_client_continue()?
342 * Type of last message processed (for warn_no_receive_done).
349 * Check if any of the clients we have left are unrelated to
352 * @param sh service to check clients for
353 * @return #GNUNET_YES if we have non-monitoring clients left
356 have_non_monitor_clients(struct GNUNET_SERVICE_Handle *sh)
358 for (struct GNUNET_SERVICE_Client *client = sh->clients_head; NULL != client;
359 client = client->next)
361 if (client->is_monitor)
370 * Suspend accepting connections from the listen socket temporarily.
371 * Resume activity using #do_resume.
373 * @param sh service to stop accepting connections.
374 * @param sr reason for suspending accepting connections
377 do_suspend(struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
379 struct ServiceListenContext *slc;
381 GNUNET_assert(0 == (sh->suspend_state & sr));
382 sh->suspend_state |= sr;
383 for (slc = sh->slc_head; NULL != slc; slc = slc->next)
385 if (NULL != slc->listen_task)
387 GNUNET_SCHEDULER_cancel(slc->listen_task);
388 slc->listen_task = NULL;
395 * Shutdown task triggered when a service should be terminated.
396 * This considers active clients and the service options to see
397 * how this specific service is to be terminated, and depending
398 * on this proceeds with the shutdown logic.
400 * @param cls our `struct GNUNET_SERVICE_Handle`
403 service_shutdown(void *cls)
405 struct GNUNET_SERVICE_Handle *sh = cls;
409 case GNUNET_SERVICE_OPTION_NONE:
410 GNUNET_SERVICE_shutdown(sh);
413 case GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN:
414 /* This task should never be run if we are using
415 the manual shutdown. */
419 case GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN:
420 if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN))
421 do_suspend(sh, SUSPEND_STATE_SHUTDOWN);
422 if (GNUNET_NO == have_non_monitor_clients(sh))
423 GNUNET_SERVICE_shutdown(sh);
430 * Check if the given IP address is in the list of IP addresses.
432 * @param list a list of networks
433 * @param add the IP to check (in network byte order)
434 * @return #GNUNET_NO if the IP is not in the list, #GNUNET_YES if it it is
437 check_ipv4_listed(const struct GNUNET_STRINGS_IPv4NetworkPolicy *list,
438 const struct in_addr *add)
445 while ((0 != list[i].network.s_addr) || (0 != list[i].netmask.s_addr))
447 if ((add->s_addr & list[i].netmask.s_addr) ==
448 (list[i].network.s_addr & list[i].netmask.s_addr))
457 * Check if the given IP address is in the list of IP addresses.
459 * @param list a list of networks
460 * @param ip the IP to check (in network byte order)
461 * @return #GNUNET_NO if the IP is not in the list, #GNUNET_YES if it it is
464 check_ipv6_listed(const struct GNUNET_STRINGS_IPv6NetworkPolicy *list,
465 const struct in6_addr *ip)
474 while (0 != GNUNET_is_zero(&list[i].network))
476 for (j = 0; j < sizeof(struct in6_addr) / sizeof(int); j++)
477 if (((((int *)ip)[j] & ((int *)&list[i].netmask)[j])) !=
478 (((int *)&list[i].network)[j] & ((int *)&list[i].netmask)[j]))
490 * Task run when we are ready to transmit data to the
493 * @param cls the `struct GNUNET_SERVICE_Client *` to send to
498 struct GNUNET_SERVICE_Client *client = cls;
503 LOG(GNUNET_ERROR_TYPE_DEBUG,
504 "service: sending message with type %u\n",
505 ntohs(client->msg->type));
508 client->send_task = NULL;
509 buf = (const char *)client->msg;
510 left = ntohs(client->msg->size) - client->msg_pos;
511 ret = GNUNET_NETWORK_socket_send(client->sock, &buf[client->msg_pos], left);
512 GNUNET_assert(ret <= (ssize_t)left);
515 LOG(GNUNET_ERROR_TYPE_DEBUG, "no data send");
516 GNUNET_MQ_inject_error(client->mq, GNUNET_MQ_ERROR_WRITE);
521 if ((EAGAIN == errno) || (EINTR == errno))
529 GNUNET_log_strerror(GNUNET_ERROR_TYPE_WARNING, "send");
530 LOG(GNUNET_ERROR_TYPE_DEBUG,
531 "socket send returned with error code %i",
533 GNUNET_MQ_inject_error(client->mq, GNUNET_MQ_ERROR_WRITE);
537 if (0 == client->msg_pos)
539 GNUNET_MQ_impl_send_in_flight(client->mq);
541 client->msg_pos += ret;
542 if (left > (size_t)ret)
544 GNUNET_assert(NULL == client->drop_task);
546 GNUNET_SCHEDULER_add_write_net(GNUNET_TIME_UNIT_FOREVER_REL,
552 GNUNET_MQ_impl_send_continue(client->mq);
557 * Signature of functions implementing the sending functionality of a
560 * @param mq the message queue
561 * @param msg the message to send
562 * @param impl_state our `struct GNUNET_SERVICE_Client *`
565 service_mq_send(struct GNUNET_MQ_Handle *mq,
566 const struct GNUNET_MessageHeader *msg,
569 struct GNUNET_SERVICE_Client *client = impl_state;
572 if (NULL != client->drop_task)
573 return; /* we're going down right now, do not try to send */
574 GNUNET_assert(NULL == client->send_task);
575 LOG(GNUNET_ERROR_TYPE_DEBUG,
576 "Sending message of type %u and size %u to client\n",
582 GNUNET_SCHEDULER_add_write_net(GNUNET_TIME_UNIT_FOREVER_REL,
590 * Implementation function that cancels the currently sent message.
592 * @param mq message queue
593 * @param impl_state state specific to the implementation
596 service_mq_cancel(struct GNUNET_MQ_Handle *mq, void *impl_state)
598 struct GNUNET_SERVICE_Client *client = impl_state;
601 GNUNET_assert(0 == client->msg_pos);
603 GNUNET_SCHEDULER_cancel(client->send_task);
604 client->send_task = NULL;
609 * Generic error handler, called with the appropriate
610 * error code and the same closure specified at the creation of
612 * Not every message queue implementation supports an error handler.
614 * @param cls closure with our `struct GNUNET_SERVICE_Client`
615 * @param error error code
618 service_mq_error_handler(void *cls, enum GNUNET_MQ_Error error)
620 struct GNUNET_SERVICE_Client *client = cls;
621 struct GNUNET_SERVICE_Handle *sh = client->sh;
623 if ((GNUNET_MQ_ERROR_NO_MATCH == error) && (GNUNET_NO == sh->require_found))
625 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
626 "No handler for message of type %u found\n",
627 (unsigned int)client->warn_type);
628 GNUNET_SERVICE_client_continue(client);
629 return; /* ignore error */
631 GNUNET_SERVICE_client_drop(client);
636 * Task run to warn about missing calls to #GNUNET_SERVICE_client_continue().
638 * @param cls our `struct GNUNET_SERVICE_Client *` to process more requests from
641 warn_no_client_continue(void *cls)
643 struct GNUNET_SERVICE_Client *client = cls;
647 client->warn_type); /* type should never be 0 here, as we don't use 0 */
648 client->warn_task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_MINUTES,
649 &warn_no_client_continue,
652 GNUNET_ERROR_TYPE_WARNING,
654 "Processing code for message of type %u did not call `GNUNET_SERVICE_client_continue' after %s\n"),
655 (unsigned int)client->warn_type,
656 GNUNET_STRINGS_relative_time_to_string(GNUNET_TIME_absolute_get_duration(
663 * Functions with this signature are called whenever a
664 * complete message is received by the tokenizer for a client.
666 * Do not call #GNUNET_MST_destroy() from within
667 * the scope of this callback.
669 * @param cls closure with the `struct GNUNET_SERVICE_Client *`
670 * @param message the actual message
671 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the client was dropped
674 service_client_mst_cb(void *cls, const struct GNUNET_MessageHeader *message)
676 struct GNUNET_SERVICE_Client *client = cls;
678 LOG(GNUNET_ERROR_TYPE_DEBUG,
679 "Received message of type %u and size %u from client\n",
680 ntohs(message->type),
681 ntohs(message->size));
682 GNUNET_assert(GNUNET_NO == client->needs_continue);
683 client->needs_continue = GNUNET_YES;
684 client->warn_type = ntohs(message->type);
685 client->warn_start = GNUNET_TIME_absolute_get();
686 GNUNET_assert(NULL == client->warn_task);
687 client->warn_task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_MINUTES,
688 &warn_no_client_continue,
690 GNUNET_MQ_inject_message(client->mq, message);
691 if (NULL != client->drop_task)
692 return GNUNET_SYSERR;
698 * A client sent us data. Receive and process it. If we are done,
699 * reschedule this task.
701 * @param cls the `struct GNUNET_SERVICE_Client` that sent us data.
704 service_client_recv(void *cls)
706 struct GNUNET_SERVICE_Client *client = cls;
709 client->recv_task = NULL;
710 ret = GNUNET_MST_read(client->mst, client->sock, GNUNET_NO, GNUNET_YES);
711 if (GNUNET_SYSERR == ret)
713 /* client closed connection (or IO error) */
714 if (NULL == client->drop_task)
716 GNUNET_assert(GNUNET_NO == client->needs_continue);
717 GNUNET_SERVICE_client_drop(client);
721 if (GNUNET_NO == ret)
722 return; /* more messages in buffer, wait for application
723 to be done processing */
724 GNUNET_assert(GNUNET_OK == ret);
725 if (GNUNET_YES == client->needs_continue)
727 if (NULL != client->recv_task)
729 /* MST needs more data, re-schedule read job */
731 GNUNET_SCHEDULER_add_read_net(GNUNET_TIME_UNIT_FOREVER_REL,
733 &service_client_recv,
739 * We have successfully accepted a connection from a client. Now
740 * setup the client (with the scheduler) and tell the application.
742 * @param sh service that accepted the client
743 * @param sock socket associated with the client
746 start_client(struct GNUNET_SERVICE_Handle *sh,
747 struct GNUNET_NETWORK_Handle *csock)
749 struct GNUNET_SERVICE_Client *client;
751 client = GNUNET_new(struct GNUNET_SERVICE_Client);
752 GNUNET_CONTAINER_DLL_insert(sh->clients_head, sh->clients_tail, client);
754 client->sock = csock;
755 client->mq = GNUNET_MQ_queue_for_callbacks(&service_mq_send,
760 &service_mq_error_handler,
762 client->mst = GNUNET_MST_create(&service_client_mst_cb, client);
763 if (NULL != sh->connect_cb)
764 client->user_context = sh->connect_cb(sh->cb_cls, client, client->mq);
765 GNUNET_MQ_set_handlers_closure(client->mq, client->user_context);
767 GNUNET_SCHEDULER_add_read_net(GNUNET_TIME_UNIT_FOREVER_REL,
769 &service_client_recv,
775 * We have a client. Accept the incoming socket(s) (and reschedule
778 * @param cls the `struct ServiceListenContext` of the ready listen socket
781 accept_client(void *cls)
783 struct ServiceListenContext *slc = cls;
784 struct GNUNET_SERVICE_Handle *sh = slc->sh;
786 slc->listen_task = NULL;
789 struct GNUNET_NETWORK_Handle *sock;
790 const struct sockaddr_in *v4;
791 const struct sockaddr_in6 *v6;
792 struct sockaddr_storage sa;
796 addrlen = sizeof(sa);
797 sock = GNUNET_NETWORK_socket_accept(slc->listen_socket,
798 (struct sockaddr *)&sa,
803 do_suspend(sh, SUSPEND_STATE_EMFILE);
804 else if (EAGAIN != errno)
805 GNUNET_log_strerror(GNUNET_ERROR_TYPE_WARNING, "accept");
808 switch (sa.ss_family)
811 GNUNET_assert(addrlen == sizeof(struct sockaddr_in));
812 v4 = (const struct sockaddr_in *)&sa;
813 ok = (((NULL == sh->v4_allowed) ||
814 (check_ipv4_listed(sh->v4_allowed, &v4->sin_addr))) &&
815 ((NULL == sh->v4_denied) ||
816 (!check_ipv4_listed(sh->v4_denied, &v4->sin_addr))));
820 GNUNET_assert(addrlen == sizeof(struct sockaddr_in6));
821 v6 = (const struct sockaddr_in6 *)&sa;
822 ok = (((NULL == sh->v6_allowed) ||
823 (check_ipv6_listed(sh->v6_allowed, &v6->sin6_addr))) &&
824 ((NULL == sh->v6_denied) ||
825 (!check_ipv6_listed(sh->v6_denied, &v6->sin6_addr))));
830 ok = GNUNET_OK; /* controlled using file-system ACL now */
834 LOG(GNUNET_ERROR_TYPE_WARNING,
835 _("Unknown address family %d\n"),
841 LOG(GNUNET_ERROR_TYPE_DEBUG,
842 "Service rejected incoming connection from %s due to policy.\n",
843 GNUNET_a2s((const struct sockaddr *)&sa, addrlen));
844 GNUNET_break(GNUNET_OK == GNUNET_NETWORK_socket_close(sock));
847 LOG(GNUNET_ERROR_TYPE_DEBUG,
848 "Service accepted incoming connection from %s.\n",
849 GNUNET_a2s((const struct sockaddr *)&sa, addrlen));
850 start_client(slc->sh, sock);
852 if (0 != sh->suspend_state)
855 GNUNET_SCHEDULER_add_read_net(GNUNET_TIME_UNIT_FOREVER_REL,
863 * Resume accepting connections from the listen socket.
865 * @param sh service to resume accepting connections.
866 * @param sr reason that is no longer causing the suspension,
867 * or #SUSPEND_STATE_NONE on first startup
870 do_resume(struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
872 struct ServiceListenContext *slc;
874 GNUNET_assert((SUSPEND_STATE_NONE == sr) || (0 != (sh->suspend_state & sr)));
875 sh->suspend_state -= sr;
876 if (SUSPEND_STATE_NONE != sh->suspend_state)
878 for (slc = sh->slc_head; NULL != slc; slc = slc->next)
880 GNUNET_assert(NULL == slc->listen_task);
882 GNUNET_SCHEDULER_add_read_net(GNUNET_TIME_UNIT_FOREVER_REL,
891 * First task run by any service. Initializes our shutdown task,
892 * starts the listening operation on our listen sockets and launches
893 * the custom logic of the application service.
895 * @param cls our `struct GNUNET_SERVICE_Handle`
898 service_main(void *cls)
900 struct GNUNET_SERVICE_Handle *sh = cls;
902 if (GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN != sh->options)
903 GNUNET_SCHEDULER_add_shutdown(&service_shutdown, sh);
904 do_resume(sh, SUSPEND_STATE_NONE);
906 if (-1 != sh->ready_confirm_fd)
908 GNUNET_break(1 == write(sh->ready_confirm_fd, ".", 1));
909 GNUNET_break(0 == close(sh->ready_confirm_fd));
910 sh->ready_confirm_fd = -1;
913 if (NULL != sh->service_init_cb)
914 sh->service_init_cb(sh->cb_cls, sh->cfg, sh);
919 * Parse an IPv4 access control list.
921 * @param ret location where to write the ACL (set)
922 * @param sh service context to use to get the configuration
923 * @param option name of the ACL option to parse
924 * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including
928 process_acl4(struct GNUNET_STRINGS_IPv4NetworkPolicy **ret,
929 struct GNUNET_SERVICE_Handle *sh,
934 if (!GNUNET_CONFIGURATION_have_value(sh->cfg, sh->service_name, option))
939 GNUNET_break(GNUNET_OK ==
940 GNUNET_CONFIGURATION_get_value_string(sh->cfg,
944 if (NULL == (*ret = GNUNET_STRINGS_parse_ipv4_policy(opt)))
946 LOG(GNUNET_ERROR_TYPE_WARNING,
947 _("Could not parse IPv4 network specification `%s' for `%s:%s'\n"),
952 return GNUNET_SYSERR;
960 * Parse an IPv6 access control list.
962 * @param ret location where to write the ACL (set)
963 * @param sh service context to use to get the configuration
964 * @param option name of the ACL option to parse
965 * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including
969 process_acl6(struct GNUNET_STRINGS_IPv6NetworkPolicy **ret,
970 struct GNUNET_SERVICE_Handle *sh,
975 if (!GNUNET_CONFIGURATION_have_value(sh->cfg, sh->service_name, option))
980 GNUNET_break(GNUNET_OK ==
981 GNUNET_CONFIGURATION_get_value_string(sh->cfg,
985 if (NULL == (*ret = GNUNET_STRINGS_parse_ipv6_policy(opt)))
987 LOG(GNUNET_ERROR_TYPE_WARNING,
988 _("Could not parse IPv6 network specification `%s' for `%s:%s'\n"),
993 return GNUNET_SYSERR;
1001 * Add the given UNIX domain path as an address to the
1002 * list (as the first entry).
1004 * @param saddrs array to update
1005 * @param saddrlens where to store the address length
1006 * @param unixpath path to add
1007 * @param abstract #GNUNET_YES to add an abstract UNIX domain socket. This
1008 * parameter is ignore on systems other than LINUX
1011 add_unixpath(struct sockaddr **saddrs,
1012 socklen_t *saddrlens,
1013 const char *unixpath,
1017 struct sockaddr_un *un;
1019 un = GNUNET_new(struct sockaddr_un);
1020 un->sun_family = AF_UNIX;
1021 GNUNET_strlcpy(un->sun_path, unixpath, sizeof(un->sun_path));
1023 if (GNUNET_YES == abstract)
1024 un->sun_path[0] = '\0';
1026 #if HAVE_SOCKADDR_UN_SUN_LEN
1027 un->sun_len = (u_char)sizeof(struct sockaddr_un);
1029 *saddrs = (struct sockaddr *)un;
1030 *saddrlens = sizeof(struct sockaddr_un);
1032 /* this function should never be called
1033 * unless AF_UNIX is defined! */
1040 * Get the list of addresses that a server for the given service
1043 * @param service_name name of the service
1044 * @param cfg configuration (which specifies the addresses)
1045 * @param addrs set (call by reference) to an array of pointers to the
1046 * addresses the server should bind to and listen on; the
1047 * array will be NULL-terminated (on success)
1048 * @param addr_lens set (call by reference) to an array of the lengths
1049 * of the respective `struct sockaddr` struct in the @a addrs
1050 * array (on success)
1051 * @return number of addresses found on success,
1052 * #GNUNET_SYSERR if the configuration
1053 * did not specify reasonable finding information or
1054 * if it specified a hostname that could not be resolved;
1055 * #GNUNET_NO if the number of addresses configured is
1056 * zero (in this case, `*addrs` and `*addr_lens` will be
1060 get_server_addresses(const char *service_name,
1061 const struct GNUNET_CONFIGURATION_Handle *cfg,
1062 struct sockaddr ***addrs,
1063 socklen_t **addr_lens)
1066 struct GNUNET_NETWORK_Handle *desc;
1067 unsigned long long port;
1069 struct addrinfo hints;
1070 struct addrinfo *res;
1071 struct addrinfo *pos;
1072 struct addrinfo *next;
1077 struct sockaddr **saddrs;
1078 socklen_t *saddrlens;
1084 disablev6 = GNUNET_NO;
1085 if ((GNUNET_NO == GNUNET_NETWORK_test_pf(PF_INET6)) ||
1087 GNUNET_CONFIGURATION_get_value_yesno(cfg, service_name, "DISABLEV6")))
1088 disablev6 = GNUNET_YES;
1091 if (GNUNET_CONFIGURATION_have_value(cfg, service_name, "PORT"))
1093 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number(cfg,
1098 LOG(GNUNET_ERROR_TYPE_ERROR,
1099 _("Require valid port number for service `%s' in configuration!\n"),
1104 LOG(GNUNET_ERROR_TYPE_ERROR,
1105 _("Require valid port number for service `%s' in configuration!\n"),
1107 return GNUNET_SYSERR;
1111 if (GNUNET_CONFIGURATION_have_value(cfg, service_name, "BINDTO"))
1113 GNUNET_break(GNUNET_OK ==
1114 GNUNET_CONFIGURATION_get_value_string(cfg,
1123 abstract = GNUNET_NO;
1126 GNUNET_CONFIGURATION_have_value(cfg, service_name, "UNIXPATH")) &&
1127 (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename(cfg,
1131 (0 < strlen(unixpath)))
1133 /* probe UNIX support */
1134 struct sockaddr_un s_un;
1136 if (strlen(unixpath) >= sizeof(s_un.sun_path))
1138 LOG(GNUNET_ERROR_TYPE_WARNING,
1139 _("UNIXPATH `%s' too long, maximum length is %llu\n"),
1141 (unsigned long long)sizeof(s_un.sun_path));
1142 unixpath = GNUNET_NETWORK_shorten_unixpath(unixpath);
1143 LOG(GNUNET_ERROR_TYPE_INFO, _("Using `%s' instead\n"), unixpath);
1146 abstract = GNUNET_CONFIGURATION_get_value_yesno(cfg,
1148 "USE_ABSTRACT_SOCKETS");
1149 if (GNUNET_SYSERR == abstract)
1150 abstract = GNUNET_NO;
1152 if ((GNUNET_YES != abstract) &&
1153 (GNUNET_OK != GNUNET_DISK_directory_create_for_file(unixpath)))
1154 GNUNET_log_strerror_file(GNUNET_ERROR_TYPE_ERROR, "mkdir", unixpath);
1156 if (NULL != unixpath)
1158 desc = GNUNET_NETWORK_socket_create(AF_UNIX, SOCK_STREAM, 0);
1161 if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
1164 LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR, "socket");
1165 GNUNET_free_non_null(hostname);
1166 GNUNET_free(unixpath);
1167 return GNUNET_SYSERR;
1169 LOG(GNUNET_ERROR_TYPE_INFO,
1171 "Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
1174 GNUNET_free(unixpath);
1179 GNUNET_break(GNUNET_OK == GNUNET_NETWORK_socket_close(desc));
1185 if ((0 == port) && (NULL == unixpath))
1187 LOG(GNUNET_ERROR_TYPE_ERROR,
1189 "Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
1191 GNUNET_free_non_null(hostname);
1192 return GNUNET_SYSERR;
1196 saddrs = GNUNET_new_array(2, struct sockaddr *);
1197 saddrlens = GNUNET_new_array(2, socklen_t);
1198 add_unixpath(saddrs, saddrlens, unixpath, abstract);
1199 GNUNET_free_non_null(unixpath);
1200 GNUNET_free_non_null(hostname);
1202 *addr_lens = saddrlens;
1206 if (NULL != hostname)
1208 LOG(GNUNET_ERROR_TYPE_DEBUG,
1209 "Resolving `%s' since that is where `%s' will bind to.\n",
1212 memset(&hints, 0, sizeof(struct addrinfo));
1214 hints.ai_family = AF_INET;
1215 hints.ai_protocol = IPPROTO_TCP;
1216 if ((0 != (ret = getaddrinfo(hostname, NULL, &hints, &res))) ||
1219 LOG(GNUNET_ERROR_TYPE_ERROR,
1220 _("Failed to resolve `%s': %s\n"),
1223 GNUNET_free(hostname);
1224 GNUNET_free_non_null(unixpath);
1225 return GNUNET_SYSERR;
1229 while (NULL != (pos = next))
1231 next = pos->ai_next;
1232 if ((disablev6) && (pos->ai_family == AF_INET6))
1238 LOG(GNUNET_ERROR_TYPE_ERROR,
1239 _("Failed to find %saddress for `%s'.\n"),
1240 disablev6 ? "IPv4 " : "",
1243 GNUNET_free(hostname);
1244 GNUNET_free_non_null(unixpath);
1245 return GNUNET_SYSERR;
1248 if (NULL != unixpath)
1250 saddrs = GNUNET_new_array(resi + 1, struct sockaddr *);
1251 saddrlens = GNUNET_new_array(resi + 1, socklen_t);
1253 if (NULL != unixpath)
1255 add_unixpath(saddrs, saddrlens, unixpath, abstract);
1259 while (NULL != (pos = next))
1261 next = pos->ai_next;
1262 if ((disablev6) && (AF_INET6 == pos->ai_family))
1264 if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
1265 continue; /* not TCP */
1266 if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
1267 continue; /* huh? */
1268 LOG(GNUNET_ERROR_TYPE_DEBUG,
1269 "Service `%s' will bind to `%s'\n",
1271 GNUNET_a2s(pos->ai_addr, pos->ai_addrlen));
1272 if (AF_INET == pos->ai_family)
1274 GNUNET_assert(sizeof(struct sockaddr_in) == pos->ai_addrlen);
1275 saddrlens[i] = pos->ai_addrlen;
1276 saddrs[i] = GNUNET_malloc(saddrlens[i]);
1277 GNUNET_memcpy(saddrs[i], pos->ai_addr, saddrlens[i]);
1278 ((struct sockaddr_in *)saddrs[i])->sin_port = htons(port);
1282 GNUNET_assert(AF_INET6 == pos->ai_family);
1283 GNUNET_assert(sizeof(struct sockaddr_in6) == pos->ai_addrlen);
1284 saddrlens[i] = pos->ai_addrlen;
1285 saddrs[i] = GNUNET_malloc(saddrlens[i]);
1286 GNUNET_memcpy(saddrs[i], pos->ai_addr, saddrlens[i]);
1287 ((struct sockaddr_in6 *)saddrs[i])->sin6_port = htons(port);
1291 GNUNET_free(hostname);
1297 /* will bind against everything, just set port */
1302 if (NULL != unixpath)
1305 saddrs = GNUNET_new_array(resi + 1, struct sockaddr *);
1306 saddrlens = GNUNET_new_array(resi + 1, socklen_t);
1307 if (NULL != unixpath)
1309 add_unixpath(saddrs, saddrlens, unixpath, abstract);
1312 saddrlens[i] = sizeof(struct sockaddr_in);
1313 saddrs[i] = GNUNET_malloc(saddrlens[i]);
1314 #if HAVE_SOCKADDR_IN_SIN_LEN
1315 ((struct sockaddr_in *)saddrs[i])->sin_len = saddrlens[i];
1317 ((struct sockaddr_in *)saddrs[i])->sin_family = AF_INET;
1318 ((struct sockaddr_in *)saddrs[i])->sin_port = htons(port);
1324 if (NULL != unixpath)
1326 saddrs = GNUNET_new_array(resi + 1, struct sockaddr *);
1327 saddrlens = GNUNET_new_array(resi + 1, socklen_t);
1329 if (NULL != unixpath)
1331 add_unixpath(saddrs, saddrlens, unixpath, abstract);
1334 saddrlens[i] = sizeof(struct sockaddr_in6);
1335 saddrs[i] = GNUNET_malloc(saddrlens[i]);
1336 #if HAVE_SOCKADDR_IN_SIN_LEN
1337 ((struct sockaddr_in6 *)saddrs[i])->sin6_len = saddrlens[0];
1339 ((struct sockaddr_in6 *)saddrs[i])->sin6_family = AF_INET6;
1340 ((struct sockaddr_in6 *)saddrs[i])->sin6_port = htons(port);
1342 saddrlens[i] = sizeof(struct sockaddr_in);
1343 saddrs[i] = GNUNET_malloc(saddrlens[i]);
1344 #if HAVE_SOCKADDR_IN_SIN_LEN
1345 ((struct sockaddr_in *)saddrs[i])->sin_len = saddrlens[1];
1347 ((struct sockaddr_in *)saddrs[i])->sin_family = AF_INET;
1348 ((struct sockaddr_in *)saddrs[i])->sin_port = htons(port);
1351 GNUNET_free_non_null(unixpath);
1353 *addr_lens = saddrlens;
1360 * Read listen sockets from the parent process (ARM).
1362 * @param sh service context to initialize
1363 * @return NULL-terminated array of sockets on success,
1364 * NULL if not ok (must bind yourself)
1366 static struct GNUNET_NETWORK_Handle **
1367 receive_sockets_from_parent(struct GNUNET_SERVICE_Handle *sh)
1369 static struct GNUNET_NETWORK_Handle **lsocks;
1370 const char *env_buf;
1376 env_buf = getenv("GNUNET_OS_READ_LSOCKS");
1377 if ((NULL == env_buf) || (strlen(env_buf) <= 0))
1379 /* Using W32 API directly here, because this pipe will
1380 * never be used outside of this function, and it's just too much of a bother
1381 * to create a GNUnet API that boxes a HANDLE (the way it is done with socks)
1383 lsocks_pipe = (HANDLE)strtoul(env_buf, NULL, 10);
1384 if ((0 == lsocks_pipe) || (INVALID_HANDLE_VALUE == lsocks_pipe))
1393 ret = ReadFile(lsocks_pipe, &count, sizeof(count), &rd, NULL);
1394 if ((0 == ret) || (sizeof(count) != rd) || (0 == count))
1396 lsocks = GNUNET_new_array(count + 1, struct GNUNET_NETWORK_Handle *);
1399 for (i = 0; i < count; i++)
1401 WSAPROTOCOL_INFOA pi;
1405 ret = ReadFile(lsocks_pipe, &size, sizeof(size), &rd, NULL);
1406 if ((0 == ret) || (sizeof(size) != rd) || (sizeof(pi) != size))
1408 ret = ReadFile(lsocks_pipe, &pi, sizeof(pi), &rd, NULL);
1409 if ((0 == ret) || (sizeof(pi) != rd))
1411 s = WSASocketA(pi.iAddressFamily,
1416 WSA_FLAG_OVERLAPPED);
1417 lsocks[i] = GNUNET_NETWORK_socket_box_native(s);
1418 if (NULL == lsocks[i])
1420 else if (i == count - 1)
1425 lsocks[count] = NULL;
1429 CloseHandle(lsocks_pipe);
1433 LOG(GNUNET_ERROR_TYPE_ERROR,
1434 _("Could not access a pre-bound socket, will try to bind myself\n"));
1435 for (i = 0; (i < count) && (NULL != lsocks[i]); i++)
1436 GNUNET_break(GNUNET_OK == GNUNET_NETWORK_socket_close(lsocks[i]));
1437 GNUNET_free(lsocks);
1446 * Create and initialize a listen socket for the server.
1448 * @param server_addr address to listen on
1449 * @param socklen length of @a server_addr
1450 * @return NULL on error, otherwise the listen socket
1452 static struct GNUNET_NETWORK_Handle *
1453 open_listen_socket(const struct sockaddr *server_addr, socklen_t socklen)
1455 struct GNUNET_NETWORK_Handle *sock;
1459 switch (server_addr->sa_family)
1462 port = ntohs(((const struct sockaddr_in *)server_addr)->sin_port);
1466 port = ntohs(((const struct sockaddr_in6 *)server_addr)->sin6_port);
1478 sock = GNUNET_NETWORK_socket_create(server_addr->sa_family, SOCK_STREAM, 0);
1481 LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR, "socket");
1485 /* bind the socket */
1486 if (GNUNET_OK != GNUNET_NETWORK_socket_bind(sock, server_addr, socklen))
1489 if (EADDRINUSE != errno)
1491 /* we don't log 'EADDRINUSE' here since an IPv4 bind may
1492 * fail if we already took the port on IPv6; if both IPv4 and
1493 * IPv6 binds fail, then our caller will log using the
1494 * errno preserved in 'eno' */
1496 LOG(GNUNET_ERROR_TYPE_ERROR,
1497 _("`%s' failed for port %d (%s).\n"),
1500 (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
1502 LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR, "bind");
1508 LOG(GNUNET_ERROR_TYPE_WARNING,
1509 _("`%s' failed for port %d (%s): address already in use\n"),
1512 (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
1513 else if (AF_UNIX == server_addr->sa_family)
1515 LOG(GNUNET_ERROR_TYPE_WARNING,
1516 _("`%s' failed for `%s': address already in use\n"),
1518 GNUNET_a2s(server_addr, socklen));
1521 GNUNET_break(GNUNET_OK == GNUNET_NETWORK_socket_close(sock));
1525 if (GNUNET_OK != GNUNET_NETWORK_socket_listen(sock, 5))
1527 LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR, "listen");
1528 GNUNET_break(GNUNET_OK == GNUNET_NETWORK_socket_close(sock));
1533 LOG(GNUNET_ERROR_TYPE_DEBUG,
1534 "Server starts to listen on port %u.\n",
1541 * Setup service handle
1543 * Configuration may specify:
1544 * - PORT (where to bind to for TCP)
1545 * - UNIXPATH (where to bind to for UNIX domain sockets)
1546 * - DISABLEV6 (disable support for IPv6, otherwise we use dual-stack)
1547 * - BINDTO (hostname or IP address to bind to, otherwise we take everything)
1548 * - ACCEPT_FROM (only allow connections from specified IPv4 subnets)
1549 * - ACCEPT_FROM6 (only allow connections from specified IPv6 subnets)
1550 * - REJECT_FROM (disallow allow connections from specified IPv4 subnets)
1551 * - REJECT_FROM6 (disallow allow connections from specified IPv6 subnets)
1553 * @param sh service context to initialize
1554 * @return #GNUNET_OK if configuration succeeded
1557 setup_service(struct GNUNET_SERVICE_Handle *sh)
1560 struct GNUNET_NETWORK_Handle **lsocks;
1569 if (GNUNET_CONFIGURATION_have_value(sh->cfg, sh->service_name, "TOLERANT"))
1571 if (GNUNET_SYSERR ==
1572 (tolerant = GNUNET_CONFIGURATION_get_value_yesno(sh->cfg,
1576 LOG(GNUNET_ERROR_TYPE_ERROR,
1577 _("Specified value for `%s' of service `%s' is invalid\n"),
1580 return GNUNET_SYSERR;
1584 tolerant = GNUNET_NO;
1589 if ((NULL != (nfds = getenv("LISTEN_FDS"))) &&
1590 (1 == sscanf(nfds, "%u%1s", &cnt, dummy)) && (cnt > 0) &&
1591 (cnt < FD_SETSIZE) && (cnt + 4 < FD_SETSIZE))
1593 lsocks = GNUNET_new_array(cnt + 1, struct GNUNET_NETWORK_Handle *);
1596 flags = fcntl(3 + cnt, F_GETFD);
1597 if ((flags < 0) || (0 != (flags & FD_CLOEXEC)) ||
1598 (NULL == (lsocks[cnt] = GNUNET_NETWORK_socket_box_native(3 + cnt))))
1600 LOG(GNUNET_ERROR_TYPE_ERROR,
1602 "Could not access pre-bound socket %u, will try to bind myself\n"),
1603 (unsigned int)3 + cnt);
1605 while (NULL != lsocks[cnt])
1606 GNUNET_break(GNUNET_OK ==
1607 GNUNET_NETWORK_socket_close(lsocks[cnt++]));
1608 GNUNET_free(lsocks);
1613 unsetenv("LISTEN_FDS");
1616 if (NULL != getenv("GNUNET_OS_READ_LSOCKS"))
1618 lsocks = receive_sockets_from_parent(sh);
1619 putenv("GNUNET_OS_READ_LSOCKS=");
1625 /* listen only on inherited sockets if we have any */
1626 struct GNUNET_NETWORK_Handle **ls;
1628 for (ls = lsocks; NULL != *ls; ls++)
1630 struct ServiceListenContext *slc;
1632 slc = GNUNET_new(struct ServiceListenContext);
1634 slc->listen_socket = *ls;
1635 GNUNET_CONTAINER_DLL_insert(sh->slc_head, sh->slc_tail, slc);
1637 GNUNET_free(lsocks);
1641 struct sockaddr **addrs;
1642 socklen_t *addrlens;
1645 num = get_server_addresses(sh->service_name, sh->cfg, &addrs, &addrlens);
1646 if (GNUNET_SYSERR == num)
1647 return GNUNET_SYSERR;
1649 for (int i = 0; i < num; i++)
1651 struct ServiceListenContext *slc;
1653 slc = GNUNET_new(struct ServiceListenContext);
1655 slc->listen_socket = open_listen_socket(addrs[i], addrlens[i]);
1656 GNUNET_free(addrs[i]);
1657 if (NULL == slc->listen_socket)
1659 GNUNET_log_strerror(GNUNET_ERROR_TYPE_ERROR, "bind");
1663 GNUNET_CONTAINER_DLL_insert(sh->slc_head, sh->slc_tail, slc);
1665 GNUNET_free_non_null(addrlens);
1666 GNUNET_free_non_null(addrs);
1667 if ((0 != num) && (NULL == sh->slc_head))
1669 /* All attempts to bind failed, hard failure */
1671 GNUNET_ERROR_TYPE_ERROR,
1673 "Could not bind to any of the ports I was supposed to, refusing to run!\n"));
1674 return GNUNET_SYSERR;
1678 sh->require_found = tolerant ? GNUNET_NO : GNUNET_YES;
1679 sh->match_uid = GNUNET_CONFIGURATION_get_value_yesno(sh->cfg,
1682 sh->match_gid = GNUNET_CONFIGURATION_get_value_yesno(sh->cfg,
1685 process_acl4(&sh->v4_denied, sh, "REJECT_FROM");
1686 process_acl4(&sh->v4_allowed, sh, "ACCEPT_FROM");
1687 process_acl6(&sh->v6_denied, sh, "REJECT_FROM6");
1688 process_acl6(&sh->v6_allowed, sh, "ACCEPT_FROM6");
1694 * Get the name of the user that'll be used
1695 * to provide the service.
1697 * @param sh service context
1698 * @return value of the 'USERNAME' option
1701 get_user_name(struct GNUNET_SERVICE_Handle *sh)
1705 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename(sh->cfg,
1717 * @param sh service context
1718 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1721 set_user_id(struct GNUNET_SERVICE_Handle *sh)
1725 if (NULL == (user = get_user_name(sh)))
1726 return GNUNET_OK; /* keep */
1731 pws = getpwnam(user);
1734 LOG(GNUNET_ERROR_TYPE_ERROR,
1735 _("Cannot obtain information about user `%s': %s\n"),
1737 errno == 0 ? _("No such user") : strerror(errno));
1739 return GNUNET_SYSERR;
1741 if ((0 != setgid(pws->pw_gid)) || (0 != setegid(pws->pw_gid)) ||
1743 (0 != initgroups(user, pws->pw_gid)) ||
1745 (0 != setuid(pws->pw_uid)) || (0 != seteuid(pws->pw_uid)))
1747 if ((0 != setregid(pws->pw_gid, pws->pw_gid)) ||
1748 (0 != setreuid(pws->pw_uid, pws->pw_uid)))
1750 LOG(GNUNET_ERROR_TYPE_ERROR,
1751 _("Cannot change user/group to `%s': %s\n"),
1755 return GNUNET_SYSERR;
1765 * Get the name of the file where we will
1766 * write the PID of the service.
1768 * @param sh service context
1769 * @return name of the file for the process ID
1772 get_pid_file_name(struct GNUNET_SERVICE_Handle *sh)
1776 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename(sh->cfg,
1786 * Delete the PID file that was created by our parent.
1788 * @param sh service context
1791 pid_file_delete(struct GNUNET_SERVICE_Handle *sh)
1793 char *pif = get_pid_file_name(sh);
1796 return; /* no PID file */
1797 if (0 != unlink(pif))
1798 LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_WARNING, "unlink", pif);
1804 * Detach from terminal.
1806 * @param sh service context
1807 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1810 detach_terminal(struct GNUNET_SERVICE_Handle *sh)
1817 if (0 != pipe(filedes))
1819 LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR, "pipe");
1820 return GNUNET_SYSERR;
1825 LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR, "fork");
1826 return GNUNET_SYSERR;
1833 GNUNET_break(0 == close(filedes[1]));
1835 if (1 != read(filedes[0], &c, sizeof(char)))
1836 LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING, "read");
1844 LOG(GNUNET_ERROR_TYPE_INFO,
1845 _("Service process failed to initialize\n"));
1849 LOG(GNUNET_ERROR_TYPE_INFO,
1850 _("Service process could not initialize server function\n"));
1854 LOG(GNUNET_ERROR_TYPE_INFO,
1855 _("Service process failed to report status\n"));
1858 exit(1); /* child reported error */
1860 GNUNET_break(0 == close(0));
1861 GNUNET_break(0 == close(1));
1862 GNUNET_break(0 == close(filedes[0]));
1863 nullfd = open("/dev/null", O_RDWR | O_APPEND);
1865 return GNUNET_SYSERR;
1866 /* set stdin/stdout to /dev/null */
1867 if ((dup2(nullfd, 0) < 0) || (dup2(nullfd, 1) < 0))
1869 LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR, "dup2");
1870 (void)close(nullfd);
1871 return GNUNET_SYSERR;
1873 (void)close(nullfd);
1874 /* Detach from controlling terminal */
1877 LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR, "setsid");
1878 sh->ready_confirm_fd = filedes[1];
1880 /* FIXME: we probably need to do something else
1881 * elsewhere in order to fork the process itself... */
1889 * Tear down the service, closing the listen sockets and
1892 * @param sh handle to the service to tear down.
1895 teardown_service(struct GNUNET_SERVICE_Handle *sh)
1897 struct ServiceListenContext *slc;
1899 GNUNET_free_non_null(sh->v4_denied);
1900 GNUNET_free_non_null(sh->v6_denied);
1901 GNUNET_free_non_null(sh->v4_allowed);
1902 GNUNET_free_non_null(sh->v6_allowed);
1903 while (NULL != (slc = sh->slc_head))
1905 GNUNET_CONTAINER_DLL_remove(sh->slc_head, sh->slc_tail, slc);
1906 if (NULL != slc->listen_task)
1907 GNUNET_SCHEDULER_cancel(slc->listen_task);
1908 GNUNET_break(GNUNET_OK ==
1909 GNUNET_NETWORK_socket_close(slc->listen_socket));
1916 * Function to return link to AGPL source upon request.
1918 * @param cls closure with the identification of the client
1919 * @param msg AGPL request
1922 return_agpl(void *cls, const struct GNUNET_MessageHeader *msg)
1924 struct GNUNET_SERVICE_Client *client = cls;
1925 struct GNUNET_MQ_Handle *mq;
1926 struct GNUNET_MQ_Envelope *env;
1927 struct GNUNET_MessageHeader *res;
1931 slen = strlen(GNUNET_AGPL_URL) + 1;
1932 env = GNUNET_MQ_msg_extra(res, GNUNET_MESSAGE_TYPE_RESPONSE_AGPL, slen);
1933 memcpy(&res[1], GNUNET_AGPL_URL, slen);
1934 mq = GNUNET_SERVICE_client_get_mq(client);
1935 GNUNET_MQ_send(mq, env);
1936 GNUNET_SERVICE_client_continue(client);
1941 * Low-level function to start a service if the scheduler
1942 * is already running. Should only be used directly in
1945 * The function will launch the service with the name @a service_name
1946 * using the @a service_options to configure its shutdown
1947 * behavior. When clients connect or disconnect, the respective
1948 * @a connect_cb or @a disconnect_cb functions will be called. For
1949 * messages received from the clients, the respective @a handlers will
1950 * be invoked; for the closure of the handlers we use the return value
1951 * from the @a connect_cb invocation of the respective client.
1953 * Each handler MUST call #GNUNET_SERVICE_client_continue() after each
1954 * message to receive further messages from this client. If
1955 * #GNUNET_SERVICE_client_continue() is not called within a short
1956 * time, a warning will be logged. If delays are expected, services
1957 * should call #GNUNET_SERVICE_client_disable_continue_warning() to
1958 * disable the warning.
1960 * Clients sending invalid messages (based on @a handlers) will be
1961 * dropped. Additionally, clients can be dropped at any time using
1962 * #GNUNET_SERVICE_client_drop().
1964 * The service must be stopped using #GNUNET_SERVICE_stop().
1966 * @param service_name name of the service to run
1967 * @param cfg configuration to use
1968 * @param connect_cb function to call whenever a client connects
1969 * @param disconnect_cb function to call whenever a client disconnects
1970 * @param cls closure argument for @a connect_cb and @a disconnect_cb
1971 * @param handlers NULL-terminated array of message handlers for the service,
1972 * the closure will be set to the value returned by
1973 * the @a connect_cb for the respective connection
1974 * @return NULL on error
1976 struct GNUNET_SERVICE_Handle *
1977 GNUNET_SERVICE_start(const char *service_name,
1978 const struct GNUNET_CONFIGURATION_Handle *cfg,
1979 GNUNET_SERVICE_ConnectHandler connect_cb,
1980 GNUNET_SERVICE_DisconnectHandler disconnect_cb,
1982 const struct GNUNET_MQ_MessageHandler *handlers)
1984 struct GNUNET_SERVICE_Handle *sh;
1986 sh = GNUNET_new(struct GNUNET_SERVICE_Handle);
1987 sh->service_name = service_name;
1989 sh->connect_cb = connect_cb;
1990 sh->disconnect_cb = disconnect_cb;
1992 sh->handlers = GNUNET_MQ_copy_handlers2(handlers, &return_agpl, NULL);
1993 if (GNUNET_OK != setup_service(sh))
1995 GNUNET_free_non_null(sh->handlers);
1999 do_resume(sh, SUSPEND_STATE_NONE);
2005 * Stops a service that was started with #GNUNET_SERVICE_start().
2007 * @param srv service to stop
2010 GNUNET_SERVICE_stop(struct GNUNET_SERVICE_Handle *srv)
2012 struct GNUNET_SERVICE_Client *client;
2014 GNUNET_SERVICE_suspend(srv);
2015 while (NULL != (client = srv->clients_head))
2016 GNUNET_SERVICE_client_drop(client);
2017 teardown_service(srv);
2018 GNUNET_free_non_null(srv->handlers);
2024 * Creates the "main" function for a GNUnet service. You
2025 * should almost always use the #GNUNET_SERVICE_MAIN macro
2026 * instead of calling this function directly (except
2027 * for ARM, which should call this function directly).
2029 * The function will launch the service with the name @a service_name
2030 * using the @a service_options to configure its shutdown
2031 * behavior. Once the service is ready, the @a init_cb will be called
2032 * for service-specific initialization. @a init_cb will be given the
2033 * service handler which can be used to control the service's
2034 * availability. When clients connect or disconnect, the respective
2035 * @a connect_cb or @a disconnect_cb functions will be called. For
2036 * messages received from the clients, the respective @a handlers will
2037 * be invoked; for the closure of the handlers we use the return value
2038 * from the @a connect_cb invocation of the respective client.
2040 * Each handler MUST call #GNUNET_SERVICE_client_continue() after each
2041 * message to receive further messages from this client. If
2042 * #GNUNET_SERVICE_client_continue() is not called within a short
2043 * time, a warning will be logged. If delays are expected, services
2044 * should call #GNUNET_SERVICE_client_disable_continue_warning() to
2045 * disable the warning.
2047 * Clients sending invalid messages (based on @a handlers) will be
2048 * dropped. Additionally, clients can be dropped at any time using
2049 * #GNUNET_SERVICE_client_drop().
2051 * @param argc number of command-line arguments in @a argv
2052 * @param argv array of command-line arguments
2053 * @param service_name name of the service to run
2054 * @param options options controlling shutdown of the service
2055 * @param service_init_cb function to call once the service is ready
2056 * @param connect_cb function to call whenever a client connects
2057 * @param disconnect_cb function to call whenever a client disconnects
2058 * @param cls closure argument for @a service_init_cb, @a connect_cb and @a disconnect_cb
2059 * @param handlers NULL-terminated array of message handlers for the service,
2060 * the closure will be set to the value returned by
2061 * the @a connect_cb for the respective connection
2062 * @return 0 on success, non-zero on error
2065 GNUNET_SERVICE_run_(int argc,
2067 const char *service_name,
2068 enum GNUNET_SERVICE_Options options,
2069 GNUNET_SERVICE_InitCallback service_init_cb,
2070 GNUNET_SERVICE_ConnectHandler connect_cb,
2071 GNUNET_SERVICE_DisconnectHandler disconnect_cb,
2073 const struct GNUNET_MQ_MessageHandler *handlers)
2075 struct GNUNET_SERVICE_Handle sh;
2081 char *opt_cfg_filename;
2086 unsigned long long skew_offset;
2087 unsigned long long skew_variance;
2088 long long clock_offset;
2089 struct GNUNET_CONFIGURATION_Handle *cfg;
2092 const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get();
2094 struct GNUNET_GETOPT_CommandLineOption service_options[] =
2095 { GNUNET_GETOPT_option_cfgfile(&opt_cfg_filename),
2096 GNUNET_GETOPT_option_flag('d',
2099 "do daemonize (detach from terminal)"),
2101 GNUNET_GETOPT_option_help(NULL),
2102 GNUNET_GETOPT_option_loglevel(&loglev),
2103 GNUNET_GETOPT_option_logfile(&logfile),
2104 GNUNET_GETOPT_option_version(pd->version),
2105 GNUNET_GETOPT_OPTION_END };
2108 memset(&sh, 0, sizeof(sh));
2109 xdg = getenv("XDG_CONFIG_HOME");
2111 GNUNET_asprintf(&cfg_filename,
2117 cfg_filename = GNUNET_strdup(pd->user_config_file);
2118 sh.ready_confirm_fd = -1;
2119 sh.options = options;
2120 sh.cfg = cfg = GNUNET_CONFIGURATION_create();
2121 sh.service_init_cb = service_init_cb;
2122 sh.connect_cb = connect_cb;
2123 sh.disconnect_cb = disconnect_cb;
2125 sh.handlers = GNUNET_MQ_copy_handlers(handlers);
2126 sh.service_name = service_name;
2128 /* setup subsystems */
2131 opt_cfg_filename = NULL;
2134 if (NULL != pd->gettext_domain)
2136 setlocale(LC_ALL, "");
2137 path = (NULL == pd->gettext_path) ?
2138 GNUNET_OS_installation_get_path(GNUNET_OS_IPK_LOCALEDIR) :
2139 GNUNET_strdup(pd->gettext_path);
2142 bindtextdomain(pd->gettext_domain, path);
2145 textdomain(pd->gettext_domain);
2148 ret = GNUNET_GETOPT_run(service_name, service_options, argc, argv);
2149 if (GNUNET_SYSERR == ret)
2151 if (GNUNET_NO == ret)
2156 if (GNUNET_OK != GNUNET_log_setup(service_name, loglev, logfile))
2161 if (NULL != opt_cfg_filename)
2163 if ((GNUNET_YES != GNUNET_DISK_file_test(opt_cfg_filename)) ||
2164 (GNUNET_SYSERR == GNUNET_CONFIGURATION_load(cfg, opt_cfg_filename)))
2166 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
2167 _("Malformed configuration file `%s', exit ...\n"),
2174 if (GNUNET_YES == GNUNET_DISK_file_test(cfg_filename))
2176 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load(cfg, cfg_filename))
2178 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
2179 _("Malformed configuration file `%s', exit ...\n"),
2186 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load(cfg, NULL))
2188 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
2189 _("Malformed configuration, exit ...\n"));
2194 if (GNUNET_OK != setup_service(&sh))
2196 if ((1 == do_daemonize) && (GNUNET_OK != detach_terminal(&sh)))
2201 if (GNUNET_OK != set_user_id(&sh))
2203 LOG(GNUNET_ERROR_TYPE_DEBUG,
2204 "Service `%s' runs with configuration from `%s'\n",
2206 (NULL != opt_cfg_filename) ? opt_cfg_filename : cfg_filename);
2207 if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(sh.cfg,
2211 (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(sh.cfg,
2216 clock_offset = skew_offset - skew_variance;
2217 GNUNET_TIME_set_offset(clock_offset);
2218 LOG(GNUNET_ERROR_TYPE_DEBUG, "Skewing clock by %dll ms\n", clock_offset);
2220 GNUNET_RESOLVER_connect(sh.cfg);
2222 /* actually run service */
2224 GNUNET_SCHEDULER_run(&service_main, &sh);
2226 if (1 == do_daemonize)
2227 pid_file_delete(&sh);
2230 if (-1 != sh.ready_confirm_fd)
2232 if (1 != write(sh.ready_confirm_fd, err ? "I" : "S", 1))
2233 LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING, "write");
2234 GNUNET_break(0 == close(sh.ready_confirm_fd));
2240 if ((GNUNET_YES == GNUNET_CONFIGURATION_have_value(sh.cfg,
2243 (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(sh.cfg,
2251 GAUGER(service_name, counter, mi.usmblks, "blocks");
2252 GNUNET_free(counter);
2256 teardown_service(&sh);
2257 GNUNET_free_non_null(sh.handlers);
2258 GNUNET_SPEEDUP_stop_();
2259 GNUNET_CONFIGURATION_destroy(cfg);
2260 GNUNET_free_non_null(logfile);
2261 GNUNET_free_non_null(loglev);
2262 GNUNET_free(cfg_filename);
2263 GNUNET_free_non_null(opt_cfg_filename);
2265 return err ? GNUNET_SYSERR : sh.ret;
2270 * Suspend accepting connections from the listen socket temporarily.
2271 * Resume activity using #GNUNET_SERVICE_resume.
2273 * @param sh service to stop accepting connections.
2276 GNUNET_SERVICE_suspend(struct GNUNET_SERVICE_Handle *sh)
2278 do_suspend(sh, SUSPEND_STATE_APP);
2283 * Resume accepting connections from the listen socket.
2285 * @param sh service to resume accepting connections.
2288 GNUNET_SERVICE_resume(struct GNUNET_SERVICE_Handle *sh)
2290 do_resume(sh, SUSPEND_STATE_APP);
2295 * Task run to resume receiving data from the client after
2296 * the client called #GNUNET_SERVICE_client_continue().
2298 * @param cls our `struct GNUNET_SERVICE_Client`
2301 resume_client_receive(void *cls)
2303 struct GNUNET_SERVICE_Client *c = cls;
2306 c->recv_task = NULL;
2307 /* first, check if there is still something in the buffer */
2308 ret = GNUNET_MST_next(c->mst, GNUNET_YES);
2309 if (GNUNET_SYSERR == ret)
2311 if (NULL == c->drop_task)
2312 GNUNET_SERVICE_client_drop(c);
2315 if (GNUNET_NO == ret)
2316 return; /* done processing, wait for more later */
2317 GNUNET_assert(GNUNET_OK == ret);
2318 if (GNUNET_YES == c->needs_continue)
2319 return; /* #GNUNET_MST_next() did give a message to the client */
2320 /* need to receive more data from the network first */
2321 if (NULL != c->recv_task)
2323 c->recv_task = GNUNET_SCHEDULER_add_read_net(GNUNET_TIME_UNIT_FOREVER_REL,
2325 &service_client_recv,
2331 * Continue receiving further messages from the given client.
2332 * Must be called after each message received.
2334 * @param c the client to continue receiving from
2337 GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
2339 GNUNET_assert(NULL == c->drop_task);
2340 GNUNET_assert(GNUNET_YES == c->needs_continue);
2341 GNUNET_assert(NULL == c->recv_task);
2342 c->needs_continue = GNUNET_NO;
2343 if (NULL != c->warn_task)
2345 GNUNET_SCHEDULER_cancel(c->warn_task);
2346 c->warn_task = NULL;
2348 c->recv_task = GNUNET_SCHEDULER_add_now(&resume_client_receive, c);
2353 * Disable the warning the server issues if a message is not
2354 * acknowledged in a timely fashion. Use this call if a client is
2355 * intentionally delayed for a while. Only applies to the current
2358 * @param c client for which to disable the warning
2361 GNUNET_SERVICE_client_disable_continue_warning(struct GNUNET_SERVICE_Client *c)
2363 GNUNET_break(NULL != c->warn_task);
2364 if (NULL != c->warn_task)
2366 GNUNET_SCHEDULER_cancel(c->warn_task);
2367 c->warn_task = NULL;
2373 * Asynchronously finish dropping the client.
2375 * @param cls the `struct GNUNET_SERVICE_Client`.
2378 finish_client_drop(void *cls)
2380 struct GNUNET_SERVICE_Client *c = cls;
2381 struct GNUNET_SERVICE_Handle *sh = c->sh;
2383 c->drop_task = NULL;
2384 GNUNET_assert(NULL == c->send_task);
2385 GNUNET_assert(NULL == c->recv_task);
2386 GNUNET_assert(NULL == c->warn_task);
2387 GNUNET_MST_destroy(c->mst);
2388 GNUNET_MQ_destroy(c->mq);
2389 if (GNUNET_NO == c->persist)
2391 GNUNET_break(GNUNET_OK == GNUNET_NETWORK_socket_close(c->sock));
2392 if ((0 != (SUSPEND_STATE_EMFILE & sh->suspend_state)) &&
2393 (0 == (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)))
2394 do_resume(sh, SUSPEND_STATE_EMFILE);
2398 GNUNET_NETWORK_socket_free_memory_only_(c->sock);
2401 if ((0 != (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)) &&
2402 (GNUNET_NO == have_non_monitor_clients(sh)))
2403 GNUNET_SERVICE_shutdown(sh);
2408 * Ask the server to disconnect from the given client. This is the
2409 * same as returning #GNUNET_SYSERR within the check procedure when
2410 * handling a message, wexcept that it allows dropping of a client even
2411 * when not handling a message from that client. The `disconnect_cb`
2412 * will be called on @a c even if the application closes the connection
2413 * using this function.
2415 * @param c client to disconnect now
2418 GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
2420 struct GNUNET_SERVICE_Handle *sh = c->sh;
2422 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2423 "Client dropped: %p (MQ: %p)\n",
2428 void *backtrace_array[MAX_TRACE_DEPTH];
2429 int num_backtrace_strings = backtrace(backtrace_array, MAX_TRACE_DEPTH);
2430 char **backtrace_strings =
2431 backtrace_symbols(backtrace_array, t->num_backtrace_strings);
2432 for (unsigned int i = 0; i < num_backtrace_strings; i++)
2433 LOG(GNUNET_ERROR_TYPE_DEBUG,
2434 "client drop trace %u: %s\n",
2436 backtrace_strings[i]);
2439 if (NULL != c->drop_task)
2441 /* asked to drop twice! */
2445 GNUNET_CONTAINER_DLL_remove(sh->clients_head, sh->clients_tail, c);
2446 if (NULL != sh->disconnect_cb)
2447 sh->disconnect_cb(sh->cb_cls, c, c->user_context);
2448 if (NULL != c->warn_task)
2450 GNUNET_SCHEDULER_cancel(c->warn_task);
2451 c->warn_task = NULL;
2453 if (NULL != c->recv_task)
2455 GNUNET_SCHEDULER_cancel(c->recv_task);
2456 c->recv_task = NULL;
2458 if (NULL != c->send_task)
2460 GNUNET_SCHEDULER_cancel(c->send_task);
2461 c->send_task = NULL;
2463 c->drop_task = GNUNET_SCHEDULER_add_now(&finish_client_drop, c);
2468 * Explicitly stops the service.
2470 * @param sh server to shutdown
2473 GNUNET_SERVICE_shutdown(struct GNUNET_SERVICE_Handle *sh)
2475 struct GNUNET_SERVICE_Client *client;
2477 if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN))
2478 do_suspend(sh, SUSPEND_STATE_SHUTDOWN);
2479 while (NULL != (client = sh->clients_head))
2480 GNUNET_SERVICE_client_drop(client);
2485 * Set the 'monitor' flag on this client. Clients which have been
2486 * marked as 'monitors' won't prevent the server from shutting down
2487 * once #GNUNET_SERVICE_stop_listening() has been invoked. The idea is
2488 * that for "normal" clients we likely want to allow them to process
2489 * their requests; however, monitor-clients are likely to 'never'
2490 * disconnect during shutdown and thus will not be considered when
2491 * determining if the server should continue to exist after
2492 * shutdown has been triggered.
2494 * @param c client to mark as a monitor
2497 GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
2499 c->is_monitor = GNUNET_YES;
2500 if (((0 != (SUSPEND_STATE_SHUTDOWN & c->sh->suspend_state)) &&
2501 (GNUNET_NO == have_non_monitor_clients(c->sh))))
2502 GNUNET_SERVICE_shutdown(c->sh);
2507 * Set the persist option on this client. Indicates that the
2508 * underlying socket or fd should never really be closed. Used for
2509 * indicating process death.
2511 * @param c client to persist the socket (never to be closed)
2514 GNUNET_SERVICE_client_persist(struct GNUNET_SERVICE_Client *c)
2516 c->persist = GNUNET_YES;
2521 * Obtain the message queue of @a c. Convenience function.
2523 * @param c the client to continue receiving from
2524 * @return the message queue of @a c
2526 struct GNUNET_MQ_Handle *
2527 GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
2533 /* end of service_new.c */