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>
18 #include "lockprocs.h"
19 #include <afs/afs_AdminErrors.h>
23 * VLDB entry conversion routines.
24 * convert from one type of VLDB record to another. There are only
25 * two types "old" and "new".
29 OldVLDB_to_NewVLDB(struct vldbentry *source, struct nvldbentry *dest,
36 memset(dest, 0, sizeof(struct nvldbentry));
37 strncpy(dest->name, source->name, sizeof(dest->name));
38 for (i = 0; i < source->nServers; i++) {
39 dest->serverNumber[i] = source->serverNumber[i];
40 dest->serverPartition[i] = source->serverPartition[i];
41 dest->serverFlags[i] = source->serverFlags[i];
43 dest->nServers = source->nServers;
44 for (i = 0; i < MAXTYPES; i++)
45 dest->volumeId[i] = source->volumeId[i];
46 dest->cloneId = source->cloneId;
47 dest->flags = source->flags;
58 * We can fail to store the new to old VLDB record if there are more
59 * servers in the cell than the old format can handle. If we fail,
64 NewVLDB_to_OldVLDB(struct nvldbentry *source, struct vldbentry *dest,
71 memset(dest, 0, sizeof(struct vldbentry));
72 strncpy(dest->name, source->name, sizeof(dest->name));
73 if (source->nServers <= OMAXNSERVERS) {
74 for (i = 0; i < source->nServers; i++) {
75 dest->serverNumber[i] = source->serverNumber[i];
76 dest->serverPartition[i] = source->serverPartition[i];
77 dest->serverFlags[i] = source->serverFlags[i];
80 for (i = 0; i < MAXTYPES; i++)
81 dest->volumeId[i] = source->volumeId[i];
82 dest->cloneId = source->cloneId;
83 dest->flags = source->flags;
96 VLDB_CreateEntry(afs_cell_handle_p cellHandle, struct nvldbentry *entryp,
99 struct vldbentry oentry;
100 afs_status_t tst = 0;
104 if (cellHandle->vos_new) {
105 tst = ubik_VL_CreateEntryN(cellHandle->vos, 0, entryp);
107 if (tst == RXGEN_OPCODE) {
108 cellHandle->vos_new = 0;
114 if (NewVLDB_to_OldVLDB(entryp, &oentry, &tst)) {
115 tst = ubik_VL_CreateEntry(cellHandle->vos, 0, &oentry);
121 } while (tst == RXGEN_OPCODE);
130 aVLDB_GetEntryByID(afs_cell_handle_p cellHandle, afs_int32 volid,
131 afs_int32 voltype, struct nvldbentry *entryp,
134 struct vldbentry oentry;
135 afs_status_t tst = 0;
139 if (cellHandle->vos_new) {
141 ubik_VL_GetEntryByIDN(cellHandle->vos, 0, volid,
144 if (tst == RXGEN_OPCODE) {
145 cellHandle->vos_new = 0;
152 ubik_VL_GetEntryByID(cellHandle->vos, 0, volid, voltype,
155 rc = OldVLDB_to_NewVLDB(&oentry, entryp, &tst);
159 } while (tst == RXGEN_OPCODE);
168 aVLDB_GetEntryByName(afs_cell_handle_p cellHandle, const char *namep,
169 struct nvldbentry *entryp, afs_status_p st)
171 struct vldbentry oentry;
172 afs_status_t tst = 0;
176 if (cellHandle->vos_new) {
178 ubik_VL_GetEntryByNameN(cellHandle->vos, 0, namep,
181 if (tst == RXGEN_OPCODE) {
182 cellHandle->vos_new = 0;
189 ubik_VL_GetEntryByNameO(cellHandle->vos, 0, namep,
192 rc = OldVLDB_to_NewVLDB(&oentry, entryp, &tst);
196 } while (tst == RXGEN_OPCODE);
205 VLDB_ReplaceEntry(afs_cell_handle_p cellHandle, afs_int32 volid,
206 afs_int32 voltype, struct nvldbentry *entryp,
207 afs_int32 releasetype, afs_status_p st)
209 struct vldbentry oentry;
210 afs_status_t tst = 0;
214 if (cellHandle->vos_new) {
216 ubik_VL_ReplaceEntryN(cellHandle->vos, 0, volid,
217 voltype, entryp, releasetype);
219 if (tst == RXGEN_OPCODE) {
220 cellHandle->vos_new = 0;
226 if (NewVLDB_to_OldVLDB(entryp, &oentry, &tst)) {
228 ubik_VL_ReplaceEntry(cellHandle->vos, 0, volid,
229 voltype, &oentry, releasetype);
235 } while (tst == RXGEN_OPCODE);
244 VLDB_ListAttributes(afs_cell_handle_p cellHandle,
245 VldbListByAttributes * attrp, afs_int32 * entriesp,
246 nbulkentries * blkentriesp, afs_status_p st)
248 bulkentries arrayEntries;
250 afs_status_t tst = 0;
254 if (cellHandle->vos_new) {
256 ubik_VL_ListAttributesN(cellHandle->vos, 0, attrp,
257 entriesp, blkentriesp);
259 if (tst == RXGEN_OPCODE) {
260 cellHandle->vos_new = 0;
266 memset((void *)&arrayEntries, 0, sizeof(arrayEntries));
268 ubik_VL_ListAttributes(cellHandle->vos, 0, attrp,
269 entriesp, &arrayEntries);
271 blkentriesp->nbulkentries_val =
272 (nvldbentry *) malloc(*entriesp * sizeof(*blkentriesp));
273 if (blkentriesp->nbulkentries_val != NULL) {
274 for (i = 0; i < *entriesp; i++) {
275 OldVLDB_to_NewVLDB((struct vldbentry *)&arrayEntries.
277 (struct nvldbentry *)&blkentriesp->
278 nbulkentries_val[i], &tst);
283 if (arrayEntries.bulkentries_val) {
284 free(arrayEntries.bulkentries_val);
290 } while (tst == RXGEN_OPCODE);
299 VLDB_ListAttributesN2(afs_cell_handle_p cellHandle,
300 VldbListByAttributes * attrp, char *name,
301 afs_int32 thisindex, afs_int32 * nentriesp,
302 nbulkentries * blkentriesp, afs_int32 * nextindexp,
306 afs_status_t tst = 0;
309 ubik_VL_ListAttributesN2(cellHandle->vos, 0, attrp,
310 (name ? name : ""), thisindex, nentriesp, blkentriesp,
323 VLDB_IsSameAddrs(afs_cell_handle_p cellHandle, afs_int32 serv1,
324 afs_int32 serv2, int *equal, afs_status_p st)
327 afs_status_t tst = 0;
329 ListAddrByAttributes attrs;
331 afs_uint32 *addrp, nentries, unique, i;
336 if (serv1 == serv2) {
339 goto fail_VLDB_IsSameAddrs;
342 memset(&attrs, 0, sizeof(attrs));
343 attrs.Mask = VLADDR_IPADDR;
344 attrs.ipaddr = serv1;
345 memset(&addrs, 0, sizeof(addrs));
346 memset(&uuid, 0, sizeof(uuid));
348 ubik_VL_GetAddrsU(cellHandle->vos, 0, &attrs, &uuid, &unique,
352 goto fail_VLDB_IsSameAddrs;
355 addrp = addrs.bulkaddrs_val;
356 for (i = 0; i < nentries; i++, addrp++) {
357 if (serv2 == *addrp) {
364 fail_VLDB_IsSameAddrs:
373 * GetVolumeInfo - retrieve information about a particular volume.
377 * IN cellHandle - a handle that corresponds to the cell where the volume
380 * IN volid - the volume to be retrieved.
382 * OUT rentry - the vldb entry of the volume.
384 * OUT server - the address of the server where the volume resides in
387 * OUT partition - the volume to be retrieved.
389 * OUT voltype - the type of volume retrieved.
393 * No locks are obtained or released by this function
397 * Returns != 0 upon successful completion.
401 GetVolumeInfo(afs_cell_handle_p cellHandle, unsigned int volid,
402 struct nvldbentry *rentry, afs_int32 * server,
403 afs_int32 * partition, afs_int32 * voltype, afs_status_p st)
409 if (!aVLDB_GetEntryByID(cellHandle, volid, -1, rentry, &tst)) {
411 goto fail_GetVolumeInfo;
414 if (volid == rentry->volumeId[ROVOL]) {
416 for (i = 0; i < rentry->nServers; i++) {
417 if ((index == -1) && (rentry->serverFlags[i] & ITSROVOL)
418 && !(rentry->serverFlags[i] & RO_DONTUSE))
423 goto fail_GetVolumeInfo;
425 *server = rentry->serverNumber[index];
426 *partition = rentry->serverPartition[index];
428 goto fail_GetVolumeInfo;
431 if ((index = Lp_GetRwIndex(cellHandle, rentry, &tst)) < 0) {
432 goto fail_GetVolumeInfo;
434 if (volid == rentry->volumeId[RWVOL]) {
436 *server = rentry->serverNumber[index];
437 *partition = rentry->serverPartition[index];
438 } else if (volid == rentry->volumeId[BACKVOL]) {
440 *server = rentry->serverNumber[index];
441 *partition = rentry->serverPartition[index];
454 * ValidateVolumeName - validate a potential volume name
458 * IN volumeName - the volume name to be validated.
462 * No locks are obtained or released by this function
466 * Returns != 0 upon successful completion.
470 ValidateVolumeName(const char *volumeName, afs_status_p st)
473 afs_status_t tst = 0;
476 if ((volumeName == NULL) || (*volumeName == 0)) {
477 tst = ADMVOSVOLUMENAMENULL;
478 goto fail_ValidateVolumeName;
481 if (!ISNAMEVALID(volumeName)) {
482 tst = ADMVOSVOLUMENAMETOOLONG;
483 goto fail_ValidateVolumeName;
486 len = strlen(volumeName);
488 if (((len > 8) && (!strcmp(&volumeName[len - 9], ".readonly")))
489 || ((len > 6) && (!strcmp(&volumeName[len - 7], ".backup")))) {
490 tst = ADMVOSVOLUMENAMEINVALID;
491 goto fail_ValidateVolumeName;
496 fail_ValidateVolumeName:
505 /*extract the name of volume <name> without readonly or backup suffixes
506 * and return the result as <rname>.
509 vsu_ExtractName(char *rname, char *name)
514 strncpy(sname, name, 32);
516 total = strlen(sname);
517 if ((total > 9) && (!strcmp(&sname[total - 9], ".readonly"))) {
518 /*discard the last 8 chars */
519 sname[total - 9] = '\0';
520 strcpy(rname, sname);
522 } else if ((total > 7) && (!strcmp(&sname[total - 7], ".backup"))) {
523 /*discard last 6 chars */
524 sname[total - 7] = '\0';
525 strcpy(rname, sname);
528 strncpy(rname, name, VOLSER_OLDMAXVOLNAME);
536 * AddressMatch - determines if an IP address matches a pattern
540 * IN addrTest - the IP address to test, in either byte-order
541 * IN addrPattern - the IP address pattern, in the same byte-order
545 * No locks are obtained or released by this function
549 * Returns != 0 if the address matches the pattern specified
550 * (where 255 in any byte in the pattern indicates a wildcard).
554 AddressMatch(int addrTest, int addrPattern)
559 /* Test the high byte */
560 bTest = addrTest >> 24;
561 bPattern = addrPattern >> 24;
562 if ((bTest != bPattern) && (bPattern != 255)) {
566 /* Test the next-highest byte */
567 bTest = (addrTest >> 16) & 255;
568 bPattern = (addrPattern >> 16) & 255;
569 if ((bTest != bPattern) && (bPattern != 255)) {
573 /* Test the next-to-lowest byte */
574 bTest = (addrTest >> 8) & 255;
575 bPattern = (addrPattern >> 8) & 255;
576 if ((bTest != bPattern) && (bPattern != 255)) {
580 /* Test the low byte */
581 bTest = addrTest & 255;
582 bPattern = addrPattern & 255;
583 if ((bTest != bPattern) && (bPattern != 255)) {
592 * RemoveBadAddresses - (optionally) removes addresses that are better ignored
596 * IN OUT totalp - the number of addresses in the addrsp structure
597 * IN OUT addrsp - a bulk array of addresses
601 * No locks are obtained or released by this function
605 * Returns != 0 upon successful completion.
608 static pthread_once_t badaddr_init_once = PTHREAD_ONCE_INIT;
609 static int addr_to_skip;
617 #define cszREG_IGNORE_KEY "Software\\OpenAFS\\AFS Control Center"
618 #define cszREG_IGNORE_VALUE "IgnoreBadAddrs"
621 * In order for this routine to do anything, it must first validate
622 * that the user of this machine wants this filtering to take place.
623 * There is an undocumented registry value which signifies that it's
624 * okay to filter bogus IP addresses--and, moreover, indicates
625 * the range of values which may be ignored. Check that value.
629 addr_to_skip = 0; /* don't ignore any addrs unless we find otherwise */
630 if (RegOpenKey(HKEY_LOCAL_MACHINE, cszREG_IGNORE_KEY, &hk) == 0) {
631 DWORD dwType = REG_DWORD;
632 DWORD dwSize = sizeof(addr_to_skip);
633 RegQueryValueEx(hk, cszREG_IGNORE_VALUE, 0, &dwType,
634 (PBYTE) & addr_to_skip, &dwSize);
640 * We only support this functionality (so far) on NT; on other
641 * platforms, we'll never ignore IP addresses. If the feature
642 * is needed in the future, here's the place to add it.
646 addr_to_skip = 0; /* don't skip any addresses */
653 RemoveBadAddresses(afs_int32 * totalp, bulkaddrs * addrsp)
655 pthread_once(&badaddr_init_once, badaddr_once);
658 * If we've been requested to skip anything, addr_to_skip will be
659 * non-zero. It's actually an IP address of the form:
661 * A "255" means any value is acceptable, and any other value means
662 * the to-be-skipped address must match that value.
665 if (addr_to_skip && addrsp && addrsp->bulkaddrs_val) {
668 for (; iiRead < addrsp->bulkaddrs_len; ++iiRead) {
671 * Check this IP address to see if it should be skipped.
674 if (!AddressMatch(addrsp->bulkaddrs_val[iiRead], addr_to_skip)) {
677 * The address is okay; make sure it stays in the list.
680 if (iiWrite != iiRead) {
681 addrsp->bulkaddrs_val[iiWrite] =
682 addrsp->bulkaddrs_val[iiRead];
688 *totalp = (afs_int32) iiWrite;
689 addrsp->bulkaddrs_len = iiWrite;