Release bumped to "gts4".
[tac_plus.git] / main.c
1 /*
2  * tac_plus.c
3  *
4  * TACACS_PLUS daemon suitable for using on Un*x systems.
5  *
6  * October 1994, Lol Grant
7  *
8  * Copyright (c) 1994-1998 by Cisco systems, Inc.
9  * Permission to use, copy, modify, and distribute this software for
10  * any purpose and without fee is hereby granted, provided that this
11  * copyright and permission notice appear on all copies of the
12  * software and supporting documentation, the name of Cisco Systems,
13  * Inc. not be used in advertising or publicity pertaining to
14  * distribution of the program without specific prior permission, and
15  * notice be given in supporting documentation that modification,
16  * copying and distribution is by permission of Cisco Systems, Inc.
17  *
18  * Cisco Systems, Inc. makes no representations about the suitability
19  * of this software for any purpose.  THIS SOFTWARE IS PROVIDED ``AS
20  * IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
21  * WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
22  * FITNESS FOR A PARTICULAR PURPOSE.
23 */
24
25
26 #include "tac_plus.h"
27
28 #include <stdlib.h>
29 #include <sys/wait.h>
30 #include <signal.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <netdb.h>
37 #include <errno.h>
38 #ifdef HAVE_SYS_TIME_H
39 #include <sys/time.h>
40 #endif
41 #ifdef HAVE_UNISTD_H
42 #include <unistd.h>
43 #endif
44 #ifdef HAVE_SYSLOG_H
45 #include <syslog.h>
46 #endif
47 #ifdef HAVE_SYS_SYSLOG_H
48 #include <sys/syslog.h>
49 #endif
50 #ifdef HAVE_FCNTL_H
51 #include <fcntl.h>
52 #endif
53 #ifdef HAVE_SYS_IOCTL_H
54 #include <sys/ioctl.h>
55 #endif
56
57 #include "main.h"
58 #include "report.h"
59 #include "utils.h"
60 #include "cfgfile.h"
61 #include "packet.h"
62 #include "dump.h"
63 #include "author.h"
64 #include "acct.h"
65 #include "authen.h"
66 #include "do_acct.h"
67 #include "parse.h"
68
69 #ifdef MAXSESS
70 #include "maxsess.h"
71 #endif
72
73
74 static void version TAC_ARGS((void));
75 static void start_session TAC_ARGS((void));
76
77
78 /* Configurable:
79  */
80
81 #ifndef TAC_PLUS_PORT
82 #define TAC_PLUS_PORT                   49
83 #endif
84
85
86 static int standalone  = 1; /* running standalone (1) or under inetd (0) */
87 static int initialised = 0; /* data structures have been allocated */
88 int sendauth_only      = 0; /* don't respond to sendpass requests */
89 int debug              = 0; /* debugging flags */
90 static int port        = 0; /* port we're listening on */
91 int console            = 0; /* write all syslog messages to console */
92 int parse_only         = 0; /* exit after verbose parsing */
93 int single             = 0; /* single thread (for debugging) */
94
95 struct session session;     /* session data */
96
97 static char pidfilebuf[75]; /* holds current name of the pidfile */
98
99
100 #ifndef REAPCHILD
101 static RETSIGTYPE reapchild TAC_ARGS((int signo));
102
103 static RETSIGTYPE
104 reapchild(signo)
105 int signo;
106 {
107 #ifdef UNIONWAIT
108     union wait status;
109 #else
110     int status;
111 #endif
112     int pid;
113
114     signal(SIGCHLD, reapchild);
115
116     for (;;) {
117         pid = wait3(&status, WNOHANG, 0);
118         if (pid <= 0)
119             return;
120         if (debug & DEBUG_FORK_FLAG)
121             report(LOG_DEBUG, "%d reaped", pid);
122     }
123 }
124 #endif /* REAPCHILD */
125
126 static void die TAC_ARGS((int signum));
127
128 static void
129 die(signum)
130 int signum;
131 {
132     report(LOG_INFO, "Received signal %d, shutting down", signum);
133     unlink(pidfilebuf);
134     tac_exit(0);
135 }
136
137 static void init TAC_ARGS((void));
138
139 static void
140 init()
141 {
142     if (initialised)
143         cfg_clean_config();
144
145     report(LOG_INFO, "Reading config");
146
147     session.acctfile = tac_strdup("/var/log/acctfile");
148
149     if (!session.cfgfile) {
150         report(LOG_ERR, "no config file specified");
151         tac_exit(1);
152     }
153
154     /* read the config file */
155     if (cfg_read_config(session.cfgfile)) {
156         report(LOG_ERR, "Parsing %s", session.cfgfile);
157         fprintf(stderr,"Config file not found!!\n");
158         tac_exit(1);
159     }
160
161     initialised++;
162
163     report(LOG_INFO, "Version %s%s Initialized %d", VERSION, VERSION_TAIL, initialised);
164
165 }
166
167 /* 'handler()' will be called during initialization to setup signal handler,
168  * keep it in mind when modifying it!
169  */
170
171 static int handler_occured = 0;
172
173 static RETSIGTYPE handler TAC_ARGS((int signum));
174
175 static RETSIGTYPE
176 handler(signum)
177 int signum;
178 {
179     /* never execute any non-trivial (=system-call) commands here
180      * as it may immediately abort the whole 'handler()' (SYSV signal).
181      * We hope that SA_RESTART is NOT set for our signals
182      */
183     handler_occured = 1;
184     /* It is never wrong to reinstall 'handler' just to be safe */
185     signal(SIGUSR1, handler);
186     signal(SIGHUP , handler);
187
188     /* DON'T interrupt! */
189 #ifdef HAVE_SIGINTERRUPT
190     siginterrupt(SIGUSR1, 0 /* flag */);
191     siginterrupt(SIGHUP , 0 /* flag */);
192 #endif
193 }
194
195 static void check_handler_occured TAC_ARGS((void));
196
197 static RETSIGTYPE
198 check_handler_occured()
199 {
200
201     if (!handler_occured)
202         return;
203
204     handler_occured = 0;
205     report(LOG_INFO, "Signal detected, reloading configuration");
206     init();
207 }
208
209 /*
210  * Return a socket bound to an appropriate port number/address. Exits
211  * the program on failure */
212
213 static int get_socket TAC_ARGS((void));
214
215 static int
216 get_socket()
217 {
218     int s;
219     struct sockaddr_in sin;
220     struct servent *sp;
221     int on = 1;
222
223     bzero((char *) &sin, sizeof(sin));
224
225     if (port) {
226         sin.sin_port = htons(port);
227     } else {
228         sp = getservbyname("tacacs", "tcp");
229         if (sp)
230             sin.sin_port = sp->s_port;
231         else {
232             report(LOG_ERR, "Cannot find socket port");
233             tac_exit(1);
234         }
235     }
236
237     sin.sin_family = AF_INET;
238     sin.sin_addr.s_addr = htonl(INADDR_ANY);
239
240     s = socket(AF_INET, SOCK_STREAM, 0);
241
242     if (s < 0) {
243         console++;
244         report(LOG_ERR, "get_socket: socket: %s", sys_errlist[errno]);
245         tac_exit(1);
246     }
247 #ifdef SO_REUSEADDR
248         if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &on,
249                        sizeof(on)) < 0)
250             perror("setsockopt - SO_REUSEADDR");
251 #endif                          /* SO_REUSEADDR */
252
253     if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
254         console++;
255         report(LOG_ERR, "get_socket: bind %d %s",
256                ntohs(sin.sin_port),
257                sys_errlist[errno]);
258         tac_exit(1);
259     }
260     return (s);
261 }
262
263 static void open_logfile TAC_ARGS((void));
264
265 static void
266 open_logfile()
267 {
268 #ifdef LOG_LOCAL6
269     openlog("tac_plus", LOG_PID, LOG_LOCAL6);
270 #else
271     openlog("tac_plus", LOG_PID);
272 #endif
273     setlogmask(LOG_UPTO(LOG_DEBUG));
274 }
275
276 static void prep_session_peer TAC_ARGS((const struct sockaddr_in *from));
277
278 static void
279 prep_session_peer(from)
280 const struct sockaddr_in *from;
281 {
282     struct hostent *hp;
283
284     if (session.peer_addr && session.peer_addr != session.peer)
285         free(session.peer_addr);
286     if (session.peer)
287         free(session.peer);
288
289     session.peer_addr = tac_strdup( (char *) inet_ntoa(from->sin_addr) );
290
291     hp = gethostbyaddr((char *) &from->sin_addr.s_addr, sizeof(from->sin_addr.s_addr), AF_INET);
292
293     if (hp)
294         session.peer = tac_strdup(hp->h_name);
295     else
296         session.peer = session.peer_addr;
297 }
298
299 /*
300  * main
301  *
302  * We will eventually be called from inetd or via the rc scripts directly
303  * Parse arguments and act appropiately.
304  */
305
306 int main TAC_ARGS((int argc, char **argv));
307
308 int
309 main(argc, argv)
310 int argc;
311 char **argv;
312 {
313     extern char *optarg;
314     int childpid;
315     int c;
316     int s;
317     FILE *fp;
318     int lookup_peer = 0;
319
320     debug = 0;                  /* no debugging */
321     standalone = 1;                     /* standalone */
322     single = 0;                 /* single threaded */
323
324     /* initialise global session data */
325     bzero(&session, sizeof(session));
326     session.peer = tac_strdup("unknown");
327
328     open_logfile();
329
330 #ifdef TAC_PLUS_PORT
331     port = TAC_PLUS_PORT;
332 #endif
333
334 #ifdef MAINTAINER_MODE
335     session.cfgfile = "/etc/tacacs/tac_plus.cfg";
336 #endif
337
338     if (argc <= 1) {
339         fprintf(stderr, "Usage: tac_plus -C <configuration file>\n");
340         fprintf(stderr, "\t[ -t ] [ -P ] [ -g ] [ -p <port> ]\n");
341         fprintf(stderr, "\t[ -d <debug level> ] [ -i ] [ -v ] [ -s ]\n");
342         fprintf(stderr, "\t[ -l logfile ]");
343 #ifdef MAXSESS
344         fprintf(stderr, " [ -w whologfile ]");
345 #endif
346         fprintf(stderr, "\n");
347         tac_exit(1);
348     }
349
350     while ((c = getopt(argc, argv, "td:C:ip:PgvsLl:w:u:")) != EOF)
351         switch (c) {
352         case 'L':               /* lookup peer names via DNS */
353             lookup_peer++;
354             break;
355         case 's':               /* don't respond to sendpass */
356             sendauth_only++;
357             break;
358         case 'v':               /* print version and exit */
359             version();
360             tac_exit(1);
361         case 't':
362             console++;          /* log to console too */
363             break;
364         case 'P':               /* Parse config file only */
365             parse_only++;
366             break;
367         case 'g':               /* single threaded */
368             single++;
369             break;
370         case 'p':               /* port */
371             port = atoi(optarg);
372             break;
373         case 'd':               /* debug */
374             debug = atoi(optarg);
375             break;
376         case 'C':               /* config file name */
377             session.cfgfile = tac_strdup(optarg);
378             break;
379         case 'i':               /* stand-alone */
380             standalone = 0;
381             break;
382         case 'l':               /* logfile */
383             logfile = tac_strdup(optarg);
384             break;
385 #ifdef MAXSESS
386         case 'w':               /* wholog file */
387             wholog = tac_strdup(optarg);
388             break;
389 #endif
390         case 'u':
391             wtmpfile = tac_strdup(optarg);
392             break;
393
394         default:
395             fprintf(stderr, "%s: bad switch %c\n", argv[0], c);
396             tac_exit(1);
397         }
398
399     if (geteuid() != 0) {
400         fprintf(stderr, "Warning, not running as uid 0\n");
401         fprintf(stderr, "Tac_plus is usually run as root\n");
402     }
403
404     parser_init();
405
406     init();
407
408     handler(-1 /* signum */);           /* connect to the signals */
409     handler_occured = 0;                /* post-fix cludge */
410
411     signal(SIGTERM, die);
412     signal(SIGPIPE, SIG_IGN);
413
414     if (parse_only)
415         tac_exit(0);
416
417     if (debug)
418         report(LOG_DEBUG, "tac_plus server %s%s starting", VERSION, VERSION_TAIL);
419
420     if (!standalone) {
421         /* running under inetd */
422         struct sockaddr_in name;
423         socklen_t name_len;
424 #ifdef FIONBIO
425         int fionbio_on = 1;
426 #endif
427
428         name_len = sizeof(name);
429
430         if (getpeername(session.sock, (struct sockaddr *) &name, &name_len)) {
431             report(LOG_ERR, "getpeername failure %s", sys_errlist[errno]);
432             prep_session_peer(NULL);
433         } else
434             prep_session_peer(&name);
435
436         session.sock = 0;
437 #ifdef FIONBIO
438         if (ioctl(session.sock, FIONBIO, &fionbio_on) < 0) {
439             report(LOG_ERR, "ioctl(FIONBIO) %s", sys_errlist[errno]);
440             tac_exit(1);
441         }
442 #endif
443         start_session();
444         tac_exit(0);
445     }
446
447     if (!single) {
448         /* Running standalone. Background ourselves, let go of controlling tty */
449
450 #ifdef SIGTTOU
451         signal(SIGTTOU, SIG_IGN);
452 #endif
453 #ifdef SIGTTIN
454         signal(SIGTTIN, SIG_IGN);
455 #endif
456 #ifdef SIGTSTP
457         signal(SIGTSTP, SIG_IGN);
458 #endif
459
460         signal(SIGHUP, SIG_IGN);
461
462         if ((childpid = fork()) < 0)
463             report(LOG_ERR, "Can't fork first child");
464         else if (childpid > 0)
465             exit(0);            /* parent */
466
467         if (debug)
468             report(LOG_DEBUG, "Backgrounded");
469
470 #ifndef REAPCHILD
471
472 #ifdef SETPGRP_VOID
473         if (setpgrp() == -1)
474 #else /* SETPGRP_VOID */
475         if (setpgrp(0, getpid()) == -1)
476 #endif /* SETPGRP_VOID */
477             report(LOG_ERR, "Can't change process group");
478
479 #ifdef TIOCNOTTY
480         c = open("/dev/tty", O_RDWR);
481         if (c >= 0) {
482             ioctl(c, TIOCNOTTY, (char *) 0);
483             (void) close(c);
484         }
485 #endif
486         signal(SIGCHLD, reapchild);
487
488 #else /* REAPCHILD */
489
490 #ifdef SETPGRP_VOID
491         if (setpgrp() == 1)
492 #else /* SETPGRP_VOID */
493         if (setpgrp(0, getpid()) == 1)
494 #endif /* SETPGRP_VOID */
495             report(LOG_ERR, "Can't change process group");
496
497         signal(SIGHUP, SIG_IGN);
498
499         if ((childpid = fork()) < 0)
500             report(LOG_ERR, "Can't fork second child");
501         else if (childpid > 0)
502             exit(0);
503
504         if (debug & DEBUG_FORK_FLAG)
505             report(LOG_DEBUG, "Forked grandchild");
506
507         signal(SIGCHLD, SIG_IGN);
508
509 #endif /* REAPCHILD */
510
511         closelog(); /* some systems require this */
512
513         for (c = 0; c < getdtablesize(); c++)
514             (void) close(c);
515
516         /* make sure we can still log to syslog now we've closed everything */
517         open_logfile();
518
519     } /* ! single threaded */
520
521     ostream = NULL;
522     /* chdir("/"); */
523     umask(0);
524     errno = 0;
525
526     s = get_socket();
527
528 #ifndef SOMAXCONN
529 #ifdef LINUX
530 #define SOMAXCONN 128
531 #else
532 #define SOMAXCONN 5
533 #endif /* LINUX */
534 #endif /* SOMAXCONN */
535
536     if (listen(s, SOMAXCONN) < 0) {
537         console++;
538         report(LOG_ERR, "listen: %s", sys_errlist[errno]);
539         tac_exit(1);
540     }
541
542     if (port == TAC_PLUS_PORT) {
543         strcpy(pidfilebuf, TACPLUS_PIDFILE);
544     } else {
545         sprintf(pidfilebuf, "%s.%d", TACPLUS_PIDFILE, port);
546     }
547
548     /* write process id to pidfile */
549     if ((fp = fopen(pidfilebuf, "w")) != NULL) {
550         fprintf(fp, "%d\n", (int) getpid());
551         fclose(fp);
552     } else
553         report(LOG_ERR, "Cannot write pid to %s %s",
554                pidfilebuf, sys_errlist[errno]);
555
556 #ifdef TACPLUS_GROUPID
557     if (setgid(TACPLUS_GROUPID))
558         report(LOG_ERR, "Cannot set group id to %d %s",
559                TACPLUS_GROUPID, sys_errlist[errno]);
560 #endif
561
562 #ifdef TACPLUS_USERID
563     if (setuid(TACPLUS_USERID))
564         report(LOG_ERR, "Cannot set user id to %d %s",
565                TACPLUS_USERID, sys_errlist[errno]);
566 #endif
567
568 #ifdef MAXSESS
569     maxsess_loginit();
570 #endif /* MAXSESS */
571
572     report(LOG_DEBUG, "uid=%d euid=%d gid=%d egid=%d s=%d",
573            (int) getuid(), (int) geteuid(), (int) getgid(), (int) getegid(), s);
574
575     for (;;) {
576         int pid;
577         struct sockaddr_in from;
578         socklen_t from_len;
579         int newsockfd;
580
581         check_handler_occured();
582
583         bzero((char *) &from, sizeof(from));
584         from_len = sizeof(from);
585
586         /* PERMIT interrupt of accept()! */
587 #ifdef HAVE_SIGINTERRUPT
588         siginterrupt(SIGUSR1, 1 /* flag */);
589         siginterrupt(SIGHUP , 1 /* flag */);
590 #endif
591
592         errno = 0;
593         newsockfd = accept(s, (struct sockaddr *) &from, &from_len);
594
595         /* DON'T interrupt! */
596 #ifdef HAVE_SIGINTERRUPT
597         siginterrupt(SIGUSR1, 0 /* flag */);
598         siginterrupt(SIGHUP , 0 /* flag */);
599 #endif
600
601         check_handler_occured();
602
603         if (newsockfd < 0) {
604             /* sometimes we may get even 'errno==0' when 'handler()' signal occured */
605             if (errno == EINTR || errno == 0)
606                 continue;
607
608             report(LOG_ERR, "accept: %s", sys_errlist[errno]);
609             continue;
610         }
611         prep_session_peer(&from);
612
613         if (debug & DEBUG_PACKET_FLAG)
614             report(LOG_DEBUG, "session request from %s sock=%d",
615                    session.peer, newsockfd);
616
617         if (!single) {
618             pid = fork();
619
620             if (pid < 0) {
621                 report(LOG_ERR, "fork error");
622                 tac_exit(1);
623             }
624         } else {
625             pid = 0;
626         }
627
628         if (pid == 0) {
629             /* child */
630             if (!single)
631                 close(s);
632             session.sock = newsockfd;
633             start_session();
634             shutdown(session.sock, 2);
635             close(session.sock);
636             if (!single)
637                 tac_exit(0);
638         } else {
639             if (debug & DEBUG_FORK_FLAG)
640                 report(LOG_DEBUG, "forked %d", pid);
641             /* parent */
642             close(newsockfd);
643         }
644     }
645 }
646
647 #ifdef GETDTABLESIZE
648 int
649 getdtablesize()
650 {
651     return(_NFILE);
652 }
653 #endif /* GETDTABLESIZE */
654
655 static int bad_version_check TAC_ARGS((u_char *pak));
656
657 /* Make sure version number is kosher. Return 0 if it is */
658 static int
659 bad_version_check(pak)
660 u_char *pak;
661 {
662     HDR *hdr = (HDR *) pak;
663
664     switch (hdr->type) {
665     case TAC_PLUS_AUTHEN:
666         /*
667          * Let authen routines take care of more sophisticated version
668          * checking as its now a bit involved.
669          */
670         return(0);
671
672     case TAC_PLUS_AUTHOR:
673     case TAC_PLUS_ACCT:
674         if (hdr->version != TAC_PLUS_VER_0) {
675             send_error_reply(hdr->type, "Illegal packet version");
676             return(1);
677         }
678         return(0);
679
680     default:
681         return(1);
682     }
683 }
684
685 /*
686  * Determine the packet type, read the rest of the packet data,
687  * decrypt it and call the appropriate service routine.
688  *
689  */
690
691 static void start_session TAC_ARGS((void));
692
693 static void
694 start_session()
695 {
696     u_char *pak;
697     HDR *hdr;
698
699     session.seq_no = 0;
700     session.aborted = 0;
701     session.version = 0;
702
703     /* Now we are starting our new 'request' cycle */
704     cfg_request_scan_begin();
705
706     pak = read_packet();
707     if (!pak) {
708         return;
709     }
710
711     if (debug & DEBUG_PACKET_FLAG) {
712         report(LOG_DEBUG, "validation request from %s", session.peer);
713         dump_nas_pak(pak);
714     }
715     hdr = (HDR *) pak;
716
717     session.session_id = ntohl(hdr->session_id);
718
719     /* Do some version checking */
720     if (bad_version_check(pak)) {
721         free(pak);
722         return;
723     }
724
725     switch (hdr->type) {
726     case TAC_PLUS_AUTHEN:
727         authen(pak);
728         free(pak);
729         return;
730
731     case TAC_PLUS_AUTHOR:
732         author(pak);
733         free(pak);
734         return;
735
736     case TAC_PLUS_ACCT:
737         accounting(pak);
738         return;
739
740     default:
741         /* Note: can't send error reply if type is unknown */
742         report(LOG_ERR, "Illegal type %d in received packet", hdr->type);
743         free(pak);
744         return;
745     }
746 }
747
748 static void version TAC_ARGS((void));
749
750 static void
751 version()
752 {
753     fprintf(stdout, "tac_plus version %s%s\n", VERSION, VERSION_TAIL);
754 #ifdef AIX
755     fprintf(stdout,"AIX\n");
756 #endif
757 #ifdef ARAP_DES
758     fprintf(stdout,"ARAP_DES\n");
759 #endif
760 #ifdef BSDI
761     fprintf(stdout,"BSDI\n");
762 #endif
763 #ifdef CONST_SYSERRLIST
764     fprintf(stdout,"CONST_SYSERRLIST\n");
765 #endif
766 #ifdef DEBUG
767     fprintf(stdout,"DEBUG\n");
768 #endif
769 #ifdef DES_DEBUG
770     fprintf(stdout,"DES_DEBUG\n");
771 #endif
772 #ifdef FIONBIO
773     fprintf(stdout,"FIONBIO\n");
774 #endif
775 #ifdef FREEBSD
776     fprintf(stdout,"FREEBSD\n");
777 #endif
778 #ifdef GETDTABLESIZE
779     fprintf(stdout,"GETDTABLESIZE\n");
780 #endif
781 #ifdef HPUX
782     fprintf(stdout,"HPUX\n");
783 #endif
784 #ifdef LINUX
785     fprintf(stdout,"LINUX\n");
786 #endif
787 #ifdef LOG_LOCAL6
788     fprintf(stdout,"LOG_LOCAL6\n");
789 #endif
790 #ifdef MAXSESS
791     fprintf(stdout,"MAXSESS\n");
792 #endif
793 #ifdef MIPS
794     fprintf(stdout,"MIPS\n");
795 #endif
796 #ifdef NEED_BZERO
797     fprintf(stdout,"NEED_BZERO\n");
798 #endif
799 #ifdef NETBSD
800     fprintf(stdout,"NETBSD\n");
801 #endif
802 #ifdef REAPCHILD
803     fprintf(stdout,"REAPCHILD\n");
804 #endif
805 #ifdef SHADOW_PASSWORDS
806     fprintf(stdout,"SHADOW_PASSWORDS\n");
807 #endif
808 #ifdef SIGTSTP
809     fprintf(stdout,"SIGTSTP\n");
810 #endif
811 #ifdef SIGTTIN
812     fprintf(stdout,"SIGTTIN\n");
813 #endif
814 #ifdef SIGTTOU
815     fprintf(stdout,"SIGTTOU\n");
816 #endif
817 #ifdef SKEY
818     fprintf(stdout,"SKEY\n");
819 #endif
820 #ifdef SOLARIS
821     fprintf(stdout,"SOLARIS\n");
822 #endif
823 #ifdef SO_REUSEADDR
824     fprintf(stdout,"SO_REUSEADDR\n");
825 #endif
826 #ifdef HAVE_STRCSPN
827     fprintf(stdout,"HAVE_STRCSPN\n");
828 #endif
829 #ifdef SYSV
830     fprintf(stdout,"SYSV\n");
831 #endif
832 #ifdef TACPLUS_GROUPID
833     fprintf(stdout,"TACPLUS_GROUPID\n");
834 #endif
835 #ifdef TAC_PLUS_PORT
836     fprintf(stdout,"TAC_PLUS_PORT\n");
837 #endif
838 #ifdef TACPLUS_USERID
839     fprintf(stdout,"TACPLUS_USERID\n");
840 #endif
841 #ifdef UNIONWAIT
842     fprintf(stdout,"UNIONWAIT\n");
843 #endif
844 #ifdef _BSD1
845     fprintf(stdout,"_BSD1\n");
846 #endif
847 #ifdef _BSD_INCLUDES
848     fprintf(stdout,"_BSD_INCLUDES\n");
849 #endif
850 #ifdef __STDC__
851     fprintf(stdout,"__STDC__\n");
852 #endif
853 }