generic-client-init-function-20041009
[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/auth.h>
47 #include <afs/cellconfig.h>
48 #include <afs/keys.h>
49 #include <ubik.h>
50 #include <afs/afsint.h>
51 #include <afs/cmd.h>
52 #include <rx/rxkad.h>
53 #include "volser.h"
54 #include "volint.h"
55 #include "lockdata.h"
56
57 struct ubik_client *cstruct;
58 static rxkad_level vsu_rxkad_level = rxkad_clear;
59
60 static void
61 ovlentry_to_nvlentry(oentryp, nentryp)
62      struct vldbentry *oentryp;
63      struct nvldbentry *nentryp;
64 {
65     register int i;
66
67     memset(nentryp, 0, sizeof(struct nvldbentry));
68     strncpy(nentryp->name, oentryp->name, sizeof(nentryp->name));
69     for (i = 0; i < oentryp->nServers; i++) {
70         nentryp->serverNumber[i] = oentryp->serverNumber[i];
71         nentryp->serverPartition[i] = oentryp->serverPartition[i];
72         nentryp->serverFlags[i] = oentryp->serverFlags[i];
73     }
74     nentryp->nServers = oentryp->nServers;
75     for (i = 0; i < MAXTYPES; i++)
76         nentryp->volumeId[i] = oentryp->volumeId[i];
77     nentryp->cloneId = oentryp->cloneId;
78     nentryp->flags = oentryp->flags;
79 }
80
81 static
82 nvlentry_to_ovlentry(nentryp, oentryp)
83      struct nvldbentry *nentryp;
84      struct vldbentry *oentryp;
85 {
86     register int i;
87
88     memset(oentryp, 0, sizeof(struct vldbentry));
89     strncpy(oentryp->name, nentryp->name, sizeof(oentryp->name));
90     if (nentryp->nServers > OMAXNSERVERS) {
91         /*
92          * The alternative is to store OMAXSERVERS but it's always better
93          * to know what's going on...
94          */
95         return VL_BADSERVER;
96     }
97     for (i = 0; i < nentryp->nServers; i++) {
98         oentryp->serverNumber[i] = nentryp->serverNumber[i];
99         oentryp->serverPartition[i] = nentryp->serverPartition[i];
100         oentryp->serverFlags[i] = nentryp->serverFlags[i];
101     }
102     oentryp->nServers = i;
103     for (i = 0; i < MAXTYPES; i++)
104         oentryp->volumeId[i] = nentryp->volumeId[i];
105     oentryp->cloneId = nentryp->cloneId;
106     oentryp->flags = nentryp->flags;
107     return 0;
108 }
109
110 static int newvlserver = 0;
111
112 VLDB_CreateEntry(entryp)
113      struct nvldbentry *entryp;
114 {
115     struct vldbentry oentry;
116     register int code;
117
118     if (newvlserver == 1) {
119       tryold:
120         code = nvlentry_to_ovlentry(entryp, &oentry);
121         if (code)
122             return code;
123         code = ubik_Call(VL_CreateEntry, cstruct, 0, &oentry);
124         return code;
125     }
126     code = ubik_Call(VL_CreateEntryN, cstruct, 0, entryp);
127     if (!newvlserver) {
128         if (code == RXGEN_OPCODE) {
129             newvlserver = 1;    /* Doesn't support new interface */
130             goto tryold;
131         } else if (!code) {
132             newvlserver = 2;
133         }
134     }
135     return code;
136 }
137
138 VLDB_GetEntryByID(volid, voltype, entryp)
139      afs_int32 volid, voltype;
140      struct nvldbentry *entryp;
141 {
142     struct vldbentry oentry;
143     register int code;
144
145     if (newvlserver == 1) {
146       tryold:
147         code =
148             ubik_Call(VL_GetEntryByID, cstruct, 0, volid, voltype, &oentry);
149         if (!code)
150             ovlentry_to_nvlentry(&oentry, entryp);
151         return code;
152     }
153     code = ubik_Call(VL_GetEntryByIDN, cstruct, 0, volid, voltype, entryp);
154     if (!newvlserver) {
155         if (code == RXGEN_OPCODE) {
156             newvlserver = 1;    /* Doesn't support new interface */
157             goto tryold;
158         } else if (!code) {
159             newvlserver = 2;
160         }
161     }
162     return code;
163 }
164
165 VLDB_GetEntryByName(namep, entryp)
166      char *namep;
167      struct nvldbentry *entryp;
168 {
169     struct vldbentry oentry;
170     register int code;
171
172     if (newvlserver == 1) {
173       tryold:
174         code = ubik_Call(VL_GetEntryByNameO, cstruct, 0, namep, &oentry);
175         if (!code)
176             ovlentry_to_nvlentry(&oentry, entryp);
177         return code;
178     }
179     code = ubik_Call(VL_GetEntryByNameN, cstruct, 0, namep, entryp);
180     if (!newvlserver) {
181         if (code == RXGEN_OPCODE) {
182             newvlserver = 1;    /* Doesn't support new interface */
183             goto tryold;
184         } else if (!code) {
185             newvlserver = 2;
186         }
187     }
188     return code;
189 }
190
191 VLDB_ReplaceEntry(volid, voltype, entryp, releasetype)
192      afs_int32 volid, voltype, releasetype;
193      struct nvldbentry *entryp;
194 {
195     struct vldbentry oentry;
196     register int code;
197
198     if (newvlserver == 1) {
199       tryold:
200         code = nvlentry_to_ovlentry(entryp, &oentry);
201         if (code)
202             return code;
203         code =
204             ubik_Call(VL_ReplaceEntry, cstruct, 0, volid, voltype, &oentry,
205                       releasetype);
206         return code;
207     }
208     code =
209         ubik_Call(VL_ReplaceEntryN, cstruct, 0, volid, voltype, entryp,
210                   releasetype);
211     if (!newvlserver) {
212         if (code == RXGEN_OPCODE) {
213             newvlserver = 1;    /* Doesn't support new interface */
214             goto tryold;
215         } else if (!code) {
216             newvlserver = 2;
217         }
218     }
219     return code;
220 }
221
222
223
224 VLDB_ListAttributes(attrp, entriesp, blkentriesp)
225      VldbListByAttributes *attrp;
226      afs_int32 *entriesp;
227      nbulkentries *blkentriesp;
228 {
229     bulkentries arrayEntries;
230     register int code, i;
231
232     if (newvlserver == 1) {
233       tryold:
234         memset(&arrayEntries, 0, sizeof(arrayEntries)); /*initialize to hint the stub  to alloc space */
235         code =
236             ubik_Call(VL_ListAttributes, cstruct, 0, attrp, entriesp,
237                       &arrayEntries);
238         if (!code) {
239             blkentriesp->nbulkentries_val =
240                 (nvldbentry *) malloc(*entriesp * sizeof(struct nvldbentry));
241             for (i = 0; i < *entriesp; i++) {   /* process each entry */
242                 ovlentry_to_nvlentry(&arrayEntries.bulkentries_val[i],
243                                      &blkentriesp->nbulkentries_val[i]);
244             }
245         }
246         if (arrayEntries.bulkentries_val)
247             free(arrayEntries.bulkentries_val);
248         return code;
249     }
250     code =
251         ubik_Call(VL_ListAttributesN, cstruct, 0, attrp, entriesp,
252                   blkentriesp);
253     if (!newvlserver) {
254         if (code == RXGEN_OPCODE) {
255             newvlserver = 1;    /* Doesn't support new interface */
256             goto tryold;
257         } else if (!code) {
258             newvlserver = 2;
259         }
260     }
261     return code;
262 }
263
264 VLDB_ListAttributesN2(attrp, name, thisindex, nentriesp, blkentriesp,
265                       nextindexp)
266      VldbListByAttributes *attrp;
267      char *name;
268      afs_int32 thisindex;
269      afs_int32 *nentriesp;
270      nbulkentries *blkentriesp;
271      afs_int32 *nextindexp;
272 {
273     afs_int32 code;
274
275     code =
276         ubik_Call(VL_ListAttributesN2, cstruct, 0, attrp, (name ? name : ""),
277                   thisindex, nentriesp, blkentriesp, nextindexp);
278     return code;
279 }
280
281
282 static int vlserverv4 = -1;
283 struct cacheips {
284     afs_int32 server;
285     afs_int32 count;
286     afs_uint32 addrs[16];
287 };
288 /*
289  * Increase cache size.  This avoids high CPU usage by the vlserver
290  * in environments where there are more than 16 fileservers in the
291  * cell.
292  */
293 #define GETADDRUCACHESIZE             64
294 struct cacheips cacheips[GETADDRUCACHESIZE];
295 int cacheip_index = 0;
296
297 VLDB_IsSameAddrs(serv1, serv2, errorp)
298      afs_int32 serv1, serv2, *errorp;
299 {
300     register int code;
301     ListAddrByAttributes attrs;
302     bulkaddrs addrs;
303     afs_uint32 *addrp, nentries, unique, i, j, f1, f2;
304     afsUUID uuid;
305     static int initcache = 0;
306
307     *errorp = 0;
308
309     if (serv1 == serv2)
310         return 1;
311     if (vlserverv4 == 1) {
312         return 0;
313     }
314     if (!initcache) {
315         for (i = 0; i < GETADDRUCACHESIZE; i++) {
316             cacheips[i].server = cacheips[i].count = 0;
317         }
318         initcache = 1;
319     }
320
321     /* See if it's cached */
322     for (i = 0; i < GETADDRUCACHESIZE; i++) {
323         f1 = f2 = 0;
324         for (j = 0; j < cacheips[i].count; j++) {
325             if (serv1 == cacheips[i].addrs[j])
326                 f1 = 1;
327             else if (serv2 == cacheips[i].addrs[j])
328                 f2 = 1;
329
330             if (f1 && f2)
331                 return 1;
332         }
333         if (f1 || f2)
334             return 0;
335         if (cacheips[i].server == serv1)
336             return 0;
337     }
338
339     memset(&attrs, 0, sizeof(attrs));
340     attrs.Mask = VLADDR_IPADDR;
341     attrs.ipaddr = serv1;
342     memset(&addrs, 0, sizeof(addrs));
343     memset(&uuid, 0, sizeof(uuid));
344     code =
345         ubik_Call(VL_GetAddrsU, cstruct, 0, &attrs, &uuid, &unique, &nentries,
346                   &addrs);
347     if (vlserverv4 == -1) {
348         if (code == RXGEN_OPCODE) {
349             vlserverv4 = 1;     /* Doesn't support new interface */
350             return 0;
351         } else if (!code) {
352             vlserverv4 = 2;
353         }
354     }
355     if (code == VL_NOENT)
356         return 0;
357     if (code) {
358         *errorp = code;
359         return 0;
360     }
361
362     code = 0;
363     if (nentries > GETADDRUCACHESIZE)
364         nentries = GETADDRUCACHESIZE;   /* safety check; should not happen */
365     if (++cacheip_index >= GETADDRUCACHESIZE)
366         cacheip_index = 0;
367     cacheips[cacheip_index].server = serv1;
368     cacheips[cacheip_index].count = nentries;
369     addrp = addrs.bulkaddrs_val;
370     for (i = 0; i < nentries; i++, addrp++) {
371         cacheips[cacheip_index].addrs[i] = *addrp;
372         if (serv2 == *addrp) {
373             code = 1;
374         }
375     }
376     return code;
377 }
378
379
380 #ifdef  notdef
381 afs_int32
382 subik_Call(aproc, aclient, aflags, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,
383            p11, p12, p13, p14, p15, p16)
384      register struct ubik_client *aclient;
385      int (*aproc) ();
386      afs_int32 aflags;
387      afs_int32 p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14,
388          p15, p16;
389 {
390     struct vldbentry vldbentry;
391     register int code, (*nproc) ();
392
393     if (newvlserver == 1) {
394     }
395     code =
396         ubik_Call(aproc, aclient, aflags, p1, p2, p3, p4, p5, p6, p7, p8, p9,
397                   p10, p11, p12, p13, p14, p15, p16);
398     if (!newvlserver) {
399         if (code == RXGEN_OPCODE) {
400             newvlserver = 1;    /* Doesn't support new interface */
401         } else if (!code) {
402             newvlserver = 2;
403         }
404     }
405 }
406 #endif /* notdef */
407
408
409 /*
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.
414 */
415 void
416 vsu_SetCrypt(cryptflag)
417      int cryptflag;
418 {
419     if (cryptflag) {
420         vsu_rxkad_level = rxkad_crypt;
421     } else {
422         vsu_rxkad_level = rxkad_auth;
423     }
424 }
425
426
427 /*
428   Get the appropriate type of ubik client structure out from the system.
429 */
430 afs_int32
431 vsu_ClientInit(noAuthFlag, confDir, cellName, sauth, uclientp, secproc)
432      int noAuthFlag;
433      int (*secproc) ();
434      char *cellName;
435      struct ubik_client **uclientp;
436      char *confDir;
437      afs_int32 sauth;
438 {
439     afs_int32 code, scIndex, i;
440     struct afsconf_cell info;
441     struct afsconf_dir *tdir;
442     struct ktc_principal sname;
443     struct ktc_token ttoken;
444     struct rx_securityClass *sc;
445     static struct rx_connection *serverconns[VLDB_MAXSERVERS];
446     char cellstr[64];
447
448     return ugen_ClientInit(noAuthFlag, confDir, cellName, sauth, uclientp, 
449                            secproc, "vsu_ClientInit", vsu_rxkad_level,
450                            VLDB_MAXSERVERS, AFSCONF_VLDBSERVICE, 90,
451                            0, 0, USER_SERVICE_ID);
452 }
453
454
455 /*extract the name of volume <name> without readonly or backup suffixes
456  * and return the result as <rname>.
457  */
458 int
459 vsu_ExtractName(rname, name)
460      char rname[], name[];
461 {
462     char sname[VOLSER_OLDMAXVOLNAME + 1];
463     int total;
464
465     strncpy(sname, name, sizeof(sname));
466     sname[sizeof(sname) - 1] = '\0';
467     total = strlen(sname);
468     if (!strcmp(&sname[total - 9], ".readonly")) {
469         /*discard the last 8 chars */
470         sname[total - 9] = '\0';
471         strcpy(rname, sname);
472         return 0;
473     } else if (!strcmp(&sname[total - 7], ".backup")) {
474         /*discard last 6 chars */
475         sname[total - 7] = '\0';
476         strcpy(rname, sname);
477         return 0;
478     } else {
479         strncpy(rname, name, VOLSER_OLDMAXVOLNAME);
480         rname[VOLSER_OLDMAXVOLNAME] = '\0';
481         return -1;
482     }
483 }
484
485
486 /* returns 0 if failed */
487 afs_uint32
488 vsu_GetVolumeID(astring, acstruct, errp)
489      struct ubik_client *acstruct;
490      afs_int32 *errp;
491      char *astring;
492 {
493     afs_uint32 tc, value;
494
495     char *str, *ptr, volname[VOLSER_OLDMAXVOLNAME + 1];
496     int tryname, curval;
497     struct nvldbentry entry;
498     afs_int32 vcode = 0;
499     int total;
500
501     *errp = 0;
502     total = strlen(astring);
503     str = astring;
504     ptr = astring;
505     tryname = 0;
506     while ((curval = *str++)) {
507         if (curval < '0' || curval > '9')
508             tryname = 1;
509     }
510
511     if (tryname) {
512         vsu_ExtractName(volname, astring);
513         vcode = VLDB_GetEntryByName(volname, &entry);
514         if (!vcode) {
515             if (!strcmp(&astring[total - 9], ".readonly"))
516                 return entry.volumeId[ROVOL];
517             else if ((!strcmp(&astring[total - 7], ".backup")))
518                 return entry.volumeId[BACKVOL];
519             else
520                 return (entry.volumeId[RWVOL]);
521         } else {
522             *errp = vcode;
523             return 0;           /* can't find volume */
524         }
525     }
526
527     value = 0;
528     while ((tc = *astring++)) {
529         if (tc & 0x80) {
530             if (!tryname)
531                 fprintf(STDERR, "goofed in volid \n");
532             else {
533                 fprintf(STDERR, "Could not get entry from vldb for %s\n",
534                         ptr);
535                 PrintError("", vcode);
536             }
537             *errp = EINVAL;
538             return 0;
539         }
540         if (tc < '0' || tc > '9') {
541             if (!tryname)
542                 fprintf(STDERR,
543                         "internal error: out of range char in vol ID\n");
544             else {
545                 fprintf(STDERR, "Could not get entry from vldb for %s\n",
546                         ptr);
547                 PrintError("", vcode);
548             }
549             *errp = ERANGE;
550             return 0;
551         }
552         value *= 10;
553         value += (tc - '0');
554     }
555     return value;
556 }