volser: Tidy header includes
[openafs.git] / src / volser / vsutils.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
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  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12 #include <afs/stds.h>
13
14 #include <roken.h>
15
16 #include <ctype.h>
17 #ifdef AFS_AIX_ENV
18 #include <sys/statfs.h>
19 #endif
20
21 #include <lock.h>
22 #include <rx/xdr.h>
23 #include <rx/rx.h>
24 #include <rx/rx_globals.h>
25 #include <afs/nfs.h>
26 #include <afs/vlserver.h>
27 #include <afs/cellconfig.h>
28 #include <afs/keys.h>
29 #include <ubik.h>
30 #include <afs/afsint.h>
31 #include <afs/cmd.h>
32 #include <rx/rxkad.h>
33
34 #include "volser.h"
35 #include "volint.h"
36 #include "lockdata.h"
37
38 #include "vsutils_prototypes.h"
39
40 struct ubik_client *cstruct;
41 static rxkad_level vsu_rxkad_level = rxkad_clear;
42
43 static void
44 ovlentry_to_nvlentry(struct vldbentry *oentryp,
45                      struct nvldbentry *nentryp)
46 {
47     int i;
48
49     memset(nentryp, 0, sizeof(struct nvldbentry));
50     strncpy(nentryp->name, oentryp->name, sizeof(nentryp->name));
51     for (i = 0; i < oentryp->nServers; i++) {
52         nentryp->serverNumber[i] = oentryp->serverNumber[i];
53         nentryp->serverPartition[i] = oentryp->serverPartition[i];
54         nentryp->serverFlags[i] = oentryp->serverFlags[i];
55     }
56     nentryp->nServers = oentryp->nServers;
57     for (i = 0; i < MAXTYPES; i++)
58         nentryp->volumeId[i] = oentryp->volumeId[i];
59     nentryp->cloneId = oentryp->cloneId;
60     nentryp->flags = oentryp->flags;
61 }
62
63 static int
64 nvlentry_to_ovlentry(struct nvldbentry *nentryp,
65                      struct vldbentry *oentryp)
66 {
67     int i;
68
69     memset(oentryp, 0, sizeof(struct vldbentry));
70     strncpy(oentryp->name, nentryp->name, sizeof(oentryp->name));
71     if (nentryp->nServers > OMAXNSERVERS) {
72         /*
73          * The alternative is to store OMAXSERVERS but it's always better
74          * to know what's going on...
75          */
76         return VL_BADSERVER;
77     }
78     for (i = 0; i < nentryp->nServers; i++) {
79         oentryp->serverNumber[i] = nentryp->serverNumber[i];
80         oentryp->serverPartition[i] = nentryp->serverPartition[i];
81         oentryp->serverFlags[i] = nentryp->serverFlags[i];
82     }
83     oentryp->nServers = i;
84     for (i = 0; i < MAXTYPES; i++)
85         oentryp->volumeId[i] = nentryp->volumeId[i];
86     oentryp->cloneId = nentryp->cloneId;
87     oentryp->flags = nentryp->flags;
88     return 0;
89 }
90
91 enum _vlserver_type {
92     vltype_unknown = 0,
93     vltype_old = 1,
94     vltype_new = 2,
95     vltype_uuid = 3
96 };
97
98 static enum _vlserver_type newvlserver = vltype_unknown;
99
100 int
101 VLDB_CreateEntry(struct nvldbentry *entryp)
102 {
103     struct vldbentry oentry;
104     int code;
105
106     if (newvlserver == vltype_old) {
107       tryold:
108         code = nvlentry_to_ovlentry(entryp, &oentry);
109         if (code)
110             return code;
111         code = ubik_VL_CreateEntry(cstruct, 0, &oentry);
112         return code;
113     }
114     code = ubik_VL_CreateEntryN(cstruct, 0, entryp);
115     if (newvlserver == vltype_unknown) {
116         if (code == RXGEN_OPCODE) {
117             newvlserver = vltype_old;   /* Doesn't support new interface */
118             goto tryold;
119         } else if (!code) {
120             newvlserver = vltype_new;
121         }
122     }
123     return code;
124 }
125
126 int
127 VLDB_GetEntryByID(afs_uint32 volid, afs_int32 voltype, struct nvldbentry *entryp)
128 {
129     struct vldbentry oentry;
130     int code;
131
132     if (newvlserver == vltype_old) {
133       tryold:
134         code =
135             ubik_VL_GetEntryByID(cstruct, 0, volid, voltype, &oentry);
136         if (!code)
137             ovlentry_to_nvlentry(&oentry, entryp);
138         return code;
139     }
140     code = ubik_VL_GetEntryByIDN(cstruct, 0, volid, voltype, entryp);
141     if (newvlserver == vltype_unknown) {
142         if (code == RXGEN_OPCODE) {
143             newvlserver = vltype_old;   /* Doesn't support new interface */
144             goto tryold;
145         } else if (!code) {
146             newvlserver = vltype_new;
147         }
148     }
149     return code;
150 }
151
152 int
153 VLDB_GetEntryByName(char *namep, struct nvldbentry *entryp)
154 {
155     struct vldbentry oentry;
156     int code;
157
158     if (newvlserver == vltype_old) {
159       tryold:
160         code = ubik_VL_GetEntryByNameO(cstruct, 0, namep, &oentry);
161         if (!code)
162             ovlentry_to_nvlentry(&oentry, entryp);
163         return code;
164     }
165     code = ubik_VL_GetEntryByNameN(cstruct, 0, namep, entryp);
166     if (newvlserver == vltype_unknown) {
167         if (code == RXGEN_OPCODE) {
168             newvlserver = vltype_old;   /* Doesn't support new interface */
169             goto tryold;
170         } else if (!code) {
171             newvlserver = vltype_new;
172         }
173     }
174     return code;
175 }
176
177 int
178 VLDB_ReplaceEntry(afs_uint32 volid, afs_int32 voltype, struct nvldbentry *entryp, afs_int32 releasetype)
179 {
180     struct vldbentry oentry;
181     int code;
182
183     if (newvlserver == vltype_old) {
184       tryold:
185         code = nvlentry_to_ovlentry(entryp, &oentry);
186         if (code)
187             return code;
188         code =
189             ubik_VL_ReplaceEntry(cstruct, 0, volid, voltype, &oentry,
190                       releasetype);
191         return code;
192     }
193     code =
194         ubik_VL_ReplaceEntryN(cstruct, 0, volid, voltype, entryp,
195                   releasetype);
196     if (newvlserver == vltype_unknown) {
197         if (code == RXGEN_OPCODE) {
198             newvlserver = vltype_old;   /* Doesn't support new interface */
199             goto tryold;
200         } else if (!code) {
201             newvlserver = vltype_new;
202         }
203     }
204     return code;
205 }
206
207 static void
208 convertBulkToNBulk(bulkentries *bulk, nbulkentries *nbulk) {
209     unsigned int i;
210
211     if (bulk->bulkentries_len == 0)
212         return;
213
214     nbulk->nbulkentries_len = bulk->bulkentries_len;
215     nbulk->nbulkentries_val =
216         xdr_alloc(bulk->bulkentries_len * sizeof(struct nvldbentry));
217
218     for (i = 0; i < bulk->bulkentries_len; i++) {
219         ovlentry_to_nvlentry(&bulk->bulkentries_val[i],
220                              &nbulk->nbulkentries_val[i]);
221     }
222 }
223
224 int
225 VLDB_ListAttributes(VldbListByAttributes *attrp,
226                     afs_int32 *entriesp,
227                     nbulkentries *blkentriesp)
228 {
229     bulkentries arrayEntries;
230     int code;
231
232     if (newvlserver == vltype_old) {
233       tryold:
234         memset(&arrayEntries, 0, sizeof(arrayEntries));
235         code =
236             ubik_VL_ListAttributes(cstruct, 0, attrp, entriesp,
237                       &arrayEntries);
238
239         if (code)
240             return code;
241
242         /* Ensure the number of entries claimed matches the no. returned */
243         if (*entriesp < 0)
244             *entriesp = 0;
245         if (*entriesp > arrayEntries.bulkentries_len)
246             *entriesp = arrayEntries.bulkentries_len;
247
248         convertBulkToNBulk(&arrayEntries, blkentriesp);
249
250         xdr_free((xdrproc_t) xdr_bulkentries, &arrayEntries);
251         return code;
252     }
253     code =
254         ubik_VL_ListAttributesN(cstruct, 0, attrp, entriesp, blkentriesp);
255     if (newvlserver == vltype_unknown) {
256         if (code == RXGEN_OPCODE) {
257             newvlserver = vltype_old;   /* Doesn't support new interface */
258             goto tryold;
259         } else if (!code) {
260             newvlserver = vltype_new;
261         }
262     }
263
264     /* Ensure the number of entries claimed matches the no. returned */
265     if (*entriesp < 0)
266         *entriesp = 0;
267     if (*entriesp > blkentriesp->nbulkentries_len)
268         *entriesp = blkentriesp->nbulkentries_len;
269
270     return code;
271 }
272
273 int
274 VLDB_ListAttributesN2(VldbListByAttributes *attrp,
275                       char *name,
276                       afs_int32 thisindex,
277                       afs_int32 *nentriesp,
278                       nbulkentries *blkentriesp,
279                       afs_int32 *nextindexp)
280 {
281     afs_int32 code = RXGEN_OPCODE;
282
283     if (newvlserver != vltype_old) {
284         code =
285             ubik_VL_ListAttributesN2(cstruct, 0, attrp, (name ? name : ""),
286                                      thisindex, nentriesp, blkentriesp, nextindexp);
287         if (code)
288             return code;
289
290         /* Ensure the number of entries claimed matches the no. returned */
291         if (*nentriesp < 0)
292             *nentriesp = 0;
293         if (*nentriesp > blkentriesp->nbulkentries_len)
294             *nentriesp = blkentriesp->nbulkentries_len;
295     }
296     return code;
297 }
298
299 struct cacheips {
300     afs_uint32 server;
301     afs_uint32 count;
302     afs_uint32 addrs[16];
303 };
304 /*
305  * Increase cache size.  This avoids high CPU usage by the vlserver
306  * in environments where there are more than 16 fileservers in the
307  * cell.
308  */
309 #define GETADDRUCACHESIZE             64
310 struct cacheips cacheips[GETADDRUCACHESIZE];
311 int cacheip_index = 0;
312
313 int
314 VLDB_IsSameAddrs(afs_uint32 serv1, afs_uint32 serv2, afs_int32 *errorp)
315 {
316     int code;
317     ListAddrByAttributes attrs;
318     bulkaddrs addrs;
319     afs_uint32 *addrp, j, f1, f2;
320     afs_int32 unique, nentries, i;
321     afsUUID uuid;
322     static int initcache = 0;
323
324     *errorp = 0;
325
326     if (serv1 == serv2)
327         return 1;
328     if (newvlserver == vltype_old || newvlserver == vltype_new) {
329         return 0;
330     }
331     if (!initcache) {
332         for (i = 0; i < GETADDRUCACHESIZE; i++) {
333             cacheips[i].server = cacheips[i].count = 0;
334         }
335         initcache = 1;
336     }
337
338     /* See if it's cached */
339     for (i = 0; i < GETADDRUCACHESIZE; i++) {
340         f1 = f2 = 0;
341         for (j = 0; j < cacheips[i].count; j++) {
342             if (serv1 == cacheips[i].addrs[j])
343                 f1 = 1;
344             else if (serv2 == cacheips[i].addrs[j])
345                 f2 = 1;
346
347             if (f1 && f2)
348                 return 1;
349         }
350         if (f1 || f2)
351             return 0;
352         if (cacheips[i].server == serv1)
353             return 0;
354     }
355
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));
361     code =
362         ubik_VL_GetAddrsU(cstruct, 0, &attrs, &uuid, &unique, &nentries,
363                   &addrs);
364     if (newvlserver == vltype_unknown) {
365         if (code == RXGEN_OPCODE) {
366             return 0;
367         } else if (!code) {
368             newvlserver = vltype_uuid;
369         }
370     }
371     if (code == VL_NOENT)
372         return 0;
373     if (code) {
374         *errorp = code;
375         return 0;
376     }
377
378     code = 0;
379     if (nentries > GETADDRUCACHESIZE)
380         nentries = GETADDRUCACHESIZE;   /* safety check; should not happen */
381     if (++cacheip_index >= GETADDRUCACHESIZE)
382         cacheip_index = 0;
383     cacheips[cacheip_index].server = serv1;
384     cacheips[cacheip_index].count = nentries;
385     addrp = addrs.bulkaddrs_val;
386     for (i = 0; i < nentries; i++, addrp++) {
387         cacheips[cacheip_index].addrs[i] = *addrp;
388         if (serv2 == *addrp) {
389             code = 1;
390         }
391     }
392     return code;
393 }
394
395
396 /*
397   Set encryption.  If 'cryptflag' is nonzero, encrpytion is turned on
398   for authenticated connections; if zero, encryption is turned off.
399   Calling this function always results in a level of at least rxkad_auth;
400   to get a rxkad_clear connection, simply don't call this.
401 */
402 void
403 vsu_SetCrypt(int cryptflag)
404 {
405     if (cryptflag) {
406         vsu_rxkad_level = rxkad_crypt;
407     } else {
408         vsu_rxkad_level = rxkad_auth;
409     }
410 }
411
412
413 /*
414   Get the appropriate type of ubik client structure out from the system.
415 */
416 afs_int32
417 vsu_ClientInit(int noAuthFlag, const char *confDir, char *cellName, afs_int32 sauth,
418                struct ubik_client **uclientp,
419                int (*secproc)(struct rx_securityClass *, afs_int32))
420 {
421     return ugen_ClientInit(noAuthFlag, confDir, cellName, sauth, uclientp,
422                            secproc, "vsu_ClientInit", vsu_rxkad_level,
423                            VLDB_MAXSERVERS, AFSCONF_VLDBSERVICE, 90,
424                            0, 0, USER_SERVICE_ID);
425 }
426
427
428 /*extract the name of volume <name> without readonly or backup suffixes
429  * and return the result as <rname>.
430  */
431 int
432 vsu_ExtractName(char rname[], char name[])
433 {
434     char sname[VOLSER_OLDMAXVOLNAME + 1];
435     size_t total;
436
437     strncpy(sname, name, sizeof(sname));
438     sname[sizeof(sname) - 1] = '\0';
439     total = strlen(sname);
440     if (!strcmp(&sname[total - 9], ".readonly")) {
441         /*discard the last 8 chars */
442         sname[total - 9] = '\0';
443         strcpy(rname, sname);
444         return 0;
445     } else if (!strcmp(&sname[total - 7], ".backup")) {
446         /*discard last 6 chars */
447         sname[total - 7] = '\0';
448         strcpy(rname, sname);
449         return 0;
450     } else {
451         strncpy(rname, name, VOLSER_OLDMAXVOLNAME);
452         rname[VOLSER_OLDMAXVOLNAME] = '\0';
453         return -1;
454     }
455 }
456
457 /* returns 0 if failed */
458 afs_uint32
459 vsu_GetVolumeID(char *astring, struct ubik_client *acstruct, afs_int32 *errp)
460 {
461     char volname[VOLSER_OLDMAXVOLNAME + 1];
462     struct nvldbentry entry;
463     afs_int32 vcode = 0;
464     size_t total;
465
466     *errp = 0;
467
468     if (isdigit(astring[0])) {
469         char *end;
470         afs_uint32 result;
471         result = strtoul(astring, &end, 10);
472         if (result != UINT_MAX && *end == '\0')
473             return result;
474     }
475
476     /* It was not a volume number but something else */
477     total = strlen(astring);
478     vsu_ExtractName(volname, astring);
479     vcode = VLDB_GetEntryByName(volname, &entry);
480     if (!vcode) {
481       if ((total >= 9) && (!strcmp(&astring[total - 9], ".readonly")))
482         return entry.volumeId[ROVOL];
483       else if ((total >= 7) && (!strcmp(&astring[total - 7], ".backup")))
484         return entry.volumeId[BACKVOL];
485       else
486         return (entry.volumeId[RWVOL]);
487     }
488     *errp = vcode;
489     return 0;           /* can't find volume */
490 }