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