The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
radiusd.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * $Id: ee3c25be1e41862662fedb260326b94c1d712ced $
19  *
20  * @file radiusd.c
21  * @brief Main loop of the radius server.
22  *
23  * @copyright 2000-2018 The FreeRADIUS server project
24  * @copyright 1999,2000 Miquel van Smoorenburg (miquels@cistron.nl)
25  * @copyright 2000 Alan DeKok (aland@freeradius.org)
26  * @copyright 2000 Alan Curry (pacman-radius@cqc.com)
27  * @copyright 2000 Jeff Carneal (jeff@apex.net)
28  * @copyright 2000 Chad Miller (cmiller@surfsouth.com)
29  */
30 RCSID("$Id: ee3c25be1e41862662fedb260326b94c1d712ced $")
31 
32 #include <freeradius-devel/server/base.h>
33 #include <freeradius-devel/server/dependency.h>
34 #include <freeradius-devel/server/map_proc.h>
35 #include <freeradius-devel/server/module.h>
36 #include <freeradius-devel/server/radmin.h>
37 #include <freeradius-devel/server/state.h>
38 #include <freeradius-devel/server/virtual_servers.h>
39 #include <freeradius-devel/util/debug.h>
40 #include <freeradius-devel/util/size.h>
41 #include <freeradius-devel/util/strerror.h>
42 
43 #include <freeradius-devel/tls/base.h>
44 #include <freeradius-devel/tls/log.h>
45 
46 #include <freeradius-devel/unlang/base.h>
47 
48 #include <freeradius-devel/util/misc.h>
49 #include <freeradius-devel/util/syserror.h>
50 
51 #ifdef HAVE_CAPABILITY_H
52 #include <freeradius-devel/util/cap.h>
53 #endif
54 
55 #include <fcntl.h>
56 #include <signal.h>
57 #include <sys/file.h>
58 #include <sys/mman.h>
59 
60 #ifdef HAVE_GETOPT_H
61 # include <getopt.h>
62 #endif
63 
64 #ifdef HAVE_SYS_WAIT_H
65 # include <sys/wait.h>
66 #endif
67 #ifndef WEXITSTATUS
68 # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
69 #endif
70 #ifndef WIFEXITED
71 # define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
72 #endif
73 
74 #ifdef HAVE_SYSTEMD
75 # include <systemd/sd-daemon.h>
76 #endif
77 
78 #ifdef WITH_TLS
79 # include <freeradius-devel/tls/version.h>
80 #endif
81 
82 char const *radiusd_version = RADIUSD_VERSION_BUILD("FreeRADIUS");
83 static pid_t radius_pid;
84 
85 /*
86  * Configuration items.
87  */
88 
89 /*
90  * Static functions.
91  */
92 static void usage(main_config_t const *config, int status);
93 
94 static void sig_fatal (int);
95 #ifdef SIGHUP
96 static void sig_hup (int);
97 #endif
98 
99 /** Configure talloc debugging features
100  *
101  * @param[in] config The main config.
102  * @return
103  * - 1 on config conflict.
104  * - 0 on success.
105  * - -1 on error.
106  */
108 {
109  if (config->spawn_workers) {
110  if (config->talloc_memory_report) {
111  fr_strerror_printf("talloc_memory_report requires single threaded mode (-s | -X)");
112  return 1;
113  }
114  return 0;
115  }
116 
117  if (!config->talloc_memory_report) {
118  talloc_disable_null_tracking();
119  return 0;
120  }
121 
122  talloc_enable_null_tracking();
123 
124  return 0;
125 }
126 
127 
128 /** Create module and xlat per-thread instances
129  *
130  */
131 static int thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el, UNUSED void *uctx)
132 {
133  if (modules_rlm_thread_instantiate(ctx, el) < 0) return -1;
134 
135  if (virtual_servers_thread_instantiate(ctx, el) < 0) return -1;
136 
137  if (xlat_thread_instantiate(ctx, el) < 0) return -1;
138 #ifdef WITH_TLS
139  if (fr_openssl_thread_init(main_config->openssl_async_pool_init,
140  main_config->openssl_async_pool_max) < 0) return -1;
141 #endif
142  return 0;
143 }
144 
145 /** Explicitly cleanup module/xlat resources
146  *
147  */
148 static void thread_detach(UNUSED void *uctx)
149 {
151 
153 
155 }
156 
157 #define EXIT_WITH_FAILURE \
158 do { \
159  ret = EXIT_FAILURE; \
160  goto cleanup; \
161 } while (0)
162 
163 #define EXIT_WITH_SUCCESS \
164 do { \
165  ret = EXIT_SUCCESS; \
166  goto cleanup; \
167 } while (0)
168 
169 static fr_event_timer_t const *fr_time_sync_ev = NULL;
170 
172 {
174 
175  (void) fr_event_timer_in(el, el, &fr_time_sync_ev, when, fr_time_sync_event, NULL);
176  (void) fr_time_sync();
177 }
178 
179 #ifndef NDEBUG
180 /** Encourage the server to exit after a period of time
181  *
182  * @param[in] el The main loop.
183  * @param[in] now Current time. Should be 0, when adding the event.
184  * @param[in] uctx Pointer to a fr_time_delta_t indicating how long
185  * the server should run before exit.
186  */
187 static void fr_exit_after(fr_event_list_t *el, fr_time_t now, void *uctx)
188 {
189  static fr_event_timer_t const *ev;
190 
191  fr_time_delta_t exit_after = *(fr_time_delta_t *)uctx;
192 
193  if (fr_time_eq(now, fr_time_wrap(0))) {
194  if (fr_event_timer_in(el, el, &ev, exit_after, fr_exit_after, uctx) < 0) {
195  PERROR("Failed inserting exit event");
196  }
197  return;
198  }
199 
201 }
202 #endif
203 
204 #ifdef HAVE_CAPABILITY_H
205 #define DUMP_CAPABILITIES(_phase) \
206 { \
207  char *cap_str; \
208  if (fr_cap_set_to_str(talloc_autofree_context(), &cap_str) < 0) { \
209  PWARN("Failed retrieving %s capabilities", _phase); \
210  } else { \
211  INFO("%s capabilities: %s", _phase, cap_str); \
212  talloc_free(cap_str); \
213  } \
214 }
215 #else
216 #define DUMP_CAPABILITIES(_phase)
217 #endif
218 
219 /** Entry point for the daemon
220  *
221  * @hidecallgraph
222  */
223 int main(int argc, char *argv[])
224 {
225  int status;
226  int c;
227  bool display_version = false;
228  bool radmin = false;
229  int from_child[2] = {-1, -1};
230  char const *program;
231  fr_schedule_t *sc = NULL;
232  int ret = EXIT_SUCCESS;
233 
234  TALLOC_CTX *global_ctx = NULL;
235  main_config_t *config = NULL;
236  bool talloc_memory_report = false;
237 
238  bool raddb_dir_set = false;
239 
240  size_t pool_size = 0;
241  void *pool_page_start = NULL;
242  size_t pool_page_len = 0;
243  bool do_mprotect;
244 
245 #ifndef NDEBUG
246  fr_time_delta_t exit_after = fr_time_delta_wrap(0);
247 #endif
248  /*
249  * Must be called first, so the handler is called last
250  */
252 
253  /*
254  * Setup talloc callbacks so we get useful errors
255  */
256  (void) fr_talloc_fault_setup();
257 
258  /*
259  * We probably don't want to free the talloc global_ctx context
260  * directly, so we'll allocate a new context beneath it, and
261  * free that before any leak reports.
262  */
263  {
264  char *env;
265 
266  /*
267  * If a FR_GLOBAL_POOL value is provided and
268  * is of a valid size, we pre-allocate a global
269  * memory pool, and mprotect() it once we're done
270  * parsing the global config.
271  *
272  * This lets us catch stray writes into global
273  * memory.
274  */
275  env = getenv("FR_GLOBAL_POOL");
276  if (env) {
277  if (fr_size_from_str(&pool_size, &FR_SBUFF_IN(env, strlen(env))) < 0) {
278  fr_perror("Invalid pool size string \"%s\"", env);
280  }
281 
282  /*
283  * Pre-allocate a global memory pool for the static
284  * config to exist in. We mprotect() this later to
285  * catch any stray writes.
286  */
288  &pool_page_start, &pool_page_len, 0, pool_size);
289  do_mprotect = true;
290  } else {
291  global_ctx = talloc_new(talloc_autofree_context());
292  do_mprotect = false;
293  }
294 
295  if (!global_ctx) {
296  fprintf(stderr, "Failed allocating global context\n");
298  }
299  }
300 
301  /*
302  * Allocate the main config structure.
303  * It's allocated so we can hang talloced buffers off it.
304  */
306  if (!config) {
307  fprintf(stderr, "Failed allocating main config");
309  }
310 
311  /*
312  * Set some default values
313  */
314  program = strrchr(argv[0], FR_DIR_SEP);
315  if (!program) {
316  program = argv[0];
317  } else {
318  program++;
319  }
320  main_config_name_set_default(config, program, false);
321 
322  config->daemonize = true;
323  config->spawn_workers = true;
324 
325 #ifdef OSFC2
326  set_auth_parameters(argc, argv);
327 #endif
328 
329 #ifdef WIN32
330  {
331  WSADATA wsaData;
332  if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
333  fprintf(stderr, "%s: Unable to initialize socket library.\n", config->name);
335  }
336  }
337 #endif
338 
339  fr_debug_lvl = 0;
340  fr_time_start();
341 
342  /*
343  * Don't put output anywhere until we get told a little
344  * more.
345  */
347  default_log.fd = -1;
348  default_log.print_level = true;
350 
351  /*
352  * Set the panic action and enable other debugging facilities
353  */
354  if (fr_fault_setup(global_ctx, getenv("PANIC_ACTION"), argv[0]) < 0) {
355  fr_perror("Failed installing fault handlers... continuing");
356  }
357 
358  /* Process the options. */
359  while ((c = getopt(argc, argv, "Cd:D:e:fhi:l:Mmn:p:PrsS:tTvxX")) != -1) switch (c) {
360  case 'C':
361  check_config = true;
362  config->spawn_workers = false;
363  config->daemonize = false;
364  break;
365 
366  case 'd':
368  raddb_dir_set = true;
369  break;
370 
371  case 'D':
373  break;
374 
375 #ifndef NDEBUG
376  case 'e':
377  exit_after = fr_time_delta_from_sec(atoi(optarg));
378  break;
379 #endif
380 
381  case 'f':
382  config->daemonize = false;
383  break;
384 
385  case 'h':
386  usage(config, EXIT_SUCCESS);
387  break;
388 
389  case 'l':
390  if (strcmp(optarg, "stdout") == 0) goto do_stdout;
391 
392  config->log_file = talloc_typed_strdup(global_ctx, optarg);
395  default_log.fd = open(config->log_file, O_WRONLY | O_APPEND | O_CREAT, 0640);
396  if (default_log.fd < 0) {
397  fprintf(stderr, "%s: Failed to open log file %s: %s\n",
398  config->name, config->log_file, fr_syserror(errno));
400  }
401  break;
402 
403  case 'm':
404  config->allow_multiple_procs = true;
405  break;
406 
407  case 'M':
408  config->talloc_memory_report = true;
409  break;
410 
411  case 'n':
412  main_config_name_set_default(config, optarg, true);
413  break;
414 
415  case 'P': /* Force the PID to be written, even in -f mode */
416  config->write_pid = true;
417  break;
418 
419  case 'r': /* internal radmin-style control interface */
420  config->spawn_workers = false;
421  config->daemonize = false;
422  radmin = true;
423  break;
424 
425  case 's': /* Single process mode */
426  config->spawn_workers = false;
427  config->daemonize = false;
428  break;
429 
430  case 'S': /* Migration support */
431  if (main_config_parse_option(optarg) < 0) {
432  fprintf(stderr, "%s: Unknown configuration option '%s'\n",
433  config->name, optarg);
435  }
436  break;
437 
438  case 't': /* no child threads */
439  config->spawn_workers = false;
440  break;
441 
442  case 'T': /* enable timestamps */
444  break;
445 
446  case 'v':
447  display_version = true;
448  break;
449 
450  case 'X':
451  config->spawn_workers = false;
452  config->daemonize = false;
453  fr_debug_lvl += 2;
454  if (fr_debug_lvl > 2) default_log.suppress_secrets = false;
455 
456  do_stdout:
458  default_log.fd = STDOUT_FILENO;
459  break;
460 
461  case 'x':
462  fr_debug_lvl++;
463  if (fr_debug_lvl > 2) default_log.suppress_secrets = false;
464  break;
465 
466  default:
467  usage(config, EXIT_FAILURE);
468  break;
469  }
470 
471  /*
472  * Allow the configuration directory to be set from an
473  * environment variable. This allows tests to change the
474  * configuration directory without changing the scripts
475  * being executed.
476  */
477  if (!raddb_dir_set) {
478  char const *raddb_dir = getenv("FREERADIUS_CONFIG_DIR");
479 
480  if (raddb_dir) main_config_raddb_dir_set(config, raddb_dir);
481  }
482 
483  /*
484  * We've now got enough information to check to see
485  * if another process is running with the same config.
486  */
487  config->debug_level = fr_debug_lvl;
488 
489  /*
490  * Mismatch between the binary and the libraries it depends on.
491  */
493  fr_perror("%s", config->name);
495  }
496 
498 
499 #ifdef WITH_TLS
500  /*
501  * Mismatch between build time OpenSSL and linked SSL, better to die
502  * here than segfault later.
503  */
505 
506  /*
507  * Initialising OpenSSL once, here, is safer than having individual modules do it.
508  * Must be called before display_version to ensure relevant engines are loaded.
509  *
510  * fr_openssl_init() must be called before *ANY* OpenSSL functions are used, which is why
511  * it's called so early.
512  */
513  if (fr_openssl_init() < 0) EXIT_WITH_FAILURE;
514 #endif
515 
516  /*
517  * According to the talloc peeps, no two threads may modify any part of
518  * a ctx tree with a common root without synchronisation.
519  *
520  * So we can't run with a null context and threads.
521  */
522  if (talloc_config_set(config) != 0) {
523  fr_perror("%s", config->name);
525  }
526 
527  /*
528  * Better here, so it doesn't matter whether we get passed -xv or -vx.
529  */
530  if (display_version) {
531  if (fr_debug_lvl == 0) fr_debug_lvl = 1;
533  default_log.fd = STDOUT_FILENO;
534 
535  INFO("%s - %s", config->name, radiusd_version);
538  }
539 
541 
542  /*
543  * Under linux CAP_SYS_PTRACE is usually only available before setuid/setguid,
544  * so we need to check whether we can attach before calling those functions
545  * (in main_config_init()).
546  */
548 
549  /*
550  * Write the PID always if we're running as a daemon.
551  */
552  if (config->daemonize) config->write_pid = true;
553 
554  /*
555  * Initialize the DL infrastructure, which is used by the
556  * config file parser. Note that we pass an empty path
557  * here, as we haven't yet read the configuration file.
558  */
559  modules_init(NULL);
560 
561  /*
562  * Initialise the top level dictionary hashes which hold
563  * the protocols.
564  */
565  if (!fr_dict_global_ctx_init(NULL, true, config->dict_dir)) {
566  fr_perror("%s", program);
568  }
569 
570 #ifdef WITH_TLS
571  if (fr_tls_dict_init() < 0) {
572  fr_perror("%s", program);
574  }
575 #endif
576 
577  /*
578  * Setup the global structures for module lists
579  */
580  if (modules_rlm_init() < 0) {
581  fr_perror("%s", program);
583  }
584 
585  if (virtual_servers_init() < 0) {
586  fr_perror("%s", program);
588  }
589 
590  /*
591  * Load dictionary attributes used
592  * for requests.
593  */
594  if (request_global_init() < 0) {
595  fr_perror("%s", program);
597  }
598 
599  /*
600  * Read the configuration files, BEFORE doing anything else.
601  */
603 
604  if (!config->suppress_secrets) default_log.suppress_secrets = false;
605 
606  /*
607  * Check we're the only process using this config.
608  */
609  if (!config->allow_multiple_procs) {
611  case 0: /* No other processes running */
612  break;
613 
614  case -1: /* Permissions error - fail open */
615  PWARN("%s - Process concurrency checks disabled", program);
616  break;
617 
618  case 1:
619  default: /* All other errors */
620  fr_perror("%s", program);
622  }
623  }
624 
625  /*
626  * Set panic_action from the main config if one wasn't specified in the
627  * environment.
628  */
629  if (config->panic_action && !getenv("PANIC_ACTION") &&
630  (fr_fault_setup(global_ctx, config->panic_action, argv[0]) < 0)) {
631  fr_perror("radiusd - Failed configuring panic action: %s", config->name);
633  }
634 
635  /*
636  * This is very useful in figuring out why the panic_action didn't fire.
637  */
639 
640  /*
641  * Track configuration versions. This lets us know if the configuration changed.
642  */
643  if (fr_debug_lvl) {
644  uint8_t digest[16];
645 
646  cf_md5_final(digest);
647 
648  digest[6] &= 0x0f; /* ver is 0b0100 at bits 48:51 */
649  digest[6] |= 0x40;
650  digest[8] &= ~0xc0; /* var is 0b10 at bits 64:65 */
651  digest[8] |= 0x80;
652 
653  /*
654  * UUIDv4 format: 4-2-2-2-6
655  */
656  INFO("Configuration version: %02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
657  digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7],
658  digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15]);
659  }
660 
661  /*
662  * Call this again now we've loaded the configuration. Yes I know...
663  */
664  if (talloc_config_set(config) < 0) {
665  fr_perror("%s", config->name);
667  }
668 
669  /*
670  * Check for vulnerabilities in the version of libssl were linked against.
671  */
672 #ifdef WITH_TLS
673 # ifdef ENABLE_OPENSSL_VERSION_CHECK
674  if (fr_openssl_version_check(config->allow_vulnerable_openssl) < 0) EXIT_WITH_FAILURE;
675 # endif
676 
677  /*
678  * Toggle FIPS mode
679  */
680  if (config->openssl_fips_mode_is_set &&
681  (fr_openssl_fips_mode(config->openssl_fips_mode) < 0)) EXIT_WITH_FAILURE;
682 #endif
683 
684  /*
685  * The systemd watchdog enablement must be checked before we
686  * daemonize, but the watchdog notifications can come from any
687  * process.
688  */
689 #ifdef HAVE_SYSTEMD_WATCHDOG
690  if (!check_config) main_loop_set_sd_watchdog_interval();
691 #else
692  /*
693  * If the default systemd unit file is used, but the server wasn't
694  * built with support for systemd, the status returned by systemctl
695  * will stay permanently as "activating".
696  *
697  * We detect this condition and warn about it here, using the
698  * presence of the NOTIFY_SOCKET environmental variable to determine
699  * whether we're running under systemd.
700  */
701  if (getenv("NOTIFY_SOCKET")) INFO("Built without support for systemd watchdog, but running under systemd");
702 #endif
703 
704  /*
705  * Don't allow radmin when checking the config.
706  */
707  if (check_config) radmin = false;
708 
709  if (fr_radmin_start(config, radmin) < 0) EXIT_WITH_FAILURE;
710 
711  /*
712  * Disconnect from session
713  */
714  if (config->daemonize) {
715  pid_t pid;
716  int devnull;
717 
718  DUMP_CAPABILITIES("pre-fork");
719 
720  /*
721  * Really weird things happen if we leave stdin open and call things like
722  * system() later.
723  */
724  devnull = open("/dev/null", O_RDWR);
725  if (devnull < 0) {
726  ERROR("Failed opening /dev/null: %s", fr_syserror(errno));
728  }
729  dup2(devnull, STDIN_FILENO);
730 
731  close(devnull);
732 
733  if (pipe(from_child) != 0) {
734  ERROR("Couldn't open pipe for child status: %s", fr_syserror(errno));
736  }
737 
738  pid = fork();
739  if (pid < 0) {
740  ERROR("Couldn't fork: %s", fr_syserror(errno));
742  }
743 
744  /*
745  * The parent exits, so the child can run in the background.
746  *
747  * As the child can still encounter an error during initialisation
748  * we do a blocking read on a pipe between it and the parent.
749  *
750  * Just before entering the event loop the child will send a success
751  * or failure message to the parent, via the pipe.
752  */
753  if (pid > 0) {
754  uint8_t child_ret;
755  int stat_loc;
756 
757  /* So the pipe is correctly widowed if the child exits */
758  close(from_child[1]);
759 
760  /*
761  * The child writes a 0x01 byte on success, and closes
762  * the pipe on error.
763  */
764  if ((read(from_child[0], &child_ret, 1) < 0)) child_ret = 0;
765 
766  /* For cleanliness... */
767  close(from_child[0]);
768 
769  /* Don't turn children into zombies */
770  if (child_ret == 0) {
771  waitpid(pid, &stat_loc, WNOHANG);
773  }
774 
775 #ifdef HAVE_SYSTEMD
776  /*
777  * Update the systemd MAINPID to be our child,
778  * as the parent is about to exit.
779  */
780  sd_notifyf(0, "MAINPID=%lu", (unsigned long)pid);
781 #endif
782 
783  goto cleanup;
784  /*
785  * The child needs to increment the semaphore as the parent
786  * is going to exit, and it will decrement the semaphore.
787  */
788  } else if (pid == 0) {
790  PWARN("%s - Failed incrementing exclusive proc semaphore in child", program);
791  }
792  }
793 
794  /* so the pipe is correctly widowed if the parent exits?! */
795  close(from_child[0]);
796 #ifdef HAVE_SETSID
797  setsid();
798 #endif
799 
800  DUMP_CAPABILITIES("post-fork");
801  } else {
802  DUMP_CAPABILITIES("pre-suid-down");
803  }
804 
805  /*
806  * Ensure that we're using the CORRECT pid after forking, NOT the one
807  * we started with.
808  */
809  radius_pid = getpid();
810 
811  /*
812  * Initialise the interpreter, registering operations.
813  */
815 
816  if (server_init(config->root_cs, config->raddb_dir, fr_dict_unconst(fr_dict_internal())) < 0) EXIT_WITH_FAILURE;
817 
818  /*
819  * Everything seems to have loaded OK, exit gracefully.
820  */
821  if (check_config) {
822  DEBUG("Configuration appears to be OK");
823  goto cleanup;
824  }
825 
826  /*
827  * Initialise the SNMP stats structures
828  */
829  if (fr_snmp_init() < 0) {
830  PERROR("Failed initialising SNMP");
832  }
833 
834  /*
835  * Initialize the global event loop which handles things like
836  * systemd.
837  *
838  * This has to be done post-fork in case we're using kqueue, where the
839  * queue isn't inherited by the child process.
840  */
841  if (main_loop_init() < 0) {
842  PERROR("Failed initialising main event loop");
844  }
845 
846  /*
847  * Start the network / worker threads.
848  */
849  {
850  fr_event_list_t *el = NULL;
851  fr_schedule_config_t *schedule;
852 
853  schedule = talloc_zero(global_ctx, fr_schedule_config_t);
854  schedule->max_workers = config->max_workers;
855  schedule->max_networks = config->max_networks;
856  schedule->stats_interval = config->stats_interval;
857 
858  schedule->network.max_outstanding = config->max_requests;
859 
860 #define COPY(_x) schedule->worker._x = config->_x
861  COPY(max_requests);
862  COPY(max_request_time);
863 
864  /*
865  * Single server mode: use the global event list.
866  * Otherwise, each network thread will create
867  * its own event list.
868  */
869  if (!config->spawn_workers) {
871  }
872 
873  /*
874  * Fix spurious messages
875  */
878  thread_instantiate, thread_detach, schedule);
879  if (!sc) {
880  PERROR("Failed starting the scheduler");
882  }
883 
884  /*
885  * Tell the virtual servers to open their sockets.
886  */
888  }
889 
890  /*
891  * At this point, no one has any business *ever* going
892  * back to root uid.
893  */
895 
896  DUMP_CAPABILITIES("post-suid-down");
897 
898  /*
899  * Dropping down may change the RLIMIT_CORE value, so
900  * reset it back to what to should be here.
901  */
903 
904  /*
905  * If we're debugging, then a CTRL-C will cause the server to die
906  * immediately. Use SIGTERM to shut down the server cleanly in
907  * that case.
908  */
909  if (fr_set_signal(SIGINT, sig_fatal) < 0) {
910  set_signal_error:
911  PERROR("Failed installing signal handler");
913  }
914 
915 #ifdef SIGQUIT
916  if (fr_set_signal(SIGQUIT, sig_fatal) < 0) goto set_signal_error;
917 #endif
918 
919  /*
920  * Now that we've set everything up, we can install the signal
921  * handlers. Before this, if we get any signal, we don't know
922  * what to do, so we might as well do the default, and die.
923  */
924 #ifdef SIGPIPE
925  if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
926  ERROR("Failed ignoring SIGPIPE: %s", fr_syserror(errno));
927  goto cleanup;
928  }
929 #endif
930 
931  if (fr_set_signal(SIGHUP, sig_hup) < 0) goto set_signal_error;
932  if (fr_set_signal(SIGTERM, sig_fatal) < 0) goto set_signal_error;
933 
934 #ifdef WITH_STATS
936 #endif
937 
938  /*
939  * Write the PID after we've forked, so that we write the correct one.
940  */
941  if (config->write_pid) {
942  FILE *fp;
943 
944  fp = fopen(config->pid_file, "w");
945  if (fp != NULL) {
946  /*
947  * @fixme What about following symlinks,
948  * and having it over-write a normal file?
949  */
950  fprintf(fp, "%d\n", (int) radius_pid);
951  fclose(fp);
952  } else {
953  ERROR("Failed creating PID file %s: %s", config->pid_file, fr_syserror(errno));
955  }
956  }
957 
958  trigger_exec(NULL, NULL, "server.start", false, NULL);
959 
960  /*
961  * Inform the parent (who should still be waiting) that the rest of
962  * initialisation went OK, and that it should exit with a 0 status.
963  * If we don't get this far, then we just close the pipe on exit, and the
964  * parent gets a read failure.
965  */
966  if (config->daemonize) {
967  if (write(from_child[1], "\001", 1) < 0) {
968  WARN("Failed informing parent of successful start: %s",
969  fr_syserror(errno));
970  }
971  close(from_child[1]);
972  }
973 
974  /*
975  * Clear the libfreeradius error buffer.
976  */
978 
979  /*
980  * Prevent anything from modifying the dictionaries
981  * they're now immutable.
982  */
984 
985  /*
986  * Protect global memory - If something attempts
987  * to write to this memory we get a SIGBUS.
988  */
989  if (do_mprotect) {
990  if (mprotect(pool_page_start, pool_page_len, PROT_READ) < 0) {
991  PERROR("Protecting global memory failed: %s", fr_syserror(errno));
993  }
994  DEBUG("Global memory protected");
995  }
996 
998 #ifndef NDEBUG
999  if (fr_time_delta_ispos(exit_after)) fr_exit_after(main_loop_event_list(), fr_time_wrap(0), &exit_after);
1000 #endif
1001  /*
1002  * Process requests until HUP or exit.
1003  */
1004  INFO("Ready to process requests"); /* we were actually ready a while ago, but oh well */
1005  while ((status = main_loop_start()) == 0x80) {
1006 #ifdef WITH_STATS
1007  radius_stats_init(1);
1008 #endif
1010  }
1011 
1012  /*
1013  * Ignore the TERM signal: we're about to die.
1014  */
1015  if (unlikely(signal(SIGTERM, SIG_IGN) == SIG_ERR)) {
1016  ERROR("Failed blocking SIGTERM, we may receive spurious signals: %s",
1017  fr_syserror(errno));
1018  }
1019 
1020  /*
1021  * Unprotect global memory
1022  */
1023  if (do_mprotect) {
1024  if (mprotect(pool_page_start, pool_page_len,
1025  PROT_READ | PROT_WRITE) < 0) {
1026  PERROR("Unprotecting global memory failed: %s", fr_syserror(errno));
1028  }
1029  DEBUG("Global memory unprotected");
1030  }
1031 
1032  if (status < 0) {
1033  PERROR("Exiting due to internal error");
1034  ret = EXIT_FAILURE;
1035  } else {
1036  INFO("Exiting normally");
1037  ret = EXIT_SUCCESS;
1038  }
1039 
1040  fr_radmin_stop();
1041 
1042  /*
1043  * Fire signal and stop triggers after ignoring SIGTERM, so handlers are
1044  * not killed with the rest of the process group, below.
1045  */
1046  if (status == 2) trigger_exec(NULL, NULL, "server.signal.term", true, NULL);
1047  trigger_exec(NULL, NULL, "server.stop", false, NULL);
1048 
1049  /*
1050  * Stop the scheduler, this signals the network and worker threads
1051  * to exit gracefully. fr_schedule_destroy only returns once all
1052  * threads have been joined.
1053  */
1054  (void) fr_schedule_destroy(&sc);
1055 
1056  /*
1057  * We're exiting, so we can delete the PID file.
1058  * (If it doesn't exist, we can ignore the error returned by unlink)
1059  */
1060  if (config->daemonize) {
1061  DEBUG3("Unlinking PID file %s", config->pid_file);
1062  unlink(config->pid_file);
1063  }
1064 
1065  /*
1066  * Free memory in an explicit and consistent order
1067  *
1068  * We could let everything be freed by the global_ctx
1069  * context, but in some cases there are odd interactions
1070  * with destructors that may cause double frees and
1071  * SEGVs.
1072  */
1073  if (!config->spawn_workers) {
1075 
1077  fr_event_loop_exit(el, 1);
1078  }
1079 
1080  main_loop_free();
1081 
1082  /*
1083  * Send a TERM signal to all associated processes
1084  * (including us, which gets ignored.)
1085  *
1086  * This _shouldn't_ be needed, but may help with
1087  * processes created by the exec code or triggers.
1088  */
1089  if (config->spawn_workers) {
1090  INFO("All threads have exited, sending SIGTERM to remaining children");
1091 
1092  /*
1093  * If pid is negative, but not -1, sig
1094  * shall be sent to all processes
1095  * (excluding an unspecified set of system processes)
1096  * whose process group ID is equal to the absolute value
1097  * of pid, and for which the process has permission
1098  * to send a signal.
1099  */
1100  kill(-getpgid(radius_pid), SIGTERM);
1101  }
1102 
1103  /*
1104  * Remove the semaphore, allowing other processes
1105  * to start. We do this before the cleanup label
1106  * as the parent process MUST NOT call this
1107  * function as it exits, otherwise the semaphore
1108  * is removed and there's no exclusivity.
1109  */
1111 
1112 cleanup:
1113  /*
1114  * This may not have been done earlier if we're
1115  * exiting due to a startup error.
1116  */
1117  (void) fr_schedule_destroy(&sc);
1118 
1119  /*
1120  * Ensure all thread local memory is cleaned up
1121  * before we start cleaning up global resources.
1122  * This is necessary for single threaded mode
1123  * to ensure that thread local resources that
1124  * depend on global resources are freed at the
1125  * appropriate time.
1126  */
1128 
1129  server_free();
1130 
1131 #ifdef WITH_TLS
1132  fr_openssl_free(); /* Cleanup any memory alloced by OpenSSL and placed into globals */
1133 #endif
1134 
1135  if (config) talloc_memory_report = config->talloc_memory_report; /* Grab this before we free the config */
1136 
1137  /*
1138  * Virtual servers need to be freed before modules
1139  * as state entries containing data with module-specific
1140  * destructors may exist.
1141  */
1143 
1144  /*
1145  * Free modules, this needs to be done explicitly
1146  * because some libraries used by modules use atexit
1147  * handlers registered after ours, and they may deinit
1148  * themselves before we free the modules and cause
1149  * crashes on exit.
1150  */
1151  modules_rlm_free();
1152 
1153 #ifdef WITH_TLS
1154  fr_tls_dict_free();
1155 #endif
1156 
1157  /*
1158  * And now nothing should be left anywhere except the
1159  * parsed configuration items.
1160  */
1162 
1163  /*
1164  * Cleanup everything else
1165  */
1166  if (talloc_free(global_ctx) < 0) {
1167 #ifndef NDEBUG
1168  fr_perror("radiusd");
1169  ret = EXIT_FAILURE;
1170 #endif
1171  }
1172 
1173  /*
1174  * Anything not cleaned up by the above is allocated in
1175  * the NULL top level context, and is likely leaked memory.
1176  */
1177  if (talloc_memory_report) fr_log_talloc_report(NULL);
1178 
1179  /*
1180  * If we're running under LSAN, try and SUID back up so
1181  * we don't inteferere with the onexit() handler.
1182  */
1184  fr_strerror_clear(); /* clear error buffer */
1185 
1186  /*
1187  * Ensure our atexit handlers run before any other
1188  * atexit handlers registered by third party libraries.
1189  */
1191 
1192  return ret;
1193 }
1194 
1195 /*
1196  * Display the syntax for starting this program.
1197  */
1198 static NEVER_RETURNS void usage(main_config_t const *config, int status)
1199 {
1200  FILE *output = status ? stderr : stdout;
1201 
1202  fprintf(output, "Usage: %s [options]\n", config->name);
1203  fprintf(output, "Options:\n");
1204  fprintf(output, " -C Check configuration and exit.\n");
1205  fprintf(stderr, " -d <raddb> Set configuration directory (defaults to " RADDBDIR ").\n");
1206  fprintf(stderr, " -D <dictdir> Set main dictionary directory (defaults to " DICTDIR ").\n");
1207 #ifndef NDEBUG
1208  fprintf(output, " -e <seconds> Exit after the specified number of seconds. Useful for diagnosing \"crash-on-exit\" issues.\n");
1209 #endif
1210  fprintf(output, " -f Run as a foreground process, not a daemon.\n");
1211  fprintf(output, " -h Print this help message.\n");
1212  fprintf(output, " -l <log_file> Logging output will be written to this file.\n");
1213 #ifndef NDEBUG
1214  fprintf(output, " -L <size> When running in memory debug mode, set a hard limit on talloced memory\n");
1215 #endif
1216  fprintf(output, " -n <name> Read raddb/name.conf instead of raddb/radiusd.conf.\n");
1217  fprintf(output, " -m Allow multiple processes reading the same radiusd.conf to exist simultaneously.\n");
1218 #ifndef NDEBUG
1219  fprintf(output, " -M Enable talloc memory debugging, and issue a memory report when the server terminates\n");
1220 #endif
1221  fprintf(output, " -P Always write out PID, even with -f.\n");
1222  fprintf(output, " -s Do not spawn child processes to handle requests (same as -ft).\n");
1223  fprintf(output, " -t Disable threads.\n");
1224  fprintf(output, " -T Prepend timestamps to log messages.\n");
1225  fprintf(output, " -v Print server version information.\n");
1226  fprintf(output, " -X Turn on full debugging (similar to -tfxxl stdout).\n");
1227  fprintf(output, " -x Turn on additional debugging (-xx gives more debugging).\n");
1228  fr_exit(status);
1229 }
1230 
1231 
1232 /*
1233  * We got a fatal signal.
1234  */
1235 static void sig_fatal(int sig)
1236 {
1237  static int last_sig;
1238 
1239  if (getpid() != radius_pid) _exit(sig);
1240 
1241  /*
1242  * Suppress duplicate signals.
1243  *
1244  * For some reason on macOS we get multiple signals
1245  * for the same event (SIGINT).
1246  *
1247  * ...this also fixes the problem of the user hammering
1248  * Ctrl-C and causing ungraceful exits as we try and
1249  * write out signals to a pipe that's already closed.
1250  */
1251  if (sig == last_sig) return;
1252  last_sig = sig;
1253 
1254  switch (sig) {
1255  case SIGTERM:
1257  break;
1258 
1259  case SIGINT:
1260 #ifdef SIGQUIT
1261  case SIGQUIT:
1262 #endif
1264  break;
1265 
1266  default:
1267  fr_exit(sig);
1268  }
1269 }
1270 
1271 #ifdef SIGHUP
1272 /*
1273  * We got the hangup signal.
1274  * Re-read the configuration files.
1275  */
1276 static void sig_hup(UNUSED int sig)
1277 {
1278  reset_signal(SIGHUP, sig_hup);
1279 
1281 }
1282 #endif
int fr_atexit_global_setup(void)
Setup the atexit handler, should be called at the start of a program's execution.
Definition: atexit.c:160
int fr_atexit_global_trigger_all(void)
Cause all global free triggers to fire.
Definition: atexit.c:286
#define fr_atexit_thread_trigger_all(...)
Definition: atexit.h:233
void fr_radmin_stop(void)
Definition: radmin.c:1101
int fr_radmin_start(main_config_t *config, bool cli)
Definition: radmin.c:1064
#define RCSID(id)
Definition: build.h:481
#define NEVER_RETURNS
Should be placed before the function return type.
Definition: build.h:311
#define unlikely(_x)
Definition: build.h:379
#define UNUSED
Definition: build.h:313
bool check_config
Definition: cf_file.c:67
void cf_md5_final(uint8_t *digest)
Definition: cf_file.c:3085
fr_dcursor_eval_t void const * uctx
Definition: dcursor.h:546
char const * fr_debug_state_to_msg(fr_debug_state_t state)
Return current value of debug_state.
Definition: debug.c:541
int fr_log_talloc_report(TALLOC_CTX const *ctx)
Generate a talloc memory report for a context and print to stderr/stdout.
Definition: debug.c:1147
int fr_reset_dumpable(void)
Reset dumpable state to previously configured value.
Definition: debug.c:890
int fr_fault_setup(TALLOC_CTX *ctx, char const *cmd, char const *program)
Registers signal handlers to execute panic_action on fatal signal.
Definition: debug.c:1242
int fr_get_lsan_state(void)
Definition: debug.c:261
void fr_debug_state_store(void)
Should be run before using setuid or setgid to get useful results.
Definition: debug.c:521
void fr_talloc_fault_setup(void)
Register talloc fault handlers.
Definition: debug.c:1223
fr_debug_state_t fr_debug_state
Whether we're attached to by a debugger.
Definition: debug.c:104
#define fr_exit(_x)
Exit, producing a log message in debug builds.
Definition: debug.h:228
void dependency_version_print(void)
Definition: dependency.c:376
int rad_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
Definition: dependency.c:71
#define ERROR(fmt,...)
Definition: dhcpclient.c:41
#define DEBUG(fmt,...)
Definition: dhcpclient.c:39
void fr_dict_global_ctx_read_only(void)
Mark all dictionaries and the global dictionary ctx as read only.
Definition: dict_util.c:4503
fr_dict_t const * fr_dict_internal(void)
Definition: dict_util.c:4610
fr_dict_t * fr_dict_unconst(fr_dict_t const *dict)
Coerce to non-const.
Definition: dict_util.c:4585
fr_dict_gctx_t * fr_dict_global_ctx_init(TALLOC_CTX *ctx, bool free_at_exit, char const *dict_dir)
Initialise the global protocol hashes.
Definition: dict_util.c:4392
#define fr_event_timer_in(...)
Definition: event.h:255
uint32_t max_outstanding
Definition: network.h:46
int server_init(CONF_SECTION *cs, char const *dict_dir, fr_dict_t *dict)
Initialize src/lib/server/.
Definition: base.c:49
void server_free(void)
Free src/lib/server/.
Definition: base.c:139
#define PERROR(_fmt,...)
Definition: log.h:228
#define DEBUG3(_fmt,...)
Definition: log.h:266
#define PWARN(_fmt,...)
Definition: log.h:227
void rad_suid_up(void)
Definition: util.c:896
bool rad_suid_is_down_permanent(void)
Return whether we've permanently dropped root privileges.
Definition: util.c:917
void(*)(int) reset_signal(int signo, void(*func)(int))
Definition: util.c:55
void rad_suid_down_permanent(void)
Definition: util.c:905
int unlang_global_init(void)
Definition: base.c:133
waitpid(reap->pid_ev->pid, &status, 0)
talloc_free(reap)
void fr_event_loop_exit(fr_event_list_t *el, int code)
Signal an event loop exit with the specified code.
Definition: event.c:2744
Stores all information relating to an event list.
Definition: event.c:411
A timer event.
Definition: event.c:102
int fr_debug_lvl
Definition: log.c:43
static FILE * devnull
File handle for /dev/null.
Definition: log.c:59
fr_log_t default_log
Definition: log.c:291
@ L_DST_NULL
Discard log messages.
Definition: log.h:83
@ L_DST_FILES
Log to a file on disk.
Definition: log.h:79
@ L_DST_STDOUT
Log to stdout.
Definition: log.h:78
@ L_TIMESTAMP_ON
Always log timestamps.
Definition: log.h:90
int main_config_parse_option(char const *value)
Definition: main_config.c:1511
int main_config_free(main_config_t **config)
Definition: main_config.c:1423
void main_config_raddb_dir_set(main_config_t *config, char const *name)
Set the global radius config directory.
Definition: main_config.c:862
void main_config_exclusive_proc_done(UNUSED main_config_t const *config)
Clean up the semaphore when the main config is freed.
Definition: main_config.c:877
void main_config_hup(main_config_t *config)
Definition: main_config.c:1469
int main_config_exclusive_proc(main_config_t *config)
Check to see if we're the only process using this configuration file (or PID file if specified)
Definition: main_config.c:916
void main_config_name_set_default(main_config_t *config, char const *name, bool overwrite_config)
Set the server name.
Definition: main_config.c:843
int main_config_init(main_config_t *config)
Definition: main_config.c:1036
main_config_t const * main_config
Main server configuration.
Definition: main_config.c:69
int main_config_exclusive_proc_child(UNUSED main_config_t const *config)
Increment the semaphore in the child process so that it's not released when the parent exits.
Definition: main_config.c:895
main_config_t * main_config_alloc(TALLOC_CTX *ctx)
Allocate a main_config_t struct, setting defaults.
Definition: main_config.c:1003
void main_config_dict_dir_set(main_config_t *config, char const *name)
Set the global dictionary directory.
Definition: main_config.c:991
Main server configuration.
Definition: main_config.h:51
int main_loop_start(void)
Definition: main_loop.c:195
fr_event_list_t * main_loop_event_list(void)
Return the main loop event list.
Definition: main_loop.c:165
void main_loop_signal_raise(int flag)
Definition: main_loop.c:79
int main_loop_init(void)
Initialise the main event loop, setting up signal handlers.
Definition: main_loop.c:254
void main_loop_free(void)
Definition: main_loop.c:190
@ RADIUS_SIGNAL_SELF_HUP
Definition: main_loop.h:36
@ RADIUS_SIGNAL_SELF_TERM
Definition: main_loop.h:37
unsigned char uint8_t
Definition: merged_model.c:30
int fr_set_signal(int sig, sig_t func)
Sets a signal handler using sigaction if available, else signal.
Definition: misc.c:47
void modules_rlm_thread_detach(void)
Frees thread-specific data for all registered backend modules.
Definition: module_rlm.c:963
int modules_rlm_free(void)
Cleanup all global structures.
Definition: module_rlm.c:1352
int modules_rlm_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Allocates thread-specific data for all registered backend modules.
Definition: module_rlm.c:976
int modules_rlm_init(void)
Initialise the module list structure.
Definition: module_rlm.c:1370
static const conf_parser_t config[]
Definition: base.c:183
#define WARN(fmt,...)
Definition: radclient.h:47
#define INFO(fmt,...)
Definition: radict.c:54
int main(int argc, char *argv[])
Entry point for the daemon.
Definition: radiusd.c:223
static void thread_detach(UNUSED void *uctx)
Explicitly cleanup module/xlat resources.
Definition: radiusd.c:148
static fr_event_timer_t const * fr_time_sync_ev
Definition: radiusd.c:169
static void fr_exit_after(fr_event_list_t *el, fr_time_t now, void *uctx)
Encourage the server to exit after a period of time.
Definition: radiusd.c:187
#define COPY(_x)
#define DUMP_CAPABILITIES(_phase)
Definition: radiusd.c:216
static void usage(main_config_t const *config, int status)
Definition: radiusd.c:1198
#define EXIT_WITH_SUCCESS
Definition: radiusd.c:163
char const * radiusd_version
Definition: radiusd.c:82
static void fr_time_sync_event(fr_event_list_t *el, UNUSED fr_time_t now, UNUSED void *uctx)
Definition: radiusd.c:171
static int thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el, UNUSED void *uctx)
Create module and xlat per-thread instances.
Definition: radiusd.c:131
static int talloc_config_set(main_config_t *config)
Configure talloc debugging features.
Definition: radiusd.c:107
static void sig_fatal(int)
Definition: radiusd.c:1235
static pid_t radius_pid
Definition: radiusd.c:83
#define EXIT_WITH_FAILURE
Definition: radiusd.c:157
static bool cleanup
Definition: radsniff.c:60
int request_global_init(void)
Definition: request.c:722
#define FR_SBUFF_IN(_start, _len_or_end)
fr_schedule_t * fr_schedule_create(TALLOC_CTX *ctx, fr_event_list_t *el, fr_log_t *logger, fr_log_lvl_t lvl, fr_schedule_thread_instantiate_t worker_thread_instantiate, fr_schedule_thread_detach_t worker_thread_detach, fr_schedule_config_t *config)
Create a scheduler and spawn the child threads.
Definition: schedule.c:463
int fr_schedule_destroy(fr_schedule_t **sc_to_free)
Destroy a scheduler, and tell its child threads to exit.
Definition: schedule.c:761
The scheduler.
Definition: schedule.c:125
fr_network_config_t network
configuration for each network;
Definition: schedule.h:68
uint32_t max_workers
number of network threads
Definition: schedule.h:65
fr_time_delta_t stats_interval
print channel statistics
Definition: schedule.h:70
uint32_t max_networks
number of network threads
Definition: schedule.h:64
void radius_stats_init(int flag)
Definition: stats.c:151
Signals that can be sent to a request.
fr_slen_t fr_size_from_str(size_t *out, fr_sbuff_t *in)
Parse a size string with optional unit.
Definition: size.c:40
static const uchar sc[16]
Definition: smbdes.c:115
int fr_snmp_init(void)
Initialise the tree of SNMP map structures used to attach callbacks to OIDs.
Definition: snmp.c:1129
void modules_init(char const *lib_dir)
Perform global initialisation for modules.
Definition: module.c:1910
#define fr_time()
Allow us to arbitrarily manipulate time.
Definition: state_test.c:8
fr_log_dst_t dst
Log destination.
Definition: log.h:97
int fd
File descriptor to write messages to.
Definition: log.h:112
fr_log_timestamp_t timestamp
Prefix log messages with timestamps.
Definition: log.h:110
bool suppress_secrets
suppress secrets when printing to this destination
Definition: log.h:108
char const * file
Path to log file.
Definition: log.h:113
bool print_level
sometimes we don't want log levels printed
Definition: log.h:106
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition: syserror.c:243
static TALLOC_CTX * global_ctx
Definition: talloc.c:36
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition: talloc.c:445
TALLOC_CTX * talloc_page_aligned_pool(TALLOC_CTX *ctx, void **start, size_t *end_len, unsigned int headers, size_t size)
Return a page aligned talloc memory pool.
Definition: talloc.c:312
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
Definition: talloc.h:51
int fr_time_sync(void)
Get a new fr_time_monotonic_to_realtime value.
Definition: time.c:102
int fr_time_start(void)
Initialize the local time.
Definition: time.c:150
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition: time.h:590
#define fr_time_delta_wrap(_time)
Definition: time.h:152
#define fr_time_wrap(_time)
Definition: time.h:145
#define fr_time_delta_ispos(_a)
Definition: time.h:290
#define fr_time_eq(_a, _b)
Definition: time.h:241
A time delta, a difference in time measured in nanoseconds.
Definition: time.h:80
"server local" time.
Definition: time.h:69
int fr_openssl_version_consistent(void)
Definition: version.c:280
int trigger_exec(unlang_interpret_t *intp, CONF_SECTION const *cs, char const *name, bool rate_limit, fr_pair_list_t *args)
Execute a trigger - call an executable to process an event.
Definition: trigger.c:233
close(uq->fd)
static fr_event_list_t * el
void xlat_thread_detach(void)
Destroy any thread specific xlat instances.
Definition: xlat_inst.c:489
int xlat_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Create thread specific instance tree and create thread instances.
Definition: xlat_inst.c:444
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
Definition: strerror.c:733
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
Definition: strerror.c:577
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition: strerror.h:64
int fr_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
Definition: version.c:40
#define RADIUSD_VERSION_BUILD(_x)
Create a version string for a utility in the suite of FreeRADIUS utilities.
Definition: version.h:58
#define RADIUSD_MAGIC_NUMBER
Definition: version.h:81
int virtual_servers_open(fr_schedule_t *sc)
Open all the listen sockets.
void virtual_servers_thread_detach(void)
Free thread-specific data for all process modules and listeners.
int virtual_servers_init(void)
Performs global initialisation for the virtual server code.
int virtual_servers_free(void)
int virtual_servers_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Perform thread instantiation for all process modules and listeners.