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
;