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
12 #include "lockprocs.h"
13 #include <afs/afs_AdminErrors.h>
22 * Functions that aren't prototyped, but that we use
25 extern int VL_CreateEntryN(), VL_CreateEntry(), VL_GetEntryByIDN(), VL_GetEntryByID(), VL_GetEntryByNameN(), VL_GetEntryByNameO(), VL_ReplaceEntryN(), VL_ReplaceEntry(), VL_ListAttributesN(), VL_ListAttributes(), VL_GetAddrsU();
28 * VLDB entry conversion routines.
29 * convert from one type of VLDB record to another. There are only
30 * two types "old" and "new".
33 static int OldVLDB_to_NewVLDB(
34 struct vldbentry *source,
35 struct nvldbentry *dest,
42 bzero(dest, 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,
69 static int NewVLDB_to_OldVLDB(
70 struct nvldbentry *source,
71 struct vldbentry *dest,
78 bzero(dest, sizeof(struct vldbentry));
79 strncpy(dest->name, source->name, sizeof(dest->name));
80 if (source->nServers <= OMAXNSERVERS) {
81 for (i = 0; i < source->nServers; i++) {
82 dest->serverNumber[i] = source->serverNumber[i];
83 dest->serverPartition[i] = source->serverPartition[i];
84 dest->serverFlags[i] = source->serverFlags[i];
87 for (i = 0; i < MAXTYPES; i++)
88 dest->volumeId[i] = source->volumeId[i];
89 dest->cloneId = source->cloneId;
90 dest->flags = source->flags;
102 int VLDB_CreateEntry(
103 afs_cell_handle_p cellHandle,
104 struct nvldbentry *entryp,
107 struct vldbentry oentry;
108 afs_status_t tst = 0;
112 if (cellHandle->vos_new) {
113 tst = ubik_Call(VL_CreateEntryN, cellHandle->vos, 0, entryp);
115 if (tst == RXGEN_OPCODE) {
116 cellHandle->vos_new = 0;
122 if (NewVLDB_to_OldVLDB(entryp, &oentry, &tst)) {
123 tst = ubik_Call(VL_CreateEntry, cellHandle->vos, 0, &oentry);
129 } while (tst == RXGEN_OPCODE);
137 int VLDB_GetEntryByID(
138 afs_cell_handle_p cellHandle,
141 struct nvldbentry *entryp,
144 struct vldbentry oentry;
145 afs_status_t tst = 0;
149 if (cellHandle->vos_new) {
150 tst = ubik_Call(VL_GetEntryByIDN, cellHandle->vos, 0, volid,
153 if (tst == RXGEN_OPCODE) {
154 cellHandle->vos_new = 0;
160 tst = ubik_Call(VL_GetEntryByID, cellHandle->vos, 0, volid,
163 rc = OldVLDB_to_NewVLDB(&oentry, entryp, &tst);
167 } while (tst == RXGEN_OPCODE);
175 int VLDB_GetEntryByName(
176 afs_cell_handle_p cellHandle,
178 struct nvldbentry *entryp,
181 struct vldbentry oentry;
182 afs_status_t tst = 0;
186 if (cellHandle->vos_new) {
187 tst = ubik_Call(VL_GetEntryByNameN, cellHandle->vos, 0, namep,
190 if (tst == RXGEN_OPCODE) {
191 cellHandle->vos_new = 0;
197 tst = ubik_Call(VL_GetEntryByNameO, cellHandle->vos, 0, namep,
200 rc = OldVLDB_to_NewVLDB(&oentry, entryp, &tst);
204 } while (tst == RXGEN_OPCODE);
212 int VLDB_ReplaceEntry(
213 afs_cell_handle_p cellHandle,
216 struct nvldbentry *entryp,
217 afs_int32 releasetype,
220 struct vldbentry oentry;
221 afs_status_t tst = 0;
225 if (cellHandle->vos_new) {
226 tst = ubik_Call(VL_ReplaceEntryN, cellHandle->vos, 0, volid,
227 voltype, entryp, releasetype);
229 if (tst == RXGEN_OPCODE) {
230 cellHandle->vos_new = 0;
236 if (NewVLDB_to_OldVLDB(entryp, &oentry, &tst)) {
237 tst = ubik_Call(VL_ReplaceEntry, cellHandle->vos, 0, volid,
238 voltype, &oentry, releasetype);
244 } while (tst == RXGEN_OPCODE);
252 int VLDB_ListAttributes(
253 afs_cell_handle_p cellHandle,
254 VldbListByAttributes *attrp,
256 nbulkentries *blkentriesp,
259 bulkentries arrayEntries;
261 afs_status_t tst = 0;
265 if (cellHandle->vos_new) {
266 tst = ubik_Call(VL_ListAttributesN, cellHandle->vos, 0, attrp,
267 entriesp, blkentriesp);
269 if (tst == RXGEN_OPCODE) {
270 cellHandle->vos_new = 0;
276 memset((void *) &arrayEntries, 0, sizeof(arrayEntries));
277 tst = ubik_Call(VL_ListAttributes, cellHandle->vos, 0, attrp,
278 entriesp, arrayEntries);
280 blkentriesp->nbulkentries_val = (nvldbentry *) malloc(*entriesp * sizeof(*blkentriesp));
281 if (blkentriesp->nbulkentries_val != NULL) {
282 for(i=0;i< *entriesp;i++) {
283 OldVLDB_to_NewVLDB((struct vldbentry *) &arrayEntries.bulkentries_val[i], (struct nvldbentry *) &blkentriesp->nbulkentries_val[i], &tst);
288 if (arrayEntries.bulkentries_val) {
289 free(arrayEntries.bulkentries_val);
295 } while (tst == RXGEN_OPCODE);
303 int VLDB_ListAttributesN2(
304 afs_cell_handle_p cellHandle,
305 VldbListByAttributes *attrp,
308 afs_int32 *nentriesp,
309 nbulkentries *blkentriesp,
310 afs_int32 *nextindexp,
314 afs_status_t tst = 0;
316 tst = ubik_Call(VL_ListAttributesN2, cellHandle->vos, 0,
317 attrp, (name ? name : ""), thisindex,
318 nentriesp, blkentriesp, nextindexp);
329 int VLDB_IsSameAddrs(
330 afs_cell_handle_p cellHandle,
337 afs_status_t tst = 0;
339 ListAddrByAttributes attrs;
349 if (serv1 == serv2) {
352 goto fail_VLDB_IsSameAddrs;
355 bzero(&attrs, sizeof(attrs));
356 attrs.Mask = VLADDR_IPADDR;
357 attrs.ipaddr = serv1;
358 bzero(&addrs, sizeof(addrs));
359 bzero(&uuid, sizeof(uuid));
360 tst = ubik_Call(VL_GetAddrsU, cellHandle->vos, 0, &attrs, &uuid,
361 &unique, &nentries, &addrs);
364 goto fail_VLDB_IsSameAddrs;
367 addrp = addrs.bulkaddrs_val;
368 for (i = 0; i < nentries; i++, addrp++) {
369 if (serv2 == *addrp) {
376 fail_VLDB_IsSameAddrs:
385 * GetVolumeInfo - retrieve information about a particular volume.
389 * IN cellHandle - a handle that corresponds to the cell where the volume
392 * IN volid - the volume to be retrieved.
394 * OUT rentry - the vldb entry of the volume.
396 * OUT server - the address of the server where the volume resides in
399 * OUT partition - the volume to be retrieved.
401 * OUT voltype - the type of volume retrieved.
405 * No locks are obtained or released by this function
409 * Returns != 0 upon successful completion.
413 afs_cell_handle_p cellHandle,
415 struct nvldbentry *rentry,
417 afs_int32 *partition,
425 if (!VLDB_GetEntryByID(cellHandle, volid, -1, rentry, &tst)) {
427 goto fail_GetVolumeInfo;
430 if(volid == rentry->volumeId[ROVOL]){
432 for (i = 0; i < rentry->nServers; i++) {
433 if ( (index == -1) && (rentry->serverFlags[i] & ITSROVOL) &&
434 !(rentry->serverFlags[i] & RO_DONTUSE) )
439 goto fail_GetVolumeInfo;
441 *server = rentry->serverNumber[index];
442 *partition = rentry->serverPartition[index];
444 goto fail_GetVolumeInfo;
447 if ((index = Lp_GetRwIndex(cellHandle, rentry, &tst))<0) {
448 goto fail_GetVolumeInfo;
450 if(volid == rentry->volumeId[RWVOL]){
452 *server = rentry->serverNumber[index];
453 *partition = rentry->serverPartition[index];
454 } else if(volid == rentry->volumeId[BACKVOL]){
456 *server = rentry->serverNumber[index];
457 *partition = rentry->serverPartition[index];
470 * ValidateVolumeName - validate a potential volume name
474 * IN volumeName - the volume name to be validated.
478 * No locks are obtained or released by this function
482 * Returns != 0 upon successful completion.
485 int ValidateVolumeName(
486 const char *volumeName,
490 afs_status_t tst = 0;
493 if ((volumeName == NULL) || (*volumeName == 0)) {
494 tst = ADMVOSVOLUMENAMENULL;
495 goto fail_ValidateVolumeName;
498 if (!ISNAMEVALID(volumeName)) {
499 tst = ADMVOSVOLUMENAMETOOLONG;
500 goto fail_ValidateVolumeName;
503 len = strlen(volumeName);
505 if (((len > 8) && (!strcmp(&volumeName[len - 9], ".readonly"))) ||
506 ((len > 6) && (!strcmp(&volumeName[len - 7], ".backup")))) {
507 tst = ADMVOSVOLUMENAMEINVALID;
508 goto fail_ValidateVolumeName;
513 fail_ValidateVolumeName:
522 /*extract the name of volume <name> without readonly or backup suffixes
523 * and return the result as <rname>.
533 total = strlen(sname);
534 if((total > 9) && (!strcmp(&sname[total - 9],".readonly"))) {
535 /*discard the last 8 chars */
536 sname[total - 9] = '\0';
540 else if((total > 7) && (!strcmp(&sname[total - 7 ],".backup"))) {
541 /*discard last 6 chars */
542 sname[total - 7] = '\0';
547 strncpy(rname,name,VOLSER_OLDMAXVOLNAME);
555 * AddressMatch - determines if an IP address matches a pattern
559 * IN addrTest - the IP address to test, in either byte-order
560 * IN addrPattern - the IP address pattern, in the same byte-order
564 * No locks are obtained or released by this function
568 * Returns != 0 if the address matches the pattern specified
569 * (where 255 in any byte in the pattern indicates a wildcard).
579 /* Test the high byte */
580 bTest = addrTest >> 24;
581 bPattern = addrPattern >> 24;
582 if ((bTest != bPattern) && (bPattern != 255)) {
586 /* Test the next-highest byte */
587 bTest = (addrTest >> 16) & 255;
588 bPattern = (addrPattern >> 16) & 255;
589 if ((bTest != bPattern) && (bPattern != 255)) {
593 /* Test the next-to-lowest byte */
594 bTest = (addrTest >> 8) & 255;
595 bPattern = (addrPattern >> 8) & 255;
596 if ((bTest != bPattern) && (bPattern != 255)) {
600 /* Test the low byte */
601 bTest = addrTest & 255;
602 bPattern = addrPattern & 255;
603 if ((bTest != bPattern) && (bPattern != 255)) {
612 * RemoveBadAddresses - (optionally) removes addresses that are better ignored
616 * IN OUT totalp - the number of addresses in the addrsp structure
617 * IN OUT addrsp - a bulk array of addresses
621 * No locks are obtained or released by this function
625 * Returns != 0 upon successful completion.
628 static pthread_once_t badaddr_init_once = PTHREAD_ONCE_INIT;
629 static int addr_to_skip;
631 static void badaddr_once (void)
636 #define cszREG_IGNORE_KEY "Software\\TransarcCorporation\\AFS Control Center"
637 #define cszREG_IGNORE_VALUE "IgnoreBadAddrs"
640 * In order for this routine to do anything, it must first validate
641 * that the user of this machine wants this filtering to take place.
642 * There is an undocumented registry value which signifies that it's
643 * okay to filter bogus IP addresses--and, moreover, indicates
644 * the range of values which may be ignored. Check that value.
648 addr_to_skip = 0; /* don't ignore any addrs unless we find otherwise */
649 if (RegOpenKey (HKEY_LOCAL_MACHINE, cszREG_IGNORE_KEY, &hk) == 0) {
650 DWORD dwType = REG_DWORD;
651 DWORD dwSize = sizeof(addr_to_skip);
652 RegQueryValueEx (hk, cszREG_IGNORE_VALUE, 0,
653 &dwType, (PBYTE)&addr_to_skip, &dwSize);
660 * We only support this functionality (so far) on NT; on other
661 * platforms, we'll never ignore IP addresses. If the feature
662 * is needed in the future, here's the place to add it.
666 addr_to_skip = 0; /* don't skip any addresses */
672 int RemoveBadAddresses(
676 pthread_once (&badaddr_init_once, badaddr_once);
679 * If we've been requested to skip anything, addr_to_skip will be
680 * non-zero. It's actually an IP address of the form:
682 * A "255" means any value is acceptable, and any other value means
683 * the to-be-skipped address must match that value.
686 if (addr_to_skip && addrsp && addrsp->bulkaddrs_val) {
689 for ( ; iiRead < addrsp->bulkaddrs_len; ++iiRead) {
692 * Check this IP address to see if it should be skipped.
695 if (!AddressMatch(addrsp->bulkaddrs_val[iiRead],addr_to_skip)) {
698 * The address is okay; make sure it stays in the list.
701 if (iiWrite != iiRead) {
702 addrsp->bulkaddrs_val[iiWrite] =
703 addrsp->bulkaddrs_val[iiRead];
709 *totalp = (afs_int32)iiWrite;
710 addrsp->bulkaddrs_len = iiWrite;