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 extern struct ubik_client *cstruct;
70 FILE *logIO, *ErrorlogIO, *centralLogIO, *lastLogIO;
71 char lFile[AFSDIR_PATH_MAX];
72 char logFile[AFSDIR_PATH_MAX + 256];
73 char ErrorlogFile[AFSDIR_PATH_MAX + 256];
74 char lastLogFile[AFSDIR_PATH_MAX + 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 >= 2147483648.0) || (total < 0)) /* Don't go over 2G */
241 *number = 2147483647;
249 stringNowReplace(char *logFile, char *deviceName)
252 char storeDevice[256];
253 int mvFlag = 0, devPrefLen;
255 char devPrefix[] = "\\\\.";
257 char devPrefix[] = "/dev";
260 devPrefLen = strlen(devPrefix);
261 strcpy(storeDevice, deviceName);
262 if (strncmp(deviceName, devPrefix, devPrefLen) == 0) {
263 deviceName += devPrefLen;
266 while ((pos = strchr(deviceName, devPrefix[0]))) /* look for / or \ */
268 strcat(logFile, deviceName);
269 /* now put back deviceName to the way it was */
271 deviceName -= devPrefLen;
273 strcpy(deviceName, storeDevice);
280 * get the configuration information for a particular tape device
281 * as specified by the portoffset
283 * filename - full pathname of file containing the tape device
284 * configuration information
285 * config - for return results
286 * portOffset - for which configuration is required
288 * logging not available when this routine is called
289 * caller return value checks
291 * 0 => Found entry with same port, return info in config.
292 * -1 => Error encountered trying to read the file.
293 * 1 => Desired entry does not exist or file does not exist.
298 GetDeviceConfig(char *filename, struct tapeConfig *config, afs_int32 portOffset)
302 char devName[LINESIZE], tcapacity[LINESIZE], tfmsize[LINESIZE],
307 afs_int32 code = 0, count;
309 /* Initialize the config struct */
310 config->capacity = 0;
311 config->fileMarkSize = 0;
312 config->portOffset = portOffset;
313 strcpy(config->device, "");
315 devFile = fopen(filename, "r");
319 fprintf(stderr, "Error %d: Can't open %s\n", errno, filename);
323 while (fgets(line, LINESIZE - 1, devFile)) {
325 sscanf(line, "%s %s %s %u%s\n", tcapacity, tfmsize, devName,
328 if (count == 4 || count == 5) {
329 if (atocl(tcapacity, 'K', &capacity)) {
331 "tapeconfig: Tape capacity parse error in: %s\n",
335 if (atocl(tfmsize, 'B', &fmSize)) {
337 "tapeconfig: File-mark size parse error in: %s\n",
342 count = sscanf(line, "%s %u%s\n", devName, &aport, trest);
343 if (count == 2 || count == 3) {
344 capacity = 0x7fffffff;
347 fprintf(stderr, "tapeconfig: Parse error in: %s\n", line);
352 if ((aport < 0) || (aport > BC_MAXPORTOFFSET)) {
353 fprintf(stderr, "tapeconfig: Port offset parse error in: %s\n",
358 if (aport != portOffset)
362 fprintf(stderr, "Invalid file mark size, %d, in: %s\n", fmSize,
367 config->capacity = capacity;
368 config->fileMarkSize = fmSize;
369 config->portOffset = aport;
370 strncpy(config->device, devName, 100);
375 /* fprintf(stderr, "Can't find tapeconfig entry for port offset %d\n", portOffset); */
387 GetConfigParams(char *filename, afs_int32 port)
389 char paramFile[AFSDIR_PATH_MAX + 257];
391 char line[LINESIZE], cmd[LINESIZE], value[LINESIZE];
395 /* DEFAULT SETTINGS FOR GLOBAL PARAMETERS */
396 dump_namecheck = 1; /* check tape name on dumps */
397 queryoperator = 1; /* can question operator */
398 autoQuery = 1; /* prompt for first tape */
399 isafile = 0; /* Do not dump to a file */
400 opencallout = NULL; /* open callout routine */
401 closecallout = NULL; /* close callout routine */
402 tapemounted = 0; /* tape is not mounted */
404 BufferSize = (CONF_XBSA ? XBSADFLTBUFFER : BUTM_BLOCKSIZE);
405 dumpRestAuthnLevel = rpc_c_protect_level_default;
406 xbsaObjectOwner = NULL; /* bsaObjectOwner */
407 appObjectOwner = NULL; /* appObjectOwner */
408 adsmServerName = NULL; /* TSM server name - same as ADSM */
409 xbsaSecToken = NULL; /* XBSA sercurity token */
410 xbsalGName = NULL; /* XBSA IGName */
412 BufferSize = BUTM_BLOCKSIZE;
414 centralLogFile = NULL; /* Log for all butcs */
415 centralLogIO = 0; /* Log for all butcs */
416 statusSize = 0; /* size before status message */
417 maxpass = PASSESDFLT; /* dump passes */
418 lastLog = 0; /* separate log for last pass */
419 lastLogIO = 0; /* separate log for last pass */
420 groupId = 0; /* Group id for multiple dumps */
422 /* Try opening the CFG_<port> file */
423 snprintf(paramFile, sizeof(paramFile), "%s_%d", filename, port);
424 devFile = fopen(paramFile, "r");
426 /* Set log names to TL_<port>, TL_<port>.lp and TE_<port> */
427 snprintf(logFile, sizeof(logFile), "%s_%d", lFile, port);
428 snprintf(lastLogFile, sizeof(lastLogFile), "%s_%d.lp", lFile, port);
429 snprintf(ErrorlogFile, sizeof(ErrorlogFile), "%s_%d", eFile, port);
430 } else if (CONF_XBSA) {
431 /* If configured as XBSA, a configuration file CFG_<port> must exist */
432 printf("Cannot open configuration file %s", paramFile);
435 /* Try the CFG_<device> name as the device file */
436 strcpy(paramFile, filename);
437 stringNowReplace(paramFile, globalTapeConfig.device);
438 /* Set log names to TL_<device>, TL_<device> and TE_<device> */
439 strcpy(logFile, lFile);
440 stringNowReplace(logFile, globalTapeConfig.device);
441 strcpy(lastLogFile, lFile);
442 stringNowReplace(lastLogFile, globalTapeConfig.device);
443 strcat(lastLogFile, ".lp");
444 strcpy(ErrorlogFile, eFile);
445 stringNowReplace(ErrorlogFile, globalTapeConfig.device);
447 /* Now open the device file */
448 devFile = fopen(paramFile, "r");
450 ERROR_EXIT(0); /* CFG file doesn't exist for non-XBSA and that's ok */
453 /* Read each line of the Configuration file */
454 while (fgets(line, LINESIZE - 1, devFile)) {
455 cnt = sscanf(line, "%s %s", cmd, value);
458 printf("Bad line in %s: %s\n", paramFile, line);
462 for (cnt = 0; cnt < strlen(cmd); cnt++)
463 if (islower(cmd[cnt]))
464 cmd[cnt] = toupper(cmd[cnt]);
466 if (!strcmp(cmd, "NAME_CHECK")) {
469 ("Warning: The %s parameter is ignored with a Backup Service\n",
474 for (cnt = 0; cnt < strlen(value); cnt++)
475 if (islower(value[cnt]))
476 value[cnt] = toupper(value[cnt]);
478 if (!strcmp(value, "NO")) {
479 printf("Dump tape name check is disabled\n");
482 printf("Dump tape name check is enabled\n");
487 else if (!strcmp(cmd, "MOUNT")) {
490 ("Warning: The %s parameter is ignored with a Backup Service\n",
495 opencallout = strdup(value);
496 printf("Tape mount callout routine is %s\n", opencallout);
499 else if (!strcmp(cmd, "UNMOUNT")) {
502 ("Warning: The %s parameter is ignored with a Backup Service\n",
507 closecallout = strdup(value);
508 printf("Tape unmount callout routine is %s\n", closecallout);
511 else if (!strcmp(cmd, "ASK")) {
512 for (cnt = 0; cnt < strlen(value); cnt++)
513 if (islower(value[cnt]))
514 value[cnt] = toupper(value[cnt]);
516 if (!strcmp(value, "NO")) {
517 printf("Operator queries are disabled\n");
520 printf("Operator queries are enabled\n");
525 else if (!strcmp(cmd, "FILE")) {
528 ("Warning: The %s parameter is ignored with a Backup Service\n",
533 for (cnt = 0; cnt < strlen(value); cnt++)
534 if (islower(value[cnt]))
535 value[cnt] = toupper(value[cnt]);
537 if (!strcmp(value, "YES")) {
538 printf("Will dump to a file\n");
541 printf("Will not dump to a file\n");
546 else if (!strcmp(cmd, "AUTOQUERY")) {
549 ("Warning: The %s parameter is ignored with a Backup Service\n",
554 for (cnt = 0; cnt < strlen(value); cnt++)
555 if (islower(value[cnt]))
556 value[cnt] = toupper(value[cnt]);
558 if (!strcmp(value, "NO")) {
559 printf("Auto query is disabled\n");
562 printf("Auto query is enabled\n");
567 else if (!strcmp(cmd, "BUFFERSIZE")) {
569 afs_int32 numTapeblocks;
572 if (atocl(value, 'K', &size)) {
573 fprintf(stderr, "BUFFERSIZE parse error\n");
577 /* A tapeblock is 16KB. Determine # of tapeblocks. Then
578 * determine BufferSize needed for that many tapeblocks.
580 numTapeblocks = size / 16;
581 if (numTapeblocks <= 0)
583 printf("BUFFERSIZE is %u KBytes\n", (numTapeblocks * 16));
584 BufferSize = numTapeblocks * BUTM_BLOCKSIZE;
587 if (atocl(value, 'B', &size)) {
588 fprintf(stderr, "BUFFERSIZE parse error\n");
591 if (size < XBSAMINBUFFER)
592 size = XBSAMINBUFFER;
593 if (size > XBSAMAXBUFFER)
594 size = XBSAMAXBUFFER;
595 printf("XBSA buffer size is %u Bytes\n", size);
601 /* All the xbsa spacific parameters */
602 else if (!strcmp(cmd, "TYPE") || !strcmp(cmd, "NODE")
603 || !strcmp(cmd, "SERVER") || !strcmp(cmd, "PASSWORD")
604 || !strcmp(cmd, "PASSFILE") || !strcmp(cmd, "MGMTCLASS")) {
605 printf("This binary does not have XBSA support\n");
609 else if (!strcmp(cmd, "TYPE")) { /* required for XBSA */
612 ("Warning: The %s parameter is ignored with a tape drive\n",
617 for (cnt = 0; (size_t) cnt < strlen(value); cnt++)
618 if (islower(value[cnt]))
619 value[cnt] = toupper(value[cnt]);
621 if (strcmp(value, "TSM") == 0) {
622 xbsaType = XBSA_SERVER_TYPE_ADSM; /* Known XBSA server type */
624 printf("Configuration file error, %s %s is not recognized\n",
626 xbsaType = XBSA_SERVER_TYPE_UNKNOWN;
628 printf("XBSA type is %s\n",
630 XBSA_SERVER_TYPE_UNKNOWN) ? "Unknown" : value));
633 else if (!strcmp(cmd, "NODE")) {
636 ("Warning: The %s parameter is ignored with a tape drive\n",
640 xbsaObjectOwner = strdup(value);
641 printf("XBSA node is %s\n", xbsaObjectOwner);
644 else if (!strcmp(cmd, "SERVER")) { /* required for XBSA */
647 ("Warning: The %s parameter is ignored with a tape drive\n",
651 adsmServerName = strdup(value);
652 printf("XBSA server is %s\n", adsmServerName);
655 else if (!strcmp(cmd, "PASSWORD")) { /* This or PASSFILE required for XBSA */
658 ("Warning: The %s parameter is ignored with a tape drive\n",
664 ("Warning: The %s parameter is ignored. Already read password\n",
669 xbsaSecToken = strdup(value);
670 printf("XBSA Password has been read\n");
673 else if (!strcmp(cmd, "PASSFILE")) { /* This or PASSWORD required for XBSA */
677 ("Warning: The %s parameter is ignored with a tape drive\n",
683 ("Warning: The %s parameter is ignored. Already read password\n",
688 pwdFile = fopen(value, "r");
691 ("Configuration file error, cannot open password file %s\n",
695 xbsaSecToken = malloc(LINESIZE);
696 if (!fscanf(pwdFile, "%s", xbsaSecToken)) {
698 ("Configuration file error, cannot read password file %s\n",
702 printf("XBSA password retrieved from password file\n");
705 else if (!strcmp(cmd, "MGMTCLASS")) { /* XBSA */
708 ("Warning: The %s parameter is ignored with a tape drive\n",
712 xbsalGName = strdup(value);
713 printf("XBSA management class is %s\n", xbsalGName);
717 else if (!strcmp(cmd, "MAXPASS")) {
718 maxpass = SafeATOL(value);
719 if (maxpass < PASSESMIN)
721 if (maxpass > PASSESMAX)
723 printf("MAXPASS is %d\n", maxpass);
726 else if (!strcmp(cmd, "GROUPID")) {
727 groupId = SafeATOL(value);
728 if ((groupId < MINGROUPID) || (groupId > MAXGROUPID)) {
729 printf("Configuration file error, %s %s is invalid\n", cmd,
733 printf("Group Id is %d\n", groupId);
736 else if (!strcmp(cmd, "LASTLOG")) {
737 for (cnt = 0; (size_t) cnt < strlen(value); cnt++)
738 if (islower(value[cnt]))
739 value[cnt] = toupper(value[cnt]);
741 lastLog = (strcmp(value, "YES") == 0);
742 printf("Will %sgenerate a last log\n", (lastLog ? "" : "not "));
745 else if (!strcmp(cmd, "CENTRALLOG")) {
746 centralLogFile = strdup(value);
747 printf("Central log file is %s\n", centralLogFile);
750 else if (!strcmp(cmd, "STATUS")) {
751 if (atocl(value, 'B', &statusSize)) {
752 fprintf(stderr, "STATUS parse error\n");
755 if (statusSize < MINSTATUS)
756 statusSize = MINSTATUS;
757 if (statusSize > MAXSTATUS)
758 statusSize = MAXSTATUS;
762 printf("Warning: Unrecognized configuration parameter: %s", line);
767 /* Statussize is in bytes and requires that BufferSize be set first */
768 statusSize *= BufferSize;
770 statusSize = 0x7fffffff; /*max size */
771 printf("Status every %ld Bytes\n", afs_printable_int32_ld(statusSize));
778 /* If the butc is configured as XBSA, check for required parameters */
780 if (!code && CONF_XBSA) {
781 if (xbsaType == XBSA_SERVER_TYPE_UNKNOWN) {
783 ("Configuration file error, the TYPE parameter must be specified, or\n");
784 printf("an entry must exist in %s for port %d\n", tapeConfigFile,
788 if (!adsmServerName) {
790 ("Configuration file error, the SERVER parameter must be specified\n");
795 ("Configuration file error, the PASSWORD or PASSFILE parameter must be specified\n");
807 xbsa_Finalize(&butxInfo);
813 tc_IsLocalRealmMatch(void *rock, char *name, char *inst, char *cell)
815 struct afsconf_dir *dir = (struct afsconf_dir *)rock;
816 afs_int32 islocal = 0; /* default to no */
819 code = afsconf_IsLocalRealmMatch(dir, &islocal, name, inst, cell);
821 TLog(0, "Failed local realm check; code=%d, name=%s, inst=%s, cell=%s\n",
822 code, name, inst, cell);
828 WorkerBee(struct cmd_syndesc *as, void *arock)
830 afs_int32 code, numClasses;
831 struct rx_securityClass *(nullObjects[1]), **secObjs, **allObjs;
832 struct rx_service *service;
836 /*process arguments */
837 afs_int32 portOffset = 0;
838 #ifdef AFS_PTHREAD_ENV
839 pthread_t dbWatcherPid;
840 pthread_attr_t tattr;
843 PROCESS dbWatcherPid;
846 afs_uint32 host = htonl(INADDR_ANY);
847 char *auditIface = NULL;
851 /*initialize the error tables */
852 initialize_KA_error_table();
853 initialize_RXK_error_table();
854 initialize_KTC_error_table();
855 initialize_ACFG_error_table();
856 initialize_CMD_error_table();
857 initialize_VL_error_table();
858 initialize_BUTM_error_table();
859 initialize_BUTC_error_table();
861 initialize_BUTX_error_table();
863 initialize_VOLS_error_table();
864 initialize_BUDB_error_table();
865 initialize_BUCD_error_table();
867 if (as->parms[0].items) {
868 portOffset = SafeATOL(as->parms[0].items->data);
869 if (portOffset == -1) {
870 fprintf(stderr, "Illegal port offset '%s'\n",
871 as->parms[0].items->data);
873 } else if (portOffset > BC_MAXPORTOFFSET) {
874 fprintf(stderr, "%u exceeds max port offset %u\n", portOffset,
880 xbsaType = XBSA_SERVER_TYPE_NONE; /* default */
881 if (as->parms[3].items) { /* -device */
882 globalTapeConfig.capacity = 0x7fffffff; /* 2T for max tape capacity */
883 globalTapeConfig.fileMarkSize = 0;
884 globalTapeConfig.portOffset = portOffset;
885 strncpy(globalTapeConfig.device, as->parms[3].items->data, 100);
886 xbsaType = XBSA_SERVER_TYPE_NONE; /* Not XBSA */
888 /* Search for an entry in tapeconfig file */
889 code = GetDeviceConfig(tapeConfigFile, &globalTapeConfig, portOffset);
891 fprintf(stderr, "Problem in reading config file %s\n",
895 /* Set xbsaType. If code == 1, no entry was found in the tapeconfig file so
896 * it's an XBSA server. Don't know if its ADSM or not so its unknown.
899 ((code == 1) ? XBSA_SERVER_TYPE_UNKNOWN : XBSA_SERVER_TYPE_NONE);
902 if (as->parms[6].items) { /* -restoretofile */
903 restoretofile = strdup(as->parms[6].items->data);
904 printf("Restore to file '%s'\n", restoretofile);
907 /* Go and read the config file: CFG_<device> or CFG_<port>. We will also set
908 * the exact xbsaType within the call (won't be unknown) - double check.
910 code = GetConfigParams(pFile, portOffset);
914 if (xbsaType == XBSA_SERVER_TYPE_UNKNOWN) {
916 ("\nConfiguration file error, the TYPE parameter must be specified, or\n");
917 printf("an entry must exist in %s for port %d\n", tapeConfigFile,
922 /* Not compiled for XBSA code so we can't support it */
924 printf("\nNo entry found in %s for port %d\n", tapeConfigFile,
926 printf("This binary does not have XBSA support\n");
931 /* Open the log files. The pathnames were set in GetConfigParams() */
932 logIO = fopen(logFile, "a");
934 fprintf(stderr, "Failed to open %s\n", logFile);
937 ErrorlogIO = fopen(ErrorlogFile, "a");
939 fprintf(stderr, "Failed to open %s\n", ErrorlogFile);
943 lastLogIO = fopen(lastLogFile, "a");
945 fprintf(stderr, "Failed to open %s\n", lastLogFile);
949 if (centralLogFile) {
956 statcode = stat(centralLogFile, &sbuf);
957 centralLogIO = fopen(centralLogFile, "a");
959 fprintf(stderr, "Failed to open %s; error %d\n", centralLogFile,
964 /* Make sure it is not in AFS, has to have been created first */
965 path = malloc(AFSDIR_PATH_MAX);
966 if (path == NULL || !realpath(centralLogFile, path)) {
968 "Warning: can't determine real path of '%s' (%d)\n",
969 centralLogFile, errno);
971 if (strncmp(path, "/afs/", 5) == 0) {
972 fprintf(stderr, "The central log '%s' should not be in AFS\n",
980 /* Write header if created it */
983 "TASK START DATE/TIME END DATE/TIME ELAPSED VOLUMESET\n";
985 "----- ------------------- ------------------- -------- ---------\n";
986 /* File didn't exist before so write the header lines */
987 fwrite(h1, strlen(h1), 1, centralLogIO);
988 fwrite(h2, strlen(h2), 1, centralLogIO);
989 fflush(centralLogIO);
993 /* Open the configuration directory */
994 butc_confdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
995 if (butc_confdir == NULL) {
996 TLog(0, "Failed to open server configuration directory");
1000 if (afsconf_CountKeys(butc_confdir) == 0) {
1001 TLog(0, "WARNING: No encryption keys found! "
1002 "All authenticated accesses will fail. "
1003 "Run akeyconvert or asetkey to import encryption keys.\n");
1006 /* Start auditing */
1008 /* Process -audit-interface and -auditlog */
1009 if (as->parms[10].items != NULL)
1010 auditIface = as->parms[10].items->data;
1012 if (as->parms[9].items != NULL) {
1014 code = osi_audit_cmd_Options(auditIface, as->parms[9].items);
1016 TLog(0, "Error processing -audit-interface or -auditlog parameters");
1022 osi_audit(TC_StartEvent, 0, AUD_END);
1023 osi_audit_set_user_check(butc_confdir, tc_IsLocalRealmMatch);
1025 if (as->parms[1].items) {
1026 debugLevel = SafeATOL(as->parms[1].items->data);
1027 if (debugLevel == -1) {
1028 TLog(0, "Illegal debug level '%s'\n", as->parms[1].items->data);
1033 /* Setup XBSA library interface */
1036 rc = xbsa_MountLibrary(&butxInfo, xbsaType);
1037 if (rc != XBSA_SUCCESS) {
1038 TapeLog(0, 0, rc, 0, "Unable to mount the XBSA library\n");
1042 forcemultiple = (as->parms[7].items ? 1 : 0);/*-xbsaforcemultiple */
1044 printf("Force XBSA multiple server support\n");
1046 rc = InitToServer(0 /*taskid */ , &butxInfo, adsmServerName);
1047 if (rc != XBSA_SUCCESS)
1049 (void)signal(SIGINT, xbsa_shutdown);
1050 (void)signal(SIGHUP, xbsa_shutdown);
1055 if (as->parms[2].items)
1056 strncpy(cellName, as->parms[2].items->data, sizeof(cellName));
1060 if (as->parms[4].items)
1063 localauth = (as->parms[5].items ? 1 : 0);
1064 rxBind = (as->parms[8].items ? 1 : 0);
1065 allow_unauth = (as->parms[11].items ? 1 : 0);
1067 if (!allow_unauth && !localauth) {
1068 const char *errstr = "Neither -localauth nor -allow_unauthenticated was provided; refusing to start in unintended insecure configuration\n";
1069 TLog(0, "%s", (char *)errstr);
1075 if (AFSDIR_SERVER_NETRESTRICT_FILEPATH ||
1076 AFSDIR_SERVER_NETINFO_FILEPATH) {
1078 ccode = afsconf_ParseNetFiles(SHostAddrs, NULL, NULL,
1079 ADDRSPERSITE, reason,
1080 AFSDIR_SERVER_NETINFO_FILEPATH,
1081 AFSDIR_SERVER_NETRESTRICT_FILEPATH);
1084 ccode = rx_getAllAddr(SHostAddrs, ADDRSPERSITE);
1087 host = SHostAddrs[0];
1090 TLog(0, "butc binding rx to %s:%d\n",
1091 afs_inet_ntoa_r(host, hoststr), BC_TAPEPORT + portOffset);
1092 code = rx_InitHost(host, htons(BC_TAPEPORT + portOffset));
1094 TapeLog(0, 0, code, 0, "rx init failed on port %u\n",
1095 BC_TAPEPORT + portOffset);
1098 rx_SetRxDeadTime(150);
1100 /* Establish connection with the vldb server */
1101 code = vldbClientInit(0, localauth, cellName, &cstruct, &tokenExpires);
1103 TapeLog(0, 0, code, 0, "Can't access vldb\n");
1107 strcpy(globalCellName, cellName);
1109 /*initialize the dumpNode list */
1110 InitNodeList(portOffset);
1112 deviceLatch = malloc(sizeof(struct deviceSyncNode));
1113 Lock_Init(&(deviceLatch->lock));
1114 deviceLatch->flags = 0;
1116 /* initialize database support, volume support, and logs */
1119 * Create security objects for the Rx server functionality. Historically
1120 * this was a single rxnull security object, since the tape controller was
1121 * run by an operator that had local access to the tape device and some
1122 * administrative privilege in the cell (to be able to perform volume-level
1123 * accesses), but on a machine that was not necessarily trusted to hold the
1126 * Such a configuration is, of course, insecure because anyone can make
1127 * inbound RPCs and manipulate the database, including creating bogus
1128 * dumps and restoring them! Additionally, in modern usage, butc is
1129 * frequently run with -localauth to authenticate its outbound connections
1130 * to the volservers and budb with the cell-wide key, in which case the
1131 * cell-wide key is present and could be used to authenticate incoming
1132 * connections as well.
1134 * If -localauth is in use, create the full barrage of server security
1135 * objects, including rxkad, so that inbound connections can be verified
1136 * to only be made by authenticated clients. Otherwise, only the rxnull
1137 * class is in use with a single server security object. Note that butc
1138 * will refuse to start in this configuration unless the
1139 * "-allow_unauthenticated" flag is provided, indicating that the operator
1140 * has ensured that incoming connections are appropriately restricted by
1141 * firewall configuration or network topology.
1145 nullObjects[RX_SECIDX_NULL] = rxnull_NewServerSecurityObject();
1146 if (!nullObjects[RX_SECIDX_NULL]) {
1147 TLog(0, "rxnull_NewServerSecurityObject");
1151 secObjs = nullObjects;
1153 /* Must be -localauth, so the cell keys are available. */
1154 afsconf_BuildServerSecurityObjects(butc_confdir, &allObjs, &numClasses);
1159 rx_NewServiceHost(host, 0, 1, "BUTC", secObjs, numClasses, TC_ExecuteRequest);
1161 TLog(0, "rx_NewService");
1164 rx_SetMaxProcs(service, 4);
1166 /* Establish connection to the backup database */
1167 code = udbClientInit(0, localauth, cellName);
1169 TapeLog(0, 0, code, 0, "Can't access backup database\n");
1172 /* This call is here to verify that we are authentiated.
1173 * The call does nothing and will return BUDB_NOTPERMITTED
1174 * if we don't belong.
1176 code = bcdb_deleteDump(0, 0, 0, 0);
1177 if (code == BUDB_NOTPERMITTED) {
1178 TapeLog(0, 0, code, 0, "Can't access backup database\n");
1183 #ifdef AFS_PTHREAD_ENV
1184 code = pthread_attr_init(&tattr);
1186 TapeLog(0, 0, code, 0,
1187 "Can't pthread_attr_init database monitor task");
1190 code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
1192 TapeLog(0, 0, code, 0,
1193 "Can't pthread_attr_setdetachstate database monitor task");
1197 code = pthread_create(&dbWatcherPid, &tattr, dbWatcher, (void *)2);
1198 AFS_SIGSET_RESTORE();
1201 LWP_CreateProcess(dbWatcher, 20480, LWP_NORMAL_PRIORITY, (void *)2,
1202 "dbWatcher", &dbWatcherPid);
1205 TapeLog(0, 0, code, 0, "Can't create database monitor task");
1209 TLog(0, "Starting Tape Coordinator: Port offset %u Debug level %u\n",
1210 portOffset, debugLevel);
1211 TLog(0, "Token expires: %s\n", cTIME(&tokenExpires));
1213 rx_StartServer(1); /* Donate this process to the server process pool */
1214 TLog(0, "Error: StartServer returned");
1218 #ifndef AFS_NT40_ENV
1219 #include "AFS_component_version_number.c"
1223 main(int argc, char **argv)
1225 struct cmd_syndesc *ts;
1226 struct cmd_item *ti;
1228 #ifdef AFS_AIX32_ENV
1230 * The following signal action for AIX is necessary so that in case of a
1231 * crash (i.e. core is generated) we can include the user's data section
1232 * in the core dump. Unfortunately, by default, only a partial core is
1233 * generated which, in many cases, isn't too useful.
1235 struct sigaction nsa;
1237 sigemptyset(&nsa.sa_mask);
1238 nsa.sa_handler = SIG_DFL;
1239 nsa.sa_flags = SA_FULLDUMP;
1240 sigaction(SIGSEGV, &nsa, NULL);
1241 sigaction(SIGABRT, &nsa, NULL);
1246 ts = cmd_CreateSyntax(NULL, WorkerBee, NULL, 0, "tape coordinator");
1247 cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "port offset");
1248 cmd_AddParm(ts, "-debuglevel", CMD_SINGLE, CMD_OPTIONAL, "0 | 1 | 2");
1249 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
1250 cmd_AddParm(ts, "-device", CMD_SINGLE, (CMD_OPTIONAL | CMD_HIDE),
1251 "tape device path");
1252 cmd_AddParm(ts, "-noautoquery", CMD_FLAG, CMD_OPTIONAL,
1253 "do not query operator for first tape");
1254 cmd_AddParm(ts, "-localauth", CMD_FLAG, CMD_OPTIONAL,
1255 "create tickets from KeyFile");
1256 cmd_AddParm(ts, "-restoretofile", CMD_SINGLE, (CMD_OPTIONAL | CMD_HIDE),
1257 "file to restore to");
1258 cmd_AddParm(ts, "-xbsaforcemultiple", CMD_FLAG, (CMD_OPTIONAL | CMD_HIDE),
1259 "Force multiple XBSA server support");
1260 cmd_AddParm(ts, "-rxbind", CMD_FLAG, CMD_OPTIONAL,
1262 cmd_AddParm(ts, "-auditlog", CMD_LIST, CMD_OPTIONAL,
1263 "[interface:]path[:options]");
1264 cmd_AddParm(ts, "-audit-interface", CMD_SINGLE, CMD_OPTIONAL,
1265 "default interface");
1266 cmd_AddParm(ts, "-allow_unauthenticated", CMD_FLAG, CMD_OPTIONAL,
1267 "allow unauthenticated inbound RPCs (requires firewalling)");
1269 /* Initialize dirpaths */
1270 if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
1272 ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0);
1274 fprintf(stderr, "Unable to obtain AFS server directory.\n");
1278 /* setup the file paths */
1279 strcompose(eFile, AFSDIR_PATH_MAX, AFSDIR_SERVER_BACKUP_DIRPATH, "/",
1280 TE_PREFIX, (char *)NULL);
1281 strcompose(lFile, AFSDIR_PATH_MAX, AFSDIR_SERVER_BACKUP_DIRPATH, "/",
1282 TL_PREFIX, (char *)NULL);
1283 strcompose(pFile, AFSDIR_PATH_MAX, AFSDIR_SERVER_BACKUP_DIRPATH, "/",
1284 CFG_PREFIX, (char *)NULL);
1285 strcpy(tapeConfigFile, AFSDIR_SERVER_TAPECONFIG_FILEPATH);
1287 /* special case "no args" case since cmd_dispatch gives help message
1291 ts = calloc(1, sizeof(struct cmd_syndesc));
1293 ti = malloc(sizeof(struct cmd_item));
1296 ts->parms[0].items = ti;
1297 ti = malloc(sizeof(struct cmd_item));
1300 ts->parms[1].items = ti;
1301 ts->parms[2].items = NULL;
1302 ts->parms[3].items = NULL;
1303 ts->parms[4].items = NULL;
1304 ts->parms[5].items = NULL;
1305 return WorkerBee(ts, NULL);
1307 return cmd_Dispatch(argc, argv);