Minor fixes to debug functions
[freeradius.git] / src / main / radiusd.c
1 /*
2  * radiusd.c    Main loop of the radius server.
3  *
4  * Version:     $Id$
5  *
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.
10  *
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.
15  *
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
19  *
20  * Copyright 2000-2012  The FreeRADIUS server project
21  * Copyright 1999,2000  Miquel van Smoorenburg <miquels@cistron.nl>
22  * Copyright 2000  Alan DeKok <aland@ox.org>
23  * Copyright 2000  Alan Curry <pacman-radius@cqc.com>
24  * Copyright 2000  Jeff Carneal <jeff@apex.net>
25  * Copyright 2000  Chad Miller <cmiller@surfsouth.com>
26  */
27
28 RCSID("$Id$")
29
30 #include <freeradius-devel/radiusd.h>
31 #include <freeradius-devel/modules.h>
32 #include <freeradius-devel/rad_assert.h>
33
34 #include <sys/file.h>
35
36 #include <fcntl.h>
37 #include <ctype.h>
38
39 #ifdef HAVE_GETOPT_H
40 #       include <getopt.h>
41 #endif
42
43 #ifdef HAVE_SYS_WAIT_H
44 #       include <sys/wait.h>
45 #endif
46 #ifndef WEXITSTATUS
47 #       define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
48 #endif
49 #ifndef WIFEXITED
50 #       define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
51 #endif
52
53 /*
54  *  Global variables.
55  */
56 char const *progname = NULL;
57 char const *radius_dir = NULL;
58 char const *radacct_dir = NULL;
59 char const *radlog_dir = NULL;
60 char const *radlib_dir = NULL;
61 bool log_stripped_names;
62 log_debug_t debug_flag = 0;
63 bool check_config = false;
64 bool memory_report = false;
65
66 char const *radiusd_version = "FreeRADIUS Version " RADIUSD_VERSION_STRING
67 #ifdef RADIUSD_VERSION_COMMIT
68 " (git #" STRINGIFY(RADIUSD_VERSION_COMMIT) ")"
69 #endif
70 ", for host " HOSTINFO ", built on " __DATE__ " at " __TIME__;
71
72 pid_t radius_pid;
73
74 /*
75  *  Configuration items.
76  */
77
78 /*
79  *      Static functions.
80  */
81 static void usage(int);
82
83 static void sig_fatal (int);
84 #ifdef SIGHUP
85 static void sig_hup (int);
86 #endif
87
88 #ifdef WITH_VERIFY_PTR
89 static void die_horribly(char const *reason)
90 {
91         ERROR("talloc abort: %s\n", reason);
92         abort();
93 }
94 #endif
95
96 /*
97  *      The main guy.
98  */
99 int main(int argc, char *argv[])
100 {
101         int rcode = EXIT_SUCCESS;
102         int status;
103         int argval;
104         bool spawn_flag = true;
105         bool dont_fork = false;
106         bool write_pid = false;
107         int flag = 0;
108         int from_child[2] = {-1, -1};
109
110
111 #ifdef OSFC2
112         set_auth_parameters(argc,argv);
113 #endif
114
115         if ((progname = strrchr(argv[0], FR_DIR_SEP)) == NULL)
116                 progname = argv[0];
117         else
118                 progname++;
119
120 #ifdef WIN32
121         {
122                 WSADATA wsaData;
123                 if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
124                         fprintf(stderr, "%s: Unable to initialize socket library.\n", progname);
125                         exit(EXIT_FAILURE);
126                 }
127         }
128 #endif
129
130         debug_flag = 0;
131         spawn_flag = true;
132         radius_dir = talloc_strdup(NULL, RADIUS_DIR);
133
134         /*
135          *      Ensure that the configuration is initialized.
136          */
137         memset(&mainconfig, 0, sizeof(mainconfig));
138         mainconfig.myip.af = AF_UNSPEC;
139         mainconfig.port = -1;
140         mainconfig.name = "radiusd";
141
142         /*
143          *      Don't put output anywhere until we get told a little
144          *      more.
145          */
146         default_log.dest = L_DST_NULL;
147         default_log.fd = -1;
148         mainconfig.log_file = NULL;
149
150         /*  Process the options.  */
151         while ((argval = getopt(argc, argv, "Cd:D:fhi:l:mMn:p:PstvxX")) != EOF) {
152
153                 switch(argval) {
154                         case 'C':
155                                 check_config = true;
156                                 spawn_flag = false;
157                                 dont_fork = true;
158                                 break;
159
160                         case 'd':
161                                 if (radius_dir) {
162                                         rad_const_free(radius_dir);
163                                 }
164                                 radius_dir = talloc_strdup(NULL, optarg);
165                                 break;
166
167                         case 'D':
168                                 mainconfig.dictionary_dir = talloc_strdup(NULL, optarg);
169                                 break;
170
171                         case 'f':
172                                 dont_fork = true;
173                                 break;
174
175                         case 'h':
176                                 usage(0);
177                                 break;
178
179                         case 'l':
180                                 if (strcmp(optarg, "stdout") == 0) {
181                                         goto do_stdout;
182                                 }
183                                 mainconfig.log_file = strdup(optarg);
184                                 default_log.dest = L_DST_FILES;
185                                 default_log.fd = open(mainconfig.log_file,
186                                                             O_WRONLY | O_APPEND | O_CREAT, 0640);
187                                 if (default_log.fd < 0) {
188                                         fprintf(stderr, "radiusd: Failed to open log file %s: %s\n", mainconfig.log_file, fr_syserror(errno));
189                                         exit(EXIT_FAILURE);
190                                 }
191                                 fr_log_fp = fdopen(default_log.fd, "a");
192                                 break;
193
194                         case 'i':
195                                 if (ip_hton(optarg, AF_UNSPEC, &mainconfig.myip) < 0) {
196                                         fprintf(stderr, "radiusd: Invalid IP Address or hostname \"%s\"\n", optarg);
197                                         exit(EXIT_FAILURE);
198                                 }
199                                 flag |= 1;
200                                 break;
201
202                         case 'n':
203                                 mainconfig.name = optarg;
204                                 break;
205
206                         case 'm':
207                                 mainconfig.debug_memory = 1;
208                                 break;
209
210                         case 'M':
211                                 memory_report = 1;
212                                 mainconfig.debug_memory = 1;
213                                 break;
214
215                         case 'p':
216                                 mainconfig.port = atoi(optarg);
217                                 if ((mainconfig.port <= 0) ||
218                                     (mainconfig.port >= 65536)) {
219                                         fprintf(stderr, "radiusd: Invalid port number %s\n", optarg);
220                                         exit(EXIT_FAILURE);
221                                 }
222                                 flag |= 2;
223                                 break;
224
225                         case 'P':
226                                 /* Force the PID to be written, even in -f mode */
227                                 write_pid = true;
228                                 break;
229
230                         case 's':       /* Single process mode */
231                                 spawn_flag = false;
232                                 dont_fork = true;
233                                 break;
234
235                         case 't':       /* no child threads */
236                                 spawn_flag = false;
237                                 break;
238
239                         case 'v':
240                                 /* Don't print timestamps */
241                                 debug_flag += 2;
242                                 fr_log_fp = stdout;
243                                 default_log.dest = L_DST_STDOUT;
244                                 default_log.fd = STDOUT_FILENO;
245
246                                 version();
247                                 exit(EXIT_SUCCESS);
248                         case 'X':
249                                 spawn_flag = false;
250                                 dont_fork = true;
251                                 debug_flag += 2;
252                                 mainconfig.log_auth = true;
253                                 mainconfig.log_auth_badpass = true;
254                                 mainconfig.log_auth_goodpass = true;
255                 do_stdout:
256                                 fr_log_fp = stdout;
257                                 default_log.dest = L_DST_STDOUT;
258                                 default_log.fd = STDOUT_FILENO;
259                                 break;
260
261                         case 'x':
262                                 debug_flag++;
263                                 break;
264
265                         default:
266                                 usage(1);
267                                 break;
268                 }
269         }
270
271         if (memory_report) {
272                 talloc_enable_null_tracking();
273 #ifdef WITH_VERIFY_PTR
274                 talloc_set_abort_fn(die_horribly);
275 #endif
276         }
277         talloc_set_log_fn(log_talloc);
278
279         /*
280          *      Mismatch between the binary and the libraries it depends on
281          */
282         if (fr_check_lib_magic(RADIUSD_MAGIC_NUMBER) < 0) {
283                 fr_perror("radiusd");
284                 exit(EXIT_FAILURE);
285         }
286
287         if (rad_check_lib_magic(RADIUSD_MAGIC_NUMBER) < 0) {
288                 exit(EXIT_FAILURE);
289         }
290
291         /*
292          *      Mismatch between build time OpenSSL and linked SSL,
293          *      better to die here than segfault later.
294          */
295 #ifdef HAVE_OPENSSL_CRYPTO_H
296         if (ssl_check_version() < 0) {
297                 exit(EXIT_FAILURE);
298         }
299
300         /*
301          *      Initialising OpenSSL once, here, is safer than having individual
302          *      modules do it.
303          */
304         tls_global_init();
305 #endif
306
307         if (flag && (flag != 0x03)) {
308                 fprintf(stderr, "radiusd: The options -i and -p cannot be used individually.\n");
309                 exit(EXIT_FAILURE);
310         }
311
312         if (debug_flag) {
313                 version();
314         }
315
316         /*  Read the configuration files, BEFORE doing anything else.  */
317         if (read_mainconfig(0) < 0) {
318                 exit(EXIT_FAILURE);
319         }
320
321 #ifndef __MINGW32__
322         /*
323          *  Disconnect from session
324          */
325         if (dont_fork == false) {
326                 pid_t pid;
327
328                 if (pipe(from_child) != 0) {
329                         ERROR("Couldn't open pipe for child status: %s", fr_syserror(errno));
330                         exit(EXIT_FAILURE);
331                 }
332
333                 pid = fork();
334                 if (pid < 0) {
335                         ERROR("Couldn't fork: %s", fr_syserror(errno));
336                         exit(EXIT_FAILURE);
337                 }
338
339                 /*
340                  *  The parent exits, so the child can run in the background.
341                  *
342                  *  As the child can still encounter an error during initialisation
343                  *  we do a blocking read on a pipe between it and the parent.
344                  *
345                  *  Just before entering the event loop the child will send a success
346                  *  or failure message to the parent, via the pipe.
347                  */
348                 if (pid > 0) {
349                         uint8_t ret = 0;
350                         int stat_loc;
351
352                         /* So the pipe is correctly widowed if the child exits */
353                         close(from_child[1]);
354
355                         /*
356                          *      The child writes a 0x01 byte on
357                          *      success, and closes the pipe on error.
358                          */
359                         if ((read(from_child[0], &ret, 1) < 0)) {
360                                 ret = 0;
361                         }
362
363                         /* For cleanliness... */
364                         close(from_child[0]);
365
366                         /* Don't turn children into zombies */
367                         if (!ret) {
368                                 waitpid(pid, &stat_loc, WNOHANG);
369                                 exit(EXIT_FAILURE);
370                         }
371
372                         exit(EXIT_SUCCESS);
373                 }
374
375                 /* so the pipe is correctly widowed if the parent exits?! */
376                 close(from_child[0]);
377 #ifdef HAVE_SETSID
378                 setsid();
379 #endif
380         }
381 #endif
382
383         /*
384          *  Ensure that we're using the CORRECT pid after forking,
385          *  NOT the one we started with.
386          */
387         radius_pid = getpid();
388
389         /*
390          *      If we're running as a daemon, close the default file
391          *      descriptors, AFTER forking.
392          */
393         if (!debug_flag) {
394                 int devnull;
395
396                 devnull = open("/dev/null", O_RDWR);
397                 if (devnull < 0) {
398                         ERROR("Failed opening /dev/null: %s\n",
399                                fr_syserror(errno));
400                         exit(EXIT_FAILURE);
401                 }
402                 dup2(devnull, STDIN_FILENO);
403                 if (default_log.dest == L_DST_STDOUT) {
404                         setlinebuf(stdout);
405                         default_log.fd = STDOUT_FILENO;
406                 } else {
407                         dup2(devnull, STDOUT_FILENO);
408                 }
409                 if (default_log.dest == L_DST_STDERR) {
410                         setlinebuf(stderr);
411                         default_log.fd = STDERR_FILENO;
412                 } else {
413                         dup2(devnull, STDERR_FILENO);
414                 }
415                 close(devnull);
416
417         } else {
418                 setlinebuf(stdout); /* unbuffered output */
419         }
420
421         /*
422          *      Now we have logging check that the OpenSSL
423          */
424
425         /*
426          *      Initialize the event pool, including threads.
427          */
428         radius_event_init(mainconfig.config, spawn_flag);
429
430         /*
431          *      Now that we've set everything up, we can install the signal
432          *      handlers.  Before this, if we get any signal, we don't know
433          *      what to do, so we might as well do the default, and die.
434          */
435 #ifdef SIGPIPE
436         signal(SIGPIPE, SIG_IGN);
437 #endif
438
439         if ((fr_set_signal(SIGHUP, sig_hup) < 0) ||
440             (fr_set_signal(SIGTERM, sig_fatal) < 0)) {
441                 ERROR("%s", fr_strerror());
442                 exit(EXIT_FAILURE);
443         }
444
445         /*
446          *      If we're debugging, then a CTRL-C will cause the
447          *      server to die immediately.  Use SIGTERM to shut down
448          *      the server cleanly in that case.
449          */
450         if ((mainconfig.debug_memory == 1) || (debug_flag == 0)) {
451                 if ((fr_set_signal(SIGINT, sig_fatal) < 0)
452 #ifdef SIGQUIT
453                 || (fr_set_signal(SIGQUIT, sig_fatal) < 0)
454 #endif
455                 ) {
456                         ERROR("%s", fr_strerror());
457                         exit(EXIT_FAILURE);
458                 }
459         }
460
461         /*
462          *      Everything seems to have loaded OK, exit gracefully.
463          */
464         if (check_config) {
465                 DEBUG("Configuration appears to be OK.");
466
467                 /* for -C -m|-M */
468                 if (mainconfig.debug_memory) {
469                         goto cleanup;
470                 }
471
472                 exit(EXIT_SUCCESS);
473         }
474
475 #ifdef WITH_STATS
476         radius_stats_init(0);
477 #endif
478
479         /*
480          *      Write out the PID anyway if were in foreground mode.
481          */
482         if (!dont_fork) write_pid = true;
483
484         /*
485          *  Only write the PID file if we're running as a daemon.
486          *
487          *  And write it AFTER we've forked, so that we write the
488          *  correct PID.
489          */
490         if (write_pid) {
491                 FILE *fp;
492
493                 fp = fopen(mainconfig.pid_file, "w");
494                 if (fp != NULL) {
495                         /*
496                          *      FIXME: What about following symlinks,
497                          *      and having it over-write a normal file?
498                          */
499                         fprintf(fp, "%d\n", (int) radius_pid);
500                         fclose(fp);
501                 } else {
502                         ERROR("Failed creating PID file %s: %s\n",
503                                mainconfig.pid_file, fr_syserror(errno));
504                         exit(EXIT_FAILURE);
505                 }
506         }
507
508         exec_trigger(NULL, NULL, "server.start", false);
509
510         /*
511          *      Inform the parent (who should still be waiting) that
512          *      the rest of initialisation went OK, and that it should
513          *      exit with a 0 status.  If we don't get this far, then
514          *      we just close the pipe on exit, and the parent gets a
515          *      read failure.
516          */
517         if (!dont_fork) {
518                 if (write(from_child[1], "\001", 1) < 0) {
519                         WARN("Failed informing parent of successful start: %s",
520                              fr_syserror(errno));
521                 }
522                 close(from_child[1]);
523         }
524
525         /*
526          *      Process requests until HUP or exit.
527          */
528         while ((status = radius_event_process()) == 0x80) {
529 #ifdef WITH_STATS
530                 radius_stats_init(1);
531 #endif
532                 hup_mainconfig();
533         }
534         if (status < 0) {
535                 ERROR("Exiting due to internal error: %s", fr_strerror());
536                 rcode = EXIT_FAILURE;
537         } else {
538                 INFO("Exiting normally.");
539         }
540
541         exec_trigger(NULL, NULL, "server.stop", false);
542
543         /*
544          *      Ignore the TERM signal: we're
545          *      about to die.
546          */
547         signal(SIGTERM, SIG_IGN);
548
549         /*
550          *      Send a TERM signal to all
551          *      associated processes
552          *      (including us, which gets
553          *      ignored.)
554          */
555 #ifndef __MINGW32__
556         if (spawn_flag) kill(-radius_pid, SIGTERM);
557 #endif
558
559         /*
560          *      We're exiting, so we can delete the PID
561          *      file.  (If it doesn't exist, we can ignore
562          *      the error returned by unlink)
563          */
564         if (dont_fork == false) {
565                 unlink(mainconfig.pid_file);
566         }
567
568         radius_event_free();
569
570 cleanup:
571         /*
572          *      Detach any modules.
573          */
574         detach_modules();
575
576         xlat_free();            /* modules may have xlat's */
577
578         /*
579          *      Free the configuration items.
580          */
581         free_mainconfig();
582
583         rad_const_free(radius_dir);
584
585 #ifdef WIN32
586         WSACleanup();
587 #endif
588
589         if (memory_report) {
590                 INFO("Allocated memory at time of report:");
591                 log_talloc_report(NULL);
592         }
593
594         return rcode;
595 }
596
597
598 /*
599  *  Display the syntax for starting this program.
600  */
601 static void NEVER_RETURNS usage(int status)
602 {
603         FILE *output = status?stderr:stdout;
604
605         fprintf(output, "Usage: %s [-d db_dir] [-l log_dir] [-i address] [-n name] [-fsvXx]\n", progname);
606         fprintf(output, "Options:\n");
607         fprintf(output, "  -C            Check configuration and exit.\n");
608         fprintf(output, "  -d raddb_dir  Configuration files are in \"raddbdir/*\".\n");
609         fprintf(output, "  -f            Run as a foreground process, not a daemon.\n");
610         fprintf(output, "  -h            Print this help message.\n");
611         fprintf(output, "  -i ipaddr     Listen on ipaddr ONLY.\n");
612         fprintf(output, "  -l log_file   Logging output will be written to this file.\n");
613         fprintf(output, "  -m            On SIGINT or SIGQUIT exit cleanly instead of immediately.\n");
614         fprintf(output, "  -n name       Read raddb/name.conf instead of raddb/radiusd.conf.\n");
615         fprintf(output, "  -p port       Listen on port ONLY.\n");
616         fprintf(output, "  -P            Always write out PID, even with -f.\n");
617         fprintf(output, "  -s            Do not spawn child processes to handle requests.\n");
618         fprintf(output, "  -t            Disable threads.\n");
619         fprintf(output, "  -v            Print server version information.\n");
620         fprintf(output, "  -X            Turn on full debugging.\n");
621         fprintf(output, "  -x            Turn on additional debugging. (-xx gives more debugging).\n");
622         exit(status);
623 }
624
625
626 /*
627  *      We got a fatal signal.
628  */
629 static void sig_fatal(int sig)
630 {
631         if (getpid() != radius_pid) _exit(sig);
632
633         switch(sig) {
634         case SIGTERM:
635                 radius_signal_self(RADIUS_SIGNAL_SELF_TERM);
636                 break;
637
638         case SIGINT:
639 #ifdef SIGQUIT
640         case SIGQUIT:
641 #endif
642                 if (mainconfig.debug_memory || memory_report) {
643                         radius_signal_self(RADIUS_SIGNAL_SELF_TERM);
644                         break;
645                 }
646                 /* FALL-THROUGH */
647
648         default:
649                 _exit(sig);
650         }
651 }
652
653 #ifdef SIGHUP
654 /*
655  *  We got the hangup signal.
656  *  Re-read the configuration files.
657  */
658 static void sig_hup(UNUSED int sig)
659 {
660         reset_signal(SIGHUP, sig_hup);
661
662         radius_signal_self(RADIUS_SIGNAL_SELF_HUP);
663 }
664 #endif