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/authcon.h>
41 #include <afs/cellconfig.h>
43 #include <afs/volser.h>
45 #include <afs/audit.h>
46 #include <afs/com_err.h>
48 #include <afs/tcdata.h>
49 #include <afs/bubasics.h>
50 #include <afs/budb_errs.h>
51 #include <afs/budb_client.h>
52 #include <afs/bucoord_prototypes.h>
54 #include <afs/kautils.h>
57 #include "error_macros.h"
59 #include "butc_xbsa.h"
60 #include "butc_prototypes.h"
61 #include "butc_internal.h"
63 #define N_SECURITY_OBJECTS 3
64 #define ERRCODE_RANGE 8 /* from error_table.h */
66 #define TE_PREFIX "TE"
67 #define TL_PREFIX "TL"
68 #define CFG_PREFIX "CFG"
70 extern struct ubik_client *cstruct;
71 FILE *logIO, *ErrorlogIO, *centralLogIO, *lastLogIO;
72 char lFile[AFSDIR_PATH_MAX];
73 char logFile[AFSDIR_PATH_MAX + 256];
74 char ErrorlogFile[AFSDIR_PATH_MAX + 256];
75 char lastLogFile[AFSDIR_PATH_MAX + 256];
76 char eFile[AFSDIR_PATH_MAX];
77 char tapeConfigFile[AFSDIR_PATH_MAX];
78 char pFile[AFSDIR_PATH_MAX];
80 struct tapeConfig globalTapeConfig;
81 struct deviceSyncNode *deviceLatch;
82 char globalCellName[64];
83 char *whoami = "butc";
85 /* GLOBAL CONFIGURATION PARAMETERS */
101 #define MINGROUPID 0x1
102 #define MAXGROUPID 0x7FFFFFFF
103 afs_int32 statusSize;
105 #define MAXSTATUS 0x7fffffff
106 afs_int32 BufferSize; /* Size in B stored for data */
107 char *centralLogFile;
108 afs_int32 lastLog; /* Log last pass info */
110 struct afsconf_dir *butc_confdir;
111 int allow_unauth = 0;
113 #define ADDRSPERSITE 16 /* Same global is in rx/rx_user.c */
114 afs_uint32 SHostAddrs[ADDRSPERSITE];
123 while ((tc = *anum)) {
124 if (tc < '0' || tc > '9')
134 * Convert a string into an afs_int32.
135 * Returned afs_int32 is in Bytes, Kb, Mb, Gb, or Tb. Based on crunit char.
136 * This routine only converts unsigned float values.
137 * The returned value is a whole number.
139 * numstring - text string to be converted.
140 * crunit - value returned in 'B', 'K', 'M', 'G', 'T'.
141 * ' ' or NULL ==> 'B' (bytes).
143 * number - returned value in requested crunit - rounded
144 * to nearest whole number.
147 * -1 - error in conversion
149 * should deal with signed numbers. Should signal error if no digits
153 atocl(char *numstring, char crunit, afs_int32 *number)
162 /* Determine which units to report in */
196 sscanf(numstring, "%f%c%s", &total, &cunit, rest);
197 if ((count > 2) || (count <= 0))
200 cunit = 'B'; /* bytes */
234 /* Go to correct unit */
235 for (; units < runits; units += 3)
237 for (; units > runits; units -= 3)
240 total += 0.5; /* Round up */
241 if ((total >= 2147483648.0) || (total < 0)) /* Don't go over 2G */
242 *number = 2147483647;
250 stringNowReplace(char *logFile, char *deviceName)
253 char storeDevice[256];
254 int mvFlag = 0, devPrefLen;
256 char devPrefix[] = "\\\\.";
258 char devPrefix[] = "/dev";
261 devPrefLen = strlen(devPrefix);
262 strcpy(storeDevice, deviceName);
263 if (strncmp(deviceName, devPrefix, devPrefLen) == 0) {
264 deviceName += devPrefLen;
267 while ((pos = strchr(deviceName, devPrefix[0]))) /* look for / or \ */
269 strcat(logFile, deviceName);
270 /* now put back deviceName to the way it was */
272 deviceName -= devPrefLen;
274 strcpy(deviceName, storeDevice);
281 * get the configuration information for a particular tape device
282 * as specified by the portoffset
284 * filename - full pathname of file containing the tape device
285 * configuration information
286 * config - for return results
287 * portOffset - for which configuration is required
289 * logging not available when this routine is called
290 * caller return value checks
292 * 0 => Found entry with same port, return info in config.
293 * -1 => Error encountered trying to read the file.
294 * 1 => Desired entry does not exist or file does not exist.
299 GetDeviceConfig(char *filename, struct tapeConfig *config, afs_int32 portOffset)
303 char devName[LINESIZE], tcapacity[LINESIZE], tfmsize[LINESIZE],
308 afs_int32 code = 0, count;
310 /* Initialize the config struct */
311 config->capacity = 0;
312 config->fileMarkSize = 0;
313 config->portOffset = portOffset;
314 strcpy(config->device, "");
316 devFile = fopen(filename, "r");
320 fprintf(stderr, "Error %d: Can't open %s\n", errno, filename);
324 while (fgets(line, LINESIZE - 1, devFile)) {
326 sscanf(line, "%s %s %s %u%s\n", tcapacity, tfmsize, devName,
329 if (count == 4 || count == 5) {
330 if (atocl(tcapacity, 'K', &capacity)) {
332 "tapeconfig: Tape capacity parse error in: %s\n",
336 if (atocl(tfmsize, 'B', &fmSize)) {
338 "tapeconfig: File-mark size parse error in: %s\n",
343 count = sscanf(line, "%s %u%s\n", devName, &aport, trest);
344 if (count == 2 || count == 3) {
345 capacity = 0x7fffffff;
348 fprintf(stderr, "tapeconfig: Parse error in: %s\n", line);
353 if ((aport < 0) || (aport > BC_MAXPORTOFFSET)) {
354 fprintf(stderr, "tapeconfig: Port offset parse error in: %s\n",
359 if (aport != portOffset)
363 fprintf(stderr, "Invalid file mark size, %d, in: %s\n", fmSize,
368 config->capacity = capacity;
369 config->fileMarkSize = fmSize;
370 config->portOffset = aport;
371 strncpy(config->device, devName, 100);
376 /* fprintf(stderr, "Can't find tapeconfig entry for port offset %d\n", portOffset); */
388 GetConfigParams(char *filename, afs_int32 port)
390 char paramFile[AFSDIR_PATH_MAX + 257];
392 char line[LINESIZE], cmd[LINESIZE], value[LINESIZE];
396 /* DEFAULT SETTINGS FOR GLOBAL PARAMETERS */
397 dump_namecheck = 1; /* check tape name on dumps */
398 queryoperator = 1; /* can question operator */
399 autoQuery = 1; /* prompt for first tape */
400 isafile = 0; /* Do not dump to a file */
401 opencallout = NULL; /* open callout routine */
402 closecallout = NULL; /* close callout routine */
403 tapemounted = 0; /* tape is not mounted */
405 BufferSize = (CONF_XBSA ? XBSADFLTBUFFER : BUTM_BLOCKSIZE);
406 dumpRestAuthnLevel = rpc_c_protect_level_default;
407 xbsaObjectOwner = NULL; /* bsaObjectOwner */
408 appObjectOwner = NULL; /* appObjectOwner */
409 adsmServerName = NULL; /* TSM server name - same as ADSM */
410 xbsaSecToken = NULL; /* XBSA sercurity token */
411 xbsalGName = NULL; /* XBSA IGName */
413 BufferSize = BUTM_BLOCKSIZE;
415 centralLogFile = NULL; /* Log for all butcs */
416 centralLogIO = 0; /* Log for all butcs */
417 statusSize = 0; /* size before status message */
418 maxpass = PASSESDFLT; /* dump passes */
419 lastLog = 0; /* separate log for last pass */
420 lastLogIO = 0; /* separate log for last pass */
421 groupId = 0; /* Group id for multiple dumps */
423 /* Try opening the CFG_<port> file */
424 snprintf(paramFile, sizeof(paramFile), "%s_%d", filename, port);
425 devFile = fopen(paramFile, "r");
427 /* Set log names to TL_<port>, TL_<port>.lp and TE_<port> */
428 snprintf(logFile, sizeof(logFile), "%s_%d", lFile, port);
429 snprintf(lastLogFile, sizeof(lastLogFile), "%s_%d.lp", lFile, port);
430 snprintf(ErrorlogFile, sizeof(ErrorlogFile), "%s_%d", eFile, port);
431 } else if (CONF_XBSA) {
432 /* If configured as XBSA, a configuration file CFG_<port> must exist */
433 printf("Cannot open configuration file %s", paramFile);
436 /* Try the CFG_<device> name as the device file */
437 strcpy(paramFile, filename);
438 stringNowReplace(paramFile, globalTapeConfig.device);
439 /* Set log names to TL_<device>, TL_<device> and TE_<device> */
440 strcpy(logFile, lFile);
441 stringNowReplace(logFile, globalTapeConfig.device);
442 strcpy(lastLogFile, lFile);
443 stringNowReplace(lastLogFile, globalTapeConfig.device);
444 strcat(lastLogFile, ".lp");
445 strcpy(ErrorlogFile, eFile);
446 stringNowReplace(ErrorlogFile, globalTapeConfig.device);
448 /* Now open the device file */
449 devFile = fopen(paramFile, "r");
451 ERROR_EXIT(0); /* CFG file doesn't exist for non-XBSA and that's ok */
454 /* Read each line of the Configuration file */
455 while (fgets(line, LINESIZE - 1, devFile)) {
456 cnt = sscanf(line, "%s %s", cmd, value);
459 printf("Bad line in %s: %s\n", paramFile, line);
463 for (cnt = 0; cnt < strlen(cmd); cnt++)
464 if (islower(cmd[cnt]))
465 cmd[cnt] = toupper(cmd[cnt]);
467 if (!strcmp(cmd, "NAME_CHECK")) {
470 ("Warning: The %s parameter is ignored with a Backup Service\n",
475 for (cnt = 0; cnt < strlen(value); cnt++)
476 if (islower(value[cnt]))
477 value[cnt] = toupper(value[cnt]);
479 if (!strcmp(value, "NO")) {
480 printf("Dump tape name check is disabled\n");
483 printf("Dump tape name check is enabled\n");
488 else if (!strcmp(cmd, "MOUNT")) {
491 ("Warning: The %s parameter is ignored with a Backup Service\n",
496 opencallout = strdup(value);
497 printf("Tape mount callout routine is %s\n", opencallout);
500 else if (!strcmp(cmd, "UNMOUNT")) {
503 ("Warning: The %s parameter is ignored with a Backup Service\n",
508 closecallout = strdup(value);
509 printf("Tape unmount callout routine is %s\n", closecallout);
512 else if (!strcmp(cmd, "ASK")) {
513 for (cnt = 0; cnt < strlen(value); cnt++)
514 if (islower(value[cnt]))
515 value[cnt] = toupper(value[cnt]);
517 if (!strcmp(value, "NO")) {
518 printf("Operator queries are disabled\n");
521 printf("Operator queries are enabled\n");
526 else if (!strcmp(cmd, "FILE")) {
529 ("Warning: The %s parameter is ignored with a Backup Service\n",
534 for (cnt = 0; cnt < strlen(value); cnt++)
535 if (islower(value[cnt]))
536 value[cnt] = toupper(value[cnt]);
538 if (!strcmp(value, "YES")) {
539 printf("Will dump to a file\n");
542 printf("Will not dump to a file\n");
547 else if (!strcmp(cmd, "AUTOQUERY")) {
550 ("Warning: The %s parameter is ignored with a Backup Service\n",
555 for (cnt = 0; cnt < strlen(value); cnt++)
556 if (islower(value[cnt]))
557 value[cnt] = toupper(value[cnt]);
559 if (!strcmp(value, "NO")) {
560 printf("Auto query is disabled\n");
563 printf("Auto query is enabled\n");
568 else if (!strcmp(cmd, "BUFFERSIZE")) {
570 afs_int32 numTapeblocks;
573 if (atocl(value, 'K', &size)) {
574 fprintf(stderr, "BUFFERSIZE parse error\n");
578 /* A tapeblock is 16KB. Determine # of tapeblocks. Then
579 * determine BufferSize needed for that many tapeblocks.
581 numTapeblocks = size / 16;
582 if (numTapeblocks <= 0)
584 printf("BUFFERSIZE is %u KBytes\n", (numTapeblocks * 16));
585 BufferSize = numTapeblocks * BUTM_BLOCKSIZE;
588 if (atocl(value, 'B', &size)) {
589 fprintf(stderr, "BUFFERSIZE parse error\n");
592 if (size < XBSAMINBUFFER)
593 size = XBSAMINBUFFER;
594 if (size > XBSAMAXBUFFER)
595 size = XBSAMAXBUFFER;
596 printf("XBSA buffer size is %u Bytes\n", size);
602 /* All the xbsa spacific parameters */
603 else if (!strcmp(cmd, "TYPE") || !strcmp(cmd, "NODE")
604 || !strcmp(cmd, "SERVER") || !strcmp(cmd, "PASSWORD")
605 || !strcmp(cmd, "PASSFILE") || !strcmp(cmd, "MGMTCLASS")) {
606 printf("This binary does not have XBSA support\n");
610 else if (!strcmp(cmd, "TYPE")) { /* required for XBSA */
613 ("Warning: The %s parameter is ignored with a tape drive\n",
618 for (cnt = 0; (size_t) cnt < strlen(value); cnt++)
619 if (islower(value[cnt]))
620 value[cnt] = toupper(value[cnt]);
622 if (strcmp(value, "TSM") == 0) {
623 xbsaType = XBSA_SERVER_TYPE_ADSM; /* Known XBSA server type */
625 printf("Configuration file error, %s %s is not recognized\n",
627 xbsaType = XBSA_SERVER_TYPE_UNKNOWN;
629 printf("XBSA type is %s\n",
631 XBSA_SERVER_TYPE_UNKNOWN) ? "Unknown" : value));
634 else if (!strcmp(cmd, "NODE")) {
637 ("Warning: The %s parameter is ignored with a tape drive\n",
641 xbsaObjectOwner = strdup(value);
642 printf("XBSA node is %s\n", xbsaObjectOwner);
645 else if (!strcmp(cmd, "SERVER")) { /* required for XBSA */
648 ("Warning: The %s parameter is ignored with a tape drive\n",
652 adsmServerName = strdup(value);
653 printf("XBSA server is %s\n", adsmServerName);
656 else if (!strcmp(cmd, "PASSWORD")) { /* This or PASSFILE required for XBSA */
659 ("Warning: The %s parameter is ignored with a tape drive\n",
665 ("Warning: The %s parameter is ignored. Already read password\n",
670 xbsaSecToken = strdup(value);
671 printf("XBSA Password has been read\n");
674 else if (!strcmp(cmd, "PASSFILE")) { /* This or PASSWORD required for XBSA */
678 ("Warning: The %s parameter is ignored with a tape drive\n",
684 ("Warning: The %s parameter is ignored. Already read password\n",
689 pwdFile = fopen(value, "r");
692 ("Configuration file error, cannot open password file %s\n",
696 xbsaSecToken = malloc(LINESIZE);
697 if (!fscanf(pwdFile, "%s", xbsaSecToken)) {
699 ("Configuration file error, cannot read password file %s\n",
703 printf("XBSA password retrieved from password file\n");
706 else if (!strcmp(cmd, "MGMTCLASS")) { /* XBSA */
709 ("Warning: The %s parameter is ignored with a tape drive\n",
713 xbsalGName = strdup(value);
714 printf("XBSA management class is %s\n", xbsalGName);
718 else if (!strcmp(cmd, "MAXPASS")) {
719 maxpass = SafeATOL(value);
720 if (maxpass < PASSESMIN)
722 if (maxpass > PASSESMAX)
724 printf("MAXPASS is %d\n", maxpass);
727 else if (!strcmp(cmd, "GROUPID")) {
728 groupId = SafeATOL(value);
729 if ((groupId < MINGROUPID) || (groupId > MAXGROUPID)) {
730 printf("Configuration file error, %s %s is invalid\n", cmd,
734 printf("Group Id is %d\n", groupId);
737 else if (!strcmp(cmd, "LASTLOG")) {
738 for (cnt = 0; (size_t) cnt < strlen(value); cnt++)
739 if (islower(value[cnt]))
740 value[cnt] = toupper(value[cnt]);
742 lastLog = (strcmp(value, "YES") == 0);
743 printf("Will %sgenerate a last log\n", (lastLog ? "" : "not "));
746 else if (!strcmp(cmd, "CENTRALLOG")) {
747 centralLogFile = strdup(value);
748 printf("Central log file is %s\n", centralLogFile);
751 else if (!strcmp(cmd, "STATUS")) {
752 if (atocl(value, 'B', &statusSize)) {
753 fprintf(stderr, "STATUS parse error\n");
756 if (statusSize < MINSTATUS)
757 statusSize = MINSTATUS;
758 if (statusSize > MAXSTATUS)
759 statusSize = MAXSTATUS;
763 printf("Warning: Unrecognized configuration parameter: %s", line);
768 /* Statussize is in bytes and requires that BufferSize be set first */
769 statusSize *= BufferSize;
771 statusSize = 0x7fffffff; /*max size */
772 printf("Status every %ld Bytes\n", afs_printable_int32_ld(statusSize));
779 /* If the butc is configured as XBSA, check for required parameters */
781 if (!code && CONF_XBSA) {
782 if (xbsaType == XBSA_SERVER_TYPE_UNKNOWN) {
784 ("Configuration file error, the TYPE parameter must be specified, or\n");
785 printf("an entry must exist in %s for port %d\n", tapeConfigFile,
789 if (!adsmServerName) {
791 ("Configuration file error, the SERVER parameter must be specified\n");
796 ("Configuration file error, the PASSWORD or PASSFILE parameter must be specified\n");
808 xbsa_Finalize(&butxInfo);
814 tc_IsLocalRealmMatch(void *rock, char *name, char *inst, char *cell)
816 struct afsconf_dir *dir = (struct afsconf_dir *)rock;
817 afs_int32 islocal = 0; /* default to no */
820 code = afsconf_IsLocalRealmMatch(dir, &islocal, name, inst, cell);
822 TLog(0, "Failed local realm check; code=%d, name=%s, inst=%s, cell=%s\n",
823 code, name, inst, cell);
829 WorkerBee(struct cmd_syndesc *as, void *arock)
831 afs_int32 code, numClasses;
832 struct rx_securityClass *(nullObjects[1]), **secObjs, **allObjs;
833 struct rx_service *service;
837 /*process arguments */
838 afs_int32 portOffset = 0;
839 #ifdef AFS_PTHREAD_ENV
840 pthread_t dbWatcherPid;
841 pthread_attr_t tattr;
844 PROCESS dbWatcherPid;
847 afs_uint32 host = htonl(INADDR_ANY);
848 char *auditIface = NULL;
852 /*initialize the error tables */
853 initialize_KA_error_table();
854 initialize_RXK_error_table();
855 initialize_KTC_error_table();
856 initialize_ACFG_error_table();
857 initialize_CMD_error_table();
858 initialize_VL_error_table();
859 initialize_BUTM_error_table();
860 initialize_BUTC_error_table();
862 initialize_BUTX_error_table();
864 initialize_VOLS_error_table();
865 initialize_BUDB_error_table();
866 initialize_BUCD_error_table();
868 if (as->parms[0].items) {
869 portOffset = SafeATOL(as->parms[0].items->data);
870 if (portOffset == -1) {
871 fprintf(stderr, "Illegal port offset '%s'\n",
872 as->parms[0].items->data);
874 } else if (portOffset > BC_MAXPORTOFFSET) {
875 fprintf(stderr, "%u exceeds max port offset %u\n", portOffset,
881 xbsaType = XBSA_SERVER_TYPE_NONE; /* default */
882 if (as->parms[3].items) { /* -device */
883 globalTapeConfig.capacity = 0x7fffffff; /* 2T for max tape capacity */
884 globalTapeConfig.fileMarkSize = 0;
885 globalTapeConfig.portOffset = portOffset;
886 strncpy(globalTapeConfig.device, as->parms[3].items->data, 100);
887 xbsaType = XBSA_SERVER_TYPE_NONE; /* Not XBSA */
889 /* Search for an entry in tapeconfig file */
890 code = GetDeviceConfig(tapeConfigFile, &globalTapeConfig, portOffset);
892 fprintf(stderr, "Problem in reading config file %s\n",
896 /* Set xbsaType. If code == 1, no entry was found in the tapeconfig file so
897 * it's an XBSA server. Don't know if its ADSM or not so its unknown.
900 ((code == 1) ? XBSA_SERVER_TYPE_UNKNOWN : XBSA_SERVER_TYPE_NONE);
903 if (as->parms[6].items) { /* -restoretofile */
904 restoretofile = strdup(as->parms[6].items->data);
905 printf("Restore to file '%s'\n", restoretofile);
908 /* Go and read the config file: CFG_<device> or CFG_<port>. We will also set
909 * the exact xbsaType within the call (won't be unknown) - double check.
911 code = GetConfigParams(pFile, portOffset);
915 if (xbsaType == XBSA_SERVER_TYPE_UNKNOWN) {
917 ("\nConfiguration file error, the TYPE parameter must be specified, or\n");
918 printf("an entry must exist in %s for port %d\n", tapeConfigFile,
923 /* Not compiled for XBSA code so we can't support it */
925 printf("\nNo entry found in %s for port %d\n", tapeConfigFile,
927 printf("This binary does not have XBSA support\n");
932 /* Open the log files. The pathnames were set in GetConfigParams() */
933 logIO = fopen(logFile, "a");
935 fprintf(stderr, "Failed to open %s\n", logFile);
938 ErrorlogIO = fopen(ErrorlogFile, "a");
940 fprintf(stderr, "Failed to open %s\n", ErrorlogFile);
944 lastLogIO = fopen(lastLogFile, "a");
946 fprintf(stderr, "Failed to open %s\n", lastLogFile);
950 if (centralLogFile) {
957 statcode = stat(centralLogFile, &sbuf);
958 centralLogIO = fopen(centralLogFile, "a");
960 fprintf(stderr, "Failed to open %s; error %d\n", centralLogFile,
965 /* Make sure it is not in AFS, has to have been created first */
966 path = malloc(AFSDIR_PATH_MAX);
967 if (path == NULL || !realpath(centralLogFile, path)) {
969 "Warning: can't determine real path of '%s' (%d)\n",
970 centralLogFile, errno);
972 if (strncmp(path, "/afs/", 5) == 0) {
973 fprintf(stderr, "The central log '%s' should not be in AFS\n",
981 /* Write header if created it */
984 "TASK START DATE/TIME END DATE/TIME ELAPSED VOLUMESET\n";
986 "----- ------------------- ------------------- -------- ---------\n";
987 /* File didn't exist before so write the header lines */
988 fwrite(h1, strlen(h1), 1, centralLogIO);
989 fwrite(h2, strlen(h2), 1, centralLogIO);
990 fflush(centralLogIO);
994 /* Open the configuration directory */
995 butc_confdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
996 if (butc_confdir == NULL) {
997 TLog(0, "Failed to open server configuration directory");
1001 /* Start auditing */
1003 /* Process -audit-interface and -auditlog */
1004 if (as->parms[10].items != NULL)
1005 auditIface = as->parms[10].items->data;
1007 if (as->parms[9].items != NULL) {
1009 code = osi_audit_cmd_Options(auditIface, as->parms[9].items);
1011 TLog(0, "Error processing -audit-interface or -auditlog parameters");
1017 osi_audit(TC_StartEvent, 0, AUD_END);
1018 osi_audit_set_user_check(butc_confdir, tc_IsLocalRealmMatch);
1020 if (as->parms[1].items) {
1021 debugLevel = SafeATOL(as->parms[1].items->data);
1022 if (debugLevel == -1) {
1023 TLog(0, "Illegal debug level '%s'\n", as->parms[1].items->data);
1028 /* Setup XBSA library interface */
1031 rc = xbsa_MountLibrary(&butxInfo, xbsaType);
1032 if (rc != XBSA_SUCCESS) {
1033 TapeLog(0, 0, rc, 0, "Unable to mount the XBSA library\n");
1037 forcemultiple = (as->parms[7].items ? 1 : 0);/*-xbsaforcemultiple */
1039 printf("Force XBSA multiple server support\n");
1041 rc = InitToServer(0 /*taskid */ , &butxInfo, adsmServerName);
1042 if (rc != XBSA_SUCCESS)
1044 (void)signal(SIGINT, xbsa_shutdown);
1045 (void)signal(SIGHUP, xbsa_shutdown);
1050 if (as->parms[2].items)
1051 strncpy(cellName, as->parms[2].items->data, sizeof(cellName));
1055 if (as->parms[4].items)
1058 localauth = (as->parms[5].items ? 1 : 0);
1059 rxBind = (as->parms[8].items ? 1 : 0);
1060 allow_unauth = (as->parms[11].items ? 1 : 0);
1062 if (!allow_unauth && !localauth) {
1063 const char *errstr = "Neither -localauth nor -allow_unauthenticated was provided; refusing to start in unintended insecure configuration\n";
1064 TLog(0, "%s", (char *)errstr);
1070 if (AFSDIR_SERVER_NETRESTRICT_FILEPATH ||
1071 AFSDIR_SERVER_NETINFO_FILEPATH) {
1073 ccode = afsconf_ParseNetFiles(SHostAddrs, NULL, NULL,
1074 ADDRSPERSITE, reason,
1075 AFSDIR_SERVER_NETINFO_FILEPATH,
1076 AFSDIR_SERVER_NETRESTRICT_FILEPATH);
1079 ccode = rx_getAllAddr(SHostAddrs, ADDRSPERSITE);
1082 host = SHostAddrs[0];
1085 TLog(0, "butc binding rx to %s:%d\n",
1086 afs_inet_ntoa_r(host, hoststr), BC_TAPEPORT + portOffset);
1087 code = rx_InitHost(host, htons(BC_TAPEPORT + portOffset));
1089 TapeLog(0, 0, code, 0, "rx init failed on port %u\n",
1090 BC_TAPEPORT + portOffset);
1093 rx_SetRxDeadTime(150);
1095 /* Establish connection with the vldb server */
1096 code = vldbClientInit(0, localauth, cellName, &cstruct, &tokenExpires);
1098 TapeLog(0, 0, code, 0, "Can't access vldb\n");
1102 strcpy(globalCellName, cellName);
1104 /*initialize the dumpNode list */
1105 InitNodeList(portOffset);
1107 deviceLatch = malloc(sizeof(struct deviceSyncNode));
1108 Lock_Init(&(deviceLatch->lock));
1109 deviceLatch->flags = 0;
1111 /* initialize database support, volume support, and logs */
1114 * Create security objects for the Rx server functionality. Historically
1115 * this was a single rxnull security object, since the tape controller was
1116 * run by an operator that had local access to the tape device and some
1117 * administrative privilege in the cell (to be able to perform volume-level
1118 * accesses), but on a machine that was not necessarily trusted to hold the
1121 * Such a configuration is, of course, insecure because anyone can make
1122 * inbound RPCs and manipulate the database, including creating bogus
1123 * dumps and restoring them! Additionally, in modern usage, butc is
1124 * frequently run with -localauth to authenticate its outbound connections
1125 * to the volservers and budb with the cell-wide key, in which case the
1126 * cell-wide key is present and could be used to authenticate incoming
1127 * connections as well.
1129 * If -localauth is in use, create the full barrage of server security
1130 * objects, including rxkad, so that inbound connections can be verified
1131 * to only be made by authenticated clients. Otherwise, only the rxnull
1132 * class is in use with a single server security object. Note that butc
1133 * will refuse to start in this configuration unless the
1134 * "-allow_unauthenticated" flag is provided, indicating that the operator
1135 * has ensured that incoming connections are appropriately restricted by
1136 * firewall configuration or network topology.
1140 nullObjects[RX_SECIDX_NULL] = rxnull_NewServerSecurityObject();
1141 if (!nullObjects[RX_SECIDX_NULL]) {
1142 TLog(0, "rxnull_NewServerSecurityObject");
1146 secObjs = nullObjects;
1148 /* Must be -localauth, so the cell keys are available. */
1149 struct afsconf_bsso_info bsso;
1150 memset(&bsso, 0, sizeof(bsso));
1151 bsso.dir = butc_confdir;
1152 afsconf_BuildServerSecurityObjects_int(&bsso, &allObjs, &numClasses);
1157 rx_NewServiceHost(host, 0, 1, "BUTC", secObjs, numClasses, TC_ExecuteRequest);
1159 TLog(0, "rx_NewService");
1162 rx_SetMaxProcs(service, 4);
1164 /* Establish connection to the backup database */
1165 code = udbClientInit(0, localauth, cellName);
1167 TapeLog(0, 0, code, 0, "Can't access backup database\n");
1170 /* This call is here to verify that we are authentiated.
1171 * The call does nothing and will return BUDB_NOTPERMITTED
1172 * if we don't belong.
1174 code = bcdb_deleteDump(0, 0, 0, 0);
1175 if (code == BUDB_NOTPERMITTED) {
1176 TapeLog(0, 0, code, 0, "Can't access backup database\n");
1181 #ifdef AFS_PTHREAD_ENV
1182 code = pthread_attr_init(&tattr);
1184 TapeLog(0, 0, code, 0,
1185 "Can't pthread_attr_init database monitor task");
1188 code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
1190 TapeLog(0, 0, code, 0,
1191 "Can't pthread_attr_setdetachstate database monitor task");
1195 code = pthread_create(&dbWatcherPid, &tattr, dbWatcher, (void *)2);
1196 AFS_SIGSET_RESTORE();
1199 LWP_CreateProcess(dbWatcher, 20480, LWP_NORMAL_PRIORITY, (void *)2,
1200 "dbWatcher", &dbWatcherPid);
1203 TapeLog(0, 0, code, 0, "Can't create database monitor task");
1207 TLog(0, "Starting Tape Coordinator: Port offset %u Debug level %u\n",
1208 portOffset, debugLevel);
1209 TLog(0, "Token expires: %s\n", cTIME(&tokenExpires));
1211 rx_StartServer(1); /* Donate this process to the server process pool */
1212 TLog(0, "Error: StartServer returned");
1216 #ifndef AFS_NT40_ENV
1217 #include "AFS_component_version_number.c"
1221 main(int argc, char **argv)
1223 struct cmd_syndesc *ts;
1224 struct cmd_item *ti;
1226 #ifdef AFS_AIX32_ENV
1228 * The following signal action for AIX is necessary so that in case of a
1229 * crash (i.e. core is generated) we can include the user's data section
1230 * in the core dump. Unfortunately, by default, only a partial core is
1231 * generated which, in many cases, isn't too useful.
1233 struct sigaction nsa;
1235 sigemptyset(&nsa.sa_mask);
1236 nsa.sa_handler = SIG_DFL;
1237 nsa.sa_flags = SA_FULLDUMP;
1238 sigaction(SIGSEGV, &nsa, NULL);
1239 sigaction(SIGABRT, &nsa, NULL);
1244 ts = cmd_CreateSyntax(NULL, WorkerBee, NULL, 0, "tape coordinator");
1245 cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "port offset");
1246 cmd_AddParm(ts, "-debuglevel", CMD_SINGLE, CMD_OPTIONAL, "0 | 1 | 2");
1247 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
1248 cmd_AddParm(ts, "-device", CMD_SINGLE, (CMD_OPTIONAL | CMD_HIDE),
1249 "tape device path");
1250 cmd_AddParm(ts, "-noautoquery", CMD_FLAG, CMD_OPTIONAL,
1251 "do not query operator for first tape");
1252 cmd_AddParm(ts, "-localauth", CMD_FLAG, CMD_OPTIONAL,
1253 "create tickets from KeyFile");
1254 cmd_AddParm(ts, "-restoretofile", CMD_SINGLE, (CMD_OPTIONAL | CMD_HIDE),
1255 "file to restore to");
1256 cmd_AddParm(ts, "-xbsaforcemultiple", CMD_FLAG, (CMD_OPTIONAL | CMD_HIDE),
1257 "Force multiple XBSA server support");
1258 cmd_AddParm(ts, "-rxbind", CMD_FLAG, CMD_OPTIONAL,
1260 cmd_AddParm(ts, "-auditlog", CMD_LIST, CMD_OPTIONAL,
1261 "[interface:]path[:options]");
1262 cmd_AddParm(ts, "-audit-interface", CMD_SINGLE, CMD_OPTIONAL,
1263 "default interface");
1264 cmd_AddParm(ts, "-allow_unauthenticated", CMD_FLAG, CMD_OPTIONAL,
1265 "allow unauthenticated inbound RPCs (requires firewalling)");
1267 /* Initialize dirpaths */
1268 if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
1270 ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0);
1272 fprintf(stderr, "Unable to obtain AFS server directory.\n");
1276 /* setup the file paths */
1277 strcompose(eFile, AFSDIR_PATH_MAX, AFSDIR_SERVER_BACKUP_DIRPATH, "/",
1278 TE_PREFIX, (char *)NULL);
1279 strcompose(lFile, AFSDIR_PATH_MAX, AFSDIR_SERVER_BACKUP_DIRPATH, "/",
1280 TL_PREFIX, (char *)NULL);
1281 strcompose(pFile, AFSDIR_PATH_MAX, AFSDIR_SERVER_BACKUP_DIRPATH, "/",
1282 CFG_PREFIX, (char *)NULL);
1283 strcpy(tapeConfigFile, AFSDIR_SERVER_TAPECONFIG_FILEPATH);
1285 /* special case "no args" case since cmd_dispatch gives help message
1289 ts = calloc(1, sizeof(struct cmd_syndesc));
1291 ti = malloc(sizeof(struct cmd_item));
1294 ts->parms[0].items = ti;
1295 ti = malloc(sizeof(struct cmd_item));
1298 ts->parms[1].items = ti;
1299 ts->parms[2].items = NULL;
1300 ts->parms[3].items = NULL;
1301 ts->parms[4].items = NULL;
1302 ts->parms[5].items = NULL;
1303 return WorkerBee(ts, NULL);
1305 return cmd_Dispatch(argc, argv);