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