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