misc-build-cleanup-20010917
[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("$Header$");
14
15 #include <afs/stds.h>
16 #ifdef AFS_NT40_ENV
17 #include <fcntl.h>
18 #include <winsock2.h>
19 #else
20 #include <sys/types.h>
21 #include <sys/file.h>
22 #include <netdb.h>
23 #include <netinet/in.h>
24 #endif /* AFS_NT40_ENV */
25 #include <sys/stat.h>
26 #ifdef AFS_AIX_ENV
27 #include <sys/statfs.h>
28 #endif
29 #include <errno.h>
30 #include <lock.h>
31 #include <rx/xdr.h>
32 #include <rx/rx.h>
33 #include <rx/rx_globals.h>
34 #include <afs/nfs.h>
35 #include <afs/vlserver.h>
36 #include <afs/auth.h>
37 #include <afs/cellconfig.h>
38 #include <afs/keys.h>
39 #include <ubik.h>
40 #include <afs/afsint.h>
41 #include <afs/cmd.h>
42 #include <rx/rxkad.h>
43 #include "volser.h"
44 #include "volint.h"
45 #include "lockdata.h"
46
47 struct ubik_client *cstruct;
48 extern int VL_CreateEntry(), VL_CreateEntryN();
49 extern int VL_GetEntryByID(), VL_GetEntryByIDN();
50 extern int VL_GetEntryByNameO(), VL_GetEntryByNameN();
51 extern int VL_ReplaceEntry(), VL_ReplaceEntryN();
52 extern int VL_ListAttributes(), VL_ListAttributesN(), VL_ListAttributesN2();
53
54 static void ovlentry_to_nvlentry(oentryp, nentryp)
55     struct vldbentry *oentryp;
56     struct nvldbentry *nentryp;
57 {
58     register int i;
59
60     memset(nentryp, 0, sizeof(struct nvldbentry));
61     strncpy(nentryp->name, oentryp->name, sizeof(nentryp->name));
62     for (i=0; i < oentryp->nServers; i++) {
63         nentryp->serverNumber[i] = oentryp->serverNumber[i];
64         nentryp->serverPartition[i] = oentryp->serverPartition[i];
65         nentryp->serverFlags[i] = oentryp->serverFlags[i];
66     }
67     nentryp->nServers = oentryp->nServers;
68     for (i=0; i<MAXTYPES; i++)
69         nentryp->volumeId[i] = oentryp->volumeId[i];
70     nentryp->cloneId = oentryp->cloneId;
71     nentryp->flags = oentryp->flags;
72 }
73
74 static 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_Call(VL_CreateEntry, cstruct, 0, &oentry);
116         return code;
117     }
118     code = ubik_Call(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 = ubik_Call(VL_GetEntryByID, cstruct, 0, volid, voltype, &oentry);
140         if (!code)
141             ovlentry_to_nvlentry(&oentry, entryp);
142         return code;
143     }
144     code = ubik_Call(VL_GetEntryByIDN, cstruct, 0, volid, voltype, entryp);
145     if (!newvlserver) {
146         if (code == RXGEN_OPCODE) {
147             newvlserver = 1;    /* Doesn't support new interface */
148             goto tryold;
149         } else if (!code) {
150             newvlserver = 2;
151         }
152     }
153     return code;
154 }
155
156 VLDB_GetEntryByName(namep, entryp)
157     char *namep;
158     struct nvldbentry *entryp;
159 {
160     struct vldbentry oentry;
161     register int code;
162
163     if (newvlserver == 1) {
164 tryold:
165         code = ubik_Call(VL_GetEntryByNameO, cstruct, 0, namep, &oentry);
166         if (!code)
167             ovlentry_to_nvlentry(&oentry, entryp);
168         return code;
169     }
170     code = ubik_Call(VL_GetEntryByNameN, cstruct, 0, namep, entryp);
171     if (!newvlserver) {
172         if (code == RXGEN_OPCODE) {
173             newvlserver = 1;    /* Doesn't support new interface */
174             goto tryold;
175         } else if (!code) {
176             newvlserver = 2;
177         }
178     }
179     return code;
180 }
181
182 VLDB_ReplaceEntry(volid, voltype, entryp, releasetype)
183     afs_int32 volid, voltype, releasetype;
184     struct nvldbentry *entryp;
185 {
186     struct vldbentry oentry;
187     register int code;
188
189     if (newvlserver == 1) {
190 tryold:
191         code = nvlentry_to_ovlentry(entryp, &oentry);
192         if (code)
193             return code;
194         code = ubik_Call(VL_ReplaceEntry, cstruct, 0, volid, voltype, &oentry, releasetype);
195         return code;
196     }
197     code = ubik_Call(VL_ReplaceEntryN, cstruct, 0, volid, voltype, entryp, releasetype);
198     if (!newvlserver) {
199         if (code == RXGEN_OPCODE) {
200             newvlserver = 1;    /* Doesn't support new interface */
201             goto tryold;
202         } else if (!code) {
203             newvlserver = 2;
204         }
205     }
206     return code;
207 }
208
209
210
211 VLDB_ListAttributes(attrp, entriesp, blkentriesp)
212     VldbListByAttributes *attrp;     
213     afs_int32 *entriesp;
214     nbulkentries *blkentriesp;
215 {
216     bulkentries arrayEntries;
217     register int code, i;
218
219     if (newvlserver == 1) {
220 tryold:
221         memset(&arrayEntries, 0, sizeof(arrayEntries)); /*initialize to hint the stub  to alloc space */
222         code = ubik_Call(VL_ListAttributes, cstruct, 0, attrp, entriesp, &arrayEntries);
223         if (!code) {
224             blkentriesp->nbulkentries_val = (nvldbentry *)malloc(*entriesp * sizeof(struct nvldbentry));
225             for (i = 0; i < *entriesp; i++) {   /* process each entry */
226                 ovlentry_to_nvlentry(&arrayEntries.bulkentries_val[i], &blkentriesp->nbulkentries_val[i]);              
227             }
228         }
229         if (arrayEntries.bulkentries_val) free(arrayEntries.bulkentries_val);
230         return code;
231     }
232     code = ubik_Call(VL_ListAttributesN, cstruct, 0, attrp, entriesp, blkentriesp);
233     if (!newvlserver) {
234         if (code == RXGEN_OPCODE) {
235             newvlserver = 1;    /* Doesn't support new interface */
236             goto tryold;
237         } else if (!code) {
238             newvlserver = 2;
239         }
240     }
241     return code;
242 }
243
244 VLDB_ListAttributesN2(attrp, name, thisindex, nentriesp, blkentriesp, nextindexp)
245   VldbListByAttributes *attrp;
246   char                 *name;
247   afs_int32                thisindex;
248   afs_int32                *nentriesp;
249   nbulkentries         *blkentriesp;
250   afs_int32                *nextindexp;
251 {
252   afs_int32 code;
253
254   code = ubik_Call(VL_ListAttributesN2, cstruct, 0, 
255                    attrp, (name?name:""), thisindex, 
256                    nentriesp, blkentriesp, nextindexp);
257   return code;
258 }
259
260
261 static int vlserverv4=-1;
262 struct cacheips {
263     afs_int32 server;
264     afs_int32 count;
265     afs_uint32 addrs[16];
266 };
267 struct cacheips cacheips[16];
268 int cacheip_index=0;
269 extern int VL_GetAddrsU();
270 VLDB_IsSameAddrs(serv1, serv2, errorp)
271     afs_int32 serv1, serv2, *errorp;
272 {
273     register int code;
274     ListAddrByAttributes attrs;
275     bulkaddrs addrs;
276     afs_uint32 *addrp, nentries,  unique, i, j, f1, f2;
277     afsUUID uuid;
278     static int initcache = 0;
279
280     *errorp = 0;
281
282     if (serv1 == serv2)   
283         return 1;
284     if (vlserverv4 == 1) {
285         return 0;
286     }
287     if (!initcache) {
288         for (i=0; i<16; i++) {
289            cacheips[i].server = cacheips[i].count = 0;
290         }
291         initcache = 1;
292     }
293
294     /* See if it's cached */
295     for (i=0; i<16; i++) {
296        f1 = f2 = 0;
297        for (j=0; j < cacheips[i].count; j++) {
298           if      (serv1 == cacheips[i].addrs[j]) f1 = 1;
299           else if (serv2 == cacheips[i].addrs[j]) f2 = 1;
300
301           if (f1 && f2)
302              return 1;
303        }        
304        if (f1 || f2)
305           return 0;
306   }
307
308     memset(&attrs, 0, sizeof(attrs));
309     attrs.Mask = VLADDR_IPADDR;
310     attrs.ipaddr = serv1;
311     memset(&addrs, 0, sizeof(addrs));
312     memset(&uuid, 0, sizeof(uuid));
313     code = ubik_Call(VL_GetAddrsU, cstruct, 0, &attrs, &uuid, &unique, &nentries, &addrs);
314     if (vlserverv4 == -1) {
315         if (code == RXGEN_OPCODE) {
316             vlserverv4 = 1;     /* Doesn't support new interface */
317             return 0;
318         } else if (!code) {
319             vlserverv4 = 2;
320         }
321     }
322     if (code == VL_NOENT)
323         return 0;
324     if (code) {
325         *errorp = code;
326         return 0;
327     }
328
329     code = 0;
330     if (++cacheip_index >= 16) cacheip_index = 0;
331     cacheips[cacheip_index].server = serv1;
332     cacheips[cacheip_index].count = nentries;
333     addrp = addrs.bulkaddrs_val;
334     for (i=0; i<nentries; i++, addrp++) {
335         cacheips[cacheip_index].addrs[i] = *addrp;
336         if (serv2 == *addrp) {
337             code = 1;
338         }
339     }
340     return code;
341 }
342
343
344 #ifdef  notdef
345 afs_int32 subik_Call(aproc, aclient, aflags, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)
346     register struct ubik_client *aclient;
347     int (*aproc)();
348     afs_int32 aflags;
349     afs_int32 p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16;
350 {
351     struct vldbentry vldbentry;
352     register int code, (*nproc)();
353
354     if (newvlserver == 1) {
355     }
356     code = ubik_Call(aproc, aclient, aflags, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16);
357     if (!newvlserver) {
358         if (code == RXGEN_OPCODE) {
359             newvlserver = 1;    /* Doesn't support new interface */
360         } else if (!code) {
361             newvlserver = 2;
362         }
363     }
364 }
365 #endif /* notdef */
366
367
368 /*
369   Get the appropriate type of ubik client structure out from the system.
370 */
371 afs_int32 vsu_ClientInit(noAuthFlag, confDir, cellName, sauth, uclientp, secproc)
372     int noAuthFlag;
373     int (*secproc)();
374     char *cellName;
375     struct ubik_client **uclientp;
376     char *confDir;
377     afs_int32 sauth;
378 {
379     afs_int32 code, scIndex, i;
380     struct afsconf_cell info;
381     struct afsconf_dir *tdir;
382     struct ktc_principal sname;
383     struct ktc_token ttoken;
384     struct rx_securityClass *sc;
385     static struct rx_connection *serverconns[VLDB_MAXSERVERS];
386     char cellstr[64];
387
388
389     code = rx_Init(0);
390     if (code) {
391         fprintf(STDERR,"vsu_ClientInit: could not initialize rx.\n");
392         return code;
393     }
394     rx_SetRxDeadTime(90);
395
396     if (sauth) {  /* -localauth */
397         tdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
398         if (!tdir) {
399             fprintf(STDERR, "vsu_ClientInit: Could not process files in configuration directory (%s).\n",
400                     AFSDIR_SERVER_ETC_DIRPATH);
401             return -1;
402         }
403         code = afsconf_ClientAuth(tdir, &sc, &scIndex); /* sets sc,scIndex */
404         if (code) {
405             fprintf(STDERR, "vsu_ClientInit: Could not get security object for -localAuth\n");
406             return -1;
407         }
408         code = afsconf_GetCellInfo(tdir, tdir->cellName, AFSCONF_VLDBSERVICE,
409                &info);
410         if (code) {
411             fprintf(STDERR, "vsu_ClientInit: can't find cell %s's hosts in %s/%s\n",
412                    cellName, AFSDIR_SERVER_ETC_DIRPATH,AFSDIR_CELLSERVDB_FILE);
413             exit(1);
414         }
415     }
416     else {  /* not -localauth */
417         tdir = afsconf_Open(confDir);
418         if (!tdir) {
419             fprintf(STDERR, "vsu_ClientInit: Could not process files in configuration directory (%s).\n",
420                     confDir);
421             return -1;
422         }
423
424         if (!cellName) {
425             code = afsconf_GetLocalCell(tdir, cellstr, sizeof(cellstr));
426             if (code) {
427                 fprintf(STDERR, "vsu_ClientInit: can't get local cellname, check %s/%s\n",
428                         confDir, AFSDIR_THISCELL_FILE);
429                 exit(1);
430             }
431             cellName = cellstr;
432         }
433
434         code = afsconf_GetCellInfo(tdir, cellName, AFSCONF_VLDBSERVICE, &info);
435         if (code) {
436             fprintf(STDERR, "vsu_ClientInit: can't find cell %s's hosts in %s/%s\n",
437                     cellName, confDir,AFSDIR_CELLSERVDB_FILE);
438             exit(1);
439         }
440         if (noAuthFlag)    /* -noauth */
441             scIndex = 0;
442         else {             /* not -noauth */
443             strcpy(sname.cell, info.name);
444             sname.instance[0] = 0;
445             strcpy(sname.name, "afs");
446             code = ktc_GetToken(&sname, &ttoken, sizeof(ttoken), (char *)0);
447             if (code) {   /* did not get ticket */
448                 fprintf(STDERR, "vsu_ClientInit: Could not get afs tokens, running unauthenticated.\n");
449                 scIndex = 0;
450             }
451             else {     /* got a ticket */
452                 scIndex = 2;
453                 if ((ttoken.kvno < 0) || (ttoken.kvno > 255)) {
454                     fprintf(STDERR, "vsu_ClientInit: funny kvno (%d) in ticket, proceeding\n",
455                             ttoken.kvno);
456                 }
457             }
458         }
459
460         switch (scIndex) {
461           case 0 :
462             sc = (struct rx_securityClass *) rxnull_NewClientSecurityObject();
463             break;
464           case 2:
465             sc = (struct rx_securityClass *)rxkad_NewClientSecurityObject(
466                  rxkad_clear, &ttoken.sessionKey, ttoken.kvno,
467                  ttoken.ticketLen, ttoken.ticket);
468             break;
469           default:
470             fprintf(STDERR, "vsu_ClientInit: unsupported security index %d\n",
471                      scIndex);
472             exit(1);
473             break;
474         }
475     }
476
477     if (secproc)     /* tell UV module about default authentication */
478         (*secproc) (sc, scIndex);
479     if (info.numServers > VLDB_MAXSERVERS) {
480         fprintf(STDERR, "vsu_ClientInit: info.numServers=%d (> VLDB_MAXSERVERS=%d)\n",
481                 info.numServers, VLDB_MAXSERVERS);
482         exit(1);
483     }
484     for (i=0; i<info.numServers; i++) {
485         serverconns[i] = rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
486                          info.hostAddr[i].sin_port, USER_SERVICE_ID,
487                          sc, scIndex);
488     }
489     *uclientp = 0;
490     code = ubik_ClientInit(serverconns, uclientp);
491     if (code) {
492         fprintf(STDERR, "vsu_ClientInit: ubik client init failed.\n");
493         return code;
494     }
495     return 0;
496 }
497
498
499 /*extract the name of volume <name> without readonly or backup suffixes
500  * and return the result as <rname>.
501  */
502 vsu_ExtractName(rname,name)
503 char rname[],name[];
504 {   char sname[32];
505     int total;
506
507     strcpy(sname,name);
508     total = strlen(sname);
509     if(!strcmp(&sname[total - 9],".readonly")) {
510         /*discard the last 8 chars */
511         sname[total - 9] = '\0';
512         strcpy(rname,sname);
513         return 0;
514     }
515     else if(!strcmp(&sname[total - 7 ],".backup")) {
516         /*discard last 6 chars */
517         sname[total - 7] = '\0';
518         strcpy(rname,sname);
519         return 0;
520     }
521     else {
522         strncpy(rname,name,VOLSER_OLDMAXVOLNAME);
523         return -1;
524     }
525 }
526
527
528 /* returns 0 if failed */
529 afs_uint32 vsu_GetVolumeID(astring, acstruct, errp)
530 struct ubik_client *acstruct;
531 afs_int32 *errp;
532 char *astring; {
533     afs_uint32 tc, value;
534
535     char *str,*ptr, volname[VOLSER_OLDMAXVOLNAME+1];
536     int tryname, curval;
537     struct nvldbentry entry;
538     afs_int32 vcode = 0;
539     int total;
540
541     *errp = 0;
542     total = strlen(astring);
543     str = astring;
544     ptr = astring;
545     tryname = 0;
546     while (curval = *str++){
547         if(curval < '0' || curval > '9')
548             tryname = 1;
549     }
550
551     if(tryname) {
552         vsu_ExtractName(volname,astring);
553         vcode = VLDB_GetEntryByName(volname, &entry);
554         if(!vcode) {
555             if(!strcmp(&astring[total - 9],".readonly"))
556                 return entry.volumeId[ROVOL];
557             else if ((!strcmp(&astring[total - 7 ],".backup")))
558                 return entry.volumeId[BACKVOL];
559             else
560                 return (entry.volumeId[RWVOL]);   
561         } else {
562             *errp = vcode;
563             return 0;   /* can't find volume */
564         }
565     }
566
567     value = 0;
568     while (tc = *astring++) {
569         if (tc & 0x80) {
570             if(!tryname) fprintf(STDERR,"goofed in volid \n");
571             else {fprintf(STDERR,"Could not get entry from vldb for %s\n",ptr);PrintError("",vcode);}
572             *errp = EINVAL;
573             return 0;
574         }
575         if (tc < '0' || tc > '9'){
576             if(!tryname) fprintf(STDERR,"internal error: out of range char in vol ID\n");
577             else {fprintf(STDERR,"Could not get entry from vldb for %s\n",ptr);PrintError("",vcode);}
578             *errp = ERANGE;
579             return 0;
580         }
581         value *= 10;
582         value += (tc - '0');
583     }
584     return value;
585 }