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