/* * Copyright 2000, International Business Machines Corporation and others. * All Rights Reserved. * * This software has been released under the terms of the IBM Public * License. For details, see the LICENSE file in the top-level source * directory or online at http://www.openafs.org/dl/license10.html */ #include #include RCSID("$Header$"); #include #ifdef AFS_NT40_ENV #include #include #else #include #include #include #include #endif /* AFS_NT40_ENV */ #include #ifdef AFS_AIX_ENV #include #endif #ifdef HAVE_STRING_H #include #else #ifdef HAVE_STRINGS_H #include #endif #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "volser.h" #include "volint.h" #include "lockdata.h" struct ubik_client *cstruct; static rxkad_level vsu_rxkad_level = rxkad_clear; extern int VL_CreateEntry(), VL_CreateEntryN(); extern int VL_GetEntryByID(), VL_GetEntryByIDN(); extern int VL_GetEntryByNameO(), VL_GetEntryByNameN(); extern int VL_ReplaceEntry(), VL_ReplaceEntryN(); extern int VL_ListAttributes(), VL_ListAttributesN(), VL_ListAttributesN2(); static void ovlentry_to_nvlentry(oentryp, nentryp) struct vldbentry *oentryp; struct nvldbentry *nentryp; { register int i; memset(nentryp, 0, sizeof(struct nvldbentry)); strncpy(nentryp->name, oentryp->name, sizeof(nentryp->name)); for (i=0; i < oentryp->nServers; i++) { nentryp->serverNumber[i] = oentryp->serverNumber[i]; nentryp->serverPartition[i] = oentryp->serverPartition[i]; nentryp->serverFlags[i] = oentryp->serverFlags[i]; } nentryp->nServers = oentryp->nServers; for (i=0; ivolumeId[i] = oentryp->volumeId[i]; nentryp->cloneId = oentryp->cloneId; nentryp->flags = oentryp->flags; } static nvlentry_to_ovlentry(nentryp, oentryp) struct nvldbentry *nentryp; struct vldbentry *oentryp; { register int i; memset(oentryp, 0, sizeof(struct vldbentry)); strncpy(oentryp->name, nentryp->name, sizeof(oentryp->name)); if (nentryp->nServers > OMAXNSERVERS) { /* * The alternative is to store OMAXSERVERS but it's always better * to know what's going on... */ return VL_BADSERVER; } for (i=0; i < nentryp->nServers; i++) { oentryp->serverNumber[i] = nentryp->serverNumber[i]; oentryp->serverPartition[i] = nentryp->serverPartition[i]; oentryp->serverFlags[i] = nentryp->serverFlags[i]; } oentryp->nServers = i; for (i=0; ivolumeId[i] = nentryp->volumeId[i]; oentryp->cloneId = nentryp->cloneId; oentryp->flags = nentryp->flags; return 0; } static int newvlserver=0; VLDB_CreateEntry(entryp) struct nvldbentry *entryp; { struct vldbentry oentry; register int code; if (newvlserver == 1) { tryold: code = nvlentry_to_ovlentry(entryp, &oentry); if (code) return code; code = ubik_Call(VL_CreateEntry, cstruct, 0, &oentry); return code; } code = ubik_Call(VL_CreateEntryN, cstruct, 0, entryp); if (!newvlserver) { if (code == RXGEN_OPCODE) { newvlserver = 1; /* Doesn't support new interface */ goto tryold; } else if (!code) { newvlserver = 2; } } return code; } VLDB_GetEntryByID(volid, voltype, entryp) afs_int32 volid, voltype; struct nvldbentry *entryp; { struct vldbentry oentry; register int code; if (newvlserver == 1) { tryold: code = ubik_Call(VL_GetEntryByID, cstruct, 0, volid, voltype, &oentry); if (!code) ovlentry_to_nvlentry(&oentry, entryp); return code; } code = ubik_Call(VL_GetEntryByIDN, cstruct, 0, volid, voltype, entryp); if (!newvlserver) { if (code == RXGEN_OPCODE) { newvlserver = 1; /* Doesn't support new interface */ goto tryold; } else if (!code) { newvlserver = 2; } } return code; } VLDB_GetEntryByName(namep, entryp) char *namep; struct nvldbentry *entryp; { struct vldbentry oentry; register int code; if (newvlserver == 1) { tryold: code = ubik_Call(VL_GetEntryByNameO, cstruct, 0, namep, &oentry); if (!code) ovlentry_to_nvlentry(&oentry, entryp); return code; } code = ubik_Call(VL_GetEntryByNameN, cstruct, 0, namep, entryp); if (!newvlserver) { if (code == RXGEN_OPCODE) { newvlserver = 1; /* Doesn't support new interface */ goto tryold; } else if (!code) { newvlserver = 2; } } return code; } VLDB_ReplaceEntry(volid, voltype, entryp, releasetype) afs_int32 volid, voltype, releasetype; struct nvldbentry *entryp; { struct vldbentry oentry; register int code; if (newvlserver == 1) { tryold: code = nvlentry_to_ovlentry(entryp, &oentry); if (code) return code; code = ubik_Call(VL_ReplaceEntry, cstruct, 0, volid, voltype, &oentry, releasetype); return code; } code = ubik_Call(VL_ReplaceEntryN, cstruct, 0, volid, voltype, entryp, releasetype); if (!newvlserver) { if (code == RXGEN_OPCODE) { newvlserver = 1; /* Doesn't support new interface */ goto tryold; } else if (!code) { newvlserver = 2; } } return code; } VLDB_ListAttributes(attrp, entriesp, blkentriesp) VldbListByAttributes *attrp; afs_int32 *entriesp; nbulkentries *blkentriesp; { bulkentries arrayEntries; register int code, i; if (newvlserver == 1) { tryold: memset(&arrayEntries, 0, sizeof(arrayEntries)); /*initialize to hint the stub to alloc space */ code = ubik_Call(VL_ListAttributes, cstruct, 0, attrp, entriesp, &arrayEntries); if (!code) { blkentriesp->nbulkentries_val = (nvldbentry *)malloc(*entriesp * sizeof(struct nvldbentry)); for (i = 0; i < *entriesp; i++) { /* process each entry */ ovlentry_to_nvlentry(&arrayEntries.bulkentries_val[i], &blkentriesp->nbulkentries_val[i]); } } if (arrayEntries.bulkentries_val) free(arrayEntries.bulkentries_val); return code; } code = ubik_Call(VL_ListAttributesN, cstruct, 0, attrp, entriesp, blkentriesp); if (!newvlserver) { if (code == RXGEN_OPCODE) { newvlserver = 1; /* Doesn't support new interface */ goto tryold; } else if (!code) { newvlserver = 2; } } return code; } VLDB_ListAttributesN2(attrp, name, thisindex, nentriesp, blkentriesp, nextindexp) VldbListByAttributes *attrp; char *name; afs_int32 thisindex; afs_int32 *nentriesp; nbulkentries *blkentriesp; afs_int32 *nextindexp; { afs_int32 code; code = ubik_Call(VL_ListAttributesN2, cstruct, 0, attrp, (name?name:""), thisindex, nentriesp, blkentriesp, nextindexp); return code; } static int vlserverv4=-1; struct cacheips { afs_int32 server; afs_int32 count; afs_uint32 addrs[16]; }; /* * Increase cache size. This avoids high CPU usage by the vlserver * in environments where there are more than 16 fileservers in the * cell. */ #define GETADDRUCACHESIZE 64 struct cacheips cacheips[GETADDRUCACHESIZE]; int cacheip_index=0; extern int VL_GetAddrsU(); VLDB_IsSameAddrs(serv1, serv2, errorp) afs_int32 serv1, serv2, *errorp; { register int code; ListAddrByAttributes attrs; bulkaddrs addrs; afs_uint32 *addrp, nentries, unique, i, j, f1, f2; afsUUID uuid; static int initcache = 0; *errorp = 0; if (serv1 == serv2) return 1; if (vlserverv4 == 1) { return 0; } if (!initcache) { for (i=0; i < GETADDRUCACHESIZE; i++) { cacheips[i].server = cacheips[i].count = 0; } initcache = 1; } /* See if it's cached */ for (i=0; i < GETADDRUCACHESIZE; i++) { f1 = f2 = 0; for (j=0; j < cacheips[i].count; j++) { if (serv1 == cacheips[i].addrs[j]) f1 = 1; else if (serv2 == cacheips[i].addrs[j]) f2 = 1; if (f1 && f2) return 1; } if (f1 || f2) return 0; if (cacheips[i].server == serv1) return 0; } memset(&attrs, 0, sizeof(attrs)); attrs.Mask = VLADDR_IPADDR; attrs.ipaddr = serv1; memset(&addrs, 0, sizeof(addrs)); memset(&uuid, 0, sizeof(uuid)); code = ubik_Call(VL_GetAddrsU, cstruct, 0, &attrs, &uuid, &unique, &nentries, &addrs); if (vlserverv4 == -1) { if (code == RXGEN_OPCODE) { vlserverv4 = 1; /* Doesn't support new interface */ return 0; } else if (!code) { vlserverv4 = 2; } } if (code == VL_NOENT) return 0; if (code) { *errorp = code; return 0; } code = 0; if (nentries > GETADDRUCACHESIZE) nentries = GETADDRUCACHESIZE; /* safety check; should not happen */ if (++cacheip_index >= GETADDRUCACHESIZE) cacheip_index = 0; cacheips[cacheip_index].server = serv1; cacheips[cacheip_index].count = nentries; addrp = addrs.bulkaddrs_val; for (i=0; icellName, AFSCONF_VLDBSERVICE, &info); if (code) { fprintf(STDERR, "vsu_ClientInit: can't find cell %s's hosts in %s/%s\n", cellName, AFSDIR_SERVER_ETC_DIRPATH,AFSDIR_CELLSERVDB_FILE); exit(1); } } else { /* not -localauth */ tdir = afsconf_Open(confDir); if (!tdir) { fprintf(STDERR, "vsu_ClientInit: Could not process files in configuration directory (%s).\n", confDir); return -1; } if (!cellName) { code = afsconf_GetLocalCell(tdir, cellstr, sizeof(cellstr)); if (code) { fprintf(STDERR, "vsu_ClientInit: can't get local cellname, check %s/%s\n", confDir, AFSDIR_THISCELL_FILE); exit(1); } cellName = cellstr; } code = afsconf_GetCellInfo(tdir, cellName, AFSCONF_VLDBSERVICE, &info); if (code) { fprintf(STDERR, "vsu_ClientInit: can't find cell %s's hosts in %s/%s\n", cellName, confDir,AFSDIR_CELLSERVDB_FILE); exit(1); } if (noAuthFlag) /* -noauth */ scIndex = 0; else { /* not -noauth */ strcpy(sname.cell, info.name); sname.instance[0] = 0; strcpy(sname.name, "afs"); code = ktc_GetToken(&sname, &ttoken, sizeof(ttoken), NULL); if (code) { /* did not get ticket */ fprintf(STDERR, "vsu_ClientInit: Could not get afs tokens, running unauthenticated.\n"); scIndex = 0; } else { /* got a ticket */ scIndex = 2; if ((ttoken.kvno < 0) || (ttoken.kvno > 255)) { fprintf(STDERR, "vsu_ClientInit: funny kvno (%d) in ticket, proceeding\n", ttoken.kvno); } } } switch (scIndex) { case 0 : sc = rxnull_NewClientSecurityObject(); break; case 2: sc = rxkad_NewClientSecurityObject( vsu_rxkad_level, &ttoken.sessionKey, ttoken.kvno, ttoken.ticketLen, ttoken.ticket); break; default: fprintf(STDERR, "vsu_ClientInit: unsupported security index %d\n", scIndex); exit(1); break; } } afsconf_Close(tdir); if (secproc) /* tell UV module about default authentication */ (*secproc) (sc, scIndex); if (info.numServers > VLDB_MAXSERVERS) { fprintf(STDERR, "vsu_ClientInit: info.numServers=%d (> VLDB_MAXSERVERS=%d)\n", info.numServers, VLDB_MAXSERVERS); exit(1); } for (i=0; i without readonly or backup suffixes * and return the result as . */ vsu_ExtractName(rname,name) char rname[],name[]; { char sname[VOLSER_OLDMAXVOLNAME+1]; int total; strncpy(sname, name, sizeof(sname)); sname[sizeof(sname)-1] = '\0'; total = strlen(sname); if(!strcmp(&sname[total - 9],".readonly")) { /*discard the last 8 chars */ sname[total - 9] = '\0'; strcpy(rname, sname); return 0; } else if(!strcmp(&sname[total - 7],".backup")) { /*discard last 6 chars */ sname[total - 7] = '\0'; strcpy(rname,sname); return 0; } else { strncpy(rname,name,VOLSER_OLDMAXVOLNAME); rname[VOLSER_OLDMAXVOLNAME] = '\0'; return -1; } } /* returns 0 if failed */ afs_uint32 vsu_GetVolumeID(astring, acstruct, errp) struct ubik_client *acstruct; afs_int32 *errp; char *astring; { afs_uint32 tc, value; char *str,*ptr, volname[VOLSER_OLDMAXVOLNAME+1]; int tryname, curval; struct nvldbentry entry; afs_int32 vcode = 0; int total; *errp = 0; total = strlen(astring); str = astring; ptr = astring; tryname = 0; while ((curval = *str++)){ if(curval < '0' || curval > '9') tryname = 1; } if(tryname) { vsu_ExtractName(volname,astring); vcode = VLDB_GetEntryByName(volname, &entry); if(!vcode) { if(!strcmp(&astring[total - 9],".readonly")) return entry.volumeId[ROVOL]; else if ((!strcmp(&astring[total - 7 ],".backup"))) return entry.volumeId[BACKVOL]; else return (entry.volumeId[RWVOL]); } else { *errp = vcode; return 0; /* can't find volume */ } } value = 0; while ((tc = *astring++)) { if (tc & 0x80) { if(!tryname) fprintf(STDERR,"goofed in volid \n"); else {fprintf(STDERR,"Could not get entry from vldb for %s\n",ptr);PrintError("",vcode);} *errp = EINVAL; return 0; } if (tc < '0' || tc > '9'){ if(!tryname) fprintf(STDERR,"internal error: out of range char in vol ID\n"); else {fprintf(STDERR,"Could not get entry from vldb for %s\n",ptr);PrintError("",vcode);} *errp = ERANGE; return 0; } value *= 10; value += (tc - '0'); } return value; }