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>
29 * VLDB entry conversion routines.
30 * convert from one type of VLDB record to another. There are only
31 * two types "old" and "new".
35 OldVLDB_to_NewVLDB(struct vldbentry *source, struct nvldbentry *dest,
42 memset(dest, 0, sizeof(struct nvldbentry));
43 strncpy(dest->name, source->name, sizeof(dest->name));
44 for (i = 0; i < source->nServers; i++) {
45 dest->serverNumber[i] = source->serverNumber[i];
46 dest->serverPartition[i] = source->serverPartition[i];
47 dest->serverFlags[i] = source->serverFlags[i];
49 dest->nServers = source->nServers;
50 for (i = 0; i < MAXTYPES; i++)
51 dest->volumeId[i] = source->volumeId[i];
52 dest->cloneId = source->cloneId;
53 dest->flags = source->flags;
64 * We can fail to store the new to old VLDB record if there are more
65 * servers in the cell than the old format can handle. If we fail,
70 NewVLDB_to_OldVLDB(struct nvldbentry *source, struct vldbentry *dest,
77 memset(dest, 0, sizeof(struct vldbentry));
78 strncpy(dest->name, source->name, sizeof(dest->name));
79 if (source->nServers <= OMAXNSERVERS) {
80 for (i = 0; i < source->nServers; i++) {
81 dest->serverNumber[i] = source->serverNumber[i];
82 dest->serverPartition[i] = source->serverPartition[i];
83 dest->serverFlags[i] = source->serverFlags[i];
86 for (i = 0; i < MAXTYPES; i++)
87 dest->volumeId[i] = source->volumeId[i];
88 dest->cloneId = source->cloneId;
89 dest->flags = source->flags;
102 VLDB_CreateEntry(afs_cell_handle_p cellHandle, struct nvldbentry *entryp,
105 struct vldbentry oentry;
106 afs_status_t tst = 0;
110 if (cellHandle->vos_new) {
111 tst = ubik_VL_CreateEntryN(cellHandle->vos, 0, entryp);
113 if (tst == RXGEN_OPCODE) {
114 cellHandle->vos_new = 0;
120 if (NewVLDB_to_OldVLDB(entryp, &oentry, &tst)) {
121 tst = ubik_VL_CreateEntry(cellHandle->vos, 0, &oentry);
127 } while (tst == RXGEN_OPCODE);
136 aVLDB_GetEntryByID(afs_cell_handle_p cellHandle, afs_int32 volid,
137 afs_int32 voltype, struct nvldbentry *entryp,
140 struct vldbentry oentry;
141 afs_status_t tst = 0;
145 if (cellHandle->vos_new) {
147 ubik_VL_GetEntryByIDN(cellHandle->vos, 0, volid,
150 if (tst == RXGEN_OPCODE) {
151 cellHandle->vos_new = 0;
158 ubik_VL_GetEntryByID(cellHandle->vos, 0, volid, voltype,
161 rc = OldVLDB_to_NewVLDB(&oentry, entryp, &tst);
165 } while (tst == RXGEN_OPCODE);
174 aVLDB_GetEntryByName(afs_cell_handle_p cellHandle, const char *namep,
175 struct nvldbentry *entryp, afs_status_p st)
177 struct vldbentry oentry;
178 afs_status_t tst = 0;
182 if (cellHandle->vos_new) {
184 ubik_VL_GetEntryByNameN(cellHandle->vos, 0, namep,
187 if (tst == RXGEN_OPCODE) {
188 cellHandle->vos_new = 0;
195 ubik_VL_GetEntryByNameO(cellHandle->vos, 0, namep,
198 rc = OldVLDB_to_NewVLDB(&oentry, entryp, &tst);
202 } while (tst == RXGEN_OPCODE);
211 VLDB_ReplaceEntry(afs_cell_handle_p cellHandle, afs_int32 volid,
212 afs_int32 voltype, struct nvldbentry *entryp,
213 afs_int32 releasetype, afs_status_p st)
215 struct vldbentry oentry;
216 afs_status_t tst = 0;
220 if (cellHandle->vos_new) {
222 ubik_VL_ReplaceEntryN(cellHandle->vos, 0, volid,
223 voltype, entryp, releasetype);
225 if (tst == RXGEN_OPCODE) {
226 cellHandle->vos_new = 0;
232 if (NewVLDB_to_OldVLDB(entryp, &oentry, &tst)) {
234 ubik_VL_ReplaceEntry(cellHandle->vos, 0, volid,
235 voltype, &oentry, releasetype);
241 } while (tst == RXGEN_OPCODE);
250 VLDB_ListAttributes(afs_cell_handle_p cellHandle,
251 VldbListByAttributes * attrp, afs_int32 * entriesp,
252 nbulkentries * blkentriesp, afs_status_p st)
254 bulkentries arrayEntries;
256 afs_status_t tst = 0;
260 if (cellHandle->vos_new) {
262 ubik_VL_ListAttributesN(cellHandle->vos, 0, attrp,
263 entriesp, blkentriesp);
265 if (tst == RXGEN_OPCODE) {
266 cellHandle->vos_new = 0;
272 memset((void *)&arrayEntries, 0, sizeof(arrayEntries));
274 ubik_VL_ListAttributes(cellHandle->vos, 0, attrp,
275 entriesp, &arrayEntries);
277 blkentriesp->nbulkentries_val =
278 (nvldbentry *) malloc(*entriesp * sizeof(*blkentriesp));
279 if (blkentriesp->nbulkentries_val != NULL) {
280 for (i = 0; i < *entriesp; i++) {
281 OldVLDB_to_NewVLDB((struct vldbentry *)&arrayEntries.
283 (struct nvldbentry *)&blkentriesp->
284 nbulkentries_val[i], &tst);
289 if (arrayEntries.bulkentries_val) {
290 free(arrayEntries.bulkentries_val);
296 } while (tst == RXGEN_OPCODE);
305 VLDB_ListAttributesN2(afs_cell_handle_p cellHandle,
306 VldbListByAttributes * attrp, char *name,
307 afs_int32 thisindex, afs_int32 * nentriesp,
308 nbulkentries * blkentriesp, afs_int32 * nextindexp,
312 afs_status_t tst = 0;
315 ubik_VL_ListAttributesN2(cellHandle->vos, 0, attrp,
316 (name ? name : ""), thisindex, nentriesp, blkentriesp,
329 VLDB_IsSameAddrs(afs_cell_handle_p cellHandle, afs_int32 serv1,
330 afs_int32 serv2, int *equal, afs_status_p st)
333 afs_status_t tst = 0;
335 ListAddrByAttributes attrs;
337 afs_uint32 *addrp, nentries, unique, i;
342 if (serv1 == serv2) {
345 goto fail_VLDB_IsSameAddrs;
348 memset(&attrs, 0, sizeof(attrs));
349 attrs.Mask = VLADDR_IPADDR;
350 attrs.ipaddr = serv1;
351 memset(&addrs, 0, sizeof(addrs));
352 memset(&uuid, 0, sizeof(uuid));
354 ubik_VL_GetAddrsU(cellHandle->vos, 0, &attrs, &uuid, &unique,
358 goto fail_VLDB_IsSameAddrs;
361 addrp = addrs.bulkaddrs_val;
362 for (i = 0; i < nentries; i++, addrp++) {
363 if (serv2 == *addrp) {
370 fail_VLDB_IsSameAddrs:
379 * GetVolumeInfo - retrieve information about a particular volume.
383 * IN cellHandle - a handle that corresponds to the cell where the volume
386 * IN volid - the volume to be retrieved.
388 * OUT rentry - the vldb entry of the volume.
390 * OUT server - the address of the server where the volume resides in
393 * OUT partition - the volume to be retrieved.
395 * OUT voltype - the type of volume retrieved.
399 * No locks are obtained or released by this function
403 * Returns != 0 upon successful completion.
407 GetVolumeInfo(afs_cell_handle_p cellHandle, unsigned int volid,
408 struct nvldbentry *rentry, afs_int32 * server,
409 afs_int32 * partition, afs_int32 * voltype, afs_status_p st)
415 if (!aVLDB_GetEntryByID(cellHandle, volid, -1, rentry, &tst)) {
417 goto fail_GetVolumeInfo;
420 if (volid == rentry->volumeId[ROVOL]) {
422 for (i = 0; i < rentry->nServers; i++) {
423 if ((index == -1) && (rentry->serverFlags[i] & ITSROVOL)
424 && !(rentry->serverFlags[i] & RO_DONTUSE))
429 goto fail_GetVolumeInfo;
431 *server = rentry->serverNumber[index];
432 *partition = rentry->serverPartition[index];
434 goto fail_GetVolumeInfo;
437 if ((index = Lp_GetRwIndex(cellHandle, rentry, &tst)) < 0) {
438 goto fail_GetVolumeInfo;
440 if (volid == rentry->volumeId[RWVOL]) {
442 *server = rentry->serverNumber[index];
443 *partition = rentry->serverPartition[index];
444 } else if (volid == rentry->volumeId[BACKVOL]) {
446 *server = rentry->serverNumber[index];
447 *partition = rentry->serverPartition[index];
460 * ValidateVolumeName - validate a potential volume name
464 * IN volumeName - the volume name to be validated.
468 * No locks are obtained or released by this function
472 * Returns != 0 upon successful completion.
476 ValidateVolumeName(const char *volumeName, afs_status_p st)
479 afs_status_t tst = 0;
482 if ((volumeName == NULL) || (*volumeName == 0)) {
483 tst = ADMVOSVOLUMENAMENULL;
484 goto fail_ValidateVolumeName;
487 if (!ISNAMEVALID(volumeName)) {
488 tst = ADMVOSVOLUMENAMETOOLONG;
489 goto fail_ValidateVolumeName;
492 len = strlen(volumeName);
494 if (((len > 8) && (!strcmp(&volumeName[len - 9], ".readonly")))
495 || ((len > 6) && (!strcmp(&volumeName[len - 7], ".backup")))) {
496 tst = ADMVOSVOLUMENAMEINVALID;
497 goto fail_ValidateVolumeName;
502 fail_ValidateVolumeName:
511 /*extract the name of volume <name> without readonly or backup suffixes
512 * and return the result as <rname>.
515 vsu_ExtractName(char *rname, char *name)
520 strncpy(sname, name, 32);
522 total = strlen(sname);
523 if ((total > 9) && (!strcmp(&sname[total - 9], ".readonly"))) {
524 /*discard the last 8 chars */
525 sname[total - 9] = '\0';
526 strcpy(rname, sname);
528 } else if ((total > 7) && (!strcmp(&sname[total - 7], ".backup"))) {
529 /*discard last 6 chars */
530 sname[total - 7] = '\0';
531 strcpy(rname, sname);
534 strncpy(rname, name, VOLSER_OLDMAXVOLNAME);
542 * AddressMatch - determines if an IP address matches a pattern
546 * IN addrTest - the IP address to test, in either byte-order
547 * IN addrPattern - the IP address pattern, in the same byte-order
551 * No locks are obtained or released by this function
555 * Returns != 0 if the address matches the pattern specified
556 * (where 255 in any byte in the pattern indicates a wildcard).
560 AddressMatch(int addrTest, int addrPattern)
565 /* Test the high byte */
566 bTest = addrTest >> 24;
567 bPattern = addrPattern >> 24;
568 if ((bTest != bPattern) && (bPattern != 255)) {
572 /* Test the next-highest byte */
573 bTest = (addrTest >> 16) & 255;
574 bPattern = (addrPattern >> 16) & 255;
575 if ((bTest != bPattern) && (bPattern != 255)) {
579 /* Test the next-to-lowest byte */
580 bTest = (addrTest >> 8) & 255;
581 bPattern = (addrPattern >> 8) & 255;
582 if ((bTest != bPattern) && (bPattern != 255)) {
586 /* Test the low byte */
587 bTest = addrTest & 255;
588 bPattern = addrPattern & 255;
589 if ((bTest != bPattern) && (bPattern != 255)) {
598 * RemoveBadAddresses - (optionally) removes addresses that are better ignored
602 * IN OUT totalp - the number of addresses in the addrsp structure
603 * IN OUT addrsp - a bulk array of addresses
607 * No locks are obtained or released by this function
611 * Returns != 0 upon successful completion.
614 static pthread_once_t badaddr_init_once = PTHREAD_ONCE_INIT;
615 static int addr_to_skip;
623 #define cszREG_IGNORE_KEY "Software\\OpenAFS\\AFS Control Center"
624 #define cszREG_IGNORE_VALUE "IgnoreBadAddrs"
627 * In order for this routine to do anything, it must first validate
628 * that the user of this machine wants this filtering to take place.
629 * There is an undocumented registry value which signifies that it's
630 * okay to filter bogus IP addresses--and, moreover, indicates
631 * the range of values which may be ignored. Check that value.
635 addr_to_skip = 0; /* don't ignore any addrs unless we find otherwise */
636 if (RegOpenKey(HKEY_LOCAL_MACHINE, cszREG_IGNORE_KEY, &hk) == 0) {
637 DWORD dwType = REG_DWORD;
638 DWORD dwSize = sizeof(addr_to_skip);
639 RegQueryValueEx(hk, cszREG_IGNORE_VALUE, 0, &dwType,
640 (PBYTE) & addr_to_skip, &dwSize);
646 * We only support this functionality (so far) on NT; on other
647 * platforms, we'll never ignore IP addresses. If the feature
648 * is needed in the future, here's the place to add it.
652 addr_to_skip = 0; /* don't skip any addresses */
659 RemoveBadAddresses(afs_int32 * totalp, bulkaddrs * addrsp)
661 pthread_once(&badaddr_init_once, badaddr_once);
664 * If we've been requested to skip anything, addr_to_skip will be
665 * non-zero. It's actually an IP address of the form:
667 * A "255" means any value is acceptable, and any other value means
668 * the to-be-skipped address must match that value.
671 if (addr_to_skip && addrsp && addrsp->bulkaddrs_val) {
674 for (; iiRead < addrsp->bulkaddrs_len; ++iiRead) {
677 * Check this IP address to see if it should be skipped.
680 if (!AddressMatch(addrsp->bulkaddrs_val[iiRead], addr_to_skip)) {
683 * The address is okay; make sure it stays in the list.
686 if (iiWrite != iiRead) {
687 addrsp->bulkaddrs_val[iiWrite] =
688 addrsp->bulkaddrs_val[iiRead];
694 *totalp = (afs_int32) iiWrite;
695 addrsp->bulkaddrs_len = iiWrite;