GNUnet  0.10.x
tcp_service_legacy.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2009, 2012 GNUnet e.V.
4 
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.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
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/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19 */
20 
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_protocols.h"
29 #include "gnunet_constants.h"
31 
32 #if HAVE_MALLINFO
33 #include <malloc.h>
34 #include "gauger.h"
35 #endif
36 
37 
38 /* ******************* access control ******************** */
39 
47 static int
49  const struct in_addr *add)
50 {
51  unsigned int i;
52 
53  if (NULL == list)
54  return GNUNET_NO;
55  i = 0;
56  while ((list[i].network.s_addr != 0) || (list[i].netmask.s_addr != 0))
57  {
58  if ((add->s_addr & list[i].netmask.s_addr) ==
59  (list[i].network.s_addr & list[i].netmask.s_addr))
60  return GNUNET_YES;
61  i++;
62  }
63  return GNUNET_NO;
64 }
65 
66 
74 static int
76  const struct in6_addr *ip)
77 {
78  unsigned int i;
79  unsigned int j;
80  struct in6_addr zero;
81 
82  if (NULL == list)
83  return GNUNET_NO;
84  memset (&zero, 0, sizeof (struct in6_addr));
85  i = 0;
86 NEXT:
87  while (0 != memcmp (&zero, &list[i].network, sizeof (struct in6_addr)))
88  {
89  for (j = 0; j < sizeof (struct in6_addr) / sizeof (int); j++)
90  if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) !=
91  (((int *) &list[i].network)[j] & ((int *) &list[i].netmask)[j]))
92  {
93  i++;
94  goto NEXT;
95  }
96  return GNUNET_YES;
97  }
98  return GNUNET_NO;
99 }
100 
101 
102 /* ****************** service struct ****************** */
103 
104 
109 {
114 
119 
124  struct sockaddr **addrs;
125 
129  const char *service_name;
130 
135 
139  void *task_cls;
140 
145 
150 
156 
162 
168 
172  socklen_t *addrlens;
173 
178 
183 
188 
192  int ret;
193 
200 
206 
213 
222 
227 
228 };
229 
230 
231 /* ****************** message handlers ****************** */
232 
241 static size_t
242 write_test (void *cls, size_t size, void *buf)
243 {
244  struct GNUNET_SERVER_Client *client = cls;
245  struct GNUNET_MessageHeader *msg;
246 
247  if (size < sizeof (struct GNUNET_MessageHeader))
248  {
250  return 0; /* client disconnected */
251  }
252  msg = (struct GNUNET_MessageHeader *) buf;
253  msg->type = htons (GNUNET_MESSAGE_TYPE_TEST);
254  msg->size = htons (sizeof (struct GNUNET_MessageHeader));
256  return sizeof (struct GNUNET_MessageHeader);
257 }
258 
259 
267 static void
268 handle_test (void *cls, struct GNUNET_SERVER_Client *client,
269  const struct GNUNET_MessageHeader *message)
270 {
271  /* simply bounce message back to acknowledge */
272  if (NULL ==
274  sizeof (struct GNUNET_MessageHeader),
276  &write_test, client))
278 }
279 
280 
286 static const struct GNUNET_SERVER_MessageHandler defhandlers[] = {
288  sizeof (struct GNUNET_MessageHeader)},
289  {NULL, NULL, 0, 0}
290 };
291 
292 
293 /* ****************** service core routines ************** */
294 
295 
306 static int
308  const struct sockaddr *addr, socklen_t addrlen)
309 {
310  struct LEGACY_SERVICE_Context *sctx = cls;
311  const struct sockaddr_in *i4;
312  const struct sockaddr_in6 *i6;
313  int ret;
314 
315  switch (addr->sa_family)
316  {
317  case AF_INET:
318  GNUNET_assert (addrlen == sizeof (struct sockaddr_in));
319  i4 = (const struct sockaddr_in *) addr;
320  ret = ((NULL == sctx->v4_allowed) ||
321  (check_ipv4_listed (sctx->v4_allowed, &i4->sin_addr))) &&
322  ((NULL == sctx->v4_denied) ||
323  (!check_ipv4_listed (sctx->v4_denied, &i4->sin_addr)));
324  break;
325  case AF_INET6:
326  GNUNET_assert (addrlen == sizeof (struct sockaddr_in6));
327  i6 = (const struct sockaddr_in6 *) addr;
328  ret = ((NULL == sctx->v6_allowed) ||
329  (check_ipv6_listed (sctx->v6_allowed, &i6->sin6_addr))) &&
330  ((NULL == sctx->v6_denied) ||
331  (!check_ipv6_listed (sctx->v6_denied, &i6->sin6_addr)));
332  break;
333 #ifndef WINDOWS
334  case AF_UNIX:
335  ret = GNUNET_OK; /* controlled using file-system ACL now */
336  break;
337 #endif
338  default:
339  LOG (GNUNET_ERROR_TYPE_WARNING, _("Unknown address family %d\n"),
340  addr->sa_family);
341  return GNUNET_SYSERR;
342  }
343  if (GNUNET_OK != ret)
344  {
346  _("Access from `%s' denied to service `%s'\n"),
347  GNUNET_a2s (addr, addrlen),
348  sctx->service_name);
349  }
350  return ret;
351 }
352 
353 
361 static char *
363 {
364  char *pif;
365 
366  if (GNUNET_OK !=
368  "PIDFILE", &pif))
369  return NULL;
370  return pif;
371 }
372 
373 
383 static int
385  struct LEGACY_SERVICE_Context *sctx,
386  const char *option)
387 {
388  char *opt;
389 
390  if (!GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name, option))
391  {
392  *ret = NULL;
393  return GNUNET_OK;
394  }
397  sctx->service_name,
398  option, &opt));
399  if (NULL == (*ret = GNUNET_STRINGS_parse_ipv4_policy (opt)))
400  {
402  _("Could not parse IPv4 network specification `%s' for `%s:%s'\n"),
403  opt, sctx->service_name, option);
404  GNUNET_free (opt);
405  return GNUNET_SYSERR;
406  }
407  GNUNET_free (opt);
408  return GNUNET_OK;
409 }
410 
411 
421 static int
423  struct LEGACY_SERVICE_Context *sctx,
424  const char *option)
425 {
426  char *opt;
427 
428  if (!GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name, option))
429  {
430  *ret = NULL;
431  return GNUNET_OK;
432  }
435  sctx->service_name,
436  option, &opt));
437  if (NULL == (*ret = GNUNET_STRINGS_parse_ipv6_policy (opt)))
438  {
440  _("Could not parse IPv6 network specification `%s' for `%s:%s'\n"),
441  opt, sctx->service_name, option);
442  GNUNET_free (opt);
443  return GNUNET_SYSERR;
444  }
445  GNUNET_free (opt);
446  return GNUNET_OK;
447 }
448 
449 
460 static void
461 add_unixpath (struct sockaddr **saddrs,
462  socklen_t *saddrlens,
463  const char *unixpath,
464  int abstract)
465 {
466 #ifdef AF_UNIX
467  struct sockaddr_un *un;
468 
469  un = GNUNET_new (struct sockaddr_un);
470  un->sun_family = AF_UNIX;
471  GNUNET_strlcpy (un->sun_path, unixpath, sizeof (un->sun_path));
472 #ifdef LINUX
473  if (GNUNET_YES == abstract)
474  un->sun_path[0] = '\0';
475 #endif
476 #if HAVE_SOCKADDR_UN_SUN_LEN
477  un->sun_len = (u_char) sizeof (struct sockaddr_un);
478 #endif
479  *saddrs = (struct sockaddr *) un;
480  *saddrlens = sizeof (struct sockaddr_un);
481 #else
482  /* this function should never be called
483  * unless AF_UNIX is defined! */
484  GNUNET_assert (0);
485 #endif
486 }
487 
488 
509 int
511  const struct GNUNET_CONFIGURATION_Handle *cfg,
512  struct sockaddr ***addrs,
513  socklen_t ** addr_lens)
514 {
515  int disablev6;
516  struct GNUNET_NETWORK_Handle *desc;
517  unsigned long long port;
518  char *unixpath;
519  struct addrinfo hints;
520  struct addrinfo *res;
521  struct addrinfo *pos;
522  struct addrinfo *next;
523  unsigned int i;
524  int resi;
525  int ret;
526  int abstract;
527  struct sockaddr **saddrs;
528  socklen_t *saddrlens;
529  char *hostname;
530 
531  *addrs = NULL;
532  *addr_lens = NULL;
533  desc = NULL;
534  if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "DISABLEV6"))
535  {
536  if (GNUNET_SYSERR ==
537  (disablev6 =
538  GNUNET_CONFIGURATION_get_value_yesno (cfg, service_name, "DISABLEV6")))
539  return GNUNET_SYSERR;
540  }
541  else
542  disablev6 = GNUNET_NO;
543 
544  if (! disablev6)
545  {
546  /* probe IPv6 support */
547  desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
548  if (NULL == desc)
549  {
550  if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
551  (EACCES == errno))
552  {
554  return GNUNET_SYSERR;
555  }
557  _("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
558  service_name, STRERROR (errno));
559  disablev6 = GNUNET_YES;
560  }
561  else
562  {
564  desc = NULL;
565  }
566  }
567 
568  port = 0;
569  if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT"))
570  {
571  if (GNUNET_OK !=
572  GNUNET_CONFIGURATION_get_value_number (cfg, service_name,
573  "PORT", &port))
574  {
576  _("Require valid port number for service `%s' in configuration!\n"),
577  service_name);
578  }
579  if (port > 65535)
580  {
582  _("Require valid port number for service `%s' in configuration!\n"),
583  service_name);
584  return GNUNET_SYSERR;
585  }
586  }
587 
588  if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "BINDTO"))
589  {
591  GNUNET_CONFIGURATION_get_value_string (cfg, service_name,
592  "BINDTO", &hostname));
593  }
594  else
595  hostname = NULL;
596 
597  unixpath = NULL;
598  abstract = GNUNET_NO;
599 #ifdef AF_UNIX
600  if ((GNUNET_YES ==
601  GNUNET_CONFIGURATION_have_value (cfg, service_name, "UNIXPATH")) &&
602  (GNUNET_OK ==
603  GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH",
604  &unixpath)) &&
605  (0 < strlen (unixpath)))
606  {
607  /* probe UNIX support */
608  struct sockaddr_un s_un;
609 
610  if (strlen (unixpath) >= sizeof (s_un.sun_path))
611  {
613  _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath,
614  (unsigned long long) sizeof (s_un.sun_path));
615  unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
617  _("Using `%s' instead\n"),
618  unixpath);
619  }
620 #ifdef LINUX
621  abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
622  "TESTING",
623  "USE_ABSTRACT_SOCKETS");
624  if (GNUNET_SYSERR == abstract)
625  abstract = GNUNET_NO;
626 #endif
627  if ((GNUNET_YES != abstract)
628  && (GNUNET_OK !=
631  "mkdir",
632  unixpath);
633  }
634  if (NULL != unixpath)
635  {
636  desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
637  if (NULL == desc)
638  {
639  if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
640  (EACCES == errno))
641  {
643  GNUNET_free_non_null (hostname);
644  GNUNET_free (unixpath);
645  return GNUNET_SYSERR;
646  }
648  _("Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
649  service_name,
650  STRERROR (errno));
651  GNUNET_free (unixpath);
652  unixpath = NULL;
653  }
654  else
655  {
657  desc = NULL;
658  }
659  }
660 #endif
661 
662  if ((0 == port) && (NULL == unixpath))
663  {
665  _("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
666  service_name);
667  GNUNET_free_non_null (hostname);
668  return GNUNET_SYSERR;
669  }
670  if (0 == port)
671  {
672  saddrs = GNUNET_malloc (2 * sizeof (struct sockaddr *));
673  saddrlens = GNUNET_malloc (2 * sizeof (socklen_t));
674  add_unixpath (saddrs, saddrlens, unixpath, abstract);
675  GNUNET_free_non_null (unixpath);
676  GNUNET_free_non_null (hostname);
677  *addrs = saddrs;
678  *addr_lens = saddrlens;
679  return 1;
680  }
681 
682  if (NULL != hostname)
683  {
685  "Resolving `%s' since that is where `%s' will bind to.\n",
686  hostname,
687  service_name);
688  memset (&hints, 0, sizeof (struct addrinfo));
689  if (disablev6)
690  hints.ai_family = AF_INET;
691  hints.ai_protocol = IPPROTO_TCP;
692  if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
693  (NULL == res))
694  {
696  _("Failed to resolve `%s': %s\n"),
697  hostname,
698  gai_strerror (ret));
699  GNUNET_free (hostname);
700  GNUNET_free_non_null (unixpath);
701  return GNUNET_SYSERR;
702  }
703  next = res;
704  i = 0;
705  while (NULL != (pos = next))
706  {
707  next = pos->ai_next;
708  if ((disablev6) && (pos->ai_family == AF_INET6))
709  continue;
710  i++;
711  }
712  if (0 == i)
713  {
715  _("Failed to find %saddress for `%s'.\n"),
716  disablev6 ? "IPv4 " : "",
717  hostname);
718  freeaddrinfo (res);
719  GNUNET_free (hostname);
720  GNUNET_free_non_null (unixpath);
721  return GNUNET_SYSERR;
722  }
723  resi = i;
724  if (NULL != unixpath)
725  resi++;
726  saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
727  saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
728  i = 0;
729  if (NULL != unixpath)
730  {
731  add_unixpath (saddrs, saddrlens, unixpath, abstract);
732  i++;
733  }
734  next = res;
735  while (NULL != (pos = next))
736  {
737  next = pos->ai_next;
738  if ((disablev6) && (AF_INET6 == pos->ai_family))
739  continue;
740  if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
741  continue; /* not TCP */
742  if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
743  continue; /* huh? */
744  LOG (GNUNET_ERROR_TYPE_DEBUG, "Service `%s' will bind to `%s'\n",
745  service_name, GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
746  if (AF_INET == pos->ai_family)
747  {
748  GNUNET_assert (sizeof (struct sockaddr_in) == pos->ai_addrlen);
749  saddrlens[i] = pos->ai_addrlen;
750  saddrs[i] = GNUNET_malloc (saddrlens[i]);
751  GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
752  ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
753  }
754  else
755  {
756  GNUNET_assert (AF_INET6 == pos->ai_family);
757  GNUNET_assert (sizeof (struct sockaddr_in6) == pos->ai_addrlen);
758  saddrlens[i] = pos->ai_addrlen;
759  saddrs[i] = GNUNET_malloc (saddrlens[i]);
760  GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
761  ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
762  }
763  i++;
764  }
765  GNUNET_free (hostname);
766  freeaddrinfo (res);
767  resi = i;
768  }
769  else
770  {
771  /* will bind against everything, just set port */
772  if (disablev6)
773  {
774  /* V4-only */
775  resi = 1;
776  if (NULL != unixpath)
777  resi++;
778  i = 0;
779  saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
780  saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
781  if (NULL != unixpath)
782  {
783  add_unixpath (saddrs, saddrlens, unixpath, abstract);
784  i++;
785  }
786  saddrlens[i] = sizeof (struct sockaddr_in);
787  saddrs[i] = GNUNET_malloc (saddrlens[i]);
788 #if HAVE_SOCKADDR_IN_SIN_LEN
789  ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
790 #endif
791  ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
792  ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
793  }
794  else
795  {
796  /* dual stack */
797  resi = 2;
798  if (NULL != unixpath)
799  resi++;
800  saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
801  saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
802  i = 0;
803  if (NULL != unixpath)
804  {
805  add_unixpath (saddrs, saddrlens, unixpath, abstract);
806  i++;
807  }
808  saddrlens[i] = sizeof (struct sockaddr_in6);
809  saddrs[i] = GNUNET_malloc (saddrlens[i]);
810 #if HAVE_SOCKADDR_IN_SIN_LEN
811  ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
812 #endif
813  ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
814  ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
815  i++;
816  saddrlens[i] = sizeof (struct sockaddr_in);
817  saddrs[i] = GNUNET_malloc (saddrlens[i]);
818 #if HAVE_SOCKADDR_IN_SIN_LEN
819  ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
820 #endif
821  ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
822  ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
823  }
824  }
825  GNUNET_free_non_null (unixpath);
826  *addrs = saddrs;
827  *addr_lens = saddrlens;
828  return resi;
829 }
830 
831 
832 #ifdef MINGW
833 
840 static int
841 receive_sockets_from_parent (struct LEGACY_SERVICE_Context *sctx)
842 {
843  const char *env_buf;
844  int fail;
845  uint64_t count;
846  uint64_t i;
847  HANDLE lsocks_pipe;
848 
849  env_buf = getenv ("GNUNET_OS_READ_LSOCKS");
850  if ((NULL == env_buf) || (strlen (env_buf) <= 0))
851  return GNUNET_NO;
852  /* Using W32 API directly here, because this pipe will
853  * never be used outside of this function, and it's just too much of a bother
854  * to create a GNUnet API that boxes a HANDLE (the way it is done with socks)
855  */
856  lsocks_pipe = (HANDLE) strtoul (env_buf, NULL, 10);
857  if ( (0 == lsocks_pipe) || (INVALID_HANDLE_VALUE == lsocks_pipe))
858  return GNUNET_NO;
859  fail = 1;
860  do
861  {
862  int ret;
863  int fail2;
864  DWORD rd;
865 
866  ret = ReadFile (lsocks_pipe, &count, sizeof (count), &rd, NULL);
867  if ((0 == ret) || (sizeof (count) != rd) || (0 == count))
868  break;
869  sctx->lsocks =
870  GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle *) * (count + 1));
871 
872  fail2 = 1;
873  for (i = 0; i < count; i++)
874  {
875  WSAPROTOCOL_INFOA pi;
876  uint64_t size;
877  SOCKET s;
878 
879  ret = ReadFile (lsocks_pipe, &size, sizeof (size), &rd, NULL);
880  if ( (0 == ret) || (sizeof (size) != rd) || (sizeof (pi) != size) )
881  break;
882  ret = ReadFile (lsocks_pipe, &pi, sizeof (pi), &rd, NULL);
883  if ( (0 == ret) || (sizeof (pi) != rd))
884  break;
885  s = WSASocketA (pi.iAddressFamily, pi.iSocketType, pi.iProtocol, &pi, 0, WSA_FLAG_OVERLAPPED);
887  if (NULL == sctx->lsocks[i])
888  break;
889  else if (i == count - 1)
890  fail2 = 0;
891  }
892  if (fail2)
893  break;
894  sctx->lsocks[count] = NULL;
895  fail = 0;
896  }
897  while (fail);
898 
899  CloseHandle (lsocks_pipe);
900 
901  if (fail)
902  {
904  _("Could not access a pre-bound socket, will try to bind myself\n"));
905  for (i = 0; (i < count) && (NULL != sctx->lsocks[i]); i++)
908  sctx->lsocks = NULL;
909  return GNUNET_NO;
910  }
911  return GNUNET_YES;
912 }
913 #endif
914 
915 
934 static int
936 {
937  struct GNUNET_TIME_Relative idleout;
938  int tolerant;
939 
940 #ifndef MINGW
941  const char *nfds;
942  unsigned int cnt;
943  int flags;
944 #endif
945 
946  if (GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name, "TIMEOUT"))
947  {
948  if (GNUNET_OK !=
950  "TIMEOUT", &idleout))
951  {
953  _("Specified value for `%s' of service `%s' is invalid\n"),
954  "TIMEOUT", sctx->service_name);
955  return GNUNET_SYSERR;
956  }
957  sctx->timeout = idleout;
958  }
959  else
961 
963  (sctx->cfg, sctx->service_name, "TOLERANT"))
964  {
965  if (GNUNET_SYSERR ==
966  (tolerant =
968  "TOLERANT")))
969  {
971  _("Specified value for `%s' of service `%s' is invalid\n"),
972  "TOLERANT", sctx->service_name);
973  return GNUNET_SYSERR;
974  }
975  }
976  else
977  tolerant = GNUNET_NO;
978 
979 #ifndef MINGW
980  errno = 0;
981  if ((NULL != (nfds = getenv ("LISTEN_FDS"))) &&
982  (1 == SSCANF (nfds, "%u", &cnt)) && (cnt > 0) && (cnt < FD_SETSIZE) &&
983  (cnt + 4 < FD_SETSIZE))
984  {
985  sctx->lsocks =
986  GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle *) * (cnt + 1));
987  while (0 < cnt--)
988  {
989  flags = fcntl (3 + cnt, F_GETFD);
990  if ((flags < 0) || (0 != (flags & FD_CLOEXEC)) ||
991  (NULL ==
992  (sctx->lsocks[cnt] = GNUNET_NETWORK_socket_box_native (3 + cnt))))
993  {
995  _
996  ("Could not access pre-bound socket %u, will try to bind myself\n"),
997  (unsigned int) 3 + cnt);
998  cnt++;
999  while (sctx->lsocks[cnt] != NULL)
1000  GNUNET_break (0 == GNUNET_NETWORK_socket_close (sctx->lsocks[cnt++]));
1001  GNUNET_free (sctx->lsocks);
1002  sctx->lsocks = NULL;
1003  break;
1004  }
1005  }
1006  unsetenv ("LISTEN_FDS");
1007  }
1008 #else
1009  if (getenv ("GNUNET_OS_READ_LSOCKS") != NULL)
1010  {
1011  receive_sockets_from_parent (sctx);
1012  putenv ("GNUNET_OS_READ_LSOCKS=");
1013  }
1014 #endif
1015 
1016  if ((NULL == sctx->lsocks) &&
1017  (GNUNET_SYSERR ==
1019  &sctx->addrs, &sctx->addrlens)))
1020  return GNUNET_SYSERR;
1021  sctx->require_found = tolerant ? GNUNET_NO : GNUNET_YES;
1022  sctx->match_uid =
1024  "UNIX_MATCH_UID");
1025  sctx->match_gid =
1027  "UNIX_MATCH_GID");
1028  process_acl4 (&sctx->v4_denied, sctx, "REJECT_FROM");
1029  process_acl4 (&sctx->v4_allowed, sctx, "ACCEPT_FROM");
1030  process_acl6 (&sctx->v6_denied, sctx, "REJECT_FROM6");
1031  process_acl6 (&sctx->v6_allowed, sctx, "ACCEPT_FROM6");
1032 
1033  return GNUNET_OK;
1034 }
1035 
1036 
1044 static char *
1046 {
1047  char *un;
1048 
1049  if (GNUNET_OK !=
1051  "USERNAME", &un))
1052  return NULL;
1053  return un;
1054 }
1055 
1056 
1064 static int
1066 {
1067  FILE *pidfd;
1068  char *pif;
1069  char *user;
1070  char *rdir;
1071  int len;
1072 
1073  if (NULL == (pif = get_pid_file_name (sctx)))
1074  return GNUNET_OK; /* no file desired */
1075  user = get_user_name (sctx);
1076  rdir = GNUNET_strdup (pif);
1077  len = strlen (rdir);
1078  while ((len > 0) && (rdir[len] != DIR_SEPARATOR))
1079  len--;
1080  rdir[len] = '\0';
1081  if (0 != ACCESS (rdir, F_OK))
1082  {
1083  /* we get to create a directory -- and claim it
1084  * as ours! */
1085  (void) GNUNET_DISK_directory_create (rdir);
1086  if ((NULL != user) && (0 < strlen (user)))
1087  GNUNET_DISK_file_change_owner (rdir, user);
1088  }
1089  if (0 != ACCESS (rdir, W_OK | X_OK))
1090  {
1091  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", rdir);
1092  GNUNET_free (rdir);
1093  GNUNET_free_non_null (user);
1094  GNUNET_free (pif);
1095  return GNUNET_SYSERR;
1096  }
1097  GNUNET_free (rdir);
1098  pidfd = FOPEN (pif, "w");
1099  if (NULL == pidfd)
1100  {
1102  GNUNET_free (pif);
1103  GNUNET_free_non_null (user);
1104  return GNUNET_SYSERR;
1105  }
1106  if (0 > FPRINTF (pidfd, "%u", pid))
1107  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fprintf", pif);
1108  GNUNET_break (0 == FCLOSE (pidfd));
1109  if ((NULL != user) && (0 < strlen (user)))
1110  GNUNET_DISK_file_change_owner (pif, user);
1111  GNUNET_free_non_null (user);
1112  GNUNET_free (pif);
1113  return GNUNET_OK;
1114 }
1115 
1116 
1122 static void
1123 shutdown_task (void *cls)
1124 {
1125  struct LEGACY_SERVICE_Context *service = cls;
1126  struct GNUNET_SERVER_Handle *server = service->server;
1127 
1128  service->shutdown_task = NULL;
1129  if (0 != (service->options & LEGACY_SERVICE_OPTION_SOFT_SHUTDOWN))
1131  else
1132  GNUNET_SERVER_destroy (server);
1133 }
1134 
1135 
1141 static void
1142 service_task (void *cls)
1143 {
1144  struct LEGACY_SERVICE_Context *sctx = cls;
1145  unsigned int i;
1146 
1147  GNUNET_RESOLVER_connect (sctx->cfg);
1148  if (NULL != sctx->lsocks)
1149  sctx->server
1151  sctx->timeout, sctx->require_found);
1152  else
1153  sctx->server
1154  = GNUNET_SERVER_create (&check_access, sctx, sctx->addrs, sctx->addrlens,
1155  sctx->timeout, sctx->require_found);
1156  if (NULL == sctx->server)
1157  {
1158  if (NULL != sctx->addrs)
1159  for (i = 0; NULL != sctx->addrs[i]; i++)
1161  _("Failed to start `%s' at `%s'\n"),
1162  sctx->service_name, GNUNET_a2s (sctx->addrs[i], sctx->addrlens[i]));
1163  sctx->ret = GNUNET_SYSERR;
1164  return;
1165  }
1166 #ifndef WINDOWS
1167  if (NULL != sctx->addrs)
1168  for (i = 0; NULL != sctx->addrs[i]; i++)
1169  if ((AF_UNIX == sctx->addrs[i]->sa_family)
1170  && ('\0' != ((const struct sockaddr_un *)sctx->addrs[i])->sun_path[0]))
1171  GNUNET_DISK_fix_permissions (((const struct sockaddr_un *)sctx->addrs[i])->sun_path,
1172  sctx->match_uid,
1173  sctx->match_gid);
1174 #endif
1175 
1176 
1178  {
1179  /* install a task that will kill the server
1180  * process if the scheduler ever gets a shutdown signal */
1182  sctx);
1183  }
1184  sctx->my_handlers = GNUNET_malloc (sizeof (defhandlers));
1185  GNUNET_memcpy (sctx->my_handlers, defhandlers, sizeof (defhandlers));
1186  i = 0;
1187  while (NULL != sctx->my_handlers[i].callback)
1188  sctx->my_handlers[i++].callback_cls = sctx;
1190  if (-1 != sctx->ready_confirm_fd)
1191  {
1192  GNUNET_break (1 == WRITE (sctx->ready_confirm_fd, ".", 1));
1193  GNUNET_break (0 == CLOSE (sctx->ready_confirm_fd));
1194  sctx->ready_confirm_fd = -1;
1195  write_pid_file (sctx, getpid ());
1196  }
1197  if (NULL != sctx->addrs)
1198  {
1199  i = 0;
1200  while (NULL != sctx->addrs[i])
1201  {
1202  LOG (GNUNET_ERROR_TYPE_INFO, _("Service `%s' runs at %s\n"),
1203  sctx->service_name, GNUNET_a2s (sctx->addrs[i], sctx->addrlens[i]));
1204  i++;
1205  }
1206  }
1207  sctx->task (sctx->task_cls, sctx->server, sctx->cfg);
1208 }
1209 
1210 
1217 static int
1219 {
1220 #ifndef MINGW
1221  pid_t pid;
1222  int nullfd;
1223  int filedes[2];
1224 
1225  if (0 != PIPE (filedes))
1226  {
1228  return GNUNET_SYSERR;
1229  }
1230  pid = fork ();
1231  if (pid < 0)
1232  {
1234  return GNUNET_SYSERR;
1235  }
1236  if (0 != pid)
1237  {
1238  /* Parent */
1239  char c;
1240 
1241  GNUNET_break (0 == CLOSE (filedes[1]));
1242  c = 'X';
1243  if (1 != READ (filedes[0], &c, sizeof (char)))
1245  fflush (stdout);
1246  switch (c)
1247  {
1248  case '.':
1249  exit (0);
1250  case 'I':
1251  LOG (GNUNET_ERROR_TYPE_INFO, _("Service process failed to initialize\n"));
1252  break;
1253  case 'S':
1255  _("Service process could not initialize server function\n"));
1256  break;
1257  case 'X':
1259  _("Service process failed to report status\n"));
1260  break;
1261  }
1262  exit (1); /* child reported error */
1263  }
1264  GNUNET_break (0 == CLOSE (0));
1265  GNUNET_break (0 == CLOSE (1));
1266  GNUNET_break (0 == CLOSE (filedes[0]));
1267  nullfd = OPEN ("/dev/null", O_RDWR | O_APPEND);
1268  if (nullfd < 0)
1269  return GNUNET_SYSERR;
1270  /* set stdin/stdout to /dev/null */
1271  if ((dup2 (nullfd, 0) < 0) || (dup2 (nullfd, 1) < 0))
1272  {
1274  (void) CLOSE (nullfd);
1275  return GNUNET_SYSERR;
1276  }
1277  (void) CLOSE (nullfd);
1278  /* Detach from controlling terminal */
1279  pid = setsid ();
1280  if (-1 == pid)
1282  sctx->ready_confirm_fd = filedes[1];
1283 #else
1284  /* FIXME: we probably need to do something else
1285  * elsewhere in order to fork the process itself... */
1286  FreeConsole ();
1287 #endif
1288  return GNUNET_OK;
1289 }
1290 
1291 
1298 static int
1300 {
1301  char *user;
1302 
1303  if (NULL == (user = get_user_name (sctx)))
1304  return GNUNET_OK; /* keep */
1305 #ifndef MINGW
1306  struct passwd *pws;
1307 
1308  errno = 0;
1309  pws = getpwnam (user);
1310  if (NULL == pws)
1311  {
1313  _("Cannot obtain information about user `%s': %s\n"), user,
1314  errno == 0 ? _("No such user") : STRERROR (errno));
1315  GNUNET_free (user);
1316  return GNUNET_SYSERR;
1317  }
1318  if ((0 != setgid (pws->pw_gid)) || (0 != setegid (pws->pw_gid)) ||
1319 #if HAVE_INITGROUPS
1320  (0 != initgroups (user, pws->pw_gid)) ||
1321 #endif
1322  (0 != setuid (pws->pw_uid)) || (0 != seteuid (pws->pw_uid)))
1323  {
1324  if ((0 != setregid (pws->pw_gid, pws->pw_gid)) ||
1325  (0 != setreuid (pws->pw_uid, pws->pw_uid)))
1326  {
1327  LOG (GNUNET_ERROR_TYPE_ERROR, _("Cannot change user/group to `%s': %s\n"),
1328  user, STRERROR (errno));
1329  GNUNET_free (user);
1330  return GNUNET_SYSERR;
1331  }
1332  }
1333 #endif
1334  GNUNET_free (user);
1335  return GNUNET_OK;
1336 }
1337 
1338 
1344 static void
1346 {
1347  char *pif = get_pid_file_name (sctx);
1348 
1349  if (NULL == pif)
1350  return; /* no PID file */
1351  if (0 != UNLINK (pif))
1353  GNUNET_free (pif);
1354 }
1355 
1356 
1370 int
1371 LEGACY_SERVICE_run (int argc, char *const *argv,
1372  const char *service_name,
1375  void *task_cls)
1376 {
1377 #define HANDLE_ERROR do { GNUNET_break (0); goto shutdown; } while (0)
1378 
1379  int err;
1380  int ret;
1381  char *cfg_fn;
1382  char *opt_cfg_fn;
1383  char *loglev;
1384  char *logfile;
1385  int do_daemonize;
1386  unsigned int i;
1387  unsigned long long skew_offset;
1388  unsigned long long skew_variance;
1389  long long clock_offset;
1390  struct LEGACY_SERVICE_Context sctx;
1392  const char *xdg;
1393 
1394  struct GNUNET_GETOPT_CommandLineOption service_options[] = {
1395  GNUNET_GETOPT_option_cfgfile (&opt_cfg_fn),
1397  "daemonize",
1398  gettext_noop ("do daemonize (detach from terminal)"),
1399  &do_daemonize),
1402  GNUNET_GETOPT_option_logfile (&logfile),
1403  GNUNET_GETOPT_option_version (PACKAGE_VERSION " " VCS_VERSION),
1405  };
1406  err = 1;
1407  do_daemonize = 0;
1408  logfile = NULL;
1409  loglev = NULL;
1410  opt_cfg_fn = NULL;
1411  xdg = getenv ("XDG_CONFIG_HOME");
1412  if (NULL != xdg)
1413  GNUNET_asprintf (&cfg_fn,
1414  "%s%s%s",
1415  xdg,
1418  else
1419  cfg_fn = GNUNET_strdup (GNUNET_OS_project_data_get ()->user_config_file);
1420  memset (&sctx, 0, sizeof (sctx));
1421  sctx.options = options;
1422  sctx.ready_confirm_fd = -1;
1423  sctx.ret = GNUNET_OK;
1425  sctx.task = task;
1426  sctx.task_cls = task_cls;
1427  sctx.service_name = service_name;
1428  sctx.cfg = cfg = GNUNET_CONFIGURATION_create ();
1429 
1430  /* setup subsystems */
1431  ret = GNUNET_GETOPT_run (service_name, service_options, argc, argv);
1432  if (GNUNET_SYSERR == ret)
1433  goto shutdown;
1434  if (GNUNET_NO == ret)
1435  {
1436  err = 0;
1437  goto shutdown;
1438  }
1439  if (GNUNET_OK != GNUNET_log_setup (service_name, loglev, logfile))
1440  HANDLE_ERROR;
1441  if (NULL == opt_cfg_fn)
1442  opt_cfg_fn = GNUNET_strdup (cfg_fn);
1443  if (GNUNET_YES == GNUNET_DISK_file_test (opt_cfg_fn))
1444  {
1445  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, opt_cfg_fn))
1446  {
1448  _("Malformed configuration file `%s', exit ...\n"),
1449  opt_cfg_fn);
1450  goto shutdown;
1451  }
1452  }
1453  else
1454  {
1455  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, NULL))
1456  {
1458  _("Malformed configuration, exit ...\n"));
1459  goto shutdown;
1460  }
1461  if (0 != strcmp (opt_cfg_fn, cfg_fn))
1463  _("Could not access configuration file `%s'\n"),
1464  opt_cfg_fn);
1465  }
1466  if (GNUNET_OK != setup_service (&sctx))
1467  goto shutdown;
1468  if ((1 == do_daemonize) && (GNUNET_OK != detach_terminal (&sctx)))
1469  HANDLE_ERROR;
1470  if (GNUNET_OK != set_user_id (&sctx))
1471  goto shutdown;
1473  "Service `%s' runs with configuration from `%s'\n",
1474  service_name,
1475  opt_cfg_fn);
1476  if ((GNUNET_OK ==
1477  GNUNET_CONFIGURATION_get_value_number (sctx.cfg, "TESTING",
1478  "SKEW_OFFSET", &skew_offset)) &&
1479  (GNUNET_OK ==
1480  GNUNET_CONFIGURATION_get_value_number (sctx.cfg, "TESTING",
1481  "SKEW_VARIANCE", &skew_variance)))
1482  {
1483  clock_offset = skew_offset - skew_variance;
1484  GNUNET_TIME_set_offset (clock_offset);
1485  LOG (GNUNET_ERROR_TYPE_DEBUG, "Skewing clock by %dll ms\n", clock_offset);
1486  }
1487  /* actually run service */
1488  err = 0;
1490  /* shutdown */
1491  if ((1 == do_daemonize) && (NULL != sctx.server))
1492  pid_file_delete (&sctx);
1494 
1495 shutdown:
1496  if (-1 != sctx.ready_confirm_fd)
1497  {
1498  if (1 != WRITE (sctx.ready_confirm_fd, err ? "I" : "S", 1))
1500  GNUNET_break (0 == CLOSE (sctx.ready_confirm_fd));
1501  }
1502 #if HAVE_MALLINFO
1503  {
1504  char *counter;
1505 
1506  if ( (GNUNET_YES ==
1507  GNUNET_CONFIGURATION_have_value (sctx.cfg, service_name,
1508  "GAUGER_HEAP")) &&
1509  (GNUNET_OK ==
1510  GNUNET_CONFIGURATION_get_value_string (sctx.cfg, service_name,
1511  "GAUGER_HEAP",
1512  &counter)) )
1513  {
1514  struct mallinfo mi;
1515 
1516  mi = mallinfo ();
1517  GAUGER (service_name, counter, mi.usmblks, "blocks");
1518  GNUNET_free (counter);
1519  }
1520  }
1521 #endif
1523  i = 0;
1524  if (NULL != sctx.addrs)
1525  while (NULL != sctx.addrs[i])
1526  GNUNET_free (sctx.addrs[i++]);
1527  GNUNET_free_non_null (sctx.addrs);
1529  GNUNET_free_non_null (logfile);
1530  GNUNET_free_non_null (loglev);
1531  GNUNET_free (cfg_fn);
1532  GNUNET_free_non_null (opt_cfg_fn);
1537 
1538  return err ? GNUNET_SYSERR : sctx.ret;
1539 }
1540 
1541 
1551 struct LEGACY_SERVICE_Context *
1553  const struct GNUNET_CONFIGURATION_Handle *cfg,
1555 {
1556  int i;
1557  struct LEGACY_SERVICE_Context *sctx;
1558 
1559  sctx = GNUNET_new (struct LEGACY_SERVICE_Context);
1560  sctx->ready_confirm_fd = -1; /* no daemonizing */
1561  sctx->ret = GNUNET_OK;
1563  sctx->service_name = service_name;
1564  sctx->cfg = cfg;
1565  sctx->options = options;
1566 
1567  /* setup subsystems */
1568  if (GNUNET_OK != setup_service (sctx))
1569  {
1570  LEGACY_SERVICE_stop (sctx);
1571  return NULL;
1572  }
1573  if (NULL != sctx->lsocks)
1574  sctx->server =
1576  sctx->timeout, sctx->require_found);
1577  else
1578  sctx->server =
1579  GNUNET_SERVER_create (&check_access, sctx, sctx->addrs, sctx->addrlens,
1580  sctx->timeout, sctx->require_found);
1581 
1582  if (NULL == sctx->server)
1583  {
1584  LEGACY_SERVICE_stop (sctx);
1585  return NULL;
1586  }
1587 #ifndef WINDOWS
1588  if (NULL != sctx->addrs)
1589  for (i = 0; NULL != sctx->addrs[i]; i++)
1590  if ((AF_UNIX == sctx->addrs[i]->sa_family)
1591  && ('\0' != ((const struct sockaddr_un *)sctx->addrs[i])->sun_path[0]))
1592  GNUNET_DISK_fix_permissions (((const struct sockaddr_un *)sctx->addrs[i])->sun_path,
1593  sctx->match_uid,
1594  sctx->match_gid);
1595 #endif
1596  sctx->my_handlers = GNUNET_malloc (sizeof (defhandlers));
1597  GNUNET_memcpy (sctx->my_handlers, defhandlers, sizeof (defhandlers));
1598  i = 0;
1599  while ((sctx->my_handlers[i].callback != NULL))
1600  sctx->my_handlers[i++].callback_cls = sctx;
1602  return sctx;
1603 }
1604 
1605 
1613 struct GNUNET_SERVER_Handle *
1615 {
1616  return ctx->server;
1617 }
1618 
1619 
1627 struct GNUNET_NETWORK_Handle *const*
1629 {
1630  return ctx->lsocks;
1631 }
1632 
1633 
1639 void
1641 {
1642  unsigned int i;
1643 
1644 #if HAVE_MALLINFO
1645  {
1646  char *counter;
1647 
1648  if ( (GNUNET_YES ==
1650  "GAUGER_HEAP")) &&
1651  (GNUNET_OK ==
1653  "GAUGER_HEAP",
1654  &counter)) )
1655  {
1656  struct mallinfo mi;
1657 
1658  mi = mallinfo ();
1659  GAUGER (sctx->service_name, counter, mi.usmblks, "blocks");
1660  GNUNET_free (counter);
1661  }
1662  }
1663 #endif
1664  if (NULL != sctx->shutdown_task)
1665  {
1667  sctx->shutdown_task = NULL;
1668  }
1669  if (NULL != sctx->server)
1670  GNUNET_SERVER_destroy (sctx->server);
1672  if (NULL != sctx->addrs)
1673  {
1674  i = 0;
1675  while (NULL != sctx->addrs[i])
1676  GNUNET_free (sctx->addrs[i++]);
1677  GNUNET_free (sctx->addrs);
1678  }
1684  GNUNET_free (sctx);
1685 }
1686 
1687 
1688 /* end of service.c */
static char * get_user_name(struct LEGACY_SERVICE_Context *sctx)
Get the name of the user that&#39;ll be used to provide the service.
int GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory)...
Definition: disk.c:669
struct GNUNET_STRINGS_IPv4NetworkPolicy * GNUNET_STRINGS_parse_ipv4_policy(const char *routeListX)
Parse an IPv4 network policy.
Definition: strings.c:1654
int LEGACY_SERVICE_run(int argc, char *const *argv, const char *service_name, enum LEGACY_SERVICE_Options options, LEGACY_SERVICE_Main task, void *task_cls)
Run a standard GNUnet service startup sequence (initialize loggers and configuration, parse options).
socklen_t * addrlens
Array of the lengths of the entries in addrs.
void GNUNET_SERVER_add_handlers(struct GNUNET_SERVER_Handle *server, const struct GNUNET_SERVER_MessageHandler *handlers)
Add additional handlers to an existing server.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
#define OPEN
Definition: plibc.h:651
static int check_ipv6_listed(const struct GNUNET_STRINGS_IPv6NetworkPolicy *list, const struct in6_addr *ip)
Check if the given IP address is in the list of IP addresses.
int GNUNET_CONFIGURATION_get_value_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
struct LEGACY_SERVICE_Context * LEGACY_SERVICE_start(const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg, enum LEGACY_SERVICE_Options options)
Run a service startup sequence within an existing initialized system.
static void handle_test(void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message)
Handler for TEST message.
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
int GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
const char * service_name
Name of our service.
GNUNET_SERVER_MessageCallback callback
Function to call for messages of "type".
struct GNUNET_SCHEDULER_Task * shutdown_task
Task ID of the shutdown task.
static int write_pid_file(struct LEGACY_SERVICE_Context *sctx, pid_t pid)
Write PID file.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_help(const char *about)
Defining the option to print the command line help text (-h option).
#define FPRINTF
Definition: plibc.h:683
int GNUNET_DISK_directory_create(const char *dir)
Implementation of "mkdir -p".
Definition: disk.c:714
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1293
#define LOG(kind,...)
Definition: arm_api.c:33
struct GNUNET_STRINGS_IPv6NetworkPolicy * GNUNET_STRINGS_parse_ipv6_policy(const char *routeListX)
Parse an IPv6 network policy.
Definition: strings.c:1854
Do not trigger server shutdown on signal at all; instead, allow for the user to terminate the server ...
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define STRERROR(i)
Definition: plibc.h:676
network in CIDR notation for IPV6.
static char * config_file
Set to the name of the config file used.
Definition: gnunet-arm.c:79
static int check_ipv4_listed(const struct GNUNET_STRINGS_IPv4NetworkPolicy *list, const struct in_addr *add)
Check if the given IP address is in the list of IP addresses.
static void service_task(void *cls)
Initial task for the service.
struct GNUNET_SERVER_Handle * GNUNET_SERVER_create(GNUNET_CONNECTION_AccessCheck access_cb, void *access_cb_cls, struct sockaddr *const *server_addr, const socklen_t *socklen, struct GNUNET_TIME_Relative idle_timeout, int require_found)
Create a new server.
static struct GNUNET_FS_UnindexContext * uc
static void pid_file_delete(struct LEGACY_SERVICE_Context *sctx)
Delete the PID file that was created by our parent.
void GNUNET_SCHEDULER_run(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Initialize and run scheduler.
Definition: scheduler.c:716
static int set_user_id(struct LEGACY_SERVICE_Context *sctx)
Set user ID.
struct in_addr netmask
IPv4 netmask.
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:833
#define GNUNET_NO
Definition: gnunet_common.h:81
static const struct GNUNET_SERVER_MessageHandler defhandlers[]
Default handlers for all services.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
struct sockaddr ** addrs
NULL-terminated array of addresses to bind to, NULL if we got pre-bound listen sockets.
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
Definition of a command line option.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_create(void)
Create a new configuration object.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
void GNUNET_TIME_set_offset(long long offset)
Set the timestamp offset for this instance.
Definition: time.c:53
static struct GNUNET_PEERINFO_Handle * pi
Handle to peerinfo service.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define FOPEN(f, m)
Definition: plibc.h:644
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_logfile(char **logfn)
Allow user to specify log file name (-l option)
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
struct GNUNET_SERVER_Handle * GNUNET_SERVER_create_with_sockets(GNUNET_CONNECTION_AccessCheck access_cb, void *access_cb_cls, struct GNUNET_NETWORK_Handle **lsocks, struct GNUNET_TIME_Relative idle_timeout, int require_found)
Create a new server.
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
int GNUNET_CONFIGURATION_load(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Load configuration.
#define UNLINK(f)
Definition: plibc.h:666
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
void(* LEGACY_SERVICE_Main)(void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg)
Function called by the service&#39;s run method to run service-specific setup code.
struct GNUNET_SERVER_MessageHandler * my_handlers
My (default) message handlers.
struct in_addr network
IPv4 address.
#define LOG_STRERROR_FILE(kind, op, fn)
Definition: datacache.c:34
#define FD_SETSIZE
Definition: winproc.h:39
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_version(const char *version)
Define the option to print the version of the application (-v option)
#define PIPE(h)
Definition: plibc.h:660
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
void * task_cls
Closure for task.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_memcpy(dst, src, n)
struct GNUNET_STRINGS_IPv6NetworkPolicy * v6_allowed
IPv6 addresses that are allowed to connect (if not set, all are allowed).
#define SOCKET(a, t, p)
Definition: plibc.h:711
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_box_native(SOCKTYPE fd)
Box a native socket (and check that it is a socket).
Definition: network.c:694
Trigger a SOFT server shutdown on signals, allowing active non-monitor clients to complete their tran...
struct GNUNET_NETWORK_Handle ** lsocks
NULL-terminated array of listen sockets we should take over.
int GNUNET_CONFIGURATION_have_value(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Test if we have a value for a particular option.
static int process_acl4(struct GNUNET_STRINGS_IPv4NetworkPolicy **ret, struct LEGACY_SERVICE_Context *sctx, const char *option)
Parse an IPv4 access control list.
struct GNUNET_SERVER_Handle * server
Handle for the server.
IPV4 network in CIDR notation.
void GNUNET_CONFIGURATION_destroy(struct GNUNET_CONFIGURATION_Handle *cfg)
Destroy configuration object.
#define CLOSE(f)
Definition: plibc.h:653
static char * option
Name of the option.
Definition: gnunet-config.c:38
static char buf[2048]
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_loglevel(char **level)
Define the &#39;-L&#39; log level option.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
static int setup_service(struct LEGACY_SERVICE_Context *sctx)
Setup addr, addrlen, idle_timeout based on configuration!
handle for a server
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages)...
static size_t write_test(void *cls, size_t size, void *buf)
Send a &#39;TEST&#39; message back to the client.
LEGACY_SERVICE_Options
Options for the service (bitmask).
#define DIR_SEPARATOR
Definition: plibc.h:631
struct GNUNET_STRINGS_IPv4NetworkPolicy * v4_allowed
IPv4 addresses that are allowed to connect (if not set, all are allowed).
int match_uid
Do we require a matching UID for UNIX domain socket connections? GNUNET_NO means that the UID does no...
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static int res
int LEGACY_SERVICE_get_server_addresses(const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg, struct sockaddr ***addrs, socklen_t **addr_lens)
Get the list of addresses that a server for the given service should bind to.
struct GNUNET_SERVER_Handle * LEGACY_SERVICE_get_server(struct LEGACY_SERVICE_Context *ctx)
Obtain the server used by a service.
int GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
int GNUNET_GETOPT_run(const char *binaryOptions, const struct GNUNET_GETOPT_CommandLineOption *allOptions, unsigned int argc, char *const *argv)
Parse the command line.
Definition: getopt.c:893
static void add_unixpath(struct sockaddr **saddrs, socklen_t *saddrlens, const char *unixpath, int abstract)
Add the given UNIX domain path as an address to the list (as the first entry).
#define READ(f, b, n)
Definition: plibc.h:668
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static unsigned int size
Size of the "table".
Definition: peer.c:67
#define WRITE(f, b, n)
Definition: plibc.h:667
struct GNUNET_SERVER_TransmitHandle * GNUNET_SERVER_notify_transmit_ready(struct GNUNET_SERVER_Client *client, size_t size, struct GNUNET_TIME_Relative timeout, GNUNET_CONNECTION_TransmitReadyNotify callback, void *callback_cls)
Notify us when the server has enough space to transmit a message of the given size to the given clien...
char * getenv()
struct GNUNET_STRINGS_IPv6NetworkPolicy * v6_denied
IPv6 addresses that are not allowed to connect.
struct GNUNET_NETWORK_Handle *const * LEGACY_SERVICE_get_listen_sockets(struct LEGACY_SERVICE_Context *ctx)
Get the NULL-terminated array of listen sockets for this service.
static int add
Desired action is to add a record.
int require_found
Do we close connections if we receive messages for which we have no handler?
#define GAUGER(category, counter, value, unit)
Definition: gauger.h:20
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_cfgfile(char **fn)
Allow user to specify configuration file name (-c option)
static char * hostname
Our hostname; we give this to all the peers we start.
#define HANDLE_ERROR
#define SSCANF
Definition: plibc.h:691
static uint16_t port
Port number.
Definition: gnunet-bcd.c:79
configuration data
Definition: configuration.c:85
Context for "service_task".
#define LOG_STRERROR(kind, syscall)
void LEGACY_SERVICE_stop(struct LEGACY_SERVICE_Context *sctx)
Stop a service that was started with "LEGACY_SERVICE_start".
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_flag(char shortName, const char *name, const char *description, int *val)
Allow user to specify a flag (which internally means setting an integer to 1/GNUNET_YES/GNUNET_OK.
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:134
void GNUNET_SERVER_receive_done(struct GNUNET_SERVER_Client *client, int success)
Resume receiving from this client, we are done processing the current request.
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_get(void)
int GNUNET_DISK_file_change_owner(const char *filename, const char *user)
Change owner of a file.
Definition: disk.c:1525
Credentials for UNIX domain sockets.
int GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
void GNUNET_DISK_fix_permissions(const char *fn, int require_uid_match, int require_gid_match)
Update POSIX permissions mask of a file on disk.
Definition: disk.c:498
handle to a socket
Definition: network.c:46
int ready_confirm_fd
If we are daemonizing, this FD is set to the pipe to the parent.
struct GNUNET_STRINGS_IPv4NetworkPolicy * v4_denied
IPv4 addresses that are not allowed to connect.
char * GNUNET_NETWORK_shorten_unixpath(char *unixpath)
Given a unixpath that is too long (larger than UNIX_PATH_MAX), shorten it to an acceptable length whi...
Definition: network.c:157
static int check_access(void *cls, const struct GNUNET_CONNECTION_Credentials *uc, const struct sockaddr *addr, socklen_t addrlen)
Check if access to the service is allowed from the given address.
#define FCLOSE(f)
Definition: plibc.h:645
Header for all communications.
int match_gid
Do we require a matching GID for UNIX domain socket connections? Ignored if match_uid is GNUNET_YES...
LEGACY_SERVICE_Main task
Main service-specific task to run.
#define GNUNET_YES
Definition: gnunet_common.h:80
handle for a client of the server
#define DIR_SEPARATOR_STR
Definition: plibc.h:632
int GNUNET_log_setup(const char *comp, const char *loglevel, const char *logfile)
Setup logging.
static int detach_terminal(struct LEGACY_SERVICE_Context *sctx)
Detach from terminal.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
enum LEGACY_SERVICE_Options options
Our options.
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
static char * get_pid_file_name(struct LEGACY_SERVICE_Context *sctx)
Get the name of the file where we will write the PID of the service.
#define ACCESS(p, m)
Definition: plibc.h:656
size_t GNUNET_strlcpy(char *dst, const char *src, size_t n)
Like strlcpy but portable.
void * callback_cls
Closure argument for callback.
void GNUNET_SERVER_destroy(struct GNUNET_SERVER_Handle *server)
Free resources held by this server.
void GNUNET_SERVER_stop_listening(struct GNUNET_SERVER_Handle *server)
Stop the listen socket and get ready to shutdown the server once only &#39;monitor&#39; clients are left...
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:604
static int list
Set if we should print a list of currently running services.
Definition: gnunet-arm.c:64
void GNUNET_RESOLVER_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create the connection to the resolver service.
Definition: resolver_api.c:254
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_MESSAGE_TYPE_TEST
Test if service is online.
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_TIME_Relative timeout
Idle timeout for server.
Time for relative time used by GNUnet, in microseconds.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
#define gettext_noop(String)
Definition: gettext.h:69
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:1037
static int process_acl6(struct GNUNET_STRINGS_IPv6NetworkPolicy **ret, struct LEGACY_SERVICE_Context *sctx, const char *option)
Parse an IPv6 access control list.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
int ret
Overall success/failure of the service start.