156893Sfenner/*
298524Sfenner * Copyright: (c) 2000 United States Government as represented by the
398524Sfenner *	Secretary of the Navy. All rights reserved.
498524Sfenner *
598524Sfenner * Redistribution and use in source and binary forms, with or without
698524Sfenner * modification, are permitted provided that the following conditions
798524Sfenner * are met:
8127668Sbms *
998524Sfenner *   1. Redistributions of source code must retain the above copyright
1098524Sfenner *      notice, this list of conditions and the following disclaimer.
1198524Sfenner *   2. Redistributions in binary form must reproduce the above copyright
1298524Sfenner *      notice, this list of conditions and the following disclaimer in
1398524Sfenner *      the documentation and/or other materials provided with the
1498524Sfenner *      distribution.
1598524Sfenner *   3. The names of the authors may not be used to endorse or promote
1698524Sfenner *      products derived from this software without specific prior
1798524Sfenner *      written permission.
18127668Sbms *
1998524Sfenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2098524Sfenner * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2198524Sfenner * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2298524Sfenner */
2398524Sfenner/*
2456893Sfenner * This code unmangles RX packets.  RX is the mutant form of RPC that AFS
2556893Sfenner * uses to communicate between clients and servers.
2656893Sfenner *
2756893Sfenner * In this code, I mainly concern myself with decoding the AFS calls, not
2856893Sfenner * with the guts of RX, per se.
2956893Sfenner *
3056893Sfenner * Bah.  If I never look at rx_packet.h again, it will be too soon.
3156893Sfenner *
3256893Sfenner * Ken Hornstein <kenh@cmf.nrl.navy.mil>
3356893Sfenner */
3456893Sfenner
3556893Sfenner#ifndef lint
36127668Sbmsstatic const char rcsid[] _U_ =
37214478Srpaulo    "@(#) $Header: /tcpdump/master/tcpdump/print-rx.c,v 1.42 2008-07-01 07:44:50 guy Exp $";
3856893Sfenner#endif
3956893Sfenner
4056893Sfenner#ifdef HAVE_CONFIG_H
4156893Sfenner#include "config.h"
4256893Sfenner#endif
4356893Sfenner
4456893Sfenner#include <stdio.h>
4575115Sfenner#include <stdlib.h>
4656893Sfenner#include <string.h>
47127668Sbms#include <tcpdump-stdinc.h>
4856893Sfenner
4956893Sfenner#include "interface.h"
5056893Sfenner#include "addrtoname.h"
5175115Sfenner#include "extract.h"
5256893Sfenner
5356893Sfenner#include "rx.h"
5456893Sfenner
5575115Sfenner#include "ip.h"
5675115Sfenner
5756893Sfennerstatic struct tok rx_types[] = {
5856893Sfenner	{ RX_PACKET_TYPE_DATA,		"data" },
5956893Sfenner	{ RX_PACKET_TYPE_ACK,		"ack" },
6056893Sfenner	{ RX_PACKET_TYPE_BUSY,		"busy" },
6156893Sfenner	{ RX_PACKET_TYPE_ABORT,		"abort" },
6256893Sfenner	{ RX_PACKET_TYPE_ACKALL,	"ackall" },
6356893Sfenner	{ RX_PACKET_TYPE_CHALLENGE,	"challenge" },
6456893Sfenner	{ RX_PACKET_TYPE_RESPONSE,	"response" },
6556893Sfenner	{ RX_PACKET_TYPE_DEBUG,		"debug" },
6656893Sfenner	{ RX_PACKET_TYPE_PARAMS,	"params" },
6756893Sfenner	{ RX_PACKET_TYPE_VERSION,	"version" },
6856893Sfenner	{ 0,				NULL },
6956893Sfenner};
7056893Sfenner
7198524Sfennerstatic struct double_tok {
7298524Sfenner	int flag;		/* Rx flag */
7398524Sfenner	int packetType;		/* Packet type */
74127668Sbms	const char *s;		/* Flag string */
7598524Sfenner} rx_flags[] = {
7698524Sfenner	{ RX_CLIENT_INITIATED,	0,			"client-init" },
7798524Sfenner	{ RX_REQUEST_ACK,	0,			"req-ack" },
7898524Sfenner	{ RX_LAST_PACKET,	0,			"last-pckt" },
7998524Sfenner	{ RX_MORE_PACKETS,	0,			"more-pckts" },
8098524Sfenner	{ RX_FREE_PACKET,	0,			"free-pckt" },
8198524Sfenner	{ RX_SLOW_START_OK,	RX_PACKET_TYPE_ACK,	"slow-start" },
8298524Sfenner	{ RX_JUMBO_PACKET,	RX_PACKET_TYPE_DATA,	"jumbogram" }
8356893Sfenner};
8456893Sfenner
8556893Sfennerstatic struct tok fs_req[] = {
8656893Sfenner	{ 130,		"fetch-data" },
8756893Sfenner	{ 131,		"fetch-acl" },
8856893Sfenner	{ 132,		"fetch-status" },
8956893Sfenner	{ 133,		"store-data" },
9056893Sfenner	{ 134,		"store-acl" },
9156893Sfenner	{ 135,		"store-status" },
9256893Sfenner	{ 136,		"remove-file" },
9356893Sfenner	{ 137,		"create-file" },
9456893Sfenner	{ 138,		"rename" },
9556893Sfenner	{ 139,		"symlink" },
9656893Sfenner	{ 140,		"link" },
9756893Sfenner	{ 141,		"makedir" },
9856893Sfenner	{ 142,		"rmdir" },
9956893Sfenner	{ 143,		"oldsetlock" },
10056893Sfenner	{ 144,		"oldextlock" },
10156893Sfenner	{ 145,		"oldrellock" },
10256893Sfenner	{ 146,		"get-stats" },
10356893Sfenner	{ 147,		"give-cbs" },
10456893Sfenner	{ 148,		"get-vlinfo" },
10556893Sfenner	{ 149,		"get-vlstats" },
10656893Sfenner	{ 150,		"set-vlstats" },
10756893Sfenner	{ 151,		"get-rootvl" },
10856893Sfenner	{ 152,		"check-token" },
10956893Sfenner	{ 153,		"get-time" },
11056893Sfenner	{ 154,		"nget-vlinfo" },
11156893Sfenner	{ 155,		"bulk-stat" },
11256893Sfenner	{ 156,		"setlock" },
11356893Sfenner	{ 157,		"extlock" },
11456893Sfenner	{ 158,		"rellock" },
11556893Sfenner	{ 159,		"xstat-ver" },
11656893Sfenner	{ 160,		"get-xstat" },
11756893Sfenner	{ 161,		"dfs-lookup" },
11856893Sfenner	{ 162,		"dfs-flushcps" },
11956893Sfenner	{ 163,		"dfs-symlink" },
12098524Sfenner	{ 220,		"residency" },
121190207Srpaulo	{ 65536,        "inline-bulk-status" },
122190207Srpaulo	{ 65537,        "fetch-data-64" },
123190207Srpaulo	{ 65538,        "store-data-64" },
124190207Srpaulo	{ 65539,        "give-up-all-cbs" },
125190207Srpaulo	{ 65540,        "get-caps" },
126190207Srpaulo	{ 65541,        "cb-rx-conn-addr" },
12756893Sfenner	{ 0,		NULL },
12856893Sfenner};
12956893Sfenner
13056893Sfennerstatic struct tok cb_req[] = {
13156893Sfenner	{ 204,		"callback" },
13256893Sfenner	{ 205,		"initcb" },
13356893Sfenner	{ 206,		"probe" },
13456893Sfenner	{ 207,		"getlock" },
13556893Sfenner	{ 208,		"getce" },
13656893Sfenner	{ 209,		"xstatver" },
13756893Sfenner	{ 210,		"getxstat" },
13856893Sfenner	{ 211,		"initcb2" },
13956893Sfenner	{ 212,		"whoareyou" },
14056893Sfenner	{ 213,		"initcb3" },
14156893Sfenner	{ 214,		"probeuuid" },
14298524Sfenner	{ 215,		"getsrvprefs" },
14398524Sfenner	{ 216,		"getcellservdb" },
14498524Sfenner	{ 217,		"getlocalcell" },
14598524Sfenner	{ 218,		"getcacheconf" },
146190207Srpaulo	{ 65536,        "getce64" },
147190207Srpaulo	{ 65537,        "getcellbynum" },
148190207Srpaulo	{ 65538,        "tellmeaboutyourself" },
14956893Sfenner	{ 0,		NULL },
15056893Sfenner};
15156893Sfenner
15256893Sfennerstatic struct tok pt_req[] = {
15356893Sfenner	{ 500,		"new-user" },
15456893Sfenner	{ 501,		"where-is-it" },
15556893Sfenner	{ 502,		"dump-entry" },
15656893Sfenner	{ 503,		"add-to-group" },
15756893Sfenner	{ 504,		"name-to-id" },
15856893Sfenner	{ 505,		"id-to-name" },
15956893Sfenner	{ 506,		"delete" },
16056893Sfenner	{ 507,		"remove-from-group" },
16156893Sfenner	{ 508,		"get-cps" },
16256893Sfenner	{ 509,		"new-entry" },
16356893Sfenner	{ 510,		"list-max" },
16456893Sfenner	{ 511,		"set-max" },
16556893Sfenner	{ 512,		"list-entry" },
16656893Sfenner	{ 513,		"change-entry" },
16756893Sfenner	{ 514,		"list-elements" },
16856893Sfenner	{ 515,		"same-mbr-of" },
16956893Sfenner	{ 516,		"set-fld-sentry" },
17056893Sfenner	{ 517,		"list-owned" },
17156893Sfenner	{ 518,		"get-cps2" },
17256893Sfenner	{ 519,		"get-host-cps" },
17356893Sfenner	{ 520,		"update-entry" },
17498524Sfenner	{ 521,		"list-entries" },
175190207Srpaulo	{ 530,		"list-super-groups" },
17656893Sfenner	{ 0,		NULL },
17756893Sfenner};
17856893Sfenner
17956893Sfennerstatic struct tok vldb_req[] = {
18056893Sfenner	{ 501,		"create-entry" },
18156893Sfenner	{ 502,		"delete-entry" },
18256893Sfenner	{ 503,		"get-entry-by-id" },
18356893Sfenner	{ 504,		"get-entry-by-name" },
18456893Sfenner	{ 505,		"get-new-volume-id" },
18556893Sfenner	{ 506,		"replace-entry" },
18656893Sfenner	{ 507,		"update-entry" },
18756893Sfenner	{ 508,		"setlock" },
18856893Sfenner	{ 509,		"releaselock" },
18956893Sfenner	{ 510,		"list-entry" },
19056893Sfenner	{ 511,		"list-attrib" },
19156893Sfenner	{ 512,		"linked-list" },
19256893Sfenner	{ 513,		"get-stats" },
19356893Sfenner	{ 514,		"probe" },
19456893Sfenner	{ 515,		"get-addrs" },
19556893Sfenner	{ 516,		"change-addr" },
19656893Sfenner	{ 517,		"create-entry-n" },
19756893Sfenner	{ 518,		"get-entry-by-id-n" },
19856893Sfenner	{ 519,		"get-entry-by-name-n" },
19956893Sfenner	{ 520,		"replace-entry-n" },
20056893Sfenner	{ 521,		"list-entry-n" },
20156893Sfenner	{ 522,		"list-attrib-n" },
20256893Sfenner	{ 523,		"linked-list-n" },
20356893Sfenner	{ 524,		"update-entry-by-name" },
20456893Sfenner	{ 525,		"create-entry-u" },
20556893Sfenner	{ 526,		"get-entry-by-id-u" },
20656893Sfenner	{ 527,		"get-entry-by-name-u" },
20756893Sfenner	{ 528,		"replace-entry-u" },
20856893Sfenner	{ 529,		"list-entry-u" },
20956893Sfenner	{ 530,		"list-attrib-u" },
21056893Sfenner	{ 531,		"linked-list-u" },
21156893Sfenner	{ 532,		"regaddr" },
21256893Sfenner	{ 533,		"get-addrs-u" },
21398524Sfenner	{ 534,		"list-attrib-n2" },
21456893Sfenner	{ 0,		NULL },
21556893Sfenner};
21656893Sfenner
21756893Sfennerstatic struct tok kauth_req[] = {
21856893Sfenner	{ 1,		"auth-old" },
21956893Sfenner	{ 21,		"authenticate" },
22056893Sfenner	{ 22,		"authenticate-v2" },
22156893Sfenner	{ 2,		"change-pw" },
22256893Sfenner	{ 3,		"get-ticket-old" },
22356893Sfenner	{ 23,		"get-ticket" },
22456893Sfenner	{ 4,		"set-pw" },
22556893Sfenner	{ 5,		"set-fields" },
22656893Sfenner	{ 6,		"create-user" },
22756893Sfenner	{ 7,		"delete-user" },
22856893Sfenner	{ 8,		"get-entry" },
22956893Sfenner	{ 9,		"list-entry" },
23056893Sfenner	{ 10,		"get-stats" },
23156893Sfenner	{ 11,		"debug" },
23256893Sfenner	{ 12,		"get-pw" },
23356893Sfenner	{ 13,		"get-random-key" },
23456893Sfenner	{ 14,		"unlock" },
23556893Sfenner	{ 15,		"lock-status" },
23656893Sfenner	{ 0,		NULL },
23756893Sfenner};
23856893Sfenner
23956893Sfennerstatic struct tok vol_req[] = {
24056893Sfenner	{ 100,		"create-volume" },
24156893Sfenner	{ 101,		"delete-volume" },
24256893Sfenner	{ 102,		"restore" },
24356893Sfenner	{ 103,		"forward" },
24456893Sfenner	{ 104,		"end-trans" },
24556893Sfenner	{ 105,		"clone" },
24656893Sfenner	{ 106,		"set-flags" },
24756893Sfenner	{ 107,		"get-flags" },
24856893Sfenner	{ 108,		"trans-create" },
24956893Sfenner	{ 109,		"dump" },
25056893Sfenner	{ 110,		"get-nth-volume" },
25156893Sfenner	{ 111,		"set-forwarding" },
25256893Sfenner	{ 112,		"get-name" },
25356893Sfenner	{ 113,		"get-status" },
25456893Sfenner	{ 114,		"sig-restore" },
25556893Sfenner	{ 115,		"list-partitions" },
25656893Sfenner	{ 116,		"list-volumes" },
25756893Sfenner	{ 117,		"set-id-types" },
25856893Sfenner	{ 118,		"monitor" },
25956893Sfenner	{ 119,		"partition-info" },
26056893Sfenner	{ 120,		"reclone" },
26156893Sfenner	{ 121,		"list-one-volume" },
26256893Sfenner	{ 122,		"nuke" },
26356893Sfenner	{ 123,		"set-date" },
26456893Sfenner	{ 124,		"x-list-volumes" },
26556893Sfenner	{ 125,		"x-list-one-volume" },
26656893Sfenner	{ 126,		"set-info" },
26756893Sfenner	{ 127,		"x-list-partitions" },
26856893Sfenner	{ 128,		"forward-multiple" },
269190207Srpaulo	{ 65536,	"convert-ro" },
270190207Srpaulo	{ 65537,	"get-size" },
271190207Srpaulo	{ 65538,	"dump-v2" },
27256893Sfenner	{ 0,		NULL },
27356893Sfenner};
27456893Sfenner
27556893Sfennerstatic struct tok bos_req[] = {
27656893Sfenner	{ 80,		"create-bnode" },
27756893Sfenner	{ 81,		"delete-bnode" },
27856893Sfenner	{ 82,		"set-status" },
27956893Sfenner	{ 83,		"get-status" },
28056893Sfenner	{ 84,		"enumerate-instance" },
28156893Sfenner	{ 85,		"get-instance-info" },
28256893Sfenner	{ 86,		"get-instance-parm" },
28356893Sfenner	{ 87,		"add-superuser" },
28456893Sfenner	{ 88,		"delete-superuser" },
28556893Sfenner	{ 89,		"list-superusers" },
28656893Sfenner	{ 90,		"list-keys" },
28756893Sfenner	{ 91,		"add-key" },
28856893Sfenner	{ 92,		"delete-key" },
28956893Sfenner	{ 93,		"set-cell-name" },
29056893Sfenner	{ 94,		"get-cell-name" },
29156893Sfenner	{ 95,		"get-cell-host" },
29256893Sfenner	{ 96,		"add-cell-host" },
29356893Sfenner	{ 97,		"delete-cell-host" },
29456893Sfenner	{ 98,		"set-t-status" },
29556893Sfenner	{ 99,		"shutdown-all" },
29656893Sfenner	{ 100,		"restart-all" },
29756893Sfenner	{ 101,		"startup-all" },
29856893Sfenner	{ 102,		"set-noauth-flag" },
29956893Sfenner	{ 103,		"re-bozo" },
30056893Sfenner	{ 104,		"restart" },
30156893Sfenner	{ 105,		"start-bozo-install" },
30256893Sfenner	{ 106,		"uninstall" },
30356893Sfenner	{ 107,		"get-dates" },
30456893Sfenner	{ 108,		"exec" },
30556893Sfenner	{ 109,		"prune" },
30656893Sfenner	{ 110,		"set-restart-time" },
30756893Sfenner	{ 111,		"get-restart-time" },
30856893Sfenner	{ 112,		"start-bozo-log" },
30956893Sfenner	{ 113,		"wait-all" },
31056893Sfenner	{ 114,		"get-instance-strings" },
31198524Sfenner	{ 115,		"get-restricted" },
31298524Sfenner	{ 116,		"set-restricted" },
31356893Sfenner	{ 0,		NULL },
31456893Sfenner};
31556893Sfenner
31656893Sfennerstatic struct tok ubik_req[] = {
31756893Sfenner	{ 10000,	"vote-beacon" },
31856893Sfenner	{ 10001,	"vote-debug-old" },
31956893Sfenner	{ 10002,	"vote-sdebug-old" },
32056893Sfenner	{ 10003,	"vote-getsyncsite" },
32156893Sfenner	{ 10004,	"vote-debug" },
32256893Sfenner	{ 10005,	"vote-sdebug" },
323190207Srpaulo	{ 10006,	"vote-xdebug" },
324190207Srpaulo	{ 10007,	"vote-xsdebug" },
32556893Sfenner	{ 20000,	"disk-begin" },
32656893Sfenner	{ 20001,	"disk-commit" },
32756893Sfenner	{ 20002,	"disk-lock" },
32856893Sfenner	{ 20003,	"disk-write" },
32956893Sfenner	{ 20004,	"disk-getversion" },
33056893Sfenner	{ 20005,	"disk-getfile" },
33156893Sfenner	{ 20006,	"disk-sendfile" },
33256893Sfenner	{ 20007,	"disk-abort" },
33356893Sfenner	{ 20008,	"disk-releaselocks" },
33456893Sfenner	{ 20009,	"disk-truncate" },
33556893Sfenner	{ 20010,	"disk-probe" },
33656893Sfenner	{ 20011,	"disk-writev" },
33756893Sfenner	{ 20012,	"disk-interfaceaddr" },
33856893Sfenner	{ 20013,	"disk-setversion" },
33956893Sfenner	{ 0,		NULL },
34056893Sfenner};
34156893Sfenner
34256893Sfenner#define VOTE_LOW	10000
343190207Srpaulo#define VOTE_HIGH	10007
34456893Sfenner#define DISK_LOW	20000
34556893Sfenner#define DISK_HIGH	20013
34656893Sfenner
34756893Sfennerstatic struct tok cb_types[] = {
34856893Sfenner	{ 1,		"exclusive" },
34956893Sfenner	{ 2,		"shared" },
35056893Sfenner	{ 3,		"dropped" },
35156893Sfenner	{ 0,		NULL },
35256893Sfenner};
35356893Sfenner
35456893Sfennerstatic struct tok ubik_lock_types[] = {
35556893Sfenner	{ 1,		"read" },
35656893Sfenner	{ 2,		"write" },
35756893Sfenner	{ 3,		"wait" },
35856893Sfenner	{ 0,		NULL },
35956893Sfenner};
36056893Sfenner
361127668Sbmsstatic const char *voltype[] = { "read-write", "read-only", "backup" };
36256893Sfenner
36375115Sfennerstatic struct tok afs_fs_errors[] = {
36475115Sfenner	{ 101,		"salvage volume" },
36575115Sfenner	{ 102, 		"no such vnode" },
36675115Sfenner	{ 103, 		"no such volume" },
36775115Sfenner	{ 104, 		"volume exist" },
36875115Sfenner	{ 105, 		"no service" },
36975115Sfenner	{ 106, 		"volume offline" },
37075115Sfenner	{ 107, 		"voline online" },
37175115Sfenner	{ 108, 		"diskfull" },
37275115Sfenner	{ 109, 		"diskquota exceeded" },
37375115Sfenner	{ 110, 		"volume busy" },
37475115Sfenner	{ 111, 		"volume moved" },
37575115Sfenner	{ 112, 		"AFS IO error" },
37675115Sfenner	{ -100,		"restarting fileserver" },
37775115Sfenner	{ 0,		NULL }
37875115Sfenner};
37975115Sfenner
38056893Sfenner/*
38175115Sfenner * Reasons for acknowledging a packet
38275115Sfenner */
38375115Sfenner
38475115Sfennerstatic struct tok rx_ack_reasons[] = {
38575115Sfenner	{ 1,		"ack requested" },
38675115Sfenner	{ 2,		"duplicate packet" },
38775115Sfenner	{ 3,		"out of sequence" },
38875115Sfenner	{ 4,		"exceeds window" },
38975115Sfenner	{ 5,		"no buffer space" },
39075115Sfenner	{ 6,		"ping" },
39175115Sfenner	{ 7,		"ping response" },
39275115Sfenner	{ 8,		"delay" },
393127668Sbms	{ 9,		"idle" },
39475115Sfenner	{ 0,		NULL },
39575115Sfenner};
39675115Sfenner
39775115Sfenner/*
39856893Sfenner * Cache entries we keep around so we can figure out the RX opcode
39956893Sfenner * numbers for replies.  This allows us to make sense of RX reply packets.
40056893Sfenner */
40156893Sfenner
40256893Sfennerstruct rx_cache_entry {
40356893Sfenner	u_int32_t	callnum;	/* Call number (net order) */
40456893Sfenner	struct in_addr	client;		/* client IP address (net order) */
40556893Sfenner	struct in_addr	server;		/* server IP address (net order) */
40656893Sfenner	int		dport;		/* server port (host order) */
40756893Sfenner	u_short		serviceId;	/* Service identifier (net order) */
40856893Sfenner	u_int32_t	opcode;		/* RX opcode (host order) */
40956893Sfenner};
41056893Sfenner
41156893Sfenner#define RX_CACHE_SIZE	64
41256893Sfenner
41356893Sfennerstatic struct rx_cache_entry	rx_cache[RX_CACHE_SIZE];
41456893Sfenner
41556893Sfennerstatic int	rx_cache_next = 0;
41656893Sfennerstatic int	rx_cache_hint = 0;
417127668Sbmsstatic void	rx_cache_insert(const u_char *, const struct ip *, int);
41856893Sfennerstatic int	rx_cache_find(const struct rx_header *, const struct ip *,
41956893Sfenner			      int, int32_t *);
42056893Sfenner
42156893Sfennerstatic void fs_print(const u_char *, int);
42256893Sfennerstatic void fs_reply_print(const u_char *, int, int32_t);
42375115Sfennerstatic void acl_print(u_char *, int, u_char *);
42456893Sfennerstatic void cb_print(const u_char *, int);
42556893Sfennerstatic void cb_reply_print(const u_char *, int, int32_t);
42656893Sfennerstatic void prot_print(const u_char *, int);
42756893Sfennerstatic void prot_reply_print(const u_char *, int, int32_t);
42856893Sfennerstatic void vldb_print(const u_char *, int);
42956893Sfennerstatic void vldb_reply_print(const u_char *, int, int32_t);
43056893Sfennerstatic void kauth_print(const u_char *, int);
43156893Sfennerstatic void kauth_reply_print(const u_char *, int, int32_t);
43256893Sfennerstatic void vol_print(const u_char *, int);
43356893Sfennerstatic void vol_reply_print(const u_char *, int, int32_t);
43456893Sfennerstatic void bos_print(const u_char *, int);
43556893Sfennerstatic void bos_reply_print(const u_char *, int, int32_t);
436127668Sbmsstatic void ubik_print(const u_char *);
43756893Sfennerstatic void ubik_reply_print(const u_char *, int, int32_t);
43856893Sfenner
43975115Sfennerstatic void rx_ack_print(const u_char *, int);
44075115Sfenner
44156893Sfennerstatic int is_ubik(u_int32_t);
44256893Sfenner
44356893Sfenner/*
44456893Sfenner * Handle the rx-level packet.  See if we know what port it's going to so
44556893Sfenner * we can peek at the afs call inside
44656893Sfenner */
44756893Sfenner
44856893Sfennervoid
44956893Sfennerrx_print(register const u_char *bp, int length, int sport, int dport,
45056893Sfenner	 u_char *bp2)
45156893Sfenner{
45256893Sfenner	register struct rx_header *rxh;
45356893Sfenner	int i;
45456893Sfenner	int32_t opcode;
45556893Sfenner
456127668Sbms	if (snapend - bp < (int)sizeof (struct rx_header)) {
45756893Sfenner		printf(" [|rx] (%d)", length);
45856893Sfenner		return;
45956893Sfenner	}
46056893Sfenner
46156893Sfenner	rxh = (struct rx_header *) bp;
46256893Sfenner
46356893Sfenner	printf(" rx %s", tok2str(rx_types, "type %d", rxh->type));
46456893Sfenner
46575115Sfenner	if (vflag) {
46656893Sfenner		int firstflag = 0;
46775115Sfenner
46875115Sfenner		if (vflag > 1)
46975115Sfenner			printf(" cid %08x call# %d",
47075115Sfenner			       (int) EXTRACT_32BITS(&rxh->cid),
47175115Sfenner			       (int) EXTRACT_32BITS(&rxh->callNumber));
47275115Sfenner
47375115Sfenner		printf(" seq %d ser %d",
47475115Sfenner		       (int) EXTRACT_32BITS(&rxh->seq),
47575115Sfenner		       (int) EXTRACT_32BITS(&rxh->serial));
47675115Sfenner
47756893Sfenner		if (vflag > 2)
47856893Sfenner			printf(" secindex %d serviceid %hu",
47956893Sfenner				(int) rxh->securityIndex,
48075115Sfenner				EXTRACT_16BITS(&rxh->serviceId));
48175115Sfenner
48275115Sfenner		if (vflag > 1)
48375115Sfenner			for (i = 0; i < NUM_RX_FLAGS; i++) {
48498524Sfenner				if (rxh->flags & rx_flags[i].flag &&
48598524Sfenner				    (!rx_flags[i].packetType ||
48698524Sfenner				     rxh->type == rx_flags[i].packetType)) {
48775115Sfenner					if (!firstflag) {
48875115Sfenner						firstflag = 1;
48975115Sfenner						printf(" ");
49075115Sfenner					} else {
49175115Sfenner						printf(",");
49275115Sfenner					}
49375115Sfenner					printf("<%s>", rx_flags[i].s);
49456893Sfenner				}
49556893Sfenner			}
49656893Sfenner	}
49756893Sfenner
49856893Sfenner	/*
49956893Sfenner	 * Try to handle AFS calls that we know about.  Check the destination
50056893Sfenner	 * port and make sure it's a data packet.  Also, make sure the
50156893Sfenner	 * seq number is 1 (because otherwise it's a continuation packet,
50256893Sfenner	 * and we can't interpret that).  Also, seems that reply packets
50356893Sfenner	 * do not have the client-init flag set, so we check for that
50456893Sfenner	 * as well.
50556893Sfenner	 */
50656893Sfenner
507127668Sbms	if (rxh->type == RX_PACKET_TYPE_DATA &&
50875115Sfenner	    EXTRACT_32BITS(&rxh->seq) == 1 &&
50956893Sfenner	    rxh->flags & RX_CLIENT_INITIATED) {
51056893Sfenner
51156893Sfenner		/*
51256893Sfenner		 * Insert this call into the call cache table, so we
51356893Sfenner		 * have a chance to print out replies
51456893Sfenner		 */
51556893Sfenner
516127668Sbms		rx_cache_insert(bp, (const struct ip *) bp2, dport);
51756893Sfenner
51856893Sfenner		switch (dport) {
51956893Sfenner			case FS_RX_PORT:	/* AFS file service */
52056893Sfenner				fs_print(bp, length);
52156893Sfenner				break;
52256893Sfenner			case CB_RX_PORT:	/* AFS callback service */
52356893Sfenner				cb_print(bp, length);
52456893Sfenner				break;
52556893Sfenner			case PROT_RX_PORT:	/* AFS protection service */
52656893Sfenner				prot_print(bp, length);
52756893Sfenner				break;
52856893Sfenner			case VLDB_RX_PORT:	/* AFS VLDB service */
52956893Sfenner				vldb_print(bp, length);
53056893Sfenner				break;
53156893Sfenner			case KAUTH_RX_PORT:	/* AFS Kerberos auth service */
53256893Sfenner				kauth_print(bp, length);
53356893Sfenner				break;
53456893Sfenner			case VOL_RX_PORT:	/* AFS Volume service */
53556893Sfenner				vol_print(bp, length);
53656893Sfenner				break;
53756893Sfenner			case BOS_RX_PORT:	/* AFS BOS service */
53856893Sfenner				bos_print(bp, length);
53956893Sfenner				break;
54056893Sfenner			default:
54156893Sfenner				;
54256893Sfenner		}
543127668Sbms
54456893Sfenner	/*
54556893Sfenner	 * If it's a reply (client-init is _not_ set, but seq is one)
54656893Sfenner	 * then look it up in the cache.  If we find it, call the reply
54756893Sfenner	 * printing functions  Note that we handle abort packets here,
54856893Sfenner	 * because printing out the return code can be useful at times.
54956893Sfenner	 */
55056893Sfenner
55156893Sfenner	} else if (((rxh->type == RX_PACKET_TYPE_DATA &&
55275115Sfenner					EXTRACT_32BITS(&rxh->seq) == 1) ||
55356893Sfenner		    rxh->type == RX_PACKET_TYPE_ABORT) &&
55456893Sfenner		   (rxh->flags & RX_CLIENT_INITIATED) == 0 &&
55556893Sfenner		   rx_cache_find(rxh, (const struct ip *) bp2,
55656893Sfenner				 sport, &opcode)) {
55756893Sfenner
55856893Sfenner		switch (sport) {
55956893Sfenner			case FS_RX_PORT:	/* AFS file service */
56056893Sfenner				fs_reply_print(bp, length, opcode);
56156893Sfenner				break;
56256893Sfenner			case CB_RX_PORT:	/* AFS callback service */
56356893Sfenner				cb_reply_print(bp, length, opcode);
56456893Sfenner				break;
56556893Sfenner			case PROT_RX_PORT:	/* AFS PT service */
56656893Sfenner				prot_reply_print(bp, length, opcode);
56756893Sfenner				break;
56856893Sfenner			case VLDB_RX_PORT:	/* AFS VLDB service */
56956893Sfenner				vldb_reply_print(bp, length, opcode);
57056893Sfenner				break;
57156893Sfenner			case KAUTH_RX_PORT:	/* AFS Kerberos auth service */
57256893Sfenner				kauth_reply_print(bp, length, opcode);
57356893Sfenner				break;
57456893Sfenner			case VOL_RX_PORT:	/* AFS Volume service */
57556893Sfenner				vol_reply_print(bp, length, opcode);
57656893Sfenner				break;
57756893Sfenner			case BOS_RX_PORT:	/* AFS BOS service */
57856893Sfenner				bos_reply_print(bp, length, opcode);
57956893Sfenner				break;
58056893Sfenner			default:
58156893Sfenner				;
58256893Sfenner		}
58356893Sfenner
58475115Sfenner	/*
58575115Sfenner	 * If it's an RX ack packet, then use the appropriate ack decoding
58675115Sfenner	 * function (there isn't any service-specific information in the
58775115Sfenner	 * ack packet, so we can use one for all AFS services)
58875115Sfenner	 */
58956893Sfenner
59075115Sfenner	} else if (rxh->type == RX_PACKET_TYPE_ACK)
59175115Sfenner		rx_ack_print(bp, length);
59275115Sfenner
59375115Sfenner
59456893Sfenner	printf(" (%d)", length);
59556893Sfenner}
59656893Sfenner
59756893Sfenner/*
59856893Sfenner * Insert an entry into the cache.  Taken from print-nfs.c
59956893Sfenner */
60056893Sfenner
60156893Sfennerstatic void
602127668Sbmsrx_cache_insert(const u_char *bp, const struct ip *ip, int dport)
60356893Sfenner{
60456893Sfenner	struct rx_cache_entry *rxent;
60556893Sfenner	const struct rx_header *rxh = (const struct rx_header *) bp;
60656893Sfenner
607127668Sbms	if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t)))
60856893Sfenner		return;
60956893Sfenner
61056893Sfenner	rxent = &rx_cache[rx_cache_next];
61156893Sfenner
61256893Sfenner	if (++rx_cache_next >= RX_CACHE_SIZE)
61356893Sfenner		rx_cache_next = 0;
614127668Sbms
61556893Sfenner	rxent->callnum = rxh->callNumber;
61656893Sfenner	rxent->client = ip->ip_src;
61756893Sfenner	rxent->server = ip->ip_dst;
61856893Sfenner	rxent->dport = dport;
61956893Sfenner	rxent->serviceId = rxh->serviceId;
62075115Sfenner	rxent->opcode = EXTRACT_32BITS(bp + sizeof(struct rx_header));
62156893Sfenner}
62256893Sfenner
62356893Sfenner/*
62456893Sfenner * Lookup an entry in the cache.  Also taken from print-nfs.c
62556893Sfenner *
62656893Sfenner * Note that because this is a reply, we're looking at the _source_
62756893Sfenner * port.
62856893Sfenner */
62956893Sfenner
63056893Sfennerstatic int
63156893Sfennerrx_cache_find(const struct rx_header *rxh, const struct ip *ip, int sport,
63256893Sfenner	      int32_t *opcode)
63356893Sfenner{
63456893Sfenner	int i;
63556893Sfenner	struct rx_cache_entry *rxent;
63656893Sfenner	u_int32_t clip = ip->ip_dst.s_addr;
63756893Sfenner	u_int32_t sip = ip->ip_src.s_addr;
63856893Sfenner
63956893Sfenner	/* Start the search where we last left off */
64056893Sfenner
64156893Sfenner	i = rx_cache_hint;
64256893Sfenner	do {
64356893Sfenner		rxent = &rx_cache[i];
64456893Sfenner		if (rxent->callnum == rxh->callNumber &&
64556893Sfenner		    rxent->client.s_addr == clip &&
646127668Sbms		    rxent->server.s_addr == sip &&
64756893Sfenner		    rxent->serviceId == rxh->serviceId &&
64856893Sfenner		    rxent->dport == sport) {
64956893Sfenner
65056893Sfenner			/* We got a match! */
65156893Sfenner
65256893Sfenner			rx_cache_hint = i;
65356893Sfenner			*opcode = rxent->opcode;
65456893Sfenner			return(1);
65556893Sfenner		}
65656893Sfenner		if (++i > RX_CACHE_SIZE)
65756893Sfenner			i = 0;
65856893Sfenner	} while (i != rx_cache_hint);
65956893Sfenner
66056893Sfenner	/* Our search failed */
66156893Sfenner	return(0);
66256893Sfenner}
66356893Sfenner
66456893Sfenner/*
66556893Sfenner * These extrememly grody macros handle the printing of various AFS stuff.
66656893Sfenner */
66756893Sfenner
66856893Sfenner#define FIDOUT() { unsigned long n1, n2, n3; \
66975115Sfenner			TCHECK2(bp[0], sizeof(int32_t) * 3); \
67075115Sfenner			n1 = EXTRACT_32BITS(bp); \
67156893Sfenner			bp += sizeof(int32_t); \
67275115Sfenner			n2 = EXTRACT_32BITS(bp); \
67356893Sfenner			bp += sizeof(int32_t); \
67475115Sfenner			n3 = EXTRACT_32BITS(bp); \
67556893Sfenner			bp += sizeof(int32_t); \
67656893Sfenner			printf(" fid %d/%d/%d", (int) n1, (int) n2, (int) n3); \
67756893Sfenner		}
67856893Sfenner
67980231Sfenner#define STROUT(MAX) { unsigned int i; \
68075115Sfenner			TCHECK2(bp[0], sizeof(int32_t)); \
68180231Sfenner			i = EXTRACT_32BITS(bp); \
68298524Sfenner			if (i > (MAX)) \
68380231Sfenner				goto trunc; \
68456893Sfenner			bp += sizeof(int32_t); \
68580231Sfenner			printf(" \""); \
68680231Sfenner			if (fn_printn(bp, i, snapend)) \
68780231Sfenner				goto trunc; \
68880231Sfenner			printf("\""); \
68956893Sfenner			bp += ((i + sizeof(int32_t) - 1) / sizeof(int32_t)) * sizeof(int32_t); \
69056893Sfenner		}
69156893Sfenner
69256893Sfenner#define INTOUT() { int i; \
69375115Sfenner			TCHECK2(bp[0], sizeof(int32_t)); \
69475115Sfenner			i = (int) EXTRACT_32BITS(bp); \
69556893Sfenner			bp += sizeof(int32_t); \
69656893Sfenner			printf(" %d", i); \
69756893Sfenner		}
69856893Sfenner
69956893Sfenner#define UINTOUT() { unsigned long i; \
70075115Sfenner			TCHECK2(bp[0], sizeof(int32_t)); \
70175115Sfenner			i = EXTRACT_32BITS(bp); \
70256893Sfenner			bp += sizeof(int32_t); \
70356893Sfenner			printf(" %lu", i); \
70456893Sfenner		}
70556893Sfenner
706190207Srpaulo#define UINT64OUT() { u_int64_t i; \
707190207Srpaulo			TCHECK2(bp[0], sizeof(u_int64_t)); \
708190207Srpaulo			i = EXTRACT_64BITS(bp); \
709190207Srpaulo			bp += sizeof(u_int64_t); \
710190207Srpaulo			printf(" %" PRIu64, i); \
711190207Srpaulo		}
712190207Srpaulo
71356893Sfenner#define DATEOUT() { time_t t; struct tm *tm; char str[256]; \
71475115Sfenner			TCHECK2(bp[0], sizeof(int32_t)); \
71575115Sfenner			t = (time_t) EXTRACT_32BITS(bp); \
71656893Sfenner			bp += sizeof(int32_t); \
71756893Sfenner			tm = localtime(&t); \
71856893Sfenner			strftime(str, 256, "%Y/%m/%d %T", tm); \
71956893Sfenner			printf(" %s", str); \
72056893Sfenner		}
72156893Sfenner
72256893Sfenner#define STOREATTROUT() { unsigned long mask, i; \
72375115Sfenner			TCHECK2(bp[0], (sizeof(int32_t)*6)); \
72475115Sfenner			mask = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
72556893Sfenner			if (mask) printf (" StoreStatus"); \
726127668Sbms		        if (mask & 1) { printf(" date"); DATEOUT(); } \
72756893Sfenner			else bp += sizeof(int32_t); \
72875115Sfenner			i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
729127668Sbms		        if (mask & 2) printf(" owner %lu", i);  \
73075115Sfenner			i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
731127668Sbms		        if (mask & 4) printf(" group %lu", i); \
73275115Sfenner			i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
733127668Sbms		        if (mask & 8) printf(" mode %lo", i & 07777); \
73475115Sfenner			i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
735127668Sbms		        if (mask & 16) printf(" segsize %lu", i); \
73656893Sfenner			/* undocumented in 3.3 docu */ \
737127668Sbms		        if (mask & 1024) printf(" fsync");  \
73856893Sfenner		}
73956893Sfenner
74056893Sfenner#define UBIK_VERSIONOUT() {int32_t epoch; int32_t counter; \
74175115Sfenner			TCHECK2(bp[0], sizeof(int32_t) * 2); \
74275115Sfenner			epoch = EXTRACT_32BITS(bp); \
74356893Sfenner			bp += sizeof(int32_t); \
74475115Sfenner			counter = EXTRACT_32BITS(bp); \
74556893Sfenner			bp += sizeof(int32_t); \
74656893Sfenner			printf(" %d.%d", epoch, counter); \
74756893Sfenner		}
74856893Sfenner
74956893Sfenner#define AFSUUIDOUT() {u_int32_t temp; int i; \
75075115Sfenner			TCHECK2(bp[0], 11*sizeof(u_int32_t)); \
75175115Sfenner			temp = EXTRACT_32BITS(bp); \
75256893Sfenner			bp += sizeof(u_int32_t); \
75356893Sfenner			printf(" %08x", temp); \
75475115Sfenner			temp = EXTRACT_32BITS(bp); \
75556893Sfenner			bp += sizeof(u_int32_t); \
75656893Sfenner			printf("%04x", temp); \
75775115Sfenner			temp = EXTRACT_32BITS(bp); \
75856893Sfenner			bp += sizeof(u_int32_t); \
75956893Sfenner			printf("%04x", temp); \
76056893Sfenner			for (i = 0; i < 8; i++) { \
76175115Sfenner				temp = EXTRACT_32BITS(bp); \
76256893Sfenner				bp += sizeof(u_int32_t); \
76356893Sfenner				printf("%02x", (unsigned char) temp); \
76456893Sfenner			} \
76556893Sfenner		}
76656893Sfenner
76756893Sfenner/*
76856893Sfenner * This is the sickest one of all
76956893Sfenner */
77056893Sfenner
771111726Sfenner#define VECOUT(MAX) { u_char *sp; \
772111726Sfenner			u_char s[AFSNAMEMAX]; \
77356893Sfenner			int k; \
77498524Sfenner			if ((MAX) + 1 > sizeof(s)) \
77598524Sfenner				goto trunc; \
77698524Sfenner			TCHECK2(bp[0], (MAX) * sizeof(int32_t)); \
77756893Sfenner			sp = s; \
77898524Sfenner			for (k = 0; k < (MAX); k++) { \
779111726Sfenner				*sp++ = (u_char) EXTRACT_32BITS(bp); \
78056893Sfenner				bp += sizeof(int32_t); \
78156893Sfenner			} \
78298524Sfenner			s[(MAX)] = '\0'; \
78380231Sfenner			printf(" \""); \
78480231Sfenner			fn_print(s, NULL); \
78580231Sfenner			printf("\""); \
78656893Sfenner		}
78756893Sfenner
788190207Srpaulo#define DESTSERVEROUT() { unsigned long n1, n2, n3; \
789190207Srpaulo			TCHECK2(bp[0], sizeof(int32_t) * 3); \
790190207Srpaulo			n1 = EXTRACT_32BITS(bp); \
791190207Srpaulo			bp += sizeof(int32_t); \
792190207Srpaulo			n2 = EXTRACT_32BITS(bp); \
793190207Srpaulo			bp += sizeof(int32_t); \
794190207Srpaulo			n3 = EXTRACT_32BITS(bp); \
795190207Srpaulo			bp += sizeof(int32_t); \
796190207Srpaulo			printf(" server %d:%d:%d", (int) n1, (int) n2, (int) n3); \
797190207Srpaulo		}
798190207Srpaulo
79956893Sfenner/*
80056893Sfenner * Handle calls to the AFS file service (fs)
80156893Sfenner */
80256893Sfenner
80375115Sfennerstatic void
80456893Sfennerfs_print(register const u_char *bp, int length)
80556893Sfenner{
80656893Sfenner	int fs_op;
80756893Sfenner	unsigned long i;
80856893Sfenner
809127668Sbms	if (length <= (int)sizeof(struct rx_header))
81056893Sfenner		return;
81156893Sfenner
812127668Sbms	if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
81356893Sfenner		goto trunc;
81456893Sfenner	}
81556893Sfenner
81656893Sfenner	/*
81756893Sfenner	 * Print out the afs call we're invoking.  The table used here was
81856893Sfenner	 * gleaned from fsint/afsint.xg
81956893Sfenner	 */
82056893Sfenner
82175115Sfenner	fs_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
82256893Sfenner
82356893Sfenner	printf(" fs call %s", tok2str(fs_req, "op#%d", fs_op));
82456893Sfenner
82556893Sfenner	/*
82656893Sfenner	 * Print out arguments to some of the AFS calls.  This stuff is
82756893Sfenner	 * all from afsint.xg
82856893Sfenner	 */
82956893Sfenner
83056893Sfenner	bp += sizeof(struct rx_header) + 4;
83156893Sfenner
83256893Sfenner	/*
83356893Sfenner	 * Sigh.  This is gross.  Ritchie forgive me.
83456893Sfenner	 */
83556893Sfenner
83656893Sfenner	switch (fs_op) {
83756893Sfenner		case 130:	/* Fetch data */
83856893Sfenner			FIDOUT();
83956893Sfenner			printf(" offset");
84056893Sfenner			UINTOUT();
84156893Sfenner			printf(" length");
84256893Sfenner			UINTOUT();
84356893Sfenner			break;
84456893Sfenner		case 131:	/* Fetch ACL */
84556893Sfenner		case 132:	/* Fetch Status */
84656893Sfenner		case 143:	/* Old set lock */
84756893Sfenner		case 144:	/* Old extend lock */
84856893Sfenner		case 145:	/* Old release lock */
84956893Sfenner		case 156:	/* Set lock */
85056893Sfenner		case 157:	/* Extend lock */
85156893Sfenner		case 158:	/* Release lock */
85256893Sfenner			FIDOUT();
85356893Sfenner			break;
85456893Sfenner		case 135:	/* Store status */
85556893Sfenner			FIDOUT();
85656893Sfenner			STOREATTROUT();
85756893Sfenner			break;
85856893Sfenner		case 133:	/* Store data */
85956893Sfenner			FIDOUT();
86056893Sfenner			STOREATTROUT();
86156893Sfenner			printf(" offset");
86256893Sfenner			UINTOUT();
86356893Sfenner			printf(" length");
86456893Sfenner			UINTOUT();
86556893Sfenner			printf(" flen");
86656893Sfenner			UINTOUT();
86756893Sfenner			break;
86856893Sfenner		case 134:	/* Store ACL */
86956893Sfenner		{
87075115Sfenner			char a[AFSOPAQUEMAX+1];
87156893Sfenner			FIDOUT();
87275115Sfenner			TCHECK2(bp[0], 4);
87375115Sfenner			i = EXTRACT_32BITS(bp);
87456893Sfenner			bp += sizeof(int32_t);
87575115Sfenner			TCHECK2(bp[0], i);
87675115Sfenner			i = min(AFSOPAQUEMAX, i);
87775115Sfenner			strncpy(a, (char *) bp, i);
87856893Sfenner			a[i] = '\0';
87975115Sfenner			acl_print((u_char *) a, sizeof(a), (u_char *) a + i);
88056893Sfenner			break;
88156893Sfenner		}
88256893Sfenner		case 137:	/* Create file */
88356893Sfenner		case 141:	/* MakeDir */
88456893Sfenner			FIDOUT();
88556893Sfenner			STROUT(AFSNAMEMAX);
88656893Sfenner			STOREATTROUT();
88756893Sfenner			break;
88856893Sfenner		case 136:	/* Remove file */
88956893Sfenner		case 142:	/* Remove directory */
89056893Sfenner			FIDOUT();
89156893Sfenner			STROUT(AFSNAMEMAX);
89256893Sfenner			break;
89356893Sfenner		case 138:	/* Rename file */
89456893Sfenner			printf(" old");
89556893Sfenner			FIDOUT();
89656893Sfenner			STROUT(AFSNAMEMAX);
89756893Sfenner			printf(" new");
89856893Sfenner			FIDOUT();
89956893Sfenner			STROUT(AFSNAMEMAX);
90056893Sfenner			break;
90156893Sfenner		case 139:	/* Symlink */
90256893Sfenner			FIDOUT();
90356893Sfenner			STROUT(AFSNAMEMAX);
90456893Sfenner			printf(" link to");
90556893Sfenner			STROUT(AFSNAMEMAX);
90656893Sfenner			break;
90756893Sfenner		case 140:	/* Link */
90856893Sfenner			FIDOUT();
90956893Sfenner			STROUT(AFSNAMEMAX);
91056893Sfenner			printf(" link to");
91156893Sfenner			FIDOUT();
91256893Sfenner			break;
91356893Sfenner		case 148:	/* Get volume info */
91456893Sfenner			STROUT(AFSNAMEMAX);
91556893Sfenner			break;
91656893Sfenner		case 149:	/* Get volume stats */
91756893Sfenner		case 150:	/* Set volume stats */
91856893Sfenner			printf(" volid");
91956893Sfenner			UINTOUT();
92056893Sfenner			break;
92156893Sfenner		case 154:	/* New get volume info */
92256893Sfenner			printf(" volname");
92356893Sfenner			STROUT(AFSNAMEMAX);
92456893Sfenner			break;
92556893Sfenner		case 155:	/* Bulk stat */
926190207Srpaulo		case 65536:     /* Inline bulk stat */
92756893Sfenner		{
92856893Sfenner			unsigned long j;
92975115Sfenner			TCHECK2(bp[0], 4);
93075115Sfenner			j = EXTRACT_32BITS(bp);
93156893Sfenner			bp += sizeof(int32_t);
93256893Sfenner
93356893Sfenner			for (i = 0; i < j; i++) {
93456893Sfenner				FIDOUT();
93556893Sfenner				if (i != j - 1)
93656893Sfenner					printf(",");
93756893Sfenner			}
93856893Sfenner			if (j == 0)
93956893Sfenner				printf(" <none!>");
94056893Sfenner		}
941190207Srpaulo		case 65537:	/* Fetch data 64 */
942190207Srpaulo			FIDOUT();
943190207Srpaulo			printf(" offset");
944190207Srpaulo			UINT64OUT();
945190207Srpaulo			printf(" length");
946190207Srpaulo			UINT64OUT();
947190207Srpaulo			break;
948190207Srpaulo		case 65538:	/* Store data 64 */
949190207Srpaulo			FIDOUT();
950190207Srpaulo			STOREATTROUT();
951190207Srpaulo			printf(" offset");
952190207Srpaulo			UINT64OUT();
953190207Srpaulo			printf(" length");
954190207Srpaulo			UINT64OUT();
955190207Srpaulo			printf(" flen");
956190207Srpaulo			UINT64OUT();
957190207Srpaulo			break;
958190207Srpaulo		case 65541:    /* CallBack rx conn address */
959190207Srpaulo			printf(" addr");
960190207Srpaulo			UINTOUT();
96156893Sfenner		default:
96256893Sfenner			;
96356893Sfenner	}
96456893Sfenner
96556893Sfenner	return;
96656893Sfenner
96756893Sfennertrunc:
96856893Sfenner	printf(" [|fs]");
96956893Sfenner}
97056893Sfenner
97156893Sfenner/*
97256893Sfenner * Handle replies to the AFS file service
97356893Sfenner */
97456893Sfenner
97556893Sfennerstatic void
97656893Sfennerfs_reply_print(register const u_char *bp, int length, int32_t opcode)
97756893Sfenner{
97856893Sfenner	unsigned long i;
97956893Sfenner	struct rx_header *rxh;
98056893Sfenner
981127668Sbms	if (length <= (int)sizeof(struct rx_header))
98256893Sfenner		return;
98356893Sfenner
98456893Sfenner	rxh = (struct rx_header *) bp;
98556893Sfenner
98656893Sfenner	/*
98756893Sfenner	 * Print out the afs call we're invoking.  The table used here was
98856893Sfenner	 * gleaned from fsint/afsint.xg
98956893Sfenner	 */
99056893Sfenner
99156893Sfenner	printf(" fs reply %s", tok2str(fs_req, "op#%d", opcode));
99256893Sfenner
99356893Sfenner	bp += sizeof(struct rx_header);
99456893Sfenner
99556893Sfenner	/*
99656893Sfenner	 * If it was a data packet, interpret the response
99756893Sfenner	 */
99856893Sfenner
99975115Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA) {
100056893Sfenner		switch (opcode) {
100156893Sfenner		case 131:	/* Fetch ACL */
100256893Sfenner		{
100375115Sfenner			char a[AFSOPAQUEMAX+1];
100475115Sfenner			TCHECK2(bp[0], 4);
100575115Sfenner			i = EXTRACT_32BITS(bp);
100656893Sfenner			bp += sizeof(int32_t);
100775115Sfenner			TCHECK2(bp[0], i);
100875115Sfenner			i = min(AFSOPAQUEMAX, i);
100975115Sfenner			strncpy(a, (char *) bp, i);
101056893Sfenner			a[i] = '\0';
101175115Sfenner			acl_print((u_char *) a, sizeof(a), (u_char *) a + i);
101256893Sfenner			break;
101356893Sfenner		}
101456893Sfenner		case 137:	/* Create file */
101556893Sfenner		case 141:	/* MakeDir */
101656893Sfenner			printf(" new");
101756893Sfenner			FIDOUT();
101856893Sfenner			break;
101956893Sfenner		case 151:	/* Get root volume */
102056893Sfenner			printf(" root volume");
102156893Sfenner			STROUT(AFSNAMEMAX);
102256893Sfenner			break;
102356893Sfenner		case 153:	/* Get time */
102456893Sfenner			DATEOUT();
102556893Sfenner			break;
102656893Sfenner		default:
102756893Sfenner			;
102856893Sfenner		}
102975115Sfenner	} else if (rxh->type == RX_PACKET_TYPE_ABORT) {
103075115Sfenner		int i;
103175115Sfenner
1032127668Sbms		/*
1033127668Sbms		 * Otherwise, just print out the return code
1034127668Sbms		 */
1035127668Sbms		TCHECK2(bp[0], sizeof(int32_t));
1036127668Sbms		i = (int) EXTRACT_32BITS(bp);
1037127668Sbms		bp += sizeof(int32_t);
103875115Sfenner
103975115Sfenner		printf(" error %s", tok2str(afs_fs_errors, "#%d", i));
104075115Sfenner	} else {
104175115Sfenner		printf(" strange fs reply of type %d", rxh->type);
104256893Sfenner	}
104356893Sfenner
104456893Sfenner	return;
104556893Sfenner
104656893Sfennertrunc:
104756893Sfenner	printf(" [|fs]");
104856893Sfenner}
104956893Sfenner
105056893Sfenner/*
105156893Sfenner * Print out an AFS ACL string.  An AFS ACL is a string that has the
105256893Sfenner * following format:
105356893Sfenner *
105456893Sfenner * <positive> <negative>
105556893Sfenner * <uid1> <aclbits1>
105656893Sfenner * ....
1057127668Sbms *
105856893Sfenner * "positive" and "negative" are integers which contain the number of
105956893Sfenner * positive and negative ACL's in the string.  The uid/aclbits pair are
106056893Sfenner * ASCII strings containing the UID/PTS record and and a ascii number
106156893Sfenner * representing a logical OR of all the ACL permission bits
106256893Sfenner */
106356893Sfenner
106456893Sfennerstatic void
106575115Sfenneracl_print(u_char *s, int maxsize, u_char *end)
106656893Sfenner{
106756893Sfenner	int pos, neg, acl;
106856893Sfenner	int n, i;
106975115Sfenner	char *user;
1070172683Smlaier	char fmt[1024];
107156893Sfenner
107275115Sfenner	if ((user = (char *)malloc(maxsize)) == NULL)
107375115Sfenner		return;
107475115Sfenner
107556893Sfenner	if (sscanf((char *) s, "%d %d\n%n", &pos, &neg, &n) != 2)
107675115Sfenner		goto finish;
1077127668Sbms
107856893Sfenner	s += n;
107956893Sfenner
108056893Sfenner	if (s > end)
108175115Sfenner		goto finish;
108256893Sfenner
108356893Sfenner	/*
108456893Sfenner	 * This wacky order preserves the order used by the "fs" command
108556893Sfenner	 */
108656893Sfenner
108756893Sfenner#define ACLOUT(acl) \
108856893Sfenner	if (acl & PRSFS_READ) \
108956893Sfenner		printf("r"); \
109056893Sfenner	if (acl & PRSFS_LOOKUP) \
109156893Sfenner		printf("l"); \
109256893Sfenner	if (acl & PRSFS_INSERT) \
109356893Sfenner		printf("i"); \
109456893Sfenner	if (acl & PRSFS_DELETE) \
109556893Sfenner		printf("d"); \
109656893Sfenner	if (acl & PRSFS_WRITE) \
109756893Sfenner		printf("w"); \
109856893Sfenner	if (acl & PRSFS_LOCK) \
109956893Sfenner		printf("k"); \
110056893Sfenner	if (acl & PRSFS_ADMINISTER) \
110156893Sfenner		printf("a");
110256893Sfenner
110356893Sfenner	for (i = 0; i < pos; i++) {
1104172683Smlaier		snprintf(fmt, sizeof(fmt), "%%%ds %%d\n%%n", maxsize - 1);
1105172683Smlaier		if (sscanf((char *) s, fmt, user, &acl, &n) != 2)
110675115Sfenner			goto finish;
110756893Sfenner		s += n;
110880231Sfenner		printf(" +{");
1109111726Sfenner		fn_print((u_char *)user, NULL);
111080231Sfenner		printf(" ");
111156893Sfenner		ACLOUT(acl);
111256893Sfenner		printf("}");
111356893Sfenner		if (s > end)
111475115Sfenner			goto finish;
111556893Sfenner	}
111656893Sfenner
111756893Sfenner	for (i = 0; i < neg; i++) {
1118172683Smlaier		snprintf(fmt, sizeof(fmt), "%%%ds %%d\n%%n", maxsize - 1);
1119172683Smlaier		if (sscanf((char *) s, fmt, user, &acl, &n) != 2)
112075115Sfenner			goto finish;
112156893Sfenner		s += n;
112280231Sfenner		printf(" -{");
1123111726Sfenner		fn_print((u_char *)user, NULL);
112480231Sfenner		printf(" ");
112556893Sfenner		ACLOUT(acl);
112656893Sfenner		printf("}");
112756893Sfenner		if (s > end)
112875115Sfenner			goto finish;
112956893Sfenner	}
113075115Sfenner
113175115Sfennerfinish:
113275115Sfenner	free(user);
113375115Sfenner	return;
113456893Sfenner}
113556893Sfenner
113656893Sfenner#undef ACLOUT
113756893Sfenner
113856893Sfenner/*
113956893Sfenner * Handle calls to the AFS callback service
114056893Sfenner */
114156893Sfenner
114256893Sfennerstatic void
114356893Sfennercb_print(register const u_char *bp, int length)
114456893Sfenner{
114556893Sfenner	int cb_op;
114656893Sfenner	unsigned long i;
114756893Sfenner
1148127668Sbms	if (length <= (int)sizeof(struct rx_header))
114956893Sfenner		return;
115056893Sfenner
1151127668Sbms	if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
115256893Sfenner		goto trunc;
115356893Sfenner	}
115456893Sfenner
115556893Sfenner	/*
115656893Sfenner	 * Print out the afs call we're invoking.  The table used here was
115756893Sfenner	 * gleaned from fsint/afscbint.xg
115856893Sfenner	 */
115956893Sfenner
116075115Sfenner	cb_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
116156893Sfenner
116256893Sfenner	printf(" cb call %s", tok2str(cb_req, "op#%d", cb_op));
116356893Sfenner
116456893Sfenner	bp += sizeof(struct rx_header) + 4;
116556893Sfenner
116656893Sfenner	/*
116756893Sfenner	 * Print out the afs call we're invoking.  The table used here was
116856893Sfenner	 * gleaned from fsint/afscbint.xg
116956893Sfenner	 */
117056893Sfenner
117156893Sfenner	switch (cb_op) {
117256893Sfenner		case 204:		/* Callback */
117356893Sfenner		{
117456893Sfenner			unsigned long j, t;
117575115Sfenner			TCHECK2(bp[0], 4);
117675115Sfenner			j = EXTRACT_32BITS(bp);
117756893Sfenner			bp += sizeof(int32_t);
117856893Sfenner
117956893Sfenner			for (i = 0; i < j; i++) {
118056893Sfenner				FIDOUT();
118156893Sfenner				if (i != j - 1)
118256893Sfenner					printf(",");
118356893Sfenner			}
118456893Sfenner
118556893Sfenner			if (j == 0)
118656893Sfenner				printf(" <none!>");
118756893Sfenner
118875115Sfenner			j = EXTRACT_32BITS(bp);
118956893Sfenner			bp += sizeof(int32_t);
119056893Sfenner
119156893Sfenner			if (j != 0)
119256893Sfenner				printf(";");
119356893Sfenner
119456893Sfenner			for (i = 0; i < j; i++) {
119556893Sfenner				printf(" ver");
119656893Sfenner				INTOUT();
119756893Sfenner				printf(" expires");
119856893Sfenner				DATEOUT();
119975115Sfenner				TCHECK2(bp[0], 4);
120075115Sfenner				t = EXTRACT_32BITS(bp);
120156893Sfenner				bp += sizeof(int32_t);
120256893Sfenner				tok2str(cb_types, "type %d", t);
120356893Sfenner			}
120456893Sfenner		}
120556893Sfenner		case 214: {
120656893Sfenner			printf(" afsuuid");
120756893Sfenner			AFSUUIDOUT();
120856893Sfenner			break;
120956893Sfenner		}
121056893Sfenner		default:
121156893Sfenner			;
121256893Sfenner	}
121356893Sfenner
121456893Sfenner	return;
121556893Sfenner
121656893Sfennertrunc:
121756893Sfenner	printf(" [|cb]");
121856893Sfenner}
121956893Sfenner
122056893Sfenner/*
122156893Sfenner * Handle replies to the AFS Callback Service
122256893Sfenner */
122356893Sfenner
122456893Sfennerstatic void
122556893Sfennercb_reply_print(register const u_char *bp, int length, int32_t opcode)
122656893Sfenner{
122756893Sfenner	struct rx_header *rxh;
122856893Sfenner
1229127668Sbms	if (length <= (int)sizeof(struct rx_header))
123056893Sfenner		return;
123156893Sfenner
123256893Sfenner	rxh = (struct rx_header *) bp;
123356893Sfenner
123456893Sfenner	/*
123556893Sfenner	 * Print out the afs call we're invoking.  The table used here was
123656893Sfenner	 * gleaned from fsint/afscbint.xg
123756893Sfenner	 */
1238127668Sbms
123956893Sfenner	printf(" cb reply %s", tok2str(cb_req, "op#%d", opcode));
124056893Sfenner
124156893Sfenner	bp += sizeof(struct rx_header);
124256893Sfenner
124356893Sfenner	/*
124456893Sfenner	 * If it was a data packet, interpret the response.
124556893Sfenner	 */
124656893Sfenner
124756893Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA)
124856893Sfenner		switch (opcode) {
124956893Sfenner		case 213:	/* InitCallBackState3 */
125056893Sfenner			AFSUUIDOUT();
125156893Sfenner			break;
125256893Sfenner		default:
125356893Sfenner		;
125456893Sfenner		}
125556893Sfenner	else {
125656893Sfenner		/*
125756893Sfenner		 * Otherwise, just print out the return code
125856893Sfenner		 */
125956893Sfenner		printf(" errcode");
126056893Sfenner		INTOUT();
126156893Sfenner	}
126256893Sfenner
126356893Sfenner	return;
126456893Sfenner
126556893Sfennertrunc:
126656893Sfenner	printf(" [|cb]");
126756893Sfenner}
126856893Sfenner
126956893Sfenner/*
127056893Sfenner * Handle calls to the AFS protection database server
127156893Sfenner */
127256893Sfenner
127356893Sfennerstatic void
127456893Sfennerprot_print(register const u_char *bp, int length)
127556893Sfenner{
127656893Sfenner	unsigned long i;
127756893Sfenner	int pt_op;
127856893Sfenner
1279127668Sbms	if (length <= (int)sizeof(struct rx_header))
128056893Sfenner		return;
128156893Sfenner
1282127668Sbms	if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
128356893Sfenner		goto trunc;
128456893Sfenner	}
128556893Sfenner
128656893Sfenner	/*
128756893Sfenner	 * Print out the afs call we're invoking.  The table used here was
128856893Sfenner	 * gleaned from ptserver/ptint.xg
128956893Sfenner	 */
129056893Sfenner
129175115Sfenner	pt_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
129256893Sfenner
129356893Sfenner	printf(" pt");
129456893Sfenner
129556893Sfenner	if (is_ubik(pt_op)) {
1296127668Sbms		ubik_print(bp);
129756893Sfenner		return;
129856893Sfenner	}
129956893Sfenner
130056893Sfenner	printf(" call %s", tok2str(pt_req, "op#%d", pt_op));
130156893Sfenner
130256893Sfenner	/*
130356893Sfenner	 * Decode some of the arguments to the PT calls
130456893Sfenner	 */
130556893Sfenner
130656893Sfenner	bp += sizeof(struct rx_header) + 4;
130756893Sfenner
130856893Sfenner	switch (pt_op) {
130956893Sfenner		case 500:	/* I New User */
131056893Sfenner			STROUT(PRNAMEMAX);
131156893Sfenner			printf(" id");
131256893Sfenner			INTOUT();
131356893Sfenner			printf(" oldid");
131456893Sfenner			INTOUT();
131556893Sfenner			break;
131656893Sfenner		case 501:	/* Where is it */
131756893Sfenner		case 506:	/* Delete */
131856893Sfenner		case 508:	/* Get CPS */
131956893Sfenner		case 512:	/* List entry */
132056893Sfenner		case 514:	/* List elements */
132156893Sfenner		case 517:	/* List owned */
132256893Sfenner		case 518:	/* Get CPS2 */
132356893Sfenner		case 519:	/* Get host CPS */
1324190207Srpaulo		case 530:	/* List super groups */
132556893Sfenner			printf(" id");
132656893Sfenner			INTOUT();
132756893Sfenner			break;
132856893Sfenner		case 502:	/* Dump entry */
132956893Sfenner			printf(" pos");
133056893Sfenner			INTOUT();
133156893Sfenner			break;
133256893Sfenner		case 503:	/* Add to group */
133356893Sfenner		case 507:	/* Remove from group */
133456893Sfenner		case 515:	/* Is a member of? */
133556893Sfenner			printf(" uid");
133656893Sfenner			INTOUT();
133756893Sfenner			printf(" gid");
133856893Sfenner			INTOUT();
133956893Sfenner			break;
134056893Sfenner		case 504:	/* Name to ID */
134156893Sfenner		{
134256893Sfenner			unsigned long j;
134375115Sfenner			TCHECK2(bp[0], 4);
134475115Sfenner			j = EXTRACT_32BITS(bp);
134556893Sfenner			bp += sizeof(int32_t);
134656893Sfenner
134756893Sfenner			/*
134856893Sfenner			 * Who designed this chicken-shit protocol?
134956893Sfenner			 *
135056893Sfenner			 * Each character is stored as a 32-bit
135156893Sfenner			 * integer!
135256893Sfenner			 */
135356893Sfenner
135456893Sfenner			for (i = 0; i < j; i++) {
135556893Sfenner				VECOUT(PRNAMEMAX);
135656893Sfenner			}
135756893Sfenner			if (j == 0)
135856893Sfenner				printf(" <none!>");
135956893Sfenner		}
136056893Sfenner			break;
136156893Sfenner		case 505:	/* Id to name */
136256893Sfenner		{
136356893Sfenner			unsigned long j;
136456893Sfenner			printf(" ids:");
136575115Sfenner			TCHECK2(bp[0], 4);
136675115Sfenner			i = EXTRACT_32BITS(bp);
136756893Sfenner			bp += sizeof(int32_t);
136856893Sfenner			for (j = 0; j < i; j++)
136956893Sfenner				INTOUT();
137056893Sfenner			if (j == 0)
137156893Sfenner				printf(" <none!>");
137256893Sfenner		}
137356893Sfenner			break;
137456893Sfenner		case 509:	/* New entry */
137556893Sfenner			STROUT(PRNAMEMAX);
137656893Sfenner			printf(" flag");
137756893Sfenner			INTOUT();
137856893Sfenner			printf(" oid");
137956893Sfenner			INTOUT();
138056893Sfenner			break;
138156893Sfenner		case 511:	/* Set max */
138256893Sfenner			printf(" id");
138356893Sfenner			INTOUT();
138456893Sfenner			printf(" gflag");
138556893Sfenner			INTOUT();
138656893Sfenner			break;
138756893Sfenner		case 513:	/* Change entry */
138856893Sfenner			printf(" id");
138956893Sfenner			INTOUT();
139056893Sfenner			STROUT(PRNAMEMAX);
139156893Sfenner			printf(" oldid");
139256893Sfenner			INTOUT();
139356893Sfenner			printf(" newid");
139456893Sfenner			INTOUT();
139556893Sfenner			break;
139656893Sfenner		case 520:	/* Update entry */
139756893Sfenner			printf(" id");
139856893Sfenner			INTOUT();
139956893Sfenner			STROUT(PRNAMEMAX);
140056893Sfenner			break;
140156893Sfenner		default:
140256893Sfenner			;
140356893Sfenner	}
140456893Sfenner
140556893Sfenner
140656893Sfenner	return;
140756893Sfenner
140856893Sfennertrunc:
140956893Sfenner	printf(" [|pt]");
141056893Sfenner}
141156893Sfenner
141256893Sfenner/*
141356893Sfenner * Handle replies to the AFS protection service
141456893Sfenner */
141556893Sfenner
141656893Sfennerstatic void
141756893Sfennerprot_reply_print(register const u_char *bp, int length, int32_t opcode)
141856893Sfenner{
141956893Sfenner	struct rx_header *rxh;
142056893Sfenner	unsigned long i;
142156893Sfenner
1422127668Sbms	if (length < (int)sizeof(struct rx_header))
142356893Sfenner		return;
142456893Sfenner
142556893Sfenner	rxh = (struct rx_header *) bp;
142656893Sfenner
142756893Sfenner	/*
142856893Sfenner	 * Print out the afs call we're invoking.  The table used here was
142956893Sfenner	 * gleaned from ptserver/ptint.xg.  Check to see if it's a
143056893Sfenner	 * Ubik call, however.
143156893Sfenner	 */
143256893Sfenner
143356893Sfenner	printf(" pt");
143456893Sfenner
143556893Sfenner	if (is_ubik(opcode)) {
143656893Sfenner		ubik_reply_print(bp, length, opcode);
143756893Sfenner		return;
143856893Sfenner	}
143956893Sfenner
144056893Sfenner	printf(" reply %s", tok2str(pt_req, "op#%d", opcode));
144156893Sfenner
144256893Sfenner	bp += sizeof(struct rx_header);
144356893Sfenner
144456893Sfenner	/*
144556893Sfenner	 * If it was a data packet, interpret the response
144656893Sfenner	 */
144756893Sfenner
144856893Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA)
144956893Sfenner		switch (opcode) {
145056893Sfenner		case 504:		/* Name to ID */
145156893Sfenner		{
145256893Sfenner			unsigned long j;
145356893Sfenner			printf(" ids:");
145475115Sfenner			TCHECK2(bp[0], 4);
145575115Sfenner			i = EXTRACT_32BITS(bp);
145656893Sfenner			bp += sizeof(int32_t);
145756893Sfenner			for (j = 0; j < i; j++)
145856893Sfenner				INTOUT();
145956893Sfenner			if (j == 0)
146056893Sfenner				printf(" <none!>");
146156893Sfenner		}
146256893Sfenner			break;
146356893Sfenner		case 505:		/* ID to name */
146456893Sfenner		{
146556893Sfenner			unsigned long j;
146675115Sfenner			TCHECK2(bp[0], 4);
146775115Sfenner			j = EXTRACT_32BITS(bp);
146856893Sfenner			bp += sizeof(int32_t);
146956893Sfenner
147056893Sfenner			/*
147156893Sfenner			 * Who designed this chicken-shit protocol?
147256893Sfenner			 *
147356893Sfenner			 * Each character is stored as a 32-bit
147456893Sfenner			 * integer!
147556893Sfenner			 */
147656893Sfenner
147756893Sfenner			for (i = 0; i < j; i++) {
147856893Sfenner				VECOUT(PRNAMEMAX);
147956893Sfenner			}
148056893Sfenner			if (j == 0)
148156893Sfenner				printf(" <none!>");
148256893Sfenner		}
148356893Sfenner			break;
148456893Sfenner		case 508:		/* Get CPS */
148556893Sfenner		case 514:		/* List elements */
148656893Sfenner		case 517:		/* List owned */
148756893Sfenner		case 518:		/* Get CPS2 */
148856893Sfenner		case 519:		/* Get host CPS */
148956893Sfenner		{
149056893Sfenner			unsigned long j;
149175115Sfenner			TCHECK2(bp[0], 4);
149275115Sfenner			j = EXTRACT_32BITS(bp);
149356893Sfenner			bp += sizeof(int32_t);
149456893Sfenner			for (i = 0; i < j; i++) {
149556893Sfenner				INTOUT();
149656893Sfenner			}
149756893Sfenner			if (j == 0)
149856893Sfenner				printf(" <none!>");
149956893Sfenner		}
150056893Sfenner			break;
150156893Sfenner		case 510:		/* List max */
150256893Sfenner			printf(" maxuid");
150356893Sfenner			INTOUT();
150456893Sfenner			printf(" maxgid");
150556893Sfenner			INTOUT();
150656893Sfenner			break;
150756893Sfenner		default:
150856893Sfenner			;
150956893Sfenner		}
151056893Sfenner	else {
151156893Sfenner		/*
151256893Sfenner		 * Otherwise, just print out the return code
151356893Sfenner		 */
151456893Sfenner		printf(" errcode");
151556893Sfenner		INTOUT();
151656893Sfenner	}
151756893Sfenner
151856893Sfenner	return;
151956893Sfenner
152056893Sfennertrunc:
152156893Sfenner	printf(" [|pt]");
152256893Sfenner}
152356893Sfenner
152456893Sfenner/*
152556893Sfenner * Handle calls to the AFS volume location database service
152656893Sfenner */
152756893Sfenner
152856893Sfennerstatic void
152956893Sfennervldb_print(register const u_char *bp, int length)
153056893Sfenner{
153156893Sfenner	int vldb_op;
153256893Sfenner	unsigned long i;
153356893Sfenner
1534127668Sbms	if (length <= (int)sizeof(struct rx_header))
153556893Sfenner		return;
153656893Sfenner
1537127668Sbms	if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
153856893Sfenner		goto trunc;
153956893Sfenner	}
154056893Sfenner
154156893Sfenner	/*
154256893Sfenner	 * Print out the afs call we're invoking.  The table used here was
154356893Sfenner	 * gleaned from vlserver/vldbint.xg
154456893Sfenner	 */
154556893Sfenner
154675115Sfenner	vldb_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
154756893Sfenner
154856893Sfenner	printf(" vldb");
154956893Sfenner
155056893Sfenner	if (is_ubik(vldb_op)) {
1551127668Sbms		ubik_print(bp);
155256893Sfenner		return;
155356893Sfenner	}
155456893Sfenner	printf(" call %s", tok2str(vldb_req, "op#%d", vldb_op));
155556893Sfenner
155656893Sfenner	/*
155756893Sfenner	 * Decode some of the arguments to the VLDB calls
155856893Sfenner	 */
155956893Sfenner
156056893Sfenner	bp += sizeof(struct rx_header) + 4;
156156893Sfenner
156256893Sfenner	switch (vldb_op) {
156356893Sfenner		case 501:	/* Create new volume */
156456893Sfenner		case 517:	/* Create entry N */
156556893Sfenner			VECOUT(VLNAMEMAX);
156656893Sfenner			break;
156756893Sfenner		case 502:	/* Delete entry */
156856893Sfenner		case 503:	/* Get entry by ID */
156956893Sfenner		case 507:	/* Update entry */
157056893Sfenner		case 508:	/* Set lock */
157156893Sfenner		case 509:	/* Release lock */
157256893Sfenner		case 518:	/* Get entry by ID N */
157356893Sfenner			printf(" volid");
157456893Sfenner			INTOUT();
157575115Sfenner			TCHECK2(bp[0], sizeof(int32_t));
157675115Sfenner			i = EXTRACT_32BITS(bp);
157756893Sfenner			bp += sizeof(int32_t);
157856893Sfenner			if (i <= 2)
157956893Sfenner				printf(" type %s", voltype[i]);
158056893Sfenner			break;
158156893Sfenner		case 504:	/* Get entry by name */
158256893Sfenner		case 519:	/* Get entry by name N */
158356893Sfenner		case 524:	/* Update entry by name */
158456893Sfenner		case 527:	/* Get entry by name U */
158556893Sfenner			STROUT(VLNAMEMAX);
158656893Sfenner			break;
158756893Sfenner		case 505:	/* Get new vol id */
158856893Sfenner			printf(" bump");
158956893Sfenner			INTOUT();
159056893Sfenner			break;
159156893Sfenner		case 506:	/* Replace entry */
159256893Sfenner		case 520:	/* Replace entry N */
159356893Sfenner			printf(" volid");
159456893Sfenner			INTOUT();
159575115Sfenner			TCHECK2(bp[0], sizeof(int32_t));
159675115Sfenner			i = EXTRACT_32BITS(bp);
159756893Sfenner			bp += sizeof(int32_t);
159856893Sfenner			if (i <= 2)
159956893Sfenner				printf(" type %s", voltype[i]);
160056893Sfenner			VECOUT(VLNAMEMAX);
160156893Sfenner			break;
160256893Sfenner		case 510:	/* List entry */
160356893Sfenner		case 521:	/* List entry N */
160456893Sfenner			printf(" index");
160556893Sfenner			INTOUT();
160656893Sfenner			break;
160756893Sfenner		default:
160856893Sfenner			;
160956893Sfenner	}
161056893Sfenner
161156893Sfenner	return;
161256893Sfenner
161356893Sfennertrunc:
161456893Sfenner	printf(" [|vldb]");
161556893Sfenner}
161656893Sfenner
161756893Sfenner/*
161856893Sfenner * Handle replies to the AFS volume location database service
161956893Sfenner */
162056893Sfenner
162156893Sfennerstatic void
162256893Sfennervldb_reply_print(register const u_char *bp, int length, int32_t opcode)
162356893Sfenner{
162456893Sfenner	struct rx_header *rxh;
162556893Sfenner	unsigned long i;
162656893Sfenner
1627127668Sbms	if (length < (int)sizeof(struct rx_header))
162856893Sfenner		return;
162956893Sfenner
163056893Sfenner	rxh = (struct rx_header *) bp;
163156893Sfenner
163256893Sfenner	/*
163356893Sfenner	 * Print out the afs call we're invoking.  The table used here was
163456893Sfenner	 * gleaned from vlserver/vldbint.xg.  Check to see if it's a
163556893Sfenner	 * Ubik call, however.
163656893Sfenner	 */
163756893Sfenner
163856893Sfenner	printf(" vldb");
163956893Sfenner
164056893Sfenner	if (is_ubik(opcode)) {
164156893Sfenner		ubik_reply_print(bp, length, opcode);
164256893Sfenner		return;
164356893Sfenner	}
164456893Sfenner
164556893Sfenner	printf(" reply %s", tok2str(vldb_req, "op#%d", opcode));
164656893Sfenner
164756893Sfenner	bp += sizeof(struct rx_header);
164856893Sfenner
164956893Sfenner	/*
165056893Sfenner	 * If it was a data packet, interpret the response
165156893Sfenner	 */
165256893Sfenner
165356893Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA)
165456893Sfenner		switch (opcode) {
165556893Sfenner		case 510:	/* List entry */
165656893Sfenner			printf(" count");
165756893Sfenner			INTOUT();
165856893Sfenner			printf(" nextindex");
165956893Sfenner			INTOUT();
166056893Sfenner		case 503:	/* Get entry by id */
166156893Sfenner		case 504:	/* Get entry by name */
166256893Sfenner		{	unsigned long nservers, j;
166356893Sfenner			VECOUT(VLNAMEMAX);
166475115Sfenner			TCHECK2(bp[0], sizeof(int32_t));
166556893Sfenner			bp += sizeof(int32_t);
166656893Sfenner			printf(" numservers");
166775115Sfenner			TCHECK2(bp[0], sizeof(int32_t));
166875115Sfenner			nservers = EXTRACT_32BITS(bp);
166956893Sfenner			bp += sizeof(int32_t);
167056893Sfenner			printf(" %lu", nservers);
167156893Sfenner			printf(" servers");
167256893Sfenner			for (i = 0; i < 8; i++) {
167375115Sfenner				TCHECK2(bp[0], sizeof(int32_t));
167456893Sfenner				if (i < nservers)
167556893Sfenner					printf(" %s",
1676127668Sbms					   intoa(((struct in_addr *) bp)->s_addr));
167756893Sfenner				bp += sizeof(int32_t);
167856893Sfenner			}
167956893Sfenner			printf(" partitions");
168056893Sfenner			for (i = 0; i < 8; i++) {
168175115Sfenner				TCHECK2(bp[0], sizeof(int32_t));
168275115Sfenner				j = EXTRACT_32BITS(bp);
168356893Sfenner				if (i < nservers && j <= 26)
168456893Sfenner					printf(" %c", 'a' + (int)j);
168556893Sfenner				else if (i < nservers)
168656893Sfenner					printf(" %lu", j);
168756893Sfenner				bp += sizeof(int32_t);
168856893Sfenner			}
168975115Sfenner			TCHECK2(bp[0], 8 * sizeof(int32_t));
169056893Sfenner			bp += 8 * sizeof(int32_t);
169156893Sfenner			printf(" rwvol");
169256893Sfenner			UINTOUT();
169356893Sfenner			printf(" rovol");
169456893Sfenner			UINTOUT();
169556893Sfenner			printf(" backup");
169656893Sfenner			UINTOUT();
169756893Sfenner		}
169856893Sfenner			break;
169956893Sfenner		case 505:	/* Get new volume ID */
170056893Sfenner			printf(" newvol");
170156893Sfenner			UINTOUT();
170256893Sfenner			break;
170356893Sfenner		case 521:	/* List entry */
170456893Sfenner		case 529:	/* List entry U */
170556893Sfenner			printf(" count");
170656893Sfenner			INTOUT();
170756893Sfenner			printf(" nextindex");
170856893Sfenner			INTOUT();
170956893Sfenner		case 518:	/* Get entry by ID N */
171056893Sfenner		case 519:	/* Get entry by name N */
171156893Sfenner		{	unsigned long nservers, j;
171256893Sfenner			VECOUT(VLNAMEMAX);
171356893Sfenner			printf(" numservers");
171475115Sfenner			TCHECK2(bp[0], sizeof(int32_t));
171575115Sfenner			nservers = EXTRACT_32BITS(bp);
171656893Sfenner			bp += sizeof(int32_t);
171756893Sfenner			printf(" %lu", nservers);
171856893Sfenner			printf(" servers");
171956893Sfenner			for (i = 0; i < 13; i++) {
172075115Sfenner				TCHECK2(bp[0], sizeof(int32_t));
172156893Sfenner				if (i < nservers)
172256893Sfenner					printf(" %s",
1723127668Sbms					   intoa(((struct in_addr *) bp)->s_addr));
172456893Sfenner				bp += sizeof(int32_t);
172556893Sfenner			}
172656893Sfenner			printf(" partitions");
172756893Sfenner			for (i = 0; i < 13; i++) {
172875115Sfenner				TCHECK2(bp[0], sizeof(int32_t));
172975115Sfenner				j = EXTRACT_32BITS(bp);
173056893Sfenner				if (i < nservers && j <= 26)
173156893Sfenner					printf(" %c", 'a' + (int)j);
173256893Sfenner				else if (i < nservers)
173356893Sfenner					printf(" %lu", j);
173456893Sfenner				bp += sizeof(int32_t);
173556893Sfenner			}
173675115Sfenner			TCHECK2(bp[0], 13 * sizeof(int32_t));
173756893Sfenner			bp += 13 * sizeof(int32_t);
173856893Sfenner			printf(" rwvol");
173956893Sfenner			UINTOUT();
174056893Sfenner			printf(" rovol");
174156893Sfenner			UINTOUT();
174256893Sfenner			printf(" backup");
174356893Sfenner			UINTOUT();
174456893Sfenner		}
174556893Sfenner			break;
174656893Sfenner		case 526:	/* Get entry by ID U */
174756893Sfenner		case 527:	/* Get entry by name U */
174856893Sfenner		{	unsigned long nservers, j;
174956893Sfenner			VECOUT(VLNAMEMAX);
175056893Sfenner			printf(" numservers");
175175115Sfenner			TCHECK2(bp[0], sizeof(int32_t));
175275115Sfenner			nservers = EXTRACT_32BITS(bp);
175356893Sfenner			bp += sizeof(int32_t);
175456893Sfenner			printf(" %lu", nservers);
175556893Sfenner			printf(" servers");
175656893Sfenner			for (i = 0; i < 13; i++) {
175756893Sfenner				if (i < nservers) {
175856893Sfenner					printf(" afsuuid");
175956893Sfenner					AFSUUIDOUT();
176056893Sfenner				} else {
176175115Sfenner					TCHECK2(bp[0], 44);
176256893Sfenner					bp += 44;
176356893Sfenner				}
176456893Sfenner			}
176575115Sfenner			TCHECK2(bp[0], 4 * 13);
176656893Sfenner			bp += 4 * 13;
176756893Sfenner			printf(" partitions");
176856893Sfenner			for (i = 0; i < 13; i++) {
176975115Sfenner				TCHECK2(bp[0], sizeof(int32_t));
177075115Sfenner				j = EXTRACT_32BITS(bp);
177156893Sfenner				if (i < nservers && j <= 26)
177256893Sfenner					printf(" %c", 'a' + (int)j);
177356893Sfenner				else if (i < nservers)
177456893Sfenner					printf(" %lu", j);
177556893Sfenner				bp += sizeof(int32_t);
177656893Sfenner			}
177775115Sfenner			TCHECK2(bp[0], 13 * sizeof(int32_t));
177856893Sfenner			bp += 13 * sizeof(int32_t);
177956893Sfenner			printf(" rwvol");
178056893Sfenner			UINTOUT();
178156893Sfenner			printf(" rovol");
178256893Sfenner			UINTOUT();
178356893Sfenner			printf(" backup");
178456893Sfenner			UINTOUT();
178556893Sfenner		}
178656893Sfenner		default:
178756893Sfenner			;
178856893Sfenner		}
1789127668Sbms
179056893Sfenner	else {
179156893Sfenner		/*
179256893Sfenner		 * Otherwise, just print out the return code
179356893Sfenner		 */
179456893Sfenner		printf(" errcode");
179556893Sfenner		INTOUT();
179656893Sfenner	}
179756893Sfenner
179856893Sfenner	return;
179956893Sfenner
180056893Sfennertrunc:
180156893Sfenner	printf(" [|vldb]");
180256893Sfenner}
180356893Sfenner
180456893Sfenner/*
180556893Sfenner * Handle calls to the AFS Kerberos Authentication service
180656893Sfenner */
180756893Sfenner
180856893Sfennerstatic void
180956893Sfennerkauth_print(register const u_char *bp, int length)
181056893Sfenner{
181156893Sfenner	int kauth_op;
181256893Sfenner
1813127668Sbms	if (length <= (int)sizeof(struct rx_header))
181456893Sfenner		return;
181556893Sfenner
1816127668Sbms	if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
181756893Sfenner		goto trunc;
181856893Sfenner	}
181956893Sfenner
182056893Sfenner	/*
182156893Sfenner	 * Print out the afs call we're invoking.  The table used here was
182256893Sfenner	 * gleaned from kauth/kauth.rg
182356893Sfenner	 */
182456893Sfenner
182575115Sfenner	kauth_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
182656893Sfenner
182756893Sfenner	printf(" kauth");
182856893Sfenner
182956893Sfenner	if (is_ubik(kauth_op)) {
1830127668Sbms		ubik_print(bp);
183156893Sfenner		return;
183256893Sfenner	}
183356893Sfenner
183456893Sfenner
183556893Sfenner	printf(" call %s", tok2str(kauth_req, "op#%d", kauth_op));
183656893Sfenner
183756893Sfenner	/*
183856893Sfenner	 * Decode some of the arguments to the KA calls
183956893Sfenner	 */
184056893Sfenner
184156893Sfenner	bp += sizeof(struct rx_header) + 4;
184256893Sfenner
184356893Sfenner	switch (kauth_op) {
184456893Sfenner		case 1:		/* Authenticate old */;
184556893Sfenner		case 21:	/* Authenticate */
184656893Sfenner		case 22:	/* Authenticate-V2 */
184756893Sfenner		case 2:		/* Change PW */
184856893Sfenner		case 5:		/* Set fields */
184956893Sfenner		case 6:		/* Create user */
185056893Sfenner		case 7:		/* Delete user */
185156893Sfenner		case 8:		/* Get entry */
185256893Sfenner		case 14:	/* Unlock */
185356893Sfenner		case 15:	/* Lock status */
185456893Sfenner			printf(" principal");
185556893Sfenner			STROUT(KANAMEMAX);
185656893Sfenner			STROUT(KANAMEMAX);
185756893Sfenner			break;
185856893Sfenner		case 3:		/* GetTicket-old */
185956893Sfenner		case 23:	/* GetTicket */
186056893Sfenner		{
186156893Sfenner			int i;
186256893Sfenner			printf(" kvno");
186356893Sfenner			INTOUT();
186456893Sfenner			printf(" domain");
186556893Sfenner			STROUT(KANAMEMAX);
186675115Sfenner			TCHECK2(bp[0], sizeof(int32_t));
186775115Sfenner			i = (int) EXTRACT_32BITS(bp);
186856893Sfenner			bp += sizeof(int32_t);
186975115Sfenner			TCHECK2(bp[0], i);
187056893Sfenner			bp += i;
187156893Sfenner			printf(" principal");
187256893Sfenner			STROUT(KANAMEMAX);
187356893Sfenner			STROUT(KANAMEMAX);
187456893Sfenner			break;
187556893Sfenner		}
187656893Sfenner		case 4:		/* Set Password */
187756893Sfenner			printf(" principal");
187856893Sfenner			STROUT(KANAMEMAX);
187956893Sfenner			STROUT(KANAMEMAX);
188056893Sfenner			printf(" kvno");
188156893Sfenner			INTOUT();
188256893Sfenner			break;
188356893Sfenner		case 12:	/* Get password */
188456893Sfenner			printf(" name");
188556893Sfenner			STROUT(KANAMEMAX);
188656893Sfenner			break;
188756893Sfenner		default:
188856893Sfenner			;
188956893Sfenner	}
189056893Sfenner
189156893Sfenner	return;
189256893Sfenner
189356893Sfennertrunc:
189456893Sfenner	printf(" [|kauth]");
189556893Sfenner}
189656893Sfenner
189756893Sfenner/*
189856893Sfenner * Handle replies to the AFS Kerberos Authentication Service
189956893Sfenner */
190056893Sfenner
190156893Sfennerstatic void
190256893Sfennerkauth_reply_print(register const u_char *bp, int length, int32_t opcode)
190356893Sfenner{
190456893Sfenner	struct rx_header *rxh;
190556893Sfenner
1906127668Sbms	if (length <= (int)sizeof(struct rx_header))
190756893Sfenner		return;
190856893Sfenner
190956893Sfenner	rxh = (struct rx_header *) bp;
191056893Sfenner
191156893Sfenner	/*
191256893Sfenner	 * Print out the afs call we're invoking.  The table used here was
191356893Sfenner	 * gleaned from kauth/kauth.rg
191456893Sfenner	 */
1915127668Sbms
191656893Sfenner	printf(" kauth");
191756893Sfenner
191856893Sfenner	if (is_ubik(opcode)) {
191956893Sfenner		ubik_reply_print(bp, length, opcode);
192056893Sfenner		return;
192156893Sfenner	}
192256893Sfenner
192356893Sfenner	printf(" reply %s", tok2str(kauth_req, "op#%d", opcode));
192456893Sfenner
192556893Sfenner	bp += sizeof(struct rx_header);
192656893Sfenner
192756893Sfenner	/*
192856893Sfenner	 * If it was a data packet, interpret the response.
192956893Sfenner	 */
193056893Sfenner
193156893Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA)
193256893Sfenner		/* Well, no, not really.  Leave this for later */
193356893Sfenner		;
193456893Sfenner	else {
193556893Sfenner		/*
193656893Sfenner		 * Otherwise, just print out the return code
193756893Sfenner		 */
193856893Sfenner		printf(" errcode");
193956893Sfenner		INTOUT();
194056893Sfenner	}
194156893Sfenner
194256893Sfenner	return;
194356893Sfenner
194456893Sfennertrunc:
194556893Sfenner	printf(" [|kauth]");
194656893Sfenner}
194756893Sfenner
194856893Sfenner/*
194956893Sfenner * Handle calls to the AFS Volume location service
195056893Sfenner */
195156893Sfenner
195256893Sfennerstatic void
195356893Sfennervol_print(register const u_char *bp, int length)
195456893Sfenner{
195556893Sfenner	int vol_op;
195656893Sfenner
1957127668Sbms	if (length <= (int)sizeof(struct rx_header))
195856893Sfenner		return;
195956893Sfenner
1960127668Sbms	if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
196156893Sfenner		goto trunc;
196256893Sfenner	}
196356893Sfenner
196456893Sfenner	/*
196556893Sfenner	 * Print out the afs call we're invoking.  The table used here was
196656893Sfenner	 * gleaned from volser/volint.xg
196756893Sfenner	 */
196856893Sfenner
196975115Sfenner	vol_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
197056893Sfenner
197156893Sfenner	printf(" vol call %s", tok2str(vol_req, "op#%d", vol_op));
197256893Sfenner
1973190207Srpaulo	bp += sizeof(struct rx_header) + 4;
197456893Sfenner
1975190207Srpaulo	switch (vol_op) {
1976190207Srpaulo		case 100:	/* Create volume */
1977190207Srpaulo			printf(" partition");
1978190207Srpaulo			UINTOUT();
1979190207Srpaulo			printf(" name");
1980190207Srpaulo			STROUT(AFSNAMEMAX);
1981190207Srpaulo			printf(" type");
1982190207Srpaulo			UINTOUT();
1983190207Srpaulo			printf(" parent");
1984190207Srpaulo			UINTOUT();
1985190207Srpaulo			break;
1986190207Srpaulo		case 101:	/* Delete volume */
1987190207Srpaulo		case 107:	/* Get flags */
1988190207Srpaulo			printf(" trans");
1989190207Srpaulo			UINTOUT();
1990190207Srpaulo			break;
1991190207Srpaulo		case 102:	/* Restore */
1992190207Srpaulo			printf(" totrans");
1993190207Srpaulo			UINTOUT();
1994190207Srpaulo			printf(" flags");
1995190207Srpaulo			UINTOUT();
1996190207Srpaulo			break;
1997190207Srpaulo		case 103:	/* Forward */
1998190207Srpaulo			printf(" fromtrans");
1999190207Srpaulo			UINTOUT();
2000190207Srpaulo			printf(" fromdate");
2001190207Srpaulo			DATEOUT();
2002190207Srpaulo			DESTSERVEROUT();
2003190207Srpaulo			printf(" desttrans");
2004190207Srpaulo			INTOUT();
2005190207Srpaulo			break;
2006190207Srpaulo		case 104:	/* End trans */
2007190207Srpaulo			printf(" trans");
2008190207Srpaulo			UINTOUT();
2009190207Srpaulo			break;
2010190207Srpaulo		case 105:	/* Clone */
2011190207Srpaulo			printf(" trans");
2012190207Srpaulo			UINTOUT();
2013190207Srpaulo			printf(" purgevol");
2014190207Srpaulo			UINTOUT();
2015190207Srpaulo			printf(" newtype");
2016190207Srpaulo			UINTOUT();
2017190207Srpaulo			printf(" newname");
2018190207Srpaulo			STROUT(AFSNAMEMAX);
2019190207Srpaulo			break;
2020190207Srpaulo		case 106:	/* Set flags */
2021190207Srpaulo			printf(" trans");
2022190207Srpaulo			UINTOUT();
2023190207Srpaulo			printf(" flags");
2024190207Srpaulo			UINTOUT();
2025190207Srpaulo			break;
2026190207Srpaulo		case 108:	/* Trans create */
2027190207Srpaulo			printf(" vol");
2028190207Srpaulo			UINTOUT();
2029190207Srpaulo			printf(" partition");
2030190207Srpaulo			UINTOUT();
2031190207Srpaulo			printf(" flags");
2032190207Srpaulo			UINTOUT();
2033190207Srpaulo			break;
2034190207Srpaulo		case 109:	/* Dump */
2035190207Srpaulo		case 655537:	/* Get size */
2036190207Srpaulo			printf(" fromtrans");
2037190207Srpaulo			UINTOUT();
2038190207Srpaulo			printf(" fromdate");
2039190207Srpaulo			DATEOUT();
2040190207Srpaulo			break;
2041190207Srpaulo		case 110:	/* Get n-th volume */
2042190207Srpaulo			printf(" index");
2043190207Srpaulo			UINTOUT();
2044190207Srpaulo			break;
2045190207Srpaulo		case 111:	/* Set forwarding */
2046190207Srpaulo			printf(" tid");
2047190207Srpaulo			UINTOUT();
2048190207Srpaulo			printf(" newsite");
2049190207Srpaulo			UINTOUT();
2050190207Srpaulo			break;
2051190207Srpaulo		case 112:	/* Get name */
2052190207Srpaulo		case 113:	/* Get status */
2053190207Srpaulo			printf(" tid");
2054190207Srpaulo			break;
2055190207Srpaulo		case 114:	/* Signal restore */
2056190207Srpaulo			printf(" name");
2057190207Srpaulo			STROUT(AFSNAMEMAX);
2058190207Srpaulo			printf(" type");
2059190207Srpaulo			UINTOUT();
2060190207Srpaulo			printf(" pid");
2061190207Srpaulo			UINTOUT();
2062190207Srpaulo			printf(" cloneid");
2063190207Srpaulo			UINTOUT();
2064190207Srpaulo			break;
2065190207Srpaulo		case 116:	/* List volumes */
2066190207Srpaulo			printf(" partition");
2067190207Srpaulo			UINTOUT();
2068190207Srpaulo			printf(" flags");
2069190207Srpaulo			UINTOUT();
2070190207Srpaulo			break;
2071190207Srpaulo		case 117:	/* Set id types */
2072190207Srpaulo			printf(" tid");
2073190207Srpaulo			UINTOUT();
2074190207Srpaulo			printf(" name");
2075190207Srpaulo			STROUT(AFSNAMEMAX);
2076190207Srpaulo			printf(" type");
2077190207Srpaulo			UINTOUT();
2078190207Srpaulo			printf(" pid");
2079190207Srpaulo			UINTOUT();
2080190207Srpaulo			printf(" clone");
2081190207Srpaulo			UINTOUT();
2082190207Srpaulo			printf(" backup");
2083190207Srpaulo			UINTOUT();
2084190207Srpaulo			break;
2085190207Srpaulo		case 119:	/* Partition info */
2086190207Srpaulo			printf(" name");
2087190207Srpaulo			STROUT(AFSNAMEMAX);
2088190207Srpaulo			break;
2089190207Srpaulo		case 120:	/* Reclone */
2090190207Srpaulo			printf(" tid");
2091190207Srpaulo			UINTOUT();
2092190207Srpaulo			break;
2093190207Srpaulo		case 121:	/* List one volume */
2094190207Srpaulo		case 122:	/* Nuke volume */
2095190207Srpaulo		case 124:	/* Extended List volumes */
2096190207Srpaulo		case 125:	/* Extended List one volume */
2097190207Srpaulo		case 65536:	/* Convert RO to RW volume */
2098190207Srpaulo			printf(" partid");
2099190207Srpaulo			UINTOUT();
2100190207Srpaulo			printf(" volid");
2101190207Srpaulo			UINTOUT();
2102190207Srpaulo			break;
2103190207Srpaulo		case 123:	/* Set date */
2104190207Srpaulo			printf(" tid");
2105190207Srpaulo			UINTOUT();
2106190207Srpaulo			printf(" date");
2107190207Srpaulo			DATEOUT();
2108190207Srpaulo			break;
2109190207Srpaulo		case 126:	/* Set info */
2110190207Srpaulo			printf(" tid");
2111190207Srpaulo			UINTOUT();
2112190207Srpaulo			break;
2113190207Srpaulo		case 128:	/* Forward multiple */
2114190207Srpaulo			printf(" fromtrans");
2115190207Srpaulo			UINTOUT();
2116190207Srpaulo			printf(" fromdate");
2117190207Srpaulo			DATEOUT();
2118190207Srpaulo			{
2119190207Srpaulo				unsigned long i, j;
2120190207Srpaulo				TCHECK2(bp[0], 4);
2121190207Srpaulo				j = EXTRACT_32BITS(bp);
2122190207Srpaulo				bp += sizeof(int32_t);
2123190207Srpaulo				for (i = 0; i < j; i++) {
2124190207Srpaulo					DESTSERVEROUT();
2125190207Srpaulo					if (i != j - 1)
2126190207Srpaulo						printf(",");
2127190207Srpaulo				}
2128190207Srpaulo				if (j == 0)
2129190207Srpaulo					printf(" <none!>");
2130190207Srpaulo			}
2131190207Srpaulo			break;
2132190207Srpaulo		case 65538:	/* Dump version 2 */
2133190207Srpaulo			printf(" fromtrans");
2134190207Srpaulo			UINTOUT();
2135190207Srpaulo			printf(" fromdate");
2136190207Srpaulo			DATEOUT();
2137190207Srpaulo			printf(" flags");
2138190207Srpaulo			UINTOUT();
2139190207Srpaulo			break;
2140190207Srpaulo		default:
2141190207Srpaulo			;
2142190207Srpaulo	}
214356893Sfenner	return;
214456893Sfenner
214556893Sfennertrunc:
214656893Sfenner	printf(" [|vol]");
214756893Sfenner}
214856893Sfenner
214956893Sfenner/*
215056893Sfenner * Handle replies to the AFS Volume Service
215156893Sfenner */
215256893Sfenner
215356893Sfennerstatic void
215456893Sfennervol_reply_print(register const u_char *bp, int length, int32_t opcode)
215556893Sfenner{
215656893Sfenner	struct rx_header *rxh;
215756893Sfenner
2158127668Sbms	if (length <= (int)sizeof(struct rx_header))
215956893Sfenner		return;
216056893Sfenner
216156893Sfenner	rxh = (struct rx_header *) bp;
216256893Sfenner
216356893Sfenner	/*
216456893Sfenner	 * Print out the afs call we're invoking.  The table used here was
216556893Sfenner	 * gleaned from volser/volint.xg
216656893Sfenner	 */
2167127668Sbms
216856893Sfenner	printf(" vol reply %s", tok2str(vol_req, "op#%d", opcode));
216956893Sfenner
217056893Sfenner	bp += sizeof(struct rx_header);
217156893Sfenner
217256893Sfenner	/*
217356893Sfenner	 * If it was a data packet, interpret the response.
217456893Sfenner	 */
217556893Sfenner
2176190207Srpaulo	if (rxh->type == RX_PACKET_TYPE_DATA) {
2177190207Srpaulo		switch (opcode) {
2178190207Srpaulo			case 100:	/* Create volume */
2179190207Srpaulo				printf(" volid");
2180190207Srpaulo				UINTOUT();
2181190207Srpaulo				printf(" trans");
2182190207Srpaulo				UINTOUT();
2183190207Srpaulo				break;
2184190207Srpaulo			case 104:	/* End transaction */
2185190207Srpaulo				UINTOUT();
2186190207Srpaulo				break;
2187190207Srpaulo			case 105:	/* Clone */
2188190207Srpaulo				printf(" newvol");
2189190207Srpaulo				UINTOUT();
2190190207Srpaulo				break;
2191190207Srpaulo			case 107:	/* Get flags */
2192190207Srpaulo				UINTOUT();
2193190207Srpaulo				break;
2194190207Srpaulo			case 108:	/* Transaction create */
2195190207Srpaulo				printf(" trans");
2196190207Srpaulo				UINTOUT();
2197190207Srpaulo				break;
2198190207Srpaulo			case 110:	/* Get n-th volume */
2199190207Srpaulo				printf(" volume");
2200190207Srpaulo				UINTOUT();
2201190207Srpaulo				printf(" partition");
2202190207Srpaulo				UINTOUT();
2203190207Srpaulo				break;
2204190207Srpaulo			case 112:	/* Get name */
2205190207Srpaulo				STROUT(AFSNAMEMAX);
2206190207Srpaulo				break;
2207190207Srpaulo			case 113:	/* Get status */
2208190207Srpaulo				printf(" volid");
2209190207Srpaulo				UINTOUT();
2210190207Srpaulo				printf(" nextuniq");
2211190207Srpaulo				UINTOUT();
2212190207Srpaulo				printf(" type");
2213190207Srpaulo				UINTOUT();
2214190207Srpaulo				printf(" parentid");
2215190207Srpaulo				UINTOUT();
2216190207Srpaulo				printf(" clone");
2217190207Srpaulo				UINTOUT();
2218190207Srpaulo				printf(" backup");
2219190207Srpaulo				UINTOUT();
2220190207Srpaulo				printf(" restore");
2221190207Srpaulo				UINTOUT();
2222190207Srpaulo				printf(" maxquota");
2223190207Srpaulo				UINTOUT();
2224190207Srpaulo				printf(" minquota");
2225190207Srpaulo				UINTOUT();
2226190207Srpaulo				printf(" owner");
2227190207Srpaulo				UINTOUT();
2228190207Srpaulo				printf(" create");
2229190207Srpaulo				DATEOUT();
2230190207Srpaulo				printf(" access");
2231190207Srpaulo				DATEOUT();
2232190207Srpaulo				printf(" update");
2233190207Srpaulo				DATEOUT();
2234190207Srpaulo				printf(" expire");
2235190207Srpaulo				DATEOUT();
2236190207Srpaulo				printf(" backup");
2237190207Srpaulo				DATEOUT();
2238190207Srpaulo				printf(" copy");
2239190207Srpaulo				DATEOUT();
2240190207Srpaulo				break;
2241190207Srpaulo			case 115:	/* Old list partitions */
2242190207Srpaulo				break;
2243190207Srpaulo			case 116:	/* List volumes */
2244190207Srpaulo			case 121:	/* List one volume */
2245190207Srpaulo				{
2246190207Srpaulo					unsigned long i, j;
2247190207Srpaulo					TCHECK2(bp[0], 4);
2248190207Srpaulo					j = EXTRACT_32BITS(bp);
2249190207Srpaulo					bp += sizeof(int32_t);
2250190207Srpaulo					for (i = 0; i < j; i++) {
2251190207Srpaulo						printf(" name");
2252190207Srpaulo						VECOUT(32);
2253190207Srpaulo						printf(" volid");
2254190207Srpaulo						UINTOUT();
2255190207Srpaulo						printf(" type");
2256190207Srpaulo						bp += sizeof(int32_t) * 21;
2257190207Srpaulo						if (i != j - 1)
2258190207Srpaulo							printf(",");
2259190207Srpaulo					}
2260190207Srpaulo					if (j == 0)
2261190207Srpaulo						printf(" <none!>");
2262190207Srpaulo				}
2263190207Srpaulo				break;
2264190207Srpaulo
2265190207Srpaulo
2266190207Srpaulo			default:
2267190207Srpaulo				;
2268190207Srpaulo		}
2269190207Srpaulo	} else {
227056893Sfenner		/*
227156893Sfenner		 * Otherwise, just print out the return code
227256893Sfenner		 */
227356893Sfenner		printf(" errcode");
227456893Sfenner		INTOUT();
227556893Sfenner	}
227656893Sfenner
227756893Sfenner	return;
227856893Sfenner
227956893Sfennertrunc:
228056893Sfenner	printf(" [|vol]");
228156893Sfenner}
228256893Sfenner
228356893Sfenner/*
228456893Sfenner * Handle calls to the AFS BOS service
228556893Sfenner */
228656893Sfenner
228756893Sfennerstatic void
228856893Sfennerbos_print(register const u_char *bp, int length)
228956893Sfenner{
229056893Sfenner	int bos_op;
229156893Sfenner
2292127668Sbms	if (length <= (int)sizeof(struct rx_header))
229356893Sfenner		return;
229456893Sfenner
2295127668Sbms	if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
229656893Sfenner		goto trunc;
229756893Sfenner	}
229856893Sfenner
229956893Sfenner	/*
230056893Sfenner	 * Print out the afs call we're invoking.  The table used here was
230156893Sfenner	 * gleaned from bozo/bosint.xg
230256893Sfenner	 */
230356893Sfenner
230475115Sfenner	bos_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
230556893Sfenner
230656893Sfenner	printf(" bos call %s", tok2str(bos_req, "op#%d", bos_op));
230756893Sfenner
230856893Sfenner	/*
230956893Sfenner	 * Decode some of the arguments to the BOS calls
231056893Sfenner	 */
231156893Sfenner
231256893Sfenner	bp += sizeof(struct rx_header) + 4;
231356893Sfenner
231456893Sfenner	switch (bos_op) {
231556893Sfenner		case 80:	/* Create B node */
231656893Sfenner			printf(" type");
231756893Sfenner			STROUT(BOSNAMEMAX);
231856893Sfenner			printf(" instance");
231956893Sfenner			STROUT(BOSNAMEMAX);
232056893Sfenner			break;
232156893Sfenner		case 81:	/* Delete B node */
232256893Sfenner		case 83:	/* Get status */
232356893Sfenner		case 85:	/* Get instance info */
232456893Sfenner		case 87:	/* Add super user */
232556893Sfenner		case 88:	/* Delete super user */
232656893Sfenner		case 93:	/* Set cell name */
232756893Sfenner		case 96:	/* Add cell host */
232856893Sfenner		case 97:	/* Delete cell host */
232956893Sfenner		case 104:	/* Restart */
233056893Sfenner		case 106:	/* Uninstall */
233156893Sfenner		case 108:	/* Exec */
233256893Sfenner		case 112:	/* Getlog */
233356893Sfenner		case 114:	/* Get instance strings */
233456893Sfenner			STROUT(BOSNAMEMAX);
233556893Sfenner			break;
233656893Sfenner		case 82:	/* Set status */
233756893Sfenner		case 98:	/* Set T status */
233856893Sfenner			STROUT(BOSNAMEMAX);
233956893Sfenner			printf(" status");
234056893Sfenner			INTOUT();
234156893Sfenner			break;
234256893Sfenner		case 86:	/* Get instance parm */
234356893Sfenner			STROUT(BOSNAMEMAX);
234456893Sfenner			printf(" num");
234556893Sfenner			INTOUT();
234656893Sfenner			break;
234756893Sfenner		case 84:	/* Enumerate instance */
234856893Sfenner		case 89:	/* List super users */
234956893Sfenner		case 90:	/* List keys */
235056893Sfenner		case 91:	/* Add key */
235156893Sfenner		case 92:	/* Delete key */
235256893Sfenner		case 95:	/* Get cell host */
235356893Sfenner			INTOUT();
235456893Sfenner			break;
235556893Sfenner		case 105:	/* Install */
235656893Sfenner			STROUT(BOSNAMEMAX);
235756893Sfenner			printf(" size");
235856893Sfenner			INTOUT();
235956893Sfenner			printf(" flags");
236056893Sfenner			INTOUT();
236156893Sfenner			printf(" date");
236256893Sfenner			INTOUT();
236356893Sfenner			break;
236456893Sfenner		default:
236556893Sfenner			;
236656893Sfenner	}
236756893Sfenner
236856893Sfenner	return;
236956893Sfenner
237056893Sfennertrunc:
237156893Sfenner	printf(" [|bos]");
237256893Sfenner}
237356893Sfenner
237456893Sfenner/*
237556893Sfenner * Handle replies to the AFS BOS Service
237656893Sfenner */
237756893Sfenner
237856893Sfennerstatic void
237956893Sfennerbos_reply_print(register const u_char *bp, int length, int32_t opcode)
238056893Sfenner{
238156893Sfenner	struct rx_header *rxh;
238256893Sfenner
2383127668Sbms	if (length <= (int)sizeof(struct rx_header))
238456893Sfenner		return;
238556893Sfenner
238656893Sfenner	rxh = (struct rx_header *) bp;
238756893Sfenner
238856893Sfenner	/*
238956893Sfenner	 * Print out the afs call we're invoking.  The table used here was
239056893Sfenner	 * gleaned from volser/volint.xg
239156893Sfenner	 */
2392127668Sbms
239356893Sfenner	printf(" bos reply %s", tok2str(bos_req, "op#%d", opcode));
239456893Sfenner
239556893Sfenner	bp += sizeof(struct rx_header);
239656893Sfenner
239756893Sfenner	/*
239856893Sfenner	 * If it was a data packet, interpret the response.
239956893Sfenner	 */
240056893Sfenner
240156893Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA)
240256893Sfenner		/* Well, no, not really.  Leave this for later */
240356893Sfenner		;
240456893Sfenner	else {
240556893Sfenner		/*
240656893Sfenner		 * Otherwise, just print out the return code
240756893Sfenner		 */
240856893Sfenner		printf(" errcode");
240956893Sfenner		INTOUT();
241056893Sfenner	}
241156893Sfenner
241256893Sfenner	return;
241356893Sfenner
241456893Sfennertrunc:
241556893Sfenner	printf(" [|bos]");
241656893Sfenner}
241756893Sfenner
241856893Sfenner/*
241956893Sfenner * Check to see if this is a Ubik opcode.
242056893Sfenner */
242156893Sfenner
242256893Sfennerstatic int
242356893Sfenneris_ubik(u_int32_t opcode)
242456893Sfenner{
242556893Sfenner	if ((opcode >= VOTE_LOW && opcode <= VOTE_HIGH) ||
242656893Sfenner	    (opcode >= DISK_LOW && opcode <= DISK_HIGH))
242756893Sfenner		return(1);
242856893Sfenner	else
242956893Sfenner		return(0);
243056893Sfenner}
243156893Sfenner
243256893Sfenner/*
243356893Sfenner * Handle Ubik opcodes to any one of the replicated database services
243456893Sfenner */
243556893Sfenner
243656893Sfennerstatic void
2437127668Sbmsubik_print(register const u_char *bp)
243856893Sfenner{
243956893Sfenner	int ubik_op;
244056893Sfenner	int32_t temp;
244156893Sfenner
244256893Sfenner	/*
244356893Sfenner	 * Print out the afs call we're invoking.  The table used here was
244456893Sfenner	 * gleaned from ubik/ubik_int.xg
244556893Sfenner	 */
244656893Sfenner
244775115Sfenner	ubik_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
244856893Sfenner
244956893Sfenner	printf(" ubik call %s", tok2str(ubik_req, "op#%d", ubik_op));
245056893Sfenner
245156893Sfenner	/*
245256893Sfenner	 * Decode some of the arguments to the Ubik calls
245356893Sfenner	 */
245456893Sfenner
245556893Sfenner	bp += sizeof(struct rx_header) + 4;
245656893Sfenner
245756893Sfenner	switch (ubik_op) {
245856893Sfenner		case 10000:		/* Beacon */
245975115Sfenner			TCHECK2(bp[0], 4);
246075115Sfenner			temp = EXTRACT_32BITS(bp);
246156893Sfenner			bp += sizeof(int32_t);
246256893Sfenner			printf(" syncsite %s", temp ? "yes" : "no");
246356893Sfenner			printf(" votestart");
246456893Sfenner			DATEOUT();
246556893Sfenner			printf(" dbversion");
246656893Sfenner			UBIK_VERSIONOUT();
246756893Sfenner			printf(" tid");
246856893Sfenner			UBIK_VERSIONOUT();
246956893Sfenner			break;
247056893Sfenner		case 10003:		/* Get sync site */
247156893Sfenner			printf(" site");
247256893Sfenner			UINTOUT();
247356893Sfenner			break;
247456893Sfenner		case 20000:		/* Begin */
247556893Sfenner		case 20001:		/* Commit */
247656893Sfenner		case 20007:		/* Abort */
247756893Sfenner		case 20008:		/* Release locks */
247856893Sfenner		case 20010:		/* Writev */
247956893Sfenner			printf(" tid");
248056893Sfenner			UBIK_VERSIONOUT();
248156893Sfenner			break;
248256893Sfenner		case 20002:		/* Lock */
248356893Sfenner			printf(" tid");
248456893Sfenner			UBIK_VERSIONOUT();
248556893Sfenner			printf(" file");
248656893Sfenner			INTOUT();
248756893Sfenner			printf(" pos");
248856893Sfenner			INTOUT();
248956893Sfenner			printf(" length");
249056893Sfenner			INTOUT();
249175115Sfenner			temp = EXTRACT_32BITS(bp);
249256893Sfenner			bp += sizeof(int32_t);
249356893Sfenner			tok2str(ubik_lock_types, "type %d", temp);
249456893Sfenner			break;
249556893Sfenner		case 20003:		/* Write */
249656893Sfenner			printf(" tid");
249756893Sfenner			UBIK_VERSIONOUT();
249856893Sfenner			printf(" file");
249956893Sfenner			INTOUT();
250056893Sfenner			printf(" pos");
250156893Sfenner			INTOUT();
250256893Sfenner			break;
250356893Sfenner		case 20005:		/* Get file */
250456893Sfenner			printf(" file");
250556893Sfenner			INTOUT();
250656893Sfenner			break;
250756893Sfenner		case 20006:		/* Send file */
250856893Sfenner			printf(" file");
250956893Sfenner			INTOUT();
251056893Sfenner			printf(" length");
251156893Sfenner			INTOUT();
251256893Sfenner			printf(" dbversion");
251356893Sfenner			UBIK_VERSIONOUT();
251456893Sfenner			break;
251556893Sfenner		case 20009:		/* Truncate */
251656893Sfenner			printf(" tid");
251756893Sfenner			UBIK_VERSIONOUT();
251856893Sfenner			printf(" file");
251956893Sfenner			INTOUT();
252056893Sfenner			printf(" length");
252156893Sfenner			INTOUT();
252256893Sfenner			break;
252356893Sfenner		case 20012:		/* Set version */
252456893Sfenner			printf(" tid");
252556893Sfenner			UBIK_VERSIONOUT();
252656893Sfenner			printf(" oldversion");
252756893Sfenner			UBIK_VERSIONOUT();
252856893Sfenner			printf(" newversion");
252956893Sfenner			UBIK_VERSIONOUT();
253056893Sfenner			break;
253156893Sfenner		default:
253256893Sfenner			;
253356893Sfenner	}
253456893Sfenner
253556893Sfenner	return;
253656893Sfenner
253756893Sfennertrunc:
253856893Sfenner	printf(" [|ubik]");
253956893Sfenner}
254056893Sfenner
254156893Sfenner/*
254256893Sfenner * Handle Ubik replies to any one of the replicated database services
254356893Sfenner */
254456893Sfenner
254556893Sfennerstatic void
254656893Sfennerubik_reply_print(register const u_char *bp, int length, int32_t opcode)
254756893Sfenner{
254856893Sfenner	struct rx_header *rxh;
254956893Sfenner
2550127668Sbms	if (length < (int)sizeof(struct rx_header))
255156893Sfenner		return;
255256893Sfenner
255356893Sfenner	rxh = (struct rx_header *) bp;
255456893Sfenner
255556893Sfenner	/*
255656893Sfenner	 * Print out the ubik call we're invoking.  This table was gleaned
255756893Sfenner	 * from ubik/ubik_int.xg
255856893Sfenner	 */
255956893Sfenner
256056893Sfenner	printf(" ubik reply %s", tok2str(ubik_req, "op#%d", opcode));
256156893Sfenner
256256893Sfenner	bp += sizeof(struct rx_header);
256356893Sfenner
256456893Sfenner	/*
256556893Sfenner	 * If it was a data packet, print out the arguments to the Ubik calls
256656893Sfenner	 */
2567127668Sbms
256856893Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA)
256956893Sfenner		switch (opcode) {
257056893Sfenner		case 10000:		/* Beacon */
257156893Sfenner			printf(" vote no");
257256893Sfenner			break;
257356893Sfenner		case 20004:		/* Get version */
257456893Sfenner			printf(" dbversion");
257556893Sfenner			UBIK_VERSIONOUT();
257656893Sfenner			break;
257756893Sfenner		default:
257856893Sfenner			;
257956893Sfenner		}
2580127668Sbms
258156893Sfenner	/*
258256893Sfenner	 * Otherwise, print out "yes" it it was a beacon packet (because
258356893Sfenner	 * that's how yes votes are returned, go figure), otherwise
258456893Sfenner	 * just print out the error code.
258556893Sfenner	 */
258656893Sfenner
258756893Sfenner	else
258856893Sfenner		switch (opcode) {
258956893Sfenner		case 10000:		/* Beacon */
259056893Sfenner			printf(" vote yes until");
259156893Sfenner			DATEOUT();
259256893Sfenner			break;
259356893Sfenner		default:
259456893Sfenner			printf(" errcode");
259556893Sfenner			INTOUT();
259656893Sfenner		}
259756893Sfenner
259856893Sfenner	return;
259956893Sfenner
260056893Sfennertrunc:
260156893Sfenner	printf(" [|ubik]");
260256893Sfenner}
260375115Sfenner
260475115Sfenner/*
260575115Sfenner * Handle RX ACK packets.
260675115Sfenner */
260775115Sfenner
260875115Sfennerstatic void
260975115Sfennerrx_ack_print(register const u_char *bp, int length)
261075115Sfenner{
261175115Sfenner	struct rx_ackPacket *rxa;
261275115Sfenner	int i, start, last;
2613172683Smlaier	u_int32_t firstPacket;
261475115Sfenner
2615127668Sbms	if (length < (int)sizeof(struct rx_header))
261675115Sfenner		return;
261775115Sfenner
261875115Sfenner	bp += sizeof(struct rx_header);
261975115Sfenner
262075115Sfenner	/*
262175115Sfenner	 * This may seem a little odd .... the rx_ackPacket structure
262275115Sfenner	 * contains an array of individual packet acknowledgements
262375115Sfenner	 * (used for selective ack/nack), but since it's variable in size,
262475115Sfenner	 * we don't want to truncate based on the size of the whole
262575115Sfenner	 * rx_ackPacket structure.
262675115Sfenner	 */
262775115Sfenner
262875115Sfenner	TCHECK2(bp[0], sizeof(struct rx_ackPacket) - RX_MAXACKS);
262975115Sfenner
263075115Sfenner	rxa = (struct rx_ackPacket *) bp;
263175115Sfenner	bp += (sizeof(struct rx_ackPacket) - RX_MAXACKS);
263275115Sfenner
263375115Sfenner	/*
263475115Sfenner	 * Print out a few useful things from the ack packet structure
263575115Sfenner	 */
263675115Sfenner
263775115Sfenner	if (vflag > 2)
263875115Sfenner		printf(" bufspace %d maxskew %d",
263975115Sfenner		       (int) EXTRACT_16BITS(&rxa->bufferSpace),
264075115Sfenner		       (int) EXTRACT_16BITS(&rxa->maxSkew));
2641127668Sbms
2642172683Smlaier	firstPacket = EXTRACT_32BITS(&rxa->firstPacket);
264375115Sfenner	printf(" first %d serial %d reason %s",
2644172683Smlaier	       firstPacket, EXTRACT_32BITS(&rxa->serial),
264575115Sfenner	       tok2str(rx_ack_reasons, "#%d", (int) rxa->reason));
2646127668Sbms
264775115Sfenner	/*
264875115Sfenner	 * Okay, now we print out the ack array.  The way _this_ works
264975115Sfenner	 * is that we start at "first", and step through the ack array.
265075115Sfenner	 * If we have a contiguous range of acks/nacks, try to
265175115Sfenner	 * collapse them into a range.
265275115Sfenner	 *
265375115Sfenner	 * If you're really clever, you might have noticed that this
265475115Sfenner	 * doesn't seem quite correct.  Specifically, due to structure
265575115Sfenner	 * padding, sizeof(struct rx_ackPacket) - RX_MAXACKS won't actually
265675115Sfenner	 * yield the start of the ack array (because RX_MAXACKS is 255
265775115Sfenner	 * and the structure will likely get padded to a 2 or 4 byte
265875115Sfenner	 * boundary).  However, this is the way it's implemented inside
2659127668Sbms	 * of AFS - the start of the extra fields are at
266075115Sfenner	 * sizeof(struct rx_ackPacket) - RX_MAXACKS + nAcks, which _isn't_
266175115Sfenner	 * the exact start of the ack array.  Sigh.  That's why we aren't
266275115Sfenner	 * using bp, but instead use rxa->acks[].  But nAcks gets added
266375115Sfenner	 * to bp after this, so bp ends up at the right spot.  Go figure.
266475115Sfenner	 */
266575115Sfenner
266675115Sfenner	if (rxa->nAcks != 0) {
266775115Sfenner
266875115Sfenner		TCHECK2(bp[0], rxa->nAcks);
266975115Sfenner
267075115Sfenner		/*
267175115Sfenner		 * Sigh, this is gross, but it seems to work to collapse
267275115Sfenner		 * ranges correctly.
267375115Sfenner		 */
267475115Sfenner
267575115Sfenner		for (i = 0, start = last = -2; i < rxa->nAcks; i++)
267675115Sfenner			if (rxa->acks[i] == RX_ACK_TYPE_ACK) {
267775115Sfenner
267875115Sfenner				/*
267975115Sfenner				 * I figured this deserved _some_ explanation.
268075115Sfenner				 * First, print "acked" and the packet seq
268175115Sfenner				 * number if this is the first time we've
268275115Sfenner				 * seen an acked packet.
268375115Sfenner				 */
268475115Sfenner
268575115Sfenner				if (last == -2) {
268675115Sfenner					printf(" acked %d",
2687172683Smlaier					       firstPacket + i);
268875115Sfenner					start = i;
268975115Sfenner				}
269075115Sfenner
269175115Sfenner				/*
269275115Sfenner				 * Otherwise, if the there is a skip in
269375115Sfenner				 * the range (such as an nacked packet in
269475115Sfenner				 * the middle of some acked packets),
269575115Sfenner				 * then print the current packet number
269675115Sfenner				 * seperated from the last number by
269775115Sfenner				 * a comma.
269875115Sfenner				 */
269975115Sfenner
270075115Sfenner				else if (last != i - 1) {
2701172683Smlaier					printf(",%d", firstPacket + i);
270275115Sfenner					start = i;
270375115Sfenner				}
270475115Sfenner
270575115Sfenner				/*
270675115Sfenner				 * We always set last to the value of
270775115Sfenner				 * the last ack we saw.  Conversely, start
270875115Sfenner				 * is set to the value of the first ack
270975115Sfenner				 * we saw in a range.
271075115Sfenner				 */
271175115Sfenner
271275115Sfenner				last = i;
271375115Sfenner
271475115Sfenner				/*
271575115Sfenner				 * Okay, this bit a code gets executed when
271675115Sfenner				 * we hit a nack ... in _this_ case we
271775115Sfenner				 * want to print out the range of packets
271875115Sfenner				 * that were acked, so we need to print
271975115Sfenner				 * the _previous_ packet number seperated
272075115Sfenner				 * from the first by a dash (-).  Since we
272175115Sfenner				 * already printed the first packet above,
272275115Sfenner				 * just print the final packet.  Don't
272375115Sfenner				 * do this if there will be a single-length
272475115Sfenner				 * range.
272575115Sfenner				 */
272675115Sfenner			} else if (last == i - 1 && start != last)
2727172683Smlaier				printf("-%d", firstPacket + i - 1);
2728127668Sbms
272975115Sfenner		/*
273075115Sfenner		 * So, what's going on here?  We ran off the end of the
273175115Sfenner		 * ack list, and if we got a range we need to finish it up.
273275115Sfenner		 * So we need to determine if the last packet in the list
273375115Sfenner		 * was an ack (if so, then last will be set to it) and
273475115Sfenner		 * we need to see if the last range didn't start with the
273575115Sfenner		 * last packet (because if it _did_, then that would mean
273675115Sfenner		 * that the packet number has already been printed and
273775115Sfenner		 * we don't need to print it again).
273875115Sfenner		 */
273975115Sfenner
274075115Sfenner		if (last == i - 1 && start != last)
2741172683Smlaier			printf("-%d", firstPacket + i - 1);
274275115Sfenner
274375115Sfenner		/*
274475115Sfenner		 * Same as above, just without comments
274575115Sfenner		 */
2746127668Sbms
274775115Sfenner		for (i = 0, start = last = -2; i < rxa->nAcks; i++)
274875115Sfenner			if (rxa->acks[i] == RX_ACK_TYPE_NACK) {
274975115Sfenner				if (last == -2) {
275075115Sfenner					printf(" nacked %d",
2751172683Smlaier					       firstPacket + i);
275275115Sfenner					start = i;
275375115Sfenner				} else if (last != i - 1) {
2754172683Smlaier					printf(",%d", firstPacket + i);
275575115Sfenner					start = i;
275675115Sfenner				}
275775115Sfenner				last = i;
275875115Sfenner			} else if (last == i - 1 && start != last)
2759172683Smlaier				printf("-%d", firstPacket + i - 1);
2760127668Sbms
276175115Sfenner		if (last == i - 1 && start != last)
2762172683Smlaier			printf("-%d", firstPacket + i - 1);
276375115Sfenner
276475115Sfenner		bp += rxa->nAcks;
276575115Sfenner	}
276675115Sfenner
276775115Sfenner
276875115Sfenner	/*
276975115Sfenner	 * These are optional fields; depending on your version of AFS,
277075115Sfenner	 * you may or may not see them
277175115Sfenner	 */
277275115Sfenner
277375115Sfenner#define TRUNCRET(n)	if (snapend - bp + 1 <= n) return;
277475115Sfenner
277575115Sfenner	if (vflag > 1) {
277675115Sfenner		TRUNCRET(4);
277775115Sfenner		printf(" ifmtu");
277875115Sfenner		INTOUT();
277975115Sfenner
278075115Sfenner		TRUNCRET(4);
278175115Sfenner		printf(" maxmtu");
278275115Sfenner		INTOUT();
278375115Sfenner
278475115Sfenner		TRUNCRET(4);
278575115Sfenner		printf(" rwind");
278675115Sfenner		INTOUT();
278775115Sfenner
278875115Sfenner		TRUNCRET(4);
278975115Sfenner		printf(" maxpackets");
279075115Sfenner		INTOUT();
279175115Sfenner	}
279275115Sfenner
279375115Sfenner	return;
279475115Sfenner
279575115Sfennertrunc:
279675115Sfenner	printf(" [|ack]");
279775115Sfenner}
279875115Sfenner#undef TRUNCRET
2799