84ae88083f7613be51bec29b88a99aa9ff3d3972
[openafs.git] / src / bozo / bosserver.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12 #include <afs/stds.h>
13
14 #include <afs/procmgmt.h>
15 #include <roken.h>
16
17 #ifdef IGNORE_SOME_GCC_WARNINGS
18 # pragma GCC diagnostic warning "-Wdeprecated-declarations"
19 #endif
20
21 #ifdef HAVE_SYS_RESOURCE_H
22 #include <sys/resource.h>
23 #endif
24
25 #ifdef AFS_NT40_ENV
26 #include <direct.h>
27 #include <WINNT/afsevent.h>
28 #endif /* AFS_NT40_ENV */
29
30 #include <rx/rx.h>
31 #include <rx/xdr.h>
32 #include <rx/rx_globals.h>
33 #include <rx/rxkad.h>
34 #include <rx/rxstat.h>
35 #include <afs/keys.h>
36 #include <afs/ktime.h>
37 #include <afs/afsutil.h>
38 #include <afs/fileutil.h>
39 #include <afs/audit.h>
40 #include <afs/cellconfig.h>
41
42 #if defined(AFS_SGI_ENV)
43 #include <afs/afs_args.h>
44 #endif
45
46 #include "bosint.h"
47 #include "bnode.h"
48 #include "bosprototypes.h"
49
50 #define BOZO_LWP_STACKSIZE      16000
51 extern struct bnode_ops fsbnode_ops, dafsbnode_ops, ezbnode_ops, cronbnode_ops;
52
53 struct afsconf_dir *bozo_confdir = 0;   /* bozo configuration dir */
54 static PROCESS bozo_pid;
55 const char *bozo_fileName;
56 FILE *bozo_logFile;
57
58 const char *DoCore;
59 int DoLogging = 0;
60 int DoSyslog = 0;
61 #ifndef AFS_NT40_ENV
62 int DoSyslogFacility = LOG_DAEMON;
63 #endif
64 static afs_int32 nextRestart;
65 static afs_int32 nextDay;
66
67 struct ktime bozo_nextRestartKT, bozo_nextDayKT;
68 int bozo_newKTs;
69 int rxBind = 0;
70 int rxkadDisableDotCheck = 0;
71
72 #define ADDRSPERSITE 16         /* Same global is in rx/rx_user.c */
73 afs_uint32 SHostAddrs[ADDRSPERSITE];
74
75 int bozo_isrestricted = 0;
76 int bozo_restdisable = 0;
77
78 void
79 bozo_insecureme(int sig)
80 {
81     signal(SIGFPE, bozo_insecureme);
82     bozo_isrestricted = 0;
83     bozo_restdisable = 1;
84 }
85
86 struct bztemp {
87     FILE *file;
88 };
89
90 /* check whether caller is authorized to manage RX statistics */
91 int
92 bozo_rxstat_userok(struct rx_call *call)
93 {
94     return afsconf_SuperUser(bozo_confdir, call, NULL);
95 }
96
97 /* restart bozo process */
98 int
99 bozo_ReBozo(void)
100 {
101 #ifdef AFS_NT40_ENV
102     /* exit with restart code; SCM integrator process will restart bosserver */
103     int status = BOSEXIT_RESTART;
104
105     /* if noauth flag is set, pass "-noauth" to new bosserver */
106     if (afsconf_GetNoAuthFlag(bozo_confdir)) {
107         status |= BOSEXIT_NOAUTH_FLAG;
108     }
109     /* if logging is on, pass "-log" to new bosserver */
110     if (DoLogging) {
111         status |= BOSEXIT_LOGGING_FLAG;
112     }
113     /* if rxbind is set, pass "-rxbind" to new bosserver */
114     if (rxBind) {
115         status |= BOSEXIT_RXBIND_FLAG;
116     }
117     exit(status);
118 #else
119     /* exec new bosserver process */
120     char *argv[4];
121     int i = 0;
122
123     argv[i] = (char *)AFSDIR_SERVER_BOSVR_FILEPATH;
124     i++;
125
126     /* if noauth flag is set, pass "-noauth" to new bosserver */
127     if (afsconf_GetNoAuthFlag(bozo_confdir)) {
128         argv[i] = "-noauth";
129         i++;
130     }
131     /* if logging is on, pass "-log" to new bosserver */
132     if (DoLogging) {
133         argv[i] = "-log";
134         i++;
135     }
136     /* if rxbind is set, pass "-rxbind" to new bosserver */
137     if (rxBind) {
138         argv[i] = "-rxbind";
139         i++;
140     }
141 #ifndef AFS_NT40_ENV
142     /* if syslog logging is on, pass "-syslog" to new bosserver */
143     if (DoSyslog) {
144         char *arg = (char *)malloc(40); /* enough for -syslog=# */
145         if (DoSyslogFacility != LOG_DAEMON) {
146             snprintf(arg, 40, "-syslog=%d", DoSyslogFacility);
147         } else {
148             strcpy(arg, "-syslog");
149         }
150         argv[i] = arg;
151         i++;
152     }
153 #endif
154
155     /* null-terminate argument list */
156     argv[i] = NULL;
157
158     /* close random fd's */
159     for (i = 3; i < 64; i++) {
160         close(i);
161     }
162
163     execv(argv[0], argv);       /* should not return */
164     _exit(1);
165 #endif /* AFS_NT40_ENV */
166 }
167
168 /* make sure a dir exists */
169 static int
170 MakeDir(const char *adir)
171 {
172     struct stat tstat;
173     afs_int32 code;
174     if (stat(adir, &tstat) < 0 || (tstat.st_mode & S_IFMT) != S_IFDIR) {
175         int reqPerm;
176         unlink(adir);
177         reqPerm = GetRequiredDirPerm(adir);
178         if (reqPerm == -1)
179             reqPerm = 0777;
180 #ifdef AFS_NT40_ENV
181         /* underlying filesystem may not support directory protection */
182         code = mkdir(adir);
183 #else
184         code = mkdir(adir, reqPerm);
185 #endif
186         return code;
187     }
188     return 0;
189 }
190
191 /* create all the bozo dirs */
192 static int
193 CreateDirs(const char *coredir)
194 {
195     if ((!strncmp
196          (AFSDIR_USR_DIRPATH, AFSDIR_CLIENT_ETC_DIRPATH,
197           strlen(AFSDIR_USR_DIRPATH)))
198         ||
199         (!strncmp
200          (AFSDIR_USR_DIRPATH, AFSDIR_SERVER_BIN_DIRPATH,
201           strlen(AFSDIR_USR_DIRPATH)))) {
202         MakeDir(AFSDIR_USR_DIRPATH);
203     }
204     if (!strncmp
205         (AFSDIR_SERVER_AFS_DIRPATH, AFSDIR_SERVER_BIN_DIRPATH,
206          strlen(AFSDIR_SERVER_AFS_DIRPATH))) {
207         MakeDir(AFSDIR_SERVER_AFS_DIRPATH);
208     }
209     MakeDir(AFSDIR_SERVER_BIN_DIRPATH);
210     MakeDir(AFSDIR_SERVER_ETC_DIRPATH);
211     MakeDir(AFSDIR_SERVER_LOCAL_DIRPATH);
212     MakeDir(AFSDIR_SERVER_DB_DIRPATH);
213     MakeDir(AFSDIR_SERVER_LOGS_DIRPATH);
214 #ifndef AFS_NT40_ENV
215     if (!strncmp
216         (AFSDIR_CLIENT_VICE_DIRPATH, AFSDIR_CLIENT_ETC_DIRPATH,
217          strlen(AFSDIR_CLIENT_VICE_DIRPATH))) {
218         MakeDir(AFSDIR_CLIENT_VICE_DIRPATH);
219     }
220     MakeDir(AFSDIR_CLIENT_ETC_DIRPATH);
221
222     symlink(AFSDIR_SERVER_THISCELL_FILEPATH, AFSDIR_CLIENT_THISCELL_FILEPATH);
223     symlink(AFSDIR_SERVER_CELLSERVDB_FILEPATH,
224             AFSDIR_CLIENT_CELLSERVDB_FILEPATH);
225 #endif /* AFS_NT40_ENV */
226     if (coredir)
227         MakeDir(coredir);
228     return 0;
229 }
230
231 /* strip the \\n from the end of the line, if it is present */
232 static int
233 StripLine(char *abuffer)
234 {
235     char *tp;
236
237     tp = abuffer + strlen(abuffer);     /* starts off pointing at the null  */
238     if (tp == abuffer)
239         return 0;               /* null string, no last character to check */
240     tp--;                       /* aim at last character */
241     if (*tp == '\n')
242         *tp = 0;
243     return 0;
244 }
245
246 /* write one bnode's worth of entry into the file */
247 static int
248 bzwrite(struct bnode *abnode, void *arock)
249 {
250     struct bztemp *at = (struct bztemp *)arock;
251     int i;
252     char tbuffer[BOZO_BSSIZE];
253     afs_int32 code;
254
255     if (abnode->notifier)
256         fprintf(at->file, "bnode %s %s %d %s\n", abnode->type->name,
257                 abnode->name, abnode->fileGoal, abnode->notifier);
258     else
259         fprintf(at->file, "bnode %s %s %d\n", abnode->type->name,
260                 abnode->name, abnode->fileGoal);
261     for (i = 0;; i++) {
262         code = bnode_GetParm(abnode, i, tbuffer, BOZO_BSSIZE);
263         if (code) {
264             if (code != BZDOM)
265                 return code;
266             break;
267         }
268         fprintf(at->file, "parm %s\n", tbuffer);
269     }
270     fprintf(at->file, "end\n");
271     return 0;
272 }
273
274 #define MAXPARMS    20
275 int
276 ReadBozoFile(char *aname)
277 {
278     FILE *tfile;
279     char tbuffer[BOZO_BSSIZE];
280     char *tp;
281     char *instp, *typep, *notifier, *notp;
282     afs_int32 code;
283     afs_int32 ktmask, ktday, kthour, ktmin, ktsec;
284     afs_int32 i, goal;
285     struct bnode *tb;
286     char *parms[MAXPARMS];
287     char *thisparms[MAXPARMS];
288     int rmode;
289
290     /* rename BozoInit to BosServer for the user */
291     if (!aname) {
292         /* if BozoInit exists and BosConfig doesn't, try a rename */
293         if (access(AFSDIR_SERVER_BOZINIT_FILEPATH, 0) == 0
294             && access(AFSDIR_SERVER_BOZCONF_FILEPATH, 0) != 0) {
295             code =
296                 renamefile(AFSDIR_SERVER_BOZINIT_FILEPATH,
297                            AFSDIR_SERVER_BOZCONF_FILEPATH);
298             if (code < 0)
299                 perror("bosconfig rename");
300         }
301         if (access(AFSDIR_SERVER_BOZCONFNEW_FILEPATH, 0) == 0) {
302             code =
303                 renamefile(AFSDIR_SERVER_BOZCONFNEW_FILEPATH,
304                            AFSDIR_SERVER_BOZCONF_FILEPATH);
305             if (code < 0)
306                 perror("bosconfig rename");
307         }
308     }
309
310     /* don't do server restarts by default */
311     bozo_nextRestartKT.mask = KTIME_NEVER;
312     bozo_nextRestartKT.hour = 0;
313     bozo_nextRestartKT.min = 0;
314     bozo_nextRestartKT.day = 0;
315
316     /* restart processes at 5am if their binaries have changed */
317     bozo_nextDayKT.mask = KTIME_HOUR | KTIME_MIN;
318     bozo_nextDayKT.hour = 5;
319     bozo_nextDayKT.min = 0;
320
321     for (code = 0; code < MAXPARMS; code++)
322         parms[code] = NULL;
323     tfile = (FILE *) 0;
324     if (!aname)
325         aname = (char *)bozo_fileName;
326     tfile = fopen(aname, "r");
327     if (!tfile)
328         return 0;               /* -1 */
329     instp = malloc(BOZO_BSSIZE);
330     typep = malloc(BOZO_BSSIZE);
331     notifier = notp = malloc(BOZO_BSSIZE);
332     while (1) {
333         /* ok, read lines giving parms and such from the file */
334         tp = fgets(tbuffer, sizeof(tbuffer), tfile);
335         if (tp == (char *)0)
336             break;              /* all done */
337
338         if (strncmp(tbuffer, "restarttime", 11) == 0) {
339             code =
340                 sscanf(tbuffer, "restarttime %d %d %d %d %d", &ktmask, &ktday,
341                        &kthour, &ktmin, &ktsec);
342             if (code != 5) {
343                 code = -1;
344                 goto fail;
345             }
346             /* otherwise we've read in the proper ktime structure; now assign
347              * it and continue processing */
348             bozo_nextRestartKT.mask = ktmask;
349             bozo_nextRestartKT.day = ktday;
350             bozo_nextRestartKT.hour = kthour;
351             bozo_nextRestartKT.min = ktmin;
352             bozo_nextRestartKT.sec = ktsec;
353             continue;
354         }
355
356         if (strncmp(tbuffer, "checkbintime", 12) == 0) {
357             code =
358                 sscanf(tbuffer, "checkbintime %d %d %d %d %d", &ktmask,
359                        &ktday, &kthour, &ktmin, &ktsec);
360             if (code != 5) {
361                 code = -1;
362                 goto fail;
363             }
364             /* otherwise we've read in the proper ktime structure; now assign
365              * it and continue processing */
366             bozo_nextDayKT.mask = ktmask;       /* time to restart the system */
367             bozo_nextDayKT.day = ktday;
368             bozo_nextDayKT.hour = kthour;
369             bozo_nextDayKT.min = ktmin;
370             bozo_nextDayKT.sec = ktsec;
371             continue;
372         }
373
374         if (strncmp(tbuffer, "restrictmode", 12) == 0) {
375             code = sscanf(tbuffer, "restrictmode %d", &rmode);
376             if (code != 1) {
377                 code = -1;
378                 goto fail;
379             }
380             if (rmode != 0 && rmode != 1) {
381                 code = -1;
382                 goto fail;
383             }
384             bozo_isrestricted = rmode;
385             continue;
386         }
387
388         if (strncmp("bnode", tbuffer, 5) != 0) {
389             code = -1;
390             goto fail;
391         }
392         notifier = notp;
393         code =
394             sscanf(tbuffer, "bnode %s %s %d %s", typep, instp, &goal,
395                    notifier);
396         if (code < 3) {
397             code = -1;
398             goto fail;
399         } else if (code == 3)
400             notifier = NULL;
401
402         memset(thisparms, 0, sizeof(thisparms));
403
404         for (i = 0; i < MAXPARMS; i++) {
405             /* now read the parms, until we see an "end" line */
406             tp = fgets(tbuffer, sizeof(tbuffer), tfile);
407             if (!tp) {
408                 code = -1;
409                 goto fail;
410             }
411             StripLine(tbuffer);
412             if (!strncmp(tbuffer, "end", 3))
413                 break;
414             if (strncmp(tbuffer, "parm ", 5)) {
415                 code = -1;
416                 goto fail;      /* no "parm " either */
417             }
418             if (!parms[i])      /* make sure there's space */
419                 parms[i] = (char *)malloc(BOZO_BSSIZE);
420             strcpy(parms[i], tbuffer + 5);      /* remember the parameter for later */
421             thisparms[i] = parms[i];
422         }
423
424         /* ok, we have the type and parms, now create the object */
425         code =
426             bnode_Create(typep, instp, &tb, thisparms[0], thisparms[1],
427                          thisparms[2], thisparms[3], thisparms[4], notifier,
428                          goal ? BSTAT_NORMAL : BSTAT_SHUTDOWN, 0);
429         if (code)
430             goto fail;
431
432         /* bnode created in 'temporarily shutdown' state;
433          * check to see if we are supposed to run this guy,
434          * and if so, start the process up */
435         if (goal) {
436             bnode_SetStat(tb, BSTAT_NORMAL);    /* set goal, taking effect immediately */
437         } else {
438             bnode_SetStat(tb, BSTAT_SHUTDOWN);
439         }
440     }
441     /* all done */
442     code = 0;
443
444   fail:
445     if (instp)
446         free(instp);
447     if (typep)
448         free(typep);
449     for (i = 0; i < MAXPARMS; i++)
450         if (parms[i])
451             free(parms[i]);
452     if (tfile)
453         fclose(tfile);
454     return code;
455 }
456
457 /* write a new bozo file */
458 int
459 WriteBozoFile(char *aname)
460 {
461     FILE *tfile;
462     char tbuffer[AFSDIR_PATH_MAX];
463     afs_int32 code;
464     struct bztemp btemp;
465
466     if (!aname)
467         aname = (char *)bozo_fileName;
468     strcpy(tbuffer, aname);
469     strcat(tbuffer, ".NBZ");
470     tfile = fopen(tbuffer, "w");
471     if (!tfile)
472         return -1;
473     btemp.file = tfile;
474
475     fprintf(tfile, "restrictmode %d\n", bozo_isrestricted);
476     fprintf(tfile, "restarttime %d %d %d %d %d\n", bozo_nextRestartKT.mask,
477             bozo_nextRestartKT.day, bozo_nextRestartKT.hour,
478             bozo_nextRestartKT.min, bozo_nextRestartKT.sec);
479     fprintf(tfile, "checkbintime %d %d %d %d %d\n", bozo_nextDayKT.mask,
480             bozo_nextDayKT.day, bozo_nextDayKT.hour, bozo_nextDayKT.min,
481             bozo_nextDayKT.sec);
482     code = bnode_ApplyInstance(bzwrite, &btemp);
483     if (code || (code = ferror(tfile))) {       /* something went wrong */
484         fclose(tfile);
485         unlink(tbuffer);
486         return code;
487     }
488     /* close the file, check for errors and snap new file into place */
489     if (fclose(tfile) == EOF) {
490         unlink(tbuffer);
491         return -1;
492     }
493     code = renamefile(tbuffer, aname);
494     if (code) {
495         unlink(tbuffer);
496         return -1;
497     }
498     return 0;
499 }
500
501 static int
502 bdrestart(struct bnode *abnode, void *arock)
503 {
504     afs_int32 code;
505
506     if (abnode->fileGoal != BSTAT_NORMAL || abnode->goal != BSTAT_NORMAL)
507         return 0;               /* don't restart stopped bnodes */
508     bnode_Hold(abnode);
509     code = bnode_RestartP(abnode);
510     if (code) {
511         /* restart the dude */
512         bnode_SetStat(abnode, BSTAT_SHUTDOWN);
513         bnode_WaitStatus(abnode, BSTAT_SHUTDOWN);
514         bnode_SetStat(abnode, BSTAT_NORMAL);
515     }
516     bnode_Release(abnode);
517     return 0;                   /* keep trying all bnodes */
518 }
519
520 #define BOZO_MINSKIP 3600       /* minimum to advance clock */
521 /* lwp to handle system restarts */
522 static void *
523 BozoDaemon(void *unused)
524 {
525     afs_int32 now;
526
527     /* now initialize the values */
528     bozo_newKTs = 1;
529     while (1) {
530         IOMGR_Sleep(60);
531         now = FT_ApproxTime();
532
533         if (bozo_restdisable) {
534             bozo_Log("Restricted mode disabled by signal\n");
535             bozo_restdisable = 0;
536         }
537
538         if (bozo_newKTs) {      /* need to recompute restart times */
539             bozo_newKTs = 0;    /* done for a while */
540             nextRestart = ktime_next(&bozo_nextRestartKT, BOZO_MINSKIP);
541             nextDay = ktime_next(&bozo_nextDayKT, BOZO_MINSKIP);
542         }
543
544         /* see if we should do a restart */
545         if (now > nextRestart) {
546             SBOZO_ReBozo(0);    /* doesn't come back */
547         }
548
549         /* see if we should restart a server */
550         if (now > nextDay) {
551             nextDay = ktime_next(&bozo_nextDayKT, BOZO_MINSKIP);
552
553             /* call the bnode restartp function, and restart all that require it */
554             bnode_ApplyInstance(bdrestart, 0);
555         }
556     }
557     return NULL;
558 }
559
560 #ifdef AFS_AIX32_ENV
561 static int
562 tweak_config(void)
563 {
564     FILE *f;
565     char c[80];
566     int s, sb_max, ipfragttl;
567
568     sb_max = 131072;
569     ipfragttl = 20;
570     f = popen("/usr/sbin/no -o sb_max", "r");
571     s = fscanf(f, "sb_max = %d", &sb_max);
572     fclose(f);
573     if (s < 1)
574         return;
575     f = popen("/usr/sbin/no -o ipfragttl", "r");
576     s = fscanf(f, "ipfragttl = %d", &ipfragttl);
577     fclose(f);
578     if (s < 1)
579         ipfragttl = 20;
580
581     if (sb_max < 131072)
582         sb_max = 131072;
583     if (ipfragttl > 20)
584         ipfragttl = 20;
585
586     sprintf(c, "/usr/sbin/no -o sb_max=%d -o ipfragttl=%d", sb_max,
587             ipfragttl);
588     f = popen(c, "r");
589     fclose(f);
590 }
591 #endif
592
593 #if 0
594 /*
595  * This routine causes the calling process to go into the background and
596  * to lose its controlling tty.
597  *
598  * It does not close or otherwise alter the standard file descriptors.
599  *
600  * It writes warning messages to the standard error output if certain
601  * fundamental errors occur.
602  *
603  * This routine requires
604  *
605  * #include <sys/types.h>
606  * #include <sys/stat.h>
607  * #include <fcntl.h>
608  * #include <unistd.h>
609  * #include <stdlib.h>
610  *
611  * and has been tested on:
612  *
613  * AIX 4.2
614  * Digital Unix 4.0D
615  * HP-UX 11.0
616  * IRIX 6.5
617  * Linux 2.1.125
618  * Solaris 2.5
619  * Solaris 2.6
620  */
621
622 #ifndef AFS_NT40_ENV
623 static void
624 background(void)
625 {
626     /*
627      * A process is a process group leader if its process ID
628      * (getpid()) and its process group ID (getpgrp()) are the same.
629      */
630
631     /*
632      * To create a new session (and thereby lose our controlling
633      * terminal) we cannot be a process group leader.
634      *
635      * To guarantee we are not a process group leader, we fork and
636      * let the parent process exit.
637      */
638
639     if (getpid() == getpgrp()) {
640         pid_t pid;
641         pid = fork();
642         switch (pid) {
643         case -1:
644             abort();            /* leave footprints */
645             break;
646         case 0:         /* child */
647             break;
648         default:                /* parent */
649             exit(0);
650             break;
651         }
652     }
653
654     /*
655      * By here, we are not a process group leader, so we can make a
656      * new session and become the session leader.
657      */
658
659     {
660         pid_t sid = setsid();
661
662         if (sid == -1) {
663             static char err[] = "bosserver: WARNING: setsid() failed\n";
664             write(STDERR_FILENO, err, sizeof err - 1);
665         }
666     }
667
668     /*
669      * Once we create a new session, the current process is a
670      * session leader without a controlling tty.
671      *
672      * On some systems, the first tty device the session leader
673      * opens automatically becomes the controlling tty for the
674      * session.
675      *
676      * So, to guarantee we do not acquire a controlling tty, we fork
677      * and let the parent process exit.  The child process is not a
678      * session leader, and so it will not acquire a controlling tty
679      * even if it should happen to open a tty device.
680      */
681
682     if (getpid() == getpgrp()) {
683         pid_t pid;
684         pid = fork();
685         switch (pid) {
686         case -1:
687             abort();            /* leave footprints */
688             break;
689         case 0:         /* child */
690             break;
691         default:                /* parent */
692             exit(0);
693             break;
694         }
695     }
696
697     /*
698      * check that we no longer have a controlling tty
699      */
700
701     {
702         int fd;
703
704         fd = open("/dev/tty", O_RDONLY);
705
706         if (fd >= 0) {
707             static char err[] =
708                 "bosserver: WARNING: /dev/tty still attached\n";
709             close(fd);
710             write(STDERR_FILENO, err, sizeof err - 1);
711         }
712     }
713 }
714 #endif /* ! AFS_NT40_ENV */
715 #endif
716
717 /* start a process and monitor it */
718
719 #include "AFS_component_version_number.c"
720
721 int
722 main(int argc, char **argv, char **envp)
723 {
724     struct rx_service *tservice;
725     afs_int32 code;
726     struct afsconf_dir *tdir;
727     int noAuth = 0;
728     int i;
729     char namebuf[AFSDIR_PATH_MAX];
730     int rxMaxMTU = -1;
731     afs_uint32 host = htonl(INADDR_ANY);
732     char *auditFileName = NULL;
733     struct rx_securityClass **securityClasses;
734     afs_int32 numClasses;
735 #ifndef AFS_NT40_ENV
736     int nofork = 0;
737     struct stat sb;
738 #endif
739 #ifdef  AFS_AIX32_ENV
740     struct sigaction nsa;
741
742     /* for some reason, this permits user-mode RX to run a lot faster.
743      * we do it here in the bosserver, so we don't have to do it
744      * individually in each server.
745      */
746     tweak_config();
747
748     /*
749      * The following signal action for AIX is necessary so that in case of a
750      * crash (i.e. core is generated) we can include the user's data section
751      * in the core dump. Unfortunately, by default, only a partial core is
752      * generated which, in many cases, isn't too useful.
753      */
754     sigemptyset(&nsa.sa_mask);
755     nsa.sa_handler = SIG_DFL;
756     nsa.sa_flags = SA_FULLDUMP;
757     sigaction(SIGSEGV, &nsa, NULL);
758     sigaction(SIGABRT, &nsa, NULL);
759 #endif
760     osi_audit_init();
761     signal(SIGFPE, bozo_insecureme);
762
763 #ifdef AFS_NT40_ENV
764     /* Initialize winsock */
765     if (afs_winsockInit() < 0) {
766         ReportErrorEventAlt(AFSEVT_SVR_WINSOCK_INIT_FAILED, 0, argv[0], 0);
767         fprintf(stderr, "%s: Couldn't initialize winsock.\n", argv[0]);
768         exit(2);
769     }
770 #endif
771
772     /* Initialize dirpaths */
773     if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
774 #ifdef AFS_NT40_ENV
775         ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0);
776 #endif
777         fprintf(stderr, "%s: Unable to obtain AFS server directory.\n",
778                 argv[0]);
779         exit(2);
780     }
781
782     /* some path inits */
783     bozo_fileName = AFSDIR_SERVER_BOZCONF_FILEPATH;
784     DoCore = AFSDIR_SERVER_LOGS_DIRPATH;
785
786     /* initialize the list of dirpaths that the bosserver has
787      * an interest in monitoring */
788     initBosEntryStats();
789
790 #if defined(AFS_SGI_ENV)
791     /* offer some protection if AFS isn't loaded */
792     if (syscall(AFS_SYSCALL, AFSOP_ENDLOG) < 0 && errno == ENOPKG) {
793         printf("bosserver: AFS doesn't appear to be configured in O.S..\n");
794         exit(1);
795     }
796 #endif
797
798     /* parse cmd line */
799     for (code = 1; code < argc; code++) {
800         if (strcmp(argv[code], "-noauth") == 0) {
801             /* set noauth flag */
802             noAuth = 1;
803         } else if (strcmp(argv[code], "-log") == 0) {
804             /* set extra logging flag */
805             DoLogging = 1;
806         }
807 #ifndef AFS_NT40_ENV
808         else if (strcmp(argv[code], "-syslog") == 0) {
809             /* set syslog logging flag */
810             DoSyslog = 1;
811         } else if (strncmp(argv[code], "-syslog=", 8) == 0) {
812             DoSyslog = 1;
813             DoSyslogFacility = atoi(argv[code] + 8);
814         } else if (strncmp(argv[code], "-cores=", 7) == 0) {
815             if (strcmp((argv[code]+7), "none") == 0)
816                 DoCore = 0;
817             else
818                 DoCore = (argv[code]+7);
819         } else if (strcmp(argv[code], "-nofork") == 0) {
820             nofork = 1;
821         }
822 #endif
823         else if (strcmp(argv[code], "-enable_peer_stats") == 0) {
824             rx_enablePeerRPCStats();
825         } else if (strcmp(argv[code], "-enable_process_stats") == 0) {
826             rx_enableProcessRPCStats();
827         }
828         else if (strcmp(argv[code], "-restricted") == 0) {
829             bozo_isrestricted = 1;
830         }
831         else if (strcmp(argv[code], "-rxbind") == 0) {
832             rxBind = 1;
833         }
834         else if (strcmp(argv[code], "-allow-dotted-principals") == 0) {
835             rxkadDisableDotCheck = 1;
836         }
837         else if (!strcmp(argv[code], "-rxmaxmtu")) {
838             if ((code + 1) >= argc) {
839                 fprintf(stderr, "missing argument for -rxmaxmtu\n");
840                 exit(1);
841             }
842             rxMaxMTU = atoi(argv[++code]);
843             if ((rxMaxMTU < RX_MIN_PACKET_SIZE) ||
844                 (rxMaxMTU > RX_MAX_PACKET_DATA_SIZE)) {
845                 printf("rxMaxMTU %d invalid; must be between %d-%" AFS_SIZET_FMT "\n",
846                         rxMaxMTU, RX_MIN_PACKET_SIZE,
847                         RX_MAX_PACKET_DATA_SIZE);
848                 exit(1);
849             }
850         }
851         else if (strcmp(argv[code], "-auditlog") == 0) {
852             auditFileName = argv[++code];
853
854         } else if (strcmp(argv[code], "-audit-interface") == 0) {
855             char *interface = argv[++code];
856
857             if (osi_audit_interface(interface)) {
858                 printf("Invalid audit interface '%s'\n", interface);
859                 exit(1);
860             }
861         }
862         else {
863
864             /* hack to support help flag */
865
866 #ifndef AFS_NT40_ENV
867             printf("Usage: bosserver [-noauth] [-log] "
868                    "[-auditlog <log path>] "
869                    "[-audit-interafce <file|sysvmq> (default is file)] "
870                    "[-rxmaxmtu <bytes>] [-rxbind] [-allow-dotted-principals]"
871                    "[-syslog[=FACILITY]] "
872                    "[-enable_peer_stats] [-enable_process_stats] "
873                    "[-cores=<none|path>] \n"
874                    "[-nofork] " "[-help]\n");
875 #else
876             printf("Usage: bosserver [-noauth] [-log] "
877                    "[-auditlog <log path>] "
878                    "[-audit-interafce <file|sysvmq> (default is file)] "
879                    "[-rxmaxmtu <bytes>] [-rxbind] [-allow-dotted-principals]"
880                    "[-enable_peer_stats] [-enable_process_stats] "
881                    "[-cores=<none|path>] \n"
882                    "[-help]\n");
883 #endif
884             fflush(stdout);
885
886             exit(0);
887         }
888     }
889     if (auditFileName) {
890         osi_audit_file(auditFileName);
891     }
892
893 #ifndef AFS_NT40_ENV
894     if (geteuid() != 0) {
895         printf("bosserver: must be run as root.\n");
896         exit(1);
897     }
898 #endif
899
900     code = bnode_Init();
901     if (code) {
902         printf("bosserver: could not init bnode package, code %d\n", code);
903         exit(1);
904     }
905
906     bnode_Register("fs", &fsbnode_ops, 3);
907     bnode_Register("dafs", &dafsbnode_ops, 4);
908     bnode_Register("simple", &ezbnode_ops, 1);
909     bnode_Register("cron", &cronbnode_ops, 2);
910
911     /* create useful dirs */
912     CreateDirs(DoCore);
913
914     /* chdir to AFS log directory */
915     if (DoCore)
916         chdir(DoCore);
917     else
918         chdir(AFSDIR_SERVER_LOGS_DIRPATH);
919
920 #if 0
921     fputs(AFS_GOVERNMENT_MESSAGE, stdout);
922     fflush(stdout);
923 #endif
924
925     /* go into the background and remove our controlling tty, close open
926        file desriptors
927      */
928
929 #ifndef AFS_NT40_ENV
930     if (!nofork)
931         daemon(1, 0);
932 #endif /* ! AFS_NT40_ENV */
933
934     if ((!DoSyslog)
935 #ifndef AFS_NT40_ENV
936         && ((lstat(AFSDIR_BOZLOG_FILE, &sb) == 0) &&
937         !(S_ISFIFO(sb.st_mode)))
938 #endif
939         ) {
940         strcpy(namebuf, AFSDIR_BOZLOG_FILE);
941         strcat(namebuf, ".old");
942         renamefile(AFSDIR_BOZLOG_FILE, namebuf);        /* try rename first */
943         bozo_logFile = fopen(AFSDIR_BOZLOG_FILE, "a");
944         if (!bozo_logFile) {
945             printf("bosserver: can't initialize log file (%s).\n",
946                    AFSDIR_SERVER_BOZLOG_FILEPATH);
947             exit(1);
948         }
949         /* keep log closed normally, so can be removed */
950         fclose(bozo_logFile);
951     } else {
952 #ifndef AFS_NT40_ENV
953         openlog("bosserver", LOG_PID, DoSyslogFacility);
954 #endif
955     }
956
957 #if defined(RLIMIT_CORE) && defined(HAVE_GETRLIMIT)
958     {
959       struct rlimit rlp;
960       getrlimit(RLIMIT_CORE, &rlp);
961       if (!DoCore)
962           rlp.rlim_cur = 0;
963       else
964           rlp.rlim_max = rlp.rlim_cur = RLIM_INFINITY;
965       setrlimit(RLIMIT_CORE, &rlp);
966       getrlimit(RLIMIT_CORE, &rlp);
967       bozo_Log("Core limits now %d %d\n",(int)rlp.rlim_cur,(int)rlp.rlim_max);
968     }
969 #endif
970
971     /* Write current state of directory permissions to log file */
972     DirAccessOK();
973
974     if (rxBind) {
975         afs_int32 ccode;
976         if (AFSDIR_SERVER_NETRESTRICT_FILEPATH ||
977             AFSDIR_SERVER_NETINFO_FILEPATH) {
978             char reason[1024];
979             ccode = parseNetFiles(SHostAddrs, NULL, NULL,
980                                   ADDRSPERSITE, reason,
981                                   AFSDIR_SERVER_NETINFO_FILEPATH,
982                                   AFSDIR_SERVER_NETRESTRICT_FILEPATH);
983         } else {
984             ccode = rx_getAllAddr(SHostAddrs, ADDRSPERSITE);
985         }
986         if (ccode == 1)
987             host = SHostAddrs[0];
988     }
989
990     for (i = 0; i < 10; i++) {
991         if (rxBind) {
992             code = rx_InitHost(host, htons(AFSCONF_NANNYPORT));
993         } else {
994             code = rx_Init(htons(AFSCONF_NANNYPORT));
995         }
996         if (code) {
997             bozo_Log("can't initialize rx: code=%d\n", code);
998             sleep(3);
999         } else
1000             break;
1001     }
1002     if (i >= 10) {
1003         bozo_Log("Bos giving up, can't initialize rx\n");
1004         exit(code);
1005     }
1006
1007     code = LWP_CreateProcess(BozoDaemon, BOZO_LWP_STACKSIZE, /* priority */ 1,
1008                              /* param */ NULL , "bozo-the-clown",
1009                              &bozo_pid);
1010
1011     /* try to read the key from the config file */
1012     tdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
1013     if (!tdir) {
1014         /* try to create local cell config file */
1015         struct afsconf_cell tcell;
1016         strcpy(tcell.name, "localcell");
1017         tcell.numServers = 1;
1018         code = gethostname(tcell.hostName[0], MAXHOSTCHARS);
1019         if (code) {
1020             bozo_Log("failed to get hostname, code %d\n", errno);
1021             exit(1);
1022         }
1023         if (tcell.hostName[0][0] == 0) {
1024             bozo_Log("host name not set, can't start\n");
1025             bozo_Log("try the 'hostname' command\n");
1026             exit(1);
1027         }
1028         memset(tcell.hostAddr, 0, sizeof(tcell.hostAddr));      /* not computed */
1029         code =
1030             afsconf_SetCellInfo(bozo_confdir, AFSDIR_SERVER_ETC_DIRPATH,
1031                                 &tcell);
1032         if (code) {
1033             bozo_Log
1034                 ("could not create cell database in '%s' (code %d), quitting\n",
1035                  AFSDIR_SERVER_ETC_DIRPATH, code);
1036             exit(1);
1037         }
1038         tdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
1039         if (!tdir) {
1040             bozo_Log
1041                 ("failed to open newly-created cell database, quitting\n");
1042             exit(1);
1043         }
1044     }
1045
1046     /* read init file, starting up programs */
1047     if ((code = ReadBozoFile(0))) {
1048         bozo_Log
1049             ("bosserver: Something is wrong (%d) with the bos configuration file %s; aborting\n",
1050              code, AFSDIR_SERVER_BOZCONF_FILEPATH);
1051         exit(code);
1052     }
1053
1054     /* opened the cell databse */
1055     bozo_confdir = tdir;
1056
1057     /* allow super users to manage RX statistics */
1058     rx_SetRxStatUserOk(bozo_rxstat_userok);
1059
1060     afsconf_SetNoAuthFlag(tdir, noAuth);
1061     afsconf_BuildServerSecurityObjects(tdir, &securityClasses, &numClasses);
1062
1063     /* Disable jumbograms */
1064     rx_SetNoJumbo();
1065
1066     if (rxMaxMTU != -1) {
1067         rx_SetMaxMTU(rxMaxMTU);
1068     }
1069
1070     tservice = rx_NewServiceHost(host, 0, /* service id */ 1,
1071                                  "bozo", securityClasses, numClasses,
1072                                  BOZO_ExecuteRequest);
1073     rx_SetMinProcs(tservice, 2);
1074     rx_SetMaxProcs(tservice, 4);
1075     rx_SetStackSize(tservice, BOZO_LWP_STACKSIZE);      /* so gethostbyname works (in cell stuff) */
1076     if (rxkadDisableDotCheck) {
1077         rx_SetSecurityConfiguration(tservice, RXS_CONFIG_FLAGS,
1078                                     (void *)RXS_CONFIG_FLAGS_DISABLE_DOTCHECK);
1079     }
1080
1081     tservice =
1082         rx_NewServiceHost(host, 0, RX_STATS_SERVICE_ID, "rpcstats",
1083                           securityClasses, numClasses, RXSTATS_ExecuteRequest);
1084     rx_SetMinProcs(tservice, 2);
1085     rx_SetMaxProcs(tservice, 4);
1086     rx_StartServer(1);          /* donate this process */
1087     return 0;
1088 }
1089
1090 void
1091 bozo_Log(char *format, ...)
1092 {
1093     char tdate[27];
1094     time_t myTime;
1095     va_list ap;
1096
1097     va_start(ap, format);
1098
1099     if (DoSyslog) {
1100 #ifndef AFS_NT40_ENV
1101         vsyslog(LOG_INFO, format, ap);
1102 #endif
1103     } else {
1104         myTime = time(0);
1105         strcpy(tdate, ctime(&myTime));  /* copy out of static area asap */
1106         tdate[24] = ':';
1107
1108         /* log normally closed, so can be removed */
1109
1110         bozo_logFile = fopen(AFSDIR_SERVER_BOZLOG_FILEPATH, "a");
1111         if (bozo_logFile == NULL) {
1112             printf("bosserver: WARNING: problem with %s\n",
1113                    AFSDIR_SERVER_BOZLOG_FILEPATH);
1114             printf("%s ", tdate);
1115             vprintf(format, ap);
1116             fflush(stdout);
1117         } else {
1118             fprintf(bozo_logFile, "%s ", tdate);
1119             vfprintf(bozo_logFile, format, ap);
1120
1121             /* close so rm BosLog works */
1122             fclose(bozo_logFile);
1123         }
1124     }
1125 }