OPENAFS-SA-2016-002 ListAddrByAttributes information leak
[openafs.git] / src / vlserver / vlclient.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 #include <afs/stds.h>
13
14 #include <roken.h>
15
16 #ifdef AFS_NT40_ENV
17 #include <WINNT/afsevent.h>
18 #endif
19 #ifdef HAVE_SYS_FILE_H
20 #include <sys/file.h>
21 #endif
22 #include <ctype.h>
23
24 #include <afs/afsutil.h>
25 #include <rx/xdr.h>
26 #include <rx/rx.h>
27 #include <rx/rx_globals.h>
28 #include <rx/rxkad.h>
29 #include <afs/cellconfig.h>
30 #include <afs/keys.h>
31 #include <afs/cmd.h>
32 #include <lock.h>
33 #include <ubik.h>
34
35 #include "vlserver.h"
36
37 void fill_listattributes_entry(struct VldbListByAttributes *, char **, int);
38 void display_listattributes_entry(struct VldbListByAttributes *,int);
39 void display_entry(struct vldbentry *, int);
40 void display_entryN(struct nvldbentry *, int);
41 void display_update_entry(struct VldbUpdateEntry *, int);
42 void dump_stats(vldstats *, vital_vlheader *);
43 void GetArgs(char *, char **, int *);
44 void print_usage(void);
45 void fill_entry(struct vldbentry *, char **, int);
46 void fill_update_entry(struct VldbUpdateEntry *, char **, int);
47
48 #define VL_NUMBER_OPCODESX      34
49 static char *opcode_names[VL_NUMBER_OPCODESX] = {
50     "CreateEntry",
51     "DeleteEntry",
52     "GetEntryByID",
53     "GetEntryByName",
54     "GetNewVolumeId",
55     "ReplaceEntry",
56     "UpdateEntry",
57     "SetLock",
58     "ReleaseLock",
59     "ListEntry",
60     "ListAttributes",
61     "LinkedList",
62     "GetStats",
63     "Probe",    /* RPC is ProbeServer */
64     "GetAddrs",
65     "ChangeAddr",
66     "CreateEntryN",
67     "GetEntryByIDN",
68     "GetEntryByNameN",
69     "ReplaceEntryN",
70     "ListEntryN",
71     "ListAttributesN",
72     "LinkedListN",
73     "UpdateeEntryByName",
74     "CreateEntryU",
75     "GetEntryByIDU",
76     "GetEntryByNameU",
77     "ReplaceEntryU",
78     "ListEntryU",
79     "ListAttributesU",
80     "LinkedListU",
81     "RegisterAddr",
82     "GetAddrsU",
83     "ListAttributesN2"
84 };
85
86 struct Vlent {
87     struct Vlent *next;
88     afs_int32 rwid;
89     afs_int32 roid;
90     afs_int32 baid;
91     char name[64];
92 };
93
94 #define NVOLS   1000
95 #define ALLOCNT 50000
96 struct Vlent *VLa[NVOLS];
97 #define VHash(avol)     ((avol)&(NVOLS-1))
98 struct Vlent *VL, *SVL;
99 int VLcnt = 0;
100 struct ubik_client *cstruct;
101 struct rx_connection *serverconns[MAXSERVERS];
102 char confdir[AFSDIR_PATH_MAX];
103 char *(args[50]);
104
105 struct Vlent *
106 GetVolume(int vol, struct vldbentry *entry)
107 {
108     int i;
109     struct Vlent *vl;
110
111     if (!vol)
112         return NULL;
113     i = VHash(vol);
114     for (vl = VLa[i]; vl; vl = vl->next) {
115         if ((vl->rwid == vol && vol != entry->volumeId[0])
116             || (vl->roid == vol && vol != entry->volumeId[1])
117             || (vl->baid == vol && vol != entry->volumeId[2])) {
118             return vl;
119         }
120     }
121     VL->rwid = entry->volumeId[0];
122     VL->roid = entry->volumeId[1];
123     VL->baid = entry->volumeId[2];
124     strcpy(entry->name, VL->name);
125     VL->next = VLa[i];
126     VLa[i] = VL;
127     if (VLcnt++ > ALLOCNT) {    /* XXXX FIX XXXXXXXXX */
128         printf("Too many entries (> %d)\n", ALLOCNT);
129         exit(1);
130     }
131     VL++;
132     return NULL;
133 }
134
135 /* Almost identical's to pr_Initialize in vlserver/pruser.c */
136 afs_int32
137 vl_Initialize(char *confDir, int secFlags, int server, char *cellp)
138 {
139     return ugen_ClientInitServer(confDir, cellp, secFlags, &cstruct,
140                                  MAXSERVERS, AFSCONF_VLDBSERVICE, 90,
141                                  server, htons(AFSCONF_VLDBPORT));
142 }
143
144 /* return host address in network byte order */
145 afs_int32
146 GetServer(char *aname)
147 {
148     struct hostent *th;
149     afs_uint32 addr;
150     int b1, b2, b3, b4;
151     afs_int32 code;
152
153     code = sscanf(aname, "%d.%d.%d.%d", &b1, &b2, &b3, &b4);
154     if (code == 4) {
155         addr = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
156         return htonl(addr);     /* convert to network order (128 in byte 0) */
157     }
158     th = gethostbyname(aname);
159     if (!th)
160         return 0;
161     memcpy(&addr, th->h_addr, sizeof(addr));
162     return addr;
163 }
164
165
166 static int
167 handleit(struct cmd_syndesc *as, void *arock)
168 {
169     struct cmd_item *ti;
170     afs_int32 code, server = 0, sawserver = 0;
171     afs_int32 id, voltype;
172     struct vldbentry entry;
173     char *cellp = 0;
174     struct VldbUpdateEntry updateentry;
175     struct VldbListByAttributes listbyattributes;
176     int secFlags = AFSCONF_SECOPTS_FALLBACK_NULL;
177
178     if ((ti = as->parms[0].items))      /* -cellpath <dir> */
179         strcpy(confdir, ti->data);
180     if (as->parms[1].items)     /* -server */
181         strcpy(confdir, AFSDIR_SERVER_ETC_DIRPATH);
182     if (as->parms[2].items)     /* -noauth */
183         secFlags |= AFSCONF_SECOPTS_NOAUTH;
184     if ((ti = as->parms[3].items)) {    /* -host */
185         server = GetServer(ti->data);
186         if (server == 0) {
187             printf("server '%s' not found in host table\n", ti->data);
188             exit(1);
189         }
190         sawserver = 1;
191     }
192     if (sawserver && !as->parms[2].items && (!(ti = as->parms[4].items))) {
193         printf
194             ("Must also specify the -cell' option along with -host for authenticated conns\n");
195         exit(1);
196     }
197     if ((ti = as->parms[4].items)) {    /* -cell */
198         cellp = ti->data;
199     }
200     if ((code = vl_Initialize(confdir, secFlags, server, cellp))) {
201         printf("Couldn't initialize vldb library (code=%d).\n", code);
202         exit(1);
203     }
204
205     if (as->parms[6].items) {   /* -probe */
206         int nconns = 0;
207         int status = 0;
208         int i;
209         char hoststr[16];
210         afs_uint32 addr;
211
212         for (i = 0; cstruct->conns[i]; i++, nconns++) {
213             rx_SetConnDeadTime(cstruct->conns[i], 6);
214             addr = rx_HostOf(rx_PeerOf(cstruct->conns[i]));
215             if (!nconns) {
216                 printf("probing");
217             }
218             printf(" %s", afs_inet_ntoa_r(addr, hoststr));
219         }
220         if (nconns == 0) {
221             printf("no connections\n");
222             return 255;
223         }
224         printf("\n");
225         multi_Rx(cstruct->conns, nconns) {
226             multi_VL_ProbeServer();
227             addr = rx_HostOf(rx_PeerOf(cstruct->conns[multi_i]));
228             if (!multi_error) {
229                 printf(" ok: %s\n", afs_inet_ntoa_r(addr, hoststr));
230             } else {
231                 status = 255;
232                 printf(" not ok (%d): %s\n", multi_error,
233                        afs_inet_ntoa_r(addr, hoststr));
234             }
235         }
236         multi_End;
237         return status;
238     }
239
240     if (as->parms[5].items) {   /* -getstats */
241         vldstats stats;
242         vital_vlheader vital_header;
243         code = ubik_VL_GetStats(cstruct, 0, &stats, &vital_header);
244         if (!code)
245             dump_stats(&stats, &vital_header);
246         exit(0);
247     }
248
249     while (1) {
250         char line[500];
251         int nargs, releasetype;
252         memset(&entry, 0, sizeof(entry));
253         memset(&updateentry, 0, sizeof(updateentry));
254         memset(&listbyattributes, 0, sizeof(listbyattributes));
255         printf("vl> ");
256         if (fgets(line, 499, stdin) == NULL) {
257             printf("\n");
258             exit(0);
259         } else {
260             char *oper, *vname;
261             char **argp = args;
262
263             GetArgs(line, argp, &nargs);
264             oper = &argp[0][0];
265             ++argp, --nargs;
266             if (!*line) {
267             } else if (!strcmp(oper, "cr")) {
268                 fill_entry(&entry, argp, nargs);
269                 display_entry(&entry, 0);
270                 code = ubik_VL_CreateEntry(cstruct, 0, &entry);
271                 printf("return code is %d\n", code);
272             } else if (!strcmp(oper, "rm")) {
273                 sscanf(&(*argp)[0], "%d", &id);
274                 ++argp, --nargs;
275                 sscanf(&(*argp)[0], "%d", &voltype);
276                 code = ubik_VL_DeleteEntry(cstruct, 0, id, voltype);
277                 printf("return code is %d\n", code);
278             } else if (!strcmp(oper, "re")) {
279                 sscanf(&(*argp)[0], "%d", &id);
280                 ++argp, --nargs;
281                 sscanf(&(*argp)[0], "%d", &voltype);
282                 ++argp, --nargs;
283                 sscanf(&(*argp)[0], "%d", &releasetype);
284                 ++argp, --nargs;
285                 fill_entry(&entry, argp, nargs);
286                 display_entry(&entry, 0);
287                 code =
288                     ubik_VL_ReplaceEntry(
289                     cstruct, 0, id, voltype,
290                               &entry, releasetype);
291                 printf("return code is %d\n", code);
292             } else if (!strcmp(oper, "up")) {
293                 sscanf(&(*argp)[0], "%d", &id);
294                 ++argp, --nargs;
295                 sscanf(&(*argp)[0], "%d", &voltype);
296                 ++argp, --nargs;
297                 sscanf(&(*argp)[0], "%d", &releasetype);
298                 ++argp, --nargs;
299                 fill_update_entry(&updateentry, argp, nargs);
300                 display_update_entry(&updateentry, 0);
301                 code =
302                     ubik_VL_UpdateEntry(cstruct, 0, id, voltype,
303                               &updateentry, releasetype);
304                 printf("return code is %d\n", code);
305             } else if (!strcmp(oper, "ls")) {
306                 afs_int32 index, count, next_index;
307                 for (index = 0; 1; index = next_index) {
308                     memset(&entry, 0, sizeof(entry));
309                     code =
310                         ubik_VL_ListEntry(cstruct, 0, index, &count,
311                                   &next_index, &entry);
312                     if (code) {
313                         printf("VL_ListEntry returned code = %d\n", code);
314                         break;
315                     }
316                     if (!next_index)
317                         break;
318                     display_entry(&entry, 0);
319                 }
320             } else if (!strcmp(oper, "ldups")) {
321                 afs_int32 index, count, num = 0, num1 = 0, next_index;
322                 struct Vlent *vl1;
323
324                 VL = SVL = malloc(ALLOCNT * sizeof(struct Vlent));
325                 if (VL == NULL) {
326                     printf("Can't allocate memory...\n");
327                     exit(1);
328                 }
329                 printf("Enumerating all entries in vldb...\n");
330                 for (index = 0; 1; index = next_index) {
331                     memset(&entry, 0, sizeof(entry));
332                     code =
333                         ubik_VL_ListEntry(cstruct, 0, index, &count,
334                                   &next_index, &entry);
335                     if (code) {
336                         printf("VL_ListEntry returned code = %d\n", code);
337                         break;
338                     }
339                     if (!next_index)
340                         break;
341                     num++;
342                     if ((vl1 = GetVolume(entry.volumeId[0], &entry))) {
343                         num1++;
344                         printf
345                             ("Duplicate entry is found for RW vol %u: [RW %u, RO %u, BA %u, name=%s]\n",
346                              entry.volumeId[0], vl1->rwid, vl1->roid,
347                              vl1->baid, vl1->name);
348                     }
349                     if ((vl1 = GetVolume(entry.volumeId[1], &entry))) {
350                         num1++;
351                         printf
352                             ("Duplicate entry is found for RO vol %u: [RW %u, RO %u, BA %u, name=%s]\n",
353                              entry.volumeId[1], vl1->rwid, vl1->roid,
354                              vl1->baid, vl1->name);
355                     }
356                     if ((vl1 = GetVolume(entry.volumeId[2], &entry))) {
357                         num1++;
358                         printf
359                             ("Duplicate entry is found for BA vol %u: [RW %u, RO %u, BA %u, name=%s]\n",
360                              entry.volumeId[2], vl1->rwid, vl1->roid,
361                              vl1->baid, vl1->name);
362                     }
363                     /*display_entry(&entry, 0); */
364                 }
365                 printf("(%d vldb entries found - %d duplicates)\n", num,
366                        num1);
367             } else if (!strcmp(oper, "checkhash")) {
368                 int index, count, num = 0, num1 = 0, num2 = 0, num3 =
369                     0, num31 = 0, num4 = 0, num41 = 0, next_index;
370                 struct vldbentry tentry;
371
372                 VL = SVL = malloc(ALLOCNT * sizeof(struct Vlent));
373                 if (VL == NULL) {
374                     printf("Can't allocate memory...\n");
375                     exit(1);
376                 }
377                 printf("Volumes not found in main hash tables in vldb...\n");
378                 for (index = 0; 1; index = next_index) {
379                     memset(&entry, 0, sizeof(entry));
380                     code =
381                         ubik_VL_ListEntry(cstruct, 0, index, &count,
382                                   &next_index, &entry);
383                     if (code) {
384                         printf("VL_ListEntry returned code = %d\n", code);
385                         break;
386                     }
387                     if (!next_index)
388                         break;
389                     num++;
390                     code =
391                         ubik_VL_GetEntryByNameO(cstruct, 0, entry.name,
392                                   &tentry);
393                     if (code == VL_NOENT) {
394                         num1++;
395                         printf("\tVolume %s %d (not in namehash)\n",
396                                entry.name, entry.volumeId[RWVOL]);
397                     }
398                     code =
399                         ubik_VL_GetEntryByID(cstruct, 0,
400                                   entry.volumeId[RWVOL], RWVOL, &tentry);
401                     if (code == VL_NOENT) {
402                         num2++;
403                         printf("\tVolume %s %d (not in rwid hash)\n",
404                                entry.name, entry.volumeId[RWVOL]);
405                     }
406                     if (entry.volumeId[BACKVOL]) {
407                         code =
408                             ubik_VL_GetEntryByID(cstruct, 0,
409                                       entry.volumeId[BACKVOL], BACKVOL,
410                                       &tentry);
411                         num31++;
412                         if (code == VL_NOENT) {
413                             num3++;
414                             printf("\tVolume %s %d (not in backup id hash)\n",
415                                    entry.name, entry.volumeId[BACKVOL]);
416                         }
417                     }
418                     if (entry.volumeId[ROVOL]) {
419                         code =
420                             ubik_VL_GetEntryByID(cstruct, 0,
421                                       entry.volumeId[ROVOL], ROVOL, &tentry);
422                         num41++;
423                         if (code == VL_NOENT) {
424                             num4++;
425                             printf("\tVolume %s %d (not in RO id hash)\n",
426                                    entry.name, entry.volumeId[ROVOL]);
427                         }
428                     }
429                 }
430                 printf
431                     ("\nTotal vldb entries %d\nTotal volumes %d (%d rw, %d backup, %d ro)\n",
432                      num, num + num31 + num41, num, num31, num41);
433                 printf
434                     ("\n\t%d didn't hash properly by name\n\t%d didn't hash properly by rw volid\n",
435                      num1, num2);
436                 printf
437                     ("\t%d didn't hash properly by backup volid (out of %d)\n\t%d didn't hash properly by ro volid (out of %d)\n",
438                      num3, num31, num4, num41);
439             } else if (!strcmp(oper, "fixhash")) {
440                 int index, count, num = 0, num1 = 0, num2 = 0, next_index, x =
441                     0;
442                 struct vldbentry tentry;
443
444                 VL = SVL = malloc(ALLOCNT * sizeof(struct Vlent));
445                 if (VL == NULL) {
446                     printf("Can't allocate memory...\n");
447                     exit(1);
448                 }
449                 printf
450                     ("Volumes not found in main hash tables in vldb will be fixed...\n");
451                 memset(&updateentry, 0, sizeof(updateentry));
452                 for (index = 0; 1; index = next_index) {
453                     memset(&entry, 0, sizeof(entry));
454                     code =
455                         ubik_VL_ListEntry(cstruct, 0, index, &count,
456                                   &next_index, &entry);
457                     if (code) {
458                         printf("VL_ListEntry returned code = %d\n", code);
459                         break;
460                     }
461                     if (!next_index)
462                         break;
463                     num++;
464                     code =
465                         ubik_VL_GetEntryByNameO(cstruct, 0, entry.name,
466                                   &tentry);
467                     if (code == VL_NOENT) {
468                         num1++;
469                         updateentry.Mask = VLUPDATE_VOLNAMEHASH;
470                         printf("\tVolume %s %d (not in namehash)\n",
471                                entry.name, entry.volumeId[RWVOL]);
472                         code =
473                             ubik_VL_UpdateEntry(cstruct, 0,
474                                       entry.volumeId[RWVOL], -1, &updateentry,
475                                       0);
476                         if (code) {
477                             x++;
478                             printf("\tFailed to update volume %s (err=%d)\n",
479                                    entry.name, code);
480                         }
481                     }
482                     code =
483                         ubik_VL_GetEntryByID(cstruct, 0,
484                                   entry.volumeId[RWVOL], RWVOL, &tentry);
485                     if (code == VL_NOENT) {
486                         num1++;
487                         num2++;
488                         updateentry.Mask = VLUPDATE_RWID;
489                         updateentry.spares3 = entry.volumeId[RWVOL];
490                         printf("\tVolume %s %d (not in rw id hash)\n",
491                                entry.name, entry.volumeId[RWVOL]);
492                         code =
493                             ubik_VL_UpdateEntryByName(cstruct, 0,
494                                       entry.name, &updateentry, 0);
495                         if (code) {
496                             printf("\tFailed to update volume %s (err=%d)\n",
497                                    entry.name, code);
498                             x++;
499                         }
500                         x++;
501                     }
502                     if (entry.volumeId[BACKVOL]) {
503                         code =
504                             ubik_VL_GetEntryByID(cstruct, 0,
505                                       entry.volumeId[BACKVOL], BACKVOL,
506                                       &tentry);
507                         if (code == VL_NOENT) {
508                             num1++;
509                             updateentry.Mask = VLUPDATE_BACKUPID;
510                             updateentry.BackupId = entry.volumeId[BACKVOL];
511                             printf("\tVolume %s %d (not in backup id hash)\n",
512                                    entry.name, entry.volumeId[BACKVOL]);
513                             code =
514                                 ubik_VL_UpdateEntry(cstruct, 0,
515                                           entry.volumeId[RWVOL], -1,
516                                           &updateentry, 0);
517                             if (code) {
518                                 printf
519                                     ("\tFailed to update volume %s (err=%d)\n",
520                                      entry.name, code);
521                                 x++;
522                             }
523                         }
524                     }
525                     if (entry.volumeId[ROVOL]) {
526                         code =
527                             ubik_VL_GetEntryByID(cstruct, 0,
528                                       entry.volumeId[ROVOL], ROVOL, &tentry);
529                         if (code == VL_NOENT) {
530                             num1++;
531                             updateentry.Mask = VLUPDATE_READONLYID;
532                             updateentry.ReadOnlyId = entry.volumeId[ROVOL];
533                             printf("\tVolume %s %d (not in RO id hash)\n",
534                                    entry.name, entry.volumeId[ROVOL]);
535                             code =
536                                 ubik_VL_UpdateEntry(cstruct, 0,
537                                           entry.volumeId[RWVOL], -1,
538                                           &updateentry, 0);
539                             if (code) {
540                                 printf
541                                     ("\tFailed to update volume %s (err=%d)\n",
542                                      entry.name, code);
543                                 x++;
544                             }
545                         }
546                     }
547                 }
548                 printf
549                     ("\nTotal vldb entries found %d:\n\t%d entries didn't hash properly and are fixed except %d that need to be handled manually\n",
550                      num, num1, x);
551             } else if (!strcmp(oper, "la")) {
552                 int nentries = 0, i;
553                 bulkentries entries;
554                 struct vldbentry *entry;
555
556                 memset(&entries, 0, sizeof(entries));
557                 fill_listattributes_entry(&listbyattributes, argp, nargs);
558                 display_listattributes_entry(&listbyattributes, 0);
559                 code =
560                     ubik_VL_ListAttributes(cstruct, 0,
561                               &listbyattributes, &nentries, &entries);
562                 if (code) {
563                     printf("VL_ListAttributes returned code = %d\n", code);
564                     continue;
565                 }
566                 entry = (struct vldbentry *)entries.bulkentries_val;
567                 for (i = 0; i < nentries; i++, entry++)
568                     display_entry(entry, 0);
569                 if (entries.bulkentries_val)
570                     free(entries.bulkentries_val);
571             } else if (!strcmp(oper, "lan2")) {
572                 int nentries, i, si, nsi, t = 0;
573                 nbulkentries entries;
574                 struct nvldbentry *entry;
575                 char name[64];
576
577                 /* The volume name to search for (supports wildcarding) */
578                 if (nargs > 0) {
579                     strcpy(name, argp[0]);
580                     ++argp, --nargs;
581                 } else {
582                     strcpy(name, "");
583                 }
584
585                 fill_listattributes_entry(&listbyattributes, argp, nargs);
586                 display_listattributes_entry(&listbyattributes, 0);
587                 printf("Wildcard VolName: '%s'\n", name);
588
589                 for (si = 0; si != -1; si = nsi) {
590                     nentries = 0;
591                     memset(&entries, 0, sizeof(entries));
592                     code =
593                         ubik_VL_ListAttributesN2(cstruct, 0,
594                                   &listbyattributes, name, si, &nentries,
595                                   &entries, &nsi);
596                     if (code) {
597                         printf("VL_ListAttributesN2 returned code = %d\n",
598                                code);
599                         break;
600                     }
601
602                     t += nentries;
603                     entry = (struct nvldbentry *)entries.nbulkentries_val;
604                     for (i = 0; i < nentries; i++, entry++)
605                         display_entryN(entry, 0);
606                     if (entries.nbulkentries_val)
607                         free(entries.nbulkentries_val);
608                 }
609                 printf("--- %d volumes ---\n", t);
610             } else if (!strcmp(oper, "ln")) {
611                 int netries;
612                 vldb_list linkedvldbs;
613                 vldblist vllist, vllist1;
614
615                 fill_listattributes_entry(&listbyattributes, argp, nargs);
616                 display_listattributes_entry(&listbyattributes, 0);
617                 memset(&linkedvldbs, 0, sizeof(vldb_list));
618                 code =
619                     ubik_VL_LinkedList(cstruct, 0, &listbyattributes,
620                               &netries, &linkedvldbs);
621                 if (code) {
622                     printf("VL_LinkedList returned code = %d\n", code);
623                     continue;
624                 }
625                 printf("Found %d entr%s\n", netries,
626                        (netries == 1 ? "y" : "ies"));
627                 for (vllist = linkedvldbs.node; vllist; vllist = vllist1) {
628                     vllist1 = vllist->next_vldb;
629                     display_entry((struct vldbentry *) &vllist->VldbEntry, 0);
630                     free(vllist);
631                 }
632             } else if (!strcmp(oper, "lnn")) {
633                 int netries;
634                 nvldb_list linkedvldbs;
635                 nvldblist vllist, vllist1;
636
637                 fill_listattributes_entry(&listbyattributes, argp, nargs);
638                 display_listattributes_entry(&listbyattributes, 0);
639                 memset(&linkedvldbs, 0, sizeof(vldb_list));
640                 code =
641                     ubik_VL_LinkedListN(cstruct, 0, &listbyattributes,
642                               &netries, &linkedvldbs);
643                 if (code) {
644                     printf("VL_LinkedList returned code = %d\n", code);
645                     continue;
646                 }
647                 printf("Found %d entr%s\n", netries,
648                        (netries == 1 ? "y" : "ies"));
649                 for (vllist = linkedvldbs.node; vllist; vllist = vllist1) {
650                     vllist1 = vllist->next_vldb;
651                     display_entry((struct vldbentry *)&vllist->VldbEntry, 0);
652                     free(vllist);
653                 }
654             } else if (!strcmp(oper, "di")) {
655                 sscanf(&(*argp)[0], "%d", &id);
656                 ++argp, --nargs;
657                 sscanf(&(*argp)[0], "%d", &voltype);
658                 code =
659                     ubik_VL_GetEntryByID(cstruct, 0, id, voltype,
660                               &entry);
661                 display_entry(&entry, code);
662                 printf("return code is %d.\n", code);
663             } else if (!strcmp(oper, "rmnh")) {
664                 sscanf(&(*argp)[0], "%d", &id);
665                 ++argp, --nargs;
666                 sscanf(&(*argp)[0], "%d", &voltype);
667                 code =
668                     ubik_VL_GetEntryByID(cstruct, 0, id, voltype,
669                               &entry);
670                 display_entry(&entry, code);
671                 memset(&updateentry, 0, sizeof(updateentry));
672                 updateentry.Mask = VLUPDATE_VOLNAMEHASH;
673                 printf("\tRehashing namehash table for %s (%d)\n", entry.name,
674                        entry.volumeId[RWVOL]);
675                 code =
676                     ubik_VL_UpdateEntry(cstruct, 0,
677                               entry.volumeId[RWVOL], -1, &updateentry, 0);
678                 if (code) {
679                     printf("\tFailed to update volume %s (err=%d)\n",
680                            entry.name, code);
681                 }
682                 printf("return code is %d.\n", code);
683             } else if (!strcmp(oper, "undelete")) {
684                 afs_int32 index, count, next_index;
685
686                 memset(&updateentry, 0, sizeof(updateentry));
687                 sscanf(&(*argp)[0], "%d", &id);
688                 ++argp, --nargs;
689                 sscanf(&(*argp)[0], "%d", &voltype);
690                 if (voltype < 0 && voltype > 2) {
691                     printf("Illegal voltype; must be 0, 1 or 2\n");
692                     continue;
693                 }
694                 printf("Searching vldb for volume %d...\n", id);
695                 for (index = 0; 1; index = next_index) {
696                     memset(&entry, 0, sizeof(entry));
697                     code =
698                         ubik_VL_ListEntry(cstruct, 0, index, &count,
699                                   &next_index, &entry);
700                     if (code) {
701                         printf("VL_ListEntry returned code = %d\n", code);
702                         break;
703                     }
704                     if (!next_index)
705                         break;
706                     if (entry.volumeId[voltype] == id) {
707                         printf("\nThe current contents of the vldb for %d:\n",
708                                id);
709                         display_entry(&entry, 0);
710
711                         if (entry.flags & VLDELETED) {
712                             updateentry.Mask = VLUPDATE_FLAGS;
713                             updateentry.flags = entry.flags;
714                             updateentry.flags &= ~VLDELETED;
715                             printf
716                                 ("\tUndeleting vldb entry for vol %d (%s)\n",
717                                  id, entry.name);
718                             code =
719                                 ubik_VL_UpdateEntry(cstruct, 0, id, -1,
720                                           &updateentry, 0);
721                             if (code) {
722                                 printf
723                                     ("\tFailed to update volume %s (err=%d)\n",
724                                      entry.name, code);
725                             }
726                         } else {
727                             printf("Entry not deleted; ignored\n");
728                         }
729                         break;
730                     }
731                 }
732             } else if (!strcmp(oper, "dn")) {
733                 vname = &argp[0][0];
734                 code =
735                     ubik_VL_GetEntryByNameO(cstruct, 0, vname, &entry);
736                 display_entry(&entry, code);
737                 printf("return code is %d.\n", code);
738             } else if (!strcmp(oper, "nv")) {
739                 unsigned int newvolid;
740                 sscanf(&(*argp)[0], "%d", &id);
741                 code =
742                     ubik_VL_GetNewVolumeId(cstruct, 0, id, &newvolid);
743                 if (!code)
744                     printf("Current Max volid is (in hex):0x%x\n", newvolid);
745                 printf("return code is %d\n", code);
746             } else if (!strcmp(oper, "gs")) {
747                 vldstats stats;
748                 vital_vlheader vital_header;
749                 code =
750                     ubik_VL_GetStats(cstruct, 0, &stats, &vital_header);
751                 if (!code)
752                     dump_stats(&stats, &vital_header);
753                 printf("return code is %d.\n", code);
754             } else if (!strcmp(oper, "ga")) {
755                 int nentries, i;
756                 afs_uint32 *addrp;
757                 bulkaddrs addrs;
758                 struct VLCallBack vlcb;
759
760                 addrs.bulkaddrs_val = 0;
761                 addrs.bulkaddrs_len = 0;
762                 code = ubik_VL_GetAddrs(cstruct, 0, 0 /*Handle */ ,
763                                  0 /*spare2 */ , &vlcb,
764                                  &nentries, &addrs);
765                 if (code) {
766                     printf("VL_GetAddrs returned code = %d\n", code);
767                     continue;
768                 }
769                 addrp = addrs.bulkaddrs_val;
770                 for (i = 0; i < nentries; i++, addrp++) {
771                     if ((*addrp & 0xff000000) == 0xff000000)
772                         printf("[0x%x %u] (special multi-homed entry)\n",
773                                *addrp, *addrp);
774                     else
775                         printf("[0x%x %u] %s\n", *addrp, *addrp,
776                                hostutil_GetNameByINet(ntohl(*addrp)));
777                 }
778                 free(addrs.bulkaddrs_val);
779             } else if (!strcmp(oper, "gau")) {
780                 int nentries, i, j;
781                 afs_uint32 *addrp;
782                 bulkaddrs addrs;
783                 struct VLCallBack vlcb;
784
785                 addrs.bulkaddrs_val = 0;
786                 addrs.bulkaddrs_len = 0;
787                 code = ubik_VL_GetAddrs(cstruct, 0, 0 /*Handle */ ,
788                                  0 /*spare2 */ , &vlcb,
789                                  &nentries, &addrs);
790                 if (code) {
791                     printf("VL_GetAddrs returned code = %d\n", code);
792                     continue;
793                 }
794                 addrp = addrs.bulkaddrs_val;
795                 for (i = 0; i < nentries; i++, addrp++) {
796                     if ((*addrp & 0xff000000) == 0xff000000) {
797                         int mhnentries, unique;
798                         struct in_addr hostAddr;
799                         afs_uint32 *mhaddrp;
800                         bulkaddrs mhaddrs;
801                         ListAddrByAttributes attrs;
802                         afsUUID uuid;
803
804                         printf("[0x%x %u] (special multi-homed entry)\n",
805                                *addrp, *addrp);
806                         memset(&attrs, 0, sizeof(attrs));
807                         attrs.Mask = VLADDR_INDEX;
808                         mhaddrs.bulkaddrs_val = 0;
809                         mhaddrs.bulkaddrs_len = 0;
810                         attrs.index = *addrp & 0x00ffffff;
811
812                         code =
813                             ubik_VL_GetAddrsU(cstruct, 0, &attrs, &uuid,
814                                       &unique, &mhnentries, &mhaddrs);
815                         if (code) {
816                             printf("VL_GetAddrsU returned code = %d\n", code);
817                             continue;
818                         }
819                         printf
820                             ("   [%d]: uuid[%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x]\n   addrunique=%d, ip address(es):\n",
821                              attrs.index, uuid.time_low, uuid.time_mid,
822                              uuid.time_hi_and_version,
823                              uuid.clock_seq_hi_and_reserved,
824                              uuid.clock_seq_low, uuid.node[0], uuid.node[1],
825                              uuid.node[2], uuid.node[3], uuid.node[4],
826                              uuid.node[5], unique);
827                         mhaddrp = mhaddrs.bulkaddrs_val;
828                         for (j = 0; j < mhnentries; j++) {
829                             mhaddrp[j] = ntohl(mhaddrp[j]);
830                             hostAddr.s_addr = mhaddrp[j];
831                             printf("\t%s (%s)\n", inet_ntoa(hostAddr),
832                                    hostutil_GetNameByINet(mhaddrp[j]));
833                         }
834                         if (mhaddrs.bulkaddrs_val)
835                             free(mhaddrs.bulkaddrs_val);
836                     } else {
837                         printf("[0x%x %u] %s\n", *addrp, *addrp,
838                                hostutil_GetNameByINet(ntohl(*addrp)));
839                     }
840                 }
841                 free(addrs.bulkaddrs_val);
842             } else if (!strcmp(oper, "mhc")) {
843                 afs_uint32 serveraddrs[MAXSERVERID + 1][VL_MAXIPADDRS_PERMH];
844                 afs_int32 serveraddrtype[MAXSERVERID + 1];
845                 int nentries1, nentries2, i, j, x, y, unique, found;
846                 afs_uint32 *addrp1, *addrp2;
847                 bulkaddrs addrs1, addrs2;
848                 struct VLCallBack vlcb;
849                 ListAddrByAttributes attrs;
850                 afsUUID uuid;
851                 afs_int32 base, index;
852
853                 for (i = 0; i < MAXSERVERID + 1; i++) {
854                     serveraddrtype[i] = 0;
855                     for (j = 0; j < VL_MAXIPADDRS_PERMH; j++)
856                         serveraddrs[i][j] = 0;
857                 }
858
859                 /* Collect a list of all registered IP addresses */
860                 addrs1.bulkaddrs_val = 0;
861                 addrs1.bulkaddrs_len = 0;
862                 code =
863                     ubik_VL_GetAddrs(cstruct, 0, 0, 0, &vlcb,
864                               &nentries1, &addrs1);
865                 if (code) {
866                     printf("VL_GetAddrs returned code = %d\n", code);
867                     continue;
868                 }
869                 addrp1 = addrs1.bulkaddrs_val;
870                 for (i = 0; i < nentries1; i++, addrp1++) {
871                     if ((*addrp1 & 0xff000000) != 0xff000000) {
872                         serveraddrs[i][0] = ntohl(*addrp1);
873                         serveraddrtype[i] = 1;
874                     } else {
875                         /* It's multihomed. Get all of its addresses */
876                         serveraddrtype[i] = 2;
877                         base = (*addrp1 >> 16) & 0xff;
878                         index = *addrp1 & 0xffff;
879
880                         addrs2.bulkaddrs_val = 0;
881                         addrs2.bulkaddrs_len = 0;
882                         memset(&attrs, 0, sizeof(attrs));
883                         attrs.Mask = VLADDR_INDEX;
884                         attrs.index = (base * VL_MHSRV_PERBLK) + index;
885                         code =
886                             ubik_VL_GetAddrsU(cstruct, 0, &attrs, &uuid,
887                                       &unique, &nentries2, &addrs2);
888                         if (code) {
889                             printf("VL_GetAddrsU returned code = %d\n", code);
890                             break;
891                         }
892
893                         addrp2 = addrs2.bulkaddrs_val;
894                         for (j = 0; j < nentries2; j++) {
895                             serveraddrs[i][j] = ntohl(addrp2[j]);
896                         }
897                         free(addrs2.bulkaddrs_val);
898                     }
899
900                     if (nargs) {
901                         if (serveraddrtype[i] == 1) {
902                             printf("%u\n", serveraddrs[i][0]);
903                         } else {
904                             printf("[");
905                             for (j = 0; j < VL_MAXIPADDRS_PERMH; j++)
906                                 if (serveraddrs[i][j])
907                                     printf(" %u", serveraddrs[i][j]);
908                             printf(" ]\n");
909                         }
910                     }
911                 }
912                 free(addrs1.bulkaddrs_val);
913
914                 /* Look for any duplicates */
915                 for (i = 0; i < MAXSERVERID + 1; i++) {
916                     if (!serveraddrtype[i])
917                         continue;
918                     for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
919                         if (!serveraddrs[i][j])
920                             continue;
921
922                         found = 0;
923                         for (x = i + 1; x < MAXSERVERID + 1; x++) {
924                             if (!serveraddrtype[x])
925                                 continue;
926                             for (y = 0; y < VL_MAXIPADDRS_PERMH; y++) {
927                                 if (!serveraddrs[x][y])
928                                     continue;
929                                 if (serveraddrs[i][j] == serveraddrs[x][y]) {
930                                     serveraddrs[x][y] = 0;
931                                     found++;
932                                 }
933                             }
934                         }
935                         if (found) {
936                             printf
937                                 ("Found %d entries of IP address %u (0x%x)\n",
938                                  found + 1, serveraddrs[i][j],
939                                  serveraddrs[i][j]);
940                         }
941                     }
942                 }
943
944                /*----------------------------------------*/
945
946             } else if (!strcmp(oper, "regaddr")) {
947                 int i;
948                 afs_uint32 *addrp, tad;
949                 bulkaddrs addrs;
950                 afsUUID uuid;
951
952                 memset(&uuid, 0, sizeof(uuid));
953                 sscanf(&(*argp)[0], "%d", &i);
954                 ++argp, --nargs;
955                 memcpy(uuid.node, &i, sizeof(i));
956
957                 if (nargs < 0 || nargs > 16) {
958                     printf("Illegal # entries = %d\n", nargs);
959                     continue;
960                 }
961                 addrp = malloc(20 * 4);
962                 addrs.bulkaddrs_val = addrp;
963                 addrs.bulkaddrs_len = nargs;
964                 while (nargs > 0) {
965                     sscanf(&(*argp)[0], "%d", &tad);
966                     *addrp++ = tad;
967                     ++argp, --nargs;
968                 }
969                 code =
970                     ubik_VL_RegisterAddrs(cstruct, 0, &uuid,
971                               0 /*spare */ , &addrs);
972                 if (code) {
973                     printf("VL_RegisterAddrs returned code = %d\n", code);
974                     continue;
975                 }
976             } else if (!strcmp(oper, "ca")) {
977                 struct hostent *h1, *h2;
978                 afs_uint32 a1, a2;
979
980                 printf("changing %s", *argp);
981                 h1 = hostutil_GetHostByName(&(*argp)[0]);
982                 if (!h1) {
983                     printf("cmdebug: can't resolve address for host %s",
984                            *argp);
985                     continue;
986                 }
987                 memcpy(&a1, (afs_int32 *) h1->h_addr, sizeof(afs_uint32));
988
989                 ++argp, --nargs;
990                 printf(" to %s\n", *argp);
991                 h2 = hostutil_GetHostByName(&(*argp)[0]);
992                 if (!h2) {
993                     printf("cmdebug: can't resolve address for host %s",
994                            *argp);
995                     continue;
996                 }
997                 memcpy(&a2, (afs_int32 *) h2->h_addr, sizeof(afs_uint32));
998
999                 printf("changing 0x%x to 0x%x\n", ntohl(a1), ntohl(a2));
1000                 code =
1001                     ubik_VL_ChangeAddr(cstruct, 0, ntohl(a1),
1002                               ntohl(a2));
1003                 if (code) {
1004                     printf("VL_ChangeAddr returned code = %d\n", code);
1005                     continue;
1006                 }
1007             } else if (!strcmp(oper, "caid")) {
1008                 afs_uint32 a1, a2;
1009
1010                 sscanf(&(*argp)[0], "%d", &a1);
1011                 printf("changing %d (0x%x)", a1, a1);
1012                 ++argp, --nargs;
1013                 sscanf(&(*argp)[0], "%d", &a2);
1014                 printf(" to %d (0x%x)\n", a2, a2);
1015                 code = ubik_VL_ChangeAddr(cstruct, 0, a1, a2);
1016                 if (code) {
1017                     printf("VL_ChangeAddr returned code = %d\n", code);
1018                     continue;
1019                 }
1020             } else if ((!strcmp(oper, "?")) || !strcmp(oper, "h") || !strcmp(oper, "help"))
1021                 print_usage();
1022             else if ((!strcmp(oper, "q")) || !strcmp(oper, "quit"))
1023                 exit(0);
1024             else {
1025                 printf("Unknown oper (%s)!\n", oper);
1026                 print_usage();
1027             }
1028         }
1029     }
1030 }
1031
1032
1033 #include "AFS_component_version_number.c"
1034
1035 int
1036 main(int argc, char **argv)
1037 {
1038     struct cmd_syndesc *ts;
1039     afs_int32 code;
1040
1041     strcpy(confdir, AFSDIR_CLIENT_ETC_DIRPATH);
1042     ts = cmd_CreateSyntax("initcmd", handleit, NULL, 0, "initialize the program");
1043     cmd_AddParm(ts, "-cellpath", CMD_LIST, CMD_OPTIONAL,
1044                 "Cell configuration directory");
1045     cmd_AddParm(ts, "-server", CMD_LIST, CMD_OPTIONAL,
1046                 "Use the cell config in /usr/afs/etc (default /usr/vice/etc)");
1047     cmd_AddParm(ts, "-noauth", CMD_FLAG, CMD_OPTIONAL,
1048                 "Run it without authentication");
1049     cmd_AddParm(ts, "-host", CMD_LIST, CMD_OPTIONAL,
1050                 "vldb server to talk to");
1051     cmd_AddParm(ts, "-cell", CMD_LIST, CMD_OPTIONAL,
1052                 "cellname '-host' belongs to (required for auth conns)");
1053     cmd_AddParm(ts, "-getstats", CMD_FLAG, CMD_OPTIONAL,
1054                 "print vldb statistics (non interactive)");
1055     cmd_AddParm(ts, "-probe", CMD_FLAG, CMD_OPTIONAL,
1056                 "probe vldb servers, use with -host to probe only one. (non interactive)");
1057     code = cmd_Dispatch(argc, argv);
1058     exit(code);
1059 }
1060
1061
1062 void
1063 fill_entry(struct vldbentry *entry, char **argp, int nargs)
1064 {
1065     char *name;
1066     int i;
1067
1068     name = &argp[0][0];
1069     ++argp, --nargs;
1070     sscanf(&(*argp)[0], "%d", &entry->spares3);
1071     ++argp, --nargs;
1072     sscanf(&(*argp)[0], "%d", &entry->nServers);
1073     strcpy(entry->name, name);
1074     for (i = 0; i < entry->nServers; i++) {
1075         ++argp, --nargs;
1076         sscanf(&(*argp)[0], "%u", &entry->serverNumber[i]);
1077     }
1078     for (i = 0; i < entry->nServers; i++) {
1079         ++argp, --nargs;
1080         sscanf(&(*argp)[0], "%d", &entry->serverPartition[i]);
1081     }
1082     for (i = 0; i < entry->nServers; i++) {
1083         ++argp, --nargs;
1084         sscanf(&(*argp)[0], "%d", &entry->serverFlags[i]);
1085     }
1086     for (i = 0; i < MAXTYPES; i++) {
1087         ++argp, --nargs;
1088         sscanf(&(*argp)[0], "%u", &entry->volumeId[i]);
1089     }
1090     ++argp, --nargs;
1091     sscanf(&(*argp)[0], "%d", &entry->flags);
1092     ++argp, --nargs;
1093     sscanf(&(*argp)[0], "%u", &entry->cloneId);
1094 }
1095
1096 void
1097 fill_update_entry(struct VldbUpdateEntry *entry, char **argp, int nargs)
1098 {
1099     int i, Mask;
1100     char *name;
1101
1102     entry->Mask = 0;
1103     name = &argp[0][0];
1104     if (strcmp(name, "null")) {
1105         strcpy(entry->name, name);
1106         entry->Mask |= VLUPDATE_VOLUMENAME;
1107     }
1108     ++argp, --nargs;
1109     sscanf(&(*argp)[0], "%d", &entry->flags);
1110     if (entry->flags != -1)
1111         entry->Mask |= VLUPDATE_FLAGS;
1112     ++argp, --nargs;
1113     sscanf(&(*argp)[0], "%u", &entry->cloneId);
1114     if (entry->flags != -1)
1115         entry->Mask |= VLUPDATE_CLONEID;
1116     ++argp, --nargs;
1117     sscanf(&(*argp)[0], "%u", &entry->ReadOnlyId);
1118     if (entry->ReadOnlyId != -1)
1119         entry->Mask |= VLUPDATE_READONLYID;
1120     ++argp, --nargs;
1121     sscanf(&(*argp)[0], "%u", &entry->BackupId);
1122     if (entry->BackupId != -1)
1123         entry->Mask |= VLUPDATE_BACKUPID;
1124     ++argp, --nargs;
1125     sscanf(&(*argp)[0], "%d", &entry->nModifiedRepsites);
1126     if (entry->nModifiedRepsites != -1)
1127         entry->Mask |= VLUPDATE_REPSITES;
1128     for (i = 0; i < entry->nModifiedRepsites; i++) {
1129         ++argp, --nargs;
1130         sscanf(&(*argp)[0], "%x", &Mask);
1131         ++argp, --nargs;
1132         sscanf(&(*argp)[0], "%u", &entry->RepsitesTargetServer[i]);
1133         ++argp, --nargs;
1134         sscanf(&(*argp)[0], "%d", &entry->RepsitesTargetPart[i]);
1135         if (Mask & VLUPDATE_REPS_DELETE)
1136             entry->RepsitesMask[i] |= VLUPDATE_REPS_DELETE;
1137         if (Mask & VLUPDATE_REPS_MODSERV) {
1138             ++argp, --nargs;
1139             sscanf(&(*argp)[0], "%u", &entry->RepsitesNewServer[i]);
1140             entry->RepsitesMask[i] |= VLUPDATE_REPS_MODSERV;
1141         } else if (Mask & VLUPDATE_REPS_MODPART) {
1142             ++argp, --nargs;
1143             sscanf(&(*argp)[0], "%d", &entry->RepsitesNewPart[i]);
1144             entry->RepsitesMask[i] |= VLUPDATE_REPS_MODPART;
1145         } else if (Mask & VLUPDATE_REPS_MODFLAG) {
1146             ++argp, --nargs;
1147             sscanf(&(*argp)[0], "%d", &entry->RepsitesNewFlags[i]);
1148             entry->RepsitesMask[i] |= VLUPDATE_REPS_MODFLAG;
1149         } else if (Mask & VLUPDATE_REPS_ADD) {
1150             ++argp, --nargs;
1151             sscanf(&(*argp)[0], "%u", &entry->RepsitesNewServer[i]);
1152             ++argp, --nargs;
1153             sscanf(&(*argp)[0], "%d", &entry->RepsitesNewPart[i]);
1154             ++argp, --nargs;
1155             sscanf(&(*argp)[0], "%d", &entry->RepsitesNewFlags[i]);
1156             entry->RepsitesMask[i] |= VLUPDATE_REPS_ADD;
1157         }
1158     }
1159 }
1160
1161 void
1162 fill_listattributes_entry(struct VldbListByAttributes *entry, char **argp,
1163                           int nargs)
1164 {
1165     entry->Mask = 0;
1166
1167     if (nargs <= 0)
1168         return;
1169     entry->server = ntohl(GetServer(argp[0]));
1170     sscanf(&(*argp)[0], "%d", &entry->server);
1171     if (entry->server != 0)
1172         entry->Mask |= VLLIST_SERVER;
1173     ++argp, --nargs;
1174
1175     if (nargs <= 0)
1176         return;
1177     sscanf(&(*argp)[0], "%d", &entry->partition);
1178     if (entry->partition != -1)
1179         entry->Mask |= VLLIST_PARTITION;
1180     ++argp, --nargs;
1181
1182     if (nargs <= 0)
1183         return;
1184     sscanf(&(*argp)[0], "%d", &entry->volumeid);
1185     if (entry->volumeid != -1)
1186         entry->Mask |= VLLIST_VOLUMEID;
1187     ++argp, --nargs;
1188
1189     if (nargs <= 0)
1190         return;
1191     sscanf(&(*argp)[0], "%d", &entry->flag);
1192     if (entry->flag != -1)
1193         entry->Mask |= VLLIST_FLAG;
1194 }
1195
1196 void
1197 display_listattributes_entry(struct VldbListByAttributes *entry, int error)
1198 {
1199     if (error)
1200         return;
1201     printf("\nList entry values (Mask=%x)\n", entry->Mask);
1202     if (entry->Mask & VLLIST_SERVER)
1203         printf("\tServer: %d.%d.%d.%d\n", (entry->server >> 24) & 0xff,
1204                (entry->server >> 16) & 0xff, (entry->server >> 8) & 0xff,
1205                (entry->server) & 0xff);
1206     if (entry->Mask & VLLIST_PARTITION)
1207         printf("\tPartition: %d\n", entry->partition);
1208     if (entry->Mask & VLLIST_VOLUMEID)
1209         printf("\tVolumeId: %u\n", entry->volumeid);
1210     if (entry->Mask & VLLIST_FLAG)
1211         printf("\tFlag: %x\n", entry->flag);
1212 }
1213
1214
1215 #define volumetype_string(type) (type == RWVOL? "read/write":type == ROVOL? "readonly":type == BACKVOL? "backup":"unknown")
1216
1217 void
1218 display_entry(struct vldbentry *entry, int error)
1219 {
1220     int i;
1221
1222     if (error)
1223         return;
1224     printf("\nEntry for volume name: %s, volid=%u (flags=%X) are:\n",
1225            entry->name, entry->volumeId[RWVOL], entry->flags);
1226     printf("ParentID=%u, ReadOnlyID=%u, backupID=%u, CloneId=%u ",
1227            entry->volumeId[0], entry->volumeId[1], entry->volumeId[2],
1228            entry->cloneId);
1229     printf("nServers=%d\n", entry->nServers);
1230     printf("ServerNumber\tServerPart\tserverFlag\n");
1231     for (i = 0; i < entry->nServers; i++)
1232         printf("%12u\t%10d\t%10x\n", entry->serverNumber[i],
1233                entry->serverPartition[i], entry->serverFlags[i]);
1234 }
1235
1236 void
1237 display_entryN(struct nvldbentry *entry, int error)
1238 {
1239     int i, et, ei;
1240
1241     if (error)
1242         return;
1243     printf("\nEntry for volume name: %s, volid=%u (flags=%X) are:\n",
1244            entry->name, entry->volumeId[RWVOL], entry->flags);
1245     printf("ParentID=%u, ReadOnlyID=%u, backupID=%u, CloneId=%u ",
1246            entry->volumeId[0], entry->volumeId[1], entry->volumeId[2],
1247            entry->cloneId);
1248     printf("nServers=%d\n", entry->nServers);
1249     printf("ServerNumber\tServerPart\tserverFlag\n");
1250     ei = entry->matchindex & 0xffff;
1251     et = (entry->matchindex >> 16) & 0xffff;
1252     for (i = 0; i < entry->nServers; i++) {
1253         printf("%12u\t%10d\t%10x", entry->serverNumber[i],
1254                entry->serverPartition[i], entry->serverFlags[i]);
1255         if (i == ei) {
1256             printf(" <--- %s", (et == 4) ? "RW" : ((et == 8) ? "BK" : "RO"));
1257         }
1258         printf("\n");
1259     }
1260 }
1261
1262 void
1263 display_update_entry(struct VldbUpdateEntry *entry, int error)
1264 {
1265     int i;
1266
1267     if (error)
1268         return;
1269     printf("\nUpdate entry values (Mask=%x)\n", entry->Mask);
1270     if (entry->Mask & VLUPDATE_VOLUMENAME)
1271         printf("\tNew name: %s\n", entry->name);
1272     if (entry->Mask & VLUPDATE_FLAGS)
1273         printf("\tNew flags: %X\n", entry->flags);
1274     if (entry->Mask & VLUPDATE_CLONEID)
1275         printf("\tNew CloneId: %X\n", entry->cloneId);
1276     if (entry->Mask & VLUPDATE_READONLYID)
1277         printf("\tNew RO id: %d\n", entry->ReadOnlyId);
1278     if (entry->Mask & VLUPDATE_BACKUPID)
1279         printf("\tNew BACKUP id: %d\n", entry->BackupId);
1280     if (entry->Mask & VLUPDATE_REPSITES) {
1281         printf("\tRepsites info:\n");
1282         printf("\tFlag\tTServer\tTPart\tNServer\tNPart\tNFlag\n");
1283         for (i = 0; i < entry->nModifiedRepsites; i++) {
1284             printf("\t%4x\t%7u\t%5d", entry->RepsitesMask[i],
1285                    entry->RepsitesTargetServer[i],
1286                    entry->RepsitesTargetPart[i]);
1287             if ((entry->RepsitesMask[i] & VLUPDATE_REPS_ADD)
1288                 || (entry->RepsitesMask[i] & VLUPDATE_REPS_MODSERV))
1289                 printf("\t%7u", entry->RepsitesNewServer[i]);
1290             else
1291                 printf("\t-------");
1292             if ((entry->RepsitesMask[i] & VLUPDATE_REPS_ADD)
1293                 || (entry->RepsitesMask[i] & VLUPDATE_REPS_MODPART))
1294                 printf("\t%5d", entry->RepsitesNewPart[i]);
1295             else
1296                 printf("\t-----");
1297             if ((entry->RepsitesMask[i] & VLUPDATE_REPS_ADD)
1298                 || (entry->RepsitesMask[i] & VLUPDATE_REPS_MODFLAG))
1299                 printf("\t%5x\n", entry->RepsitesNewFlags[i]);
1300             else
1301                 printf("\t-----\n");
1302         }
1303     }
1304 }
1305
1306 void
1307 dump_stats(vldstats *stats, vital_vlheader *vital_header)
1308 {
1309     int i;
1310     char strg[30];
1311     time_t start_time = stats->start_time;
1312     struct tm tm;
1313
1314     strftime(strg, sizeof(strg), "%a %b %d %H:%M:%S %Y",
1315              localtime_r(&start_time, &tm));
1316     printf("Dynamic statistics stats (starting time: %s):\n", strg);
1317     printf("OpcodeName\t# Requests\t# Aborts\n");
1318     for (i = 0; i < VL_NUMBER_OPCODESX; i++)
1319         printf("%10s\t%10d\t%8d\n", opcode_names[i], stats->requests[i],
1320                stats->aborts[i]);
1321     printf("\nVldb header stats (version=%d)\n",
1322            ntohl(vital_header->vldbversion));
1323     printf("headersize=%d, allocs=%d, frees=%d, MaxVolid=%X\n",
1324            ntohl(vital_header->headersize), ntohl(vital_header->allocs),
1325            ntohl(vital_header->frees), ntohl(vital_header->MaxVolumeId));
1326     for (i = 0; i < MAXTYPES; i++)
1327         printf("total %s entries=%d\n", volumetype_string(i),
1328                ntohl(vital_header->totalEntries[i]));
1329 }
1330
1331 void
1332 GetArgs(char *line, char **args, int *nargs)
1333 {
1334     *nargs = 0;
1335     while (*line) {
1336         char *last = line;
1337         while (isspace(*line))
1338             line++;
1339         if (isspace(*last))
1340             *last = 0;
1341         if (!*line)
1342             break;
1343         *args++ = line, (*nargs)++;
1344         while (*line && !isspace(*line))
1345             line++;
1346     }
1347 }
1348
1349 void
1350 print_usage(void)
1351 {
1352     printf("Valid Commands:\n");
1353
1354     printf("   CreateEntry:\n");
1355     printf
1356         ("\tcr <vname> <vtype> <#S> <Saddr1>.<Saddrn> <Spart1>.<Spartn> <Sflag1>.<Sflagn> <Volid1-3> <flag>\n");
1357
1358     printf("   DeleteEntry:\n");
1359     printf("\trm <volid> <voltype>\n");
1360
1361     printf("   ReplaceEntry:\n");
1362     printf("\tre <volid> <voltype> <New vldb entry ala 'cr'>\n");
1363
1364     printf("   UpdateEntry:\n");
1365     printf
1366         ("\tup <volid> <voltype> <vname> <vtype> <#AddSer> [<Saddr1>.<Saddrn> <Spart1>.<Spartn> <Sflag1>.<Sflagn>] <Volid1-3> <flag>\n");
1367
1368     printf("   ListEntry:\n");
1369     printf("\tls\n");
1370
1371     printf("   Find duplicate entries of a volume\n");
1372     printf("\tldups\n");
1373
1374     printf("   For each vlentry, find it by name, RW id, BK id, and RO id\n");
1375     printf("\tcheckhash\n");
1376
1377     printf
1378         ("   UpdateEntry (update the volname, RW id, BK id, RO id hashes):\n");
1379     printf("\tfixhash\n");
1380
1381     printf("   ListAttributes:\n");
1382     printf("\tla [server] [partition] [volumeid] [flag]\n");
1383
1384     printf("   ListAttributesN2:\n");
1385     printf("\tlan2 [volname] [server] [partition] [volumeid] [flag]\n");
1386
1387     printf("   GetEntryByID:\n");
1388     printf("\tdi <volid> <voltype>\n");
1389
1390     printf("   UpdateEntry (refresh namehash table):\n");
1391     printf("\trmnh <volid> <voltype>\n");
1392
1393     printf("   GetEntryByName:\n");
1394     printf("\tdn <volname> <voltype>\n");
1395
1396     printf("   UpdateEntry (undelete a vol entry):\n");
1397     printf("\tundelete <volid> <voltype>\n");
1398 /*
1399  *  printf("  LinkedList\n");
1400  *  printf("\t:ln [server] [partition] [volumeid] [flag]\n");
1401  *
1402  *  printf("  LinkedListN\n");
1403  *  printf("\t:lnn [server] [partition] [volumeid] [flag]\n");
1404  */
1405     printf("   GetNewVoumeId:\n");
1406     printf("\tnv <bump-count>\n");
1407
1408     printf("   GetStats:\n");
1409     printf("\tgs\n");
1410
1411     printf("   ChangeAddr:\n");
1412     printf("\tca <oldmachname> <newmachname>\n");
1413
1414 /*
1415  *  printf("   ChangeAddr\n");
1416  *  printf("\t:caid <oldaddr> <newaddr>\n");
1417  */
1418     printf("   GetAddrs:\n");
1419     printf("\tga\n");
1420
1421     printf("   GetAddrsU:\n");
1422     printf("\tgau\n");
1423
1424     printf("   RegisterAddrs:\n");
1425     printf("\tregaddr uuidNumber <ip1 .. ipn>\n");
1426
1427     printf("\tmisc: q, quit, ?, h\n");
1428 }