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