GNUnet  0.10.x
Data Structures | Macros | Functions | Variables
tcp_service_legacy.c File Reference
#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_protocols.h"
#include "gnunet_constants.h"
#include "gnunet_resolver_service.h"
Include dependency graph for tcp_service_legacy.c:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  LEGACY_SERVICE_Context
 Context for "service_task". More...
 

Macros

#define HANDLE_ERROR
 

Functions

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. More...
 
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. More...
 
static size_t write_test (void *cls, size_t size, void *buf)
 Send a 'TEST' message back to the client. More...
 
static void handle_test (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message)
 Handler for TEST message. More...
 
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. More...
 
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. More...
 
static int process_acl4 (struct GNUNET_STRINGS_IPv4NetworkPolicy **ret, struct LEGACY_SERVICE_Context *sctx, const char *option)
 Parse an IPv4 access control list. More...
 
static int process_acl6 (struct GNUNET_STRINGS_IPv6NetworkPolicy **ret, struct LEGACY_SERVICE_Context *sctx, const char *option)
 Parse an IPv6 access control list. More...
 
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). More...
 
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. More...
 
static int setup_service (struct LEGACY_SERVICE_Context *sctx)
 Setup addr, addrlen, idle_timeout based on configuration! More...
 
static char * get_user_name (struct LEGACY_SERVICE_Context *sctx)
 Get the name of the user that'll be used to provide the service. More...
 
static int write_pid_file (struct LEGACY_SERVICE_Context *sctx, pid_t pid)
 Write PID file. More...
 
static void shutdown_task (void *cls)
 Task run during shutdown. More...
 
static void service_task (void *cls)
 Initial task for the service. More...
 
static int detach_terminal (struct LEGACY_SERVICE_Context *sctx)
 Detach from terminal. More...
 
static int set_user_id (struct LEGACY_SERVICE_Context *sctx)
 Set user ID. More...
 
static void pid_file_delete (struct LEGACY_SERVICE_Context *sctx)
 Delete the PID file that was created by our parent. More...
 
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). More...
 
struct LEGACY_SERVICE_ContextLEGACY_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. More...
 
struct GNUNET_SERVER_HandleLEGACY_SERVICE_get_server (struct LEGACY_SERVICE_Context *ctx)
 Obtain the server used by a service. More...
 
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. More...
 
void LEGACY_SERVICE_stop (struct LEGACY_SERVICE_Context *sctx)
 Stop a service that was started with "LEGACY_SERVICE_start". More...
 

Variables

static const struct GNUNET_SERVER_MessageHandler defhandlers []
 Default handlers for all services. More...
 

Macro Definition Documentation

◆ HANDLE_ERROR

#define HANDLE_ERROR
Value:
do \
{ \
GNUNET_break(0); \
goto shutdown; \
} while (0)

Referenced by LEGACY_SERVICE_run().

Function Documentation

◆ check_ipv4_listed()

static int check_ipv4_listed ( const struct GNUNET_STRINGS_IPv4NetworkPolicy list,
const struct in_addr *  add 
)
static

Check if the given IP address is in the list of IP addresses.

Parameters
lista list of networks
addthe IP to check (in network byte order)
Returns
GNUNET_NO if the IP is not in the list, GNUNET_YES if it it is

Definition at line 48 of file tcp_service_legacy.c.

References GNUNET_NO, GNUNET_YES, GNUNET_STRINGS_IPv4NetworkPolicy::netmask, and GNUNET_STRINGS_IPv4NetworkPolicy::network.

Referenced by check_access().

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 }
struct in_addr netmask
IPv4 netmask.
#define GNUNET_NO
Definition: gnunet_common.h:78
struct in_addr network
IPv4 address.
static int add
Desired action is to add a record.
#define GNUNET_YES
Definition: gnunet_common.h:77
Here is the caller graph for this function:

◆ check_ipv6_listed()

static int check_ipv6_listed ( const struct GNUNET_STRINGS_IPv6NetworkPolicy list,
const struct in6_addr *  ip 
)
static

Check if the given IP address is in the list of IP addresses.

Parameters
lista list of networks
ipthe IP to check (in network byte order)
Returns
GNUNET_NO if the IP is not in the list, GNUNET_YES if it it is

Definition at line 75 of file tcp_service_legacy.c.

References GNUNET_NO, and GNUNET_YES.

Referenced by check_access().

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 }
static const struct GNUNET_CRYPTO_EcdsaPrivateKey zero
Public key of all zeros.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_YES
Definition: gnunet_common.h:77
Here is the caller graph for this function:

◆ write_test()

static size_t write_test ( void *  cls,
size_t  size,
void *  buf 
)
static

Send a 'TEST' message back to the client.

Parameters
clsthe 'struct GNUNET_SERVER_Client' to send TEST to
sizenumber of bytes available in 'buf'
bufwhere to copy the message
Returns
number of bytes written to 'buf'

Definition at line 240 of file tcp_service_legacy.c.

References GNUNET_MESSAGE_TYPE_TEST, GNUNET_OK, GNUNET_SERVER_receive_done(), GNUNET_SYSERR, msg, GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.

Referenced by handle_test().

241 {
242  struct GNUNET_SERVER_Client *client = cls;
243  struct GNUNET_MessageHeader *msg;
244 
245  if (size < sizeof(struct GNUNET_MessageHeader))
246  {
248  return 0; /* client disconnected */
249  }
250  msg = (struct GNUNET_MessageHeader *)buf;
251  msg->type = htons(GNUNET_MESSAGE_TYPE_TEST);
252  msg->size = htons(sizeof(struct GNUNET_MessageHeader));
254  return sizeof(struct GNUNET_MessageHeader);
255 }
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
static char buf[2048]
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static unsigned int size
Size of the "table".
Definition: peer.c:66
void GNUNET_SERVER_receive_done(struct GNUNET_SERVER_Client *client, int success)
Resume receiving from this client, we are done processing the current request.
Header for all communications.
handle for a client of the server
#define GNUNET_MESSAGE_TYPE_TEST
Test if service is online.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_test()

static void handle_test ( void *  cls,
struct GNUNET_SERVER_Client client,
const struct GNUNET_MessageHeader message 
)
static

Handler for TEST message.

Parameters
clsclosure (refers to service)
clientidentification of the client
messagethe actual message

Definition at line 266 of file tcp_service_legacy.c.

References GNUNET_SERVER_notify_transmit_ready(), GNUNET_SERVER_receive_done(), GNUNET_SYSERR, GNUNET_TIME_UNIT_FOREVER_REL, and write_test().

269 {
270  /* simply bounce message back to acknowledge */
271  if (NULL ==
273  sizeof(struct GNUNET_MessageHeader),
275  &write_test,
276  client))
278 }
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
static size_t write_test(void *cls, size_t size, void *buf)
Send a &#39;TEST&#39; message back to the client.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
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...
void GNUNET_SERVER_receive_done(struct GNUNET_SERVER_Client *client, int success)
Resume receiving from this client, we are done processing the current request.
Header for all communications.
Here is the call graph for this function:

◆ check_access()

static int check_access ( void *  cls,
const struct GNUNET_CONNECTION_Credentials uc,
const struct sockaddr *  addr,
socklen_t  addrlen 
)
static

Check if access to the service is allowed from the given address.

Parameters
clsclosure
uccredentials, if available, otherwise NULL
addraddress
addrlenlength of address
Returns
GNUNET_YES to allow, GNUNET_NO to deny, GNUNET_SYSERR for unknown address family (will be denied).

Definition at line 308 of file tcp_service_legacy.c.

References _, check_ipv4_listed(), check_ipv6_listed(), GNUNET_a2s(), GNUNET_assert, GNUNET_ERROR_TYPE_WARNING, GNUNET_OK, GNUNET_SYSERR, LOG, LEGACY_SERVICE_Context::ret, LEGACY_SERVICE_Context::service_name, LEGACY_SERVICE_Context::v4_allowed, LEGACY_SERVICE_Context::v4_denied, LEGACY_SERVICE_Context::v6_allowed, and LEGACY_SERVICE_Context::v6_denied.

Referenced by LEGACY_SERVICE_start(), and service_task().

312 {
313  struct LEGACY_SERVICE_Context *sctx = cls;
314  const struct sockaddr_in *i4;
315  const struct sockaddr_in6 *i6;
316  int ret;
317 
318  switch (addr->sa_family)
319  {
320  case AF_INET:
321  GNUNET_assert(addrlen == sizeof(struct sockaddr_in));
322  i4 = (const struct sockaddr_in *)addr;
323  ret = ((NULL == sctx->v4_allowed) ||
324  (check_ipv4_listed(sctx->v4_allowed, &i4->sin_addr))) &&
325  ((NULL == sctx->v4_denied) ||
326  (!check_ipv4_listed(sctx->v4_denied, &i4->sin_addr)));
327  break;
328 
329  case AF_INET6:
330  GNUNET_assert(addrlen == sizeof(struct sockaddr_in6));
331  i6 = (const struct sockaddr_in6 *)addr;
332  ret = ((NULL == sctx->v6_allowed) ||
333  (check_ipv6_listed(sctx->v6_allowed, &i6->sin6_addr))) &&
334  ((NULL == sctx->v6_denied) ||
335  (!check_ipv6_listed(sctx->v6_denied, &i6->sin6_addr)));
336  break;
337 
338  case AF_UNIX:
339  ret = GNUNET_OK; /* controlled using file-system ACL now */
340  break;
341 
342  default:
344  _("Unknown address family %d\n"),
345  addr->sa_family);
346  return GNUNET_SYSERR;
347  }
348  if (GNUNET_OK != ret)
349  {
351  _("Access from `%s' denied to service `%s'\n"),
352  GNUNET_a2s(addr, addrlen),
353  sctx->service_name);
354  }
355  return ret;
356 }
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.
const char * service_name
Name of our service.
#define LOG(kind,...)
Definition: arm_api.c:33
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
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.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
struct GNUNET_STRINGS_IPv6NetworkPolicy * v6_allowed
IPv6 addresses that are allowed to connect (if not set, all are allowed).
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)...
struct GNUNET_STRINGS_IPv4NetworkPolicy * v4_allowed
IPv4 addresses that are allowed to connect (if not set, all are allowed).
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
struct GNUNET_STRINGS_IPv6NetworkPolicy * v6_denied
IPv6 addresses that are not allowed to connect.
Context for "service_task".
struct GNUNET_STRINGS_IPv4NetworkPolicy * v4_denied
IPv4 addresses that are not allowed to connect.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_pid_file_name()

static char* get_pid_file_name ( struct LEGACY_SERVICE_Context sctx)
static

Get the name of the file where we will write the PID of the service.

Parameters
sctxservice context
Returns
name of the file for the process ID

Definition at line 367 of file tcp_service_legacy.c.

References LEGACY_SERVICE_Context::cfg, GNUNET_CONFIGURATION_get_value_filename(), GNUNET_OK, and LEGACY_SERVICE_Context::service_name.

Referenced by pid_file_delete(), and write_pid_file().

368 {
369  char *pif;
370 
372  sctx->service_name,
373  "PIDFILE",
374  &pif))
375  return NULL;
376  return pif;
377 }
const char * service_name
Name of our service.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
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.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_acl4()

static int process_acl4 ( struct GNUNET_STRINGS_IPv4NetworkPolicy **  ret,
struct LEGACY_SERVICE_Context sctx,
const char *  option 
)
static

Parse an IPv4 access control list.

Parameters
retlocation where to write the ACL (set)
sctxservice context to use to get the configuration
optionname of the ACL option to parse
Returns
GNUNET_SYSERR on parse error, GNUNET_OK on success (including no ACL configured)

Definition at line 390 of file tcp_service_legacy.c.

References _, LEGACY_SERVICE_Context::cfg, GNUNET_break, GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_have_value(), GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_OK, GNUNET_STRINGS_parse_ipv4_policy(), GNUNET_SYSERR, LOG, and LEGACY_SERVICE_Context::service_name.

Referenced by setup_service().

393 {
394  char *opt;
395 
397  {
398  *ret = NULL;
399  return GNUNET_OK;
400  }
403  sctx->service_name,
404  option,
405  &opt));
406  if (NULL == (*ret = GNUNET_STRINGS_parse_ipv4_policy(opt)))
407  {
409  _("Could not parse IPv4 network specification `%s' for `%s:%s'\n"),
410  opt,
411  sctx->service_name,
412  option);
413  GNUNET_free(opt);
414  return GNUNET_SYSERR;
415  }
416  GNUNET_free(opt);
417  return GNUNET_OK;
418 }
struct GNUNET_STRINGS_IPv4NetworkPolicy * GNUNET_STRINGS_parse_ipv4_policy(const char *routeListX)
Parse an IPv4 network policy.
Definition: strings.c:1519
const char * service_name
Name of our service.
#define LOG(kind,...)
Definition: arm_api.c:33
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
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 char * option
Name of the option.
Definition: gnunet-config.c:38
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
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.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_acl6()

static int process_acl6 ( struct GNUNET_STRINGS_IPv6NetworkPolicy **  ret,
struct LEGACY_SERVICE_Context sctx,
const char *  option 
)
static

Parse an IPv6 access control list.

Parameters
retlocation where to write the ACL (set)
sctxservice context to use to get the configuration
optionname of the ACL option to parse
Returns
GNUNET_SYSERR on parse error, GNUNET_OK on success (including no ACL configured)

Definition at line 431 of file tcp_service_legacy.c.

References _, LEGACY_SERVICE_Context::cfg, GNUNET_break, GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_have_value(), GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_OK, GNUNET_STRINGS_parse_ipv6_policy(), GNUNET_SYSERR, LOG, and LEGACY_SERVICE_Context::service_name.

Referenced by setup_service().

434 {
435  char *opt;
436 
438  {
439  *ret = NULL;
440  return GNUNET_OK;
441  }
444  sctx->service_name,
445  option,
446  &opt));
447  if (NULL == (*ret = GNUNET_STRINGS_parse_ipv6_policy(opt)))
448  {
450  _("Could not parse IPv6 network specification `%s' for `%s:%s'\n"),
451  opt,
452  sctx->service_name,
453  option);
454  GNUNET_free(opt);
455  return GNUNET_SYSERR;
456  }
457  GNUNET_free(opt);
458  return GNUNET_OK;
459 }
const char * service_name
Name of our service.
#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:1711
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
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 char * option
Name of the option.
Definition: gnunet-config.c:38
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
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.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_unixpath()

static void add_unixpath ( struct sockaddr **  saddrs,
socklen_t *  saddrlens,
const char *  unixpath,
int  abstract 
)
static

Add the given UNIX domain path as an address to the list (as the first entry).

Parameters
saddrsarray to update
saddrlenswhere to store the address length
unixpathpath to add
abstractGNUNET_YES to add an abstract UNIX domain socket. This parameter is ignore on systems other than LINUX

Definition at line 473 of file tcp_service_legacy.c.

References GNUNET_assert, GNUNET_new, GNUNET_strlcpy(), and GNUNET_YES.

Referenced by LEGACY_SERVICE_get_server_addresses().

477 {
478 #ifdef AF_UNIX
479  struct sockaddr_un *un;
480 
481  un = GNUNET_new(struct sockaddr_un);
482  un->sun_family = AF_UNIX;
483  GNUNET_strlcpy(un->sun_path, unixpath, sizeof(un->sun_path));
484 #ifdef LINUX
485  if (GNUNET_YES == abstract)
486  un->sun_path[0] = '\0';
487 #endif
488 #if HAVE_SOCKADDR_UN_SUN_LEN
489  un->sun_len = (u_char)sizeof(struct sockaddr_un);
490 #endif
491  *saddrs = (struct sockaddr *)un;
492  *saddrlens = sizeof(struct sockaddr_un);
493 #else
494  /* this function should never be called
495  * unless AF_UNIX is defined! */
496  GNUNET_assert(0);
497 #endif
498 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_YES
Definition: gnunet_common.h:77
size_t GNUNET_strlcpy(char *dst, const char *src, size_t n)
Like strlcpy but portable.
Definition: strings.c:219
Here is the call graph for this function:
Here is the caller graph for this function:

◆ LEGACY_SERVICE_get_server_addresses()

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.

Parameters
service_namename of the service
cfgconfiguration (which specifies the addresses)
addrsset (call by reference) to an array of pointers to the addresses the server should bind to and listen on; the array will be NULL-terminated (on success)
addr_lensset (call by reference) to an array of the lengths of the respective struct sockaddr struct in the addrs array (on success)
Returns
number of addresses found on success, GNUNET_SYSERR if the configuration did not specify reasonable finding information or if it specified a hostname that could not be resolved; GNUNET_NO if the number of addresses configured is zero (in this case, *addrs and *addr_lens will be set to NULL).

Definition at line 522 of file tcp_service_legacy.c.

References _, add_unixpath(), GNUNET_a2s(), GNUNET_assert, GNUNET_break, GNUNET_CONFIGURATION_get_value_filename(), GNUNET_CONFIGURATION_get_value_number(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_CONFIGURATION_have_value(), GNUNET_DISK_directory_create_for_file(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_free_non_null, GNUNET_log_strerror_file, GNUNET_malloc, GNUNET_memcpy, GNUNET_NETWORK_shorten_unixpath(), GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_create(), GNUNET_NO, GNUNET_OK, GNUNET_SYSERR, GNUNET_YES, hostname, LOG, LOG_STRERROR, port, res, and LEGACY_SERVICE_Context::ret.

Referenced by setup_service().

527 {
528  int disablev6;
529  struct GNUNET_NETWORK_Handle *desc;
530  unsigned long long port;
531  char *unixpath;
532  struct addrinfo hints;
533  struct addrinfo *res;
534  struct addrinfo *pos;
535  struct addrinfo *next;
536  unsigned int i;
537  int resi;
538  int ret;
539  int abstract;
540  struct sockaddr **saddrs;
541  socklen_t *saddrlens;
542  char *hostname;
543 
544  *addrs = NULL;
545  *addr_lens = NULL;
546  desc = NULL;
547  if (GNUNET_CONFIGURATION_have_value(cfg, service_name, "DISABLEV6"))
548  {
549  if (GNUNET_SYSERR ==
550  (disablev6 = GNUNET_CONFIGURATION_get_value_yesno(cfg,
551  service_name,
552  "DISABLEV6")))
553  return GNUNET_SYSERR;
554  }
555  else
556  disablev6 = GNUNET_NO;
557 
558  if (!disablev6)
559  {
560  /* probe IPv6 support */
561  desc = GNUNET_NETWORK_socket_create(PF_INET6, SOCK_STREAM, 0);
562  if (NULL == desc)
563  {
564  if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
565  (EACCES == errno))
566  {
568  return GNUNET_SYSERR;
569  }
571  _(
572  "Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
573  service_name,
574  strerror(errno));
575  disablev6 = GNUNET_YES;
576  }
577  else
578  {
580  desc = NULL;
581  }
582  }
583 
584  port = 0;
586  {
588  service_name,
589  "PORT",
590  &port))
591  {
593  _("Require valid port number for service `%s' in configuration!\n"),
594  service_name);
595  }
596  if (port > 65535)
597  {
599  _("Require valid port number for service `%s' in configuration!\n"),
600  service_name);
601  return GNUNET_SYSERR;
602  }
603  }
604 
605  if (GNUNET_CONFIGURATION_have_value(cfg, service_name, "BINDTO"))
606  {
609  service_name,
610  "BINDTO",
611  &hostname));
612  }
613  else
614  hostname = NULL;
615 
616  unixpath = NULL;
617  abstract = GNUNET_NO;
618 #ifdef AF_UNIX
619  if ((GNUNET_YES ==
620  GNUNET_CONFIGURATION_have_value(cfg, service_name, "UNIXPATH")) &&
622  service_name,
623  "UNIXPATH",
624  &unixpath)) &&
625  (0 < strlen(unixpath)))
626  {
627  /* probe UNIX support */
628  struct sockaddr_un s_un;
629 
630  if (strlen(unixpath) >= sizeof(s_un.sun_path))
631  {
633  _("UNIXPATH `%s' too long, maximum length is %llu\n"),
634  unixpath,
635  (unsigned long long)sizeof(s_un.sun_path));
636  unixpath = GNUNET_NETWORK_shorten_unixpath(unixpath);
637  LOG(GNUNET_ERROR_TYPE_INFO, _("Using `%s' instead\n"), unixpath);
638  }
639 #ifdef LINUX
641  "TESTING",
642  "USE_ABSTRACT_SOCKETS");
643  if (GNUNET_SYSERR == abstract)
644  abstract = GNUNET_NO;
645 #endif
646  if ((GNUNET_YES != abstract) &&
649  }
650  if (NULL != unixpath)
651  {
652  desc = GNUNET_NETWORK_socket_create(AF_UNIX, SOCK_STREAM, 0);
653  if (NULL == desc)
654  {
655  if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
656  (EACCES == errno))
657  {
659  GNUNET_free_non_null(hostname);
660  GNUNET_free(unixpath);
661  return GNUNET_SYSERR;
662  }
664  _(
665  "Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
666  service_name,
667  strerror(errno));
668  GNUNET_free(unixpath);
669  unixpath = NULL;
670  }
671  else
672  {
674  desc = NULL;
675  }
676  }
677 #endif
678 
679  if ((0 == port) && (NULL == unixpath))
680  {
682  _(
683  "Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
684  service_name);
685  GNUNET_free_non_null(hostname);
686  return GNUNET_SYSERR;
687  }
688  if (0 == port)
689  {
690  saddrs = GNUNET_malloc(2 * sizeof(struct sockaddr *));
691  saddrlens = GNUNET_malloc(2 * sizeof(socklen_t));
692  add_unixpath(saddrs, saddrlens, unixpath, abstract);
693  GNUNET_free_non_null(unixpath);
694  GNUNET_free_non_null(hostname);
695  *addrs = saddrs;
696  *addr_lens = saddrlens;
697  return 1;
698  }
699 
700  if (NULL != hostname)
701  {
703  "Resolving `%s' since that is where `%s' will bind to.\n",
704  hostname,
705  service_name);
706  memset(&hints, 0, sizeof(struct addrinfo));
707  if (disablev6)
708  hints.ai_family = AF_INET;
709  hints.ai_protocol = IPPROTO_TCP;
710  if ((0 != (ret = getaddrinfo(hostname, NULL, &hints, &res))) ||
711  (NULL == res))
712  {
714  _("Failed to resolve `%s': %s\n"),
715  hostname,
716  gai_strerror(ret));
717  GNUNET_free(hostname);
718  GNUNET_free_non_null(unixpath);
719  return GNUNET_SYSERR;
720  }
721  next = res;
722  i = 0;
723  while (NULL != (pos = next))
724  {
725  next = pos->ai_next;
726  if ((disablev6) && (pos->ai_family == AF_INET6))
727  continue;
728  i++;
729  }
730  if (0 == i)
731  {
733  _("Failed to find %saddress for `%s'.\n"),
734  disablev6 ? "IPv4 " : "",
735  hostname);
736  freeaddrinfo(res);
737  GNUNET_free(hostname);
738  GNUNET_free_non_null(unixpath);
739  return GNUNET_SYSERR;
740  }
741  resi = i;
742  if (NULL != unixpath)
743  resi++;
744  saddrs = GNUNET_malloc((resi + 1) * sizeof(struct sockaddr *));
745  saddrlens = GNUNET_malloc((resi + 1) * sizeof(socklen_t));
746  i = 0;
747  if (NULL != unixpath)
748  {
749  add_unixpath(saddrs, saddrlens, unixpath, abstract);
750  i++;
751  }
752  next = res;
753  while (NULL != (pos = next))
754  {
755  next = pos->ai_next;
756  if ((disablev6) && (AF_INET6 == pos->ai_family))
757  continue;
758  if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
759  continue; /* not TCP */
760  if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
761  continue; /* huh? */
763  "Service `%s' will bind to `%s'\n",
764  service_name,
765  GNUNET_a2s(pos->ai_addr, pos->ai_addrlen));
766  if (AF_INET == pos->ai_family)
767  {
768  GNUNET_assert(sizeof(struct sockaddr_in) == pos->ai_addrlen);
769  saddrlens[i] = pos->ai_addrlen;
770  saddrs[i] = GNUNET_malloc(saddrlens[i]);
771  GNUNET_memcpy(saddrs[i], pos->ai_addr, saddrlens[i]);
772  ((struct sockaddr_in *)saddrs[i])->sin_port = htons(port);
773  }
774  else
775  {
776  GNUNET_assert(AF_INET6 == pos->ai_family);
777  GNUNET_assert(sizeof(struct sockaddr_in6) == pos->ai_addrlen);
778  saddrlens[i] = pos->ai_addrlen;
779  saddrs[i] = GNUNET_malloc(saddrlens[i]);
780  GNUNET_memcpy(saddrs[i], pos->ai_addr, saddrlens[i]);
781  ((struct sockaddr_in6 *)saddrs[i])->sin6_port = htons(port);
782  }
783  i++;
784  }
785  GNUNET_free(hostname);
786  freeaddrinfo(res);
787  resi = i;
788  }
789  else
790  {
791  /* will bind against everything, just set port */
792  if (disablev6)
793  {
794  /* V4-only */
795  resi = 1;
796  if (NULL != unixpath)
797  resi++;
798  i = 0;
799  saddrs = GNUNET_malloc((resi + 1) * sizeof(struct sockaddr *));
800  saddrlens = GNUNET_malloc((resi + 1) * sizeof(socklen_t));
801  if (NULL != unixpath)
802  {
803  add_unixpath(saddrs, saddrlens, unixpath, abstract);
804  i++;
805  }
806  saddrlens[i] = sizeof(struct sockaddr_in);
807  saddrs[i] = GNUNET_malloc(saddrlens[i]);
808 #if HAVE_SOCKADDR_IN_SIN_LEN
809  ((struct sockaddr_in *)saddrs[i])->sin_len = saddrlens[i];
810 #endif
811  ((struct sockaddr_in *)saddrs[i])->sin_family = AF_INET;
812  ((struct sockaddr_in *)saddrs[i])->sin_port = htons(port);
813  }
814  else
815  {
816  /* dual stack */
817  resi = 2;
818  if (NULL != unixpath)
819  resi++;
820  saddrs = GNUNET_malloc((resi + 1) * sizeof(struct sockaddr *));
821  saddrlens = GNUNET_malloc((resi + 1) * sizeof(socklen_t));
822  i = 0;
823  if (NULL != unixpath)
824  {
825  add_unixpath(saddrs, saddrlens, unixpath, abstract);
826  i++;
827  }
828  saddrlens[i] = sizeof(struct sockaddr_in6);
829  saddrs[i] = GNUNET_malloc(saddrlens[i]);
830 #if HAVE_SOCKADDR_IN_SIN_LEN
831  ((struct sockaddr_in6 *)saddrs[i])->sin6_len = saddrlens[0];
832 #endif
833  ((struct sockaddr_in6 *)saddrs[i])->sin6_family = AF_INET6;
834  ((struct sockaddr_in6 *)saddrs[i])->sin6_port = htons(port);
835  i++;
836  saddrlens[i] = sizeof(struct sockaddr_in);
837  saddrs[i] = GNUNET_malloc(saddrlens[i]);
838 #if HAVE_SOCKADDR_IN_SIN_LEN
839  ((struct sockaddr_in *)saddrs[i])->sin_len = saddrlens[1];
840 #endif
841  ((struct sockaddr_in *)saddrs[i])->sin_family = AF_INET;
842  ((struct sockaddr_in *)saddrs[i])->sin_port = htons(port);
843  }
844  }
845  GNUNET_free_non_null(unixpath);
846  *addrs = saddrs;
847  *addr_lens = saddrlens;
848  return resi;
849 }
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.
#define LOG(kind,...)
Definition: arm_api.c:33
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:681
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
#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...
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 char * service_name
Option -s: service name (hash to get service descriptor)
Definition: gnunet-vpn.c:51
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 int res
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.
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 GNUNET_SYSERR
Definition: gnunet_common.h:76
static char * hostname
Our hostname; we give this to all the peers we start.
static uint16_t port
Port number.
Definition: gnunet-bcd.c:81
#define LOG_STRERROR(kind, syscall)
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.
handle to a socket
Definition: network.c:46
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:151
#define GNUNET_YES
Definition: gnunet_common.h:77
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".
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:548
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:900
Here is the call graph for this function:
Here is the caller graph for this function:

◆ setup_service()

static int setup_service ( struct LEGACY_SERVICE_Context sctx)
static

Setup addr, addrlen, idle_timeout based on configuration!

Configuration may specify:

  • PORT (where to bind to for TCP)
  • UNIXPATH (where to bind to for UNIX domain sockets)
  • TIMEOUT (after how many ms does an inactive service timeout);
  • DISABLEV6 (disable support for IPv6, otherwise we use dual-stack)
  • BINDTO (hostname or IP address to bind to, otherwise we take everything)
  • ACCEPT_FROM (only allow connections from specified IPv4 subnets)
  • ACCEPT_FROM6 (only allow connections from specified IPv6 subnets)
  • REJECT_FROM (disallow allow connections from specified IPv4 subnets)
  • REJECT_FROM6 (disallow allow connections from specified IPv6 subnets)
Parameters
sctxservice context to initialize
Returns
GNUNET_OK if configuration succeeded

Definition at line 871 of file tcp_service_legacy.c.

References _, LEGACY_SERVICE_Context::addrlens, LEGACY_SERVICE_Context::addrs, LEGACY_SERVICE_Context::cfg, getenv(), GNUNET_break, GNUNET_CONFIGURATION_get_value_time(), GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_CONFIGURATION_have_value(), GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_malloc, GNUNET_NETWORK_socket_box_native(), GNUNET_NETWORK_socket_close(), GNUNET_NO, GNUNET_OK, GNUNET_SYSERR, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, LEGACY_SERVICE_get_server_addresses(), LOG, LEGACY_SERVICE_Context::lsocks, LEGACY_SERVICE_Context::match_gid, LEGACY_SERVICE_Context::match_uid, process_acl4(), process_acl6(), LEGACY_SERVICE_Context::require_found, LEGACY_SERVICE_Context::service_name, LEGACY_SERVICE_Context::timeout, LEGACY_SERVICE_Context::v4_allowed, LEGACY_SERVICE_Context::v4_denied, LEGACY_SERVICE_Context::v6_allowed, and LEGACY_SERVICE_Context::v6_denied.

Referenced by LEGACY_SERVICE_run(), and LEGACY_SERVICE_start().

872 {
873  struct GNUNET_TIME_Relative idleout;
874  int tolerant;
875  const char *nfds;
876  unsigned int cnt;
877  int flags;
878 
880  sctx->service_name,
881  "TIMEOUT"))
882  {
884  sctx->service_name,
885  "TIMEOUT",
886  &idleout))
887  {
889  _("Specified value for `%s' of service `%s' is invalid\n"),
890  "TIMEOUT",
891  sctx->service_name);
892  return GNUNET_SYSERR;
893  }
894  sctx->timeout = idleout;
895  }
896  else
898 
900  sctx->service_name,
901  "TOLERANT"))
902  {
903  if (GNUNET_SYSERR ==
904  (tolerant = GNUNET_CONFIGURATION_get_value_yesno(sctx->cfg,
905  sctx->service_name,
906  "TOLERANT")))
907  {
909  _("Specified value for `%s' of service `%s' is invalid\n"),
910  "TOLERANT",
911  sctx->service_name);
912  return GNUNET_SYSERR;
913  }
914  }
915  else
916  tolerant = GNUNET_NO;
917 
918  errno = 0;
919  if ((NULL != (nfds = getenv("LISTEN_FDS"))) &&
920  (1 == sscanf(nfds, "%u", &cnt)) && (cnt > 0) && (cnt < FD_SETSIZE) &&
921  (cnt + 4 < FD_SETSIZE))
922  {
923  sctx->lsocks =
924  GNUNET_malloc(sizeof(struct GNUNET_NETWORK_Handle *) * (cnt + 1));
925  while (0 < cnt--)
926  {
927  flags = fcntl(3 + cnt, F_GETFD);
928  if ((flags < 0) || (0 != (flags & FD_CLOEXEC)) ||
929  (NULL ==
930  (sctx->lsocks[cnt] = GNUNET_NETWORK_socket_box_native(3 + cnt))))
931  {
933  _(
934  "Could not access pre-bound socket %u, will try to bind myself\n"),
935  (unsigned int)3 + cnt);
936  cnt++;
937  while (sctx->lsocks[cnt] != NULL)
938  GNUNET_break(0 == GNUNET_NETWORK_socket_close(sctx->lsocks[cnt++]));
939  GNUNET_free(sctx->lsocks);
940  sctx->lsocks = NULL;
941  break;
942  }
943  }
944  unsetenv("LISTEN_FDS");
945  }
946 
947  if ((NULL == sctx->lsocks) &&
949  sctx->cfg,
950  &sctx->addrs,
951  &sctx->addrlens)))
952  return GNUNET_SYSERR;
953  sctx->require_found = tolerant ? GNUNET_NO : GNUNET_YES;
955  sctx->service_name,
956  "UNIX_MATCH_UID");
958  sctx->service_name,
959  "UNIX_MATCH_GID");
960  process_acl4(&sctx->v4_denied, sctx, "REJECT_FROM");
961  process_acl4(&sctx->v4_allowed, sctx, "ACCEPT_FROM");
962  process_acl6(&sctx->v6_denied, sctx, "REJECT_FROM6");
963  process_acl6(&sctx->v6_allowed, sctx, "ACCEPT_FROM6");
964 
965  return GNUNET_OK;
966 }
socklen_t * addrlens
Array of the lengths of the entries in addrs.
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.
const char * service_name
Name of our service.
#define LOG(kind,...)
Definition: arm_api.c:33
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
struct sockaddr ** addrs
NULL-terminated array of addresses to bind to, NULL if we got pre-bound listen sockets.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
struct GNUNET_STRINGS_IPv6NetworkPolicy * v6_allowed
IPv6 addresses that are allowed to connect (if not set, all are allowed).
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:624
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.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
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.
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.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
char * getenv()
struct GNUNET_STRINGS_IPv6NetworkPolicy * v6_denied
IPv6 addresses that are not allowed to connect.
int require_found
Do we close connections if we receive messages for which we have no handler?
handle to a socket
Definition: network.c:46
struct GNUNET_STRINGS_IPv4NetworkPolicy * v4_denied
IPv4 addresses that are not allowed to connect.
int match_gid
Do we require a matching GID for UNIX domain socket connections? Ignored if match_uid is GNUNET_YES...
#define GNUNET_YES
Definition: gnunet_common.h:77
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".
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:548
#define GNUNET_malloc(size)
Wrapper around malloc.
#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.
static int process_acl6(struct GNUNET_STRINGS_IPv6NetworkPolicy **ret, struct LEGACY_SERVICE_Context *sctx, const char *option)
Parse an IPv6 access control list.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_user_name()

static char* get_user_name ( struct LEGACY_SERVICE_Context sctx)
static

Get the name of the user that'll be used to provide the service.

Parameters
sctxservice context
Returns
value of the 'USERNAME' option

Definition at line 977 of file tcp_service_legacy.c.

References LEGACY_SERVICE_Context::cfg, GNUNET_CONFIGURATION_get_value_filename(), GNUNET_OK, and LEGACY_SERVICE_Context::service_name.

Referenced by set_user_id(), and write_pid_file().

978 {
979  char *un;
980 
982  sctx->service_name,
983  "USERNAME",
984  &un))
985  return NULL;
986  return un;
987 }
const char * service_name
Name of our service.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
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.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ write_pid_file()

static int write_pid_file ( struct LEGACY_SERVICE_Context sctx,
pid_t  pid 
)
static

Write PID file.

Parameters
sctxservice context
pidPID to write (should be equal to 'getpid()'
Returns
GNUNET_OK on success (including no work to be done)

Definition at line 998 of file tcp_service_legacy.c.

References DIR_SEPARATOR, get_pid_file_name(), get_user_name(), GNUNET_break, GNUNET_DISK_directory_create(), GNUNET_DISK_file_change_owner(), GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_free_non_null, GNUNET_OK, GNUNET_strdup, GNUNET_SYSERR, len, and LOG_STRERROR_FILE.

Referenced by service_task().

999 {
1000  FILE *pidfd;
1001  char *pif;
1002  char *user;
1003  char *rdir;
1004  int len;
1005 
1006  if (NULL == (pif = get_pid_file_name(sctx)))
1007  return GNUNET_OK; /* no file desired */
1008  user = get_user_name(sctx);
1009  rdir = GNUNET_strdup(pif);
1010  len = strlen(rdir);
1011  while ((len > 0) && (rdir[len] != DIR_SEPARATOR))
1012  len--;
1013  rdir[len] = '\0';
1014  if (0 != access(rdir, F_OK))
1015  {
1016  /* we get to create a directory -- and claim it
1017  * as ours! */
1018  (void)GNUNET_DISK_directory_create(rdir);
1019  if ((NULL != user) && (0 < strlen(user)))
1020  GNUNET_DISK_file_change_owner(rdir, user);
1021  }
1022  if (0 != access(rdir, W_OK | X_OK))
1023  {
1024  LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_ERROR, "access", rdir);
1025  GNUNET_free(rdir);
1026  GNUNET_free_non_null(user);
1027  GNUNET_free(pif);
1028  return GNUNET_SYSERR;
1029  }
1030  GNUNET_free(rdir);
1031  pidfd = fopen(pif, "w");
1032  if (NULL == pidfd)
1033  {
1035  GNUNET_free(pif);
1036  GNUNET_free_non_null(user);
1037  return GNUNET_SYSERR;
1038  }
1039  if (0 > fprintf(pidfd, "%u", pid))
1041  GNUNET_break(0 == fclose(pidfd));
1042  if ((NULL != user) && (0 < strlen(user)))
1043  GNUNET_DISK_file_change_owner(pif, user);
1044  GNUNET_free_non_null(user);
1045  GNUNET_free(pif);
1046  return GNUNET_OK;
1047 }
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_directory_create(const char *dir)
Implementation of "mkdir -p".
Definition: disk.c:586
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define LOG_STRERROR_FILE(kind, op, fn)
Definition: datacache.c:34
#define DIR_SEPARATOR
Definition: platform.h:167
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
int GNUNET_DISK_file_change_owner(const char *filename, const char *user)
Change owner of a file.
Definition: disk.c:1163
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
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 GNUNET_free(ptr)
Wrapper around free.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
Here is the call graph for this function:
Here is the caller graph for this function:

◆ shutdown_task()

static void shutdown_task ( void *  cls)
static

Task run during shutdown.

Stops the server/service.

Parameters
clsthe struct LEGACY_SERVICE_Context

Definition at line 1056 of file tcp_service_legacy.c.

References GNUNET_SERVER_destroy(), GNUNET_SERVER_stop_listening(), LEGACY_SERVICE_OPTION_SOFT_SHUTDOWN, LEGACY_SERVICE_Context::options, LEGACY_SERVICE_Context::server, service, and LEGACY_SERVICE_Context::shutdown_task.

1057 {
1058  struct LEGACY_SERVICE_Context *service = cls;
1059  struct GNUNET_SERVER_Handle *server = service->server;
1060 
1061  service->shutdown_task = NULL;
1062  if (0 != (service->options & LEGACY_SERVICE_OPTION_SOFT_SHUTDOWN))
1064  else
1065  GNUNET_SERVER_destroy(server);
1066 }
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
struct GNUNET_SCHEDULER_Task * shutdown_task
Task ID of the shutdown task.
Trigger a SOFT server shutdown on signals, allowing active non-monitor clients to complete their tran...
struct GNUNET_SERVER_Handle * server
Handle for the server.
handle for a server
Context for "service_task".
enum LEGACY_SERVICE_Options options
Our options.
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...
Here is the call graph for this function:

◆ service_task()

static void service_task ( void *  cls)
static

Initial task for the service.

Parameters
clsservice context

Definition at line 1075 of file tcp_service_legacy.c.

References _, LEGACY_SERVICE_Context::addrlens, LEGACY_SERVICE_Context::addrs, GNUNET_SERVER_MessageHandler::callback, GNUNET_SERVER_MessageHandler::callback_cls, LEGACY_SERVICE_Context::cfg, check_access(), GNUNET_a2s(), GNUNET_break, GNUNET_DISK_fix_permissions(), GNUNET_ERROR_TYPE_INFO, GNUNET_malloc, GNUNET_memcpy, GNUNET_RESOLVER_connect(), GNUNET_SCHEDULER_add_shutdown(), GNUNET_SERVER_add_handlers(), GNUNET_SERVER_create(), GNUNET_SERVER_create_with_sockets(), GNUNET_SYSERR, LEGACY_SERVICE_OPTION_MANUAL_SHUTDOWN, LOG, LEGACY_SERVICE_Context::lsocks, LEGACY_SERVICE_Context::match_gid, LEGACY_SERVICE_Context::match_uid, LEGACY_SERVICE_Context::my_handlers, LEGACY_SERVICE_Context::options, LEGACY_SERVICE_Context::ready_confirm_fd, LEGACY_SERVICE_Context::require_found, LEGACY_SERVICE_Context::ret, LEGACY_SERVICE_Context::server, LEGACY_SERVICE_Context::service_name, LEGACY_SERVICE_Context::shutdown_task, LEGACY_SERVICE_Context::task, LEGACY_SERVICE_Context::task_cls, LEGACY_SERVICE_Context::timeout, and write_pid_file().

Referenced by LEGACY_SERVICE_run().

1076 {
1077  struct LEGACY_SERVICE_Context *sctx = cls;
1078  unsigned int i;
1079 
1081  if (NULL != sctx->lsocks)
1083  sctx,
1084  sctx->lsocks,
1085  sctx->timeout,
1086  sctx->require_found);
1087  else
1089  sctx,
1090  sctx->addrs,
1091  sctx->addrlens,
1092  sctx->timeout,
1093  sctx->require_found);
1094  if (NULL == sctx->server)
1095  {
1096  if (NULL != sctx->addrs)
1097  for (i = 0; NULL != sctx->addrs[i]; i++)
1099  _("Failed to start `%s' at `%s'\n"),
1100  sctx->service_name,
1101  GNUNET_a2s(sctx->addrs[i], sctx->addrlens[i]));
1102  sctx->ret = GNUNET_SYSERR;
1103  return;
1104  }
1105 
1106  if (NULL != sctx->addrs)
1107  for (i = 0; NULL != sctx->addrs[i]; i++)
1108  if ((AF_UNIX == sctx->addrs[i]->sa_family) &&
1109  ('\0' != ((const struct sockaddr_un *)sctx->addrs[i])->sun_path[0]))
1110  GNUNET_DISK_fix_permissions(((const struct sockaddr_un *)
1111  sctx->addrs[i])
1112  ->sun_path,
1113  sctx->match_uid,
1114  sctx->match_gid);
1115 
1117  {
1118  /* install a task that will kill the server
1119  * process if the scheduler ever gets a shutdown signal */
1121  }
1122  sctx->my_handlers = GNUNET_malloc(sizeof(defhandlers));
1124  i = 0;
1125  while (NULL != sctx->my_handlers[i].callback)
1126  sctx->my_handlers[i++].callback_cls = sctx;
1128  if (-1 != sctx->ready_confirm_fd)
1129  {
1130  GNUNET_break(1 == write(sctx->ready_confirm_fd, ".", 1));
1131  GNUNET_break(0 == close(sctx->ready_confirm_fd));
1132  sctx->ready_confirm_fd = -1;
1133  write_pid_file(sctx, getpid());
1134  }
1135  if (NULL != sctx->addrs)
1136  {
1137  i = 0;
1138  while (NULL != sctx->addrs[i])
1139  {
1141  _("Service `%s' runs at %s\n"),
1142  sctx->service_name,
1143  GNUNET_a2s(sctx->addrs[i], sctx->addrlens[i]));
1144  i++;
1145  }
1146  }
1147  sctx->task(sctx->task_cls, sctx->server, sctx->cfg);
1148 }
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.
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_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:1284
#define LOG(kind,...)
Definition: arm_api.c:33
Do not trigger server shutdown on signal at all; instead, allow for the user to terminate the server ...
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.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static const struct GNUNET_SERVER_MessageHandler defhandlers[]
Default handlers for all services.
struct sockaddr ** addrs
NULL-terminated array of addresses to bind to, NULL if we got pre-bound listen sockets.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
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.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
struct GNUNET_SERVER_MessageHandler * my_handlers
My (default) message handlers.
void * task_cls
Closure for task.
struct GNUNET_NETWORK_Handle ** lsocks
NULL-terminated array of listen sockets we should take over.
struct GNUNET_SERVER_Handle * server
Handle for the 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)...
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.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
int require_found
Do we close connections if we receive messages for which we have no handler?
static void shutdown_task(void *cls)
Task run during shutdown.
Context for "service_task".
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:376
int ready_confirm_fd
If we are daemonizing, this FD is set to the pipe to the parent.
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.
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.
enum LEGACY_SERVICE_Options options
Our options.
void * callback_cls
Closure argument for callback.
void GNUNET_RESOLVER_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create the connection to the resolver service.
Definition: resolver_api.c:252
#define GNUNET_malloc(size)
Wrapper around malloc.
struct GNUNET_TIME_Relative timeout
Idle timeout for server.
int ret
Overall success/failure of the service start.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ detach_terminal()

static int detach_terminal ( struct LEGACY_SERVICE_Context sctx)
static

Detach from terminal.

Parameters
sctxservice context
Returns
GNUNET_OK on success, GNUNET_SYSERR on error

Definition at line 1158 of file tcp_service_legacy.c.

References _, GNUNET_break, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_OK, GNUNET_SYSERR, LOG, LOG_STRERROR, pid, and LEGACY_SERVICE_Context::ready_confirm_fd.

Referenced by LEGACY_SERVICE_run().

1159 {
1160  pid_t pid;
1161  int nullfd;
1162  int filedes[2];
1163 
1164  if (0 != pipe(filedes))
1165  {
1167  return GNUNET_SYSERR;
1168  }
1169  pid = fork();
1170  if (pid < 0)
1171  {
1173  return GNUNET_SYSERR;
1174  }
1175  if (0 != pid)
1176  {
1177  /* Parent */
1178  char c;
1179 
1180  GNUNET_break(0 == close(filedes[1]));
1181  c = 'X';
1182  if (1 != read(filedes[0], &c, sizeof(char)))
1184  fflush(stdout);
1185  switch (c)
1186  {
1187  case '.':
1188  exit(0);
1189 
1190  case 'I':
1192  _("Service process failed to initialize\n"));
1193  break;
1194 
1195  case 'S':
1197  _("Service process could not initialize server function\n"));
1198  break;
1199 
1200  case 'X':
1202  _("Service process failed to report status\n"));
1203  break;
1204  }
1205  exit(1); /* child reported error */
1206  }
1207  GNUNET_break(0 == close(0));
1208  GNUNET_break(0 == close(1));
1209  GNUNET_break(0 == close(filedes[0]));
1210  nullfd = open("/dev/null", O_RDWR | O_APPEND);
1211  if (nullfd < 0)
1212  return GNUNET_SYSERR;
1213  /* set stdin/stdout to /dev/null */
1214  if ((dup2(nullfd, 0) < 0) || (dup2(nullfd, 1) < 0))
1215  {
1217  (void)close(nullfd);
1218  return GNUNET_SYSERR;
1219  }
1220  (void)close(nullfd);
1221  /* Detach from controlling terminal */
1222  pid = setsid();
1223  if (-1 == pid)
1225  sctx->ready_confirm_fd = filedes[1];
1226 
1227  return GNUNET_OK;
1228 }
#define LOG(kind,...)
Definition: arm_api.c:33
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
#define LOG_STRERROR(kind, syscall)
int ready_confirm_fd
If we are daemonizing, this FD is set to the pipe to the parent.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
Here is the caller graph for this function:

◆ set_user_id()

static int set_user_id ( struct LEGACY_SERVICE_Context sctx)
static

Set user ID.

Parameters
sctxservice context
Returns
GNUNET_OK on success, GNUNET_SYSERR on error

Definition at line 1238 of file tcp_service_legacy.c.

References _, get_user_name(), GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_OK, GNUNET_SYSERR, and LOG.

Referenced by LEGACY_SERVICE_run().

1239 {
1240  char *user;
1241 
1242  if (NULL == (user = get_user_name(sctx)))
1243  return GNUNET_OK; /* keep */
1244 
1245  struct passwd *pws;
1246 
1247  errno = 0;
1248  pws = getpwnam(user);
1249  if (NULL == pws)
1250  {
1252  _("Cannot obtain information about user `%s': %s\n"),
1253  user,
1254  errno == 0 ? _("No such user") : strerror(errno));
1255  GNUNET_free(user);
1256  return GNUNET_SYSERR;
1257  }
1258  if ((0 != setgid(pws->pw_gid)) || (0 != setegid(pws->pw_gid)) ||
1259 #if HAVE_INITGROUPS
1260  (0 != initgroups(user, pws->pw_gid)) ||
1261 #endif
1262  (0 != setuid(pws->pw_uid)) || (0 != seteuid(pws->pw_uid)))
1263  {
1264  if ((0 != setregid(pws->pw_gid, pws->pw_gid)) ||
1265  (0 != setreuid(pws->pw_uid, pws->pw_uid)))
1266  {
1268  _("Cannot change user/group to `%s': %s\n"),
1269  user,
1270  strerror(errno));
1271  GNUNET_free(user);
1272  return GNUNET_SYSERR;
1273  }
1274  }
1275 
1276  GNUNET_free(user);
1277  return GNUNET_OK;
1278 }
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.
#define LOG(kind,...)
Definition: arm_api.c:33
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pid_file_delete()

static void pid_file_delete ( struct LEGACY_SERVICE_Context sctx)
static

Delete the PID file that was created by our parent.

Parameters
sctxservice context

Definition at line 1287 of file tcp_service_legacy.c.

References get_pid_file_name(), GNUNET_ERROR_TYPE_WARNING, GNUNET_free, and LOG_STRERROR_FILE.

Referenced by LEGACY_SERVICE_run().

1288 {
1289  char *pif = get_pid_file_name(sctx);
1290 
1291  if (NULL == pif)
1292  return; /* no PID file */
1293  if (0 != unlink(pif))
1295  GNUNET_free(pif);
1296 }
#define LOG_STRERROR_FILE(kind, op, fn)
Definition: datacache.c:34
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 GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ LEGACY_SERVICE_run()

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).

Parameters
argcnumber of command line arguments
argvcommand line arguments
service_nameour service name
optionsservice options
taskmain task of the service
task_clsclosure for task
Returns
GNUNET_SYSERR on error, GNUNET_OK if we shutdown nicely

Definition at line 1313 of file tcp_service_legacy.c.

References _, LEGACY_SERVICE_Context::addrlens, LEGACY_SERVICE_Context::addrs, LEGACY_SERVICE_Context::cfg, config_file, detach_terminal(), DIR_SEPARATOR_STR, GAUGER, getenv(), gettext_noop, GNUNET_asprintf(), GNUNET_break, GNUNET_CONFIGURATION_create(), GNUNET_CONFIGURATION_destroy(), GNUNET_CONFIGURATION_get_value_number(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_have_value(), GNUNET_CONFIGURATION_load(), GNUNET_DISK_file_test(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_free_non_null, GNUNET_GETOPT_option_cfgfile(), GNUNET_GETOPT_OPTION_END, GNUNET_GETOPT_option_flag(), GNUNET_GETOPT_option_help(), GNUNET_GETOPT_option_logfile(), GNUNET_GETOPT_option_loglevel(), GNUNET_GETOPT_option_version(), GNUNET_GETOPT_run(), GNUNET_log, GNUNET_log_setup(), GNUNET_NO, GNUNET_OK, GNUNET_OS_project_data_get(), GNUNET_SCHEDULER_run(), GNUNET_strdup, GNUNET_SYSERR, GNUNET_TIME_set_offset(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, HANDLE_ERROR, LOG, LOG_STRERROR, LEGACY_SERVICE_Context::my_handlers, LEGACY_SERVICE_Context::options, pid_file_delete(), LEGACY_SERVICE_Context::ready_confirm_fd, LEGACY_SERVICE_Context::ret, LEGACY_SERVICE_Context::server, LEGACY_SERVICE_Context::service_name, service_task(), set_user_id(), setup_service(), LEGACY_SERVICE_Context::task, LEGACY_SERVICE_Context::task_cls, LEGACY_SERVICE_Context::timeout, LEGACY_SERVICE_Context::v4_allowed, LEGACY_SERVICE_Context::v4_denied, LEGACY_SERVICE_Context::v6_allowed, and LEGACY_SERVICE_Context::v6_denied.

1319 {
1320 #define HANDLE_ERROR \
1321  do \
1322  { \
1323  GNUNET_break(0); \
1324  goto shutdown; \
1325  } while (0)
1326 
1327  int err;
1328  int ret;
1329  char *cfg_fn;
1330  char *opt_cfg_fn;
1331  char *loglev;
1332  char *logfile;
1333  int do_daemonize;
1334  unsigned int i;
1335  unsigned long long skew_offset;
1336  unsigned long long skew_variance;
1337  long long clock_offset;
1338  struct LEGACY_SERVICE_Context sctx;
1340  const char *xdg;
1341 
1342  struct GNUNET_GETOPT_CommandLineOption service_options[] =
1343  { GNUNET_GETOPT_option_cfgfile(&opt_cfg_fn),
1345  "daemonize",
1346  gettext_noop(
1347  "do daemonize (detach from terminal)"),
1348  &do_daemonize),
1351  GNUNET_GETOPT_option_logfile(&logfile),
1352  GNUNET_GETOPT_option_version(PACKAGE_VERSION " " VCS_VERSION),
1354  err = 1;
1355  do_daemonize = 0;
1356  logfile = NULL;
1357  loglev = NULL;
1358  opt_cfg_fn = NULL;
1359  xdg = getenv("XDG_CONFIG_HOME");
1360  if (NULL != xdg)
1361  GNUNET_asprintf(&cfg_fn,
1362  "%s%s%s",
1363  xdg,
1366  else
1367  cfg_fn = GNUNET_strdup(GNUNET_OS_project_data_get()->user_config_file);
1368  memset(&sctx, 0, sizeof(sctx));
1369  sctx.options = options;
1370  sctx.ready_confirm_fd = -1;
1371  sctx.ret = GNUNET_OK;
1372  sctx.timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1373  sctx.task = task;
1374  sctx.task_cls = task_cls;
1375  sctx.service_name = service_name;
1376  sctx.cfg = cfg = GNUNET_CONFIGURATION_create();
1377 
1378  /* setup subsystems */
1379  ret = GNUNET_GETOPT_run(service_name, service_options, argc, argv);
1380  if (GNUNET_SYSERR == ret)
1381  goto shutdown;
1382  if (GNUNET_NO == ret)
1383  {
1384  err = 0;
1385  goto shutdown;
1386  }
1387  if (GNUNET_OK != GNUNET_log_setup(service_name, loglev, logfile))
1388  HANDLE_ERROR;
1389  if (NULL == opt_cfg_fn)
1390  opt_cfg_fn = GNUNET_strdup(cfg_fn);
1391  if (GNUNET_YES == GNUNET_DISK_file_test(opt_cfg_fn))
1392  {
1393  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load(cfg, opt_cfg_fn))
1394  {
1396  _("Malformed configuration file `%s', exit ...\n"),
1397  opt_cfg_fn);
1398  goto shutdown;
1399  }
1400  }
1401  else
1402  {
1403  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load(cfg, NULL))
1404  {
1406  _("Malformed configuration, exit ...\n"));
1407  goto shutdown;
1408  }
1409  if (0 != strcmp(opt_cfg_fn, cfg_fn))
1411  _("Could not access configuration file `%s'\n"),
1412  opt_cfg_fn);
1413  }
1414  if (GNUNET_OK != setup_service(&sctx))
1415  goto shutdown;
1416  if ((1 == do_daemonize) && (GNUNET_OK != detach_terminal(&sctx)))
1417  HANDLE_ERROR;
1418  if (GNUNET_OK != set_user_id(&sctx))
1419  goto shutdown;
1421  "Service `%s' runs with configuration from `%s'\n",
1422  service_name,
1423  opt_cfg_fn);
1425  "TESTING",
1426  "SKEW_OFFSET",
1427  &skew_offset)) &&
1429  "TESTING",
1430  "SKEW_VARIANCE",
1431  &skew_variance)))
1432  {
1433  clock_offset = skew_offset - skew_variance;
1434  GNUNET_TIME_set_offset(clock_offset);
1435  LOG(GNUNET_ERROR_TYPE_DEBUG, "Skewing clock by %dll ms\n", clock_offset);
1436  }
1437  /* actually run service */
1438  err = 0;
1440  /* shutdown */
1441  if ((1 == do_daemonize) && (NULL != sctx.server))
1442  pid_file_delete(&sctx);
1443  GNUNET_free_non_null(sctx.my_handlers);
1444 
1445 shutdown:
1446  if (-1 != sctx.ready_confirm_fd)
1447  {
1448  if (1 != write(sctx.ready_confirm_fd, err ? "I" : "S", 1))
1450  GNUNET_break(0 == close(sctx.ready_confirm_fd));
1451  }
1452 #if HAVE_MALLINFO
1453  {
1454  char *counter;
1455 
1457  service_name,
1458  "GAUGER_HEAP")) &&
1460  service_name,
1461  "GAUGER_HEAP",
1462  &counter)))
1463  {
1464  struct mallinfo mi;
1465 
1466  mi = mallinfo();
1467  GAUGER(service_name, counter, mi.usmblks, "blocks");
1468  GNUNET_free(counter);
1469  }
1470  }
1471 #endif
1473  i = 0;
1474  if (NULL != sctx.addrs)
1475  while (NULL != sctx.addrs[i])
1476  GNUNET_free(sctx.addrs[i++]);
1477  GNUNET_free_non_null(sctx.addrs);
1478  GNUNET_free_non_null(sctx.addrlens);
1479  GNUNET_free_non_null(logfile);
1480  GNUNET_free_non_null(loglev);
1481  GNUNET_free(cfg_fn);
1482  GNUNET_free_non_null(opt_cfg_fn);
1483  GNUNET_free_non_null(sctx.v4_denied);
1484  GNUNET_free_non_null(sctx.v6_denied);
1485  GNUNET_free_non_null(sctx.v4_allowed);
1486  GNUNET_free_non_null(sctx.v6_allowed);
1487 
1488  return err ? GNUNET_SYSERR : sctx.ret;
1489 }
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:541
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.
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_help(const char *about)
Defining the option to print the command line help text (-h option).
#define LOG(kind,...)
Definition: arm_api.c:33
static char * config_file
Set to the name of the config file used.
Definition: gnunet-arm.c:79
static void service_task(void *cls)
Initial task for the service.
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:707
static int set_user_id(struct LEGACY_SERVICE_Context *sctx)
Set user ID.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
Definition of a command line option.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_create(void)
Create a new configuration object.
void GNUNET_TIME_set_offset(long long offset)
Set the timestamp offset for this instance.
Definition: time.c:53
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
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
int GNUNET_CONFIGURATION_load(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Load configuration.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_version(const char *version)
Define the option to print the version of the application (-v option)
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
#define DIR_SEPARATOR_STR
Definition: platform.h:168
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 char * service_name
Option -s: service name (hash to get service descriptor)
Definition: gnunet-vpn.c:51
void GNUNET_CONFIGURATION_destroy(struct GNUNET_CONFIGURATION_Handle *cfg)
Destroy configuration object.
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!
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.
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
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:886
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
char * getenv()
#define GAUGER(category, counter, value, unit)
Definition: gauger.h:18
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_cfgfile(char **fn)
Allow user to specify configuration file name (-c option)
#define HANDLE_ERROR
configuration data
Definition: configuration.c:83
Context for "service_task".
#define LOG_STRERROR(kind, syscall)
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,...)
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_get(void)
#define GNUNET_YES
Definition: gnunet_common.h:77
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.
#define GNUNET_free(ptr)
Wrapper around free.
#define gettext_noop(String)
Definition: gettext.h:69
Here is the call graph for this function:

◆ LEGACY_SERVICE_start()

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.

Parameters
service_nameour service name
cfgconfiguration to use
optionsservice options
Returns
NULL on error, service handle

Definition at line 1502 of file tcp_service_legacy.c.

References LEGACY_SERVICE_Context::addrlens, LEGACY_SERVICE_Context::addrs, GNUNET_SERVER_MessageHandler::callback, GNUNET_SERVER_MessageHandler::callback_cls, LEGACY_SERVICE_Context::cfg, check_access(), GNUNET_DISK_fix_permissions(), GNUNET_malloc, GNUNET_memcpy, GNUNET_new, GNUNET_OK, GNUNET_SERVER_add_handlers(), GNUNET_SERVER_create(), GNUNET_SERVER_create_with_sockets(), GNUNET_TIME_UNIT_FOREVER_REL, LEGACY_SERVICE_stop(), LEGACY_SERVICE_Context::lsocks, LEGACY_SERVICE_Context::match_gid, LEGACY_SERVICE_Context::match_uid, LEGACY_SERVICE_Context::my_handlers, LEGACY_SERVICE_Context::options, LEGACY_SERVICE_Context::ready_confirm_fd, LEGACY_SERVICE_Context::require_found, LEGACY_SERVICE_Context::ret, LEGACY_SERVICE_Context::server, LEGACY_SERVICE_Context::service_name, setup_service(), and LEGACY_SERVICE_Context::timeout.

Referenced by libgnunet_plugin_transport_tcp_init().

1505 {
1506  int i;
1507  struct LEGACY_SERVICE_Context *sctx;
1508 
1509  sctx = GNUNET_new(struct LEGACY_SERVICE_Context);
1510  sctx->ready_confirm_fd = -1; /* no daemonizing */
1511  sctx->ret = GNUNET_OK;
1513  sctx->service_name = service_name;
1514  sctx->cfg = cfg;
1515  sctx->options = options;
1516 
1517  /* setup subsystems */
1518  if (GNUNET_OK != setup_service(sctx))
1519  {
1520  LEGACY_SERVICE_stop(sctx);
1521  return NULL;
1522  }
1523  if (NULL != sctx->lsocks)
1525  sctx,
1526  sctx->lsocks,
1527  sctx->timeout,
1528  sctx->require_found);
1529  else
1531  sctx,
1532  sctx->addrs,
1533  sctx->addrlens,
1534  sctx->timeout,
1535  sctx->require_found);
1536 
1537  if (NULL == sctx->server)
1538  {
1539  LEGACY_SERVICE_stop(sctx);
1540  return NULL;
1541  }
1542 
1543  if (NULL != sctx->addrs)
1544  for (i = 0; NULL != sctx->addrs[i]; i++)
1545  if ((AF_UNIX == sctx->addrs[i]->sa_family) &&
1546  ('\0' != ((const struct sockaddr_un *)sctx->addrs[i])->sun_path[0]))
1547  GNUNET_DISK_fix_permissions(((const struct sockaddr_un *)
1548  sctx->addrs[i])
1549  ->sun_path,
1550  sctx->match_uid,
1551  sctx->match_gid);
1552 
1553  sctx->my_handlers = GNUNET_malloc(sizeof(defhandlers));
1555  i = 0;
1556  while ((sctx->my_handlers[i].callback != NULL))
1557  sctx->my_handlers[i++].callback_cls = sctx;
1559  return sctx;
1560 }
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.
const char * service_name
Name of our service.
GNUNET_SERVER_MessageCallback callback
Function to call for messages of "type".
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
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.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static const struct GNUNET_SERVER_MessageHandler defhandlers[]
Default handlers for all services.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
struct sockaddr ** addrs
NULL-terminated array of addresses to bind to, NULL if we got pre-bound listen sockets.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
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.
struct GNUNET_SERVER_MessageHandler * my_handlers
My (default) message handlers.
struct GNUNET_NETWORK_Handle ** lsocks
NULL-terminated array of listen sockets we should take over.
struct GNUNET_SERVER_Handle * server
Handle for the server.
static char * service_name
Option -s: service name (hash to get service descriptor)
Definition: gnunet-vpn.c:51
#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!
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 struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
int require_found
Do we close connections if we receive messages for which we have no handler?
Context for "service_task".
void LEGACY_SERVICE_stop(struct LEGACY_SERVICE_Context *sctx)
Stop a service that was started with "LEGACY_SERVICE_start".
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:376
int ready_confirm_fd
If we are daemonizing, this FD is set to the pipe to the parent.
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.
int match_gid
Do we require a matching GID for UNIX domain socket connections? Ignored if match_uid is GNUNET_YES...
enum LEGACY_SERVICE_Options options
Our options.
void * callback_cls
Closure argument for callback.
#define GNUNET_malloc(size)
Wrapper around malloc.
struct GNUNET_TIME_Relative timeout
Idle timeout for server.
int ret
Overall success/failure of the service start.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ LEGACY_SERVICE_get_server()

struct GNUNET_SERVER_Handle* LEGACY_SERVICE_get_server ( struct LEGACY_SERVICE_Context ctx)

Obtain the server used by a service.

Note that the server must NOT be destroyed by the caller.

Parameters
ctxthe service context returned from the start function
Returns
handle to the server for this service, NULL if there is none

Definition at line 1571 of file tcp_service_legacy.c.

References LEGACY_SERVICE_Context::server.

Referenced by libgnunet_plugin_transport_tcp_init().

1572 {
1573  return ctx->server;
1574 }
struct GNUNET_SERVER_Handle * server
Handle for the server.
Here is the caller graph for this function:

◆ LEGACY_SERVICE_get_listen_sockets()

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.

Parameters
ctxservice context to query
Returns
NULL if there are no listen sockets, otherwise NULL-terminated array of listen sockets.

Definition at line 1585 of file tcp_service_legacy.c.

References LEGACY_SERVICE_Context::lsocks.

Referenced by libgnunet_plugin_transport_tcp_init().

1586 {
1587  return ctx->lsocks;
1588 }
struct GNUNET_NETWORK_Handle ** lsocks
NULL-terminated array of listen sockets we should take over.
Here is the caller graph for this function:

◆ LEGACY_SERVICE_stop()

void LEGACY_SERVICE_stop ( struct LEGACY_SERVICE_Context sctx)

Stop a service that was started with "LEGACY_SERVICE_start".

Stops a service that was started with GNUNET_SERVICE_start().

Parameters
sctxthe service context returned from the start function

Definition at line 1597 of file tcp_service_legacy.c.

References LEGACY_SERVICE_Context::addrlens, LEGACY_SERVICE_Context::addrs, LEGACY_SERVICE_Context::cfg, GAUGER, GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_have_value(), GNUNET_free, GNUNET_free_non_null, GNUNET_OK, GNUNET_SCHEDULER_cancel(), GNUNET_SERVER_destroy(), GNUNET_YES, LEGACY_SERVICE_Context::my_handlers, LEGACY_SERVICE_Context::server, LEGACY_SERVICE_Context::service_name, LEGACY_SERVICE_Context::shutdown_task, LEGACY_SERVICE_Context::v4_allowed, LEGACY_SERVICE_Context::v4_denied, LEGACY_SERVICE_Context::v6_allowed, and LEGACY_SERVICE_Context::v6_denied.

Referenced by LEGACY_SERVICE_start(), libgnunet_plugin_transport_tcp_done(), and libgnunet_plugin_transport_tcp_init().

1598 {
1599  unsigned int i;
1600 
1601 #if HAVE_MALLINFO
1602  {
1603  char *counter;
1604 
1606  sctx->service_name,
1607  "GAUGER_HEAP")) &&
1609  sctx->service_name,
1610  "GAUGER_HEAP",
1611  &counter)))
1612  {
1613  struct mallinfo mi;
1614 
1615  mi = mallinfo();
1616  GAUGER(sctx->service_name, counter, mi.usmblks, "blocks");
1617  GNUNET_free(counter);
1618  }
1619  }
1620 #endif
1621  if (NULL != sctx->shutdown_task)
1622  {
1624  sctx->shutdown_task = NULL;
1625  }
1626  if (NULL != sctx->server)
1629  if (NULL != sctx->addrs)
1630  {
1631  i = 0;
1632  while (NULL != sctx->addrs[i])
1633  GNUNET_free(sctx->addrs[i++]);
1634  GNUNET_free(sctx->addrs);
1635  }
1641  GNUNET_free(sctx);
1642 }
socklen_t * addrlens
Array of the lengths of the entries in addrs.
const char * service_name
Name of our service.
struct GNUNET_SCHEDULER_Task * shutdown_task
Task ID of the shutdown task.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
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.
struct GNUNET_SERVER_MessageHandler * my_handlers
My (default) message handlers.
struct GNUNET_STRINGS_IPv6NetworkPolicy * v6_allowed
IPv6 addresses that are allowed to connect (if not set, all are allowed).
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.
struct GNUNET_SERVER_Handle * server
Handle for the server.
struct GNUNET_STRINGS_IPv4NetworkPolicy * v4_allowed
IPv4 addresses that are allowed to connect (if not set, all are allowed).
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
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.
struct GNUNET_STRINGS_IPv6NetworkPolicy * v6_denied
IPv6 addresses that are not allowed to connect.
#define GAUGER(category, counter, value, unit)
Definition: gauger.h:18
struct GNUNET_STRINGS_IPv4NetworkPolicy * v4_denied
IPv4 addresses that are not allowed to connect.
#define GNUNET_YES
Definition: gnunet_common.h:77
void GNUNET_SERVER_destroy(struct GNUNET_SERVER_Handle *server)
Free resources held by this server.
#define GNUNET_free(ptr)
Wrapper around free.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ defhandlers

const struct GNUNET_SERVER_MessageHandler defhandlers[]
static
Initial value:
=
NULL,
sizeof(struct GNUNET_MessageHeader) },
{ NULL, NULL, 0, 0 } }
static void handle_test(void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message)
Handler for TEST message.
Header for all communications.
#define GNUNET_MESSAGE_TYPE_TEST
Test if service is online.

Default handlers for all services.

Will be copied and the "callback_cls" fields will be replaced with the specific service struct.

Definition at line 286 of file tcp_service_legacy.c.