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>
15 #include <afs/afs_AdminErrors.h>
19 #include "lockprocs.h"
22 * VLDB entry conversion routines.
23 * convert from one type of VLDB record to another. There are only
24 * two types "old" and "new".
28 OldVLDB_to_NewVLDB(struct vldbentry *source, struct nvldbentry *dest,
35 memset(dest, 0, sizeof(struct nvldbentry));
36 strncpy(dest->name, source->name, sizeof(dest->name));
37 for (i = 0; i < source->nServers; i++) {
38 dest->serverNumber[i] = source->serverNumber[i];
39 dest->serverPartition[i] = source->serverPartition[i];
40 dest->serverFlags[i] = source->serverFlags[i];
42 dest->nServers = source->nServers;
43 for (i = 0; i < MAXTYPES; i++)
44 dest->volumeId[i] = source->volumeId[i];
45 dest->cloneId = source->cloneId;
46 dest->flags = source->flags;
57 * We can fail to store the new to old VLDB record if there are more
58 * servers in the cell than the old format can handle. If we fail,
63 NewVLDB_to_OldVLDB(struct nvldbentry *source, struct vldbentry *dest,
70 memset(dest, 0, sizeof(struct vldbentry));
71 strncpy(dest->name, source->name, sizeof(dest->name));
72 if (source->nServers <= OMAXNSERVERS) {
73 for (i = 0; i < source->nServers; i++) {
74 dest->serverNumber[i] = source->serverNumber[i];
75 dest->serverPartition[i] = source->serverPartition[i];
76 dest->serverFlags[i] = source->serverFlags[i];
79 for (i = 0; i < MAXTYPES; i++)
80 dest->volumeId[i] = source->volumeId[i];
81 dest->cloneId = source->cloneId;
82 dest->flags = source->flags;
95 VLDB_CreateEntry(afs_cell_handle_p cellHandle, struct nvldbentry *entryp,
98 struct vldbentry oentry;
103 if (cellHandle->vos_new) {
104 tst = ubik_VL_CreateEntryN(cellHandle->vos, 0, entryp);
106 if (tst == RXGEN_OPCODE) {
107 cellHandle->vos_new = 0;
113 if (NewVLDB_to_OldVLDB(entryp, &oentry, &tst)) {
114 tst = ubik_VL_CreateEntry(cellHandle->vos, 0, &oentry);
120 } while (tst == RXGEN_OPCODE);
129 aVLDB_GetEntryByID(afs_cell_handle_p cellHandle, afs_uint32 volid,
130 afs_int32 voltype, struct nvldbentry *entryp,
133 struct vldbentry oentry;
134 afs_status_t tst = 0;
138 if (cellHandle->vos_new) {
140 ubik_VL_GetEntryByIDN(cellHandle->vos, 0, volid,
143 if (tst == RXGEN_OPCODE) {
144 cellHandle->vos_new = 0;
151 ubik_VL_GetEntryByID(cellHandle->vos, 0, volid, voltype,
154 rc = OldVLDB_to_NewVLDB(&oentry, entryp, &tst);
158 } while (tst == RXGEN_OPCODE);
167 aVLDB_GetEntryByName(afs_cell_handle_p cellHandle, char *namep,
168 struct nvldbentry *entryp, afs_status_p st)
170 struct vldbentry oentry;
171 afs_status_t tst = 0;
175 if (cellHandle->vos_new) {
177 ubik_VL_GetEntryByNameN(cellHandle->vos, 0, namep,
180 if (tst == RXGEN_OPCODE) {
181 cellHandle->vos_new = 0;
188 ubik_VL_GetEntryByNameO(cellHandle->vos, 0, namep,
191 rc = OldVLDB_to_NewVLDB(&oentry, entryp, &tst);
195 } while (tst == RXGEN_OPCODE);
204 VLDB_ReplaceEntry(afs_cell_handle_p cellHandle, afs_uint32 volid,
205 afs_int32 voltype, struct nvldbentry *entryp,
206 afs_int32 releasetype, afs_status_p st)
208 struct vldbentry oentry;
209 afs_status_t tst = 0;
213 if (cellHandle->vos_new) {
215 ubik_VL_ReplaceEntryN(cellHandle->vos, 0, volid,
216 voltype, entryp, releasetype);
218 if (tst == RXGEN_OPCODE) {
219 cellHandle->vos_new = 0;
225 if (NewVLDB_to_OldVLDB(entryp, &oentry, &tst)) {
227 ubik_VL_ReplaceEntry(cellHandle->vos, 0, volid,
228 voltype, &oentry, releasetype);
234 } while (tst == RXGEN_OPCODE);
243 VLDB_ListAttributes(afs_cell_handle_p cellHandle,
244 VldbListByAttributes * attrp, afs_int32 * entriesp,
245 nbulkentries * blkentriesp, afs_status_p st)
247 bulkentries arrayEntries;
249 afs_status_t tst = 0;
253 if (cellHandle->vos_new) {
255 ubik_VL_ListAttributesN(cellHandle->vos, 0, attrp,
256 entriesp, blkentriesp);
258 if (tst == RXGEN_OPCODE) {
259 cellHandle->vos_new = 0;
264 if (*entriesp > blkentriesp->nbulkentries_len)
265 *entriesp = blkentriesp->nbulkentries_len;
269 memset((void *)&arrayEntries, 0, sizeof(arrayEntries));
271 ubik_VL_ListAttributes(cellHandle->vos, 0, attrp,
272 entriesp, &arrayEntries);
277 if (*entriesp > arrayEntries.bulkentries_len)
278 *entriesp = arrayEntries.bulkentries_len;
281 blkentriesp->nbulkentries_val =
282 calloc(*entriesp, sizeof(struct nvldbentry));
283 if (blkentriesp->nbulkentries_val != NULL) {
284 for (i = 0; i < *entriesp; i++) {
285 OldVLDB_to_NewVLDB((struct vldbentry *)&arrayEntries.
287 (struct nvldbentry *)&blkentriesp->
288 nbulkentries_val[i], &tst);
294 blkentriesp->nbulkentries_val = NULL;
297 xdr_free((xdrproc_t)xdr_bulkentries, &arrayEntries);
303 } while (tst == RXGEN_OPCODE);
312 VLDB_ListAttributesN2(afs_cell_handle_p cellHandle,
313 VldbListByAttributes * attrp, char *name,
314 afs_int32 thisindex, afs_int32 * nentriesp,
315 nbulkentries * blkentriesp, afs_int32 * nextindexp,
319 afs_status_t tst = 0;
322 ubik_VL_ListAttributesN2(cellHandle->vos, 0, attrp,
323 (name ? name : ""), thisindex, nentriesp, blkentriesp,
336 VLDB_IsSameAddrs(afs_cell_handle_p cellHandle, afs_int32 serv1,
337 afs_int32 serv2, int *equal, afs_status_p st)
340 afs_status_t tst = 0;
342 ListAddrByAttributes attrs;
345 afs_int32 nentries, unique, i;
350 if (serv1 == serv2) {
353 goto fail_VLDB_IsSameAddrs;
356 memset(&attrs, 0, sizeof(attrs));
357 attrs.Mask = VLADDR_IPADDR;
358 attrs.ipaddr = serv1;
359 memset(&addrs, 0, sizeof(addrs));
360 memset(&uuid, 0, sizeof(uuid));
362 ubik_VL_GetAddrsU(cellHandle->vos, 0, &attrs, &uuid, &unique,
366 goto fail_VLDB_IsSameAddrs;
369 addrp = addrs.bulkaddrs_val;
370 for (i = 0; i < nentries; i++, addrp++) {
371 if (serv2 == *addrp) {
378 fail_VLDB_IsSameAddrs:
387 * GetVolumeInfo - retrieve information about a particular volume.
391 * IN cellHandle - a handle that corresponds to the cell where the volume
394 * IN volid - the volume to be retrieved.
396 * OUT rentry - the vldb entry of the volume.
398 * OUT server - the address of the server where the volume resides in
401 * OUT partition - the volume to be retrieved.
403 * OUT voltype - the type of volume retrieved.
407 * No locks are obtained or released by this function
411 * Returns != 0 upon successful completion.
415 GetVolumeInfo(afs_cell_handle_p cellHandle, afs_uint32 volid,
416 struct nvldbentry *rentry, afs_int32 * server,
417 afs_int32 * partition, afs_int32 * voltype, afs_status_p st)
423 if (!aVLDB_GetEntryByID(cellHandle, volid, -1, rentry, &tst)) {
425 goto fail_GetVolumeInfo;
428 if (volid == rentry->volumeId[ROVOL]) {
430 for (i = 0; i < rentry->nServers; i++) {
431 if ((index == -1) && (rentry->serverFlags[i] & VLSF_ROVOL)
432 && !(rentry->serverFlags[i] & VLSF_DONTUSE))
437 goto fail_GetVolumeInfo;
439 *server = rentry->serverNumber[index];
440 *partition = rentry->serverPartition[index];
442 goto fail_GetVolumeInfo;
445 if ((index = Lp_GetRwIndex(cellHandle, rentry, &tst)) < 0) {
446 goto fail_GetVolumeInfo;
448 if (volid == rentry->volumeId[RWVOL]) {
450 *server = rentry->serverNumber[index];
451 *partition = rentry->serverPartition[index];
452 } else if (volid == rentry->volumeId[BACKVOL]) {
454 *server = rentry->serverNumber[index];
455 *partition = rentry->serverPartition[index];
468 * ValidateVolumeName - validate a potential volume name
472 * IN volumeName - the volume name to be validated.
476 * No locks are obtained or released by this function
480 * Returns != 0 upon successful completion.
484 ValidateVolumeName(const char *volumeName, afs_status_p st)
487 afs_status_t tst = 0;
490 if ((volumeName == NULL) || (*volumeName == 0)) {
491 tst = ADMVOSVOLUMENAMENULL;
492 goto fail_ValidateVolumeName;
495 if (!ISNAMEVALID(volumeName)) {
496 tst = ADMVOSVOLUMENAMETOOLONG;
497 goto fail_ValidateVolumeName;
500 len = strlen(volumeName);
502 if (((len > 8) && (!strcmp(&volumeName[len - 9], ".readonly")))
503 || ((len > 6) && (!strcmp(&volumeName[len - 7], ".backup")))) {
504 tst = ADMVOSVOLUMENAMEINVALID;
505 goto fail_ValidateVolumeName;
510 fail_ValidateVolumeName:
519 /*extract the name of volume <name> without readonly or backup suffixes
520 * and return the result as <rname>.
523 vsu_ExtractName(char *rname, char *name)
528 strncpy(sname, name, 32);
530 total = strlen(sname);
531 if ((total > 9) && (!strcmp(&sname[total - 9], ".readonly"))) {
532 /*discard the last 8 chars */
533 sname[total - 9] = '\0';
534 strcpy(rname, sname);
536 } else if ((total > 7) && (!strcmp(&sname[total - 7], ".backup"))) {
537 /*discard last 6 chars */
538 sname[total - 7] = '\0';
539 strcpy(rname, sname);
542 strncpy(rname, name, VOLSER_OLDMAXVOLNAME);
550 * AddressMatch - determines if an IP address matches a pattern
554 * IN addrTest - the IP address to test, in either byte-order
555 * IN addrPattern - the IP address pattern, in the same byte-order
559 * No locks are obtained or released by this function
563 * Returns != 0 if the address matches the pattern specified
564 * (where 255 in any byte in the pattern indicates a wildcard).
568 AddressMatch(int addrTest, int addrPattern)
573 /* Test the high byte */
574 bTest = (addrTest >> 24) & 255;
575 bPattern = (addrPattern >> 24) & 255;
576 if ((bTest != bPattern) && (bPattern != 255)) {
580 /* Test the next-highest byte */
581 bTest = (addrTest >> 16) & 255;
582 bPattern = (addrPattern >> 16) & 255;
583 if ((bTest != bPattern) && (bPattern != 255)) {
587 /* Test the next-to-lowest byte */
588 bTest = (addrTest >> 8) & 255;
589 bPattern = (addrPattern >> 8) & 255;
590 if ((bTest != bPattern) && (bPattern != 255)) {
594 /* Test the low byte */
595 bTest = addrTest & 255;
596 bPattern = addrPattern & 255;
597 if ((bTest != bPattern) && (bPattern != 255)) {
606 * RemoveBadAddresses - (optionally) removes addresses that are better ignored
610 * IN OUT totalp - the number of addresses in the addrsp structure
611 * IN OUT addrsp - a bulk array of addresses
615 * No locks are obtained or released by this function
619 * Returns != 0 upon successful completion.
622 static pthread_once_t badaddr_init_once = PTHREAD_ONCE_INIT;
623 static int addr_to_skip;
631 #define cszREG_IGNORE_KEY "Software\\OpenAFS\\AFS Control Center"
632 #define cszREG_IGNORE_VALUE "IgnoreBadAddrs"
635 * In order for this routine to do anything, it must first validate
636 * that the user of this machine wants this filtering to take place.
637 * There is an undocumented registry value which signifies that it's
638 * okay to filter bogus IP addresses--and, moreover, indicates
639 * the range of values which may be ignored. Check that value.
643 addr_to_skip = 0; /* don't ignore any addrs unless we find otherwise */
644 if (RegOpenKey(HKEY_LOCAL_MACHINE, cszREG_IGNORE_KEY, &hk) == 0) {
645 DWORD dwType = REG_DWORD;
646 DWORD dwSize = sizeof(addr_to_skip);
647 RegQueryValueEx(hk, cszREG_IGNORE_VALUE, 0, &dwType,
648 (PBYTE) & addr_to_skip, &dwSize);
654 * We only support this functionality (so far) on NT; on other
655 * platforms, we'll never ignore IP addresses. If the feature
656 * is needed in the future, here's the place to add it.
660 addr_to_skip = 0; /* don't skip any addresses */
667 RemoveBadAddresses(afs_int32 * totalp, bulkaddrs * addrsp)
669 pthread_once(&badaddr_init_once, badaddr_once);
672 * If we've been requested to skip anything, addr_to_skip will be
673 * non-zero. It's actually an IP address of the form:
675 * A "255" means any value is acceptable, and any other value means
676 * the to-be-skipped address must match that value.
679 if (addr_to_skip && addrsp && addrsp->bulkaddrs_val) {
682 for (; iiRead < addrsp->bulkaddrs_len; ++iiRead) {
685 * Check this IP address to see if it should be skipped.
688 if (!AddressMatch(addrsp->bulkaddrs_val[iiRead], addr_to_skip)) {
691 * The address is okay; make sure it stays in the list.
694 if (iiWrite != iiRead) {
695 addrsp->bulkaddrs_val[iiWrite] =
696 addrsp->bulkaddrs_val[iiRead];
702 *totalp = (afs_int32) iiWrite;
703 addrsp->bulkaddrs_len = iiWrite;