Update NEWS for 1.6.22
[pkg-k5-afs_openafs.git] / src / volser / vsutils.c
blob711673f63311752ec3902dce44a1414c62587da2
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
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
8 */
10 #include <afsconfig.h>
11 #include <afs/param.h>
14 #include <afs/stds.h>
15 #include <string.h>
16 #include <ctype.h>
17 #ifdef AFS_NT40_ENV
18 #include <fcntl.h>
19 #include <winsock2.h>
20 #else
21 #include <sys/types.h>
22 #include <sys/file.h>
23 #include <netdb.h>
24 #include <netinet/in.h>
25 #endif /* AFS_NT40_ENV */
26 #include <sys/stat.h>
27 #ifdef AFS_AIX_ENV
28 #include <sys/statfs.h>
29 #endif
31 #include <errno.h>
32 #include <lock.h>
33 #include <rx/xdr.h>
34 #include <rx/rx.h>
35 #include <rx/rx_globals.h>
36 #include <afs/nfs.h>
37 #include <afs/vlserver.h>
38 #include <afs/cellconfig.h>
39 #include <afs/keys.h>
40 #include <ubik.h>
41 #include <afs/afsint.h>
42 #include <afs/cmd.h>
43 #include <rx/rxkad.h>
44 #include "volser.h"
45 #include "volint.h"
46 #include "lockdata.h"
48 #include "vsutils_prototypes.h"
50 struct ubik_client *cstruct;
51 static rxkad_level vsu_rxkad_level = rxkad_clear;
53 static void
54 ovlentry_to_nvlentry(struct vldbentry *oentryp,
55 struct nvldbentry *nentryp)
57 int i;
59 memset(nentryp, 0, sizeof(struct nvldbentry));
60 strncpy(nentryp->name, oentryp->name, sizeof(nentryp->name));
61 for (i = 0; i < oentryp->nServers; i++) {
62 nentryp->serverNumber[i] = oentryp->serverNumber[i];
63 nentryp->serverPartition[i] = oentryp->serverPartition[i];
64 nentryp->serverFlags[i] = oentryp->serverFlags[i];
66 nentryp->nServers = oentryp->nServers;
67 for (i = 0; i < MAXTYPES; i++)
68 nentryp->volumeId[i] = oentryp->volumeId[i];
69 nentryp->cloneId = oentryp->cloneId;
70 nentryp->flags = oentryp->flags;
73 static int
74 nvlentry_to_ovlentry(struct nvldbentry *nentryp,
75 struct vldbentry *oentryp)
77 int i;
79 memset(oentryp, 0, sizeof(struct vldbentry));
80 strncpy(oentryp->name, nentryp->name, sizeof(oentryp->name));
81 if (nentryp->nServers > OMAXNSERVERS) {
83 * The alternative is to store OMAXSERVERS but it's always better
84 * to know what's going on...
86 return VL_BADSERVER;
88 for (i = 0; i < nentryp->nServers; i++) {
89 oentryp->serverNumber[i] = nentryp->serverNumber[i];
90 oentryp->serverPartition[i] = nentryp->serverPartition[i];
91 oentryp->serverFlags[i] = nentryp->serverFlags[i];
93 oentryp->nServers = i;
94 for (i = 0; i < MAXTYPES; i++)
95 oentryp->volumeId[i] = nentryp->volumeId[i];
96 oentryp->cloneId = nentryp->cloneId;
97 oentryp->flags = nentryp->flags;
98 return 0;
101 enum _vlserver_type {
102 vltype_unknown = 0,
103 vltype_old = 1,
104 vltype_new = 2,
105 vltype_uuid = 3
108 static enum _vlserver_type newvlserver = vltype_unknown;
111 VLDB_CreateEntry(struct nvldbentry *entryp)
113 struct vldbentry oentry;
114 int code;
116 if (newvlserver == vltype_old) {
117 tryold:
118 code = nvlentry_to_ovlentry(entryp, &oentry);
119 if (code)
120 return code;
121 code = ubik_VL_CreateEntry(cstruct, 0, &oentry);
122 return code;
124 code = ubik_VL_CreateEntryN(cstruct, 0, entryp);
125 if (newvlserver == vltype_unknown) {
126 if (code == RXGEN_OPCODE) {
127 newvlserver = vltype_old; /* Doesn't support new interface */
128 goto tryold;
129 } else if (!code) {
130 newvlserver = vltype_new;
133 return code;
137 VLDB_GetEntryByID(afs_uint32 volid, afs_int32 voltype, struct nvldbentry *entryp)
139 struct vldbentry oentry;
140 int code;
142 if (newvlserver == vltype_old) {
143 tryold:
144 code =
145 ubik_VL_GetEntryByID(cstruct, 0, volid, voltype, &oentry);
146 if (!code)
147 ovlentry_to_nvlentry(&oentry, entryp);
148 return code;
150 code = ubik_VL_GetEntryByIDN(cstruct, 0, volid, voltype, entryp);
151 if (newvlserver == vltype_unknown) {
152 if (code == RXGEN_OPCODE) {
153 newvlserver = vltype_old; /* Doesn't support new interface */
154 goto tryold;
155 } else if (!code) {
156 newvlserver = vltype_new;
159 return code;
163 VLDB_GetEntryByName(char *namep, struct nvldbentry *entryp)
165 struct vldbentry oentry;
166 int code;
168 if (newvlserver == vltype_old) {
169 tryold:
170 code = ubik_VL_GetEntryByNameO(cstruct, 0, namep, &oentry);
171 if (!code)
172 ovlentry_to_nvlentry(&oentry, entryp);
173 return code;
175 code = ubik_VL_GetEntryByNameN(cstruct, 0, namep, entryp);
176 if (newvlserver == vltype_unknown) {
177 if (code == RXGEN_OPCODE) {
178 newvlserver = vltype_old; /* Doesn't support new interface */
179 goto tryold;
180 } else if (!code) {
181 newvlserver = vltype_new;
184 return code;
188 VLDB_ReplaceEntry(afs_uint32 volid, afs_int32 voltype, struct nvldbentry *entryp, afs_int32 releasetype)
190 struct vldbentry oentry;
191 int code;
193 if (newvlserver == vltype_old) {
194 tryold:
195 code = nvlentry_to_ovlentry(entryp, &oentry);
196 if (code)
197 return code;
198 code =
199 ubik_VL_ReplaceEntry(cstruct, 0, volid, voltype, &oentry,
200 releasetype);
201 return code;
203 code =
204 ubik_VL_ReplaceEntryN(cstruct, 0, volid, voltype, entryp,
205 releasetype);
206 if (newvlserver == vltype_unknown) {
207 if (code == RXGEN_OPCODE) {
208 newvlserver = vltype_old; /* Doesn't support new interface */
209 goto tryold;
210 } else if (!code) {
211 newvlserver = vltype_new;
214 return code;
217 static void
218 convertBulkToNBulk(bulkentries *bulk, nbulkentries *nbulk) {
219 int i;
221 if (bulk->bulkentries_len == 0)
222 return;
224 nbulk->nbulkentries_len = bulk->bulkentries_len;
225 nbulk->nbulkentries_val =
226 xdr_alloc(bulk->bulkentries_len * sizeof(struct nvldbentry));
228 for (i = 0; i < bulk->bulkentries_len; i++) {
229 ovlentry_to_nvlentry(&bulk->bulkentries_val[i],
230 &nbulk->nbulkentries_val[i]);
235 VLDB_ListAttributes(VldbListByAttributes *attrp,
236 afs_int32 *entriesp,
237 nbulkentries *blkentriesp)
239 bulkentries arrayEntries;
240 int code;
242 if (newvlserver == vltype_old) {
243 tryold:
244 memset(&arrayEntries, 0, sizeof(arrayEntries));
245 code =
246 ubik_VL_ListAttributes(cstruct, 0, attrp, entriesp,
247 &arrayEntries);
249 if (code)
250 return code;
252 /* Ensure the number of entries claimed matches the no. returned */
253 if (*entriesp < 0)
254 *entriesp = 0;
255 if (*entriesp > arrayEntries.bulkentries_len)
256 *entriesp = arrayEntries.bulkentries_len;
258 convertBulkToNBulk(&arrayEntries, blkentriesp);
260 xdr_free((xdrproc_t) xdr_bulkentries, &arrayEntries);
261 return code;
263 code =
264 ubik_VL_ListAttributesN(cstruct, 0, attrp, entriesp, blkentriesp);
265 if (newvlserver == vltype_unknown) {
266 if (code == RXGEN_OPCODE) {
267 newvlserver = vltype_old; /* Doesn't support new interface */
268 goto tryold;
269 } else if (!code) {
270 newvlserver = vltype_new;
274 if (code)
275 return code;
277 /* Ensure the number of entries claimed matches the no. returned */
278 if (*entriesp < 0)
279 *entriesp = 0;
280 if (*entriesp > blkentriesp->nbulkentries_len)
281 *entriesp = blkentriesp->nbulkentries_len;
283 return code;
287 VLDB_ListAttributesN2(VldbListByAttributes *attrp,
288 char *name,
289 afs_int32 thisindex,
290 afs_int32 *nentriesp,
291 nbulkentries *blkentriesp,
292 afs_int32 *nextindexp)
294 afs_int32 code = RXGEN_OPCODE;
296 if (newvlserver != vltype_old) {
297 code =
298 ubik_VL_ListAttributesN2(cstruct, 0, attrp, (name ? name : ""),
299 thisindex, nentriesp, blkentriesp, nextindexp);
300 if (code)
301 return code;
303 /* Ensure the number of entries claimed matches the no. returned */
304 if (*nentriesp < 0)
305 *nentriesp = 0;
306 if (*nentriesp > blkentriesp->nbulkentries_len)
307 *nentriesp = blkentriesp->nbulkentries_len;
309 return code;
312 struct cacheips {
313 afs_uint32 server;
314 afs_int32 count;
315 afs_uint32 addrs[16];
318 * Increase cache size. This avoids high CPU usage by the vlserver
319 * in environments where there are more than 16 fileservers in the
320 * cell.
322 #define GETADDRUCACHESIZE 64
323 struct cacheips cacheips[GETADDRUCACHESIZE];
324 int cacheip_index = 0;
327 VLDB_IsSameAddrs(afs_uint32 serv1, afs_uint32 serv2, afs_int32 *errorp)
329 int code;
330 ListAddrByAttributes attrs;
331 bulkaddrs addrs;
332 afs_uint32 *addrp, i, j, f1, f2;
333 afs_int32 unique, nentries;
334 afsUUID uuid;
335 static int initcache = 0;
337 *errorp = 0;
339 if (serv1 == serv2)
340 return 1;
341 if (newvlserver == vltype_old || newvlserver == vltype_new) {
342 return 0;
344 if (!initcache) {
345 for (i = 0; i < GETADDRUCACHESIZE; i++) {
346 cacheips[i].server = cacheips[i].count = 0;
348 initcache = 1;
351 /* See if it's cached */
352 for (i = 0; i < GETADDRUCACHESIZE; i++) {
353 f1 = f2 = 0;
354 for (j = 0; j < cacheips[i].count; j++) {
355 if (serv1 == cacheips[i].addrs[j])
356 f1 = 1;
357 else if (serv2 == cacheips[i].addrs[j])
358 f2 = 1;
360 if (f1 && f2)
361 return 1;
363 if (f1 || f2)
364 return 0;
365 if (cacheips[i].server == serv1)
366 return 0;
369 memset(&attrs, 0, sizeof(attrs));
370 attrs.Mask = VLADDR_IPADDR;
371 attrs.ipaddr = serv1;
372 memset(&addrs, 0, sizeof(addrs));
373 memset(&uuid, 0, sizeof(uuid));
374 code =
375 ubik_VL_GetAddrsU(cstruct, 0, &attrs, &uuid, &unique, &nentries,
376 &addrs);
377 if (newvlserver == vltype_unknown) {
378 if (code == RXGEN_OPCODE) {
379 return 0;
380 } else if (!code) {
381 newvlserver = vltype_uuid;
384 if (code == VL_NOENT)
385 return 0;
386 if (code) {
387 *errorp = code;
388 return 0;
391 code = 0;
392 if (nentries > GETADDRUCACHESIZE)
393 nentries = GETADDRUCACHESIZE; /* safety check; should not happen */
394 if (++cacheip_index >= GETADDRUCACHESIZE)
395 cacheip_index = 0;
396 cacheips[cacheip_index].server = serv1;
397 cacheips[cacheip_index].count = nentries;
398 addrp = addrs.bulkaddrs_val;
399 for (i = 0; i < nentries; i++, addrp++) {
400 cacheips[cacheip_index].addrs[i] = *addrp;
401 if (serv2 == *addrp) {
402 code = 1;
405 return code;
410 Set encryption. If 'cryptflag' is nonzero, encrpytion is turned on
411 for authenticated connections; if zero, encryption is turned off.
412 Calling this function always results in a level of at least rxkad_auth;
413 to get a rxkad_clear connection, simply don't call this.
415 void
416 vsu_SetCrypt(int cryptflag)
418 if (cryptflag) {
419 vsu_rxkad_level = rxkad_crypt;
420 } else {
421 vsu_rxkad_level = rxkad_auth;
427 Get the appropriate type of ubik client structure out from the system.
429 afs_int32
430 vsu_ClientInit(int noAuthFlag, const char *confDir, char *cellName, afs_int32 sauth,
431 struct ubik_client **uclientp,
432 int (*secproc)(struct rx_securityClass *, afs_int32))
434 return ugen_ClientInit(noAuthFlag, confDir, cellName, sauth, uclientp,
435 secproc, "vsu_ClientInit", vsu_rxkad_level,
436 VLDB_MAXSERVERS, AFSCONF_VLDBSERVICE, 90,
437 0, 0, USER_SERVICE_ID);
441 /*extract the name of volume <name> without readonly or backup suffixes
442 * and return the result as <rname>.
445 vsu_ExtractName(char rname[], char name[])
447 char sname[VOLSER_OLDMAXVOLNAME + 1];
448 int total;
450 strncpy(sname, name, sizeof(sname));
451 sname[sizeof(sname) - 1] = '\0';
452 total = strlen(sname);
453 if (!strcmp(&sname[total - 9], ".readonly")) {
454 /*discard the last 8 chars */
455 sname[total - 9] = '\0';
456 strcpy(rname, sname);
457 return 0;
458 } else if (!strcmp(&sname[total - 7], ".backup")) {
459 /*discard last 6 chars */
460 sname[total - 7] = '\0';
461 strcpy(rname, sname);
462 return 0;
463 } else {
464 strncpy(rname, name, VOLSER_OLDMAXVOLNAME);
465 rname[VOLSER_OLDMAXVOLNAME] = '\0';
466 return -1;
470 /* returns 0 if failed */
471 afs_uint32
472 vsu_GetVolumeID(char *astring, struct ubik_client *acstruct, afs_int32 *errp)
474 char volname[VOLSER_OLDMAXVOLNAME + 1];
475 struct nvldbentry entry;
476 afs_int32 vcode = 0;
477 int total;
479 *errp = 0;
481 if (isdigit(astring[0])) {
482 char *end;
483 afs_uint32 result;
484 result = strtoul(astring, &end, 10);
485 if (result != UINT_MAX && *end == '\0')
486 return result;
489 /* It was not a volume number but something else */
490 total = strlen(astring);
491 vsu_ExtractName(volname, astring);
492 vcode = VLDB_GetEntryByName(volname, &entry);
493 if (!vcode) {
494 if ((total >= 9) && (!strcmp(&astring[total - 9], ".readonly")))
495 return entry.volumeId[ROVOL];
496 else if ((total >= 7) && (!strcmp(&astring[total - 7], ".backup")))
497 return entry.volumeId[BACKVOL];
498 else
499 return (entry.volumeId[RWVOL]);
501 *errp = vcode;
502 return 0; /* can't find volume */