Use EXIT_FAILURE and EXIT_SUCCESS macros
[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/log.h>
33 #include <freeradius-devel/rad_assert.h>
34
35 #include <sys/file.h>
36
37 #include <fcntl.h>
38 #include <ctype.h>
39
40 #include <signal.h>
41
42 #ifdef HAVE_GETOPT_H
43 #       include <getopt.h>
44 #endif
45
46 #ifdef HAVE_SYS_WAIT_H
47 #       include <sys/wait.h>
48 #endif
49 #ifndef WEXITSTATUS
50 #       define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
51 #endif
52 #ifndef WIFEXITED
53 #       define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
54 #endif
55
56 /*
57  *  Global variables.
58  */
59 char const *progname = NULL;
60 char const *radius_dir = NULL;
61 char const *radacct_dir = NULL;
62 char const *radlog_dir = NULL;
63 char const *radlib_dir = NULL;
64 int log_stripped_names;
65 log_debug_t debug_flag = 0;
66 int check_config = false;
67 int memory_report = false;
68
69 char const *radiusd_version = "FreeRADIUS Version " RADIUSD_VERSION_STRING
70 #ifdef RADIUSD_VERSION_COMMIT
71 " (git #" RADIUSD_VERSION_COMMIT ")"
72 #endif
73 ", for host " HOSTINFO ", built on " __DATE__ " at " __TIME__;
74
75 pid_t radius_pid;
76
77 /*
78  *  Configuration items.
79  */
80
81 /*
82  *      Static functions.
83  */
84 static void usage(int);
85
86 static void sig_fatal (int);
87 #ifdef SIGHUP
88 static void sig_hup (int);
89 #endif
90
91 #ifdef WITH_VERIFY_PTR
92 static void die_horribly(char const *reason)
93 {
94         ERROR("talloc abort: %s\n", reason);
95         abort();
96 }
97 #endif
98
99 /*
100  *      The main guy.
101  */
102 int main(int argc, char *argv[])
103 {
104         int rcode = EXIT_SUCCESS;
105         int status;
106         int argval;
107         int spawn_flag = true;
108         int dont_fork = false;
109         int write_pid = false;
110         int flag = 0;
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                 talloc_set_log_fn(log_talloc);
285 #ifdef WITH_VERIFY_PTR
286                 talloc_set_abort_fn(die_horribly);
287 #endif
288
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 #endif
300
301         if (flag && (flag != 0x03)) {
302                 fprintf(stderr, "radiusd: The options -i and -p cannot be used individually.\n");
303                 exit(EXIT_FAILURE);
304         }
305
306         if (debug_flag) {
307                 version();
308         }
309
310         /*  Read the configuration files, BEFORE doing anything else.  */
311         if (read_mainconfig(0) < 0) {
312                 exit(EXIT_FAILURE);
313         }
314
315 #ifndef __MINGW32__
316         /*
317          *  Disconnect from session
318          */
319         if (dont_fork == false) {
320                 pid_t pid = fork();
321
322                 if (pid < 0) {
323                         ERROR("Couldn't fork: %s", strerror(errno));
324                         exit(EXIT_FAILURE);
325                 }
326
327                 /*
328                  *  The parent exits, so the child can run in the background.
329                  */
330                 if (pid > 0) {
331                         exit(EXIT_SUCCESS);
332                 }
333 #ifdef HAVE_SETSID
334                 setsid();
335 #endif
336         }
337 #endif
338
339         /*
340          *  Ensure that we're using the CORRECT pid after forking,
341          *  NOT the one we started with.
342          */
343         radius_pid = getpid();
344
345         /*
346          *      If we're running as a daemon, close the default file
347          *      descriptors, AFTER forking.
348          */
349         if (!debug_flag) {
350                 int devnull;
351
352                 devnull = open("/dev/null", O_RDWR);
353                 if (devnull < 0) {
354                         ERROR("Failed opening /dev/null: %s\n",
355                                strerror(errno));
356                         exit(EXIT_FAILURE);
357                 }
358                 dup2(devnull, STDIN_FILENO);
359                 if (default_log.dest == L_DST_STDOUT) {
360                         setlinebuf(stdout);
361                         default_log.fd = STDOUT_FILENO;
362                 } else {
363                         dup2(devnull, STDOUT_FILENO);
364                 }
365                 if (default_log.dest == L_DST_STDERR) {
366                         setlinebuf(stderr);
367                         default_log.fd = STDERR_FILENO;
368                 } else {
369                         dup2(devnull, STDERR_FILENO);
370                 }
371                 close(devnull);
372
373         } else {
374                 setlinebuf(stdout); /* unbuffered output */
375         }
376         
377         /*
378          *      Now we have logging check that the OpenSSL
379          */
380
381         /*
382          *      Initialize the event pool, including threads.
383          */
384         radius_event_init(mainconfig.config, spawn_flag);
385
386         /*
387          *      Now that we've set everything up, we can install the signal
388          *      handlers.  Before this, if we get any signal, we don't know
389          *      what to do, so we might as well do the default, and die.
390          */
391 #ifdef SIGPIPE
392         signal(SIGPIPE, SIG_IGN);
393 #endif
394 #ifdef HAVE_SIGACTION
395         act.sa_handler = sig_hup;
396         sigaction(SIGHUP, &act, NULL);
397         act.sa_handler = sig_fatal;
398         sigaction(SIGTERM, &act, NULL);
399 #else
400 #ifdef SIGHUP
401         signal(SIGHUP, sig_hup);
402 #endif
403         signal(SIGTERM, sig_fatal);
404 #endif
405         /*
406          *      If we're debugging, then a CTRL-C will cause the
407          *      server to die immediately.  Use SIGTERM to shut down
408          *      the server cleanly in that case.
409          */
410         if ((mainconfig.debug_memory == 1) || (debug_flag == 0)) {
411 #ifdef HAVE_SIGACTION
412                 act.sa_handler = sig_fatal;
413                 sigaction(SIGINT, &act, NULL);
414                 sigaction(SIGQUIT, &act, NULL);
415 #else
416                 signal(SIGINT, sig_fatal);
417 #ifdef SIGQUIT
418                 signal(SIGQUIT, sig_fatal);
419 #endif
420 #endif
421         }
422
423         /*
424          *      Everything seems to have loaded OK, exit gracefully.
425          */
426         if (check_config) {
427                 DEBUG("Configuration appears to be OK.");
428                 
429                 /* for -C -m|-M */
430                 if (mainconfig.debug_memory) {
431                         goto cleanup;
432                 }
433                 
434                 exit(EXIT_SUCCESS);
435         }
436
437 #ifdef WITH_STATS
438         radius_stats_init(0);
439 #endif
440
441         /*
442          *      Write out the PID anyway if were in foreground mode.
443          */
444         if (!dont_fork) write_pid = true;
445
446         /*
447          *  Only write the PID file if we're running as a daemon.
448          *
449          *  And write it AFTER we've forked, so that we write the
450          *  correct PID.
451          */
452         if (write_pid) {
453                 FILE *fp;
454
455                 fp = fopen(mainconfig.pid_file, "w");
456                 if (fp != NULL) {
457                         /*
458                          *      FIXME: What about following symlinks,
459                          *      and having it over-write a normal file?
460                          */
461                         fprintf(fp, "%d\n", (int) radius_pid);
462                         fclose(fp);
463                 } else {
464                         ERROR("Failed creating PID file %s: %s\n",
465                                mainconfig.pid_file, strerror(errno));
466                         exit(EXIT_FAILURE);
467                 }
468         }
469
470         exec_trigger(NULL, NULL, "server.start", false);
471
472         /*
473          *      Process requests until HUP or exit.
474          */
475         while ((status = radius_event_process()) == 0x80) {
476 #ifdef WITH_STATS
477                 radius_stats_init(1);
478 #endif
479                 hup_mainconfig();
480         }
481         if (status < 0) {
482                 ERROR("Exiting due to internal error: %s", fr_strerror());
483                 rcode = EXIT_FAILURE;
484         } else {
485                 INFO("Exiting normally.");
486         }
487
488         exec_trigger(NULL, NULL, "server.stop", false);
489
490         /*
491          *      Ignore the TERM signal: we're
492          *      about to die.
493          */
494         signal(SIGTERM, SIG_IGN);
495         
496         /*
497          *      Send a TERM signal to all
498          *      associated processes
499          *      (including us, which gets
500          *      ignored.)
501          */
502 #ifndef __MINGW32__
503         if (spawn_flag) kill(-radius_pid, SIGTERM);
504 #endif
505         
506         /*
507          *      We're exiting, so we can delete the PID
508          *      file.  (If it doesn't exist, we can ignore
509          *      the error returned by unlink)
510          */
511         if (dont_fork == false) {
512                 unlink(mainconfig.pid_file);
513         }
514         
515         radius_event_free();
516
517 cleanup:
518         /*
519          *      Detach any modules.
520          */
521         detach_modules();
522         
523         xlat_free();            /* modules may have xlat's */
524
525         /*
526          *      Free the configuration items.
527          */
528         free_mainconfig();
529         
530         rad_const_free(radius_dir);
531                 
532 #ifdef WIN32
533         WSACleanup();
534 #endif
535
536         if (memory_report) {
537                 INFO("Allocated memory at time of report:");
538                 log_talloc_report(NULL);
539         }
540
541         return rcode;
542 }
543
544
545 /*
546  *  Display the syntax for starting this program.
547  */
548 static void NEVER_RETURNS usage(int status)
549 {
550         FILE *output = status?stderr:stdout;
551
552         fprintf(output,
553                         "Usage: %s [-d db_dir] [-l log_dir] [-i address] [-n name] [-fsvXx]\n", progname);
554         fprintf(output, "Options:\n\n");
555         fprintf(output, "  -C            Check configuration and exit.\n");
556         fprintf(output, "  -d raddb_dir  Configuration files are in \"raddbdir/*\".\n");
557         fprintf(output, "  -f            Run as a foreground process, not a daemon.\n");
558         fprintf(output, "  -h            Print this help message.\n");
559         fprintf(output, "  -i ipaddr     Listen on ipaddr ONLY.\n");
560         fprintf(output, "  -l log_file   Logging output will be written to this file.\n");
561         fprintf(output, "  -m            On SIGINT or SIGQUIT exit cleanly instead of immediately.\n");
562         fprintf(output, "  -n name       Read raddb/name.conf instead of raddb/radiusd.conf\n");
563         fprintf(output, "  -p port       Listen on port ONLY.\n");
564         fprintf(output, "  -P            Always write out PID, even with -f");
565         fprintf(output, "  -s            Do not spawn child processes to handle requests.\n");
566         fprintf(output, "  -t            Disable threads.\n");
567         fprintf(output, "  -v            Print server version information.\n");
568         fprintf(output, "  -X            Turn on full debugging.\n");
569         fprintf(output, "  -x            Turn on additional debugging. (-xx gives more debugging).\n");
570         exit(status);
571 }
572
573
574 /*
575  *      We got a fatal signal.
576  */
577 static void sig_fatal(int sig)
578 {
579         if (getpid() != radius_pid) _exit(sig);
580
581         switch(sig) {
582                 case SIGTERM:
583                         radius_signal_self(RADIUS_SIGNAL_SELF_TERM);
584                         break;
585
586                 case SIGINT:
587 #ifdef SIGQUIT
588                 case SIGQUIT:
589 #endif
590                         if (mainconfig.debug_memory || memory_report) {
591                                 radius_signal_self(RADIUS_SIGNAL_SELF_TERM);
592                                 break;
593                         }
594                         /* FALL-THROUGH */
595
596                 default:
597                         _exit(sig);
598         }
599 }
600
601 #ifdef SIGHUP
602 /*
603  *  We got the hangup signal.
604  *  Re-read the configuration files.
605  */
606 static void sig_hup(UNUSED int sig)
607 {
608         reset_signal(SIGHUP, sig_hup);
609
610         radius_signal_self(RADIUS_SIGNAL_SELF_HUP);
611 }
612 #endif