Upgrade to tcpdump-4.0.0.
[dragonfly.git] / contrib / tcpdump / print-rx.c
1 /*
2  * Copyright: (c) 2000 United States Government as represented by the
3  *      Secretary of the Navy. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  *   1. Redistributions of source code must retain the above copyright
10  *      notice, this list of conditions and the following disclaimer.
11  *   2. Redistributions in binary form must reproduce the above copyright
12  *      notice, this list of conditions and the following disclaimer in
13  *      the documentation and/or other materials provided with the
14  *      distribution.
15  *   3. The names of the authors may not be used to endorse or promote
16  *      products derived from this software without specific prior
17  *      written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22  */
23 /*
24  * This code unmangles RX packets.  RX is the mutant form of RPC that AFS
25  * uses to communicate between clients and servers.
26  *
27  * In this code, I mainly concern myself with decoding the AFS calls, not
28  * with the guts of RX, per se.
29  *
30  * Bah.  If I never look at rx_packet.h again, it will be too soon.
31  *
32  * Ken Hornstein <kenh@cmf.nrl.navy.mil>
33  */
34
35 #ifndef lint
36 static const char rcsid[] _U_ =
37     "@(#) $Header: /tcpdump/master/tcpdump/print-rx.c,v 1.39.2.3 2008-07-01 07:45:09 guy Exp $";
38 #endif
39
40 #ifdef HAVE_CONFIG_H
41 #include "config.h"
42 #endif
43
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <tcpdump-stdinc.h>
48
49 #include "interface.h"
50 #include "addrtoname.h"
51 #include "extract.h"
52
53 #include "rx.h"
54
55 #include "ip.h"
56
57 static struct tok rx_types[] = {
58         { RX_PACKET_TYPE_DATA,          "data" },
59         { RX_PACKET_TYPE_ACK,           "ack" },
60         { RX_PACKET_TYPE_BUSY,          "busy" },
61         { RX_PACKET_TYPE_ABORT,         "abort" },
62         { RX_PACKET_TYPE_ACKALL,        "ackall" },
63         { RX_PACKET_TYPE_CHALLENGE,     "challenge" },
64         { RX_PACKET_TYPE_RESPONSE,      "response" },
65         { RX_PACKET_TYPE_DEBUG,         "debug" },
66         { RX_PACKET_TYPE_PARAMS,        "params" },
67         { RX_PACKET_TYPE_VERSION,       "version" },
68         { 0,                            NULL },
69 };
70
71 static struct double_tok {
72         int flag;               /* Rx flag */
73         int packetType;         /* Packet type */
74         const char *s;          /* Flag string */
75 } rx_flags[] = {
76         { RX_CLIENT_INITIATED,  0,                      "client-init" },
77         { RX_REQUEST_ACK,       0,                      "req-ack" },
78         { RX_LAST_PACKET,       0,                      "last-pckt" },
79         { RX_MORE_PACKETS,      0,                      "more-pckts" },
80         { RX_FREE_PACKET,       0,                      "free-pckt" },
81         { RX_SLOW_START_OK,     RX_PACKET_TYPE_ACK,     "slow-start" },
82         { RX_JUMBO_PACKET,      RX_PACKET_TYPE_DATA,    "jumbogram" }
83 };
84
85 static struct tok fs_req[] = {
86         { 130,          "fetch-data" },
87         { 131,          "fetch-acl" },
88         { 132,          "fetch-status" },
89         { 133,          "store-data" },
90         { 134,          "store-acl" },
91         { 135,          "store-status" },
92         { 136,          "remove-file" },
93         { 137,          "create-file" },
94         { 138,          "rename" },
95         { 139,          "symlink" },
96         { 140,          "link" },
97         { 141,          "makedir" },
98         { 142,          "rmdir" },
99         { 143,          "oldsetlock" },
100         { 144,          "oldextlock" },
101         { 145,          "oldrellock" },
102         { 146,          "get-stats" },
103         { 147,          "give-cbs" },
104         { 148,          "get-vlinfo" },
105         { 149,          "get-vlstats" },
106         { 150,          "set-vlstats" },
107         { 151,          "get-rootvl" },
108         { 152,          "check-token" },
109         { 153,          "get-time" },
110         { 154,          "nget-vlinfo" },
111         { 155,          "bulk-stat" },
112         { 156,          "setlock" },
113         { 157,          "extlock" },
114         { 158,          "rellock" },
115         { 159,          "xstat-ver" },
116         { 160,          "get-xstat" },
117         { 161,          "dfs-lookup" },
118         { 162,          "dfs-flushcps" },
119         { 163,          "dfs-symlink" },
120         { 220,          "residency" },
121         { 65536,        "inline-bulk-status" },
122         { 65537,        "fetch-data-64" },
123         { 65538,        "store-data-64" },
124         { 65539,        "give-up-all-cbs" },
125         { 65540,        "get-caps" },
126         { 65541,        "cb-rx-conn-addr" },
127         { 0,            NULL },
128 };
129
130 static struct tok cb_req[] = {
131         { 204,          "callback" },
132         { 205,          "initcb" },
133         { 206,          "probe" },
134         { 207,          "getlock" },
135         { 208,          "getce" },
136         { 209,          "xstatver" },
137         { 210,          "getxstat" },
138         { 211,          "initcb2" },
139         { 212,          "whoareyou" },
140         { 213,          "initcb3" },
141         { 214,          "probeuuid" },
142         { 215,          "getsrvprefs" },
143         { 216,          "getcellservdb" },
144         { 217,          "getlocalcell" },
145         { 218,          "getcacheconf" },
146         { 65536,        "getce64" },
147         { 65537,        "getcellbynum" },
148         { 65538,        "tellmeaboutyourself" },
149         { 0,            NULL },
150 };
151
152 static struct tok pt_req[] = {
153         { 500,          "new-user" },
154         { 501,          "where-is-it" },
155         { 502,          "dump-entry" },
156         { 503,          "add-to-group" },
157         { 504,          "name-to-id" },
158         { 505,          "id-to-name" },
159         { 506,          "delete" },
160         { 507,          "remove-from-group" },
161         { 508,          "get-cps" },
162         { 509,          "new-entry" },
163         { 510,          "list-max" },
164         { 511,          "set-max" },
165         { 512,          "list-entry" },
166         { 513,          "change-entry" },
167         { 514,          "list-elements" },
168         { 515,          "same-mbr-of" },
169         { 516,          "set-fld-sentry" },
170         { 517,          "list-owned" },
171         { 518,          "get-cps2" },
172         { 519,          "get-host-cps" },
173         { 520,          "update-entry" },
174         { 521,          "list-entries" },
175         { 530,          "list-super-groups" },
176         { 0,            NULL },
177 };
178
179 static struct tok vldb_req[] = {
180         { 501,          "create-entry" },
181         { 502,          "delete-entry" },
182         { 503,          "get-entry-by-id" },
183         { 504,          "get-entry-by-name" },
184         { 505,          "get-new-volume-id" },
185         { 506,          "replace-entry" },
186         { 507,          "update-entry" },
187         { 508,          "setlock" },
188         { 509,          "releaselock" },
189         { 510,          "list-entry" },
190         { 511,          "list-attrib" },
191         { 512,          "linked-list" },
192         { 513,          "get-stats" },
193         { 514,          "probe" },
194         { 515,          "get-addrs" },
195         { 516,          "change-addr" },
196         { 517,          "create-entry-n" },
197         { 518,          "get-entry-by-id-n" },
198         { 519,          "get-entry-by-name-n" },
199         { 520,          "replace-entry-n" },
200         { 521,          "list-entry-n" },
201         { 522,          "list-attrib-n" },
202         { 523,          "linked-list-n" },
203         { 524,          "update-entry-by-name" },
204         { 525,          "create-entry-u" },
205         { 526,          "get-entry-by-id-u" },
206         { 527,          "get-entry-by-name-u" },
207         { 528,          "replace-entry-u" },
208         { 529,          "list-entry-u" },
209         { 530,          "list-attrib-u" },
210         { 531,          "linked-list-u" },
211         { 532,          "regaddr" },
212         { 533,          "get-addrs-u" },
213         { 534,          "list-attrib-n2" },
214         { 0,            NULL },
215 };
216
217 static struct tok kauth_req[] = {
218         { 1,            "auth-old" },
219         { 21,           "authenticate" },
220         { 22,           "authenticate-v2" },
221         { 2,            "change-pw" },
222         { 3,            "get-ticket-old" },
223         { 23,           "get-ticket" },
224         { 4,            "set-pw" },
225         { 5,            "set-fields" },
226         { 6,            "create-user" },
227         { 7,            "delete-user" },
228         { 8,            "get-entry" },
229         { 9,            "list-entry" },
230         { 10,           "get-stats" },
231         { 11,           "debug" },
232         { 12,           "get-pw" },
233         { 13,           "get-random-key" },
234         { 14,           "unlock" },
235         { 15,           "lock-status" },
236         { 0,            NULL },
237 };
238
239 static struct tok vol_req[] = {
240         { 100,          "create-volume" },
241         { 101,          "delete-volume" },
242         { 102,          "restore" },
243         { 103,          "forward" },
244         { 104,          "end-trans" },
245         { 105,          "clone" },
246         { 106,          "set-flags" },
247         { 107,          "get-flags" },
248         { 108,          "trans-create" },
249         { 109,          "dump" },
250         { 110,          "get-nth-volume" },
251         { 111,          "set-forwarding" },
252         { 112,          "get-name" },
253         { 113,          "get-status" },
254         { 114,          "sig-restore" },
255         { 115,          "list-partitions" },
256         { 116,          "list-volumes" },
257         { 117,          "set-id-types" },
258         { 118,          "monitor" },
259         { 119,          "partition-info" },
260         { 120,          "reclone" },
261         { 121,          "list-one-volume" },
262         { 122,          "nuke" },
263         { 123,          "set-date" },
264         { 124,          "x-list-volumes" },
265         { 125,          "x-list-one-volume" },
266         { 126,          "set-info" },
267         { 127,          "x-list-partitions" },
268         { 128,          "forward-multiple" },
269         { 65536,        "convert-ro" },
270         { 65537,        "get-size" },
271         { 65538,        "dump-v2" },
272         { 0,            NULL },
273 };
274
275 static struct tok bos_req[] = {
276         { 80,           "create-bnode" },
277         { 81,           "delete-bnode" },
278         { 82,           "set-status" },
279         { 83,           "get-status" },
280         { 84,           "enumerate-instance" },
281         { 85,           "get-instance-info" },
282         { 86,           "get-instance-parm" },
283         { 87,           "add-superuser" },
284         { 88,           "delete-superuser" },
285         { 89,           "list-superusers" },
286         { 90,           "list-keys" },
287         { 91,           "add-key" },
288         { 92,           "delete-key" },
289         { 93,           "set-cell-name" },
290         { 94,           "get-cell-name" },
291         { 95,           "get-cell-host" },
292         { 96,           "add-cell-host" },
293         { 97,           "delete-cell-host" },
294         { 98,           "set-t-status" },
295         { 99,           "shutdown-all" },
296         { 100,          "restart-all" },
297         { 101,          "startup-all" },
298         { 102,          "set-noauth-flag" },
299         { 103,          "re-bozo" },
300         { 104,          "restart" },
301         { 105,          "start-bozo-install" },
302         { 106,          "uninstall" },
303         { 107,          "get-dates" },
304         { 108,          "exec" },
305         { 109,          "prune" },
306         { 110,          "set-restart-time" },
307         { 111,          "get-restart-time" },
308         { 112,          "start-bozo-log" },
309         { 113,          "wait-all" },
310         { 114,          "get-instance-strings" },
311         { 115,          "get-restricted" },
312         { 116,          "set-restricted" },
313         { 0,            NULL },
314 };
315
316 static struct tok ubik_req[] = {
317         { 10000,        "vote-beacon" },
318         { 10001,        "vote-debug-old" },
319         { 10002,        "vote-sdebug-old" },
320         { 10003,        "vote-getsyncsite" },
321         { 10004,        "vote-debug" },
322         { 10005,        "vote-sdebug" },
323         { 10006,        "vote-xdebug" },
324         { 10007,        "vote-xsdebug" },
325         { 20000,        "disk-begin" },
326         { 20001,        "disk-commit" },
327         { 20002,        "disk-lock" },
328         { 20003,        "disk-write" },
329         { 20004,        "disk-getversion" },
330         { 20005,        "disk-getfile" },
331         { 20006,        "disk-sendfile" },
332         { 20007,        "disk-abort" },
333         { 20008,        "disk-releaselocks" },
334         { 20009,        "disk-truncate" },
335         { 20010,        "disk-probe" },
336         { 20011,        "disk-writev" },
337         { 20012,        "disk-interfaceaddr" },
338         { 20013,        "disk-setversion" },
339         { 0,            NULL },
340 };
341
342 #define VOTE_LOW        10000
343 #define VOTE_HIGH       10007
344 #define DISK_LOW        20000
345 #define DISK_HIGH       20013
346
347 static struct tok cb_types[] = {
348         { 1,            "exclusive" },
349         { 2,            "shared" },
350         { 3,            "dropped" },
351         { 0,            NULL },
352 };
353
354 static struct tok ubik_lock_types[] = {
355         { 1,            "read" },
356         { 2,            "write" },
357         { 3,            "wait" },
358         { 0,            NULL },
359 };
360
361 static const char *voltype[] = { "read-write", "read-only", "backup" };
362
363 static struct tok afs_fs_errors[] = {
364         { 101,          "salvage volume" },
365         { 102,          "no such vnode" },
366         { 103,          "no such volume" },
367         { 104,          "volume exist" },
368         { 105,          "no service" },
369         { 106,          "volume offline" },
370         { 107,          "voline online" },
371         { 108,          "diskfull" },
372         { 109,          "diskquota exceeded" },
373         { 110,          "volume busy" },
374         { 111,          "volume moved" },
375         { 112,          "AFS IO error" },
376         { -100,         "restarting fileserver" },
377         { 0,            NULL }
378 };
379
380 /*
381  * Reasons for acknowledging a packet
382  */
383
384 static struct tok rx_ack_reasons[] = {
385         { 1,            "ack requested" },
386         { 2,            "duplicate packet" },
387         { 3,            "out of sequence" },
388         { 4,            "exceeds window" },
389         { 5,            "no buffer space" },
390         { 6,            "ping" },
391         { 7,            "ping response" },
392         { 8,            "delay" },
393         { 9,            "idle" },
394         { 0,            NULL },
395 };
396
397 /*
398  * Cache entries we keep around so we can figure out the RX opcode
399  * numbers for replies.  This allows us to make sense of RX reply packets.
400  */
401
402 struct rx_cache_entry {
403         u_int32_t       callnum;        /* Call number (net order) */
404         struct in_addr  client;         /* client IP address (net order) */
405         struct in_addr  server;         /* server IP address (net order) */
406         int             dport;          /* server port (host order) */
407         u_short         serviceId;      /* Service identifier (net order) */
408         u_int32_t       opcode;         /* RX opcode (host order) */
409 };
410
411 #define RX_CACHE_SIZE   64
412
413 static struct rx_cache_entry    rx_cache[RX_CACHE_SIZE];
414
415 static int      rx_cache_next = 0;
416 static int      rx_cache_hint = 0;
417 static void     rx_cache_insert(const u_char *, const struct ip *, int);
418 static int      rx_cache_find(const struct rx_header *, const struct ip *,
419                               int, int32_t *);
420
421 static void fs_print(const u_char *, int);
422 static void fs_reply_print(const u_char *, int, int32_t);
423 static void acl_print(u_char *, int, u_char *);
424 static void cb_print(const u_char *, int);
425 static void cb_reply_print(const u_char *, int, int32_t);
426 static void prot_print(const u_char *, int);
427 static void prot_reply_print(const u_char *, int, int32_t);
428 static void vldb_print(const u_char *, int);
429 static void vldb_reply_print(const u_char *, int, int32_t);
430 static void kauth_print(const u_char *, int);
431 static void kauth_reply_print(const u_char *, int, int32_t);
432 static void vol_print(const u_char *, int);
433 static void vol_reply_print(const u_char *, int, int32_t);
434 static void bos_print(const u_char *, int);
435 static void bos_reply_print(const u_char *, int, int32_t);
436 static void ubik_print(const u_char *);
437 static void ubik_reply_print(const u_char *, int, int32_t);
438
439 static void rx_ack_print(const u_char *, int);
440
441 static int is_ubik(u_int32_t);
442
443 /*
444  * Handle the rx-level packet.  See if we know what port it's going to so
445  * we can peek at the afs call inside
446  */
447
448 void
449 rx_print(register const u_char *bp, int length, int sport, int dport,
450          u_char *bp2)
451 {
452         register struct rx_header *rxh;
453         int i;
454         int32_t opcode;
455
456         if (snapend - bp < (int)sizeof (struct rx_header)) {
457                 printf(" [|rx] (%d)", length);
458                 return;
459         }
460
461         rxh = (struct rx_header *) bp;
462
463         printf(" rx %s", tok2str(rx_types, "type %d", rxh->type));
464
465         if (vflag) {
466                 int firstflag = 0;
467
468                 if (vflag > 1)
469                         printf(" cid %08x call# %d",
470                                (int) EXTRACT_32BITS(&rxh->cid),
471                                (int) EXTRACT_32BITS(&rxh->callNumber));
472
473                 printf(" seq %d ser %d",
474                        (int) EXTRACT_32BITS(&rxh->seq),
475                        (int) EXTRACT_32BITS(&rxh->serial));
476
477                 if (vflag > 2)
478                         printf(" secindex %d serviceid %hu",
479                                 (int) rxh->securityIndex,
480                                 EXTRACT_16BITS(&rxh->serviceId));
481
482                 if (vflag > 1)
483                         for (i = 0; i < NUM_RX_FLAGS; i++) {
484                                 if (rxh->flags & rx_flags[i].flag &&
485                                     (!rx_flags[i].packetType ||
486                                      rxh->type == rx_flags[i].packetType)) {
487                                         if (!firstflag) {
488                                                 firstflag = 1;
489                                                 printf(" ");
490                                         } else {
491                                                 printf(",");
492                                         }
493                                         printf("<%s>", rx_flags[i].s);
494                                 }
495                         }
496         }
497
498         /*
499          * Try to handle AFS calls that we know about.  Check the destination
500          * port and make sure it's a data packet.  Also, make sure the
501          * seq number is 1 (because otherwise it's a continuation packet,
502          * and we can't interpret that).  Also, seems that reply packets
503          * do not have the client-init flag set, so we check for that
504          * as well.
505          */
506
507         if (rxh->type == RX_PACKET_TYPE_DATA &&
508             EXTRACT_32BITS(&rxh->seq) == 1 &&
509             rxh->flags & RX_CLIENT_INITIATED) {
510
511                 /*
512                  * Insert this call into the call cache table, so we
513                  * have a chance to print out replies
514                  */
515
516                 rx_cache_insert(bp, (const struct ip *) bp2, dport);
517
518                 switch (dport) {
519                         case FS_RX_PORT:        /* AFS file service */
520                                 fs_print(bp, length);
521                                 break;
522                         case CB_RX_PORT:        /* AFS callback service */
523                                 cb_print(bp, length);
524                                 break;
525                         case PROT_RX_PORT:      /* AFS protection service */
526                                 prot_print(bp, length);
527                                 break;
528                         case VLDB_RX_PORT:      /* AFS VLDB service */
529                                 vldb_print(bp, length);
530                                 break;
531                         case KAUTH_RX_PORT:     /* AFS Kerberos auth service */
532                                 kauth_print(bp, length);
533                                 break;
534                         case VOL_RX_PORT:       /* AFS Volume service */
535                                 vol_print(bp, length);
536                                 break;
537                         case BOS_RX_PORT:       /* AFS BOS service */
538                                 bos_print(bp, length);
539                                 break;
540                         default:
541                                 ;
542                 }
543
544         /*
545          * If it's a reply (client-init is _not_ set, but seq is one)
546          * then look it up in the cache.  If we find it, call the reply
547          * printing functions  Note that we handle abort packets here,
548          * because printing out the return code can be useful at times.
549          */
550
551         } else if (((rxh->type == RX_PACKET_TYPE_DATA &&
552                                         EXTRACT_32BITS(&rxh->seq) == 1) ||
553                     rxh->type == RX_PACKET_TYPE_ABORT) &&
554                    (rxh->flags & RX_CLIENT_INITIATED) == 0 &&
555                    rx_cache_find(rxh, (const struct ip *) bp2,
556                                  sport, &opcode)) {
557
558                 switch (sport) {
559                         case FS_RX_PORT:        /* AFS file service */
560                                 fs_reply_print(bp, length, opcode);
561                                 break;
562                         case CB_RX_PORT:        /* AFS callback service */
563                                 cb_reply_print(bp, length, opcode);
564                                 break;
565                         case PROT_RX_PORT:      /* AFS PT service */
566                                 prot_reply_print(bp, length, opcode);
567                                 break;
568                         case VLDB_RX_PORT:      /* AFS VLDB service */
569                                 vldb_reply_print(bp, length, opcode);
570                                 break;
571                         case KAUTH_RX_PORT:     /* AFS Kerberos auth service */
572                                 kauth_reply_print(bp, length, opcode);
573                                 break;
574                         case VOL_RX_PORT:       /* AFS Volume service */
575                                 vol_reply_print(bp, length, opcode);
576                                 break;
577                         case BOS_RX_PORT:       /* AFS BOS service */
578                                 bos_reply_print(bp, length, opcode);
579                                 break;
580                         default:
581                                 ;
582                 }
583
584         /*
585          * If it's an RX ack packet, then use the appropriate ack decoding
586          * function (there isn't any service-specific information in the
587          * ack packet, so we can use one for all AFS services)
588          */
589
590         } else if (rxh->type == RX_PACKET_TYPE_ACK)
591                 rx_ack_print(bp, length);
592
593
594         printf(" (%d)", length);
595 }
596
597 /*
598  * Insert an entry into the cache.  Taken from print-nfs.c
599  */
600
601 static void
602 rx_cache_insert(const u_char *bp, const struct ip *ip, int dport)
603 {
604         struct rx_cache_entry *rxent;
605         const struct rx_header *rxh = (const struct rx_header *) bp;
606
607         if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t)))
608                 return;
609
610         rxent = &rx_cache[rx_cache_next];
611
612         if (++rx_cache_next >= RX_CACHE_SIZE)
613                 rx_cache_next = 0;
614
615         rxent->callnum = rxh->callNumber;
616         rxent->client = ip->ip_src;
617         rxent->server = ip->ip_dst;
618         rxent->dport = dport;
619         rxent->serviceId = rxh->serviceId;
620         rxent->opcode = EXTRACT_32BITS(bp + sizeof(struct rx_header));
621 }
622
623 /*
624  * Lookup an entry in the cache.  Also taken from print-nfs.c
625  *
626  * Note that because this is a reply, we're looking at the _source_
627  * port.
628  */
629
630 static int
631 rx_cache_find(const struct rx_header *rxh, const struct ip *ip, int sport,
632               int32_t *opcode)
633 {
634         int i;
635         struct rx_cache_entry *rxent;
636         u_int32_t clip = ip->ip_dst.s_addr;
637         u_int32_t sip = ip->ip_src.s_addr;
638
639         /* Start the search where we last left off */
640
641         i = rx_cache_hint;
642         do {
643                 rxent = &rx_cache[i];
644                 if (rxent->callnum == rxh->callNumber &&
645                     rxent->client.s_addr == clip &&
646                     rxent->server.s_addr == sip &&
647                     rxent->serviceId == rxh->serviceId &&
648                     rxent->dport == sport) {
649
650                         /* We got a match! */
651
652                         rx_cache_hint = i;
653                         *opcode = rxent->opcode;
654                         return(1);
655                 }
656                 if (++i > RX_CACHE_SIZE)
657                         i = 0;
658         } while (i != rx_cache_hint);
659
660         /* Our search failed */
661         return(0);
662 }
663
664 /*
665  * These extrememly grody macros handle the printing of various AFS stuff.
666  */
667
668 #define FIDOUT() { unsigned long n1, n2, n3; \
669                         TCHECK2(bp[0], sizeof(int32_t) * 3); \
670                         n1 = EXTRACT_32BITS(bp); \
671                         bp += sizeof(int32_t); \
672                         n2 = EXTRACT_32BITS(bp); \
673                         bp += sizeof(int32_t); \
674                         n3 = EXTRACT_32BITS(bp); \
675                         bp += sizeof(int32_t); \
676                         printf(" fid %d/%d/%d", (int) n1, (int) n2, (int) n3); \
677                 }
678
679 #define STROUT(MAX) { unsigned int i; \
680                         TCHECK2(bp[0], sizeof(int32_t)); \
681                         i = EXTRACT_32BITS(bp); \
682                         if (i > (MAX)) \
683                                 goto trunc; \
684                         bp += sizeof(int32_t); \
685                         printf(" \""); \
686                         if (fn_printn(bp, i, snapend)) \
687                                 goto trunc; \
688                         printf("\""); \
689                         bp += ((i + sizeof(int32_t) - 1) / sizeof(int32_t)) * sizeof(int32_t); \
690                 }
691
692 #define INTOUT() { int i; \
693                         TCHECK2(bp[0], sizeof(int32_t)); \
694                         i = (int) EXTRACT_32BITS(bp); \
695                         bp += sizeof(int32_t); \
696                         printf(" %d", i); \
697                 }
698
699 #define UINTOUT() { unsigned long i; \
700                         TCHECK2(bp[0], sizeof(int32_t)); \
701                         i = EXTRACT_32BITS(bp); \
702                         bp += sizeof(int32_t); \
703                         printf(" %lu", i); \
704                 }
705
706 #define UINT64OUT() { u_int64_t i; \
707                         TCHECK2(bp[0], sizeof(u_int64_t)); \
708                         i = EXTRACT_64BITS(bp); \
709                         bp += sizeof(u_int64_t); \
710                         printf(" %" PRIu64, i); \
711                 }
712
713 #define DATEOUT() { time_t t; struct tm *tm; char str[256]; \
714                         TCHECK2(bp[0], sizeof(int32_t)); \
715                         t = (time_t) EXTRACT_32BITS(bp); \
716                         bp += sizeof(int32_t); \
717                         tm = localtime(&t); \
718                         strftime(str, 256, "%Y/%m/%d %T", tm); \
719                         printf(" %s", str); \
720                 }
721
722 #define STOREATTROUT() { unsigned long mask, i; \
723                         TCHECK2(bp[0], (sizeof(int32_t)*6)); \
724                         mask = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
725                         if (mask) printf (" StoreStatus"); \
726                         if (mask & 1) { printf(" date"); DATEOUT(); } \
727                         else bp += sizeof(int32_t); \
728                         i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
729                         if (mask & 2) printf(" owner %lu", i);  \
730                         i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
731                         if (mask & 4) printf(" group %lu", i); \
732                         i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
733                         if (mask & 8) printf(" mode %lo", i & 07777); \
734                         i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
735                         if (mask & 16) printf(" segsize %lu", i); \
736                         /* undocumented in 3.3 docu */ \
737                         if (mask & 1024) printf(" fsync");  \
738                 }
739
740 #define UBIK_VERSIONOUT() {int32_t epoch; int32_t counter; \
741                         TCHECK2(bp[0], sizeof(int32_t) * 2); \
742                         epoch = EXTRACT_32BITS(bp); \
743                         bp += sizeof(int32_t); \
744                         counter = EXTRACT_32BITS(bp); \
745                         bp += sizeof(int32_t); \
746                         printf(" %d.%d", epoch, counter); \
747                 }
748
749 #define AFSUUIDOUT() {u_int32_t temp; int i; \
750                         TCHECK2(bp[0], 11*sizeof(u_int32_t)); \
751                         temp = EXTRACT_32BITS(bp); \
752                         bp += sizeof(u_int32_t); \
753                         printf(" %08x", temp); \
754                         temp = EXTRACT_32BITS(bp); \
755                         bp += sizeof(u_int32_t); \
756                         printf("%04x", temp); \
757                         temp = EXTRACT_32BITS(bp); \
758                         bp += sizeof(u_int32_t); \
759                         printf("%04x", temp); \
760                         for (i = 0; i < 8; i++) { \
761                                 temp = EXTRACT_32BITS(bp); \
762                                 bp += sizeof(u_int32_t); \
763                                 printf("%02x", (unsigned char) temp); \
764                         } \
765                 }
766
767 /*
768  * This is the sickest one of all
769  */
770
771 #define VECOUT(MAX) { u_char *sp; \
772                         u_char s[AFSNAMEMAX]; \
773                         int k; \
774                         if ((MAX) + 1 > sizeof(s)) \
775                                 goto trunc; \
776                         TCHECK2(bp[0], (MAX) * sizeof(int32_t)); \
777                         sp = s; \
778                         for (k = 0; k < (MAX); k++) { \
779                                 *sp++ = (u_char) EXTRACT_32BITS(bp); \
780                                 bp += sizeof(int32_t); \
781                         } \
782                         s[(MAX)] = '\0'; \
783                         printf(" \""); \
784                         fn_print(s, NULL); \
785                         printf("\""); \
786                 }
787
788 #define DESTSERVEROUT() { unsigned long n1, n2, n3; \
789                         TCHECK2(bp[0], sizeof(int32_t) * 3); \
790                         n1 = EXTRACT_32BITS(bp); \
791                         bp += sizeof(int32_t); \
792                         n2 = EXTRACT_32BITS(bp); \
793                         bp += sizeof(int32_t); \
794                         n3 = EXTRACT_32BITS(bp); \
795                         bp += sizeof(int32_t); \
796                         printf(" server %d:%d:%d", (int) n1, (int) n2, (int) n3); \
797                 }
798
799 /*
800  * Handle calls to the AFS file service (fs)
801  */
802
803 static void
804 fs_print(register const u_char *bp, int length)
805 {
806         int fs_op;
807         unsigned long i;
808
809         if (length <= (int)sizeof(struct rx_header))
810                 return;
811
812         if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
813                 goto trunc;
814         }
815
816         /*
817          * Print out the afs call we're invoking.  The table used here was
818          * gleaned from fsint/afsint.xg
819          */
820
821         fs_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
822
823         printf(" fs call %s", tok2str(fs_req, "op#%d", fs_op));
824
825         /*
826          * Print out arguments to some of the AFS calls.  This stuff is
827          * all from afsint.xg
828          */
829
830         bp += sizeof(struct rx_header) + 4;
831
832         /*
833          * Sigh.  This is gross.  Ritchie forgive me.
834          */
835
836         switch (fs_op) {
837                 case 130:       /* Fetch data */
838                         FIDOUT();
839                         printf(" offset");
840                         UINTOUT();
841                         printf(" length");
842                         UINTOUT();
843                         break;
844                 case 131:       /* Fetch ACL */
845                 case 132:       /* Fetch Status */
846                 case 143:       /* Old set lock */
847                 case 144:       /* Old extend lock */
848                 case 145:       /* Old release lock */
849                 case 156:       /* Set lock */
850                 case 157:       /* Extend lock */
851                 case 158:       /* Release lock */
852                         FIDOUT();
853                         break;
854                 case 135:       /* Store status */
855                         FIDOUT();
856                         STOREATTROUT();
857                         break;
858                 case 133:       /* Store data */
859                         FIDOUT();
860                         STOREATTROUT();
861                         printf(" offset");
862                         UINTOUT();
863                         printf(" length");
864                         UINTOUT();
865                         printf(" flen");
866                         UINTOUT();
867                         break;
868                 case 134:       /* Store ACL */
869                 {
870                         char a[AFSOPAQUEMAX+1];
871                         FIDOUT();
872                         TCHECK2(bp[0], 4);
873                         i = EXTRACT_32BITS(bp);
874                         bp += sizeof(int32_t);
875                         TCHECK2(bp[0], i);
876                         i = min(AFSOPAQUEMAX, i);
877                         strncpy(a, (char *) bp, i);
878                         a[i] = '\0';
879                         acl_print((u_char *) a, sizeof(a), (u_char *) a + i);
880                         break;
881                 }
882                 case 137:       /* Create file */
883                 case 141:       /* MakeDir */
884                         FIDOUT();
885                         STROUT(AFSNAMEMAX);
886                         STOREATTROUT();
887                         break;
888                 case 136:       /* Remove file */
889                 case 142:       /* Remove directory */
890                         FIDOUT();
891                         STROUT(AFSNAMEMAX);
892                         break;
893                 case 138:       /* Rename file */
894                         printf(" old");
895                         FIDOUT();
896                         STROUT(AFSNAMEMAX);
897                         printf(" new");
898                         FIDOUT();
899                         STROUT(AFSNAMEMAX);
900                         break;
901                 case 139:       /* Symlink */
902                         FIDOUT();
903                         STROUT(AFSNAMEMAX);
904                         printf(" link to");
905                         STROUT(AFSNAMEMAX);
906                         break;
907                 case 140:       /* Link */
908                         FIDOUT();
909                         STROUT(AFSNAMEMAX);
910                         printf(" link to");
911                         FIDOUT();
912                         break;
913                 case 148:       /* Get volume info */
914                         STROUT(AFSNAMEMAX);
915                         break;
916                 case 149:       /* Get volume stats */
917                 case 150:       /* Set volume stats */
918                         printf(" volid");
919                         UINTOUT();
920                         break;
921                 case 154:       /* New get volume info */
922                         printf(" volname");
923                         STROUT(AFSNAMEMAX);
924                         break;
925                 case 155:       /* Bulk stat */
926                 case 65536:     /* Inline bulk stat */
927                 {
928                         unsigned long j;
929                         TCHECK2(bp[0], 4);
930                         j = EXTRACT_32BITS(bp);
931                         bp += sizeof(int32_t);
932
933                         for (i = 0; i < j; i++) {
934                                 FIDOUT();
935                                 if (i != j - 1)
936                                         printf(",");
937                         }
938                         if (j == 0)
939                                 printf(" <none!>");
940                 }
941                 case 65537:     /* Fetch data 64 */
942                         FIDOUT();
943                         printf(" offset");
944                         UINT64OUT();
945                         printf(" length");
946                         UINT64OUT();
947                         break;
948                 case 65538:     /* Store data 64 */
949                         FIDOUT();
950                         STOREATTROUT();
951                         printf(" offset");
952                         UINT64OUT();
953                         printf(" length");
954                         UINT64OUT();
955                         printf(" flen");
956                         UINT64OUT();
957                         break;
958                 case 65541:    /* CallBack rx conn address */
959                         printf(" addr");
960                         UINTOUT();
961                 default:
962                         ;
963         }
964
965         return;
966
967 trunc:
968         printf(" [|fs]");
969 }
970
971 /*
972  * Handle replies to the AFS file service
973  */
974
975 static void
976 fs_reply_print(register const u_char *bp, int length, int32_t opcode)
977 {
978         unsigned long i;
979         struct rx_header *rxh;
980
981         if (length <= (int)sizeof(struct rx_header))
982                 return;
983
984         rxh = (struct rx_header *) bp;
985
986         /*
987          * Print out the afs call we're invoking.  The table used here was
988          * gleaned from fsint/afsint.xg
989          */
990
991         printf(" fs reply %s", tok2str(fs_req, "op#%d", opcode));
992
993         bp += sizeof(struct rx_header);
994
995         /*
996          * If it was a data packet, interpret the response
997          */
998
999         if (rxh->type == RX_PACKET_TYPE_DATA) {
1000                 switch (opcode) {
1001                 case 131:       /* Fetch ACL */
1002                 {
1003                         char a[AFSOPAQUEMAX+1];
1004                         TCHECK2(bp[0], 4);
1005                         i = EXTRACT_32BITS(bp);
1006                         bp += sizeof(int32_t);
1007                         TCHECK2(bp[0], i);
1008                         i = min(AFSOPAQUEMAX, i);
1009                         strncpy(a, (char *) bp, i);
1010                         a[i] = '\0';
1011                         acl_print((u_char *) a, sizeof(a), (u_char *) a + i);
1012                         break;
1013                 }
1014                 case 137:       /* Create file */
1015                 case 141:       /* MakeDir */
1016                         printf(" new");
1017                         FIDOUT();
1018                         break;
1019                 case 151:       /* Get root volume */
1020                         printf(" root volume");
1021                         STROUT(AFSNAMEMAX);
1022                         break;
1023                 case 153:       /* Get time */
1024                         DATEOUT();
1025                         break;
1026                 default:
1027                         ;
1028                 }
1029         } else if (rxh->type == RX_PACKET_TYPE_ABORT) {
1030                 int i;
1031
1032                 /*
1033                  * Otherwise, just print out the return code
1034                  */
1035                 TCHECK2(bp[0], sizeof(int32_t));
1036                 i = (int) EXTRACT_32BITS(bp);
1037                 bp += sizeof(int32_t);
1038
1039                 printf(" error %s", tok2str(afs_fs_errors, "#%d", i));
1040         } else {
1041                 printf(" strange fs reply of type %d", rxh->type);
1042         }
1043
1044         return;
1045
1046 trunc:
1047         printf(" [|fs]");
1048 }
1049
1050 /*
1051  * Print out an AFS ACL string.  An AFS ACL is a string that has the
1052  * following format:
1053  *
1054  * <positive> <negative>
1055  * <uid1> <aclbits1>
1056  * ....
1057  *
1058  * "positive" and "negative" are integers which contain the number of
1059  * positive and negative ACL's in the string.  The uid/aclbits pair are
1060  * ASCII strings containing the UID/PTS record and and a ascii number
1061  * representing a logical OR of all the ACL permission bits
1062  */
1063
1064 static void
1065 acl_print(u_char *s, int maxsize, u_char *end)
1066 {
1067         int pos, neg, acl;
1068         int n, i;
1069         char *user;
1070         char fmt[1024];
1071
1072         if ((user = (char *)malloc(maxsize)) == NULL)
1073                 return;
1074
1075         if (sscanf((char *) s, "%d %d\n%n", &pos, &neg, &n) != 2)
1076                 goto finish;
1077
1078         s += n;
1079
1080         if (s > end)
1081                 goto finish;
1082
1083         /*
1084          * This wacky order preserves the order used by the "fs" command
1085          */
1086
1087 #define ACLOUT(acl) \
1088         if (acl & PRSFS_READ) \
1089                 printf("r"); \
1090         if (acl & PRSFS_LOOKUP) \
1091                 printf("l"); \
1092         if (acl & PRSFS_INSERT) \
1093                 printf("i"); \
1094         if (acl & PRSFS_DELETE) \
1095                 printf("d"); \
1096         if (acl & PRSFS_WRITE) \
1097                 printf("w"); \
1098         if (acl & PRSFS_LOCK) \
1099                 printf("k"); \
1100         if (acl & PRSFS_ADMINISTER) \
1101                 printf("a");
1102
1103         for (i = 0; i < pos; i++) {
1104                 snprintf(fmt, sizeof(fmt), "%%%ds %%d\n%%n", maxsize - 1);
1105                 if (sscanf((char *) s, fmt, user, &acl, &n) != 2)
1106                         goto finish;
1107                 s += n;
1108                 printf(" +{");
1109                 fn_print((u_char *)user, NULL);
1110                 printf(" ");
1111                 ACLOUT(acl);
1112                 printf("}");
1113                 if (s > end)
1114                         goto finish;
1115         }
1116
1117         for (i = 0; i < neg; i++) {
1118                 snprintf(fmt, sizeof(fmt), "%%%ds %%d\n%%n", maxsize - 1);
1119                 if (sscanf((char *) s, fmt, user, &acl, &n) != 2)
1120                         goto finish;
1121                 s += n;
1122                 printf(" -{");
1123                 fn_print((u_char *)user, NULL);
1124                 printf(" ");
1125                 ACLOUT(acl);
1126                 printf("}");
1127                 if (s > end)
1128                         goto finish;
1129         }
1130
1131 finish:
1132         free(user);
1133         return;
1134 }
1135
1136 #undef ACLOUT
1137
1138 /*
1139  * Handle calls to the AFS callback service
1140  */
1141
1142 static void
1143 cb_print(register const u_char *bp, int length)
1144 {
1145         int cb_op;
1146         unsigned long i;
1147
1148         if (length <= (int)sizeof(struct rx_header))
1149                 return;
1150
1151         if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
1152                 goto trunc;
1153         }
1154
1155         /*
1156          * Print out the afs call we're invoking.  The table used here was
1157          * gleaned from fsint/afscbint.xg
1158          */
1159
1160         cb_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
1161
1162         printf(" cb call %s", tok2str(cb_req, "op#%d", cb_op));
1163
1164         bp += sizeof(struct rx_header) + 4;
1165
1166         /*
1167          * Print out the afs call we're invoking.  The table used here was
1168          * gleaned from fsint/afscbint.xg
1169          */
1170
1171         switch (cb_op) {
1172                 case 204:               /* Callback */
1173                 {
1174                         unsigned long j, t;
1175                         TCHECK2(bp[0], 4);
1176                         j = EXTRACT_32BITS(bp);
1177                         bp += sizeof(int32_t);
1178
1179                         for (i = 0; i < j; i++) {
1180                                 FIDOUT();
1181                                 if (i != j - 1)
1182                                         printf(",");
1183                         }
1184
1185                         if (j == 0)
1186                                 printf(" <none!>");
1187
1188                         j = EXTRACT_32BITS(bp);
1189                         bp += sizeof(int32_t);
1190
1191                         if (j != 0)
1192                                 printf(";");
1193
1194                         for (i = 0; i < j; i++) {
1195                                 printf(" ver");
1196                                 INTOUT();
1197                                 printf(" expires");
1198                                 DATEOUT();
1199                                 TCHECK2(bp[0], 4);
1200                                 t = EXTRACT_32BITS(bp);
1201                                 bp += sizeof(int32_t);
1202                                 tok2str(cb_types, "type %d", t);
1203                         }
1204                 }
1205                 case 214: {
1206                         printf(" afsuuid");
1207                         AFSUUIDOUT();
1208                         break;
1209                 }
1210                 default:
1211                         ;
1212         }
1213
1214         return;
1215
1216 trunc:
1217         printf(" [|cb]");
1218 }
1219
1220 /*
1221  * Handle replies to the AFS Callback Service
1222  */
1223
1224 static void
1225 cb_reply_print(register const u_char *bp, int length, int32_t opcode)
1226 {
1227         struct rx_header *rxh;
1228
1229         if (length <= (int)sizeof(struct rx_header))
1230                 return;
1231
1232         rxh = (struct rx_header *) bp;
1233
1234         /*
1235          * Print out the afs call we're invoking.  The table used here was
1236          * gleaned from fsint/afscbint.xg
1237          */
1238
1239         printf(" cb reply %s", tok2str(cb_req, "op#%d", opcode));
1240
1241         bp += sizeof(struct rx_header);
1242
1243         /*
1244          * If it was a data packet, interpret the response.
1245          */
1246
1247         if (rxh->type == RX_PACKET_TYPE_DATA)
1248                 switch (opcode) {
1249                 case 213:       /* InitCallBackState3 */
1250                         AFSUUIDOUT();
1251                         break;
1252                 default:
1253                 ;
1254                 }
1255         else {
1256                 /*
1257                  * Otherwise, just print out the return code
1258                  */
1259                 printf(" errcode");
1260                 INTOUT();
1261         }
1262
1263         return;
1264
1265 trunc:
1266         printf(" [|cb]");
1267 }
1268
1269 /*
1270  * Handle calls to the AFS protection database server
1271  */
1272
1273 static void
1274 prot_print(register const u_char *bp, int length)
1275 {
1276         unsigned long i;
1277         int pt_op;
1278
1279         if (length <= (int)sizeof(struct rx_header))
1280                 return;
1281
1282         if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
1283                 goto trunc;
1284         }
1285
1286         /*
1287          * Print out the afs call we're invoking.  The table used here was
1288          * gleaned from ptserver/ptint.xg
1289          */
1290
1291         pt_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
1292
1293         printf(" pt");
1294
1295         if (is_ubik(pt_op)) {
1296                 ubik_print(bp);
1297                 return;
1298         }
1299
1300         printf(" call %s", tok2str(pt_req, "op#%d", pt_op));
1301
1302         /*
1303          * Decode some of the arguments to the PT calls
1304          */
1305
1306         bp += sizeof(struct rx_header) + 4;
1307
1308         switch (pt_op) {
1309                 case 500:       /* I New User */
1310                         STROUT(PRNAMEMAX);
1311                         printf(" id");
1312                         INTOUT();
1313                         printf(" oldid");
1314                         INTOUT();
1315                         break;
1316                 case 501:       /* Where is it */
1317                 case 506:       /* Delete */
1318                 case 508:       /* Get CPS */
1319                 case 512:       /* List entry */
1320                 case 514:       /* List elements */
1321                 case 517:       /* List owned */
1322                 case 518:       /* Get CPS2 */
1323                 case 519:       /* Get host CPS */
1324                 case 530:       /* List super groups */
1325                         printf(" id");
1326                         INTOUT();
1327                         break;
1328                 case 502:       /* Dump entry */
1329                         printf(" pos");
1330                         INTOUT();
1331                         break;
1332                 case 503:       /* Add to group */
1333                 case 507:       /* Remove from group */
1334                 case 515:       /* Is a member of? */
1335                         printf(" uid");
1336                         INTOUT();
1337                         printf(" gid");
1338                         INTOUT();
1339                         break;
1340                 case 504:       /* Name to ID */
1341                 {
1342                         unsigned long j;
1343                         TCHECK2(bp[0], 4);
1344                         j = EXTRACT_32BITS(bp);
1345                         bp += sizeof(int32_t);
1346
1347                         /*
1348                          * Who designed this chicken-shit protocol?
1349                          *
1350                          * Each character is stored as a 32-bit
1351                          * integer!
1352                          */
1353
1354                         for (i = 0; i < j; i++) {
1355                                 VECOUT(PRNAMEMAX);
1356                         }
1357                         if (j == 0)
1358                                 printf(" <none!>");
1359                 }
1360                         break;
1361                 case 505:       /* Id to name */
1362                 {
1363                         unsigned long j;
1364                         printf(" ids:");
1365                         TCHECK2(bp[0], 4);
1366                         i = EXTRACT_32BITS(bp);
1367                         bp += sizeof(int32_t);
1368                         for (j = 0; j < i; j++)
1369                                 INTOUT();
1370                         if (j == 0)
1371                                 printf(" <none!>");
1372                 }
1373                         break;
1374                 case 509:       /* New entry */
1375                         STROUT(PRNAMEMAX);
1376                         printf(" flag");
1377                         INTOUT();
1378                         printf(" oid");
1379                         INTOUT();
1380                         break;
1381                 case 511:       /* Set max */
1382                         printf(" id");
1383                         INTOUT();
1384                         printf(" gflag");
1385                         INTOUT();
1386                         break;
1387                 case 513:       /* Change entry */
1388                         printf(" id");
1389                         INTOUT();
1390                         STROUT(PRNAMEMAX);
1391                         printf(" oldid");
1392                         INTOUT();
1393                         printf(" newid");
1394                         INTOUT();
1395                         break;
1396                 case 520:       /* Update entry */
1397                         printf(" id");
1398                         INTOUT();
1399                         STROUT(PRNAMEMAX);
1400                         break;
1401                 default:
1402                         ;
1403         }
1404
1405
1406         return;
1407
1408 trunc:
1409         printf(" [|pt]");
1410 }
1411
1412 /*
1413  * Handle replies to the AFS protection service
1414  */
1415
1416 static void
1417 prot_reply_print(register const u_char *bp, int length, int32_t opcode)
1418 {
1419         struct rx_header *rxh;
1420         unsigned long i;
1421
1422         if (length < (int)sizeof(struct rx_header))
1423                 return;
1424
1425         rxh = (struct rx_header *) bp;
1426
1427         /*
1428          * Print out the afs call we're invoking.  The table used here was
1429          * gleaned from ptserver/ptint.xg.  Check to see if it's a
1430          * Ubik call, however.
1431          */
1432
1433         printf(" pt");
1434
1435         if (is_ubik(opcode)) {
1436                 ubik_reply_print(bp, length, opcode);
1437                 return;
1438         }
1439
1440         printf(" reply %s", tok2str(pt_req, "op#%d", opcode));
1441
1442         bp += sizeof(struct rx_header);
1443
1444         /*
1445          * If it was a data packet, interpret the response
1446          */
1447
1448         if (rxh->type == RX_PACKET_TYPE_DATA)
1449                 switch (opcode) {
1450                 case 504:               /* Name to ID */
1451                 {
1452                         unsigned long j;
1453                         printf(" ids:");
1454                         TCHECK2(bp[0], 4);
1455                         i = EXTRACT_32BITS(bp);
1456                         bp += sizeof(int32_t);
1457                         for (j = 0; j < i; j++)
1458                                 INTOUT();
1459                         if (j == 0)
1460                                 printf(" <none!>");
1461                 }
1462                         break;
1463                 case 505:               /* ID to name */
1464                 {
1465                         unsigned long j;
1466                         TCHECK2(bp[0], 4);
1467                         j = EXTRACT_32BITS(bp);
1468                         bp += sizeof(int32_t);
1469
1470                         /*
1471                          * Who designed this chicken-shit protocol?
1472                          *
1473                          * Each character is stored as a 32-bit
1474                          * integer!
1475                          */
1476
1477                         for (i = 0; i < j; i++) {
1478                                 VECOUT(PRNAMEMAX);
1479                         }
1480                         if (j == 0)
1481                                 printf(" <none!>");
1482                 }
1483                         break;
1484                 case 508:               /* Get CPS */
1485                 case 514:               /* List elements */
1486                 case 517:               /* List owned */
1487                 case 518:               /* Get CPS2 */
1488                 case 519:               /* Get host CPS */
1489                 {
1490                         unsigned long j;
1491                         TCHECK2(bp[0], 4);
1492                         j = EXTRACT_32BITS(bp);
1493                         bp += sizeof(int32_t);
1494                         for (i = 0; i < j; i++) {
1495                                 INTOUT();
1496                         }
1497                         if (j == 0)
1498                                 printf(" <none!>");
1499                 }
1500                         break;
1501                 case 510:               /* List max */
1502                         printf(" maxuid");
1503                         INTOUT();
1504                         printf(" maxgid");
1505                         INTOUT();
1506                         break;
1507                 default:
1508                         ;
1509                 }
1510         else {
1511                 /*
1512                  * Otherwise, just print out the return code
1513                  */
1514                 printf(" errcode");
1515                 INTOUT();
1516         }
1517
1518         return;
1519
1520 trunc:
1521         printf(" [|pt]");
1522 }
1523
1524 /*
1525  * Handle calls to the AFS volume location database service
1526  */
1527
1528 static void
1529 vldb_print(register const u_char *bp, int length)
1530 {
1531         int vldb_op;
1532         unsigned long i;
1533
1534         if (length <= (int)sizeof(struct rx_header))
1535                 return;
1536
1537         if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
1538                 goto trunc;
1539         }
1540
1541         /*
1542          * Print out the afs call we're invoking.  The table used here was
1543          * gleaned from vlserver/vldbint.xg
1544          */
1545
1546         vldb_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
1547
1548         printf(" vldb");
1549
1550         if (is_ubik(vldb_op)) {
1551                 ubik_print(bp);
1552                 return;
1553         }
1554         printf(" call %s", tok2str(vldb_req, "op#%d", vldb_op));
1555
1556         /*
1557          * Decode some of the arguments to the VLDB calls
1558          */
1559
1560         bp += sizeof(struct rx_header) + 4;
1561
1562         switch (vldb_op) {
1563                 case 501:       /* Create new volume */
1564                 case 517:       /* Create entry N */
1565                         VECOUT(VLNAMEMAX);
1566                         break;
1567                 case 502:       /* Delete entry */
1568                 case 503:       /* Get entry by ID */
1569                 case 507:       /* Update entry */
1570                 case 508:       /* Set lock */
1571                 case 509:       /* Release lock */
1572                 case 518:       /* Get entry by ID N */
1573                         printf(" volid");
1574                         INTOUT();
1575                         TCHECK2(bp[0], sizeof(int32_t));
1576                         i = EXTRACT_32BITS(bp);
1577                         bp += sizeof(int32_t);
1578                         if (i <= 2)
1579                                 printf(" type %s", voltype[i]);
1580                         break;
1581                 case 504:       /* Get entry by name */
1582                 case 519:       /* Get entry by name N */
1583                 case 524:       /* Update entry by name */
1584                 case 527:       /* Get entry by name U */
1585                         STROUT(VLNAMEMAX);
1586                         break;
1587                 case 505:       /* Get new vol id */
1588                         printf(" bump");
1589                         INTOUT();
1590                         break;
1591                 case 506:       /* Replace entry */
1592                 case 520:       /* Replace entry N */
1593                         printf(" volid");
1594                         INTOUT();
1595                         TCHECK2(bp[0], sizeof(int32_t));
1596                         i = EXTRACT_32BITS(bp);
1597                         bp += sizeof(int32_t);
1598                         if (i <= 2)
1599                                 printf(" type %s", voltype[i]);
1600                         VECOUT(VLNAMEMAX);
1601                         break;
1602                 case 510:       /* List entry */
1603                 case 521:       /* List entry N */
1604                         printf(" index");
1605                         INTOUT();
1606                         break;
1607                 default:
1608                         ;
1609         }
1610
1611         return;
1612
1613 trunc:
1614         printf(" [|vldb]");
1615 }
1616
1617 /*
1618  * Handle replies to the AFS volume location database service
1619  */
1620
1621 static void
1622 vldb_reply_print(register const u_char *bp, int length, int32_t opcode)
1623 {
1624         struct rx_header *rxh;
1625         unsigned long i;
1626
1627         if (length < (int)sizeof(struct rx_header))
1628                 return;
1629
1630         rxh = (struct rx_header *) bp;
1631
1632         /*
1633          * Print out the afs call we're invoking.  The table used here was
1634          * gleaned from vlserver/vldbint.xg.  Check to see if it's a
1635          * Ubik call, however.
1636          */
1637
1638         printf(" vldb");
1639
1640         if (is_ubik(opcode)) {
1641                 ubik_reply_print(bp, length, opcode);
1642                 return;
1643         }
1644
1645         printf(" reply %s", tok2str(vldb_req, "op#%d", opcode));
1646
1647         bp += sizeof(struct rx_header);
1648
1649         /*
1650          * If it was a data packet, interpret the response
1651          */
1652
1653         if (rxh->type == RX_PACKET_TYPE_DATA)
1654                 switch (opcode) {
1655                 case 510:       /* List entry */
1656                         printf(" count");
1657                         INTOUT();
1658                         printf(" nextindex");
1659                         INTOUT();
1660                 case 503:       /* Get entry by id */
1661                 case 504:       /* Get entry by name */
1662                 {       unsigned long nservers, j;
1663                         VECOUT(VLNAMEMAX);
1664                         TCHECK2(bp[0], sizeof(int32_t));
1665                         bp += sizeof(int32_t);
1666                         printf(" numservers");
1667                         TCHECK2(bp[0], sizeof(int32_t));
1668                         nservers = EXTRACT_32BITS(bp);
1669                         bp += sizeof(int32_t);
1670                         printf(" %lu", nservers);
1671                         printf(" servers");
1672                         for (i = 0; i < 8; i++) {
1673                                 TCHECK2(bp[0], sizeof(int32_t));
1674                                 if (i < nservers)
1675                                         printf(" %s",
1676                                            intoa(((struct in_addr *) bp)->s_addr));
1677                                 bp += sizeof(int32_t);
1678                         }
1679                         printf(" partitions");
1680                         for (i = 0; i < 8; i++) {
1681                                 TCHECK2(bp[0], sizeof(int32_t));
1682                                 j = EXTRACT_32BITS(bp);
1683                                 if (i < nservers && j <= 26)
1684                                         printf(" %c", 'a' + (int)j);
1685                                 else if (i < nservers)
1686                                         printf(" %lu", j);
1687                                 bp += sizeof(int32_t);
1688                         }
1689                         TCHECK2(bp[0], 8 * sizeof(int32_t));
1690                         bp += 8 * sizeof(int32_t);
1691                         printf(" rwvol");
1692                         UINTOUT();
1693                         printf(" rovol");
1694                         UINTOUT();
1695                         printf(" backup");
1696                         UINTOUT();
1697                 }
1698                         break;
1699                 case 505:       /* Get new volume ID */
1700                         printf(" newvol");
1701                         UINTOUT();
1702                         break;
1703                 case 521:       /* List entry */
1704                 case 529:       /* List entry U */
1705                         printf(" count");
1706                         INTOUT();
1707                         printf(" nextindex");
1708                         INTOUT();
1709                 case 518:       /* Get entry by ID N */
1710                 case 519:       /* Get entry by name N */
1711                 {       unsigned long nservers, j;
1712                         VECOUT(VLNAMEMAX);
1713                         printf(" numservers");
1714                         TCHECK2(bp[0], sizeof(int32_t));
1715                         nservers = EXTRACT_32BITS(bp);
1716                         bp += sizeof(int32_t);
1717                         printf(" %lu", nservers);
1718                         printf(" servers");
1719                         for (i = 0; i < 13; i++) {
1720                                 TCHECK2(bp[0], sizeof(int32_t));
1721                                 if (i < nservers)
1722                                         printf(" %s",
1723                                            intoa(((struct in_addr *) bp)->s_addr));
1724                                 bp += sizeof(int32_t);
1725                         }
1726                         printf(" partitions");
1727                         for (i = 0; i < 13; i++) {
1728                                 TCHECK2(bp[0], sizeof(int32_t));
1729                                 j = EXTRACT_32BITS(bp);
1730                                 if (i < nservers && j <= 26)
1731                                         printf(" %c", 'a' + (int)j);
1732                                 else if (i < nservers)
1733                                         printf(" %lu", j);
1734                                 bp += sizeof(int32_t);
1735                         }
1736                         TCHECK2(bp[0], 13 * sizeof(int32_t));
1737                         bp += 13 * sizeof(int32_t);
1738                         printf(" rwvol");
1739                         UINTOUT();
1740                         printf(" rovol");
1741                         UINTOUT();
1742                         printf(" backup");
1743                         UINTOUT();
1744                 }
1745                         break;
1746                 case 526:       /* Get entry by ID U */
1747                 case 527:       /* Get entry by name U */
1748                 {       unsigned long nservers, j;
1749                         VECOUT(VLNAMEMAX);
1750                         printf(" numservers");
1751                         TCHECK2(bp[0], sizeof(int32_t));
1752                         nservers = EXTRACT_32BITS(bp);
1753                         bp += sizeof(int32_t);
1754                         printf(" %lu", nservers);
1755                         printf(" servers");
1756                         for (i = 0; i < 13; i++) {
1757                                 if (i < nservers) {
1758                                         printf(" afsuuid");
1759                                         AFSUUIDOUT();
1760                                 } else {
1761                                         TCHECK2(bp[0], 44);
1762                                         bp += 44;
1763                                 }
1764                         }
1765                         TCHECK2(bp[0], 4 * 13);
1766                         bp += 4 * 13;
1767                         printf(" partitions");
1768                         for (i = 0; i < 13; i++) {
1769                                 TCHECK2(bp[0], sizeof(int32_t));
1770                                 j = EXTRACT_32BITS(bp);
1771                                 if (i < nservers && j <= 26)
1772                                         printf(" %c", 'a' + (int)j);
1773                                 else if (i < nservers)
1774                                         printf(" %lu", j);
1775                                 bp += sizeof(int32_t);
1776                         }
1777                         TCHECK2(bp[0], 13 * sizeof(int32_t));
1778                         bp += 13 * sizeof(int32_t);
1779                         printf(" rwvol");
1780                         UINTOUT();
1781                         printf(" rovol");
1782                         UINTOUT();
1783                         printf(" backup");
1784                         UINTOUT();
1785                 }
1786                 default:
1787                         ;
1788                 }
1789
1790         else {
1791                 /*
1792                  * Otherwise, just print out the return code
1793                  */
1794                 printf(" errcode");
1795                 INTOUT();
1796         }
1797
1798         return;
1799
1800 trunc:
1801         printf(" [|vldb]");
1802 }
1803
1804 /*
1805  * Handle calls to the AFS Kerberos Authentication service
1806  */
1807
1808 static void
1809 kauth_print(register const u_char *bp, int length)
1810 {
1811         int kauth_op;
1812
1813         if (length <= (int)sizeof(struct rx_header))
1814                 return;
1815
1816         if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
1817                 goto trunc;
1818         }
1819
1820         /*
1821          * Print out the afs call we're invoking.  The table used here was
1822          * gleaned from kauth/kauth.rg
1823          */
1824
1825         kauth_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
1826
1827         printf(" kauth");
1828
1829         if (is_ubik(kauth_op)) {
1830                 ubik_print(bp);
1831                 return;
1832         }
1833
1834
1835         printf(" call %s", tok2str(kauth_req, "op#%d", kauth_op));
1836
1837         /*
1838          * Decode some of the arguments to the KA calls
1839          */
1840
1841         bp += sizeof(struct rx_header) + 4;
1842
1843         switch (kauth_op) {
1844                 case 1:         /* Authenticate old */;
1845                 case 21:        /* Authenticate */
1846                 case 22:        /* Authenticate-V2 */
1847                 case 2:         /* Change PW */
1848                 case 5:         /* Set fields */
1849                 case 6:         /* Create user */
1850                 case 7:         /* Delete user */
1851                 case 8:         /* Get entry */
1852                 case 14:        /* Unlock */
1853                 case 15:        /* Lock status */
1854                         printf(" principal");
1855                         STROUT(KANAMEMAX);
1856                         STROUT(KANAMEMAX);
1857                         break;
1858                 case 3:         /* GetTicket-old */
1859                 case 23:        /* GetTicket */
1860                 {
1861                         int i;
1862                         printf(" kvno");
1863                         INTOUT();
1864                         printf(" domain");
1865                         STROUT(KANAMEMAX);
1866                         TCHECK2(bp[0], sizeof(int32_t));
1867                         i = (int) EXTRACT_32BITS(bp);
1868                         bp += sizeof(int32_t);
1869                         TCHECK2(bp[0], i);
1870                         bp += i;
1871                         printf(" principal");
1872                         STROUT(KANAMEMAX);
1873                         STROUT(KANAMEMAX);
1874                         break;
1875                 }
1876                 case 4:         /* Set Password */
1877                         printf(" principal");
1878                         STROUT(KANAMEMAX);
1879                         STROUT(KANAMEMAX);
1880                         printf(" kvno");
1881                         INTOUT();
1882                         break;
1883                 case 12:        /* Get password */
1884                         printf(" name");
1885                         STROUT(KANAMEMAX);
1886                         break;
1887                 default:
1888                         ;
1889         }
1890
1891         return;
1892
1893 trunc:
1894         printf(" [|kauth]");
1895 }
1896
1897 /*
1898  * Handle replies to the AFS Kerberos Authentication Service
1899  */
1900
1901 static void
1902 kauth_reply_print(register const u_char *bp, int length, int32_t opcode)
1903 {
1904         struct rx_header *rxh;
1905
1906         if (length <= (int)sizeof(struct rx_header))
1907                 return;
1908
1909         rxh = (struct rx_header *) bp;
1910
1911         /*
1912          * Print out the afs call we're invoking.  The table used here was
1913          * gleaned from kauth/kauth.rg
1914          */
1915
1916         printf(" kauth");
1917
1918         if (is_ubik(opcode)) {
1919                 ubik_reply_print(bp, length, opcode);
1920                 return;
1921         }
1922
1923         printf(" reply %s", tok2str(kauth_req, "op#%d", opcode));
1924
1925         bp += sizeof(struct rx_header);
1926
1927         /*
1928          * If it was a data packet, interpret the response.
1929          */
1930
1931         if (rxh->type == RX_PACKET_TYPE_DATA)
1932                 /* Well, no, not really.  Leave this for later */
1933                 ;
1934         else {
1935                 /*
1936                  * Otherwise, just print out the return code
1937                  */
1938                 printf(" errcode");
1939                 INTOUT();
1940         }
1941
1942         return;
1943
1944 trunc:
1945         printf(" [|kauth]");
1946 }
1947
1948 /*
1949  * Handle calls to the AFS Volume location service
1950  */
1951
1952 static void
1953 vol_print(register const u_char *bp, int length)
1954 {
1955         int vol_op;
1956
1957         if (length <= (int)sizeof(struct rx_header))
1958                 return;
1959
1960         if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
1961                 goto trunc;
1962         }
1963
1964         /*
1965          * Print out the afs call we're invoking.  The table used here was
1966          * gleaned from volser/volint.xg
1967          */
1968
1969         vol_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
1970
1971         printf(" vol call %s", tok2str(vol_req, "op#%d", vol_op));
1972
1973         bp += sizeof(struct rx_header) + 4;
1974
1975         switch (vol_op) {
1976                 case 100:       /* Create volume */
1977                         printf(" partition");
1978                         UINTOUT();
1979                         printf(" name");
1980                         STROUT(AFSNAMEMAX);
1981                         printf(" type");
1982                         UINTOUT();
1983                         printf(" parent");
1984                         UINTOUT();
1985                         break;
1986                 case 101:       /* Delete volume */
1987                 case 107:       /* Get flags */
1988                         printf(" trans");
1989                         UINTOUT();
1990                         break;
1991                 case 102:       /* Restore */
1992                         printf(" totrans");
1993                         UINTOUT();
1994                         printf(" flags");
1995                         UINTOUT();
1996                         break;
1997                 case 103:       /* Forward */
1998                         printf(" fromtrans");
1999                         UINTOUT();
2000                         printf(" fromdate");
2001                         DATEOUT();
2002                         DESTSERVEROUT();
2003                         printf(" desttrans");
2004                         INTOUT();
2005                         break;
2006                 case 104:       /* End trans */
2007                         printf(" trans");
2008                         UINTOUT();
2009                         break;
2010                 case 105:       /* Clone */
2011                         printf(" trans");
2012                         UINTOUT();
2013                         printf(" purgevol");
2014                         UINTOUT();
2015                         printf(" newtype");
2016                         UINTOUT();
2017                         printf(" newname");
2018                         STROUT(AFSNAMEMAX);
2019                         break;
2020                 case 106:       /* Set flags */
2021                         printf(" trans");
2022                         UINTOUT();
2023                         printf(" flags");
2024                         UINTOUT();
2025                         break;
2026                 case 108:       /* Trans create */
2027                         printf(" vol");
2028                         UINTOUT();
2029                         printf(" partition");
2030                         UINTOUT();
2031                         printf(" flags");
2032                         UINTOUT();
2033                         break;
2034                 case 109:       /* Dump */
2035                 case 655537:    /* Get size */
2036                         printf(" fromtrans");
2037                         UINTOUT();
2038                         printf(" fromdate");
2039                         DATEOUT();
2040                         break;
2041                 case 110:       /* Get n-th volume */
2042                         printf(" index");
2043                         UINTOUT();
2044                         break;
2045                 case 111:       /* Set forwarding */
2046                         printf(" tid");
2047                         UINTOUT();
2048                         printf(" newsite");
2049                         UINTOUT();
2050                         break;
2051                 case 112:       /* Get name */
2052                 case 113:       /* Get status */
2053                         printf(" tid");
2054                         break;
2055                 case 114:       /* Signal restore */
2056                         printf(" name");
2057                         STROUT(AFSNAMEMAX);
2058                         printf(" type");
2059                         UINTOUT();
2060                         printf(" pid");
2061                         UINTOUT();
2062                         printf(" cloneid");
2063                         UINTOUT();
2064                         break;
2065                 case 116:       /* List volumes */
2066                         printf(" partition");
2067                         UINTOUT();
2068                         printf(" flags");
2069                         UINTOUT();
2070                         break;
2071                 case 117:       /* Set id types */
2072                         printf(" tid");
2073                         UINTOUT();
2074                         printf(" name");
2075                         STROUT(AFSNAMEMAX);
2076                         printf(" type");
2077                         UINTOUT();
2078                         printf(" pid");
2079                         UINTOUT();
2080                         printf(" clone");
2081                         UINTOUT();
2082                         printf(" backup");
2083                         UINTOUT();
2084                         break;
2085                 case 119:       /* Partition info */
2086                         printf(" name");
2087                         STROUT(AFSNAMEMAX);
2088                         break;
2089                 case 120:       /* Reclone */
2090                         printf(" tid");
2091                         UINTOUT();
2092                         break;
2093                 case 121:       /* List one volume */
2094                 case 122:       /* Nuke volume */
2095                 case 124:       /* Extended List volumes */
2096                 case 125:       /* Extended List one volume */
2097                 case 65536:     /* Convert RO to RW volume */
2098                         printf(" partid");
2099                         UINTOUT();
2100                         printf(" volid");
2101                         UINTOUT();
2102                         break;
2103                 case 123:       /* Set date */
2104                         printf(" tid");
2105                         UINTOUT();
2106                         printf(" date");
2107                         DATEOUT();
2108                         break;
2109                 case 126:       /* Set info */
2110                         printf(" tid");
2111                         UINTOUT();
2112                         break;
2113                 case 128:       /* Forward multiple */
2114                         printf(" fromtrans");
2115                         UINTOUT();
2116                         printf(" fromdate");
2117                         DATEOUT();
2118                         {
2119                                 unsigned long i, j;
2120                                 TCHECK2(bp[0], 4);
2121                                 j = EXTRACT_32BITS(bp);
2122                                 bp += sizeof(int32_t);
2123                                 for (i = 0; i < j; i++) {
2124                                         DESTSERVEROUT();
2125                                         if (i != j - 1)
2126                                                 printf(",");
2127                                 }
2128                                 if (j == 0)
2129                                         printf(" <none!>");
2130                         }
2131                         break;
2132                 case 65538:     /* Dump version 2 */
2133                         printf(" fromtrans");
2134                         UINTOUT();
2135                         printf(" fromdate");
2136                         DATEOUT();
2137                         printf(" flags");
2138                         UINTOUT();
2139                         break;
2140                 default:
2141                         ;
2142         }
2143         return;
2144
2145 trunc:
2146         printf(" [|vol]");
2147 }
2148
2149 /*
2150  * Handle replies to the AFS Volume Service
2151  */
2152
2153 static void
2154 vol_reply_print(register const u_char *bp, int length, int32_t opcode)
2155 {
2156         struct rx_header *rxh;
2157
2158         if (length <= (int)sizeof(struct rx_header))
2159                 return;
2160
2161         rxh = (struct rx_header *) bp;
2162
2163         /*
2164          * Print out the afs call we're invoking.  The table used here was
2165          * gleaned from volser/volint.xg
2166          */
2167
2168         printf(" vol reply %s", tok2str(vol_req, "op#%d", opcode));
2169
2170         bp += sizeof(struct rx_header);
2171
2172         /*
2173          * If it was a data packet, interpret the response.
2174          */
2175
2176         if (rxh->type == RX_PACKET_TYPE_DATA) {
2177                 switch (opcode) {
2178                         case 100:       /* Create volume */
2179                                 printf(" volid");
2180                                 UINTOUT();
2181                                 printf(" trans");
2182                                 UINTOUT();
2183                                 break;
2184                         case 104:       /* End transaction */
2185                                 UINTOUT();
2186                                 break;
2187                         case 105:       /* Clone */
2188                                 printf(" newvol");
2189                                 UINTOUT();
2190                                 break;
2191                         case 107:       /* Get flags */
2192                                 UINTOUT();
2193                                 break;
2194                         case 108:       /* Transaction create */
2195                                 printf(" trans");
2196                                 UINTOUT();
2197                                 break;
2198                         case 110:       /* Get n-th volume */
2199                                 printf(" volume");
2200                                 UINTOUT();
2201                                 printf(" partition");
2202                                 UINTOUT();
2203                                 break;
2204                         case 112:       /* Get name */
2205                                 STROUT(AFSNAMEMAX);
2206                                 break;
2207                         case 113:       /* Get status */
2208                                 printf(" volid");
2209                                 UINTOUT();
2210                                 printf(" nextuniq");
2211                                 UINTOUT();
2212                                 printf(" type");
2213                                 UINTOUT();
2214                                 printf(" parentid");
2215                                 UINTOUT();
2216                                 printf(" clone");
2217                                 UINTOUT();
2218                                 printf(" backup");
2219                                 UINTOUT();
2220                                 printf(" restore");
2221                                 UINTOUT();
2222                                 printf(" maxquota");
2223                                 UINTOUT();
2224                                 printf(" minquota");
2225                                 UINTOUT();
2226                                 printf(" owner");
2227                                 UINTOUT();
2228                                 printf(" create");
2229                                 DATEOUT();
2230                                 printf(" access");
2231                                 DATEOUT();
2232                                 printf(" update");
2233                                 DATEOUT();
2234                                 printf(" expire");
2235                                 DATEOUT();
2236                                 printf(" backup");
2237                                 DATEOUT();
2238                                 printf(" copy");
2239                                 DATEOUT();
2240                                 break;
2241                         case 115:       /* Old list partitions */
2242                                 break;
2243                         case 116:       /* List volumes */
2244                         case 121:       /* List one volume */
2245                                 {
2246                                         unsigned long i, j;
2247                                         TCHECK2(bp[0], 4);
2248                                         j = EXTRACT_32BITS(bp);
2249                                         bp += sizeof(int32_t);
2250                                         for (i = 0; i < j; i++) {
2251                                                 printf(" name");
2252                                                 VECOUT(32);
2253                                                 printf(" volid");
2254                                                 UINTOUT();
2255                                                 printf(" type");
2256                                                 bp += sizeof(int32_t) * 21;
2257                                                 if (i != j - 1)
2258                                                         printf(",");
2259                                         }
2260                                         if (j == 0)
2261                                                 printf(" <none!>");
2262                                 }
2263                                 break;
2264                                 
2265
2266                         default:
2267                                 ;
2268                 }
2269         } else {
2270                 /*
2271                  * Otherwise, just print out the return code
2272                  */
2273                 printf(" errcode");
2274                 INTOUT();
2275         }
2276
2277         return;
2278
2279 trunc:
2280         printf(" [|vol]");
2281 }
2282
2283 /*
2284  * Handle calls to the AFS BOS service
2285  */
2286
2287 static void
2288 bos_print(register const u_char *bp, int length)
2289 {
2290         int bos_op;
2291
2292         if (length <= (int)sizeof(struct rx_header))
2293                 return;
2294
2295         if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
2296                 goto trunc;
2297         }
2298
2299         /*
2300          * Print out the afs call we're invoking.  The table used here was
2301          * gleaned from bozo/bosint.xg
2302          */
2303
2304         bos_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
2305
2306         printf(" bos call %s", tok2str(bos_req, "op#%d", bos_op));
2307
2308         /*
2309          * Decode some of the arguments to the BOS calls
2310          */
2311
2312         bp += sizeof(struct rx_header) + 4;
2313
2314         switch (bos_op) {
2315                 case 80:        /* Create B node */
2316                         printf(" type");
2317                         STROUT(BOSNAMEMAX);
2318                         printf(" instance");
2319                         STROUT(BOSNAMEMAX);
2320                         break;
2321                 case 81:        /* Delete B node */
2322                 case 83:        /* Get status */
2323                 case 85:        /* Get instance info */
2324                 case 87:        /* Add super user */
2325                 case 88:        /* Delete super user */
2326                 case 93:        /* Set cell name */
2327                 case 96:        /* Add cell host */
2328                 case 97:        /* Delete cell host */
2329                 case 104:       /* Restart */
2330                 case 106:       /* Uninstall */
2331                 case 108:       /* Exec */
2332                 case 112:       /* Getlog */
2333                 case 114:       /* Get instance strings */
2334                         STROUT(BOSNAMEMAX);
2335                         break;
2336                 case 82:        /* Set status */
2337                 case 98:        /* Set T status */
2338                         STROUT(BOSNAMEMAX);
2339                         printf(" status");
2340                         INTOUT();
2341                         break;
2342                 case 86:        /* Get instance parm */
2343                         STROUT(BOSNAMEMAX);
2344                         printf(" num");
2345                         INTOUT();
2346                         break;
2347                 case 84:        /* Enumerate instance */
2348                 case 89:        /* List super users */
2349                 case 90:        /* List keys */
2350                 case 91:        /* Add key */
2351                 case 92:        /* Delete key */
2352                 case 95:        /* Get cell host */
2353                         INTOUT();
2354                         break;
2355                 case 105:       /* Install */
2356                         STROUT(BOSNAMEMAX);
2357                         printf(" size");
2358                         INTOUT();
2359                         printf(" flags");
2360                         INTOUT();
2361                         printf(" date");
2362                         INTOUT();
2363                         break;
2364                 default:
2365                         ;
2366         }
2367
2368         return;
2369
2370 trunc:
2371         printf(" [|bos]");
2372 }
2373
2374 /*
2375  * Handle replies to the AFS BOS Service
2376  */
2377
2378 static void
2379 bos_reply_print(register const u_char *bp, int length, int32_t opcode)
2380 {
2381         struct rx_header *rxh;
2382
2383         if (length <= (int)sizeof(struct rx_header))
2384                 return;
2385
2386         rxh = (struct rx_header *) bp;
2387
2388         /*
2389          * Print out the afs call we're invoking.  The table used here was
2390          * gleaned from volser/volint.xg
2391          */
2392
2393         printf(" bos reply %s", tok2str(bos_req, "op#%d", opcode));
2394
2395         bp += sizeof(struct rx_header);
2396
2397         /*
2398          * If it was a data packet, interpret the response.
2399          */
2400
2401         if (rxh->type == RX_PACKET_TYPE_DATA)
2402                 /* Well, no, not really.  Leave this for later */
2403                 ;
2404         else {
2405                 /*
2406                  * Otherwise, just print out the return code
2407                  */
2408                 printf(" errcode");
2409                 INTOUT();
2410         }
2411
2412         return;
2413
2414 trunc:
2415         printf(" [|bos]");
2416 }
2417
2418 /*
2419  * Check to see if this is a Ubik opcode.
2420  */
2421
2422 static int
2423 is_ubik(u_int32_t opcode)
2424 {
2425         if ((opcode >= VOTE_LOW && opcode <= VOTE_HIGH) ||
2426             (opcode >= DISK_LOW && opcode <= DISK_HIGH))
2427                 return(1);
2428         else
2429                 return(0);
2430 }
2431
2432 /*
2433  * Handle Ubik opcodes to any one of the replicated database services
2434  */
2435
2436 static void
2437 ubik_print(register const u_char *bp)
2438 {
2439         int ubik_op;
2440         int32_t temp;
2441
2442         /*
2443          * Print out the afs call we're invoking.  The table used here was
2444          * gleaned from ubik/ubik_int.xg
2445          */
2446
2447         ubik_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
2448
2449         printf(" ubik call %s", tok2str(ubik_req, "op#%d", ubik_op));
2450
2451         /*
2452          * Decode some of the arguments to the Ubik calls
2453          */
2454
2455         bp += sizeof(struct rx_header) + 4;
2456
2457         switch (ubik_op) {
2458                 case 10000:             /* Beacon */
2459                         TCHECK2(bp[0], 4);
2460                         temp = EXTRACT_32BITS(bp);
2461                         bp += sizeof(int32_t);
2462                         printf(" syncsite %s", temp ? "yes" : "no");
2463                         printf(" votestart");
2464                         DATEOUT();
2465                         printf(" dbversion");
2466                         UBIK_VERSIONOUT();
2467                         printf(" tid");
2468                         UBIK_VERSIONOUT();
2469                         break;
2470                 case 10003:             /* Get sync site */
2471                         printf(" site");
2472                         UINTOUT();
2473                         break;
2474                 case 20000:             /* Begin */
2475                 case 20001:             /* Commit */
2476                 case 20007:             /* Abort */
2477                 case 20008:             /* Release locks */
2478                 case 20010:             /* Writev */
2479                         printf(" tid");
2480                         UBIK_VERSIONOUT();
2481                         break;
2482                 case 20002:             /* Lock */
2483                         printf(" tid");
2484                         UBIK_VERSIONOUT();
2485                         printf(" file");
2486                         INTOUT();
2487                         printf(" pos");
2488                         INTOUT();
2489                         printf(" length");
2490                         INTOUT();
2491                         temp = EXTRACT_32BITS(bp);
2492                         bp += sizeof(int32_t);
2493                         tok2str(ubik_lock_types, "type %d", temp);
2494                         break;
2495                 case 20003:             /* Write */
2496                         printf(" tid");
2497                         UBIK_VERSIONOUT();
2498                         printf(" file");
2499                         INTOUT();
2500                         printf(" pos");
2501                         INTOUT();
2502                         break;
2503                 case 20005:             /* Get file */
2504                         printf(" file");
2505                         INTOUT();
2506                         break;
2507                 case 20006:             /* Send file */
2508                         printf(" file");
2509                         INTOUT();
2510                         printf(" length");
2511                         INTOUT();
2512                         printf(" dbversion");
2513                         UBIK_VERSIONOUT();
2514                         break;
2515                 case 20009:             /* Truncate */
2516                         printf(" tid");
2517                         UBIK_VERSIONOUT();
2518                         printf(" file");
2519                         INTOUT();
2520                         printf(" length");
2521                         INTOUT();
2522                         break;
2523                 case 20012:             /* Set version */
2524                         printf(" tid");
2525                         UBIK_VERSIONOUT();
2526                         printf(" oldversion");
2527                         UBIK_VERSIONOUT();
2528                         printf(" newversion");
2529                         UBIK_VERSIONOUT();
2530                         break;
2531                 default:
2532                         ;
2533         }
2534
2535         return;
2536
2537 trunc:
2538         printf(" [|ubik]");
2539 }
2540
2541 /*
2542  * Handle Ubik replies to any one of the replicated database services
2543  */
2544
2545 static void
2546 ubik_reply_print(register const u_char *bp, int length, int32_t opcode)
2547 {
2548         struct rx_header *rxh;
2549
2550         if (length < (int)sizeof(struct rx_header))
2551                 return;
2552
2553         rxh = (struct rx_header *) bp;
2554
2555         /*
2556          * Print out the ubik call we're invoking.  This table was gleaned
2557          * from ubik/ubik_int.xg
2558          */
2559
2560         printf(" ubik reply %s", tok2str(ubik_req, "op#%d", opcode));
2561
2562         bp += sizeof(struct rx_header);
2563
2564         /*
2565          * If it was a data packet, print out the arguments to the Ubik calls
2566          */
2567
2568         if (rxh->type == RX_PACKET_TYPE_DATA)
2569                 switch (opcode) {
2570                 case 10000:             /* Beacon */
2571                         printf(" vote no");
2572                         break;
2573                 case 20004:             /* Get version */
2574                         printf(" dbversion");
2575                         UBIK_VERSIONOUT();
2576                         break;
2577                 default:
2578                         ;
2579                 }
2580
2581         /*
2582          * Otherwise, print out "yes" it it was a beacon packet (because
2583          * that's how yes votes are returned, go figure), otherwise
2584          * just print out the error code.
2585          */
2586
2587         else
2588                 switch (opcode) {
2589                 case 10000:             /* Beacon */
2590                         printf(" vote yes until");
2591                         DATEOUT();
2592                         break;
2593                 default:
2594                         printf(" errcode");
2595                         INTOUT();
2596                 }
2597
2598         return;
2599
2600 trunc:
2601         printf(" [|ubik]");
2602 }
2603
2604 /*
2605  * Handle RX ACK packets.
2606  */
2607
2608 static void
2609 rx_ack_print(register const u_char *bp, int length)
2610 {
2611         struct rx_ackPacket *rxa;
2612         int i, start, last;
2613         u_int32_t firstPacket;
2614
2615         if (length < (int)sizeof(struct rx_header))
2616                 return;
2617
2618         bp += sizeof(struct rx_header);
2619
2620         /*
2621          * This may seem a little odd .... the rx_ackPacket structure
2622          * contains an array of individual packet acknowledgements
2623          * (used for selective ack/nack), but since it's variable in size,
2624          * we don't want to truncate based on the size of the whole
2625          * rx_ackPacket structure.
2626          */
2627
2628         TCHECK2(bp[0], sizeof(struct rx_ackPacket) - RX_MAXACKS);
2629
2630         rxa = (struct rx_ackPacket *) bp;
2631         bp += (sizeof(struct rx_ackPacket) - RX_MAXACKS);
2632
2633         /*
2634          * Print out a few useful things from the ack packet structure
2635          */
2636
2637         if (vflag > 2)
2638                 printf(" bufspace %d maxskew %d",
2639                        (int) EXTRACT_16BITS(&rxa->bufferSpace),
2640                        (int) EXTRACT_16BITS(&rxa->maxSkew));
2641
2642         firstPacket = EXTRACT_32BITS(&rxa->firstPacket);
2643         printf(" first %d serial %d reason %s",
2644                firstPacket, EXTRACT_32BITS(&rxa->serial),
2645                tok2str(rx_ack_reasons, "#%d", (int) rxa->reason));
2646
2647         /*
2648          * Okay, now we print out the ack array.  The way _this_ works
2649          * is that we start at "first", and step through the ack array.
2650          * If we have a contiguous range of acks/nacks, try to
2651          * collapse them into a range.
2652          *
2653          * If you're really clever, you might have noticed that this
2654          * doesn't seem quite correct.  Specifically, due to structure
2655          * padding, sizeof(struct rx_ackPacket) - RX_MAXACKS won't actually
2656          * yield the start of the ack array (because RX_MAXACKS is 255
2657          * and the structure will likely get padded to a 2 or 4 byte
2658          * boundary).  However, this is the way it's implemented inside
2659          * of AFS - the start of the extra fields are at
2660          * sizeof(struct rx_ackPacket) - RX_MAXACKS + nAcks, which _isn't_
2661          * the exact start of the ack array.  Sigh.  That's why we aren't
2662          * using bp, but instead use rxa->acks[].  But nAcks gets added
2663          * to bp after this, so bp ends up at the right spot.  Go figure.
2664          */
2665
2666         if (rxa->nAcks != 0) {
2667
2668                 TCHECK2(bp[0], rxa->nAcks);
2669
2670                 /*
2671                  * Sigh, this is gross, but it seems to work to collapse
2672                  * ranges correctly.
2673                  */
2674
2675                 for (i = 0, start = last = -2; i < rxa->nAcks; i++)
2676                         if (rxa->acks[i] == RX_ACK_TYPE_ACK) {
2677
2678                                 /*
2679                                  * I figured this deserved _some_ explanation.
2680                                  * First, print "acked" and the packet seq
2681                                  * number if this is the first time we've
2682                                  * seen an acked packet.
2683                                  */
2684
2685                                 if (last == -2) {
2686                                         printf(" acked %d",
2687                                                firstPacket + i);
2688                                         start = i;
2689                                 }
2690
2691                                 /*
2692                                  * Otherwise, if the there is a skip in
2693                                  * the range (such as an nacked packet in
2694                                  * the middle of some acked packets),
2695                                  * then print the current packet number
2696                                  * seperated from the last number by
2697                                  * a comma.
2698                                  */
2699
2700                                 else if (last != i - 1) {
2701                                         printf(",%d", firstPacket + i);
2702                                         start = i;
2703                                 }
2704
2705                                 /*
2706                                  * We always set last to the value of
2707                                  * the last ack we saw.  Conversely, start
2708                                  * is set to the value of the first ack
2709                                  * we saw in a range.
2710                                  */
2711
2712                                 last = i;
2713
2714                                 /*
2715                                  * Okay, this bit a code gets executed when
2716                                  * we hit a nack ... in _this_ case we
2717                                  * want to print out the range of packets
2718                                  * that were acked, so we need to print
2719                                  * the _previous_ packet number seperated
2720                                  * from the first by a dash (-).  Since we
2721                                  * already printed the first packet above,
2722                                  * just print the final packet.  Don't
2723                                  * do this if there will be a single-length
2724                                  * range.
2725                                  */
2726                         } else if (last == i - 1 && start != last)
2727                                 printf("-%d", firstPacket + i - 1);
2728
2729                 /*
2730                  * So, what's going on here?  We ran off the end of the
2731                  * ack list, and if we got a range we need to finish it up.
2732                  * So we need to determine if the last packet in the list
2733                  * was an ack (if so, then last will be set to it) and
2734                  * we need to see if the last range didn't start with the
2735                  * last packet (because if it _did_, then that would mean
2736                  * that the packet number has already been printed and
2737                  * we don't need to print it again).
2738                  */
2739
2740                 if (last == i - 1 && start != last)
2741                         printf("-%d", firstPacket + i - 1);
2742
2743                 /*
2744                  * Same as above, just without comments
2745                  */
2746
2747                 for (i = 0, start = last = -2; i < rxa->nAcks; i++)
2748                         if (rxa->acks[i] == RX_ACK_TYPE_NACK) {
2749                                 if (last == -2) {
2750                                         printf(" nacked %d",
2751                                                firstPacket + i);
2752                                         start = i;
2753                                 } else if (last != i - 1) {
2754                                         printf(",%d", firstPacket + i);
2755                                         start = i;
2756                                 }
2757                                 last = i;
2758                         } else if (last == i - 1 && start != last)
2759                                 printf("-%d", firstPacket + i - 1);
2760
2761                 if (last == i - 1 && start != last)
2762                         printf("-%d", firstPacket + i - 1);
2763
2764                 bp += rxa->nAcks;
2765         }
2766
2767
2768         /*
2769          * These are optional fields; depending on your version of AFS,
2770          * you may or may not see them
2771          */
2772
2773 #define TRUNCRET(n)     if (snapend - bp + 1 <= n) return;
2774
2775         if (vflag > 1) {
2776                 TRUNCRET(4);
2777                 printf(" ifmtu");
2778                 INTOUT();
2779
2780                 TRUNCRET(4);
2781                 printf(" maxmtu");
2782                 INTOUT();
2783
2784                 TRUNCRET(4);
2785                 printf(" rwind");
2786                 INTOUT();
2787
2788                 TRUNCRET(4);
2789                 printf(" maxpackets");
2790                 INTOUT();
2791         }
2792
2793         return;
2794
2795 trunc:
2796         printf(" [|ack]");
2797 }
2798 #undef TRUNCRET