time: Use clock_gettime
[dragonfly.git] / contrib / tcpdump / print-rx.c
blob70393ea5cbbe2c290971d012a349d81f74edde1d
1 /*
2 * Copyright: (c) 2000 United States Government as represented by the
3 * Secretary of the Navy. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
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.
24 * This code unmangles RX packets. RX is the mutant form of RPC that AFS
25 * uses to communicate between clients and servers.
27 * In this code, I mainly concern myself with decoding the AFS calls, not
28 * with the guts of RX, per se.
30 * Bah. If I never look at rx_packet.h again, it will be too soon.
32 * Ken Hornstein <kenh@cmf.nrl.navy.mil>
35 #ifndef lint
36 static const char rcsid[] _U_ =
37 "@(#) $Header: /tcpdump/master/tcpdump/print-rx.c,v 1.42 2008-07-01 07:44:50 guy Exp $";
38 #endif
40 #ifdef HAVE_CONFIG_H
41 #include "config.h"
42 #endif
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <tcpdump-stdinc.h>
49 #include "interface.h"
50 #include "addrtoname.h"
51 #include "extract.h"
53 #include "rx.h"
55 #include "ip.h"
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 },
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" }
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
342 #define VOTE_LOW 10000
343 #define VOTE_HIGH 10007
344 #define DISK_LOW 20000
345 #define DISK_HIGH 20013
347 static struct tok cb_types[] = {
348 { 1, "exclusive" },
349 { 2, "shared" },
350 { 3, "dropped" },
351 { 0, NULL },
354 static struct tok ubik_lock_types[] = {
355 { 1, "read" },
356 { 2, "write" },
357 { 3, "wait" },
358 { 0, NULL },
361 static const char *voltype[] = { "read-write", "read-only", "backup" };
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 }
381 * Reasons for acknowledging a packet
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 },
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.
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) */
411 #define RX_CACHE_SIZE 64
413 static struct rx_cache_entry rx_cache[RX_CACHE_SIZE];
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 *);
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);
439 static void rx_ack_print(const u_char *, int);
441 static int is_ubik(u_int32_t);
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
448 void
449 rx_print(register const u_char *bp, int length, int sport, int dport,
450 u_char *bp2)
452 register struct rx_header *rxh;
453 int i;
454 int32_t opcode;
456 if (snapend - bp < (int)sizeof (struct rx_header)) {
457 printf(" [|rx] (%d)", length);
458 return;
461 rxh = (struct rx_header *) bp;
463 printf(" rx %s", tok2str(rx_types, "type %d", rxh->type));
465 if (vflag) {
466 int firstflag = 0;
468 if (vflag > 1)
469 printf(" cid %08x call# %d",
470 (int) EXTRACT_32BITS(&rxh->cid),
471 (int) EXTRACT_32BITS(&rxh->callNumber));
473 printf(" seq %d ser %d",
474 (int) EXTRACT_32BITS(&rxh->seq),
475 (int) EXTRACT_32BITS(&rxh->serial));
477 if (vflag > 2)
478 printf(" secindex %d serviceid %hu",
479 (int) rxh->securityIndex,
480 EXTRACT_16BITS(&rxh->serviceId));
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(",");
493 printf("<%s>", rx_flags[i].s);
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.
507 if (rxh->type == RX_PACKET_TYPE_DATA &&
508 EXTRACT_32BITS(&rxh->seq) == 1 &&
509 rxh->flags & RX_CLIENT_INITIATED) {
512 * Insert this call into the call cache table, so we
513 * have a chance to print out replies
516 rx_cache_insert(bp, (const struct ip *) bp2, dport);
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:
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.
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)) {
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:
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)
590 } else if (rxh->type == RX_PACKET_TYPE_ACK)
591 rx_ack_print(bp, length);
594 printf(" (%d)", length);
598 * Insert an entry into the cache. Taken from print-nfs.c
601 static void
602 rx_cache_insert(const u_char *bp, const struct ip *ip, int dport)
604 struct rx_cache_entry *rxent;
605 const struct rx_header *rxh = (const struct rx_header *) bp;
607 if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t)))
608 return;
610 rxent = &rx_cache[rx_cache_next];
612 if (++rx_cache_next >= RX_CACHE_SIZE)
613 rx_cache_next = 0;
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));
624 * Lookup an entry in the cache. Also taken from print-nfs.c
626 * Note that because this is a reply, we're looking at the _source_
627 * port.
630 static int
631 rx_cache_find(const struct rx_header *rxh, const struct ip *ip, int sport,
632 int32_t *opcode)
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;
639 /* Start the search where we last left off */
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) {
650 /* We got a match! */
652 rx_cache_hint = i;
653 *opcode = rxent->opcode;
654 return(1);
656 if (++i > RX_CACHE_SIZE)
657 i = 0;
658 } while (i != rx_cache_hint);
660 /* Our search failed */
661 return(0);
665 * These extrememly grody macros handle the printing of various AFS stuff.
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); \
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); \
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); \
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); \
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); \
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); \
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"); \
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); \
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); \
768 * This is the sickest one of all
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); \
782 s[(MAX)] = '\0'; \
783 printf(" \""); \
784 fn_print(s, NULL); \
785 printf("\""); \
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); \
800 * Handle calls to the AFS file service (fs)
803 static void
804 fs_print(register const u_char *bp, int length)
806 int fs_op;
807 unsigned long i;
809 if (length <= (int)sizeof(struct rx_header))
810 return;
812 if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
813 goto trunc;
817 * Print out the afs call we're invoking. The table used here was
818 * gleaned from fsint/afsint.xg
821 fs_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
823 printf(" fs call %s", tok2str(fs_req, "op#%d", fs_op));
826 * Print out arguments to some of the AFS calls. This stuff is
827 * all from afsint.xg
830 bp += sizeof(struct rx_header) + 4;
833 * Sigh. This is gross. Ritchie forgive me.
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 */
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;
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 */
928 unsigned long j;
929 TCHECK2(bp[0], 4);
930 j = EXTRACT_32BITS(bp);
931 bp += sizeof(int32_t);
933 for (i = 0; i < j; i++) {
934 FIDOUT();
935 if (i != j - 1)
936 printf(",");
938 if (j == 0)
939 printf(" <none!>");
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:
965 return;
967 trunc:
968 printf(" [|fs]");
972 * Handle replies to the AFS file service
975 static void
976 fs_reply_print(register const u_char *bp, int length, int32_t opcode)
978 unsigned long i;
979 struct rx_header *rxh;
981 if (length <= (int)sizeof(struct rx_header))
982 return;
984 rxh = (struct rx_header *) bp;
987 * Print out the afs call we're invoking. The table used here was
988 * gleaned from fsint/afsint.xg
991 printf(" fs reply %s", tok2str(fs_req, "op#%d", opcode));
993 bp += sizeof(struct rx_header);
996 * If it was a data packet, interpret the response
999 if (rxh->type == RX_PACKET_TYPE_DATA) {
1000 switch (opcode) {
1001 case 131: /* Fetch ACL */
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;
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:
1029 } else if (rxh->type == RX_PACKET_TYPE_ABORT) {
1030 int i;
1033 * Otherwise, just print out the return code
1035 TCHECK2(bp[0], sizeof(int32_t));
1036 i = (int) EXTRACT_32BITS(bp);
1037 bp += sizeof(int32_t);
1039 printf(" error %s", tok2str(afs_fs_errors, "#%d", i));
1040 } else {
1041 printf(" strange fs reply of type %d", rxh->type);
1044 return;
1046 trunc:
1047 printf(" [|fs]");
1051 * Print out an AFS ACL string. An AFS ACL is a string that has the
1052 * following format:
1054 * <positive> <negative>
1055 * <uid1> <aclbits1>
1056 * ....
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
1064 static void
1065 acl_print(u_char *s, int maxsize, u_char *end)
1067 int pos, neg, acl;
1068 int n, i;
1069 char *user;
1070 char fmt[1024];
1072 if ((user = (char *)malloc(maxsize)) == NULL)
1073 return;
1075 if (sscanf((char *) s, "%d %d\n%n", &pos, &neg, &n) != 2)
1076 goto finish;
1078 s += n;
1080 if (s > end)
1081 goto finish;
1084 * This wacky order preserves the order used by the "fs" command
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");
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;
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;
1131 finish:
1132 free(user);
1133 return;
1136 #undef ACLOUT
1139 * Handle calls to the AFS callback service
1142 static void
1143 cb_print(register const u_char *bp, int length)
1145 int cb_op;
1146 unsigned long i;
1148 if (length <= (int)sizeof(struct rx_header))
1149 return;
1151 if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
1152 goto trunc;
1156 * Print out the afs call we're invoking. The table used here was
1157 * gleaned from fsint/afscbint.xg
1160 cb_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
1162 printf(" cb call %s", tok2str(cb_req, "op#%d", cb_op));
1164 bp += sizeof(struct rx_header) + 4;
1167 * Print out the afs call we're invoking. The table used here was
1168 * gleaned from fsint/afscbint.xg
1171 switch (cb_op) {
1172 case 204: /* Callback */
1174 unsigned long j, t;
1175 TCHECK2(bp[0], 4);
1176 j = EXTRACT_32BITS(bp);
1177 bp += sizeof(int32_t);
1179 for (i = 0; i < j; i++) {
1180 FIDOUT();
1181 if (i != j - 1)
1182 printf(",");
1185 if (j == 0)
1186 printf(" <none!>");
1188 j = EXTRACT_32BITS(bp);
1189 bp += sizeof(int32_t);
1191 if (j != 0)
1192 printf(";");
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);
1205 case 214: {
1206 printf(" afsuuid");
1207 AFSUUIDOUT();
1208 break;
1210 default:
1214 return;
1216 trunc:
1217 printf(" [|cb]");
1221 * Handle replies to the AFS Callback Service
1224 static void
1225 cb_reply_print(register const u_char *bp, int length, int32_t opcode)
1227 struct rx_header *rxh;
1229 if (length <= (int)sizeof(struct rx_header))
1230 return;
1232 rxh = (struct rx_header *) bp;
1235 * Print out the afs call we're invoking. The table used here was
1236 * gleaned from fsint/afscbint.xg
1239 printf(" cb reply %s", tok2str(cb_req, "op#%d", opcode));
1241 bp += sizeof(struct rx_header);
1244 * If it was a data packet, interpret the response.
1247 if (rxh->type == RX_PACKET_TYPE_DATA)
1248 switch (opcode) {
1249 case 213: /* InitCallBackState3 */
1250 AFSUUIDOUT();
1251 break;
1252 default:
1255 else {
1257 * Otherwise, just print out the return code
1259 printf(" errcode");
1260 INTOUT();
1263 return;
1265 trunc:
1266 printf(" [|cb]");
1270 * Handle calls to the AFS protection database server
1273 static void
1274 prot_print(register const u_char *bp, int length)
1276 unsigned long i;
1277 int pt_op;
1279 if (length <= (int)sizeof(struct rx_header))
1280 return;
1282 if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
1283 goto trunc;
1287 * Print out the afs call we're invoking. The table used here was
1288 * gleaned from ptserver/ptint.xg
1291 pt_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
1293 printf(" pt");
1295 if (is_ubik(pt_op)) {
1296 ubik_print(bp);
1297 return;
1300 printf(" call %s", tok2str(pt_req, "op#%d", pt_op));
1303 * Decode some of the arguments to the PT calls
1306 bp += sizeof(struct rx_header) + 4;
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 */
1342 unsigned long j;
1343 TCHECK2(bp[0], 4);
1344 j = EXTRACT_32BITS(bp);
1345 bp += sizeof(int32_t);
1348 * Who designed this chicken-shit protocol?
1350 * Each character is stored as a 32-bit
1351 * integer!
1354 for (i = 0; i < j; i++) {
1355 VECOUT(PRNAMEMAX);
1357 if (j == 0)
1358 printf(" <none!>");
1360 break;
1361 case 505: /* Id to name */
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!>");
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:
1406 return;
1408 trunc:
1409 printf(" [|pt]");
1413 * Handle replies to the AFS protection service
1416 static void
1417 prot_reply_print(register const u_char *bp, int length, int32_t opcode)
1419 struct rx_header *rxh;
1420 unsigned long i;
1422 if (length < (int)sizeof(struct rx_header))
1423 return;
1425 rxh = (struct rx_header *) bp;
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.
1433 printf(" pt");
1435 if (is_ubik(opcode)) {
1436 ubik_reply_print(bp, length, opcode);
1437 return;
1440 printf(" reply %s", tok2str(pt_req, "op#%d", opcode));
1442 bp += sizeof(struct rx_header);
1445 * If it was a data packet, interpret the response
1448 if (rxh->type == RX_PACKET_TYPE_DATA)
1449 switch (opcode) {
1450 case 504: /* Name to ID */
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!>");
1462 break;
1463 case 505: /* ID to name */
1465 unsigned long j;
1466 TCHECK2(bp[0], 4);
1467 j = EXTRACT_32BITS(bp);
1468 bp += sizeof(int32_t);
1471 * Who designed this chicken-shit protocol?
1473 * Each character is stored as a 32-bit
1474 * integer!
1477 for (i = 0; i < j; i++) {
1478 VECOUT(PRNAMEMAX);
1480 if (j == 0)
1481 printf(" <none!>");
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 */
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();
1497 if (j == 0)
1498 printf(" <none!>");
1500 break;
1501 case 510: /* List max */
1502 printf(" maxuid");
1503 INTOUT();
1504 printf(" maxgid");
1505 INTOUT();
1506 break;
1507 default:
1510 else {
1512 * Otherwise, just print out the return code
1514 printf(" errcode");
1515 INTOUT();
1518 return;
1520 trunc:
1521 printf(" [|pt]");
1525 * Handle calls to the AFS volume location database service
1528 static void
1529 vldb_print(register const u_char *bp, int length)
1531 int vldb_op;
1532 unsigned long i;
1534 if (length <= (int)sizeof(struct rx_header))
1535 return;
1537 if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
1538 goto trunc;
1542 * Print out the afs call we're invoking. The table used here was
1543 * gleaned from vlserver/vldbint.xg
1546 vldb_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
1548 printf(" vldb");
1550 if (is_ubik(vldb_op)) {
1551 ubik_print(bp);
1552 return;
1554 printf(" call %s", tok2str(vldb_req, "op#%d", vldb_op));
1557 * Decode some of the arguments to the VLDB calls
1560 bp += sizeof(struct rx_header) + 4;
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:
1611 return;
1613 trunc:
1614 printf(" [|vldb]");
1618 * Handle replies to the AFS volume location database service
1621 static void
1622 vldb_reply_print(register const u_char *bp, int length, int32_t opcode)
1624 struct rx_header *rxh;
1625 unsigned long i;
1627 if (length < (int)sizeof(struct rx_header))
1628 return;
1630 rxh = (struct rx_header *) bp;
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.
1638 printf(" vldb");
1640 if (is_ubik(opcode)) {
1641 ubik_reply_print(bp, length, opcode);
1642 return;
1645 printf(" reply %s", tok2str(vldb_req, "op#%d", opcode));
1647 bp += sizeof(struct rx_header);
1650 * If it was a data packet, interpret the response
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);
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);
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();
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);
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);
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();
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;
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);
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();
1786 default:
1790 else {
1792 * Otherwise, just print out the return code
1794 printf(" errcode");
1795 INTOUT();
1798 return;
1800 trunc:
1801 printf(" [|vldb]");
1805 * Handle calls to the AFS Kerberos Authentication service
1808 static void
1809 kauth_print(register const u_char *bp, int length)
1811 int kauth_op;
1813 if (length <= (int)sizeof(struct rx_header))
1814 return;
1816 if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
1817 goto trunc;
1821 * Print out the afs call we're invoking. The table used here was
1822 * gleaned from kauth/kauth.rg
1825 kauth_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
1827 printf(" kauth");
1829 if (is_ubik(kauth_op)) {
1830 ubik_print(bp);
1831 return;
1835 printf(" call %s", tok2str(kauth_req, "op#%d", kauth_op));
1838 * Decode some of the arguments to the KA calls
1841 bp += sizeof(struct rx_header) + 4;
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 */
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;
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:
1891 return;
1893 trunc:
1894 printf(" [|kauth]");
1898 * Handle replies to the AFS Kerberos Authentication Service
1901 static void
1902 kauth_reply_print(register const u_char *bp, int length, int32_t opcode)
1904 struct rx_header *rxh;
1906 if (length <= (int)sizeof(struct rx_header))
1907 return;
1909 rxh = (struct rx_header *) bp;
1912 * Print out the afs call we're invoking. The table used here was
1913 * gleaned from kauth/kauth.rg
1916 printf(" kauth");
1918 if (is_ubik(opcode)) {
1919 ubik_reply_print(bp, length, opcode);
1920 return;
1923 printf(" reply %s", tok2str(kauth_req, "op#%d", opcode));
1925 bp += sizeof(struct rx_header);
1928 * If it was a data packet, interpret the response.
1931 if (rxh->type == RX_PACKET_TYPE_DATA)
1932 /* Well, no, not really. Leave this for later */
1934 else {
1936 * Otherwise, just print out the return code
1938 printf(" errcode");
1939 INTOUT();
1942 return;
1944 trunc:
1945 printf(" [|kauth]");
1949 * Handle calls to the AFS Volume location service
1952 static void
1953 vol_print(register const u_char *bp, int length)
1955 int vol_op;
1957 if (length <= (int)sizeof(struct rx_header))
1958 return;
1960 if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
1961 goto trunc;
1965 * Print out the afs call we're invoking. The table used here was
1966 * gleaned from volser/volint.xg
1969 vol_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
1971 printf(" vol call %s", tok2str(vol_req, "op#%d", vol_op));
1973 bp += sizeof(struct rx_header) + 4;
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();
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(",");
2128 if (j == 0)
2129 printf(" <none!>");
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:
2143 return;
2145 trunc:
2146 printf(" [|vol]");
2150 * Handle replies to the AFS Volume Service
2153 static void
2154 vol_reply_print(register const u_char *bp, int length, int32_t opcode)
2156 struct rx_header *rxh;
2158 if (length <= (int)sizeof(struct rx_header))
2159 return;
2161 rxh = (struct rx_header *) bp;
2164 * Print out the afs call we're invoking. The table used here was
2165 * gleaned from volser/volint.xg
2168 printf(" vol reply %s", tok2str(vol_req, "op#%d", opcode));
2170 bp += sizeof(struct rx_header);
2173 * If it was a data packet, interpret the response.
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 */
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(",");
2260 if (j == 0)
2261 printf(" <none!>");
2263 break;
2266 default:
2269 } else {
2271 * Otherwise, just print out the return code
2273 printf(" errcode");
2274 INTOUT();
2277 return;
2279 trunc:
2280 printf(" [|vol]");
2284 * Handle calls to the AFS BOS service
2287 static void
2288 bos_print(register const u_char *bp, int length)
2290 int bos_op;
2292 if (length <= (int)sizeof(struct rx_header))
2293 return;
2295 if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
2296 goto trunc;
2300 * Print out the afs call we're invoking. The table used here was
2301 * gleaned from bozo/bosint.xg
2304 bos_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
2306 printf(" bos call %s", tok2str(bos_req, "op#%d", bos_op));
2309 * Decode some of the arguments to the BOS calls
2312 bp += sizeof(struct rx_header) + 4;
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:
2368 return;
2370 trunc:
2371 printf(" [|bos]");
2375 * Handle replies to the AFS BOS Service
2378 static void
2379 bos_reply_print(register const u_char *bp, int length, int32_t opcode)
2381 struct rx_header *rxh;
2383 if (length <= (int)sizeof(struct rx_header))
2384 return;
2386 rxh = (struct rx_header *) bp;
2389 * Print out the afs call we're invoking. The table used here was
2390 * gleaned from volser/volint.xg
2393 printf(" bos reply %s", tok2str(bos_req, "op#%d", opcode));
2395 bp += sizeof(struct rx_header);
2398 * If it was a data packet, interpret the response.
2401 if (rxh->type == RX_PACKET_TYPE_DATA)
2402 /* Well, no, not really. Leave this for later */
2404 else {
2406 * Otherwise, just print out the return code
2408 printf(" errcode");
2409 INTOUT();
2412 return;
2414 trunc:
2415 printf(" [|bos]");
2419 * Check to see if this is a Ubik opcode.
2422 static int
2423 is_ubik(u_int32_t opcode)
2425 if ((opcode >= VOTE_LOW && opcode <= VOTE_HIGH) ||
2426 (opcode >= DISK_LOW && opcode <= DISK_HIGH))
2427 return(1);
2428 else
2429 return(0);
2433 * Handle Ubik opcodes to any one of the replicated database services
2436 static void
2437 ubik_print(register const u_char *bp)
2439 int ubik_op;
2440 int32_t temp;
2443 * Print out the afs call we're invoking. The table used here was
2444 * gleaned from ubik/ubik_int.xg
2447 ubik_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
2449 printf(" ubik call %s", tok2str(ubik_req, "op#%d", ubik_op));
2452 * Decode some of the arguments to the Ubik calls
2455 bp += sizeof(struct rx_header) + 4;
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:
2535 return;
2537 trunc:
2538 printf(" [|ubik]");
2542 * Handle Ubik replies to any one of the replicated database services
2545 static void
2546 ubik_reply_print(register const u_char *bp, int length, int32_t opcode)
2548 struct rx_header *rxh;
2550 if (length < (int)sizeof(struct rx_header))
2551 return;
2553 rxh = (struct rx_header *) bp;
2556 * Print out the ubik call we're invoking. This table was gleaned
2557 * from ubik/ubik_int.xg
2560 printf(" ubik reply %s", tok2str(ubik_req, "op#%d", opcode));
2562 bp += sizeof(struct rx_header);
2565 * If it was a data packet, print out the arguments to the Ubik calls
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:
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.
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();
2598 return;
2600 trunc:
2601 printf(" [|ubik]");
2605 * Handle RX ACK packets.
2608 static void
2609 rx_ack_print(register const u_char *bp, int length)
2611 struct rx_ackPacket *rxa;
2612 int i, start, last;
2613 u_int32_t firstPacket;
2615 if (length < (int)sizeof(struct rx_header))
2616 return;
2618 bp += sizeof(struct rx_header);
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.
2628 TCHECK2(bp[0], sizeof(struct rx_ackPacket) - RX_MAXACKS);
2630 rxa = (struct rx_ackPacket *) bp;
2631 bp += (sizeof(struct rx_ackPacket) - RX_MAXACKS);
2634 * Print out a few useful things from the ack packet structure
2637 if (vflag > 2)
2638 printf(" bufspace %d maxskew %d",
2639 (int) EXTRACT_16BITS(&rxa->bufferSpace),
2640 (int) EXTRACT_16BITS(&rxa->maxSkew));
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));
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.
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.
2666 if (rxa->nAcks != 0) {
2668 TCHECK2(bp[0], rxa->nAcks);
2671 * Sigh, this is gross, but it seems to work to collapse
2672 * ranges correctly.
2675 for (i = 0, start = last = -2; i < rxa->nAcks; i++)
2676 if (rxa->acks[i] == RX_ACK_TYPE_ACK) {
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.
2685 if (last == -2) {
2686 printf(" acked %d",
2687 firstPacket + i);
2688 start = i;
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.
2700 else if (last != i - 1) {
2701 printf(",%d", firstPacket + i);
2702 start = i;
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.
2712 last = i;
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.
2726 } else if (last == i - 1 && start != last)
2727 printf("-%d", firstPacket + i - 1);
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).
2740 if (last == i - 1 && start != last)
2741 printf("-%d", firstPacket + i - 1);
2744 * Same as above, just without comments
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;
2757 last = i;
2758 } else if (last == i - 1 && start != last)
2759 printf("-%d", firstPacket + i - 1);
2761 if (last == i - 1 && start != last)
2762 printf("-%d", firstPacket + i - 1);
2764 bp += rxa->nAcks;
2769 * These are optional fields; depending on your version of AFS,
2770 * you may or may not see them
2773 #define TRUNCRET(n) if (snapend - bp + 1 <= n) return;
2775 if (vflag > 1) {
2776 TRUNCRET(4);
2777 printf(" ifmtu");
2778 INTOUT();
2780 TRUNCRET(4);
2781 printf(" maxmtu");
2782 INTOUT();
2784 TRUNCRET(4);
2785 printf(" rwind");
2786 INTOUT();
2788 TRUNCRET(4);
2789 printf(" maxpackets");
2790 INTOUT();
2793 return;
2795 trunc:
2796 printf(" [|ack]");
2798 #undef TRUNCRET