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