2 * Copyright (C) 1998 Transarc Corporation. All rights reserved.
9 #include <afs/afs_AdminErrors.h>
12 * Functions that aren't prototyped, but that we use
15 extern int VL_CreateEntryN(), VL_CreateEntry(), VL_GetEntryByIDN(), VL_GetEntryByID(), VL_GetEntryByNameN(), VL_GetEntryByNameO(), VL_ReplaceEntryN(), VL_ReplaceEntry(), VL_ListAttributesN(), VL_ListAttributes(), VL_GetAddrsU();
18 * VLDB entry conversion routines.
19 * convert from one type of VLDB record to another. There are only
20 * two types "old" and "new".
23 static int OldVLDB_to_NewVLDB(
24 struct vldbentry *source,
25 struct nvldbentry *dest,
32 bzero(dest, sizeof(struct nvldbentry));
33 strncpy(dest->name, source->name, sizeof(dest->name));
34 for (i = 0; i < source->nServers; i++) {
35 dest->serverNumber[i] = source->serverNumber[i];
36 dest->serverPartition[i] = source->serverPartition[i];
37 dest->serverFlags[i] = source->serverFlags[i];
39 dest->nServers = source->nServers;
40 for (i = 0; i < MAXTYPES; i++)
41 dest->volumeId[i] = source->volumeId[i];
42 dest->cloneId = source->cloneId;
43 dest->flags = source->flags;
54 * We can fail to store the new to old VLDB record if there are more
55 * servers in the cell than the old format can handle. If we fail,
59 static int NewVLDB_to_OldVLDB(
60 struct nvldbentry *source,
61 struct vldbentry *dest,
68 bzero(dest, sizeof(struct vldbentry));
69 strncpy(dest->name, source->name, sizeof(dest->name));
70 if (source->nServers <= OMAXNSERVERS) {
71 for (i = 0; i < source->nServers; i++) {
72 dest->serverNumber[i] = source->serverNumber[i];
73 dest->serverPartition[i] = source->serverPartition[i];
74 dest->serverFlags[i] = source->serverFlags[i];
77 for (i = 0; i < MAXTYPES; i++)
78 dest->volumeId[i] = source->volumeId[i];
79 dest->cloneId = source->cloneId;
80 dest->flags = source->flags;
93 afs_cell_handle_p cellHandle,
94 struct nvldbentry *entryp,
97 struct vldbentry oentry;
102 if (cellHandle->vos_new) {
103 tst = ubik_Call(VL_CreateEntryN, cellHandle->vos, 0, entryp);
105 if (tst == RXGEN_OPCODE) {
106 cellHandle->vos_new = 0;
112 if (NewVLDB_to_OldVLDB(entryp, &oentry, &tst)) {
113 tst = ubik_Call(VL_CreateEntry, cellHandle->vos, 0, &oentry);
119 } while (tst == RXGEN_OPCODE);
127 int VLDB_GetEntryByID(
128 afs_cell_handle_p cellHandle,
131 struct nvldbentry *entryp,
134 struct vldbentry oentry;
135 afs_status_t tst = 0;
139 if (cellHandle->vos_new) {
140 tst = ubik_Call(VL_GetEntryByIDN, cellHandle->vos, 0, volid,
143 if (tst == RXGEN_OPCODE) {
144 cellHandle->vos_new = 0;
150 tst = ubik_Call(VL_GetEntryByID, cellHandle->vos, 0, volid,
153 rc = OldVLDB_to_NewVLDB(&oentry, entryp, &tst);
157 } while (tst == RXGEN_OPCODE);
165 int VLDB_GetEntryByName(
166 afs_cell_handle_p cellHandle,
168 struct nvldbentry *entryp,
171 struct vldbentry oentry;
172 afs_status_t tst = 0;
176 if (cellHandle->vos_new) {
177 tst = ubik_Call(VL_GetEntryByNameN, cellHandle->vos, 0, namep,
180 if (tst == RXGEN_OPCODE) {
181 cellHandle->vos_new = 0;
187 tst = ubik_Call(VL_GetEntryByNameO, cellHandle->vos, 0, namep,
190 rc = OldVLDB_to_NewVLDB(&oentry, entryp, &tst);
194 } while (tst == RXGEN_OPCODE);
202 int VLDB_ReplaceEntry(
203 afs_cell_handle_p cellHandle,
206 struct nvldbentry *entryp,
207 afs_int32 releasetype,
210 struct vldbentry oentry;
211 afs_status_t tst = 0;
215 if (cellHandle->vos_new) {
216 tst = ubik_Call(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)) {
227 tst = ubik_Call(VL_ReplaceEntry, cellHandle->vos, 0, volid,
228 voltype, &oentry, releasetype);
234 } while (tst == RXGEN_OPCODE);
242 int VLDB_ListAttributes(
243 afs_cell_handle_p cellHandle,
244 VldbListByAttributes *attrp,
246 nbulkentries *blkentriesp,
249 bulkentries arrayEntries;
251 afs_status_t tst = 0;
255 if (cellHandle->vos_new) {
256 tst = ubik_Call(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));
267 tst = ubik_Call(VL_ListAttributes, cellHandle->vos, 0, attrp,
268 entriesp, arrayEntries);
270 blkentriesp->nbulkentries_val = (nvldbentry *) malloc(*entriesp * sizeof(*blkentriesp));
271 if (blkentriesp->nbulkentries_val != NULL) {
272 for(i=0;i< *entriesp;i++) {
273 OldVLDB_to_NewVLDB((struct vldbentry *) &arrayEntries.bulkentries_val[i], (struct nvldbentry *) &blkentriesp->nbulkentries_val[i], &tst);
278 if (arrayEntries.bulkentries_val) {
279 free(arrayEntries.bulkentries_val);
285 } while (tst == RXGEN_OPCODE);
293 int VLDB_ListAttributesN2(
294 afs_cell_handle_p cellHandle,
295 VldbListByAttributes *attrp,
298 afs_int32 *nentriesp,
299 nbulkentries *blkentriesp,
300 afs_int32 *nextindexp,
304 afs_status_t tst = 0;
306 tst = ubik_Call(VL_ListAttributesN2, cellHandle->vos, 0,
307 attrp, (name ? name : ""), thisindex,
308 nentriesp, blkentriesp, nextindexp);
319 int VLDB_IsSameAddrs(
320 afs_cell_handle_p cellHandle,
327 afs_status_t tst = 0;
329 ListAddrByAttributes attrs;
339 if (serv1 == serv2) {
342 goto fail_VLDB_IsSameAddrs;
345 bzero(&attrs, sizeof(attrs));
346 attrs.Mask = VLADDR_IPADDR;
347 attrs.ipaddr = serv1;
348 bzero(&addrs, sizeof(addrs));
349 bzero(&uuid, sizeof(uuid));
350 tst = ubik_Call(VL_GetAddrsU, cellHandle->vos, 0, &attrs, &uuid,
351 &unique, &nentries, &addrs);
354 goto fail_VLDB_IsSameAddrs;
357 addrp = addrs.bulkaddrs_val;
358 for (i = 0; i < nentries; i++, addrp++) {
359 if (serv2 == *addrp) {
366 fail_VLDB_IsSameAddrs:
375 * GetVolumeInfo - retrieve information about a particular volume.
379 * IN cellHandle - a handle that corresponds to the cell where the volume
382 * IN volid - the volume to be retrieved.
384 * OUT rentry - the vldb entry of the volume.
386 * OUT server - the address of the server where the volume resides in
389 * OUT partition - the volume to be retrieved.
391 * OUT voltype - the type of volume retrieved.
395 * No locks are obtained or released by this function
399 * Returns != 0 upon successful completion.
403 afs_cell_handle_p cellHandle,
405 struct nvldbentry *rentry,
407 afs_int32 *partition,
415 if (!VLDB_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.
475 int ValidateVolumeName(
476 const char *volumeName,
480 afs_status_t tst = 0;
483 if ((volumeName == NULL) || (*volumeName == 0)) {
484 tst = ADMVOSVOLUMENAMENULL;
485 goto fail_ValidateVolumeName;
488 if (!ISNAMEVALID(volumeName)) {
489 tst = ADMVOSVOLUMENAMETOOLONG;
490 goto fail_ValidateVolumeName;
493 len = strlen(volumeName);
495 if (((len > 8) && (!strcmp(&volumeName[len - 9], ".readonly"))) ||
496 ((len > 6) && (!strcmp(&volumeName[len - 7], ".backup")))) {
497 tst = ADMVOSVOLUMENAMEINVALID;
498 goto fail_ValidateVolumeName;
503 fail_ValidateVolumeName:
512 /*extract the name of volume <name> without readonly or backup suffixes
513 * and return the result as <rname>.
523 total = strlen(sname);
524 if((total > 9) && (!strcmp(&sname[total - 9],".readonly"))) {
525 /*discard the last 8 chars */
526 sname[total - 9] = '\0';
530 else if((total > 7) && (!strcmp(&sname[total - 7 ],".backup"))) {
531 /*discard last 6 chars */
532 sname[total - 7] = '\0';
537 strncpy(rname,name,VOLSER_OLDMAXVOLNAME);
545 * AddressMatch - determines if an IP address matches a pattern
549 * IN addrTest - the IP address to test, in either byte-order
550 * IN addrPattern - the IP address pattern, in the same byte-order
554 * No locks are obtained or released by this function
558 * Returns != 0 if the address matches the pattern specified
559 * (where 255 in any byte in the pattern indicates a wildcard).
569 /* Test the high byte */
570 bTest = addrTest >> 24;
571 bPattern = addrPattern >> 24;
572 if ((bTest != bPattern) && (bPattern != 255)) {
576 /* Test the next-highest byte */
577 bTest = (addrTest >> 16) & 255;
578 bPattern = (addrPattern >> 16) & 255;
579 if ((bTest != bPattern) && (bPattern != 255)) {
583 /* Test the next-to-lowest byte */
584 bTest = (addrTest >> 8) & 255;
585 bPattern = (addrPattern >> 8) & 255;
586 if ((bTest != bPattern) && (bPattern != 255)) {
590 /* Test the low byte */
591 bTest = addrTest & 255;
592 bPattern = addrPattern & 255;
593 if ((bTest != bPattern) && (bPattern != 255)) {
602 * RemoveBadAddresses - (optionally) removes addresses that are better ignored
606 * IN OUT totalp - the number of addresses in the addrsp structure
607 * IN OUT addrsp - a bulk array of addresses
611 * No locks are obtained or released by this function
615 * Returns != 0 upon successful completion.
618 static pthread_once_t badaddr_init_once = PTHREAD_ONCE_INIT;
619 static int addr_to_skip;
621 static void badaddr_once (void)
626 #define cszREG_IGNORE_KEY "Software\\TransarcCorporation\\AFS Control Center"
627 #define cszREG_IGNORE_VALUE "IgnoreBadAddrs"
630 * In order for this routine to do anything, it must first validate
631 * that the user of this machine wants this filtering to take place.
632 * There is an undocumented registry value which signifies that it's
633 * okay to filter bogus IP addresses--and, moreover, indicates
634 * the range of values which may be ignored. Check that value.
638 addr_to_skip = 0; /* don't ignore any addrs unless we find otherwise */
639 if (RegOpenKey (HKEY_LOCAL_MACHINE, cszREG_IGNORE_KEY, &hk) == 0) {
640 DWORD dwType = REG_DWORD;
641 DWORD dwSize = sizeof(addr_to_skip);
642 RegQueryValueEx (hk, cszREG_IGNORE_VALUE, 0,
643 &dwType, (PBYTE)&addr_to_skip, &dwSize);
650 * We only support this functionality (so far) on NT; on other
651 * platforms, we'll never ignore IP addresses. If the feature
652 * is needed in the future, here's the place to add it.
656 addr_to_skip = 0; /* don't skip any addresses */
662 int RemoveBadAddresses(
666 pthread_once (&badaddr_init_once, badaddr_once);
669 * If we've been requested to skip anything, addr_to_skip will be
670 * non-zero. It's actually an IP address of the form:
672 * A "255" means any value is acceptable, and any other value means
673 * the to-be-skipped address must match that value.
676 if (addr_to_skip && addrsp && addrsp->bulkaddrs_val) {
679 for ( ; iiRead < addrsp->bulkaddrs_len; ++iiRead) {
682 * Check this IP address to see if it should be skipped.
685 if (!AddressMatch(addrsp->bulkaddrs_val[iiRead],addr_to_skip)) {
688 * The address is okay; make sure it stays in the list.
691 if (iiWrite != iiRead) {
692 addrsp->bulkaddrs_val[iiWrite] =
693 addrsp->bulkaddrs_val[iiRead];
699 *totalp = (afs_int32)iiWrite;
700 addrsp->bulkaddrs_len = iiWrite;