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