30 RCSID(
"$Id: ee3c25be1e41862662fedb260326b94c1d712ced $")
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>
43 #include <freeradius-devel/tls/base.h>
44 #include <freeradius-devel/tls/log.h>
46 #include <freeradius-devel/unlang/base.h>
48 #include <freeradius-devel/util/misc.h>
49 #include <freeradius-devel/util/syserror.h>
51 #ifdef HAVE_CAPABILITY_H
52 #include <freeradius-devel/util/cap.h>
64 #ifdef HAVE_SYS_WAIT_H
65 # include <sys/wait.h>
68 # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
71 # define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
75 # include <systemd/sd-daemon.h>
79 # include <freeradius-devel/tls/version.h>
96 static void sig_hup (
int);
109 if (
config->spawn_workers) {
110 if (
config->talloc_memory_report) {
117 if (!
config->talloc_memory_report) {
118 talloc_disable_null_tracking();
122 talloc_enable_null_tracking();
139 if (fr_openssl_thread_init(
main_config->openssl_async_pool_init,
140 main_config->openssl_async_pool_max) < 0)
return -1;
157 #define EXIT_WITH_FAILURE \
159 ret = EXIT_FAILURE; \
163 #define EXIT_WITH_SUCCESS \
165 ret = EXIT_SUCCESS; \
195 PERROR(
"Failed inserting exit event");
204 #ifdef HAVE_CAPABILITY_H
205 #define DUMP_CAPABILITIES(_phase) \
208 if (fr_cap_set_to_str(talloc_autofree_context(), &cap_str) < 0) { \
209 PWARN("Failed retrieving %s capabilities", _phase); \
211 INFO("%s capabilities: %s", _phase, cap_str); \
212 talloc_free(cap_str); \
216 #define DUMP_CAPABILITIES(_phase)
223 int main(
int argc,
char *argv[])
227 bool display_version =
false;
229 int from_child[2] = {-1, -1};
232 int ret = EXIT_SUCCESS;
236 bool talloc_memory_report =
false;
238 bool raddb_dir_set =
false;
240 size_t pool_size = 0;
241 void *pool_page_start = NULL;
242 size_t pool_page_len = 0;
275 env = getenv(
"FR_GLOBAL_POOL");
278 fr_perror(
"Invalid pool size string \"%s\"", env);
288 &pool_page_start, &pool_page_len, 0, pool_size);
296 fprintf(stderr,
"Failed allocating global context\n");
307 fprintf(stderr,
"Failed allocating main config");
314 program = strrchr(argv[0], FR_DIR_SEP);
323 config->spawn_workers =
true;
326 set_auth_parameters(argc, argv);
332 if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
333 fprintf(stderr,
"%s: Unable to initialize socket library.\n",
config->name);
355 fr_perror(
"Failed installing fault handlers... continuing");
359 while ((c = getopt(argc, argv,
"Cd:D:e:fhi:l:Mmn:p:PrsS:tTvxX")) != -1)
switch (c) {
362 config->spawn_workers =
false;
363 config->daemonize =
false;
368 raddb_dir_set =
true;
382 config->daemonize =
false;
390 if (strcmp(optarg,
"stdout") == 0)
goto do_stdout;
397 fprintf(stderr,
"%s: Failed to open log file %s: %s\n",
404 config->allow_multiple_procs =
true;
408 config->talloc_memory_report =
true;
420 config->spawn_workers =
false;
421 config->daemonize =
false;
426 config->spawn_workers =
false;
427 config->daemonize =
false;
432 fprintf(stderr,
"%s: Unknown configuration option '%s'\n",
439 config->spawn_workers =
false;
447 display_version =
true;
451 config->spawn_workers =
false;
452 config->daemonize =
false;
477 if (!raddb_dir_set) {
478 char const *raddb_dir = getenv(
"FREERADIUS_CONFIG_DIR");
530 if (display_version) {
571 if (fr_tls_dict_init() < 0) {
609 if (!
config->allow_multiple_procs) {
615 PWARN(
"%s - Process concurrency checks disabled", program);
629 if (
config->panic_action && !getenv(
"PANIC_ACTION") &&
631 fr_perror(
"radiusd - Failed configuring panic action: %s",
config->name);
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]);
673 # ifdef ENABLE_OPENSSL_VERSION_CHECK
680 if (
config->openssl_fips_mode_is_set &&
689 #ifdef HAVE_SYSTEMD_WATCHDOG
690 if (!
check_config) main_loop_set_sd_watchdog_interval();
701 if (getenv(
"NOTIFY_SOCKET"))
INFO(
"Built without support for systemd watchdog, but running under systemd");
724 devnull = open(
"/dev/null", O_RDWR);
733 if (pipe(from_child) != 0) {
758 close(from_child[1]);
764 if ((read(from_child[0], &child_ret, 1) < 0)) child_ret = 0;
767 close(from_child[0]);
770 if (child_ret == 0) {
771 waitpid(pid, &stat_loc, WNOHANG);
780 sd_notifyf(0,
"MAINPID=%lu", (
unsigned long)pid);
788 }
else if (pid == 0) {
790 PWARN(
"%s - Failed incrementing exclusive proc semaphore in child", program);
795 close(from_child[0]);
822 DEBUG(
"Configuration appears to be OK");
830 PERROR(
"Failed initialising SNMP");
842 PERROR(
"Failed initialising main event loop");
860 #define COPY(_x) schedule->worker._x = config->_x
862 COPY(max_request_time);
869 if (!
config->spawn_workers) {
880 PERROR(
"Failed starting the scheduler");
911 PERROR(
"Failed installing signal handler");
925 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
931 if (
fr_set_signal(SIGHUP, sig_hup) < 0)
goto set_signal_error;
944 fp = fopen(
config->pid_file,
"w");
967 if (write(from_child[1],
"\001", 1) < 0) {
968 WARN(
"Failed informing parent of successful start: %s",
971 close(from_child[1]);
990 if (mprotect(pool_page_start, pool_page_len, PROT_READ) < 0) {
994 DEBUG(
"Global memory protected");
1004 INFO(
"Ready to process requests");
1015 if (
unlikely(signal(SIGTERM, SIG_IGN) == SIG_ERR)) {
1016 ERROR(
"Failed blocking SIGTERM, we may receive spurious signals: %s",
1024 if (mprotect(pool_page_start, pool_page_len,
1025 PROT_READ | PROT_WRITE) < 0) {
1029 DEBUG(
"Global memory unprotected");
1033 PERROR(
"Exiting due to internal error");
1036 INFO(
"Exiting normally");
1046 if (status == 2)
trigger_exec(NULL, NULL,
"server.signal.term",
true, NULL);
1062 unlink(
config->pid_file);
1073 if (!
config->spawn_workers) {
1089 if (
config->spawn_workers) {
1090 INFO(
"All threads have exited, sending SIGTERM to remaining children");
1135 if (
config) talloc_memory_report =
config->talloc_memory_report;
1200 FILE *output = status ? stderr : stdout;
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");
1208 fprintf(output,
" -e <seconds> Exit after the specified number of seconds. Useful for diagnosing \"crash-on-exit\" issues.\n");
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");
1214 fprintf(output,
" -L <size> When running in memory debug mode, set a hard limit on talloced memory\n");
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");
1219 fprintf(output,
" -M Enable talloc memory debugging, and issue a memory report when the server terminates\n");
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");
1237 static int last_sig;
1251 if (sig == last_sig)
return;
1276 static void sig_hup(
UNUSED int sig)
int fr_atexit_global_setup(void)
Setup the atexit handler, should be called at the start of a program's execution.
int fr_atexit_global_trigger_all(void)
Cause all global free triggers to fire.
#define fr_atexit_thread_trigger_all(...)
void fr_radmin_stop(void)
int fr_radmin_start(main_config_t *config, bool cli)
#define NEVER_RETURNS
Should be placed before the function return type.
void cf_md5_final(uint8_t *digest)
fr_dcursor_eval_t void const * uctx
char const * fr_debug_state_to_msg(fr_debug_state_t state)
Return current value of debug_state.
int fr_log_talloc_report(TALLOC_CTX const *ctx)
Generate a talloc memory report for a context and print to stderr/stdout.
int fr_reset_dumpable(void)
Reset dumpable state to previously configured value.
int fr_fault_setup(TALLOC_CTX *ctx, char const *cmd, char const *program)
Registers signal handlers to execute panic_action on fatal signal.
int fr_get_lsan_state(void)
void fr_debug_state_store(void)
Should be run before using setuid or setgid to get useful results.
void fr_talloc_fault_setup(void)
Register talloc fault handlers.
fr_debug_state_t fr_debug_state
Whether we're attached to by a debugger.
#define fr_exit(_x)
Exit, producing a log message in debug builds.
void dependency_version_print(void)
int rad_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
void fr_dict_global_ctx_read_only(void)
Mark all dictionaries and the global dictionary ctx as read only.
fr_dict_t const * fr_dict_internal(void)
fr_dict_t * fr_dict_unconst(fr_dict_t const *dict)
Coerce to non-const.
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.
#define fr_event_timer_in(...)
int server_init(CONF_SECTION *cs, char const *dict_dir, fr_dict_t *dict)
Initialize src/lib/server/.
void server_free(void)
Free src/lib/server/.
bool rad_suid_is_down_permanent(void)
Return whether we've permanently dropped root privileges.
void(*)(int) reset_signal(int signo, void(*func)(int))
void rad_suid_down_permanent(void)
int unlang_global_init(void)
waitpid(reap->pid_ev->pid, &status, 0)
void fr_event_loop_exit(fr_event_list_t *el, int code)
Signal an event loop exit with the specified code.
Stores all information relating to an event list.
static FILE * devnull
File handle for /dev/null.
@ L_DST_NULL
Discard log messages.
@ L_DST_FILES
Log to a file on disk.
@ L_DST_STDOUT
Log to stdout.
@ L_TIMESTAMP_ON
Always log timestamps.
int main_config_parse_option(char const *value)
int main_config_free(main_config_t **config)
void main_config_raddb_dir_set(main_config_t *config, char const *name)
Set the global radius config directory.
void main_config_exclusive_proc_done(UNUSED main_config_t const *config)
Clean up the semaphore when the main config is freed.
void main_config_hup(main_config_t *config)
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)
void main_config_name_set_default(main_config_t *config, char const *name, bool overwrite_config)
Set the server name.
int main_config_init(main_config_t *config)
main_config_t const * main_config
Main server configuration.
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.
main_config_t * main_config_alloc(TALLOC_CTX *ctx)
Allocate a main_config_t struct, setting defaults.
void main_config_dict_dir_set(main_config_t *config, char const *name)
Set the global dictionary directory.
Main server configuration.
int main_loop_start(void)
fr_event_list_t * main_loop_event_list(void)
Return the main loop event list.
void main_loop_signal_raise(int flag)
int main_loop_init(void)
Initialise the main event loop, setting up signal handlers.
void main_loop_free(void)
@ RADIUS_SIGNAL_SELF_TERM
int fr_set_signal(int sig, sig_t func)
Sets a signal handler using sigaction if available, else signal.
void modules_rlm_thread_detach(void)
Frees thread-specific data for all registered backend modules.
int modules_rlm_free(void)
Cleanup all global structures.
int modules_rlm_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Allocates thread-specific data for all registered backend modules.
int modules_rlm_init(void)
Initialise the module list structure.
static const conf_parser_t config[]
int main(int argc, char *argv[])
Entry point for the daemon.
static void thread_detach(UNUSED void *uctx)
Explicitly cleanup module/xlat resources.
static fr_event_timer_t const * fr_time_sync_ev
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.
#define DUMP_CAPABILITIES(_phase)
static void usage(main_config_t const *config, int status)
#define EXIT_WITH_SUCCESS
char const * radiusd_version
static void fr_time_sync_event(fr_event_list_t *el, UNUSED fr_time_t now, UNUSED void *uctx)
static int thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el, UNUSED void *uctx)
Create module and xlat per-thread instances.
static int talloc_config_set(main_config_t *config)
Configure talloc debugging features.
static void sig_fatal(int)
#define EXIT_WITH_FAILURE
int request_global_init(void)
#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.
int fr_schedule_destroy(fr_schedule_t **sc_to_free)
Destroy a scheduler, and tell its child threads to exit.
fr_network_config_t network
configuration for each network;
uint32_t max_workers
number of network threads
fr_time_delta_t stats_interval
print channel statistics
uint32_t max_networks
number of network threads
void radius_stats_init(int flag)
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.
static const uchar sc[16]
int fr_snmp_init(void)
Initialise the tree of SNMP map structures used to attach callbacks to OIDs.
void modules_init(char const *lib_dir)
Perform global initialisation for modules.
#define fr_time()
Allow us to arbitrarily manipulate time.
fr_log_dst_t dst
Log destination.
int fd
File descriptor to write messages to.
fr_log_timestamp_t timestamp
Prefix log messages with timestamps.
bool suppress_secrets
suppress secrets when printing to this destination
char const * file
Path to log file.
bool print_level
sometimes we don't want log levels printed
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
static TALLOC_CTX * global_ctx
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
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.
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
int fr_time_sync(void)
Get a new fr_time_monotonic_to_realtime value.
int fr_time_start(void)
Initialize the local time.
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
#define fr_time_delta_wrap(_time)
#define fr_time_wrap(_time)
#define fr_time_delta_ispos(_a)
#define fr_time_eq(_a, _b)
A time delta, a difference in time measured in nanoseconds.
int fr_openssl_version_consistent(void)
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.
static fr_event_list_t * el
void xlat_thread_detach(void)
Destroy any thread specific xlat instances.
int xlat_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Create thread specific instance tree and create thread instances.
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
int fr_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
#define RADIUSD_VERSION_BUILD(_x)
Create a version string for a utility in the suite of FreeRADIUS utilities.
#define RADIUSD_MAGIC_NUMBER
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.