2 * Copyright 2000, International Business Machines Corporation and others.
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
10 #include <afsconfig.h>
11 #include <afs/param.h>
13 #include <afs/procmgmt.h>
18 #ifdef IGNORE_SOME_GCC_WARNINGS
19 # pragma GCC diagnostic warning "-Wimplicit-function-declaration"
23 #include <WINNT/afsevent.h>
29 #include <rx/rx_globals.h>
33 #include <afs/afsint.h>
34 #include <afs/prs_fs.h>
36 #include <afs/vlserver.h>
39 #include <afs/afsutil.h>
40 #include <afs/cellconfig.h>
42 #include <afs/volser.h>
44 #include <afs/audit.h>
45 #include <afs/com_err.h>
47 #include <afs/tcdata.h>
48 #include <afs/bubasics.h>
49 #include <afs/budb_errs.h>
50 #include <afs/budb_client.h>
51 #include <afs/bucoord_prototypes.h>
53 #include <afs/kautils.h>
56 #include "error_macros.h"
58 #include "butc_xbsa.h"
59 #include "butc_prototypes.h"
60 #include "butc_internal.h"
62 #define N_SECURITY_OBJECTS 3
63 #define ERRCODE_RANGE 8 /* from error_table.h */
65 #define TE_PREFIX "TE"
66 #define TL_PREFIX "TL"
67 #define CFG_PREFIX "CFG"
69 struct ubik_client
*cstruct
;
70 FILE *logIO
, *ErrorlogIO
, *centralLogIO
, *lastLogIO
;
71 char lFile
[AFSDIR_PATH_MAX
];
73 char ErrorlogFile
[256];
74 char lastLogFile
[256];
75 char eFile
[AFSDIR_PATH_MAX
];
76 char tapeConfigFile
[AFSDIR_PATH_MAX
];
77 char pFile
[AFSDIR_PATH_MAX
];
79 struct tapeConfig globalTapeConfig
;
80 struct deviceSyncNode
*deviceLatch
;
81 char globalCellName
[64];
82 char *whoami
= "butc";
84 /* GLOBAL CONFIGURATION PARAMETERS */
100 #define MINGROUPID 0x1
101 #define MAXGROUPID 0x7FFFFFFF
102 afs_int32 statusSize
;
104 #define MAXSTATUS 0x7fffffff
105 afs_int32 BufferSize
; /* Size in B stored for data */
106 char *centralLogFile
;
107 afs_int32 lastLog
; /* Log last pass info */
109 struct afsconf_dir
*butc_confdir
;
110 int allow_unauth
= 0;
112 #define ADDRSPERSITE 16 /* Same global is in rx/rx_user.c */
113 afs_uint32 SHostAddrs
[ADDRSPERSITE
];
122 while ((tc
= *anum
)) {
123 if (tc
< '0' || tc
> '9')
133 * Convert a string into an afs_int32.
134 * Returned afs_int32 is in Bytes, Kb, Mb, Gb, or Tb. Based on crunit char.
135 * This routine only converts unsigned float values.
136 * The returned value is a whole number.
138 * numstring - text string to be converted.
139 * crunit - value returned in 'B', 'K', 'M', 'G', 'T'.
140 * ' ' or NULL ==> 'B' (bytes).
142 * number - returned value in requested crunit - rounded
143 * to nearest whole number.
146 * -1 - error in conversion
148 * should deal with signed numbers. Should signal error if no digits
152 atocl(char *numstring
, char crunit
, afs_int32
*number
)
161 /* Determine which units to report in */
195 sscanf(numstring
, "%f%c%s", &total
, &cunit
, rest
);
196 if ((count
> 2) || (count
<= 0))
199 cunit
= 'B'; /* bytes */
233 /* Go to correct unit */
234 for (; units
< runits
; units
+= 3)
236 for (; units
> runits
; units
-= 3)
239 total
+= 0.5; /* Round up */
240 if ((total
> 0x7fffffff) || (total
< 0)) /* Don't go over 2G */
247 /* replace last two ocurrences of / by _ */
250 stringReplace(char *name
)
255 pos
= strrchr(name
, '/');
258 pos
= strrchr(name
, '/');
260 strcat(name
, buffer
);
266 stringNowReplace(char *logFile
, char *deviceName
)
269 char storeDevice
[256];
270 int mvFlag
= 0, devPrefLen
;
272 char devPrefix
[] = "\\\\.";
274 char devPrefix
[] = "/dev";
277 devPrefLen
= strlen(devPrefix
);
278 strcpy(storeDevice
, deviceName
);
279 if (strncmp(deviceName
, devPrefix
, devPrefLen
) == 0) {
280 deviceName
+= devPrefLen
;
283 while ((pos
= strchr(deviceName
, devPrefix
[0]))) /* look for / or \ */
285 strcat(logFile
, deviceName
);
286 /* now put back deviceName to the way it was */
288 deviceName
-= devPrefLen
;
290 strcpy(deviceName
, storeDevice
);
297 * get the configuration information for a particular tape device
298 * as specified by the portoffset
300 * filename - full pathname of file containing the tape device
301 * configuration information
302 * config - for return results
303 * portOffset - for which configuration is required
305 * logging not available when this routine is called
306 * caller return value checks
308 * 0 => Found entry with same port, return info in config.
309 * -1 => Error encountered trying to read the file.
310 * 1 => Desired entry does not exist or file does not exist.
315 GetDeviceConfig(char *filename
, struct tapeConfig
*config
, afs_int32 portOffset
)
319 char devName
[LINESIZE
], tcapacity
[LINESIZE
], tfmsize
[LINESIZE
],
324 afs_int32 code
= 0, count
;
326 /* Initialize the config struct */
327 config
->capacity
= 0;
328 config
->fileMarkSize
= 0;
329 config
->portOffset
= portOffset
;
330 strcpy(config
->device
, "");
332 devFile
= fopen(filename
, "r");
336 fprintf(stderr
, "Error %d: Can't open %s\n", errno
, filename
);
340 while (fgets(line
, LINESIZE
- 1, devFile
)) {
342 sscanf(line
, "%s %s %s %u%s\n", tcapacity
, tfmsize
, devName
,
345 if (count
== 4 || count
== 5) {
346 if (atocl(tcapacity
, 'K', &capacity
)) {
348 "tapeconfig: Tape capacity parse error in: %s\n",
352 if (atocl(tfmsize
, 'B', &fmSize
)) {
354 "tapeconfig: File-mark size parse error in: %s\n",
359 count
= sscanf(line
, "%s %u%s\n", devName
, &aport
, trest
);
360 if (count
== 2 || count
== 3) {
361 capacity
= 0x7fffffff;
364 fprintf(stderr
, "tapeconfig: Parse error in: %s\n", line
);
369 if ((aport
< 0) || (aport
> BC_MAXPORTOFFSET
)) {
370 fprintf(stderr
, "tapeconfig: Port offset parse error in: %s\n",
375 if (aport
!= portOffset
)
379 fprintf(stderr
, "Invalid file mark size, %d, in: %s\n", fmSize
,
384 config
->capacity
= capacity
;
385 config
->fileMarkSize
= fmSize
;
386 config
->portOffset
= aport
;
387 strncpy(config
->device
, devName
, 100);
392 /* fprintf(stderr, "Can't find tapeconfig entry for port offset %d\n", portOffset); */
404 GetConfigParams(char *filename
, afs_int32 port
)
408 char line
[LINESIZE
], cmd
[LINESIZE
], value
[LINESIZE
];
412 /* DEFAULT SETTINGS FOR GLOBAL PARAMETERS */
413 dump_namecheck
= 1; /* check tape name on dumps */
414 queryoperator
= 1; /* can question operator */
415 autoQuery
= 1; /* prompt for first tape */
416 isafile
= 0; /* Do not dump to a file */
417 opencallout
= NULL
; /* open callout routine */
418 closecallout
= NULL
; /* close callout routine */
419 tapemounted
= 0; /* tape is not mounted */
421 BufferSize
= (CONF_XBSA
? XBSADFLTBUFFER
: BUTM_BLOCKSIZE
);
422 dumpRestAuthnLevel
= rpc_c_protect_level_default
;
423 xbsaObjectOwner
= NULL
; /* bsaObjectOwner */
424 appObjectOwner
= NULL
; /* appObjectOwner */
425 adsmServerName
= NULL
; /* TSM server name - same as ADSM */
426 xbsaSecToken
= NULL
; /* XBSA sercurity token */
427 xbsalGName
= NULL
; /* XBSA IGName */
429 BufferSize
= BUTM_BLOCKSIZE
;
431 centralLogFile
= NULL
; /* Log for all butcs */
432 centralLogIO
= 0; /* Log for all butcs */
433 statusSize
= 0; /* size before status message */
434 maxpass
= PASSESDFLT
; /* dump passes */
435 lastLog
= 0; /* separate log for last pass */
436 lastLogIO
= 0; /* separate log for last pass */
437 groupId
= 0; /* Group id for multiple dumps */
439 /* Try opening the CFG_<port> file */
440 sprintf(paramFile
, "%s_%d", filename
, port
);
441 devFile
= fopen(paramFile
, "r");
443 /* Set log names to TL_<port>, TL_<port>.lp and TE_<port> */
444 sprintf(logFile
, "%s_%d", lFile
, port
);
445 sprintf(lastLogFile
, "%s_%d.lp", lFile
, port
);
446 sprintf(ErrorlogFile
, "%s_%d", eFile
, port
);
447 } else if (CONF_XBSA
) {
448 /* If configured as XBSA, a configuration file CFG_<port> must exist */
449 printf("Cannot open configuration file %s", paramFile
);
452 /* Try the CFG_<device> name as the device file */
453 strcpy(paramFile
, filename
);
454 stringNowReplace(paramFile
, globalTapeConfig
.device
);
455 /* Set log names to TL_<device>, TL_<device> and TE_<device> */
456 strcpy(logFile
, lFile
);
457 stringNowReplace(logFile
, globalTapeConfig
.device
);
458 strcpy(lastLogFile
, lFile
);
459 stringNowReplace(lastLogFile
, globalTapeConfig
.device
);
460 strcat(lastLogFile
, ".lp");
461 strcpy(ErrorlogFile
, eFile
);
462 stringNowReplace(ErrorlogFile
, globalTapeConfig
.device
);
464 /* Now open the device file */
465 devFile
= fopen(paramFile
, "r");
467 ERROR_EXIT(0); /* CFG file doesn't exist for non-XBSA and that's ok */
470 /* Read each line of the Configuration file */
471 while (fgets(line
, LINESIZE
- 1, devFile
)) {
472 cnt
= sscanf(line
, "%s %s", cmd
, value
);
475 printf("Bad line in %s: %s\n", paramFile
, line
);
479 for (cnt
= 0; cnt
< strlen(cmd
); cnt
++)
480 if (islower(cmd
[cnt
]))
481 cmd
[cnt
] = toupper(cmd
[cnt
]);
483 if (!strcmp(cmd
, "NAME_CHECK")) {
486 ("Warning: The %s parameter is ignored with a Backup Service\n",
491 for (cnt
= 0; cnt
< strlen(value
); cnt
++)
492 if (islower(value
[cnt
]))
493 value
[cnt
] = toupper(value
[cnt
]);
495 if (!strcmp(value
, "NO")) {
496 printf("Dump tape name check is disabled\n");
499 printf("Dump tape name check is enabled\n");
504 else if (!strcmp(cmd
, "MOUNT")) {
507 ("Warning: The %s parameter is ignored with a Backup Service\n",
512 opencallout
= strdup(value
);
513 printf("Tape mount callout routine is %s\n", opencallout
);
516 else if (!strcmp(cmd
, "UNMOUNT")) {
519 ("Warning: The %s parameter is ignored with a Backup Service\n",
524 closecallout
= strdup(value
);
525 printf("Tape unmount callout routine is %s\n", closecallout
);
528 else if (!strcmp(cmd
, "ASK")) {
529 for (cnt
= 0; cnt
< strlen(value
); cnt
++)
530 if (islower(value
[cnt
]))
531 value
[cnt
] = toupper(value
[cnt
]);
533 if (!strcmp(value
, "NO")) {
534 printf("Operator queries are disabled\n");
537 printf("Operator queries are enabled\n");
542 else if (!strcmp(cmd
, "FILE")) {
545 ("Warning: The %s parameter is ignored with a Backup Service\n",
550 for (cnt
= 0; cnt
< strlen(value
); cnt
++)
551 if (islower(value
[cnt
]))
552 value
[cnt
] = toupper(value
[cnt
]);
554 if (!strcmp(value
, "YES")) {
555 printf("Will dump to a file\n");
558 printf("Will not dump to a file\n");
563 else if (!strcmp(cmd
, "AUTOQUERY")) {
566 ("Warning: The %s parameter is ignored with a Backup Service\n",
571 for (cnt
= 0; cnt
< strlen(value
); cnt
++)
572 if (islower(value
[cnt
]))
573 value
[cnt
] = toupper(value
[cnt
]);
575 if (!strcmp(value
, "NO")) {
576 printf("Auto query is disabled\n");
579 printf("Auto query is enabled\n");
584 else if (!strcmp(cmd
, "BUFFERSIZE")) {
586 afs_int32 tapeblocks
;
589 if (atocl(value
, 'K', &size
)) {
590 fprintf(stderr
, "BUFFERSIZE parse error\n");
594 /* A tapeblock is 16KB. Determine # of tapeblocks. Then
595 * determine BufferSize needed for that many tapeblocks.
597 tapeblocks
= size
/ 16;
600 printf("BUFFERSIZE is %u KBytes\n", (tapeblocks
* 16));
601 BufferSize
= tapeblocks
* BUTM_BLOCKSIZE
;
604 if (atocl(value
, 'B', &size
)) {
605 fprintf(stderr
, "BUFFERSIZE parse error\n");
608 if (size
< XBSAMINBUFFER
)
609 size
= XBSAMINBUFFER
;
610 if (size
> XBSAMAXBUFFER
)
611 size
= XBSAMAXBUFFER
;
612 printf("XBSA buffer size is %u Bytes\n", size
);
618 /* All the xbsa spacific parameters */
619 else if (!strcmp(cmd
, "TYPE") || !strcmp(cmd
, "NODE")
620 || !strcmp(cmd
, "SERVER") || !strcmp(cmd
, "PASSWORD")
621 || !strcmp(cmd
, "PASSFILE") || !strcmp(cmd
, "MGMTCLASS")) {
622 printf("This binary does not have XBSA support\n");
626 else if (!strcmp(cmd
, "TYPE")) { /* required for XBSA */
629 ("Warning: The %s parameter is ignored with a tape drive\n",
634 for (cnt
= 0; (size_t) cnt
< strlen(value
); cnt
++)
635 if (islower(value
[cnt
]))
636 value
[cnt
] = toupper(value
[cnt
]);
638 if (strcmp(value
, "TSM") == 0) {
639 xbsaType
= XBSA_SERVER_TYPE_ADSM
; /* Known XBSA server type */
641 printf("Configuration file error, %s %s is not recognized\n",
643 xbsaType
= XBSA_SERVER_TYPE_UNKNOWN
;
645 printf("XBSA type is %s\n",
647 XBSA_SERVER_TYPE_UNKNOWN
) ? "Unknown" : value
));
650 else if (!strcmp(cmd
, "NODE")) {
653 ("Warning: The %s parameter is ignored with a tape drive\n",
657 xbsaObjectOwner
= strdup(value
);
658 printf("XBSA node is %s\n", xbsaObjectOwner
);
661 else if (!strcmp(cmd
, "SERVER")) { /* required for XBSA */
664 ("Warning: The %s parameter is ignored with a tape drive\n",
668 adsmServerName
= strdup(value
);
669 printf("XBSA server is %s\n", adsmServerName
);
672 else if (!strcmp(cmd
, "PASSWORD")) { /* This or PASSFILE required for XBSA */
675 ("Warning: The %s parameter is ignored with a tape drive\n",
681 ("Warning: The %s parameter is ignored. Already read password\n",
686 xbsaSecToken
= strdup(value
);
687 printf("XBSA Password has been read\n");
690 else if (!strcmp(cmd
, "PASSFILE")) { /* This or PASSWORD required for XBSA */
694 ("Warning: The %s parameter is ignored with a tape drive\n",
700 ("Warning: The %s parameter is ignored. Already read password\n",
705 pwdFile
= fopen(value
, "r");
708 ("Configuration file error, cannot open password file %s\n",
712 xbsaSecToken
= malloc(LINESIZE
);
713 if (!fscanf(pwdFile
, "%s", xbsaSecToken
)) {
715 ("Configuration file error, cannot read password file %s\n",
719 printf("XBSA password retrieved from password file\n");
722 else if (!strcmp(cmd
, "MGMTCLASS")) { /* XBSA */
725 ("Warning: The %s parameter is ignored with a tape drive\n",
729 xbsalGName
= strdup(value
);
730 printf("XBSA management class is %s\n", xbsalGName
);
734 else if (!strcmp(cmd
, "MAXPASS")) {
735 maxpass
= SafeATOL(value
);
736 if (maxpass
< PASSESMIN
)
738 if (maxpass
> PASSESMAX
)
740 printf("MAXPASS is %d\n", maxpass
);
743 else if (!strcmp(cmd
, "GROUPID")) {
744 groupId
= SafeATOL(value
);
745 if ((groupId
< MINGROUPID
) || (groupId
> MAXGROUPID
)) {
746 printf("Configuration file error, %s %s is invalid\n", cmd
,
750 printf("Group Id is %d\n", groupId
);
753 else if (!strcmp(cmd
, "LASTLOG")) {
754 for (cnt
= 0; (size_t) cnt
< strlen(value
); cnt
++)
755 if (islower(value
[cnt
]))
756 value
[cnt
] = toupper(value
[cnt
]);
758 lastLog
= (strcmp(value
, "YES") == 0);
759 printf("Will %sgenerate a last log\n", (lastLog
? "" : "not "));
762 else if (!strcmp(cmd
, "CENTRALLOG")) {
763 centralLogFile
= strdup(value
);
764 printf("Central log file is %s\n", centralLogFile
);
767 else if (!strcmp(cmd
, "STATUS")) {
768 if (atocl(value
, 'B', &statusSize
)) {
769 fprintf(stderr
, "STATUS parse error\n");
772 if (statusSize
< MINSTATUS
)
773 statusSize
= MINSTATUS
;
774 if (statusSize
> MAXSTATUS
)
775 statusSize
= MAXSTATUS
;
779 printf("Warning: Unrecognized configuration parameter: %s", line
);
784 /* Statussize is in bytes and requires that BufferSize be set first */
785 statusSize
*= BufferSize
;
787 statusSize
= 0x7fffffff; /*max size */
788 printf("Status every %ld Bytes\n", afs_printable_int32_ld(statusSize
));
795 /* If the butc is configured as XBSA, check for required parameters */
797 if (!code
&& CONF_XBSA
) {
798 if (xbsaType
== XBSA_SERVER_TYPE_UNKNOWN
) {
800 ("Configuration file error, the TYPE parameter must be specified, or\n");
801 printf("an entry must exist in %s for port %d\n", tapeConfigFile
,
805 if (!adsmServerName
) {
807 ("Configuration file error, the SERVER parameter must be specified\n");
812 ("Configuration file error, the PASSWORD or PASSFILE parameter must be specified\n");
824 xbsa_Finalize(&butxInfo
);
830 tc_IsLocalRealmMatch(void *rock
, char *name
, char *inst
, char *cell
)
832 struct afsconf_dir
*dir
= (struct afsconf_dir
*)rock
;
833 afs_int32 islocal
= 0; /* default to no */
836 code
= afsconf_IsLocalRealmMatch(dir
, &islocal
, name
, inst
, cell
);
838 TLog(0, "Failed local realm check; code=%d, name=%s, inst=%s, cell=%s\n",
839 code
, name
, inst
, cell
);
845 WorkerBee(struct cmd_syndesc
*as
, void *arock
)
847 afs_int32 code
, numClasses
;
848 struct rx_securityClass
*(nullObjects
[1]), **secObjs
, **allObjs
;
849 struct rx_service
*service
;
853 /*process arguments */
854 afs_int32 portOffset
= 0;
855 #ifdef AFS_PTHREAD_ENV
856 pthread_t dbWatcherPid
;
857 pthread_attr_t tattr
;
860 PROCESS dbWatcherPid
;
862 afs_uint32 host
= htonl(INADDR_ANY
);
863 char *auditFileName
= NULL
;
864 char *auditInterface
= NULL
;
868 /*initialize the error tables */
869 initialize_KA_error_table();
870 initialize_RXK_error_table();
871 initialize_KTC_error_table();
872 initialize_ACFG_error_table();
873 initialize_CMD_error_table();
874 initialize_VL_error_table();
875 initialize_BUTM_error_table();
876 initialize_BUTC_error_table();
878 initialize_BUTX_error_table();
880 initialize_VOLS_error_table();
881 initialize_BUDB_error_table();
882 initialize_BUCD_error_table();
884 if (as
->parms
[0].items
) {
885 portOffset
= SafeATOL(as
->parms
[0].items
->data
);
886 if (portOffset
== -1) {
887 fprintf(stderr
, "Illegal port offset '%s'\n",
888 as
->parms
[0].items
->data
);
890 } else if (portOffset
> BC_MAXPORTOFFSET
) {
891 fprintf(stderr
, "%u exceeds max port offset %u\n", portOffset
,
897 xbsaType
= XBSA_SERVER_TYPE_NONE
; /* default */
898 if (as
->parms
[3].items
) { /* -device */
899 globalTapeConfig
.capacity
= 0x7fffffff; /* 2T for max tape capacity */
900 globalTapeConfig
.fileMarkSize
= 0;
901 globalTapeConfig
.portOffset
= portOffset
;
902 strncpy(globalTapeConfig
.device
, as
->parms
[3].items
->data
, 100);
903 xbsaType
= XBSA_SERVER_TYPE_NONE
; /* Not XBSA */
905 /* Search for an entry in tapeconfig file */
906 code
= GetDeviceConfig(tapeConfigFile
, &globalTapeConfig
, portOffset
);
908 fprintf(stderr
, "Problem in reading config file %s\n",
912 /* Set xbsaType. If code == 1, no entry was found in the tapeconfig file so
913 * it's an XBSA server. Don't know if its ADSM or not so its unknown.
916 ((code
== 1) ? XBSA_SERVER_TYPE_UNKNOWN
: XBSA_SERVER_TYPE_NONE
);
919 if (as
->parms
[6].items
) { /* -restoretofile */
920 restoretofile
= strdup(as
->parms
[6].items
->data
);
921 printf("Restore to file '%s'\n", restoretofile
);
924 /* Go and read the config file: CFG_<device> or CFG_<port>. We will also set
925 * the exact xbsaType within the call (won't be unknown) - double check.
927 code
= GetConfigParams(pFile
, portOffset
);
931 if (xbsaType
== XBSA_SERVER_TYPE_UNKNOWN
) {
933 ("\nConfiguration file error, the TYPE parameter must be specified, or\n");
934 printf("an entry must exist in %s for port %d\n", tapeConfigFile
,
939 /* Not compiled for XBSA code so we can't support it */
941 printf("\nNo entry found in %s for port %d\n", tapeConfigFile
,
943 printf("This binary does not have XBSA support\n");
948 /* Open the log files. The pathnames were set in GetConfigParams() */
949 logIO
= fopen(logFile
, "a");
951 fprintf(stderr
, "Failed to open %s\n", logFile
);
954 ErrorlogIO
= fopen(ErrorlogFile
, "a");
956 fprintf(stderr
, "Failed to open %s\n", ErrorlogFile
);
960 lastLogIO
= fopen(lastLogFile
, "a");
962 fprintf(stderr
, "Failed to open %s\n", lastLogFile
);
966 if (centralLogFile
) {
973 statcode
= stat(centralLogFile
, &sbuf
);
974 centralLogIO
= fopen(centralLogFile
, "a");
976 fprintf(stderr
, "Failed to open %s; error %d\n", centralLogFile
,
981 /* Make sure it is not in AFS, has to have been created first */
982 path
= malloc(AFSDIR_PATH_MAX
);
983 if (path
== NULL
|| !realpath(centralLogFile
, path
)) {
985 "Warning: can't determine real path of '%s' (%d)\n",
986 centralLogFile
, errno
);
988 if (strncmp(path
, "/afs/", 5) == 0) {
989 fprintf(stderr
, "The central log '%s' should not be in AFS\n",
997 /* Write header if created it */
1000 "TASK START DATE/TIME END DATE/TIME ELAPSED VOLUMESET\n";
1002 "----- ------------------- ------------------- -------- ---------\n";
1003 /* File didn't exist before so write the header lines */
1004 fwrite(h1
, strlen(h1
), 1, centralLogIO
);
1005 fwrite(h2
, strlen(h2
), 1, centralLogIO
);
1006 fflush(centralLogIO
);
1010 /* Open the configuration directory */
1011 butc_confdir
= afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH
);
1012 if (butc_confdir
== NULL
) {
1013 TLog(0, "Failed to open server configuration directory");
1017 /* Start auditing */
1019 if (as
->parms
[9].items
) {
1020 auditFileName
= as
->parms
[9].items
->data
;
1022 if (auditFileName
!= NULL
)
1023 osi_audit_file(auditFileName
);
1024 if (as
->parms
[10].items
) {
1025 auditInterface
= as
->parms
[10].items
->data
;
1026 if (osi_audit_interface(auditInterface
)) {
1027 TLog(0, "Invalid audit interface '%s'\n", auditInterface
);
1031 osi_audit(TC_StartEvent
, 0, AUD_END
);
1032 osi_audit_set_user_check(butc_confdir
, tc_IsLocalRealmMatch
);
1034 if (as
->parms
[1].items
) {
1035 debugLevel
= SafeATOL(as
->parms
[1].items
->data
);
1036 if (debugLevel
== -1) {
1037 TLog(0, "Illegal debug level '%s'\n", as
->parms
[1].items
->data
);
1042 /* Setup XBSA library interface */
1045 rc
= xbsa_MountLibrary(&butxInfo
, xbsaType
);
1046 if (rc
!= XBSA_SUCCESS
) {
1047 TapeLog(0, 0, rc
, 0, "Unable to mount the XBSA library\n");
1051 forcemultiple
= (as
->parms
[7].items
? 1 : 0);/*-xbsaforcemultiple */
1053 printf("Force XBSA multiple server support\n");
1055 rc
= InitToServer(0 /*taskid */ , &butxInfo
, adsmServerName
);
1056 if (rc
!= XBSA_SUCCESS
)
1058 (void)signal(SIGINT
, xbsa_shutdown
);
1059 (void)signal(SIGHUP
, xbsa_shutdown
);
1064 if (as
->parms
[2].items
)
1065 strncpy(cellName
, as
->parms
[2].items
->data
, sizeof(cellName
));
1069 if (as
->parms
[4].items
)
1072 localauth
= (as
->parms
[5].items
? 1 : 0);
1073 rxBind
= (as
->parms
[8].items
? 1 : 0);
1074 allow_unauth
= (as
->parms
[11].items
? 1 : 0);
1076 if (!allow_unauth
&& !localauth
) {
1077 const char *errstr
= "Neither -localauth nor -allow_unauthenticated was provided; refusing to start in unintended insecure configuration\n";
1078 TLog(0, "%s", (char *)errstr
);
1084 if (AFSDIR_SERVER_NETRESTRICT_FILEPATH
||
1085 AFSDIR_SERVER_NETINFO_FILEPATH
) {
1087 ccode
= afsconf_ParseNetFiles(SHostAddrs
, NULL
, NULL
,
1088 ADDRSPERSITE
, reason
,
1089 AFSDIR_SERVER_NETINFO_FILEPATH
,
1090 AFSDIR_SERVER_NETRESTRICT_FILEPATH
);
1093 ccode
= rx_getAllAddr(SHostAddrs
, ADDRSPERSITE
);
1096 host
= SHostAddrs
[0];
1099 code
= rx_InitHost(host
, htons(BC_TAPEPORT
+ portOffset
));
1101 TapeLog(0, 0, code
, 0, "rx init failed on port %u\n",
1102 BC_TAPEPORT
+ portOffset
);
1105 rx_SetRxDeadTime(150);
1107 /* Establish connection with the vldb server */
1108 code
= vldbClientInit(0, localauth
, cellName
, &cstruct
, &tokenExpires
);
1110 TapeLog(0, 0, code
, 0, "Can't access vldb\n");
1114 strcpy(globalCellName
, cellName
);
1116 /*initialize the dumpNode list */
1117 InitNodeList(portOffset
);
1119 deviceLatch
= malloc(sizeof(struct deviceSyncNode
));
1120 Lock_Init(&(deviceLatch
->lock
));
1121 deviceLatch
->flags
= 0;
1123 /* initialize database support, volume support, and logs */
1126 * Create security objects for the Rx server functionality. Historically
1127 * this was a single rxnull security object, since the tape controller was
1128 * run by an operator that had local access to the tape device and some
1129 * administrative privilege in the cell (to be able to perform volume-level
1130 * accesses), but on a machine that was not necessarily trusted to hold the
1133 * Such a configuration is, of course, insecure because anyone can make
1134 * inbound RPCs and manipulate the database, including creating bogus
1135 * dumps and restoring them! Additionally, in modern usage, butc is
1136 * frequently run with -localauth to authenticate its outbound connections
1137 * to the volservers and budb with the cell-wide key, in which case the
1138 * cell-wide key is present and could be used to authenticate incoming
1139 * connections as well.
1141 * If -localauth is in use, create the full barrage of server security
1142 * objects, including rxkad, so that inbound connections can be verified
1143 * to only be made by authenticated clients. Otherwise, only the rxnull
1144 * class is in use with a single server security object. Note that butc
1145 * will refuse to start in this configuration unless the
1146 * "-allow_unauthenticated" flag is provided, indicating that the operator
1147 * has ensured that incoming connections are appropriately restricted by
1148 * firewall configuration or network topology.
1152 nullObjects
[RX_SECIDX_NULL
] = rxnull_NewServerSecurityObject();
1153 if (!nullObjects
[RX_SECIDX_NULL
]) {
1154 TLog(0, "rxnull_NewServerSecurityObject");
1158 secObjs
= nullObjects
;
1160 /* Must be -localauth, so the cell keys are available. */
1161 afsconf_BuildServerSecurityObjects(butc_confdir
, &allObjs
, &numClasses
);
1166 rx_NewServiceHost(host
, 0, 1, "BUTC", secObjs
, numClasses
, TC_ExecuteRequest
);
1168 TLog(0, "rx_NewService");
1171 rx_SetMaxProcs(service
, 4);
1173 /* Establish connection to the backup database */
1174 code
= udbClientInit(0, localauth
, cellName
);
1176 TapeLog(0, 0, code
, 0, "Can't access backup database\n");
1179 /* This call is here to verify that we are authentiated.
1180 * The call does nothing and will return BUDB_NOTPERMITTED
1181 * if we don't belong.
1183 code
= bcdb_deleteDump(0, 0, 0, 0);
1184 if (code
== BUDB_NOTPERMITTED
) {
1185 TapeLog(0, 0, code
, 0, "Can't access backup database\n");
1190 #ifdef AFS_PTHREAD_ENV
1191 code
= pthread_attr_init(&tattr
);
1193 TapeLog(0, 0, code
, 0,
1194 "Can't pthread_attr_init database monitor task");
1197 code
= pthread_attr_setdetachstate(&tattr
, PTHREAD_CREATE_DETACHED
);
1199 TapeLog(0, 0, code
, 0,
1200 "Can't pthread_attr_setdetachstate database monitor task");
1204 code
= pthread_create(&dbWatcherPid
, &tattr
, dbWatcher
, (void *)2);
1205 AFS_SIGSET_RESTORE();
1208 LWP_CreateProcess(dbWatcher
, 20480, LWP_NORMAL_PRIORITY
, (void *)2,
1209 "dbWatcher", &dbWatcherPid
);
1212 TapeLog(0, 0, code
, 0, "Can't create database monitor task");
1216 TLog(0, "Starting Tape Coordinator: Port offset %u Debug level %u\n",
1217 portOffset
, debugLevel
);
1218 TLog(0, "Token expires: %s\n", cTIME(&tokenExpires
));
1220 rx_StartServer(1); /* Donate this process to the server process pool */
1221 TLog(0, "Error: StartServer returned");
1225 #ifndef AFS_NT40_ENV
1226 #include "AFS_component_version_number.c"
1230 main(int argc
, char **argv
)
1232 struct cmd_syndesc
*ts
;
1233 struct cmd_item
*ti
;
1235 #ifdef AFS_AIX32_ENV
1237 * The following signal action for AIX is necessary so that in case of a
1238 * crash (i.e. core is generated) we can include the user's data section
1239 * in the core dump. Unfortunately, by default, only a partial core is
1240 * generated which, in many cases, isn't too useful.
1242 struct sigaction nsa
;
1244 sigemptyset(&nsa
.sa_mask
);
1245 nsa
.sa_handler
= SIG_DFL
;
1246 nsa
.sa_flags
= SA_FULLDUMP
;
1247 sigaction(SIGSEGV
, &nsa
, NULL
);
1248 sigaction(SIGABRT
, &nsa
, NULL
);
1253 ts
= cmd_CreateSyntax(NULL
, WorkerBee
, NULL
, 0, "tape coordinator");
1254 cmd_AddParm(ts
, "-port", CMD_SINGLE
, CMD_OPTIONAL
, "port offset");
1255 cmd_AddParm(ts
, "-debuglevel", CMD_SINGLE
, CMD_OPTIONAL
, "0 | 1 | 2");
1256 cmd_AddParm(ts
, "-cell", CMD_SINGLE
, CMD_OPTIONAL
, "cell name");
1257 cmd_AddParm(ts
, "-device", CMD_SINGLE
, (CMD_OPTIONAL
| CMD_HIDE
),
1258 "tape device path");
1259 cmd_AddParm(ts
, "-noautoquery", CMD_FLAG
, CMD_OPTIONAL
,
1260 "do not query operator for first tape");
1261 cmd_AddParm(ts
, "-localauth", CMD_FLAG
, CMD_OPTIONAL
,
1262 "create tickets from KeyFile");
1263 cmd_AddParm(ts
, "-restoretofile", CMD_SINGLE
, (CMD_OPTIONAL
| CMD_HIDE
),
1264 "file to restore to");
1265 cmd_AddParm(ts
, "-xbsaforcemultiple", CMD_FLAG
, (CMD_OPTIONAL
| CMD_HIDE
),
1266 "Force multiple XBSA server support");
1267 cmd_AddParm(ts
, "-rxbind", CMD_FLAG
, CMD_OPTIONAL
,
1269 cmd_AddParm(ts
, "-auditlog", CMD_SINGLE
, CMD_OPTIONAL
, "location of audit log");
1270 cmd_AddParm(ts
, "-audit-interface", CMD_SINGLE
, CMD_OPTIONAL
,
1271 "interface to use for audit logging");
1272 cmd_AddParm(ts
, "-allow_unauthenticated", CMD_FLAG
, CMD_OPTIONAL
,
1273 "allow unauthenticated inbound RPCs (requires firewalling)");
1275 /* Initialize dirpaths */
1276 if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK
)) {
1278 ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR
, 0, argv
[0], 0);
1280 fprintf(stderr
, "Unable to obtain AFS server directory.\n");
1284 /* setup the file paths */
1285 strcompose(eFile
, AFSDIR_PATH_MAX
, AFSDIR_SERVER_BACKUP_DIRPATH
, "/",
1286 TE_PREFIX
, (char *)NULL
);
1287 strcompose(lFile
, AFSDIR_PATH_MAX
, AFSDIR_SERVER_BACKUP_DIRPATH
, "/",
1288 TL_PREFIX
, (char *)NULL
);
1289 strcompose(pFile
, AFSDIR_PATH_MAX
, AFSDIR_SERVER_BACKUP_DIRPATH
, "/",
1290 CFG_PREFIX
, (char *)NULL
);
1291 strcpy(tapeConfigFile
, AFSDIR_SERVER_TAPECONFIG_FILEPATH
);
1293 /* special case "no args" case since cmd_dispatch gives help message
1297 ts
= calloc(1, sizeof(struct cmd_syndesc
));
1299 ti
= malloc(sizeof(struct cmd_item
));
1302 ts
->parms
[0].items
= ti
;
1303 ti
= malloc(sizeof(struct cmd_item
));
1306 ts
->parms
[1].items
= ti
;
1307 ts
->parms
[2].items
= NULL
;
1308 ts
->parms
[3].items
= NULL
;
1309 ts
->parms
[4].items
= NULL
;
1310 ts
->parms
[5].items
= NULL
;
1311 return WorkerBee(ts
, NULL
);
1313 return cmd_Dispatch(argc
, argv
);