2 * mainconf.c Handle the server's configuration.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2002 The FreeRADIUS server project
21 * Copyright 2002 Alan DeKok <aland@ox.org>
24 #include <freeradius-devel/autoconf.h>
29 #ifdef HAVE_NETINET_IN_H
30 #include <netinet/in.h>
33 #ifdef HAVE_ARPA_INET_H
34 #include <arpa/inet.h>
37 #include <freeradius-devel/radiusd.h>
38 #include <freeradius-devel/rad_assert.h>
39 #include <freeradius-devel/modules.h>
40 #include <freeradius-devel/request_list.h>
42 #include <sys/resource.h>
48 #ifdef HAVE_SYS_PRTCL_H
49 #include <sys/prctl.h>
56 struct main_config_t mainconfig;
59 * Temporary local variables for parsing the configuration
62 static uid_t server_uid;
63 static gid_t server_gid;
66 * These are not used anywhere else..
68 static const char *localstatedir = NULL;
69 static const char *prefix = NULL;
70 static char *syslog_facility = NULL;
71 static const LRAD_NAME_NUMBER str2fac[] = {
82 { "daemon", LOG_DAEMON },
100 { "authpriv", LOG_AUTHPRIV },
106 { "local0", LOG_LOCAL0 },
109 { "local1", LOG_LOCAL1 },
112 { "local2", LOG_LOCAL2 },
115 { "local3", LOG_LOCAL3 },
118 { "local4", LOG_LOCAL4 },
121 { "local5", LOG_LOCAL5 },
124 { "local6", LOG_LOCAL6 },
127 { "local7", LOG_LOCAL7 },
133 * Map the proxy server configuration parameters to variables.
135 static const CONF_PARSER proxy_config[] = {
136 { "retry_delay", PW_TYPE_INTEGER, 0, &mainconfig.proxy_retry_delay, Stringify(RETRY_DELAY) },
137 { "retry_count", PW_TYPE_INTEGER, 0, &mainconfig.proxy_retry_count, Stringify(RETRY_COUNT) },
138 { "default_fallback", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_fallback, "no" },
139 { "dead_time", PW_TYPE_INTEGER, 0, &mainconfig.proxy_dead_time, Stringify(DEAD_TIME) },
140 { "wake_all_if_all_dead", PW_TYPE_BOOLEAN, 0, &mainconfig.wake_all_if_all_dead, "no" },
141 { "proxy_fail_type", PW_TYPE_STRING_PTR, 0, &mainconfig.proxy_fail_type, NULL},
142 { NULL, -1, 0, NULL, NULL }
147 * Security configuration for the server.
149 static const CONF_PARSER security_config[] = {
150 { "max_attributes", PW_TYPE_INTEGER, 0, &librad_max_attributes, Stringify(0) },
151 { "reject_delay", PW_TYPE_INTEGER, 0, &mainconfig.reject_delay, Stringify(0) },
152 { "status_server", PW_TYPE_BOOLEAN, 0, &mainconfig.status_server, "no"},
153 { NULL, -1, 0, NULL, NULL }
158 * syslog configuration for the server.
160 static const CONF_PARSER log_config[] = {
161 { "syslog_facility", PW_TYPE_STRING_PTR, 0, &syslog_facility, Stringify(0) },
162 { NULL, -1, 0, NULL, NULL }
167 * A mapping of configuration file names to internal variables
169 static const CONF_PARSER server_config[] = {
171 * FIXME: 'prefix' is the ONLY one which should be
172 * configured at compile time. Hard-coding it here is
173 * bad. It will be cleaned up once we clean up the
174 * hard-coded defines for the locations of the various
177 { "prefix", PW_TYPE_STRING_PTR, 0, &prefix, "/usr/local"},
178 { "localstatedir", PW_TYPE_STRING_PTR, 0, &localstatedir, "${prefix}/var"},
179 { "logdir", PW_TYPE_STRING_PTR, 0, &radlog_dir, "${localstatedir}/log"},
180 { "libdir", PW_TYPE_STRING_PTR, 0, &radlib_dir, "${prefix}/lib"},
181 { "radacctdir", PW_TYPE_STRING_PTR, 0, &radacct_dir, "${logdir}/radacct" },
182 { "hostname_lookups", PW_TYPE_BOOLEAN, 0, &librad_dodns, "no" },
184 { "snmp", PW_TYPE_BOOLEAN, 0, &mainconfig.do_snmp, "no" },
186 { "max_request_time", PW_TYPE_INTEGER, 0, &mainconfig.max_request_time, Stringify(MAX_REQUEST_TIME) },
187 { "cleanup_delay", PW_TYPE_INTEGER, 0, &mainconfig.cleanup_delay, Stringify(CLEANUP_DELAY) },
188 { "max_requests", PW_TYPE_INTEGER, 0, &mainconfig.max_requests, Stringify(MAX_REQUESTS) },
189 { "delete_blocked_requests", PW_TYPE_INTEGER, 0, &mainconfig.kill_unresponsive_children, Stringify(FALSE) },
190 { "allow_core_dumps", PW_TYPE_BOOLEAN, 0, &mainconfig.allow_core_dumps, "no" },
191 { "log_stripped_names", PW_TYPE_BOOLEAN, 0, &log_stripped_names,"no" },
193 { "log_file", PW_TYPE_STRING_PTR, -1, &mainconfig.log_file, "${logdir}/radius.log" },
194 { "log_auth", PW_TYPE_BOOLEAN, -1, &mainconfig.log_auth, "no" },
195 { "log_auth_badpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_badpass, "no" },
196 { "log_auth_goodpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_goodpass, "no" },
197 { "pidfile", PW_TYPE_STRING_PTR, 0, &mainconfig.pid_file, "${run_dir}/radiusd.pid"},
198 { "user", PW_TYPE_STRING_PTR, 0, &mainconfig.uid_name, NULL},
199 { "group", PW_TYPE_STRING_PTR, 0, &mainconfig.gid_name, NULL},
200 { "checkrad", PW_TYPE_STRING_PTR, 0, &mainconfig.checkrad, "${sbindir}/checkrad" },
202 { "debug_level", PW_TYPE_INTEGER, 0, &mainconfig.debug_level, "0"},
204 { "proxy_requests", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_requests, "yes" },
205 { "log", PW_TYPE_SUBSECTION, 0, NULL, (const void *) log_config},
206 { "proxy", PW_TYPE_SUBSECTION, 0, NULL, (const void *) proxy_config },
207 { "security", PW_TYPE_SUBSECTION, 0, NULL, (const void *) security_config },
208 { NULL, -1, 0, NULL, NULL }
212 #define MAX_ARGV (256)
214 * Xlat for %{config:section.subsection.attribute}
216 static int xlat_config(void *instance, REQUEST *request,
217 char *fmt, char *out,
219 RADIUS_ESCAPE_STRING func)
224 const char *from, *value;
228 char *argv[MAX_ARGV];
230 request = request; /* -Wunused */
231 instance = instance; /* -Wunused */
237 * Split the string into argv's BEFORE doing radius_xlat...
250 if (argc >= (MAX_ARGV - 1)) break;
253 * Copy the argv over to our buffer.
256 if (to >= myfmt + sizeof(myfmt) - 1) {
257 return 0; /* no error msg */
262 if (from[1] == '{') {
265 length = rad_copy_variable(to, from);
271 } else { /* FIXME: catch %%{ ? */
278 radlog(L_ERR, "config: Unexpected nested '[' in \"%s\"", fmt);
287 radlog(L_ERR, "config: Unbalanced ']' in \"%s\"", fmt);
290 if (from[1] != '.') {
291 radlog(L_ERR, "config: Unexpected text after ']' in \"%s\"", fmt);
300 if (flag == 0) break;
308 if ((*from == '.') && (flag == 0)) {
312 } /* end of string, or found a period */
315 radlog(L_ERR, "config: Unbalanced '[' in \"%s\"", fmt);
319 *(to++) = '\0'; /* terminate the string. */
323 * Expand each string, as appropriate
326 left = sizeof(argv_buf);
327 for (i = 0; i < argc; i++) {
331 * Don't touch argv's which won't be translated.
333 if (strchr(argv[i], '%') == NULL) continue;
335 sublen = radius_xlat(to, left - 1, argv[i], request, NULL);
338 * Fail to be backwards compatible.
340 * It's yucky, but it won't break anything,
341 * and it won't cause security problems.
358 cs = cf_section_find(NULL); /* get top-level section */
361 * Root through section & subsection references.
362 * The last entry of argv MUST be the CONF_PAIR.
364 for (i = 0; i < argc - 1; i++) {
369 * FIXME: What about RADIUS attributes containing '['?
371 name2 = strchr(argv[i], '[');
373 char *p = strchr(name2, ']');
374 rad_assert(p != NULL);
375 rad_assert(p[1] =='\0');
382 subcs = cf_section_sub_find_name2(cs, argv[i],
385 radlog(L_ERR, "config: section \"%s %s {}\" not found while dereferencing \"%s\"", argv[i], name2, fmt);
389 subcs = cf_section_sub_find(cs, argv[i]);
391 radlog(L_ERR, "config: section \"%s {}\" not found while dereferencing \"%s\"", argv[i], fmt);
396 } /* until argc - 1 */
399 * This can now have embedded periods in it.
401 cp = cf_pair_find(cs, argv[argc - 1]);
403 radlog(L_ERR, "config: item \"%s\" not found while dereferencing \"%s\"", argv[argc], fmt);
408 * Ensure that we only copy what's necessary.
410 * If 'outlen' is too small, then the output is chopped to fit.
412 value = cf_pair_value(cp);
414 if (outlen > strlen(value)) {
415 outlen = strlen(value) + 1;
419 return func(out, outlen, value);
424 * Recursively make directories.
426 static int r_mkdir(const char *part)
428 char *ptr, parentdir[500];
431 if (stat(part, &st) == 0)
434 ptr = strrchr(part, '/');
439 snprintf(parentdir, (ptr - part)+1, "%s", part);
441 if (r_mkdir(parentdir) != 0)
444 if (mkdir(part, 0770) != 0) {
445 radlog(L_ERR, "mkdir(%s) error: %s\n", part, strerror(errno));
453 * Checks if the log directory is writeable by a particular user.
455 static int radlogdir_iswritable(const char *effectiveuser)
457 struct passwd *pwent;
459 if (radlog_dir[0] != '/')
462 if (r_mkdir(radlog_dir) != 0)
465 /* FIXME: do we have this function? */
466 if (strstr(radlog_dir, "radius") == NULL)
469 /* we have a logdir that mentions 'radius', so it's probably
470 * safe to chown the immediate directory to be owned by the normal
471 * process owner. we gotta do it before we give up root. -chad
474 if (!effectiveuser) {
478 pwent = getpwnam(effectiveuser);
480 if (pwent == NULL) /* uh oh! */
483 if (chown(radlog_dir, pwent->pw_uid, -1) != 0)
491 * Switch UID and GID to what is specified in the config file
493 static int switch_users(void)
495 struct rlimit core_limits;
498 if (mainconfig.gid_name != NULL) {
501 gr = getgrnam(mainconfig.gid_name);
503 if (errno == ENOMEM) {
504 radlog(L_ERR|L_CONS, "Cannot switch to Group %s: out of memory", mainconfig.gid_name);
506 radlog(L_ERR|L_CONS, "Cannot switch group; %s doesn't exist", mainconfig.gid_name);
510 server_gid = gr->gr_gid;
511 if (setgid(server_gid) < 0) {
512 radlog(L_ERR|L_CONS, "Failed setting Group to %s: %s",
513 mainconfig.gid_name, strerror(errno));
517 server_gid = getgid();
521 if (mainconfig.uid_name != NULL) {
524 pw = getpwnam(mainconfig.uid_name);
526 if (errno == ENOMEM) {
527 radlog(L_ERR|L_CONS, "Cannot switch to User %s: out of memory", mainconfig.uid_name);
529 radlog(L_ERR|L_CONS, "Cannot switch user; %s doesn't exist", mainconfig.uid_name);
533 server_uid = pw->pw_uid;
534 #ifdef HAVE_INITGROUPS
535 if (initgroups(mainconfig.uid_name, server_gid) < 0) {
536 if (errno != EPERM) {
537 radlog(L_ERR|L_CONS, "Failed setting supplementary groups for User %s: %s", mainconfig.uid_name, strerror(errno));
542 if (setuid(server_uid) < 0) {
543 radlog(L_ERR|L_CONS, "Failed setting User to %s: %s", mainconfig.uid_name, strerror(errno));
548 /* Get the current maximum for core files. */
549 if (getrlimit(RLIMIT_CORE, &core_limits) < 0) {
550 radlog(L_ERR|L_CONS, "Failed to get current core limit: %s", strerror(errno));
554 if (mainconfig.allow_core_dumps) {
555 #ifdef HAVE_SYS_PRTCL_H
556 #ifdef PR_SET_DUMPABLE
557 if (prctl(PR_SET_DUMPABLE, 1) < 0) {
558 radlog(L_ERR|L_CONS,"Cannot enable core dumps: prctl(PR_SET_DUMPABLE) failed: '%s'",
564 if (setrlimit(RLIMIT_CORE, &core_limits) < 0) {
565 radlog(L_ERR|L_CONS, "Cannot update core dump limit: %s",
570 * If we're running as a daemon, and core
571 * dumps are enabled, log that information.
573 } else if ((core_limits.rlim_cur != 0) && !debug_flag)
574 radlog(L_INFO|L_CONS, "Core dumps are enabled.");
576 } else if (!debug_flag) {
578 * Not debugging. Set the core size to zero, to
579 * prevent security breaches. i.e. People
580 * reading passwords from the 'core' file.
582 struct rlimit limits;
585 limits.rlim_max = core_limits.rlim_max;
587 if (setrlimit(RLIMIT_CORE, &limits) < 0) {
588 radlog(L_ERR|L_CONS, "Cannot disable core dumps: %s",
595 * We've probably written to the log file already as
596 * root.root, so if we have switched users, we've got to
597 * update the ownership of the file.
599 if ((debug_flag == 0) &&
600 (mainconfig.radlog_dest == RADLOG_FILES) &&
601 (mainconfig.log_file != NULL)) {
602 chown(mainconfig.log_file, server_uid, server_gid);
610 * Create the linked list of realms from the new configuration type
611 * This way we don't have to change to much in the other source-files
613 static int generate_realms(const char *filename)
616 REALM *my_realms = NULL;
618 char *s, *t, *authhost, *accthost;
622 for (cs = cf_subsection_find_next(mainconfig.config, NULL, "realm");
624 cs = cf_subsection_find_next(mainconfig.config, cs, "realm")) {
625 name2 = cf_section_name2(cs);
627 radlog(L_CONS|L_ERR, "%s[%d]: Missing realm name",
628 filename, cf_section_lineno(cs));
632 * We've found a realm, allocate space for it
634 c = rad_malloc(sizeof(REALM));
635 memset(c, 0, sizeof(REALM));
640 * No authhost means LOCAL.
642 if ((authhost = cf_section_value_find(cs, "authhost")) == NULL) {
643 c->ipaddr.af = AF_INET;
644 c->ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
647 if ((s = strchr(authhost, ':')) != NULL) {
649 c->auth_port = atoi(s);
651 c->auth_port = PW_AUTH_UDP_PORT;
653 if (strcmp(authhost, "LOCAL") == 0) {
655 * Local realms don't have an IP address,
658 c->ipaddr.af = AF_INET;
659 c->ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
662 if (ip_hton(authhost, AF_INET,
664 radlog(L_ERR, "%s[%d]: Host %s not found",
665 filename, cf_section_lineno(cs),
672 * Double check length, just to be sure!
674 if (strlen(authhost) >= sizeof(c->server)) {
675 radlog(L_ERR, "%s[%d]: Server name of length %u is greater than allowed: %u",
676 filename, cf_section_lineno(cs),
678 sizeof(c->server) - 1);
684 * No accthost means LOCAL
686 if ((accthost = cf_section_value_find(cs, "accthost")) == NULL) {
687 c->acct_ipaddr.af = AF_INET;
688 c->acct_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
691 if ((s = strchr(accthost, ':')) != NULL) {
693 c->acct_port = atoi(s);
695 c->acct_port = PW_ACCT_UDP_PORT;
697 if (strcmp(accthost, "LOCAL") == 0) {
699 * Local realms don't have an IP address,
702 c->acct_ipaddr.af = AF_INET;
703 c->acct_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
706 if (ip_hton(accthost, AF_INET,
707 &c->acct_ipaddr) < 0) {
708 radlog(L_ERR, "%s[%d]: Host %s not found",
709 filename, cf_section_lineno(cs),
715 if (strlen(accthost) >= sizeof(c->acct_server)) {
716 radlog(L_ERR, "%s[%d]: Server name of length %u is greater than allowed: %u",
717 filename, cf_section_lineno(cs),
719 sizeof(c->acct_server) - 1);
724 if (strlen(name2) >= sizeof(c->realm)) {
725 radlog(L_ERR, "%s[%d]: Realm name of length %u is greater than allowed %u",
726 filename, cf_section_lineno(cs),
728 sizeof(c->server) - 1);
732 strcpy(c->realm, name2);
733 if (authhost) strcpy(c->server, authhost);
734 if (accthost) strcpy(c->acct_server, accthost);
737 * If one or the other of authentication/accounting
738 * servers is set to LOCALHOST, then don't require
741 rad_assert(c->ipaddr.af == AF_INET);
742 rad_assert(c->acct_ipaddr.af == AF_INET);
743 if ((c->ipaddr.ipaddr.ip4addr.s_addr != htonl(INADDR_NONE)) ||
744 (c->acct_ipaddr.ipaddr.ip4addr.s_addr != htonl(INADDR_NONE))) {
745 if ((s = cf_section_value_find(cs, "secret")) == NULL ) {
746 radlog(L_ERR, "%s[%d]: No shared secret supplied for realm: %s",
747 filename, cf_section_lineno(cs), name2);
751 if (strlen(s) >= sizeof(c->secret)) {
752 radlog(L_ERR, "%s[%d]: Secret of length %u is greater than the allowed maximum of %u.",
753 filename, cf_section_lineno(cs),
754 strlen(s), sizeof(c->secret) - 1);
757 strNcpy((char *)c->secret, s, sizeof(c->secret));
762 if ((cf_section_value_find(cs, "nostrip")) != NULL)
764 if ((cf_section_value_find(cs, "noacct")) != NULL)
766 if ((cf_section_value_find(cs, "trusted")) != NULL)
768 if ((cf_section_value_find(cs, "notrealm")) != NULL)
770 if ((cf_section_value_find(cs, "notsuffix")) != NULL)
772 if ((t = cf_section_value_find(cs,"ldflag")) != NULL) {
773 static const LRAD_NAME_NUMBER ldflags[] = {
775 { "round_robin", 1 },
779 c->ldflag = lrad_str2int(ldflags, t, -1);
780 if (c->ldflag == -1) {
781 radlog(L_ERR, "%s[%d]: Unknown value \"%s\" for ldflag",
782 filename, cf_section_lineno(cs),
788 c->ldflag = 0; /* non, make it fail-over */
791 c->acct_active = TRUE;
799 * And make these realms preferred over the ones
800 * in the 'realms' file.
802 *tail = mainconfig.realms;
803 mainconfig.realms = my_realms;
806 * Ensure that all of the flags agree for the realms.
808 * Yeah, it's O(N^2), but it's only once, and the
809 * maximum number of realms is small.
811 for(c = mainconfig.realms; c != NULL; c = c->next) {
815 * Check that we cannot load balance to LOCAL
816 * realms, as that doesn't make any sense.
818 rad_assert(c->ipaddr.af == AF_INET);
819 rad_assert(c->acct_ipaddr.af == AF_INET);
820 if ((c->ldflag == 1) &&
821 ((c->ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_NONE)) ||
822 (c->acct_ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_NONE)))) {
823 radlog(L_ERR | L_CONS, "ERROR: Realm %s cannot be load balanced to LOCAL",
829 * Compare this realm to all others, to ensure
830 * that the configuration is consistent.
832 for (this = c->next; this != NULL; this = this->next) {
833 if (strcasecmp(c->realm, this->realm) != 0) {
838 * Same realm: Different load balancing
841 if (c->ldflag != this->ldflag) {
842 radlog(L_ERR | L_CONS, "ERROR: Inconsistent value in realm %s for load balancing 'ldflag' attribute",
853 static const LRAD_NAME_NUMBER str2dest[] = {
854 { "null", RADLOG_NULL },
855 { "files", RADLOG_FILES },
856 { "syslog", RADLOG_SYSLOG },
857 { "stdout", RADLOG_STDOUT },
858 { "stderr", RADLOG_STDERR },
859 { NULL, RADLOG_NUM_DEST }
866 * This function can ONLY be called from the main server process.
868 int read_mainconfig(int reload)
870 static int old_debug_level = -1;
872 CONF_SECTION *cs, *oldcs;
873 rad_listen_t *listener;
875 /* Read the configuration file */
876 snprintf(buffer, sizeof(buffer), "%.200s/%.50s",
877 radius_dir, mainconfig.radiusd_conf);
878 if ((cs = cf_file_read(buffer)) == NULL) {
879 radlog(L_ERR|L_CONS, "Errors reading %s", buffer);
884 * Debug flag 1 MAY go to files.
885 * Debug flag 2 ALWAYS goes to stdout
887 * Parse the log_destination before printing anything else.
888 * All messages before this MUST be errors, which log.c
889 * will print to stderr, since log_file is NULL, too.
891 if (debug_flag < 2) {
893 char *radlog_dest = NULL;
895 rcode = cf_item_parse(cs, "log_destination",
896 PW_TYPE_STRING_PTR, &radlog_dest,
898 if (rcode < 0) return -1;
900 mainconfig.radlog_dest = lrad_str2int(str2dest, radlog_dest, RADLOG_NUM_DEST);
901 if (mainconfig.radlog_dest == RADLOG_NUM_DEST) {
902 fprintf(stderr, "radiusd: Error: Unknown log_destination %s\n",
905 cf_section_free(&cs);
909 if (mainconfig.radlog_dest == RADLOG_SYSLOG) {
910 static const CONF_PARSER syslog_config[] = {
911 { "log", PW_TYPE_SUBSECTION, 0, NULL, (const void *) log_config},
912 { NULL, -1, 0, NULL, NULL }
914 cf_section_parse(cs, NULL, syslog_config);
917 * Make sure syslog_facility isn't NULL before using it
919 if (!syslog_facility) {
920 fprintf(stderr, "radiusd: Error: Unknown syslog chosen but no facility spedified\n");
922 cf_section_free(&cs);
925 mainconfig.syslog_facility = lrad_str2int(str2fac, syslog_facility, -1);
926 if (mainconfig.syslog_facility < 0) {
927 fprintf(stderr, "radiusd: Error: Unknown syslog_facility %s\n",
930 free(syslog_facility);
931 cf_section_free(&cs);
936 if (mainconfig.radlog_dest == RADLOG_FILES) {
937 static const CONF_PARSER file_config[] = {
938 { "log_file", PW_TYPE_STRING_PTR, -1, &mainconfig.log_file, "${logdir}/radius.log" },
939 { NULL, -1, 0, NULL, NULL }
942 cf_section_parse(cs, NULL, file_config);
947 mainconfig.radlog_dest = RADLOG_STDOUT;
948 mainconfig.radlog_fd = STDOUT_FILENO;
951 radlog(L_INFO, "%s", radiusd_version);
953 radlog(L_INFO, "Starting - reading configuration files ...");
955 radlog(L_INFO, "Reloading - reading configuration files...");
958 /* Initialize the dictionary */
959 DEBUG2("read_config_files: reading dictionary");
960 if (dict_init(radius_dir, RADIUS_DICTIONARY) != 0) {
961 radlog(L_ERR|L_CONS, "Errors reading dictionary: %s",
967 * This allows us to figure out where, relative to
968 * radiusd.conf, the other configuration files exist.
970 cf_section_parse(cs, NULL, server_config);
974 * Merge the old with the new.
979 newcs = cf_section_sub_find(cs, "modules");
980 oldcs = cf_section_sub_find(mainconfig.config, "modules");
981 if (newcs && oldcs) {
982 if (!cf_section_migrate(newcs, oldcs)) {
983 radlog(L_ERR|L_CONS, "Fatal error migrating configuration data");
991 * Free the old configuration items, and replace them
994 * Note that where possible, we do atomic switch-overs,
995 * to ensure that the pointers are always valid.
997 oldcs = mainconfig.config;
998 mainconfig.config = cs;
999 cf_section_free(&oldcs);
1002 * Old-style realms file.
1004 snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_REALMS);
1005 DEBUG2("read_config_files: reading realms");
1006 if (read_realms_file(buffer) < 0) {
1007 radlog(L_ERR|L_CONS, "Errors reading realms");
1012 * If there isn't any realms it isn't fatal..
1014 snprintf(buffer, sizeof(buffer), "%.200s/%.50s",
1015 radius_dir, mainconfig.radiusd_conf);
1016 if (generate_realms(buffer) < 0) {
1021 * Register the %{config:section.subsection} xlat function.
1023 xlat_register("config", xlat_config, NULL);
1026 * Set the libraries debugging flag to whatever the main
1027 * flag is. Note that on a SIGHUP, to turn the debugging
1028 * off, we do other magic.
1030 * Increase the debug level, if the configuration file
1031 * says to, OR, if we're decreasing the debug from what it
1032 * was before, allow that, too.
1034 if ((mainconfig.debug_level > debug_flag) ||
1035 (mainconfig.debug_level <= old_debug_level)) {
1036 debug_flag = mainconfig.debug_level;
1038 librad_debug = debug_flag;
1039 old_debug_level = mainconfig.debug_level;
1042 * Go update our behaviour, based on the configuration
1047 * The first time around, ensure that we can write to the
1052 * We need root to do mkdir() and chown(), so we
1053 * do this before giving up root.
1055 radlogdir_iswritable(mainconfig.uid_name);
1059 * We should really switch users earlier in the process.
1064 * Sanity check the configuration for internal
1067 if (mainconfig.reject_delay > mainconfig.cleanup_delay) {
1068 mainconfig.reject_delay = mainconfig.cleanup_delay;
1072 * Initialize the old "bind_address" and "port", first.
1077 * Read the list of listeners.
1079 snprintf(buffer, sizeof(buffer), "%.200s/%.50s",
1080 radius_dir, mainconfig.radiusd_conf);
1081 if (listen_init(buffer, &listener) < 0) {
1086 radlog(L_ERR|L_CONS, "Server is not configured to listen on any ports. Exiting.");
1090 listen_free(&mainconfig.listen);
1091 mainconfig.listen = listener;
1094 * Walk through the listeners. If we're listening on acct
1095 * or auth, read in the clients files, else ignore them.
1097 for (listener = mainconfig.listen;
1099 listener = listener->next) {
1100 if ((listener->type == RAD_LISTEN_AUTH) ||
1101 (listener->type == RAD_LISTEN_ACCT)) {
1106 if (listener != NULL) {
1107 RADCLIENT_LIST *clients, *old_clients;
1110 * Create the new clients first, and add them
1111 * to the CONF_SECTION, where they're automagically
1112 * freed if anything goes wrong.
1114 snprintf(buffer, sizeof(buffer), "%.200s/%.50s",
1115 radius_dir, mainconfig.radiusd_conf);
1116 clients = clients_parse_section(buffer, mainconfig.config);
1122 * Free the old trees AFTER replacing them with
1125 old_clients = mainconfig.clients;
1126 mainconfig.clients = clients;
1131 /* Reload the modules. */
1132 DEBUG2("radiusd: entering modules setup");
1133 if (setup_modules(reload) < 0) {
1134 radlog(L_ERR|L_CONS, "Errors setting up modules");
1141 * Free the configuration. Called only when the server is exiting.
1143 int free_mainconfig(void)
1146 * Clean up the configuration data
1149 cf_section_free(&mainconfig.config);
1150 realm_free(mainconfig.realms);
1151 listen_free(&mainconfig.listen);