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>
22 #include <sys/types.h>
25 #include <netinet/in.h>
26 #endif /* AFS_NT40_ENV */
29 #include <sys/statfs.h>
36 #include <rx/rx_globals.h>
38 #include <afs/vlserver.h>
39 #include <afs/cellconfig.h>
42 #include <afs/afsint.h>
49 #include "vsutils_prototypes.h"
51 struct ubik_client *cstruct;
52 static rxkad_level vsu_rxkad_level = rxkad_clear;
55 ovlentry_to_nvlentry(struct vldbentry *oentryp,
56 struct nvldbentry *nentryp)
60 memset(nentryp, 0, sizeof(struct nvldbentry));
61 strncpy(nentryp->name, oentryp->name, sizeof(nentryp->name));
62 for (i = 0; i < oentryp->nServers; i++) {
64 ListAddrByAttributes m_attrs;
67 m_attrs.Mask = VLADDR_IPADDR;
68 m_attrs.ipaddr = oentryp->serverNumber[i];
70 m_addrs.bulkaddrs_val = 0;
71 m_addrs.bulkaddrs_len = 0;
72 nentryp->serverNumber[i] = oentryp->serverNumber[i];
73 nentryp->serverPartition[i] = oentryp->serverPartition[i];
74 nentryp->serverFlags[i] = oentryp->serverFlags[i];
76 nentryp->nServers = oentryp->nServers;
77 for (i = 0; i < MAXTYPES; i++)
78 nentryp->volumeId[i] = oentryp->volumeId[i];
79 nentryp->cloneId = oentryp->cloneId;
80 nentryp->flags = oentryp->flags;
84 /* It is here for when we need it. Not currently used. */
86 nvlentry_to_ovlentry(struct nvldbentry *nentryp,
87 struct vldbentry *oentryp)
91 memset(oentryp, 0, sizeof(struct vldbentry));
92 strncpy(oentryp->name, nentryp->name, sizeof(oentryp->name));
93 if (nentryp->nServers > OMAXNSERVERS) {
95 * The alternative is to store OMAXSERVERS but it's always better
96 * to know what's going on...
100 for (i = 0; i < nentryp->nServers; i++) {
101 oentryp->serverNumber[i] = nentryp->serverNumber[i];
102 oentryp->serverPartition[i] = nentryp->serverPartition[i];
103 oentryp->serverFlags[i] = nentryp->serverFlags[i];
105 oentryp->nServers = i;
106 for (i = 0; i < MAXTYPES; i++)
107 oentryp->volumeId[i] = nentryp->volumeId[i];
108 oentryp->cloneId = nentryp->cloneId;
109 oentryp->flags = nentryp->flags;
115 ovlentry_to_uvlentry(struct vldbentry *oentryp,
116 struct uvldbentry *uentryp)
120 memset(uentryp, 0, sizeof(struct uvldbentry));
121 strncpy(uentryp->name, oentryp->name, sizeof(uentryp->name));
122 for (i = 0; i < oentryp->nServers; i++) {
123 afs_int32 vcode, m_uniq=0;
125 ListAddrByAttributes m_attrs;
126 afs_int32 m_nentries;
128 m_attrs.Mask = VLADDR_IPADDR;
129 m_attrs.ipaddr = oentryp->serverNumber[i];
131 m_addrs.bulkaddrs_val = 0;
132 m_addrs.bulkaddrs_len = 0;
134 ubik_VL_GetAddrsU(cstruct, 0, &m_attrs,
135 &uentryp->serverNumber[i],
136 &m_uniq, &m_nentries,
138 uentryp->serverUnique[i] = oentryp->serverNumber[i];
139 uentryp->serverPartition[i] = oentryp->serverPartition[i];
140 uentryp->serverFlags[i] = oentryp->serverFlags[i];
142 uentryp->nServers = oentryp->nServers;
143 for (i = 0; i < MAXTYPES; i++)
144 uentryp->volumeId[i] = oentryp->volumeId[i];
145 uentryp->cloneId = oentryp->cloneId;
146 uentryp->flags = oentryp->flags;
150 uvlentry_to_ovlentry(struct uvldbentry *uentryp,
151 struct vldbentry *oentryp)
155 memset(oentryp, 0, sizeof(struct vldbentry));
156 strncpy(oentryp->name, uentryp->name, sizeof(oentryp->name));
157 if (uentryp->nServers > OMAXNSERVERS) {
159 * The alternative is to store OMAXSERVERS but it's always better
160 * to know what's going on...
164 for (i = 0; i < uentryp->nServers; i++) {
165 oentryp->serverNumber[i] = uentryp->serverUnique[i];
166 oentryp->serverPartition[i] = uentryp->serverPartition[i];
167 oentryp->serverFlags[i] = uentryp->serverFlags[i];
169 oentryp->nServers = i;
170 for (i = 0; i < MAXTYPES; i++)
171 oentryp->volumeId[i] = uentryp->volumeId[i];
172 oentryp->cloneId = uentryp->cloneId;
173 oentryp->flags = uentryp->flags;
178 nvlentry_to_uvlentry(struct nvldbentry *nentryp,
179 struct uvldbentry *uentryp)
183 memset(uentryp, 0, sizeof(struct uvldbentry));
184 strncpy(uentryp->name, nentryp->name, sizeof(uentryp->name));
185 for (i = 0; i < nentryp->nServers; i++) {
186 afs_int32 vcode, m_uniq=0;
188 ListAddrByAttributes m_attrs;
189 afs_int32 m_nentries;
191 m_attrs.Mask = VLADDR_IPADDR;
192 m_attrs.ipaddr = nentryp->serverNumber[i];
194 m_addrs.bulkaddrs_val = 0;
195 m_addrs.bulkaddrs_len = 0;
197 ubik_VL_GetAddrsU(cstruct, 0, &m_attrs,
198 &uentryp->serverNumber[i],
199 &m_uniq, &m_nentries,
201 uentryp->serverUnique[i] = m_uniq;
202 uentryp->serverPartition[i] = nentryp->serverPartition[i];
203 uentryp->serverFlags[i] = nentryp->serverFlags[i];
204 uentryp->serverFlags[i] |= VLSERVER_FLAG_UUID;
206 uentryp->nServers = nentryp->nServers;
207 for (i = 0; i < MAXTYPES; i++)
208 uentryp->volumeId[i] = nentryp->volumeId[i];
209 uentryp->cloneId = nentryp->cloneId;
210 uentryp->flags = nentryp->flags;
211 uentryp->matchindex = nentryp->matchindex;
215 uvlentry_to_nvlentry(struct uvldbentry *uentryp,
216 struct nvldbentry *nentryp)
220 memset(nentryp, 0, sizeof(struct vldbentry));
221 strncpy(nentryp->name, uentryp->name, sizeof(nentryp->name));
222 if (uentryp->nServers > NMAXNSERVERS) {
224 * The alternative is to store NMAXSERVERS but it's always better
225 * to know what's going on...
229 for (i = 0; i < uentryp->nServers; i++) {
230 nentryp->serverNumber[i] = uentryp->serverUnique[i];
231 nentryp->serverPartition[i] = uentryp->serverPartition[i];
232 nentryp->serverFlags[i] = uentryp->serverFlags[i];
234 nentryp->nServers = i;
235 for (i = 0; i < MAXTYPES; i++)
236 nentryp->volumeId[i] = uentryp->volumeId[i];
237 nentryp->cloneId = uentryp->cloneId;
238 nentryp->flags = uentryp->flags;
239 nentryp->matchindex = uentryp->matchindex;
243 enum _vlserver_type {
250 static enum _vlserver_type newvlserver = vltype_unknown;
253 VLDB_CreateEntry(struct nvldbentry *entryp)
256 struct uvldbentry uentry;
258 nvlentry_to_uvlentry(entryp, &uentry);
259 code = VLDB_CreateEntryU(&uentry);
261 code = uvlentry_to_nvlentry(&uentry, entryp);
266 VLDB_CreateEntryU(struct uvldbentry *entryp)
268 struct nvldbentry nentry;
271 if (newvlserver == vltype_old) {
272 struct vldbentry oentry;
274 code = uvlentry_to_ovlentry(entryp, &oentry);
277 code = ubik_VL_CreateEntry(cstruct, 0, &oentry);
281 code = uvlentry_to_nvlentry(entryp, &nentry);
284 code = ubik_VL_CreateEntryN(cstruct, 0, &nentry);
285 if (code == RXGEN_OPCODE) {
286 newvlserver = vltype_old;
293 VLDB_GetEntryByID(afs_uint32 volid, afs_int32 voltype, struct nvldbentry *entryp)
296 struct uvldbentry uentry;
298 nvlentry_to_uvlentry(entryp, &uentry);
299 code = VLDB_GetEntryByIDU(volid, voltype, &uentry);
301 code = uvlentry_to_nvlentry(&uentry, entryp);
306 VLDB_GetEntryByIDU(afs_uint32 volid, afs_int32 voltype, struct uvldbentry *entryp)
308 struct nvldbentry nentry;
311 if (newvlserver == vltype_old) {
312 struct vldbentry oentry;
315 ubik_VL_GetEntryByID(cstruct, 0, volid, voltype, &oentry);
317 ovlentry_to_uvlentry(&oentry, entryp);
321 code = ubik_VL_GetEntryByIDN(cstruct, 0, volid, voltype, &nentry);
322 if (code == RXGEN_OPCODE) {
323 newvlserver = vltype_old;
327 nvlentry_to_uvlentry(&nentry, entryp);
332 VLDB_GetEntryByName(char *namep, struct nvldbentry *entryp)
335 struct uvldbentry uentry;
337 nvlentry_to_uvlentry(entryp, &uentry);
338 code = VLDB_GetEntryByNameU(namep, &uentry);
340 code = uvlentry_to_nvlentry(&uentry, entryp);
345 VLDB_GetEntryByNameU(char *namep, struct uvldbentry *entryp)
349 if (newvlserver == vltype_old) {
350 struct vldbentry oentry;
352 code = ubik_VL_GetEntryByNameO(cstruct, 0, namep, &oentry);
354 ovlentry_to_uvlentry(&oentry, entryp);
357 if (newvlserver == vltype_new) {
358 struct nvldbentry nentry;
360 code = ubik_VL_GetEntryByNameN(cstruct, 0, namep, &nentry);
361 if (code == RXGEN_OPCODE) {
362 newvlserver = vltype_old;
366 nvlentry_to_uvlentry(&nentry, entryp);
368 code = ubik_VL_GetEntryByNameU(cstruct, 0, namep, entryp);
369 if (newvlserver == vltype_unknown) {
370 if (code == RXGEN_OPCODE) {
371 newvlserver = vltype_new;
374 newvlserver = vltype_uuid;
381 VLDB_ReplaceEntry(afs_uint32 volid, afs_int32 voltype, struct nvldbentry *nentryp, afs_int32 releasetype)
383 struct uvldbentry uentry;
386 nvlentry_to_uvlentry(nentryp, &uentry);
387 code = VLDB_ReplaceEntryU(volid, voltype, &uentry, releasetype);
389 code = uvlentry_to_nvlentry(&uentry, nentryp);
395 VLDB_ReplaceEntryU(afs_uint32 volid, afs_int32 voltype, struct uvldbentry *entryp, afs_int32 releasetype)
398 struct nvldbentry nentry;
400 if (newvlserver == vltype_old) {
401 struct vldbentry oentry;
403 code = uvlentry_to_ovlentry(entryp, &oentry);
407 ubik_VL_ReplaceEntry(cstruct, 0, volid, voltype, &oentry, releasetype);
410 code = uvlentry_to_nvlentry(entryp, &nentry);
413 code = ubik_VL_ReplaceEntryN(cstruct, 0, volid, voltype, &nentry, releasetype);
414 if (code == RXGEN_OPCODE) {
415 newvlserver = vltype_old;
422 convertBulkToNBulk(bulkentries *bulk, nbulkentries *nbulk) {
425 if (bulk->bulkentries_len == 0)
428 nbulk->nbulkentries_len = bulk->bulkentries_len;
429 nbulk->nbulkentries_val =
430 xdr_alloc(bulk->bulkentries_len * sizeof(struct nvldbentry));
432 for (i = 0; i < bulk->bulkentries_len; i++) {
433 ovlentry_to_nvlentry(&bulk->bulkentries_val[i],
434 &nbulk->nbulkentries_val[i]);
439 convertBulkToUBulk(bulkentries *bulk, ubulkentries *ubulk) {
442 if (bulk->bulkentries_len == 0)
445 ubulk->ubulkentries_len = bulk->bulkentries_len;
446 ubulk->ubulkentries_val =
447 xdr_alloc(bulk->bulkentries_len * sizeof(struct uvldbentry));
448 for (i = 0; i < bulk->bulkentries_len; i++) {
449 ovlentry_to_uvlentry(&bulk->bulkentries_val[i],
450 &ubulk->ubulkentries_val[i]);
455 convertNBulkToUBulk(nbulkentries *nbulk, ubulkentries *ubulk) {
458 if (nbulk->nbulkentries_len == 0)
461 ubulk->ubulkentries_len = nbulk->nbulkentries_len;
462 ubulk->ubulkentries_val =
463 xdr_alloc(nbulk->nbulkentries_len * sizeof(struct uvldbentry));
464 for (i = 0; i < nbulk->nbulkentries_len; i++) { /* process each entry */
465 nvlentry_to_uvlentry(&nbulk->nbulkentries_val[i],
466 &ubulk->ubulkentries_val[i]);
471 VLDB_ListAttributes(VldbListByAttributes *attrp,
473 nbulkentries *blkentriesp)
477 if (newvlserver == vltype_old) {
478 bulkentries arrayEntries;
480 memset(&arrayEntries, 0, sizeof(arrayEntries));
482 ubik_VL_ListAttributes(cstruct, 0, attrp, entriesp,
488 /* Ensure the number of entries claimed matches the no. returned */
491 if (*entriesp > arrayEntries.bulkentries_len)
492 *entriesp = arrayEntries.bulkentries_len;
494 convertBulkToNBulk(&arrayEntries, blkentriesp);
496 xdr_free((xdrproc_t) xdr_bulkentries, &arrayEntries);
501 ubik_VL_ListAttributesN(cstruct, 0, attrp, entriesp, blkentriesp);
502 if (code == RXGEN_OPCODE) {
503 newvlserver = vltype_old; /* Doesn't support new interface */
510 /* Ensure the number of entries claimed matches the no. returned */
513 if (*entriesp > blkentriesp->nbulkentries_len)
514 *entriesp = blkentriesp->nbulkentries_len;
520 VLDB_ListAttributesU(VldbListByAttributes *attrp,
522 ubulkentries *blkentriesp)
524 nbulkentries narrayEntries;
527 if (newvlserver == vltype_old) {
528 bulkentries arrayEntries;
530 memset(&arrayEntries, 0, sizeof(arrayEntries));
532 ubik_VL_ListAttributes(cstruct, 0, attrp, entriesp,
537 /* Ensure the number of entries claimed matches the no. returned */
540 if (*entriesp > arrayEntries.bulkentries_len)
541 *entriesp = arrayEntries.bulkentries_len;
543 convertBulkToUBulk(&arrayEntries, blkentriesp);
545 xdr_free((xdrproc_t) xdr_bulkentries, &arrayEntries);
549 memset(&narrayEntries, 0, sizeof(narrayEntries));
551 ubik_VL_ListAttributesN(cstruct, 0, attrp, entriesp, &narrayEntries);
552 if (code == RXGEN_OPCODE) {
553 newvlserver = vltype_old; /* Doesn't support new interface */
559 /* Ensure the number of entries claimed matches the no. returned */
562 if (*entriesp > narrayEntries.nbulkentries_len)
563 *entriesp = narrayEntries.nbulkentries_len;
565 convertNBulkToUBulk(&narrayEntries, blkentriesp);
567 xdr_free((xdrproc_t) xdr_bulkentries, &narrayEntries);
572 VLDB_ListAttributesN2(VldbListByAttributes *attrp,
575 afs_int32 *nentriesp,
576 nbulkentries *blkentriesp,
577 afs_int32 *nextindexp)
579 afs_int32 code = RXGEN_OPCODE;
581 if (newvlserver != vltype_old) {
583 ubik_VL_ListAttributesN2(cstruct, 0, attrp, (name ? name : ""),
584 thisindex, nentriesp, blkentriesp, nextindexp);
588 /* Ensure the number of entries claimed matches the no. returned */
591 if (*nentriesp > blkentriesp->nbulkentries_len)
592 *nentriesp = blkentriesp->nbulkentries_len;
598 VLDB_ListAttributesN2U(VldbListByAttributes *attrp,
601 afs_int32 *nentriesp,
602 ubulkentries *blkentriesp,
603 afs_int32 *nextindexp)
605 afs_int32 code = RXGEN_OPCODE;
607 if (newvlserver != vltype_old) {
608 nbulkentries narrayEntries;
610 memset(&narrayEntries, 0, sizeof(narrayEntries)); /*initialize to hint the stub to alloc space */
612 ubik_VL_ListAttributesN2(cstruct, 0, attrp, (name ? name : ""),
613 thisindex, nentriesp, &narrayEntries, nextindexp);
617 /* Ensure the number of entries claimed matches the no. returned */
620 if (*nentriesp > narrayEntries.nbulkentries_len)
621 *nentriesp = narrayEntries.nbulkentries_len;
623 convertNBulkToUBulk(&narrayEntries, blkentriesp);
625 xdr_free((xdrproc_t) xdr_bulkentries, &narrayEntries);
635 afs_uint32 addrs[16];
638 * Increase cache size. This avoids high CPU usage by the vlserver
639 * in environments where there are more than 16 fileservers in the
642 #define GETADDRUCACHESIZE 64
643 struct cacheips cacheips[GETADDRUCACHESIZE];
644 int cacheip_index = 0;
647 VLDB_IsSameAddrs(afs_uint32 serv1, afs_uint32 serv2, afs_int32 *errorp)
650 ListAddrByAttributes attrs;
652 afs_uint32 *addrp, f1, f2;
653 afs_int32 i, j, unique, nentries;
655 static int initcache = 0;
661 if (newvlserver == vltype_old ||
662 newvlserver == vltype_new) {
666 for (i = 0; i < GETADDRUCACHESIZE; i++) {
667 cacheips[i].server = cacheips[i].count = 0;
672 /* See if it's cached */
673 for (i = 0; i < GETADDRUCACHESIZE; i++) {
675 for (j = 0; j < cacheips[i].count; j++) {
676 if (serv1 == cacheips[i].addrs[j])
678 else if (serv2 == cacheips[i].addrs[j])
686 if (cacheips[i].server == serv1)
690 memset(&attrs, 0, sizeof(attrs));
691 attrs.Mask = VLADDR_IPADDR;
692 attrs.ipaddr = serv1;
693 memset(&addrs, 0, sizeof(addrs));
694 memset(&uuid, 0, sizeof(uuid));
696 ubik_VL_GetAddrsU(cstruct, 0, &attrs, &uuid, &unique, &nentries,
698 if (newvlserver == vltype_unknown) {
699 if (code == RXGEN_OPCODE) {
700 newvlserver = vltype_new;
703 newvlserver = vltype_uuid;
706 if (code == VL_NOENT)
714 if (nentries > GETADDRUCACHESIZE)
715 nentries = GETADDRUCACHESIZE; /* safety check; should not happen */
716 if (++cacheip_index >= GETADDRUCACHESIZE)
718 cacheips[cacheip_index].server = serv1;
719 cacheips[cacheip_index].count = nentries;
720 addrp = addrs.bulkaddrs_val;
721 for (i = 0; i < nentries; i++, addrp++) {
722 cacheips[cacheip_index].addrs[i] = *addrp;
723 if (serv2 == *addrp) {
732 Set encryption. If 'cryptflag' is nonzero, encrpytion is turned on
733 for authenticated connections; if zero, encryption is turned off.
734 Calling this function always results in a level of at least rxkad_auth;
735 to get a rxkad_clear connection, simply don't call this.
738 vsu_SetCrypt(int cryptflag)
741 vsu_rxkad_level = rxkad_crypt;
743 vsu_rxkad_level = rxkad_auth;
749 Get the appropriate type of ubik client structure out from the system.
752 vsu_ClientInit(int noAuthFlag, const char *confDir, char *cellName, afs_int32 sauth,
753 struct ubik_client **uclientp,
754 int (*secproc)(struct rx_securityClass *, afs_int32))
756 return ugen_ClientInit(noAuthFlag, confDir, cellName, sauth, uclientp,
757 secproc, "vsu_ClientInit", vsu_rxkad_level,
758 VLDB_MAXSERVERS, AFSCONF_VLDBSERVICE, 90,
759 0, 0, USER_SERVICE_ID);
763 /*extract the name of volume <name> without readonly or backup suffixes
764 * and return the result as <rname>.
767 vsu_ExtractName(char rname[], char name[])
769 char sname[VOLSER_OLDMAXVOLNAME + 1];
772 strncpy(sname, name, sizeof(sname));
773 sname[sizeof(sname) - 1] = '\0';
774 total = strlen(sname);
775 if (!strcmp(&sname[total - 9], ".readonly")) {
776 /*discard the last 8 chars */
777 sname[total - 9] = '\0';
778 strcpy(rname, sname);
780 } else if (!strcmp(&sname[total - 7], ".backup")) {
781 /*discard last 6 chars */
782 sname[total - 7] = '\0';
783 strcpy(rname, sname);
786 strncpy(rname, name, VOLSER_OLDMAXVOLNAME);
787 rname[VOLSER_OLDMAXVOLNAME] = '\0';
792 /* returns 0 if failed */
794 vsu_GetVolumeID(char *astring, struct ubik_client *acstruct, afs_int32 *errp)
796 char volname[VOLSER_OLDMAXVOLNAME + 1];
797 struct uvldbentry entry;
803 if (isdigit(astring[0])) {
806 result = strtoul(astring, &end, 10);
807 if (result != UINT_MAX && *end == '\0')
811 /* It was not a volume number but something else */
812 total = strlen(astring);
813 vsu_ExtractName(volname, astring);
814 vcode = VLDB_GetEntryByNameU(volname, &entry);
816 if ((total >= 9) && (!strcmp(&astring[total - 9], ".readonly")))
817 return entry.volumeId[ROVOL];
818 else if ((total >= 7) && (!strcmp(&astring[total - 7], ".backup")))
819 return entry.volumeId[BACKVOL];
821 return (entry.volumeId[RWVOL]);
824 return 0; /* can't find volume */