1 /* This file is part of GNU Radius.
2 Copyright (C) 2000,2001,2002,2003,2004,2005,2007,
3 2008 Free Software Foundation
4
5 GNU Radius is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 GNU Radius is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNU Radius; if not, write to the Free Software Foundation,
17 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <netinet/in.h>
25 #include <netdb.h>
26 #include <fcntl.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <signal.h>
31 #include <errno.h>
32 #include <sys/wait.h>
33
34 #include <radiusd.h>
35 #include <radius/radargp.h>
36 #include <radius/radutmp.h>
37 #include <radius/argcv.h>
38 #include <rewrite.h>
39 #include <snmp/asn1.h>
40 #include <snmp/snmp.h>
41 #include <timestr.h>
42
43 const char *argp_program_version = "radiusd (" PACKAGE ") " VERSION;
44 static char doc[] = N_("GNU radius daemon");
45
46 #define SHOW_DEFAULTS_OPTION 256
47 #define SELECT_PORTS_OPTION 257
48
49 static struct argp_option options[] = {
50 #define GRP 100
51 {NULL, 0, NULL, 0,
52 N_("radiusd specific switches:"), GRP},
53 {"foreground", 'f', NULL, 0,
54 N_("Stay in foreground"), GRP+1},
55 {"mode", 'm', "{t|c|b}", 0,
56 N_("Select operation mode: test, checkconf, builddbm."), GRP+1},
57 {"single-process", 's', NULL, 0,
58 N_("Run in single process mode"), GRP+1},
59 {"pid-file-dir", 'P', N_("DIR"), 0,
60 N_("Store pidfile in DIR"), GRP+1},
61 {"show-defaults", SHOW_DEFAULTS_OPTION, NULL, 0,
62 N_("Show compilation defaults"), GRP+1},
63 {"quiet", 'q', NULL, 0,
64 N_("Quiet mode (valid only with --mode)"), GRP+1},
65 {"select-free-ports", SELECT_PORTS_OPTION, N_("FILE"), 0,
66 N_("Select port numbers from available UDP ports"), GRP+1 },
67 #undef GRP
68 #define GRP 200
69 {NULL, 0, NULL, 0,
70 N_("Daemon configuration options. Please use raddb/config instead."),
71 GRP},
72
73 {"log-auth-detail", 'A', 0, 0,
74 N_("Do detailed authentication logging"), GRP+1},
75 {"acct-directory", 'a', N_("DIR"), 0,
76 N_("Set accounting directory"), GRP+1},
77 #ifdef USE_DBM
78 {"dbm", 'b', NULL, 0,
79 N_("Enable DBM support"), GRP+1},
80 #endif
81 {"logging-directory", 'l', N_("DIR"), 0,
82 N_("Set logging directory name"), GRP+1},
83 {"do-not-resolve", 'n', NULL, 0,
84 N_("Do not resolve IP addresses"), GRP+1},
85 {"ip-address", 'i', N_("IPADDR"), 0,
86 N_("Listen on IPADDR"), GRP+1},
87 {"port", 'p', "NUMBER", 0,
88 N_("Set authentication port number"), GRP+1},
89 {"log-stripped-names", 'S', NULL, 0,
90 N_("Strip prefixes/suffixes off user names before logging"), GRP+1},
91 {"debug", 'x', N_("DEBUGSPEC"), 0,
92 N_("Set debugging level"), GRP+1},
93 {"log-auth", 'y', NULL, 0,
94 N_("Log authentications"), GRP+1},
95 {"log-auth-pass", 'z', NULL, 0,
96 N_("Log users' passwords"), GRP+1},
97 #undef GRP
98 {NULL, 0, NULL, 0, NULL, 0}
99 };
100
101
102 /* *************************** Global Variables **************************** */
103
104 int debug_flag; /* can be raised from debugger only */
105 int log_mode; /* logging mode */
106 int console_logging_priority = -1; /* Default priority for console
107 logging */
108 char *auth_log_hook; /* Authentication logging hook function */
109
110 static int foreground; /* Stay in the foreground */
111 int spawn_flag; /* Whether to spawn new children for handling
112 the requests */
113
114 int use_dbm = 0; /* Use DBM storage */
115 int auth_detail = 0; /* Produce detailed logs of authentication packets */
116 char *auth_detail_template; /* Template for filenames of these logs */
117 int acct_detail = 1; /* Produce detailed logs of accounting packets */
118 char *acct_detail_template; /* Template for filenames of these logs */
119 int acct_system = 1; /* Run system accounting into radutmp/radwtmp files */
120 int auth_trace_rules = 0; /* Produce trace logs for each auth request */
121 int acct_trace_rules = 0; /* Produce trace logs for each acct request */
122 int strip_names; /* Strip preffixes/suffixes off the usernames */
123 int suspend_flag; /* Suspend processing of RADIUS requests */
124 int auth_reject_malformed_names = 0; /* Respond with Access-Reject packets
125 for requests with malformed user
126 names */
127
128 char *select_free_ports;
129 FILE *port_file;
130
131 RADIUS_USER radiusd_user; /* Run the daemon with this user privileges */
132 RADIUS_USER exec_user; /* Run the user programs with this user privileges */
133
134 #define CMD_NONE 0 /* No command */
135 #define CMD_CLEANUP 1 /* Cleanup finished children */
136 #define CMD_RELOAD 2 /* The reload of the configuration is needed */
137 #define CMD_RESTART 3 /* Try to restart */
138 #define CMD_MEMINFO 4 /* Dump memory usage statistics */
139 #define CMD_DUMPDB 5 /* Dump authentication database */
140 #define CMD_SHUTDOWN 6 /* Stop immediately */
141 #define CMD_SUSPEND 7 /* Suspend service */
142 #define CMD_CONTINUE 8 /* Continue after suspend */
143
144 int daemon_command = CMD_NONE;
145
146 static INPUT *radius_input; /* The input channels */
147
148 #ifdef USE_SNMP
149 int snmp_port;
150 serv_stat saved_status;
151 #endif
152
153 /* These are the user flag marking attributes that
154 can be used in comparing ... */
155 int auth_comp_flag; /* ... authentication requests */
156 int acct_comp_flag; /* ... accounting requests */
157
158 int checkrad_assume_logged = 1;
159 size_t max_requests = MAX_REQUESTS;
160 size_t max_children = MAX_CHILDREN;
161 unsigned process_timeout = PROCESS_TIMEOUT;
162 unsigned radiusd_write_timeout = RADIUSD_WRITE_TIMEOUT;
163 unsigned radiusd_read_timeout = RADIUSD_READ_TIMEOUT;
164
165 grad_uint32_t warning_seconds;
166 int use_guile;
167 char *message_text[MSG_COUNT];
168 grad_uint32_t myip = INADDR_ANY;
169 grad_uint32_t ref_ip = INADDR_ANY;
170 int auth_port;
171 int acct_port;
172
173 pid_t radiusd_pid;
174 int radius_mode = MODE_DAEMON;
175
176 /* Invocation vector for self-restart */
177 int xargc;
178 char **xargv;
179 char *x_debug_spec;
180
181 /* Forward declarations */
182 static RETSIGTYPE sig_handler(int sig);
183 void radiusd_main_loop();
184 static size_t radius_count_channels();
185 void radiusd_run_preconfig_hooks(void *data);
186 struct cfg_stmt config_syntax[];
187
188
189 /* ************************ Command Line Parser **************************** */
190
191 static error_t
parse_opt(int key,char * arg,struct argp_state * state)192 parse_opt(int key, char *arg, struct argp_state *state)
193 {
194 switch (key) {
195 case 'A':
196 auth_detail++;
197 break;
198
199 case 'a':
200 grad_acct_dir = grad_estrdup(arg);
201 break;
202
203 #ifdef USE_DBM
204 case 'b':
205 use_dbm++;
206 break;
207 #endif
208
209 case 'f':
210 foreground = 1;
211 break;
212
213 case 'l':
214 grad_log_dir = grad_estrdup(arg);
215 break;
216
217 case 'm':
218 switch (arg[0]) {
219 case 't':
220 radius_mode = MODE_TEST;
221 break;
222
223 case 'b':
224 #ifdef USE_DBM
225 radius_mode = MODE_BUILDDBM;
226 #else
227 argp_error(state,
228 _("radiusd compiled without DBM support"));
229 exit(1);
230 #endif
231 break;
232
233 case 'c':
234 radius_mode = MODE_CHECKCONF;
235 break;
236
237 default:
238 argp_error(state, _("unknown mode: %s"), arg);
239 exit(1);
240 }
241 break;
242
243 case 'n':
244 grad_resolve_hostnames = 0;
245 break;
246
247 case 'i':
248 if ((myip = grad_ip_gethostaddr(arg)) == 0)
249 fprintf(stderr,
250 _("invalid IP address: %s"),
251 arg);
252 break;
253
254 case 'P':
255 grad_pid_dir = arg;
256 break;
257
258 case 'p':
259 auth_port = atoi(arg);
260 acct_port = auth_port+1;
261 break;
262
263 case 'q':
264 console_logging_priority = GRAD_LOG_ERR;
265 break;
266
267 case 'S':
268 strip_names++;
269 break;
270
271 case 's': /* Single process mode */
272 spawn_flag = 0;
273 break;
274
275 case SELECT_PORTS_OPTION:
276 select_free_ports = arg;
277 break;
278
279 case 'x':
280 x_debug_spec = arg;
281 grad_set_debug_levels(arg);
282 break;
283
284 case 'y':
285 log_mode |= RLOG_AUTH;
286 break;
287
288 case 'z':
289 log_mode |= RLOG_AUTH_PASS;
290 break;
291
292 case SHOW_DEFAULTS_OPTION:
293 show_compilation_defaults();
294 exit(0);
295
296 default:
297 return ARGP_ERR_UNKNOWN;
298 }
299 return 0;
300 }
301
302 static struct argp argp = {
303 options,
304 parse_opt,
305 NULL,
306 doc,
307 grad_common_argp_child,
308 NULL, NULL
309 };
310
311
312 /* *********************** Configuration Functions ************************* */
313 void
set_config_defaults()314 set_config_defaults()
315 {
316 username_valid_chars = grad_estrdup(".-_!@#$%^&\\/");
317 message_text[MSG_ACCOUNT_CLOSED] =
318 grad_estrdup(_("Sorry, your account is currently closed\n"));
319 message_text[MSG_PASSWORD_EXPIRED] =
320 grad_estrdup(_("Password has expired\n"));
321 message_text[MSG_PASSWORD_EXPIRE_WARNING] =
322 grad_estrdup(_("Password will expire in %R{Password-Expire-Days} Days\n"));
323 message_text[MSG_ACCESS_DENIED] =
324 grad_estrdup(_("\nAccess denied\n"));
325 message_text[MSG_REALM_QUOTA] =
326 grad_estrdup(_("\nRealm quota exceeded - access denied\n"));
327 message_text[MSG_MULTIPLE_LOGIN] =
328 grad_estrdup(_("\nYou are already logged in %R{Simultaneous-Use} times - access denied\n"));
329 message_text[MSG_SECOND_LOGIN] =
330 grad_estrdup(_("\nYou are already logged in - access denied\n"));
331 message_text[MSG_TIMESPAN_VIOLATION] =
332 grad_estrdup(_("You are calling outside your allowed timespan\n"));
333 }
334
335 static int
get_port_number(char * name,char * proto,int defval)336 get_port_number(char *name, char *proto, int defval)
337 {
338 struct servent *svp;
339
340 svp = getservbyname(name, proto);
341 return svp ? ntohs(svp->s_port) : defval;
342 }
343
344 unsigned
max_ttl(time_t * t)345 max_ttl(time_t *t)
346 {
347 unsigned i, delta = 0;
348
349 for (i = 0; i < R_MAX; i++)
350 if (delta < request_class[i].ttl)
351 delta = request_class[i].ttl;
352 if (t) {
353 time(t);
354 *t += delta;
355 }
356 return delta;
357 }
358
359 static void
terminate_subprocesses()360 terminate_subprocesses()
361 {
362 int kill_sent = 0;
363 time_t t;
364
365 /* Flush any pending requests and empty the request queue */
366 radiusd_flush_queue();
367 request_init_queue();
368
369 /* Terminate all subprocesses */
370 grad_log(GRAD_LOG_INFO, _("Terminating the subprocesses"));
371 rpp_kill(-1, SIGTERM);
372
373 max_ttl(&t);
374
375 while (rpp_count()) {
376 sleep(1);
377 radiusd_cleanup();
378 if (time(NULL) >= t) {
379 if (kill_sent) {
380 int n = rpp_count();
381 grad_log(GRAD_LOG_CRIT,
382 ngettext("%d process left!",
383 "%d processes left!",
384 n),
385 n);
386 break;
387 }
388 max_ttl(&t);
389 rpp_kill(-1, SIGKILL);
390 kill_sent = 1;
391 }
392 }
393 }
394
395 static void
radiusd_preconfig_hook(void * a ARG_UNUSED,void * b ARG_UNUSED)396 radiusd_preconfig_hook(void *a ARG_UNUSED, void *b ARG_UNUSED)
397 {
398 terminate_subprocesses();
399 input_close_channels(radius_input);
400 }
401
402 static void
radiusd_postconfig_hook(void * a ARG_UNUSED,void * b ARG_UNUSED)403 radiusd_postconfig_hook(void *a ARG_UNUSED, void *b ARG_UNUSED)
404 {
405 if (radius_mode == MODE_DAEMON && radius_count_channels() == 0) {
406 if (foreground) {
407 grad_log(GRAD_LOG_ALERT,
408 _("Radiusd is not listening on any port."));
409 exit(1);
410 } else
411 grad_log(GRAD_LOG_ALERT,
412 _("Radiusd is not listening on any port. Trying to continue anyway..."));
413 }
414 }
415
416 static void
daemon_postconfig_hook(void * a ARG_UNUSED,void * b ARG_UNUSED)417 daemon_postconfig_hook(void *a ARG_UNUSED, void *b ARG_UNUSED)
418 {
419 system_acct_init();
420 }
421
422 void
radiusd_setup()423 radiusd_setup()
424 {
425 int i;
426
427 /* Close unneeded file descriptors */
428 for (i = grad_max_fd(); i >= 3; i--)
429 close(i);
430 /* Determine default port numbers for authentication and accounting */
431 if (auth_port == 0)
432 auth_port = get_port_number("radius", "udp", DEF_AUTH_PORT);
433 if (acct_port == 0)
434 acct_port = get_port_number("radacct", "udp", auth_port+1);
435 #ifdef USE_SNMP
436 snmp_port = get_port_number("snmp", "udp", 161);
437 #endif
438 srand(time(NULL));
439
440 #ifdef HAVE_CRYPT_SET_FORMAT
441 /* MD5 hashes are handled by libgnuradius function md5crypt(). To
442 handle DES hashes it falls back to system crypt(). The behaviour
443 of the latter on FreeBSD depends upon a 'default format'. so e.g.
444 crypt() may generate MD5 hashes even if presented with a valid
445 MD5 salt.
446
447 To make sure this does not happen, we need to set the default
448 crypt() format. */
449
450 crypt_set_format("des");
451 #endif
452
453 /* Register radiusd hooks first. This ensures they will be
454 executed after all other hooks */
455 radiusd_set_preconfig_hook(radiusd_preconfig_hook, NULL, 0);
456 radiusd_set_postconfig_hook(radiusd_postconfig_hook, NULL, 0);
457
458 rewrite_init();
459 dynload_init();
460 snmp_init(0, 0, (snmp_alloc_t)grad_emalloc, (snmp_free_t)grad_free);
461 mlc_init();
462 sql_init();
463 }
464
465 void
common_init()466 common_init()
467 {
468 grad_log(GRAD_LOG_INFO, _("Starting"));
469
470 radiusd_pid = getpid();
471 radius_input = input_create();
472 input_register_method(radius_input, "rpp", 0,
473 rpp_input_handler,
474 rpp_input_close,
475 NULL);
476 input_register_method(radius_input, "udp", 1,
477 udp_input_handler,
478 udp_input_close,
479 udp_input_cmp);
480 #ifdef HAVE_SETVBUF
481 setvbuf(stdout, NULL, _IOLBF, 0);
482 #endif
483 radiusd_signal_init(sig_handler);
484 forward_init();
485 #ifdef USE_SNMP
486 snmpserv_init(&saved_status);
487 #endif
488 acct_init();
489 if (select_free_ports) {
490 port_file = fopen(select_free_ports, "w");
491 if (!port_file) {
492 grad_log(GRAD_LOG_CRIT|GRAD_LOG_PERROR,
493 _("Cannot open output file %s"),
494 select_free_ports);
495 exit(1);
496 }
497 }
498
499 radiusd_reconfigure();
500
501 if (port_file) {
502 fclose(port_file);
503 port_file = NULL;
504 select_free_ports = NULL;
505 }
506
507 grad_log(GRAD_LOG_INFO, _("Ready"));
508 }
509
510
511 /* ************************** Core of radiusd ****************************** */
512 void
radiusd_daemon()513 radiusd_daemon()
514 {
515 char *p;
516 int i;
517 pid_t pid;
518
519 switch (pid = fork()) {
520 case -1:
521 grad_log(GRAD_LOG_CRIT|GRAD_LOG_PERROR, "fork");
522 exit(1);
523 case 0: /* Child */
524 break;
525 default: /* Parent */
526 exit(0);
527 }
528
529 #ifdef HAVE_SETSID
530 setsid();
531 #endif
532 /* SIGHUP is ignored because when the session leader terminates
533 all process in the session are sent the SIGHUP. */
534 grad_set_signal(SIGHUP, SIG_IGN);
535
536 /* fork() again so the parent, can exit. This means that we, as a
537 non-session group leader, can never regain a controlling
538 terminal. */
539 switch (pid = fork()) {
540 case 0:
541 break;
542 case -1:
543 grad_log(GRAD_LOG_CRIT|GRAD_LOG_PERROR, "fork");
544 exit(1);
545 default:
546 exit(0);
547 }
548
549 /* This is needed for messages generated by guile
550 functions.
551 FIXME: The compiled-in value of grad_log_dir is used */
552 p = grad_mkfilename(grad_log_dir, "radius.stderr");
553 i = open(p, O_CREAT|O_WRONLY, 0644);
554 if (i != -1) {
555 if (i != 2)
556 dup2(i, 2);
557 if (i != 1)
558 dup2(i, 1);
559 if (i != 1 && i != 2)
560 close(i);
561 fflush(stdout);
562 fflush(stderr);
563 }
564 grad_free(p);
565 }
566
567 int
radiusd_master()568 radiusd_master()
569 {
570 return radiusd_pid == getpid();
571 }
572
573
574 /* ****************************** Main function **************************** */
575
576 void
radiusd_main()577 radiusd_main()
578 {
579 switch (radius_mode) {
580 case MODE_CHECKCONF:
581 common_init();
582 exit(0);
583
584 case MODE_TEST:
585 common_init();
586 tsh();
587
588 #ifdef USE_DBM
589 case MODE_BUILDDBM:
590 common_init();
591 exit(builddbm(NULL));
592 #endif
593
594 case MODE_DAEMON:
595 if (myip != INADDR_ANY)
596 ref_ip = myip;
597 else
598 ref_ip = grad_first_ip();
599 if (ref_ip == INADDR_ANY)
600 grad_log(GRAD_LOG_ALERT, _("can't find out my own IP address"));
601
602 chdir("/");
603 umask(022);
604
605 if (!foreground)
606 radiusd_daemon();
607 /* Install daemon-specific hook */
608 radiusd_set_postconfig_hook(daemon_postconfig_hook,
609 NULL, 0);
610 common_init();
611 }
612
613 radiusd_pidfile_write(RADIUSD_PID_FILE);
614
615 if (radiusd_user.username) {
616 char *p;
617 log_change_owner(&radiusd_user);
618 p = grad_mkfilename(grad_log_dir, "radius.stderr");
619 chown(p, radiusd_user.uid, radiusd_user.gid);
620 grad_free(p);
621 radius_switch_to_user(&radiusd_user);
622 }
623
624 radiusd_main_loop();
625 }
626
627 void
radiusd_start()628 radiusd_start()
629 {
630 #ifdef USE_SERVER_GUILE
631 scheme_main();
632 #else
633 radiusd_main();
634 #endif
635 }
636
637 int
main(int argc,char ** argv)638 main(int argc, char **argv)
639 {
640 /* debug_flag can be set only from debugger.
641 It means developer is taking control in his hands, so
642 we won't modify any variables that could prevent him
643 from doing so. */
644 if (debug_flag == 0) {
645 foreground = 0;
646 spawn_flag = 1;
647 }
648 grad_app_setup();
649 grad_set_logger(radiusd_logger);
650
651 /* save the invocation */
652 xargc = argc;
653 xargv = argv;
654
655 /* Set up some default values */
656 set_config_defaults();
657
658 /* Process the options. */
659 argp_program_version_hook = version;
660 if (grad_argp_parse(&argp, &argc, &argv, 0, NULL, NULL))
661 return 1;
662
663 log_set_default("default.log", -1, -1);
664 if (radius_mode != MODE_DAEMON)
665 log_set_to_console(-1, console_logging_priority);
666
667 radiusd_setup();
668 radiusd_start();
669 /*NOTREACHED*/
670 }
671
672 static int
snmp_request_to_command()673 snmp_request_to_command()
674 {
675 #ifdef USE_SNMP
676 if (server_stat && server_stat->auth.status != saved_status) {
677 saved_status = server_stat->auth.status;
678 switch (server_stat->auth.status) {
679 case serv_reset:
680 return CMD_RESTART;
681
682 case serv_init:
683 return CMD_RELOAD;
684
685 case serv_running:
686 return CMD_CONTINUE;
687
688 case serv_suspended:
689 return CMD_SUSPEND;
690
691 case serv_shutdown:
692 return CMD_SHUTDOWN;
693
694 case serv_other:
695 /* nothing */;
696 }
697 }
698 #endif
699 return CMD_NONE;
700 }
701
702 void
radiusd_suspend()703 radiusd_suspend()
704 {
705 if (suspend_flag == 0) {
706 terminate_subprocesses();
707 grad_log(GRAD_LOG_NOTICE, _("RADIUSD SUSPENDED"));
708 suspend_flag = 1;
709 }
710 }
711
712 void
radiusd_continue()713 radiusd_continue()
714 {
715 if (suspend_flag) {
716 terminate_subprocesses();
717 suspend_flag = 0;
718 #ifdef USE_SNMP
719 server_stat->auth.status = serv_running;
720 server_stat->acct.status = serv_running;
721 #endif
722 }
723 }
724
725 static void
check_reload()726 check_reload()
727 {
728 if (daemon_command == CMD_NONE)
729 daemon_command = snmp_request_to_command();
730
731 switch (daemon_command) {
732 case CMD_CLEANUP:
733 radiusd_cleanup();
734 break;
735
736 case CMD_RELOAD:
737 grad_log(GRAD_LOG_INFO, _("Reloading configuration now"));
738 radiusd_reconfigure();
739 break;
740
741 case CMD_RESTART:
742 radiusd_restart();
743 break;
744
745 case CMD_MEMINFO:
746 break;
747
748 case CMD_DUMPDB:
749 grad_log(GRAD_LOG_INFO, _("Dumping users db to `%s'"),
750 RADIUS_DUMPDB_NAME);
751 dump_users_db();
752 break;
753
754 case CMD_SUSPEND:
755 radiusd_suspend();
756 break;
757
758 case CMD_CONTINUE:
759 radiusd_continue();
760 break;
761
762 case CMD_SHUTDOWN:
763 radiusd_exit();
764 break;
765 }
766 daemon_command = CMD_NONE;
767 }
768
769 void
radiusd_register_input_fd(char * name,int fd,void * data)770 radiusd_register_input_fd(char *name, int fd, void *data)
771 {
772 input_register_channel(radius_input, name, fd, data);
773 }
774
775 void
radiusd_close_channel(int fd)776 radiusd_close_channel(int fd)
777 {
778 input_close_channel_fd(radius_input, fd);
779 }
780
781 void
radiusd_collect_children()782 radiusd_collect_children()
783 {
784 pid_t pid;
785 int status;
786
787 for (;;) {
788 pid = waitpid((pid_t)-1, &status, WNOHANG);
789 if (pid <= 0)
790 break;
791 rpp_status_changed(pid, status);
792 }
793 }
794
795 void
radiusd_cleanup()796 radiusd_cleanup()
797 {
798 rpp_collect_exited ();
799 }
800
801 void
radiusd_restart()802 radiusd_restart()
803 {
804 pid_t pid;
805
806 grad_log(GRAD_LOG_NOTICE, _("restart initiated"));
807 if (xargv[0][0] != '/') {
808 grad_log(GRAD_LOG_ERR,
809 _("can't restart: not started as absolute pathname"));
810 return;
811 }
812
813 radiusd_run_preconfig_hooks(NULL);
814
815 if (foreground)
816 pid = 0; /* make-believe we're child */
817 else
818 pid = fork();
819 if (pid < 0) {
820 grad_log(GRAD_LOG_CRIT|GRAD_LOG_PERROR,
821 _("radiusd_restart: cannot fork"));
822 return;
823 }
824
825 radiusd_signal_init(SIG_DFL);
826 if (pid > 0) {
827 /* Parent */
828 sleep(10);
829 exit(0);
830 }
831
832 /* Let the things settle */
833 sleep(10);
834
835 /* Child */
836 grad_log(GRAD_LOG_NOTICE, _("restarting radius"));
837 execvp(xargv[0], xargv);
838 grad_log(GRAD_LOG_CRIT|GRAD_LOG_PERROR,
839 _("RADIUS NOT RESTARTED: exec failed"));
840 exit(1);
841 /*NOTREACHED*/
842 }
843
844
845
846 static int
radiusd_rpp_wait(void * arg)847 radiusd_rpp_wait(void *arg)
848 {
849 time_t *tp = arg;
850 struct timeval tv;
851
852 if (time(NULL) > *tp)
853 return 1;
854
855 tv.tv_sec = 2;
856 tv.tv_usec = 0;
857 input_select_channel(radius_input, "rpp", &tv);
858 return 0;
859 }
860
861 void
radiusd_flush_queue()862 radiusd_flush_queue()
863 {
864 time_t t;
865 max_ttl(&t);
866 rpp_flush(radiusd_rpp_wait, &t);
867 }
868
869 void
radiusd_exit()870 radiusd_exit()
871 {
872 stat_done();
873 radiusd_pidfile_remove(RADIUSD_PID_FILE);
874
875 radiusd_flush_queue();
876 grad_log(GRAD_LOG_CRIT, _("Normal shutdown."));
877
878 rpp_kill(-1, SIGTERM);
879 radiusd_exit0();
880 }
881
882 void
radiusd_exit0()883 radiusd_exit0()
884 {
885 radiusd_sql_shutdown();
886 exit(0);
887 }
888
889 void
radiusd_main_loop()890 radiusd_main_loop()
891 {
892 grad_log(GRAD_LOG_INFO, _("Ready to process requests."));
893
894 for (;;) {
895 log_open(GRAD_LOG_MAIN);
896 check_reload();
897 input_select(radius_input, NULL);
898 }
899 }
900
901
902 /* ************************ Coniguration Functions ************************* */
903
904 struct hook_rec {
905 void (*function)(void *func_data, void *call_data);
906 void *data;
907 int once; /* Run once and remove */
908 };
909
910 static grad_list_t /* of struct hook_rec */ *preconfig;
911 static grad_list_t /* of struct hook_rec */ *postconfig;
912
913 void
radiusd_set_preconfig_hook(void (* f)(void *,void *),void * p,int once)914 radiusd_set_preconfig_hook(void (*f)(void *, void *), void *p, int once)
915 {
916 struct hook_rec *hp = grad_emalloc(sizeof(*hp));
917 hp->function = f;
918 hp->data = p;
919 hp->once = once;
920 if (!preconfig)
921 preconfig = grad_list_create();
922 grad_list_prepend(preconfig, hp);
923 }
924
925 void
radiusd_set_postconfig_hook(void (* f)(void *,void *),void * p,int once)926 radiusd_set_postconfig_hook(void (*f)(void *, void *), void *p, int once)
927 {
928 struct hook_rec *hp = grad_emalloc(sizeof(*hp));
929 hp->function = f;
930 hp->data = p;
931 hp->once = once;
932 if (!postconfig)
933 postconfig = grad_list_create();
934 grad_list_prepend(postconfig, hp);
935 }
936
937 struct hook_runtime_closure {
938 grad_list_t *list;
939 void *call_data;
940 };
941
942 static int
_hook_call(void * item,void * data)943 _hook_call(void *item, void *data)
944 {
945 struct hook_rec *hp = item;
946 struct hook_runtime_closure *clos = data;
947 hp->function(hp->data, clos->call_data);
948 if (hp->once) {
949 grad_list_remove(clos->list, hp, NULL);
950 grad_free(hp);
951 }
952 return 0;
953 }
954
955 void
radiusd_run_preconfig_hooks(void * data)956 radiusd_run_preconfig_hooks(void *data)
957 {
958 struct hook_runtime_closure clos;
959 clos.list = preconfig;
960 clos.call_data = data;
961 grad_list_iterate(clos.list, _hook_call, &clos);
962 }
963
964 void
radiusd_run_postconfig_hooks(void * data)965 radiusd_run_postconfig_hooks(void *data)
966 {
967 struct hook_runtime_closure clos;
968 clos.list = postconfig;
969 clos.call_data = data;
970 grad_list_iterate(clos.list, _hook_call, &clos);
971 }
972
973 void
radiusd_reconfigure()974 radiusd_reconfigure()
975 {
976 int rc = 0;
977 char *filename;
978
979 radiusd_run_preconfig_hooks(NULL);
980
981 grad_log(GRAD_LOG_INFO, _("Loading configuration files."));
982 /* Read main configuration file */
983 filename = grad_mkfilename(grad_config_dir, RADIUS_CONFIG);
984 cfg_read(filename, config_syntax, NULL);
985 grad_free(filename);
986
987 /* Read other files */
988 rc = reload_config_file(reload_all);
989
990 if (rc) {
991 grad_log(GRAD_LOG_CRIT, _("Errors reading config file - EXITING"));
992 exit(1);
993 }
994
995 grad_path_init();
996 radiusd_run_postconfig_hooks(NULL);
997 }
998
999
1000 /* ***************************** Signal Handling *************************** */
1001
1002 static RETSIGTYPE
sig_handler(int sig)1003 sig_handler(int sig)
1004 {
1005 switch (sig) {
1006 case SIGHUP:
1007 daemon_command = CMD_RELOAD;
1008 break;
1009
1010 case SIGUSR1:
1011 daemon_command = CMD_MEMINFO;
1012 break;
1013
1014 case SIGUSR2:
1015 daemon_command = CMD_DUMPDB;
1016 break;
1017
1018 case SIGCHLD:
1019 radiusd_collect_children ();
1020 daemon_command = CMD_CLEANUP;
1021 break;
1022
1023 case SIGTERM:
1024 case SIGQUIT:
1025 daemon_command = CMD_SHUTDOWN;
1026 break;
1027
1028 case SIGPIPE:
1029 /*FIXME: Any special action? */
1030 daemon_command = CMD_CLEANUP;
1031 break;
1032
1033 default:
1034 abort();
1035 }
1036 grad_reset_signal(sig, sig_handler);
1037 }
1038
1039 void
radiusd_signal_init(RETSIGTYPE (* hp)(int sig))1040 radiusd_signal_init(RETSIGTYPE (*hp)(int sig))
1041 {
1042 static int signum[] = {
1043 SIGHUP, SIGUSR1, SIGUSR2, SIGCHLD,
1044 SIGTERM, SIGQUIT, SIGPIPE
1045 };
1046 int i;
1047
1048 for (i = 0; i < sizeof(signum)/sizeof(signum[0]); i++)
1049 grad_set_signal(signum[i], hp);
1050 }
1051
1052
1053 /* ************************************************************************* */
1054
1055 void
radiusd_pidfile_write(char * name)1056 radiusd_pidfile_write(char *name)
1057 {
1058 pid_t pid = getpid();
1059 char *p = grad_mkfilename(grad_pid_dir, name);
1060 FILE *fp = fopen(p, "w");
1061 if (fp) {
1062 fprintf(fp, "%lu\n", (u_long) pid);
1063 fclose(fp);
1064 }
1065 grad_free(p);
1066 }
1067
1068 pid_t
radiusd_pidfile_read(char * name)1069 radiusd_pidfile_read(char *name)
1070 {
1071 unsigned long val;
1072 char *p = grad_mkfilename(grad_pid_dir, name);
1073 FILE *fp = fopen(p, "r");
1074 if (!fp)
1075 return -1;
1076 if (fscanf(fp, "%lu", &val) != 1)
1077 val = -1;
1078 fclose(fp);
1079 grad_free(p);
1080 return (pid_t) val;
1081 }
1082
1083 void
radiusd_pidfile_remove(char * name)1084 radiusd_pidfile_remove(char *name)
1085 {
1086 char *p = grad_mkfilename(grad_pid_dir, name);
1087 unlink(p);
1088 grad_free(p);
1089 }
1090
1091
1092
1093 /* ************************************************************************* */
1094 static u_char recv_buffer[RAD_BUFFER_SIZE];
1095
1096 struct udp_data {
1097 int type;
1098 struct sockaddr_in addr;
1099 };
1100
1101 int
udp_input_handler(int fd,void * data)1102 udp_input_handler(int fd, void *data)
1103 {
1104 struct sockaddr sa;
1105 socklen_t salen = sizeof (sa);
1106 int size;
1107 struct udp_data *sd = data;
1108
1109 size = recvfrom(fd, (char *) recv_buffer, sizeof(recv_buffer),
1110 0, &sa, &salen);
1111 if (size < 0)
1112 request_fail(sd->type, (struct sockaddr_in*)&sa);
1113 else {
1114 REQUEST *req = request_create(sd->type,
1115 fd,
1116 &sd->addr,
1117 (struct sockaddr_in*)&sa,
1118 recv_buffer, size);
1119
1120 if (request_handle(req,
1121 spawn_flag ?
1122 rpp_forward_request : request_respond))
1123 request_free(req);
1124 }
1125 return 0;
1126 }
1127
1128 int
udp_input_close(int fd,void * data)1129 udp_input_close(int fd, void *data)
1130 {
1131 close(fd);
1132 grad_free(data);
1133 return 0;
1134 }
1135
1136 int
udp_input_cmp(const void * a,const void * b)1137 udp_input_cmp(const void *a, const void *b)
1138 {
1139 const struct udp_data *sda = a;
1140 const struct udp_data *sdb = b;
1141
1142 if (sda->addr.sin_port != sdb->addr.sin_port)
1143 return 1;
1144 if (sda->addr.sin_addr.s_addr == INADDR_ANY
1145 || sdb->addr.sin_addr.s_addr == INADDR_ANY)
1146 return 0;
1147 return sda->addr.sin_addr.s_addr != sdb->addr.sin_addr.s_addr;
1148 }
1149
1150 int
udp_open(int type,grad_uint32_t ipaddr,int port,int nonblock)1151 udp_open(int type, grad_uint32_t ipaddr, int port, int nonblock)
1152 {
1153 int fd;
1154 struct sockaddr_in s;
1155 struct udp_data *p;
1156
1157 if (select_free_ports)
1158 port = 0;
1159 s.sin_family = AF_INET;
1160 s.sin_addr.s_addr = htonl(ipaddr);
1161 s.sin_port = htons(port);
1162
1163 if (port && (p = input_find_channel(radius_input, "udp", &s))) {
1164 char buffer[GRAD_IPV4_STRING_LENGTH];
1165 grad_log(GRAD_LOG_ERR,
1166 _("socket %s:%d is already assigned for %s"),
1167 grad_ip_iptostr(ipaddr, buffer),
1168 port,
1169 request_class[p->type].name);
1170 return 1;
1171 }
1172
1173 fd = socket(PF_INET, SOCK_DGRAM, 0);
1174 if (nonblock)
1175 grad_set_nonblocking(fd);
1176 if (fd < 0) {
1177 grad_log(GRAD_LOG_CRIT|GRAD_LOG_PERROR, "%s socket",
1178 request_class[type].name);
1179 return 1;
1180 }
1181 if (bind(fd, (struct sockaddr*) &s, sizeof(s)) < 0) {
1182 grad_log(GRAD_LOG_CRIT|GRAD_LOG_PERROR,
1183 "%s bind", request_class[type].name);
1184 close(fd);
1185 return 1;
1186 }
1187
1188 if (port == 0) {
1189 socklen_t len = sizeof(s);
1190 if (getsockname(fd, &s, &len)) {
1191 grad_log(GRAD_LOG_CRIT|GRAD_LOG_PERROR,
1192 "%s getsockname", request_class[type].name);
1193 close(fd);
1194 return 1;
1195 }
1196 port = ntohs(s.sin_port);
1197 grad_log(GRAD_LOG_INFO, "%s=%u",
1198 request_class[type].name, port);
1199 fprintf(port_file, "%s=%u\n",
1200 request_class[type].name, port);
1201 switch (type) {
1202 case R_AUTH:
1203 auth_port = port;
1204 break;
1205
1206 case R_ACCT:
1207 acct_port = port;
1208 break;
1209
1210 #ifdef USE_SNMP
1211 case R_SNMP:
1212 snmp_port = port;
1213 break;
1214 #endif
1215 }
1216 }
1217
1218 p = grad_emalloc(sizeof(*p));
1219 p->type = type;
1220 p->addr = s;
1221 input_register_channel(radius_input, "udp", fd, p);
1222 return 0;
1223 }
1224
1225 static int
channel_counter(void * item,void * data)1226 channel_counter(void *item, void *data)
1227 {
1228 struct udp_data *p = item;
1229 if (p->type == R_AUTH || p->type == R_ACCT)
1230 ++*(size_t*)data;
1231 return 0;
1232 }
1233
1234 static size_t
radius_count_channels()1235 radius_count_channels()
1236 {
1237 size_t count = 0;
1238
1239 input_iterate_channels(radius_input, "udp", channel_counter, &count);
1240 return count;
1241 }
1242
1243
1244 /* ************************************************************************* */
1245
1246 static int _opened_auth_sockets;
1247 static int _opened_acct_sockets;
1248
1249 static int
rad_cfg_listen_auth(int argc,cfg_value_t * argv,void * block_data,void * handler_data)1250 rad_cfg_listen_auth(int argc, cfg_value_t *argv,
1251 void *block_data, void *handler_data)
1252 {
1253 int i, errcnt = 0;
1254
1255 if (argc == 2 && argv[1].type == CFG_BOOLEAN) {
1256 if (argv[1].v.bool == 0)
1257 auth_port = 0;
1258 return 0;
1259 }
1260
1261 for (i = 1; i < argc; i++)
1262 if (argv[i].type == CFG_NETWORK) {
1263 if (argv[i].v.network.netmask != 0xffffffffL)
1264 cfg_type_error(CFG_HOST);
1265 } else if (argv[i].type != CFG_HOST) {
1266 cfg_type_error(CFG_HOST);
1267 errcnt++;
1268 }
1269
1270 if (errcnt == 0 && radius_mode == MODE_DAEMON) {
1271 for (i = 1; i < argc; i++) {
1272 grad_uint32_t ip;
1273 int port;
1274
1275 if (argv[i].type == CFG_NETWORK) {
1276 ip = argv[i].v.network.ipaddr;
1277 port = auth_port;
1278 } else {
1279 ip = argv[i].v.host.ipaddr;
1280 port = argv[i].v.host.port;
1281 }
1282
1283 if (udp_open(R_AUTH, ip, port, 0))
1284 errcnt++;
1285 }
1286 }
1287 if (errcnt == 0)
1288 _opened_auth_sockets++;
1289 return 0;
1290 }
1291
1292 int
auth_stmt_begin(int finish,void * block_data,void * handler_data)1293 auth_stmt_begin(int finish, void *block_data, void *handler_data)
1294 {
1295 if (!finish)
1296 _opened_auth_sockets = 0;
1297 else if (radius_mode == MODE_DAEMON
1298 && !_opened_auth_sockets
1299 && auth_port)
1300 udp_open(R_AUTH, INADDR_ANY, auth_port, 0);
1301 return 0;
1302 }
1303
1304 static int
rad_cfg_listen_acct(int argc,cfg_value_t * argv,void * block_data,void * handler_data)1305 rad_cfg_listen_acct(int argc, cfg_value_t *argv,
1306 void *block_data, void *handler_data)
1307 {
1308 int i, errcnt = 0;
1309
1310 if (argc == 2 && argv[1].type == CFG_BOOLEAN) {
1311 if (argv[1].v.bool == 0)
1312 acct_port = 0;
1313 return 0;
1314 }
1315
1316 for (i = 1; i < argc; i++)
1317 if (argv[i].type == CFG_NETWORK) {
1318 if (argv[i].v.network.netmask != 0xffffffffL)
1319 cfg_type_error(CFG_HOST);
1320 } else if (argv[i].type != CFG_HOST) {
1321 cfg_type_error(CFG_HOST);
1322 errcnt++;
1323 }
1324
1325 if (errcnt == 0 && radius_mode == MODE_DAEMON) {
1326 for (i = 1; i < argc; i++) {
1327 grad_uint32_t ip;
1328 int port;
1329
1330 if (argv[i].type == CFG_NETWORK) {
1331 ip = argv[i].v.network.ipaddr;
1332 port = acct_port;
1333 } else {
1334 ip = argv[i].v.host.ipaddr;
1335 port = argv[i].v.host.port;
1336 }
1337
1338 if (udp_open(R_ACCT, ip, port, 0))
1339 errcnt++;
1340 }
1341 }
1342 _opened_acct_sockets++;
1343 return 0;
1344 }
1345
1346 int
acct_stmt_begin(int finish,void * block_data,void * handler_data)1347 acct_stmt_begin(int finish, void *block_data, void *handler_data)
1348 {
1349 if (!finish)
1350 _opened_acct_sockets = 0;
1351 else if (radius_mode == MODE_DAEMON
1352 && !_opened_acct_sockets
1353 && acct_port)
1354 udp_open(R_ACCT, INADDR_ANY, acct_port, 0);
1355 return 0;
1356 }
1357
1358 static int
rad_cfg_user(int argc,cfg_value_t * argv,void * block_data,void * handler_data)1359 rad_cfg_user(int argc, cfg_value_t *argv,
1360 void *block_data, void *handler_data)
1361 {
1362 RADIUS_USER *usr = handler_data;
1363
1364 if (argc != 2 || argv[1].type != CFG_STRING)
1365 return 1;
1366 return radius_get_user_ids((RADIUS_USER *) handler_data,
1367 argv[1].v.string);
1368 }
1369
1370 int
option_stmt_end(void * block_data,void * handler_data)1371 option_stmt_end(void *block_data, void *handler_data)
1372 {
1373 if (exec_user.username && radiusd_user.uid != 0) {
1374 grad_log(GRAD_LOG_WARN, _("Ignoring exec-program-user"));
1375 grad_free(exec_user.username);
1376 exec_user.username = NULL;
1377 } else if (exec_user.username == NULL
1378 && radiusd_user.uid == 0 && getuid() == 0)
1379 radius_get_user_ids(&exec_user, "daemon");
1380 return 0;
1381 }
1382
1383 struct cfg_stmt option_stmt[] = {
1384 { "source-ip", CS_STMT, NULL, cfg_get_ipaddr, &myip,
1385 NULL, NULL },
1386 { "max-requests", CS_STMT, NULL, cfg_get_size_t, &max_requests,
1387 NULL, NULL },
1388 { "max-threads", CS_STMT, NULL, cfg_get_size_t, &max_children,
1389 NULL, NULL },
1390 { "max-processes", CS_STMT, NULL, cfg_get_size_t, &max_children,
1391 NULL, NULL },
1392 { "process-idle-timeout", CS_STMT, NULL, cfg_get_unsigned, &process_timeout,
1393 NULL, NULL },
1394 { "master-read-timeout", CS_STMT, NULL,
1395 cfg_get_unsigned, &radiusd_read_timeout, NULL, NULL },
1396 { "master-write-timeout", CS_STMT, NULL,
1397 cfg_get_unsigned, &radiusd_write_timeout, NULL, NULL },
1398 { "exec-program-user", CS_STMT, NULL, rad_cfg_user,
1399 &exec_user, NULL, NULL },
1400 { "radiusd-user", CS_STMT, NULL, rad_cfg_user,
1401 &radiusd_user, NULL, NULL },
1402 { "log-dir", CS_STMT, NULL, cfg_get_string, &grad_log_dir,
1403 NULL, NULL },
1404 { "acct-dir", CS_STMT, NULL, cfg_get_string, &grad_acct_dir,
1405 NULL, NULL },
1406 { "resolve", CS_STMT, NULL, cfg_get_boolean, &grad_resolve_hostnames,
1407 NULL, NULL },
1408 { "username-chars", CS_STMT, NULL, cfg_get_string,
1409 &username_valid_chars, NULL, NULL },
1410 /* Obsolete statements */
1411 { "usr2delay", CS_STMT, NULL, cfg_obsolete, NULL, NULL, NULL },
1412 { NULL, }
1413 };
1414
1415 struct cfg_stmt message_stmt[] = {
1416 { "account-closed", CS_STMT, NULL,
1417 cfg_get_string, &message_text[MSG_ACCOUNT_CLOSED],
1418 NULL, NULL },
1419 { "password-expired", CS_STMT, NULL,
1420 cfg_get_string, &message_text[MSG_PASSWORD_EXPIRED],
1421 NULL, NULL },
1422 { "access-denied", CS_STMT, NULL,
1423 cfg_get_string, &message_text[MSG_ACCESS_DENIED],
1424 NULL, NULL },
1425 { "realm-quota", CS_STMT, NULL,
1426 cfg_get_string, &message_text[MSG_REALM_QUOTA],
1427 NULL, NULL },
1428 { "multiple-login", CS_STMT, NULL,
1429 cfg_get_string, &message_text[MSG_MULTIPLE_LOGIN],
1430 NULL, NULL },
1431 { "second-login", CS_STMT, NULL,
1432 cfg_get_string, &message_text[MSG_SECOND_LOGIN],
1433 NULL, NULL },
1434 { "timespan-violation", CS_STMT, NULL,
1435 cfg_get_string, &message_text[MSG_TIMESPAN_VIOLATION],
1436 NULL, NULL },
1437 { "password-expire-warning", CS_STMT, NULL,
1438 cfg_get_string, &message_text[MSG_PASSWORD_EXPIRE_WARNING],
1439 NULL, NULL },
1440 { NULL, }
1441 };
1442
1443 struct cfg_stmt auth_stmt[] = {
1444 { "port", CS_STMT, NULL, cfg_get_port, &auth_port, NULL, NULL },
1445 { "listen", CS_STMT, NULL, rad_cfg_listen_auth, NULL, NULL, NULL },
1446 { "forward", CS_STMT, NULL, rad_cfg_forward_auth, NULL, NULL, NULL },
1447 { "max-requests", CS_STMT, NULL,
1448 cfg_get_integer, &request_class[R_AUTH].max_requests, NULL, NULL },
1449 { "time-to-live", CS_STMT, NULL,
1450 cfg_get_integer, &request_class[R_AUTH].ttl, NULL, NULL },
1451 { "request-cleanup-delay", CS_STMT, NULL,
1452 cfg_get_integer, &request_class[R_AUTH].cleanup_delay, NULL, NULL },
1453 { "detail", CS_STMT, NULL, cfg_get_boolean, &auth_detail,
1454 NULL, NULL },
1455 { "detail-file-name", CS_STMT, NULL, cfg_get_string,
1456 &auth_detail_template, NULL, NULL },
1457 { "strip-names", CS_STMT, NULL, cfg_get_boolean, &strip_names,
1458 NULL, NULL },
1459 { "checkrad-assume-logged", CS_STMT, NULL,
1460 cfg_get_boolean, &checkrad_assume_logged,
1461 NULL, NULL },
1462 { "reject-malformed-names", CS_STMT, NULL,
1463 cfg_get_boolean, &auth_reject_malformed_names,
1464 NULL, NULL },
1465 { "password-expire-warning", CS_STMT, NULL,
1466 cfg_get_uint32_t, &warning_seconds,
1467 NULL, NULL },
1468 { "compare-attribute-flag", CS_STMT, NULL,
1469 cfg_get_integer, &auth_comp_flag,
1470 NULL, NULL },
1471 { "trace-rules", CS_STMT, NULL, cfg_get_boolean, &auth_trace_rules,
1472 NULL, NULL },
1473 /* Obsolete statements */
1474 { "spawn", CS_STMT, NULL, cfg_obsolete, NULL, NULL, NULL },
1475 { NULL, }
1476 };
1477
1478 struct cfg_stmt acct_stmt[] = {
1479 { "port", CS_STMT, NULL, cfg_get_port, &acct_port, NULL, NULL },
1480 { "listen", CS_STMT, NULL, rad_cfg_listen_acct, NULL, NULL, NULL },
1481 { "forward", CS_STMT, NULL, rad_cfg_forward_acct, NULL, NULL, NULL },
1482 { "max-requests", CS_STMT, NULL,
1483 cfg_get_integer, &request_class[R_ACCT].max_requests,
1484 NULL, NULL },
1485 { "time-to-live", CS_STMT, NULL,
1486 cfg_get_integer, &request_class[R_ACCT].ttl,
1487 NULL, NULL },
1488 { "request-cleanup-delay", CS_STMT, NULL,
1489 cfg_get_integer, &request_class[R_ACCT].cleanup_delay,
1490 NULL, NULL },
1491 { "detail", CS_STMT, NULL, cfg_get_boolean, &acct_detail,
1492 NULL, NULL },
1493 { "detail-file-name", CS_STMT, NULL, cfg_get_string,
1494 &acct_detail_template, NULL, NULL },
1495 { "system", CS_STMT, NULL, cfg_get_boolean, &acct_system,
1496 NULL, NULL },
1497 { "compare-attribute-flag", CS_STMT, NULL,
1498 cfg_get_integer, &acct_comp_flag,
1499 NULL, NULL },
1500 { "trace-rules", CS_STMT, NULL, cfg_get_boolean, &acct_trace_rules,
1501 NULL, NULL },
1502 /* Obsolete statements */
1503 { "spawn", CS_STMT, NULL, cfg_obsolete, NULL, NULL, NULL },
1504 { NULL, }
1505 };
1506
1507 struct cfg_stmt proxy_stmt[] = {
1508 { "max-requests", CS_STMT, NULL, cfg_obsolete, NULL, NULL, NULL },
1509 { "request-cleanup-delay", CS_STMT, NULL,
1510 cfg_obsolete, NULL, NULL, NULL },
1511 { NULL, }
1512 };
1513
1514 struct cfg_stmt config_syntax[] = {
1515 { "option", CS_BLOCK, NULL, NULL, NULL, option_stmt, option_stmt_end },
1516 { "message", CS_BLOCK, NULL, NULL, NULL, message_stmt, NULL },
1517 { "logging", CS_BLOCK, logging_stmt_begin, logging_stmt_handler, NULL,
1518 logging_stmt, logging_stmt_end },
1519 { "auth", CS_BLOCK, auth_stmt_begin, NULL, NULL, auth_stmt, NULL },
1520 { "acct", CS_BLOCK, acct_stmt_begin, NULL, NULL, acct_stmt, NULL },
1521 { "mlc", CS_BLOCK, NULL, NULL, NULL, mlc_stmt, NULL },
1522 { "proxy", CS_BLOCK, NULL, NULL, NULL, proxy_stmt, NULL },
1523 { "rewrite", CS_BLOCK, rewrite_stmt_term, NULL, NULL, rewrite_stmt, NULL },
1524 { "filters", CS_BLOCK, filters_stmt_term, NULL, NULL, filters_stmt,
1525 NULL },
1526 { "loadable-modules", CS_BLOCK, dynload_stmt_term, NULL, NULL,
1527 dynload_stmt, NULL },
1528 #ifdef USE_DBM
1529 { "usedbm", CS_STMT, NULL, cfg_get_boolean, &use_dbm, NULL, NULL },
1530 #endif
1531 #ifdef USE_SNMP
1532 { "snmp", CS_BLOCK, snmp_stmt_begin, NULL, NULL, snmp_stmt, NULL },
1533 #endif
1534 #ifdef USE_SERVER_GUILE
1535 { "guile", CS_BLOCK, NULL, guile_cfg_handler, NULL, guile_stmt, NULL },
1536 #endif
1537 { NULL, },
1538 };
1539