print-rx.c revision 98524
156893Sfenner/*
298524Sfenner * Copyright: (c) 2000 United States Government as represented by the
398524Sfenner *	Secretary of the Navy. All rights reserved.
498524Sfenner *
598524Sfenner * Redistribution and use in source and binary forms, with or without
698524Sfenner * modification, are permitted provided that the following conditions
798524Sfenner * are met:
898524Sfenner *
998524Sfenner *   1. Redistributions of source code must retain the above copyright
1098524Sfenner *      notice, this list of conditions and the following disclaimer.
1198524Sfenner *   2. Redistributions in binary form must reproduce the above copyright
1298524Sfenner *      notice, this list of conditions and the following disclaimer in
1398524Sfenner *      the documentation and/or other materials provided with the
1498524Sfenner *      distribution.
1598524Sfenner *   3. The names of the authors may not be used to endorse or promote
1698524Sfenner *      products derived from this software without specific prior
1798524Sfenner *      written permission.
1898524Sfenner *
1998524Sfenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2098524Sfenner * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2198524Sfenner * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2298524Sfenner */
2398524Sfenner/*
2456893Sfenner * This code unmangles RX packets.  RX is the mutant form of RPC that AFS
2556893Sfenner * uses to communicate between clients and servers.
2656893Sfenner *
2756893Sfenner * In this code, I mainly concern myself with decoding the AFS calls, not
2856893Sfenner * with the guts of RX, per se.
2956893Sfenner *
3056893Sfenner * Bah.  If I never look at rx_packet.h again, it will be too soon.
3156893Sfenner *
3256893Sfenner * Ken Hornstein <kenh@cmf.nrl.navy.mil>
3356893Sfenner */
3456893Sfenner
3556893Sfenner#ifndef lint
3656893Sfennerstatic const char rcsid[] =
3798524Sfenner    "@(#) $Header: /tcpdump/master/tcpdump/print-rx.c,v 1.27 2001/10/20 07:41:55 itojun Exp $";
3856893Sfenner#endif
3956893Sfenner
4056893Sfenner#ifdef HAVE_CONFIG_H
4156893Sfenner#include "config.h"
4256893Sfenner#endif
4356893Sfenner
4456893Sfenner#include <stdio.h>
4575115Sfenner#include <stdlib.h>
4656893Sfenner#include <string.h>
4775115Sfenner#include <time.h>
4856893Sfenner#include <sys/param.h>
4956893Sfenner#include <sys/time.h>
5056893Sfenner#include <sys/types.h>
5156893Sfenner#include <sys/socket.h>
5256893Sfenner#include <netinet/in.h>
5356893Sfenner#include <arpa/inet.h>
5456893Sfenner
5556893Sfenner#include "interface.h"
5656893Sfenner#include "addrtoname.h"
5775115Sfenner#include "extract.h"
5856893Sfenner
5956893Sfenner#include "rx.h"
6056893Sfenner
6175115Sfenner#include "ip.h"
6275115Sfenner
6356893Sfennerstatic struct tok rx_types[] = {
6456893Sfenner	{ RX_PACKET_TYPE_DATA,		"data" },
6556893Sfenner	{ RX_PACKET_TYPE_ACK,		"ack" },
6656893Sfenner	{ RX_PACKET_TYPE_BUSY,		"busy" },
6756893Sfenner	{ RX_PACKET_TYPE_ABORT,		"abort" },
6856893Sfenner	{ RX_PACKET_TYPE_ACKALL,	"ackall" },
6956893Sfenner	{ RX_PACKET_TYPE_CHALLENGE,	"challenge" },
7056893Sfenner	{ RX_PACKET_TYPE_RESPONSE,	"response" },
7156893Sfenner	{ RX_PACKET_TYPE_DEBUG,		"debug" },
7256893Sfenner	{ RX_PACKET_TYPE_PARAMS,	"params" },
7356893Sfenner	{ RX_PACKET_TYPE_VERSION,	"version" },
7456893Sfenner	{ 0,				NULL },
7556893Sfenner};
7656893Sfenner
7798524Sfennerstatic struct double_tok {
7898524Sfenner	int flag;		/* Rx flag */
7998524Sfenner	int packetType;		/* Packet type */
8098524Sfenner	char *s;		/* Flag string */
8198524Sfenner} rx_flags[] = {
8298524Sfenner	{ RX_CLIENT_INITIATED,	0,			"client-init" },
8398524Sfenner	{ RX_REQUEST_ACK,	0,			"req-ack" },
8498524Sfenner	{ RX_LAST_PACKET,	0,			"last-pckt" },
8598524Sfenner	{ RX_MORE_PACKETS,	0,			"more-pckts" },
8698524Sfenner	{ RX_FREE_PACKET,	0,			"free-pckt" },
8798524Sfenner	{ RX_SLOW_START_OK,	RX_PACKET_TYPE_ACK,	"slow-start" },
8898524Sfenner	{ RX_JUMBO_PACKET,	RX_PACKET_TYPE_DATA,	"jumbogram" }
8956893Sfenner};
9056893Sfenner
9156893Sfennerstatic struct tok fs_req[] = {
9256893Sfenner	{ 130,		"fetch-data" },
9356893Sfenner	{ 131,		"fetch-acl" },
9456893Sfenner	{ 132,		"fetch-status" },
9556893Sfenner	{ 133,		"store-data" },
9656893Sfenner	{ 134,		"store-acl" },
9756893Sfenner	{ 135,		"store-status" },
9856893Sfenner	{ 136,		"remove-file" },
9956893Sfenner	{ 137,		"create-file" },
10056893Sfenner	{ 138,		"rename" },
10156893Sfenner	{ 139,		"symlink" },
10256893Sfenner	{ 140,		"link" },
10356893Sfenner	{ 141,		"makedir" },
10456893Sfenner	{ 142,		"rmdir" },
10556893Sfenner	{ 143,		"oldsetlock" },
10656893Sfenner	{ 144,		"oldextlock" },
10756893Sfenner	{ 145,		"oldrellock" },
10856893Sfenner	{ 146,		"get-stats" },
10956893Sfenner	{ 147,		"give-cbs" },
11056893Sfenner	{ 148,		"get-vlinfo" },
11156893Sfenner	{ 149,		"get-vlstats" },
11256893Sfenner	{ 150,		"set-vlstats" },
11356893Sfenner	{ 151,		"get-rootvl" },
11456893Sfenner	{ 152,		"check-token" },
11556893Sfenner	{ 153,		"get-time" },
11656893Sfenner	{ 154,		"nget-vlinfo" },
11756893Sfenner	{ 155,		"bulk-stat" },
11856893Sfenner	{ 156,		"setlock" },
11956893Sfenner	{ 157,		"extlock" },
12056893Sfenner	{ 158,		"rellock" },
12156893Sfenner	{ 159,		"xstat-ver" },
12256893Sfenner	{ 160,		"get-xstat" },
12356893Sfenner	{ 161,		"dfs-lookup" },
12456893Sfenner	{ 162,		"dfs-flushcps" },
12556893Sfenner	{ 163,		"dfs-symlink" },
12698524Sfenner	{ 220,		"residency" },
12756893Sfenner	{ 0,		NULL },
12856893Sfenner};
12956893Sfenner
13056893Sfennerstatic struct tok cb_req[] = {
13156893Sfenner	{ 204,		"callback" },
13256893Sfenner	{ 205,		"initcb" },
13356893Sfenner	{ 206,		"probe" },
13456893Sfenner	{ 207,		"getlock" },
13556893Sfenner	{ 208,		"getce" },
13656893Sfenner	{ 209,		"xstatver" },
13756893Sfenner	{ 210,		"getxstat" },
13856893Sfenner	{ 211,		"initcb2" },
13956893Sfenner	{ 212,		"whoareyou" },
14056893Sfenner	{ 213,		"initcb3" },
14156893Sfenner	{ 214,		"probeuuid" },
14298524Sfenner	{ 215,		"getsrvprefs" },
14398524Sfenner	{ 216,		"getcellservdb" },
14498524Sfenner	{ 217,		"getlocalcell" },
14598524Sfenner	{ 218,		"getcacheconf" },
14656893Sfenner	{ 0,		NULL },
14756893Sfenner};
14856893Sfenner
14956893Sfennerstatic struct tok pt_req[] = {
15056893Sfenner	{ 500,		"new-user" },
15156893Sfenner	{ 501,		"where-is-it" },
15256893Sfenner	{ 502,		"dump-entry" },
15356893Sfenner	{ 503,		"add-to-group" },
15456893Sfenner	{ 504,		"name-to-id" },
15556893Sfenner	{ 505,		"id-to-name" },
15656893Sfenner	{ 506,		"delete" },
15756893Sfenner	{ 507,		"remove-from-group" },
15856893Sfenner	{ 508,		"get-cps" },
15956893Sfenner	{ 509,		"new-entry" },
16056893Sfenner	{ 510,		"list-max" },
16156893Sfenner	{ 511,		"set-max" },
16256893Sfenner	{ 512,		"list-entry" },
16356893Sfenner	{ 513,		"change-entry" },
16456893Sfenner	{ 514,		"list-elements" },
16556893Sfenner	{ 515,		"same-mbr-of" },
16656893Sfenner	{ 516,		"set-fld-sentry" },
16756893Sfenner	{ 517,		"list-owned" },
16856893Sfenner	{ 518,		"get-cps2" },
16956893Sfenner	{ 519,		"get-host-cps" },
17056893Sfenner	{ 520,		"update-entry" },
17198524Sfenner	{ 521,		"list-entries" },
17256893Sfenner	{ 0,		NULL },
17356893Sfenner};
17456893Sfenner
17556893Sfennerstatic struct tok vldb_req[] = {
17656893Sfenner	{ 501,		"create-entry" },
17756893Sfenner	{ 502,		"delete-entry" },
17856893Sfenner	{ 503,		"get-entry-by-id" },
17956893Sfenner	{ 504,		"get-entry-by-name" },
18056893Sfenner	{ 505,		"get-new-volume-id" },
18156893Sfenner	{ 506,		"replace-entry" },
18256893Sfenner	{ 507,		"update-entry" },
18356893Sfenner	{ 508,		"setlock" },
18456893Sfenner	{ 509,		"releaselock" },
18556893Sfenner	{ 510,		"list-entry" },
18656893Sfenner	{ 511,		"list-attrib" },
18756893Sfenner	{ 512,		"linked-list" },
18856893Sfenner	{ 513,		"get-stats" },
18956893Sfenner	{ 514,		"probe" },
19056893Sfenner	{ 515,		"get-addrs" },
19156893Sfenner	{ 516,		"change-addr" },
19256893Sfenner	{ 517,		"create-entry-n" },
19356893Sfenner	{ 518,		"get-entry-by-id-n" },
19456893Sfenner	{ 519,		"get-entry-by-name-n" },
19556893Sfenner	{ 520,		"replace-entry-n" },
19656893Sfenner	{ 521,		"list-entry-n" },
19756893Sfenner	{ 522,		"list-attrib-n" },
19856893Sfenner	{ 523,		"linked-list-n" },
19956893Sfenner	{ 524,		"update-entry-by-name" },
20056893Sfenner	{ 525,		"create-entry-u" },
20156893Sfenner	{ 526,		"get-entry-by-id-u" },
20256893Sfenner	{ 527,		"get-entry-by-name-u" },
20356893Sfenner	{ 528,		"replace-entry-u" },
20456893Sfenner	{ 529,		"list-entry-u" },
20556893Sfenner	{ 530,		"list-attrib-u" },
20656893Sfenner	{ 531,		"linked-list-u" },
20756893Sfenner	{ 532,		"regaddr" },
20856893Sfenner	{ 533,		"get-addrs-u" },
20998524Sfenner	{ 534,		"list-attrib-n2" },
21056893Sfenner	{ 0,		NULL },
21156893Sfenner};
21256893Sfenner
21356893Sfennerstatic struct tok kauth_req[] = {
21456893Sfenner	{ 1,		"auth-old" },
21556893Sfenner	{ 21,		"authenticate" },
21656893Sfenner	{ 22,		"authenticate-v2" },
21756893Sfenner	{ 2,		"change-pw" },
21856893Sfenner	{ 3,		"get-ticket-old" },
21956893Sfenner	{ 23,		"get-ticket" },
22056893Sfenner	{ 4,		"set-pw" },
22156893Sfenner	{ 5,		"set-fields" },
22256893Sfenner	{ 6,		"create-user" },
22356893Sfenner	{ 7,		"delete-user" },
22456893Sfenner	{ 8,		"get-entry" },
22556893Sfenner	{ 9,		"list-entry" },
22656893Sfenner	{ 10,		"get-stats" },
22756893Sfenner	{ 11,		"debug" },
22856893Sfenner	{ 12,		"get-pw" },
22956893Sfenner	{ 13,		"get-random-key" },
23056893Sfenner	{ 14,		"unlock" },
23156893Sfenner	{ 15,		"lock-status" },
23256893Sfenner	{ 0,		NULL },
23356893Sfenner};
23456893Sfenner
23556893Sfennerstatic struct tok vol_req[] = {
23656893Sfenner	{ 100,		"create-volume" },
23756893Sfenner	{ 101,		"delete-volume" },
23856893Sfenner	{ 102,		"restore" },
23956893Sfenner	{ 103,		"forward" },
24056893Sfenner	{ 104,		"end-trans" },
24156893Sfenner	{ 105,		"clone" },
24256893Sfenner	{ 106,		"set-flags" },
24356893Sfenner	{ 107,		"get-flags" },
24456893Sfenner	{ 108,		"trans-create" },
24556893Sfenner	{ 109,		"dump" },
24656893Sfenner	{ 110,		"get-nth-volume" },
24756893Sfenner	{ 111,		"set-forwarding" },
24856893Sfenner	{ 112,		"get-name" },
24956893Sfenner	{ 113,		"get-status" },
25056893Sfenner	{ 114,		"sig-restore" },
25156893Sfenner	{ 115,		"list-partitions" },
25256893Sfenner	{ 116,		"list-volumes" },
25356893Sfenner	{ 117,		"set-id-types" },
25456893Sfenner	{ 118,		"monitor" },
25556893Sfenner	{ 119,		"partition-info" },
25656893Sfenner	{ 120,		"reclone" },
25756893Sfenner	{ 121,		"list-one-volume" },
25856893Sfenner	{ 122,		"nuke" },
25956893Sfenner	{ 123,		"set-date" },
26056893Sfenner	{ 124,		"x-list-volumes" },
26156893Sfenner	{ 125,		"x-list-one-volume" },
26256893Sfenner	{ 126,		"set-info" },
26356893Sfenner	{ 127,		"x-list-partitions" },
26456893Sfenner	{ 128,		"forward-multiple" },
26556893Sfenner	{ 0,		NULL },
26656893Sfenner};
26756893Sfenner
26856893Sfennerstatic struct tok bos_req[] = {
26956893Sfenner	{ 80,		"create-bnode" },
27056893Sfenner	{ 81,		"delete-bnode" },
27156893Sfenner	{ 82,		"set-status" },
27256893Sfenner	{ 83,		"get-status" },
27356893Sfenner	{ 84,		"enumerate-instance" },
27456893Sfenner	{ 85,		"get-instance-info" },
27556893Sfenner	{ 86,		"get-instance-parm" },
27656893Sfenner	{ 87,		"add-superuser" },
27756893Sfenner	{ 88,		"delete-superuser" },
27856893Sfenner	{ 89,		"list-superusers" },
27956893Sfenner	{ 90,		"list-keys" },
28056893Sfenner	{ 91,		"add-key" },
28156893Sfenner	{ 92,		"delete-key" },
28256893Sfenner	{ 93,		"set-cell-name" },
28356893Sfenner	{ 94,		"get-cell-name" },
28456893Sfenner	{ 95,		"get-cell-host" },
28556893Sfenner	{ 96,		"add-cell-host" },
28656893Sfenner	{ 97,		"delete-cell-host" },
28756893Sfenner	{ 98,		"set-t-status" },
28856893Sfenner	{ 99,		"shutdown-all" },
28956893Sfenner	{ 100,		"restart-all" },
29056893Sfenner	{ 101,		"startup-all" },
29156893Sfenner	{ 102,		"set-noauth-flag" },
29256893Sfenner	{ 103,		"re-bozo" },
29356893Sfenner	{ 104,		"restart" },
29456893Sfenner	{ 105,		"start-bozo-install" },
29556893Sfenner	{ 106,		"uninstall" },
29656893Sfenner	{ 107,		"get-dates" },
29756893Sfenner	{ 108,		"exec" },
29856893Sfenner	{ 109,		"prune" },
29956893Sfenner	{ 110,		"set-restart-time" },
30056893Sfenner	{ 111,		"get-restart-time" },
30156893Sfenner	{ 112,		"start-bozo-log" },
30256893Sfenner	{ 113,		"wait-all" },
30356893Sfenner	{ 114,		"get-instance-strings" },
30498524Sfenner	{ 115,		"get-restricted" },
30598524Sfenner	{ 116,		"set-restricted" },
30656893Sfenner	{ 0,		NULL },
30756893Sfenner};
30856893Sfenner
30956893Sfennerstatic struct tok ubik_req[] = {
31056893Sfenner	{ 10000,	"vote-beacon" },
31156893Sfenner	{ 10001,	"vote-debug-old" },
31256893Sfenner	{ 10002,	"vote-sdebug-old" },
31356893Sfenner	{ 10003,	"vote-getsyncsite" },
31456893Sfenner	{ 10004,	"vote-debug" },
31556893Sfenner	{ 10005,	"vote-sdebug" },
31656893Sfenner	{ 20000,	"disk-begin" },
31756893Sfenner	{ 20001,	"disk-commit" },
31856893Sfenner	{ 20002,	"disk-lock" },
31956893Sfenner	{ 20003,	"disk-write" },
32056893Sfenner	{ 20004,	"disk-getversion" },
32156893Sfenner	{ 20005,	"disk-getfile" },
32256893Sfenner	{ 20006,	"disk-sendfile" },
32356893Sfenner	{ 20007,	"disk-abort" },
32456893Sfenner	{ 20008,	"disk-releaselocks" },
32556893Sfenner	{ 20009,	"disk-truncate" },
32656893Sfenner	{ 20010,	"disk-probe" },
32756893Sfenner	{ 20011,	"disk-writev" },
32856893Sfenner	{ 20012,	"disk-interfaceaddr" },
32956893Sfenner	{ 20013,	"disk-setversion" },
33056893Sfenner	{ 0,		NULL },
33156893Sfenner};
33256893Sfenner
33356893Sfenner#define VOTE_LOW	10000
33456893Sfenner#define VOTE_HIGH	10005
33556893Sfenner#define DISK_LOW	20000
33656893Sfenner#define DISK_HIGH	20013
33756893Sfenner
33856893Sfennerstatic struct tok cb_types[] = {
33956893Sfenner	{ 1,		"exclusive" },
34056893Sfenner	{ 2,		"shared" },
34156893Sfenner	{ 3,		"dropped" },
34256893Sfenner	{ 0,		NULL },
34356893Sfenner};
34456893Sfenner
34556893Sfennerstatic struct tok ubik_lock_types[] = {
34656893Sfenner	{ 1,		"read" },
34756893Sfenner	{ 2,		"write" },
34856893Sfenner	{ 3,		"wait" },
34956893Sfenner	{ 0,		NULL },
35056893Sfenner};
35156893Sfenner
35256893Sfennerstatic char *voltype[] = { "read-write", "read-only", "backup" };
35356893Sfenner
35475115Sfennerstatic struct tok afs_fs_errors[] = {
35575115Sfenner	{ 101,		"salvage volume" },
35675115Sfenner	{ 102, 		"no such vnode" },
35775115Sfenner	{ 103, 		"no such volume" },
35875115Sfenner	{ 104, 		"volume exist" },
35975115Sfenner	{ 105, 		"no service" },
36075115Sfenner	{ 106, 		"volume offline" },
36175115Sfenner	{ 107, 		"voline online" },
36275115Sfenner	{ 108, 		"diskfull" },
36375115Sfenner	{ 109, 		"diskquota exceeded" },
36475115Sfenner	{ 110, 		"volume busy" },
36575115Sfenner	{ 111, 		"volume moved" },
36675115Sfenner	{ 112, 		"AFS IO error" },
36775115Sfenner	{ -100,		"restarting fileserver" },
36875115Sfenner	{ 0,		NULL }
36975115Sfenner};
37075115Sfenner
37156893Sfenner/*
37275115Sfenner * Reasons for acknowledging a packet
37375115Sfenner */
37475115Sfenner
37575115Sfennerstatic struct tok rx_ack_reasons[] = {
37675115Sfenner	{ 1,		"ack requested" },
37775115Sfenner	{ 2,		"duplicate packet" },
37875115Sfenner	{ 3,		"out of sequence" },
37975115Sfenner	{ 4,		"exceeds window" },
38075115Sfenner	{ 5,		"no buffer space" },
38175115Sfenner	{ 6,		"ping" },
38275115Sfenner	{ 7,		"ping response" },
38375115Sfenner	{ 8,		"delay" },
38475115Sfenner	{ 0,		NULL },
38575115Sfenner};
38675115Sfenner
38775115Sfenner/*
38856893Sfenner * Cache entries we keep around so we can figure out the RX opcode
38956893Sfenner * numbers for replies.  This allows us to make sense of RX reply packets.
39056893Sfenner */
39156893Sfenner
39256893Sfennerstruct rx_cache_entry {
39356893Sfenner	u_int32_t	callnum;	/* Call number (net order) */
39456893Sfenner	struct in_addr	client;		/* client IP address (net order) */
39556893Sfenner	struct in_addr	server;		/* server IP address (net order) */
39656893Sfenner	int		dport;		/* server port (host order) */
39756893Sfenner	u_short		serviceId;	/* Service identifier (net order) */
39856893Sfenner	u_int32_t	opcode;		/* RX opcode (host order) */
39956893Sfenner};
40056893Sfenner
40156893Sfenner#define RX_CACHE_SIZE	64
40256893Sfenner
40356893Sfennerstatic struct rx_cache_entry	rx_cache[RX_CACHE_SIZE];
40456893Sfenner
40556893Sfennerstatic int	rx_cache_next = 0;
40656893Sfennerstatic int	rx_cache_hint = 0;
40756893Sfennerstatic void	rx_cache_insert(const u_char *, const struct ip *, int, int);
40856893Sfennerstatic int	rx_cache_find(const struct rx_header *, const struct ip *,
40956893Sfenner			      int, int32_t *);
41056893Sfenner
41175115Sfennerstatic void ack_print(const u_char *, int);
41256893Sfennerstatic void fs_print(const u_char *, int);
41356893Sfennerstatic void fs_reply_print(const u_char *, int, int32_t);
41475115Sfennerstatic void acl_print(u_char *, int, u_char *);
41556893Sfennerstatic void cb_print(const u_char *, int);
41656893Sfennerstatic void cb_reply_print(const u_char *, int, int32_t);
41756893Sfennerstatic void prot_print(const u_char *, int);
41856893Sfennerstatic void prot_reply_print(const u_char *, int, int32_t);
41956893Sfennerstatic void vldb_print(const u_char *, int);
42056893Sfennerstatic void vldb_reply_print(const u_char *, int, int32_t);
42156893Sfennerstatic void kauth_print(const u_char *, int);
42256893Sfennerstatic void kauth_reply_print(const u_char *, int, int32_t);
42356893Sfennerstatic void vol_print(const u_char *, int);
42456893Sfennerstatic void vol_reply_print(const u_char *, int, int32_t);
42556893Sfennerstatic void bos_print(const u_char *, int);
42656893Sfennerstatic void bos_reply_print(const u_char *, int, int32_t);
42756893Sfennerstatic void ubik_print(const u_char *, int);
42856893Sfennerstatic void ubik_reply_print(const u_char *, int, int32_t);
42956893Sfenner
43075115Sfennerstatic void rx_ack_print(const u_char *, int);
43175115Sfenner
43256893Sfennerstatic int is_ubik(u_int32_t);
43356893Sfenner
43456893Sfenner/*
43556893Sfenner * Handle the rx-level packet.  See if we know what port it's going to so
43656893Sfenner * we can peek at the afs call inside
43756893Sfenner */
43856893Sfenner
43956893Sfennervoid
44056893Sfennerrx_print(register const u_char *bp, int length, int sport, int dport,
44156893Sfenner	 u_char *bp2)
44256893Sfenner{
44356893Sfenner	register struct rx_header *rxh;
44456893Sfenner	int i;
44556893Sfenner	int32_t opcode;
44656893Sfenner
44756893Sfenner	if (snapend - bp < sizeof (struct rx_header)) {
44856893Sfenner		printf(" [|rx] (%d)", length);
44956893Sfenner		return;
45056893Sfenner	}
45156893Sfenner
45256893Sfenner	rxh = (struct rx_header *) bp;
45356893Sfenner
45456893Sfenner	printf(" rx %s", tok2str(rx_types, "type %d", rxh->type));
45556893Sfenner
45675115Sfenner	if (vflag) {
45756893Sfenner		int firstflag = 0;
45875115Sfenner
45975115Sfenner		if (vflag > 1)
46075115Sfenner			printf(" cid %08x call# %d",
46175115Sfenner			       (int) EXTRACT_32BITS(&rxh->cid),
46275115Sfenner			       (int) EXTRACT_32BITS(&rxh->callNumber));
46375115Sfenner
46475115Sfenner		printf(" seq %d ser %d",
46575115Sfenner		       (int) EXTRACT_32BITS(&rxh->seq),
46675115Sfenner		       (int) EXTRACT_32BITS(&rxh->serial));
46775115Sfenner
46856893Sfenner		if (vflag > 2)
46956893Sfenner			printf(" secindex %d serviceid %hu",
47056893Sfenner				(int) rxh->securityIndex,
47175115Sfenner				EXTRACT_16BITS(&rxh->serviceId));
47275115Sfenner
47375115Sfenner		if (vflag > 1)
47475115Sfenner			for (i = 0; i < NUM_RX_FLAGS; i++) {
47598524Sfenner				if (rxh->flags & rx_flags[i].flag &&
47698524Sfenner				    (!rx_flags[i].packetType ||
47798524Sfenner				     rxh->type == rx_flags[i].packetType)) {
47875115Sfenner					if (!firstflag) {
47975115Sfenner						firstflag = 1;
48075115Sfenner						printf(" ");
48175115Sfenner					} else {
48275115Sfenner						printf(",");
48375115Sfenner					}
48475115Sfenner					printf("<%s>", rx_flags[i].s);
48556893Sfenner				}
48656893Sfenner			}
48756893Sfenner	}
48856893Sfenner
48956893Sfenner	/*
49056893Sfenner	 * Try to handle AFS calls that we know about.  Check the destination
49156893Sfenner	 * port and make sure it's a data packet.  Also, make sure the
49256893Sfenner	 * seq number is 1 (because otherwise it's a continuation packet,
49356893Sfenner	 * and we can't interpret that).  Also, seems that reply packets
49456893Sfenner	 * do not have the client-init flag set, so we check for that
49556893Sfenner	 * as well.
49656893Sfenner	 */
49756893Sfenner
49875115Sfenner 	if (rxh->type == RX_PACKET_TYPE_ACK)
49975115Sfenner 	    ack_print(bp, length);
50075115Sfenner	else if (rxh->type == RX_PACKET_TYPE_DATA &&
50175115Sfenner	    EXTRACT_32BITS(&rxh->seq) == 1 &&
50256893Sfenner	    rxh->flags & RX_CLIENT_INITIATED) {
50356893Sfenner
50456893Sfenner		/*
50556893Sfenner		 * Insert this call into the call cache table, so we
50656893Sfenner		 * have a chance to print out replies
50756893Sfenner		 */
50856893Sfenner
50956893Sfenner		rx_cache_insert(bp, (const struct ip *) bp2, dport, length);
51056893Sfenner
51156893Sfenner		switch (dport) {
51256893Sfenner			case FS_RX_PORT:	/* AFS file service */
51356893Sfenner				fs_print(bp, length);
51456893Sfenner				break;
51556893Sfenner			case CB_RX_PORT:	/* AFS callback service */
51656893Sfenner				cb_print(bp, length);
51756893Sfenner				break;
51856893Sfenner			case PROT_RX_PORT:	/* AFS protection service */
51956893Sfenner				prot_print(bp, length);
52056893Sfenner				break;
52156893Sfenner			case VLDB_RX_PORT:	/* AFS VLDB service */
52256893Sfenner				vldb_print(bp, length);
52356893Sfenner				break;
52456893Sfenner			case KAUTH_RX_PORT:	/* AFS Kerberos auth service */
52556893Sfenner				kauth_print(bp, length);
52656893Sfenner				break;
52756893Sfenner			case VOL_RX_PORT:	/* AFS Volume service */
52856893Sfenner				vol_print(bp, length);
52956893Sfenner				break;
53056893Sfenner			case BOS_RX_PORT:	/* AFS BOS service */
53156893Sfenner				bos_print(bp, length);
53256893Sfenner				break;
53356893Sfenner			default:
53456893Sfenner				;
53556893Sfenner		}
53656893Sfenner
53756893Sfenner	/*
53856893Sfenner	 * If it's a reply (client-init is _not_ set, but seq is one)
53956893Sfenner	 * then look it up in the cache.  If we find it, call the reply
54056893Sfenner	 * printing functions  Note that we handle abort packets here,
54156893Sfenner	 * because printing out the return code can be useful at times.
54256893Sfenner	 */
54356893Sfenner
54456893Sfenner	} else if (((rxh->type == RX_PACKET_TYPE_DATA &&
54575115Sfenner					EXTRACT_32BITS(&rxh->seq) == 1) ||
54656893Sfenner		    rxh->type == RX_PACKET_TYPE_ABORT) &&
54756893Sfenner		   (rxh->flags & RX_CLIENT_INITIATED) == 0 &&
54856893Sfenner		   rx_cache_find(rxh, (const struct ip *) bp2,
54956893Sfenner				 sport, &opcode)) {
55056893Sfenner
55156893Sfenner		switch (sport) {
55256893Sfenner			case FS_RX_PORT:	/* AFS file service */
55356893Sfenner				fs_reply_print(bp, length, opcode);
55456893Sfenner				break;
55556893Sfenner			case CB_RX_PORT:	/* AFS callback service */
55656893Sfenner				cb_reply_print(bp, length, opcode);
55756893Sfenner				break;
55856893Sfenner			case PROT_RX_PORT:	/* AFS PT service */
55956893Sfenner				prot_reply_print(bp, length, opcode);
56056893Sfenner				break;
56156893Sfenner			case VLDB_RX_PORT:	/* AFS VLDB service */
56256893Sfenner				vldb_reply_print(bp, length, opcode);
56356893Sfenner				break;
56456893Sfenner			case KAUTH_RX_PORT:	/* AFS Kerberos auth service */
56556893Sfenner				kauth_reply_print(bp, length, opcode);
56656893Sfenner				break;
56756893Sfenner			case VOL_RX_PORT:	/* AFS Volume service */
56856893Sfenner				vol_reply_print(bp, length, opcode);
56956893Sfenner				break;
57056893Sfenner			case BOS_RX_PORT:	/* AFS BOS service */
57156893Sfenner				bos_reply_print(bp, length, opcode);
57256893Sfenner				break;
57356893Sfenner			default:
57456893Sfenner				;
57556893Sfenner		}
57656893Sfenner
57775115Sfenner	/*
57875115Sfenner	 * If it's an RX ack packet, then use the appropriate ack decoding
57975115Sfenner	 * function (there isn't any service-specific information in the
58075115Sfenner	 * ack packet, so we can use one for all AFS services)
58175115Sfenner	 */
58256893Sfenner
58375115Sfenner	} else if (rxh->type == RX_PACKET_TYPE_ACK)
58475115Sfenner		rx_ack_print(bp, length);
58575115Sfenner
58675115Sfenner
58756893Sfenner	printf(" (%d)", length);
58856893Sfenner}
58956893Sfenner
59056893Sfenner/*
59156893Sfenner * Insert an entry into the cache.  Taken from print-nfs.c
59256893Sfenner */
59356893Sfenner
59456893Sfennerstatic void
59556893Sfennerrx_cache_insert(const u_char *bp, const struct ip *ip, int dport,
59656893Sfenner		int length)
59756893Sfenner{
59856893Sfenner	struct rx_cache_entry *rxent;
59956893Sfenner	const struct rx_header *rxh = (const struct rx_header *) bp;
60056893Sfenner
60156893Sfenner	if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t))
60256893Sfenner		return;
60356893Sfenner
60456893Sfenner	rxent = &rx_cache[rx_cache_next];
60556893Sfenner
60656893Sfenner	if (++rx_cache_next >= RX_CACHE_SIZE)
60756893Sfenner		rx_cache_next = 0;
60856893Sfenner
60956893Sfenner	rxent->callnum = rxh->callNumber;
61056893Sfenner	rxent->client = ip->ip_src;
61156893Sfenner	rxent->server = ip->ip_dst;
61256893Sfenner	rxent->dport = dport;
61356893Sfenner	rxent->serviceId = rxh->serviceId;
61475115Sfenner	rxent->opcode = EXTRACT_32BITS(bp + sizeof(struct rx_header));
61556893Sfenner}
61656893Sfenner
61756893Sfenner/*
61856893Sfenner * Lookup an entry in the cache.  Also taken from print-nfs.c
61956893Sfenner *
62056893Sfenner * Note that because this is a reply, we're looking at the _source_
62156893Sfenner * port.
62256893Sfenner */
62356893Sfenner
62456893Sfennerstatic int
62556893Sfennerrx_cache_find(const struct rx_header *rxh, const struct ip *ip, int sport,
62656893Sfenner	      int32_t *opcode)
62756893Sfenner{
62856893Sfenner	int i;
62956893Sfenner	struct rx_cache_entry *rxent;
63056893Sfenner	u_int32_t clip = ip->ip_dst.s_addr;
63156893Sfenner	u_int32_t sip = ip->ip_src.s_addr;
63256893Sfenner
63356893Sfenner	/* Start the search where we last left off */
63456893Sfenner
63556893Sfenner	i = rx_cache_hint;
63656893Sfenner	do {
63756893Sfenner		rxent = &rx_cache[i];
63856893Sfenner		if (rxent->callnum == rxh->callNumber &&
63956893Sfenner		    rxent->client.s_addr == clip &&
64056893Sfenner		    rxent->server.s_addr == sip &&
64156893Sfenner		    rxent->serviceId == rxh->serviceId &&
64256893Sfenner		    rxent->dport == sport) {
64356893Sfenner
64456893Sfenner			/* We got a match! */
64556893Sfenner
64656893Sfenner			rx_cache_hint = i;
64756893Sfenner			*opcode = rxent->opcode;
64856893Sfenner			return(1);
64956893Sfenner		}
65056893Sfenner		if (++i > RX_CACHE_SIZE)
65156893Sfenner			i = 0;
65256893Sfenner	} while (i != rx_cache_hint);
65356893Sfenner
65456893Sfenner	/* Our search failed */
65556893Sfenner	return(0);
65656893Sfenner}
65756893Sfenner
65856893Sfenner/*
65956893Sfenner * These extrememly grody macros handle the printing of various AFS stuff.
66056893Sfenner */
66156893Sfenner
66256893Sfenner#define FIDOUT() { unsigned long n1, n2, n3; \
66375115Sfenner			TCHECK2(bp[0], sizeof(int32_t) * 3); \
66475115Sfenner			n1 = EXTRACT_32BITS(bp); \
66556893Sfenner			bp += sizeof(int32_t); \
66675115Sfenner			n2 = EXTRACT_32BITS(bp); \
66756893Sfenner			bp += sizeof(int32_t); \
66875115Sfenner			n3 = EXTRACT_32BITS(bp); \
66956893Sfenner			bp += sizeof(int32_t); \
67056893Sfenner			printf(" fid %d/%d/%d", (int) n1, (int) n2, (int) n3); \
67156893Sfenner		}
67256893Sfenner
67380231Sfenner#define STROUT(MAX) { unsigned int i; \
67475115Sfenner			TCHECK2(bp[0], sizeof(int32_t)); \
67580231Sfenner			i = EXTRACT_32BITS(bp); \
67698524Sfenner			if (i > (MAX)) \
67780231Sfenner				goto trunc; \
67856893Sfenner			bp += sizeof(int32_t); \
67980231Sfenner			printf(" \""); \
68080231Sfenner			if (fn_printn(bp, i, snapend)) \
68180231Sfenner				goto trunc; \
68280231Sfenner			printf("\""); \
68356893Sfenner			bp += ((i + sizeof(int32_t) - 1) / sizeof(int32_t)) * sizeof(int32_t); \
68456893Sfenner		}
68556893Sfenner
68656893Sfenner#define INTOUT() { int i; \
68775115Sfenner			TCHECK2(bp[0], sizeof(int32_t)); \
68875115Sfenner			i = (int) EXTRACT_32BITS(bp); \
68956893Sfenner			bp += sizeof(int32_t); \
69056893Sfenner			printf(" %d", i); \
69156893Sfenner		}
69256893Sfenner
69356893Sfenner#define UINTOUT() { unsigned long i; \
69475115Sfenner			TCHECK2(bp[0], sizeof(int32_t)); \
69575115Sfenner			i = EXTRACT_32BITS(bp); \
69656893Sfenner			bp += sizeof(int32_t); \
69756893Sfenner			printf(" %lu", i); \
69856893Sfenner		}
69956893Sfenner
70056893Sfenner#define DATEOUT() { time_t t; struct tm *tm; char str[256]; \
70175115Sfenner			TCHECK2(bp[0], sizeof(int32_t)); \
70275115Sfenner			t = (time_t) EXTRACT_32BITS(bp); \
70356893Sfenner			bp += sizeof(int32_t); \
70456893Sfenner			tm = localtime(&t); \
70556893Sfenner			strftime(str, 256, "%Y/%m/%d %T", tm); \
70656893Sfenner			printf(" %s", str); \
70756893Sfenner		}
70856893Sfenner
70956893Sfenner#define STOREATTROUT() { unsigned long mask, i; \
71075115Sfenner			TCHECK2(bp[0], (sizeof(int32_t)*6)); \
71175115Sfenner			mask = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
71256893Sfenner			if (mask) printf (" StoreStatus"); \
71356893Sfenner  		        if (mask & 1) { printf(" date"); DATEOUT(); } \
71456893Sfenner			else bp += sizeof(int32_t); \
71575115Sfenner			i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
71656893Sfenner  		        if (mask & 2) printf(" owner %lu", i);  \
71775115Sfenner			i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
71856893Sfenner  		        if (mask & 4) printf(" group %lu", i); \
71975115Sfenner			i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
72056893Sfenner  		        if (mask & 8) printf(" mode %lo", i & 07777); \
72175115Sfenner			i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
72256893Sfenner  		        if (mask & 16) printf(" segsize %lu", i); \
72356893Sfenner			/* undocumented in 3.3 docu */ \
72456893Sfenner  		        if (mask & 1024) printf(" fsync");  \
72556893Sfenner		}
72656893Sfenner
72756893Sfenner#define UBIK_VERSIONOUT() {int32_t epoch; int32_t counter; \
72875115Sfenner			TCHECK2(bp[0], sizeof(int32_t) * 2); \
72975115Sfenner			epoch = EXTRACT_32BITS(bp); \
73056893Sfenner			bp += sizeof(int32_t); \
73175115Sfenner			counter = EXTRACT_32BITS(bp); \
73256893Sfenner			bp += sizeof(int32_t); \
73356893Sfenner			printf(" %d.%d", epoch, counter); \
73456893Sfenner		}
73556893Sfenner
73656893Sfenner#define AFSUUIDOUT() {u_int32_t temp; int i; \
73775115Sfenner			TCHECK2(bp[0], 11*sizeof(u_int32_t)); \
73875115Sfenner			temp = EXTRACT_32BITS(bp); \
73956893Sfenner			bp += sizeof(u_int32_t); \
74056893Sfenner			printf(" %08x", temp); \
74175115Sfenner			temp = EXTRACT_32BITS(bp); \
74256893Sfenner			bp += sizeof(u_int32_t); \
74356893Sfenner			printf("%04x", temp); \
74475115Sfenner			temp = EXTRACT_32BITS(bp); \
74556893Sfenner			bp += sizeof(u_int32_t); \
74656893Sfenner			printf("%04x", temp); \
74756893Sfenner			for (i = 0; i < 8; i++) { \
74875115Sfenner				temp = EXTRACT_32BITS(bp); \
74956893Sfenner				bp += sizeof(u_int32_t); \
75056893Sfenner				printf("%02x", (unsigned char) temp); \
75156893Sfenner			} \
75256893Sfenner		}
75356893Sfenner
75456893Sfenner/*
75556893Sfenner * This is the sickest one of all
75656893Sfenner */
75756893Sfenner
75856893Sfenner#define VECOUT(MAX) { char *sp; \
75998524Sfenner			char s[AFSNAMEMAX]; \
76056893Sfenner			int k; \
76198524Sfenner			if ((MAX) + 1 > sizeof(s)) \
76298524Sfenner				goto trunc; \
76398524Sfenner			TCHECK2(bp[0], (MAX) * sizeof(int32_t)); \
76456893Sfenner			sp = s; \
76598524Sfenner			for (k = 0; k < (MAX); k++) { \
76675115Sfenner				*sp++ = (char) EXTRACT_32BITS(bp); \
76756893Sfenner				bp += sizeof(int32_t); \
76856893Sfenner			} \
76998524Sfenner			s[(MAX)] = '\0'; \
77080231Sfenner			printf(" \""); \
77180231Sfenner			fn_print(s, NULL); \
77280231Sfenner			printf("\""); \
77356893Sfenner		}
77456893Sfenner
77575115Sfennerstatic void
77675115Sfennerack_print(register const u_char *bp, int length)
77775115Sfenner{
77875115Sfenner        u_char nAcks;
77975115Sfenner	int i;
78075115Sfenner
78175115Sfenner	if (vflag <= 1)
78275115Sfenner	        return;
78375115Sfenner
78475115Sfenner 	if (length <= sizeof(struct rx_header))
78575115Sfenner		return;
78675115Sfenner
78775115Sfenner	bp += sizeof(struct rx_header);
78875115Sfenner
78975115Sfenner	/*
79075115Sfenner	 * Packets < firstPacket are implicitly acknowledged and may
79175115Sfenner	 * be discarded by the sender.
79275115Sfenner	 *
79375115Sfenner	 * Packets >= firstPacket+nAcks are implicitly NOT acknowledged.
79475115Sfenner	 *
79575115Sfenner	 * No packets with sequence numbers >= firstPacket should be
79675115Sfenner	 * discarded by the sender (they may thrown out at any time by
79775115Sfenner	 * the receiver)
79875115Sfenner	 */
79975115Sfenner#define RX_ACK_REASONS "RDOXSprn"
80075115Sfenner	/* Requested, Duplicate, Out_of_sequence, eXceeds_window, no_Space,
80175115Sfenner	 * Ping, ping_Response, No_{progress, particular_reason}.
80275115Sfenner	 */
80375115Sfenner#if 0
80475115Sfenner	struct rx_ackPacket {
80575115Sfenner	  u_short bufferSpace;	/* Skip! */
80675115Sfenner	  u_short maxSkew;	/* Skip! */
80775115Sfenner	  u_long  firstPacket;
80875115Sfenner	  u_long  previousPacket; /* Obsolete! */
80975115Sfenner	  u_long  serial;	/* Serial that prompted the ack, */
81075115Sfenner	  u_char  reason;	/* and the reason why. */
81175115Sfenner	  u_char  nAcks;
81275115Sfenner	  u_char  acks[RX_MAXACKS]; /* Selective acks (not a bitmap). */
81375115Sfenner	};
81475115Sfenner#endif
81575115Sfenner#define RX_ACK_TYPE_NACK 0
81675115Sfenner
81775115Sfenner	TCHECK2(bp[0], 8);	/* bufferSpace and maxSkew */
81875115Sfenner	bp += 4;
81975115Sfenner	printf(" fir %u", (unsigned)EXTRACT_32BITS(bp));
82075115Sfenner	bp += 4;
82175115Sfenner	TCHECK2(bp[0], 8);	/* previousPacket and serial */
82275115Sfenner	bp += 4;
82375115Sfenner	printf(" %u", (unsigned)EXTRACT_32BITS(bp));
82475115Sfenner	bp += 4;
82575115Sfenner	TCHECK2(bp[0], 1);
82675115Sfenner	printf("%c", RX_ACK_REASONS[(*bp - 1) & 07u]);
82775115Sfenner	bp += 1;		/* reason */
82875115Sfenner	TCHECK2(bp[0], 1);
82975115Sfenner	nAcks = *bp;
83075115Sfenner	bp += 1;		/* nAcks */
83175115Sfenner
83275115Sfenner	for (i = 0; i < nAcks; i++) {
83375115Sfenner	    TCHECK2(bp[0], 1);
83475115Sfenner	    putchar(*bp == RX_ACK_TYPE_NACK? '-' : '*');
83575115Sfenner	    bp += 1;
83675115Sfenner	}
83775115Sfenner
83875115Sfenner	return;
83975115Sfenner
84075115Sfennertrunc:
84175115Sfenner	printf(" [|ack]");
84275115Sfenner}
84375115Sfenner
84456893Sfenner/*
84556893Sfenner * Handle calls to the AFS file service (fs)
84656893Sfenner */
84756893Sfenner
84875115Sfennerstatic void
84956893Sfennerfs_print(register const u_char *bp, int length)
85056893Sfenner{
85156893Sfenner	int fs_op;
85256893Sfenner	unsigned long i;
85356893Sfenner
85456893Sfenner	if (length <= sizeof(struct rx_header))
85556893Sfenner		return;
85656893Sfenner
85756893Sfenner	if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) {
85856893Sfenner		goto trunc;
85956893Sfenner	}
86056893Sfenner
86156893Sfenner	/*
86256893Sfenner	 * Print out the afs call we're invoking.  The table used here was
86356893Sfenner	 * gleaned from fsint/afsint.xg
86456893Sfenner	 */
86556893Sfenner
86675115Sfenner	fs_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
86756893Sfenner
86856893Sfenner	printf(" fs call %s", tok2str(fs_req, "op#%d", fs_op));
86956893Sfenner
87056893Sfenner	/*
87156893Sfenner	 * Print out arguments to some of the AFS calls.  This stuff is
87256893Sfenner	 * all from afsint.xg
87356893Sfenner	 */
87456893Sfenner
87556893Sfenner	bp += sizeof(struct rx_header) + 4;
87656893Sfenner
87756893Sfenner	/*
87856893Sfenner	 * Sigh.  This is gross.  Ritchie forgive me.
87956893Sfenner	 */
88056893Sfenner
88156893Sfenner	switch (fs_op) {
88256893Sfenner		case 130:	/* Fetch data */
88356893Sfenner			FIDOUT();
88456893Sfenner			printf(" offset");
88556893Sfenner			UINTOUT();
88656893Sfenner			printf(" length");
88756893Sfenner			UINTOUT();
88856893Sfenner			break;
88956893Sfenner		case 131:	/* Fetch ACL */
89056893Sfenner		case 132:	/* Fetch Status */
89156893Sfenner		case 143:	/* Old set lock */
89256893Sfenner		case 144:	/* Old extend lock */
89356893Sfenner		case 145:	/* Old release lock */
89456893Sfenner		case 156:	/* Set lock */
89556893Sfenner		case 157:	/* Extend lock */
89656893Sfenner		case 158:	/* Release lock */
89756893Sfenner			FIDOUT();
89856893Sfenner			break;
89956893Sfenner		case 135:	/* Store status */
90056893Sfenner			FIDOUT();
90156893Sfenner			STOREATTROUT();
90256893Sfenner			break;
90356893Sfenner		case 133:	/* Store data */
90456893Sfenner			FIDOUT();
90556893Sfenner			STOREATTROUT();
90656893Sfenner			printf(" offset");
90756893Sfenner			UINTOUT();
90856893Sfenner			printf(" length");
90956893Sfenner			UINTOUT();
91056893Sfenner			printf(" flen");
91156893Sfenner			UINTOUT();
91256893Sfenner			break;
91356893Sfenner		case 134:	/* Store ACL */
91456893Sfenner		{
91575115Sfenner			char a[AFSOPAQUEMAX+1];
91656893Sfenner			FIDOUT();
91775115Sfenner			TCHECK2(bp[0], 4);
91875115Sfenner			i = EXTRACT_32BITS(bp);
91956893Sfenner			bp += sizeof(int32_t);
92075115Sfenner			TCHECK2(bp[0], i);
92175115Sfenner			i = min(AFSOPAQUEMAX, i);
92275115Sfenner			strncpy(a, (char *) bp, i);
92356893Sfenner			a[i] = '\0';
92475115Sfenner			acl_print((u_char *) a, sizeof(a), (u_char *) a + i);
92556893Sfenner			break;
92656893Sfenner		}
92756893Sfenner		case 137:	/* Create file */
92856893Sfenner		case 141:	/* MakeDir */
92956893Sfenner			FIDOUT();
93056893Sfenner			STROUT(AFSNAMEMAX);
93156893Sfenner			STOREATTROUT();
93256893Sfenner			break;
93356893Sfenner		case 136:	/* Remove file */
93456893Sfenner		case 142:	/* Remove directory */
93556893Sfenner			FIDOUT();
93656893Sfenner			STROUT(AFSNAMEMAX);
93756893Sfenner			break;
93856893Sfenner		case 138:	/* Rename file */
93956893Sfenner			printf(" old");
94056893Sfenner			FIDOUT();
94156893Sfenner			STROUT(AFSNAMEMAX);
94256893Sfenner			printf(" new");
94356893Sfenner			FIDOUT();
94456893Sfenner			STROUT(AFSNAMEMAX);
94556893Sfenner			break;
94656893Sfenner		case 139:	/* Symlink */
94756893Sfenner			FIDOUT();
94856893Sfenner			STROUT(AFSNAMEMAX);
94956893Sfenner			printf(" link to");
95056893Sfenner			STROUT(AFSNAMEMAX);
95156893Sfenner			break;
95256893Sfenner		case 140:	/* Link */
95356893Sfenner			FIDOUT();
95456893Sfenner			STROUT(AFSNAMEMAX);
95556893Sfenner			printf(" link to");
95656893Sfenner			FIDOUT();
95756893Sfenner			break;
95856893Sfenner		case 148:	/* Get volume info */
95956893Sfenner			STROUT(AFSNAMEMAX);
96056893Sfenner			break;
96156893Sfenner		case 149:	/* Get volume stats */
96256893Sfenner		case 150:	/* Set volume stats */
96356893Sfenner			printf(" volid");
96456893Sfenner			UINTOUT();
96556893Sfenner			break;
96656893Sfenner		case 154:	/* New get volume info */
96756893Sfenner			printf(" volname");
96856893Sfenner			STROUT(AFSNAMEMAX);
96956893Sfenner			break;
97056893Sfenner		case 155:	/* Bulk stat */
97156893Sfenner		{
97256893Sfenner			unsigned long j;
97375115Sfenner			TCHECK2(bp[0], 4);
97475115Sfenner			j = EXTRACT_32BITS(bp);
97556893Sfenner			bp += sizeof(int32_t);
97656893Sfenner
97756893Sfenner			for (i = 0; i < j; i++) {
97856893Sfenner				FIDOUT();
97956893Sfenner				if (i != j - 1)
98056893Sfenner					printf(",");
98156893Sfenner			}
98256893Sfenner			if (j == 0)
98356893Sfenner				printf(" <none!>");
98456893Sfenner		}
98556893Sfenner		default:
98656893Sfenner			;
98756893Sfenner	}
98856893Sfenner
98956893Sfenner	return;
99056893Sfenner
99156893Sfennertrunc:
99256893Sfenner	printf(" [|fs]");
99356893Sfenner}
99456893Sfenner
99556893Sfenner/*
99656893Sfenner * Handle replies to the AFS file service
99756893Sfenner */
99856893Sfenner
99956893Sfennerstatic void
100056893Sfennerfs_reply_print(register const u_char *bp, int length, int32_t opcode)
100156893Sfenner{
100256893Sfenner	unsigned long i;
100356893Sfenner	struct rx_header *rxh;
100456893Sfenner
100556893Sfenner	if (length <= sizeof(struct rx_header))
100656893Sfenner		return;
100756893Sfenner
100856893Sfenner	rxh = (struct rx_header *) bp;
100956893Sfenner
101056893Sfenner	/*
101156893Sfenner	 * Print out the afs call we're invoking.  The table used here was
101256893Sfenner	 * gleaned from fsint/afsint.xg
101356893Sfenner	 */
101456893Sfenner
101556893Sfenner	printf(" fs reply %s", tok2str(fs_req, "op#%d", opcode));
101656893Sfenner
101756893Sfenner	bp += sizeof(struct rx_header);
101856893Sfenner
101956893Sfenner	/*
102056893Sfenner	 * If it was a data packet, interpret the response
102156893Sfenner	 */
102256893Sfenner
102375115Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA) {
102456893Sfenner		switch (opcode) {
102556893Sfenner		case 131:	/* Fetch ACL */
102656893Sfenner		{
102775115Sfenner			char a[AFSOPAQUEMAX+1];
102875115Sfenner			TCHECK2(bp[0], 4);
102975115Sfenner			i = EXTRACT_32BITS(bp);
103056893Sfenner			bp += sizeof(int32_t);
103175115Sfenner			TCHECK2(bp[0], i);
103275115Sfenner			i = min(AFSOPAQUEMAX, i);
103375115Sfenner			strncpy(a, (char *) bp, i);
103456893Sfenner			a[i] = '\0';
103575115Sfenner			acl_print((u_char *) a, sizeof(a), (u_char *) a + i);
103656893Sfenner			break;
103756893Sfenner		}
103856893Sfenner		case 137:	/* Create file */
103956893Sfenner		case 141:	/* MakeDir */
104056893Sfenner			printf(" new");
104156893Sfenner			FIDOUT();
104256893Sfenner			break;
104356893Sfenner		case 151:	/* Get root volume */
104456893Sfenner			printf(" root volume");
104556893Sfenner			STROUT(AFSNAMEMAX);
104656893Sfenner			break;
104756893Sfenner		case 153:	/* Get time */
104856893Sfenner			DATEOUT();
104956893Sfenner			break;
105056893Sfenner		default:
105156893Sfenner			;
105256893Sfenner		}
105375115Sfenner	} else if (rxh->type == RX_PACKET_TYPE_ABORT) {
105475115Sfenner		int i;
105575115Sfenner
105675115Sfenner 		/*
105775115Sfenner 		 * Otherwise, just print out the return code
105875115Sfenner 		 */
105975115Sfenner		TCHECK2(bp[0], sizeof(int32_t));
106075115Sfenner		i = (int) EXTRACT_32BITS(bp);
106175115Sfenner		bp += sizeof(int32_t);
106275115Sfenner
106375115Sfenner		printf(" error %s", tok2str(afs_fs_errors, "#%d", i));
106475115Sfenner	} else {
106575115Sfenner		printf(" strange fs reply of type %d", rxh->type);
106656893Sfenner	}
106756893Sfenner
106856893Sfenner	return;
106956893Sfenner
107056893Sfennertrunc:
107156893Sfenner	printf(" [|fs]");
107256893Sfenner}
107356893Sfenner
107456893Sfenner/*
107556893Sfenner * Print out an AFS ACL string.  An AFS ACL is a string that has the
107656893Sfenner * following format:
107756893Sfenner *
107856893Sfenner * <positive> <negative>
107956893Sfenner * <uid1> <aclbits1>
108056893Sfenner * ....
108156893Sfenner *
108256893Sfenner * "positive" and "negative" are integers which contain the number of
108356893Sfenner * positive and negative ACL's in the string.  The uid/aclbits pair are
108456893Sfenner * ASCII strings containing the UID/PTS record and and a ascii number
108556893Sfenner * representing a logical OR of all the ACL permission bits
108656893Sfenner */
108756893Sfenner
108856893Sfennerstatic void
108975115Sfenneracl_print(u_char *s, int maxsize, u_char *end)
109056893Sfenner{
109156893Sfenner	int pos, neg, acl;
109256893Sfenner	int n, i;
109375115Sfenner	char *user;
109456893Sfenner
109575115Sfenner	if ((user = (char *)malloc(maxsize)) == NULL)
109675115Sfenner		return;
109775115Sfenner
109856893Sfenner	if (sscanf((char *) s, "%d %d\n%n", &pos, &neg, &n) != 2)
109975115Sfenner		goto finish;
110056893Sfenner
110156893Sfenner	s += n;
110256893Sfenner
110356893Sfenner	if (s > end)
110475115Sfenner		goto finish;
110556893Sfenner
110656893Sfenner	/*
110756893Sfenner	 * This wacky order preserves the order used by the "fs" command
110856893Sfenner	 */
110956893Sfenner
111056893Sfenner#define ACLOUT(acl) \
111156893Sfenner	if (acl & PRSFS_READ) \
111256893Sfenner		printf("r"); \
111356893Sfenner	if (acl & PRSFS_LOOKUP) \
111456893Sfenner		printf("l"); \
111556893Sfenner	if (acl & PRSFS_INSERT) \
111656893Sfenner		printf("i"); \
111756893Sfenner	if (acl & PRSFS_DELETE) \
111856893Sfenner		printf("d"); \
111956893Sfenner	if (acl & PRSFS_WRITE) \
112056893Sfenner		printf("w"); \
112156893Sfenner	if (acl & PRSFS_LOCK) \
112256893Sfenner		printf("k"); \
112356893Sfenner	if (acl & PRSFS_ADMINISTER) \
112456893Sfenner		printf("a");
112556893Sfenner
112656893Sfenner	for (i = 0; i < pos; i++) {
112756893Sfenner		if (sscanf((char *) s, "%s %d\n%n", user, &acl, &n) != 2)
112875115Sfenner			goto finish;
112956893Sfenner		s += n;
113080231Sfenner		printf(" +{");
113180231Sfenner		fn_print(user, NULL);
113280231Sfenner		printf(" ");
113356893Sfenner		ACLOUT(acl);
113456893Sfenner		printf("}");
113556893Sfenner		if (s > end)
113675115Sfenner			goto finish;
113756893Sfenner	}
113856893Sfenner
113956893Sfenner	for (i = 0; i < neg; i++) {
114056893Sfenner		if (sscanf((char *) s, "%s %d\n%n", user, &acl, &n) != 2)
114175115Sfenner			goto finish;
114256893Sfenner		s += n;
114380231Sfenner		printf(" -{");
114480231Sfenner		fn_print(user, NULL);
114580231Sfenner		printf(" ");
114656893Sfenner		ACLOUT(acl);
114756893Sfenner		printf("}");
114856893Sfenner		if (s > end)
114975115Sfenner			goto finish;
115056893Sfenner	}
115175115Sfenner
115275115Sfennerfinish:
115375115Sfenner	free(user);
115475115Sfenner	return;
115556893Sfenner}
115656893Sfenner
115756893Sfenner#undef ACLOUT
115856893Sfenner
115956893Sfenner/*
116056893Sfenner * Handle calls to the AFS callback service
116156893Sfenner */
116256893Sfenner
116356893Sfennerstatic void
116456893Sfennercb_print(register const u_char *bp, int length)
116556893Sfenner{
116656893Sfenner	int cb_op;
116756893Sfenner	unsigned long i;
116856893Sfenner
116956893Sfenner	if (length <= sizeof(struct rx_header))
117056893Sfenner		return;
117156893Sfenner
117256893Sfenner	if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) {
117356893Sfenner		goto trunc;
117456893Sfenner	}
117556893Sfenner
117656893Sfenner	/*
117756893Sfenner	 * Print out the afs call we're invoking.  The table used here was
117856893Sfenner	 * gleaned from fsint/afscbint.xg
117956893Sfenner	 */
118056893Sfenner
118175115Sfenner	cb_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
118256893Sfenner
118356893Sfenner	printf(" cb call %s", tok2str(cb_req, "op#%d", cb_op));
118456893Sfenner
118556893Sfenner	bp += sizeof(struct rx_header) + 4;
118656893Sfenner
118756893Sfenner	/*
118856893Sfenner	 * Print out the afs call we're invoking.  The table used here was
118956893Sfenner	 * gleaned from fsint/afscbint.xg
119056893Sfenner	 */
119156893Sfenner
119256893Sfenner	switch (cb_op) {
119356893Sfenner		case 204:		/* Callback */
119456893Sfenner		{
119556893Sfenner			unsigned long j, t;
119675115Sfenner			TCHECK2(bp[0], 4);
119775115Sfenner			j = EXTRACT_32BITS(bp);
119856893Sfenner			bp += sizeof(int32_t);
119956893Sfenner
120056893Sfenner			for (i = 0; i < j; i++) {
120156893Sfenner				FIDOUT();
120256893Sfenner				if (i != j - 1)
120356893Sfenner					printf(",");
120456893Sfenner			}
120556893Sfenner
120656893Sfenner			if (j == 0)
120756893Sfenner				printf(" <none!>");
120856893Sfenner
120975115Sfenner			j = EXTRACT_32BITS(bp);
121056893Sfenner			bp += sizeof(int32_t);
121156893Sfenner
121256893Sfenner			if (j != 0)
121356893Sfenner				printf(";");
121456893Sfenner
121556893Sfenner			for (i = 0; i < j; i++) {
121656893Sfenner				printf(" ver");
121756893Sfenner				INTOUT();
121856893Sfenner				printf(" expires");
121956893Sfenner				DATEOUT();
122075115Sfenner				TCHECK2(bp[0], 4);
122175115Sfenner				t = EXTRACT_32BITS(bp);
122256893Sfenner				bp += sizeof(int32_t);
122356893Sfenner				tok2str(cb_types, "type %d", t);
122456893Sfenner			}
122556893Sfenner		}
122656893Sfenner		case 214: {
122756893Sfenner			printf(" afsuuid");
122856893Sfenner			AFSUUIDOUT();
122956893Sfenner			break;
123056893Sfenner		}
123156893Sfenner		default:
123256893Sfenner			;
123356893Sfenner	}
123456893Sfenner
123556893Sfenner	return;
123656893Sfenner
123756893Sfennertrunc:
123856893Sfenner	printf(" [|cb]");
123956893Sfenner}
124056893Sfenner
124156893Sfenner/*
124256893Sfenner * Handle replies to the AFS Callback Service
124356893Sfenner */
124456893Sfenner
124556893Sfennerstatic void
124656893Sfennercb_reply_print(register const u_char *bp, int length, int32_t opcode)
124756893Sfenner{
124856893Sfenner	struct rx_header *rxh;
124956893Sfenner
125056893Sfenner	if (length <= sizeof(struct rx_header))
125156893Sfenner		return;
125256893Sfenner
125356893Sfenner	rxh = (struct rx_header *) bp;
125456893Sfenner
125556893Sfenner	/*
125656893Sfenner	 * Print out the afs call we're invoking.  The table used here was
125756893Sfenner	 * gleaned from fsint/afscbint.xg
125856893Sfenner	 */
125956893Sfenner
126056893Sfenner	printf(" cb reply %s", tok2str(cb_req, "op#%d", opcode));
126156893Sfenner
126256893Sfenner	bp += sizeof(struct rx_header);
126356893Sfenner
126456893Sfenner	/*
126556893Sfenner	 * If it was a data packet, interpret the response.
126656893Sfenner	 */
126756893Sfenner
126856893Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA)
126956893Sfenner		switch (opcode) {
127056893Sfenner		case 213:	/* InitCallBackState3 */
127156893Sfenner			AFSUUIDOUT();
127256893Sfenner			break;
127356893Sfenner		default:
127456893Sfenner		;
127556893Sfenner		}
127656893Sfenner	else {
127756893Sfenner		/*
127856893Sfenner		 * Otherwise, just print out the return code
127956893Sfenner		 */
128056893Sfenner		printf(" errcode");
128156893Sfenner		INTOUT();
128256893Sfenner	}
128356893Sfenner
128456893Sfenner	return;
128556893Sfenner
128656893Sfennertrunc:
128756893Sfenner	printf(" [|cb]");
128856893Sfenner}
128956893Sfenner
129056893Sfenner/*
129156893Sfenner * Handle calls to the AFS protection database server
129256893Sfenner */
129356893Sfenner
129456893Sfennerstatic void
129556893Sfennerprot_print(register const u_char *bp, int length)
129656893Sfenner{
129756893Sfenner	unsigned long i;
129856893Sfenner	int pt_op;
129956893Sfenner
130056893Sfenner	if (length <= sizeof(struct rx_header))
130156893Sfenner		return;
130256893Sfenner
130356893Sfenner	if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) {
130456893Sfenner		goto trunc;
130556893Sfenner	}
130656893Sfenner
130756893Sfenner	/*
130856893Sfenner	 * Print out the afs call we're invoking.  The table used here was
130956893Sfenner	 * gleaned from ptserver/ptint.xg
131056893Sfenner	 */
131156893Sfenner
131275115Sfenner	pt_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
131356893Sfenner
131456893Sfenner	printf(" pt");
131556893Sfenner
131656893Sfenner	if (is_ubik(pt_op)) {
131756893Sfenner		ubik_print(bp, length);
131856893Sfenner		return;
131956893Sfenner	}
132056893Sfenner
132156893Sfenner	printf(" call %s", tok2str(pt_req, "op#%d", pt_op));
132256893Sfenner
132356893Sfenner	/*
132456893Sfenner	 * Decode some of the arguments to the PT calls
132556893Sfenner	 */
132656893Sfenner
132756893Sfenner	bp += sizeof(struct rx_header) + 4;
132856893Sfenner
132956893Sfenner	switch (pt_op) {
133056893Sfenner		case 500:	/* I New User */
133156893Sfenner			STROUT(PRNAMEMAX);
133256893Sfenner			printf(" id");
133356893Sfenner			INTOUT();
133456893Sfenner			printf(" oldid");
133556893Sfenner			INTOUT();
133656893Sfenner			break;
133756893Sfenner		case 501:	/* Where is it */
133856893Sfenner		case 506:	/* Delete */
133956893Sfenner		case 508:	/* Get CPS */
134056893Sfenner		case 512:	/* List entry */
134156893Sfenner		case 514:	/* List elements */
134256893Sfenner		case 517:	/* List owned */
134356893Sfenner		case 518:	/* Get CPS2 */
134456893Sfenner		case 519:	/* Get host CPS */
134556893Sfenner			printf(" id");
134656893Sfenner			INTOUT();
134756893Sfenner			break;
134856893Sfenner		case 502:	/* Dump entry */
134956893Sfenner			printf(" pos");
135056893Sfenner			INTOUT();
135156893Sfenner			break;
135256893Sfenner		case 503:	/* Add to group */
135356893Sfenner		case 507:	/* Remove from group */
135456893Sfenner		case 515:	/* Is a member of? */
135556893Sfenner			printf(" uid");
135656893Sfenner			INTOUT();
135756893Sfenner			printf(" gid");
135856893Sfenner			INTOUT();
135956893Sfenner			break;
136056893Sfenner		case 504:	/* Name to ID */
136156893Sfenner		{
136256893Sfenner			unsigned long j;
136375115Sfenner			TCHECK2(bp[0], 4);
136475115Sfenner			j = EXTRACT_32BITS(bp);
136556893Sfenner			bp += sizeof(int32_t);
136656893Sfenner
136756893Sfenner			/*
136856893Sfenner			 * Who designed this chicken-shit protocol?
136956893Sfenner			 *
137056893Sfenner			 * Each character is stored as a 32-bit
137156893Sfenner			 * integer!
137256893Sfenner			 */
137356893Sfenner
137456893Sfenner			for (i = 0; i < j; i++) {
137556893Sfenner				VECOUT(PRNAMEMAX);
137656893Sfenner			}
137756893Sfenner			if (j == 0)
137856893Sfenner				printf(" <none!>");
137956893Sfenner		}
138056893Sfenner			break;
138156893Sfenner		case 505:	/* Id to name */
138256893Sfenner		{
138356893Sfenner			unsigned long j;
138456893Sfenner			printf(" ids:");
138575115Sfenner			TCHECK2(bp[0], 4);
138675115Sfenner			i = EXTRACT_32BITS(bp);
138756893Sfenner			bp += sizeof(int32_t);
138856893Sfenner			for (j = 0; j < i; j++)
138956893Sfenner				INTOUT();
139056893Sfenner			if (j == 0)
139156893Sfenner				printf(" <none!>");
139256893Sfenner		}
139356893Sfenner			break;
139456893Sfenner		case 509:	/* New entry */
139556893Sfenner			STROUT(PRNAMEMAX);
139656893Sfenner			printf(" flag");
139756893Sfenner			INTOUT();
139856893Sfenner			printf(" oid");
139956893Sfenner			INTOUT();
140056893Sfenner			break;
140156893Sfenner		case 511:	/* Set max */
140256893Sfenner			printf(" id");
140356893Sfenner			INTOUT();
140456893Sfenner			printf(" gflag");
140556893Sfenner			INTOUT();
140656893Sfenner			break;
140756893Sfenner		case 513:	/* Change entry */
140856893Sfenner			printf(" id");
140956893Sfenner			INTOUT();
141056893Sfenner			STROUT(PRNAMEMAX);
141156893Sfenner			printf(" oldid");
141256893Sfenner			INTOUT();
141356893Sfenner			printf(" newid");
141456893Sfenner			INTOUT();
141556893Sfenner			break;
141656893Sfenner		case 520:	/* Update entry */
141756893Sfenner			printf(" id");
141856893Sfenner			INTOUT();
141956893Sfenner			STROUT(PRNAMEMAX);
142056893Sfenner			break;
142156893Sfenner		default:
142256893Sfenner			;
142356893Sfenner	}
142456893Sfenner
142556893Sfenner
142656893Sfenner	return;
142756893Sfenner
142856893Sfennertrunc:
142956893Sfenner	printf(" [|pt]");
143056893Sfenner}
143156893Sfenner
143256893Sfenner/*
143356893Sfenner * Handle replies to the AFS protection service
143456893Sfenner */
143556893Sfenner
143656893Sfennerstatic void
143756893Sfennerprot_reply_print(register const u_char *bp, int length, int32_t opcode)
143856893Sfenner{
143956893Sfenner	struct rx_header *rxh;
144056893Sfenner	unsigned long i;
144156893Sfenner
144256893Sfenner	if (length < sizeof(struct rx_header))
144356893Sfenner		return;
144456893Sfenner
144556893Sfenner	rxh = (struct rx_header *) bp;
144656893Sfenner
144756893Sfenner	/*
144856893Sfenner	 * Print out the afs call we're invoking.  The table used here was
144956893Sfenner	 * gleaned from ptserver/ptint.xg.  Check to see if it's a
145056893Sfenner	 * Ubik call, however.
145156893Sfenner	 */
145256893Sfenner
145356893Sfenner	printf(" pt");
145456893Sfenner
145556893Sfenner	if (is_ubik(opcode)) {
145656893Sfenner		ubik_reply_print(bp, length, opcode);
145756893Sfenner		return;
145856893Sfenner	}
145956893Sfenner
146056893Sfenner	printf(" reply %s", tok2str(pt_req, "op#%d", opcode));
146156893Sfenner
146256893Sfenner	bp += sizeof(struct rx_header);
146356893Sfenner
146456893Sfenner	/*
146556893Sfenner	 * If it was a data packet, interpret the response
146656893Sfenner	 */
146756893Sfenner
146856893Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA)
146956893Sfenner		switch (opcode) {
147056893Sfenner		case 504:		/* Name to ID */
147156893Sfenner		{
147256893Sfenner			unsigned long j;
147356893Sfenner			printf(" ids:");
147475115Sfenner			TCHECK2(bp[0], 4);
147575115Sfenner			i = EXTRACT_32BITS(bp);
147656893Sfenner			bp += sizeof(int32_t);
147756893Sfenner			for (j = 0; j < i; j++)
147856893Sfenner				INTOUT();
147956893Sfenner			if (j == 0)
148056893Sfenner				printf(" <none!>");
148156893Sfenner		}
148256893Sfenner			break;
148356893Sfenner		case 505:		/* ID to name */
148456893Sfenner		{
148556893Sfenner			unsigned long j;
148675115Sfenner			TCHECK2(bp[0], 4);
148775115Sfenner			j = EXTRACT_32BITS(bp);
148856893Sfenner			bp += sizeof(int32_t);
148956893Sfenner
149056893Sfenner			/*
149156893Sfenner			 * Who designed this chicken-shit protocol?
149256893Sfenner			 *
149356893Sfenner			 * Each character is stored as a 32-bit
149456893Sfenner			 * integer!
149556893Sfenner			 */
149656893Sfenner
149756893Sfenner			for (i = 0; i < j; i++) {
149856893Sfenner				VECOUT(PRNAMEMAX);
149956893Sfenner			}
150056893Sfenner			if (j == 0)
150156893Sfenner				printf(" <none!>");
150256893Sfenner		}
150356893Sfenner			break;
150456893Sfenner		case 508:		/* Get CPS */
150556893Sfenner		case 514:		/* List elements */
150656893Sfenner		case 517:		/* List owned */
150756893Sfenner		case 518:		/* Get CPS2 */
150856893Sfenner		case 519:		/* Get host CPS */
150956893Sfenner		{
151056893Sfenner			unsigned long j;
151175115Sfenner			TCHECK2(bp[0], 4);
151275115Sfenner			j = EXTRACT_32BITS(bp);
151356893Sfenner			bp += sizeof(int32_t);
151456893Sfenner			for (i = 0; i < j; i++) {
151556893Sfenner				INTOUT();
151656893Sfenner			}
151756893Sfenner			if (j == 0)
151856893Sfenner				printf(" <none!>");
151956893Sfenner		}
152056893Sfenner			break;
152156893Sfenner		case 510:		/* List max */
152256893Sfenner			printf(" maxuid");
152356893Sfenner			INTOUT();
152456893Sfenner			printf(" maxgid");
152556893Sfenner			INTOUT();
152656893Sfenner			break;
152756893Sfenner		default:
152856893Sfenner			;
152956893Sfenner		}
153056893Sfenner	else {
153156893Sfenner		/*
153256893Sfenner		 * Otherwise, just print out the return code
153356893Sfenner		 */
153456893Sfenner		printf(" errcode");
153556893Sfenner		INTOUT();
153656893Sfenner	}
153756893Sfenner
153856893Sfenner	return;
153956893Sfenner
154056893Sfennertrunc:
154156893Sfenner	printf(" [|pt]");
154256893Sfenner}
154356893Sfenner
154456893Sfenner/*
154556893Sfenner * Handle calls to the AFS volume location database service
154656893Sfenner */
154756893Sfenner
154856893Sfennerstatic void
154956893Sfennervldb_print(register const u_char *bp, int length)
155056893Sfenner{
155156893Sfenner	int vldb_op;
155256893Sfenner	unsigned long i;
155356893Sfenner
155456893Sfenner	if (length <= sizeof(struct rx_header))
155556893Sfenner		return;
155656893Sfenner
155756893Sfenner	if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) {
155856893Sfenner		goto trunc;
155956893Sfenner	}
156056893Sfenner
156156893Sfenner	/*
156256893Sfenner	 * Print out the afs call we're invoking.  The table used here was
156356893Sfenner	 * gleaned from vlserver/vldbint.xg
156456893Sfenner	 */
156556893Sfenner
156675115Sfenner	vldb_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
156756893Sfenner
156856893Sfenner	printf(" vldb");
156956893Sfenner
157056893Sfenner	if (is_ubik(vldb_op)) {
157156893Sfenner		ubik_print(bp, length);
157256893Sfenner		return;
157356893Sfenner	}
157456893Sfenner	printf(" call %s", tok2str(vldb_req, "op#%d", vldb_op));
157556893Sfenner
157656893Sfenner	/*
157756893Sfenner	 * Decode some of the arguments to the VLDB calls
157856893Sfenner	 */
157956893Sfenner
158056893Sfenner	bp += sizeof(struct rx_header) + 4;
158156893Sfenner
158256893Sfenner	switch (vldb_op) {
158356893Sfenner		case 501:	/* Create new volume */
158456893Sfenner		case 517:	/* Create entry N */
158556893Sfenner			VECOUT(VLNAMEMAX);
158656893Sfenner			break;
158756893Sfenner		case 502:	/* Delete entry */
158856893Sfenner		case 503:	/* Get entry by ID */
158956893Sfenner		case 507:	/* Update entry */
159056893Sfenner		case 508:	/* Set lock */
159156893Sfenner		case 509:	/* Release lock */
159256893Sfenner		case 518:	/* Get entry by ID N */
159356893Sfenner			printf(" volid");
159456893Sfenner			INTOUT();
159575115Sfenner			TCHECK2(bp[0], sizeof(int32_t));
159675115Sfenner			i = EXTRACT_32BITS(bp);
159756893Sfenner			bp += sizeof(int32_t);
159856893Sfenner			if (i <= 2)
159956893Sfenner				printf(" type %s", voltype[i]);
160056893Sfenner			break;
160156893Sfenner		case 504:	/* Get entry by name */
160256893Sfenner		case 519:	/* Get entry by name N */
160356893Sfenner		case 524:	/* Update entry by name */
160456893Sfenner		case 527:	/* Get entry by name U */
160556893Sfenner			STROUT(VLNAMEMAX);
160656893Sfenner			break;
160756893Sfenner		case 505:	/* Get new vol id */
160856893Sfenner			printf(" bump");
160956893Sfenner			INTOUT();
161056893Sfenner			break;
161156893Sfenner		case 506:	/* Replace entry */
161256893Sfenner		case 520:	/* Replace entry N */
161356893Sfenner			printf(" volid");
161456893Sfenner			INTOUT();
161575115Sfenner			TCHECK2(bp[0], sizeof(int32_t));
161675115Sfenner			i = EXTRACT_32BITS(bp);
161756893Sfenner			bp += sizeof(int32_t);
161856893Sfenner			if (i <= 2)
161956893Sfenner				printf(" type %s", voltype[i]);
162056893Sfenner			VECOUT(VLNAMEMAX);
162156893Sfenner			break;
162256893Sfenner		case 510:	/* List entry */
162356893Sfenner		case 521:	/* List entry N */
162456893Sfenner			printf(" index");
162556893Sfenner			INTOUT();
162656893Sfenner			break;
162756893Sfenner		default:
162856893Sfenner			;
162956893Sfenner	}
163056893Sfenner
163156893Sfenner	return;
163256893Sfenner
163356893Sfennertrunc:
163456893Sfenner	printf(" [|vldb]");
163556893Sfenner}
163656893Sfenner
163756893Sfenner/*
163856893Sfenner * Handle replies to the AFS volume location database service
163956893Sfenner */
164056893Sfenner
164156893Sfennerstatic void
164256893Sfennervldb_reply_print(register const u_char *bp, int length, int32_t opcode)
164356893Sfenner{
164456893Sfenner	struct rx_header *rxh;
164556893Sfenner	unsigned long i;
164656893Sfenner
164756893Sfenner	if (length < sizeof(struct rx_header))
164856893Sfenner		return;
164956893Sfenner
165056893Sfenner	rxh = (struct rx_header *) bp;
165156893Sfenner
165256893Sfenner	/*
165356893Sfenner	 * Print out the afs call we're invoking.  The table used here was
165456893Sfenner	 * gleaned from vlserver/vldbint.xg.  Check to see if it's a
165556893Sfenner	 * Ubik call, however.
165656893Sfenner	 */
165756893Sfenner
165856893Sfenner	printf(" vldb");
165956893Sfenner
166056893Sfenner	if (is_ubik(opcode)) {
166156893Sfenner		ubik_reply_print(bp, length, opcode);
166256893Sfenner		return;
166356893Sfenner	}
166456893Sfenner
166556893Sfenner	printf(" reply %s", tok2str(vldb_req, "op#%d", opcode));
166656893Sfenner
166756893Sfenner	bp += sizeof(struct rx_header);
166856893Sfenner
166956893Sfenner	/*
167056893Sfenner	 * If it was a data packet, interpret the response
167156893Sfenner	 */
167256893Sfenner
167356893Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA)
167456893Sfenner		switch (opcode) {
167556893Sfenner		case 510:	/* List entry */
167656893Sfenner			printf(" count");
167756893Sfenner			INTOUT();
167856893Sfenner			printf(" nextindex");
167956893Sfenner			INTOUT();
168056893Sfenner		case 503:	/* Get entry by id */
168156893Sfenner		case 504:	/* Get entry by name */
168256893Sfenner		{	unsigned long nservers, j;
168356893Sfenner			VECOUT(VLNAMEMAX);
168475115Sfenner			TCHECK2(bp[0], sizeof(int32_t));
168556893Sfenner			bp += sizeof(int32_t);
168656893Sfenner			printf(" numservers");
168775115Sfenner			TCHECK2(bp[0], sizeof(int32_t));
168875115Sfenner			nservers = EXTRACT_32BITS(bp);
168956893Sfenner			bp += sizeof(int32_t);
169056893Sfenner			printf(" %lu", nservers);
169156893Sfenner			printf(" servers");
169256893Sfenner			for (i = 0; i < 8; i++) {
169375115Sfenner				TCHECK2(bp[0], sizeof(int32_t));
169456893Sfenner				if (i < nservers)
169556893Sfenner					printf(" %s",
169656893Sfenner					   inet_ntoa(*((struct in_addr *) bp)));
169756893Sfenner				bp += sizeof(int32_t);
169856893Sfenner			}
169956893Sfenner			printf(" partitions");
170056893Sfenner			for (i = 0; i < 8; i++) {
170175115Sfenner				TCHECK2(bp[0], sizeof(int32_t));
170275115Sfenner				j = EXTRACT_32BITS(bp);
170356893Sfenner				if (i < nservers && j <= 26)
170456893Sfenner					printf(" %c", 'a' + (int)j);
170556893Sfenner				else if (i < nservers)
170656893Sfenner					printf(" %lu", j);
170756893Sfenner				bp += sizeof(int32_t);
170856893Sfenner			}
170975115Sfenner			TCHECK2(bp[0], 8 * sizeof(int32_t));
171056893Sfenner			bp += 8 * sizeof(int32_t);
171156893Sfenner			printf(" rwvol");
171256893Sfenner			UINTOUT();
171356893Sfenner			printf(" rovol");
171456893Sfenner			UINTOUT();
171556893Sfenner			printf(" backup");
171656893Sfenner			UINTOUT();
171756893Sfenner		}
171856893Sfenner			break;
171956893Sfenner		case 505:	/* Get new volume ID */
172056893Sfenner			printf(" newvol");
172156893Sfenner			UINTOUT();
172256893Sfenner			break;
172356893Sfenner		case 521:	/* List entry */
172456893Sfenner		case 529:	/* List entry U */
172556893Sfenner			printf(" count");
172656893Sfenner			INTOUT();
172756893Sfenner			printf(" nextindex");
172856893Sfenner			INTOUT();
172956893Sfenner		case 518:	/* Get entry by ID N */
173056893Sfenner		case 519:	/* Get entry by name N */
173156893Sfenner		{	unsigned long nservers, j;
173256893Sfenner			VECOUT(VLNAMEMAX);
173356893Sfenner			printf(" numservers");
173475115Sfenner			TCHECK2(bp[0], sizeof(int32_t));
173575115Sfenner			nservers = EXTRACT_32BITS(bp);
173656893Sfenner			bp += sizeof(int32_t);
173756893Sfenner			printf(" %lu", nservers);
173856893Sfenner			printf(" servers");
173956893Sfenner			for (i = 0; i < 13; i++) {
174075115Sfenner				TCHECK2(bp[0], sizeof(int32_t));
174156893Sfenner				if (i < nservers)
174256893Sfenner					printf(" %s",
174356893Sfenner					   inet_ntoa(*((struct in_addr *) bp)));
174456893Sfenner				bp += sizeof(int32_t);
174556893Sfenner			}
174656893Sfenner			printf(" partitions");
174756893Sfenner			for (i = 0; i < 13; i++) {
174875115Sfenner				TCHECK2(bp[0], sizeof(int32_t));
174975115Sfenner				j = EXTRACT_32BITS(bp);
175056893Sfenner				if (i < nservers && j <= 26)
175156893Sfenner					printf(" %c", 'a' + (int)j);
175256893Sfenner				else if (i < nservers)
175356893Sfenner					printf(" %lu", j);
175456893Sfenner				bp += sizeof(int32_t);
175556893Sfenner			}
175675115Sfenner			TCHECK2(bp[0], 13 * sizeof(int32_t));
175756893Sfenner			bp += 13 * sizeof(int32_t);
175856893Sfenner			printf(" rwvol");
175956893Sfenner			UINTOUT();
176056893Sfenner			printf(" rovol");
176156893Sfenner			UINTOUT();
176256893Sfenner			printf(" backup");
176356893Sfenner			UINTOUT();
176456893Sfenner		}
176556893Sfenner			break;
176656893Sfenner		case 526:	/* Get entry by ID U */
176756893Sfenner		case 527:	/* Get entry by name U */
176856893Sfenner		{	unsigned long nservers, j;
176956893Sfenner			VECOUT(VLNAMEMAX);
177056893Sfenner			printf(" numservers");
177175115Sfenner			TCHECK2(bp[0], sizeof(int32_t));
177275115Sfenner			nservers = EXTRACT_32BITS(bp);
177356893Sfenner			bp += sizeof(int32_t);
177456893Sfenner			printf(" %lu", nservers);
177556893Sfenner			printf(" servers");
177656893Sfenner			for (i = 0; i < 13; i++) {
177756893Sfenner				if (i < nservers) {
177856893Sfenner					printf(" afsuuid");
177956893Sfenner					AFSUUIDOUT();
178056893Sfenner				} else {
178175115Sfenner					TCHECK2(bp[0], 44);
178256893Sfenner					bp += 44;
178356893Sfenner				}
178456893Sfenner			}
178575115Sfenner			TCHECK2(bp[0], 4 * 13);
178656893Sfenner			bp += 4 * 13;
178756893Sfenner			printf(" partitions");
178856893Sfenner			for (i = 0; i < 13; i++) {
178975115Sfenner				TCHECK2(bp[0], sizeof(int32_t));
179075115Sfenner				j = EXTRACT_32BITS(bp);
179156893Sfenner				if (i < nservers && j <= 26)
179256893Sfenner					printf(" %c", 'a' + (int)j);
179356893Sfenner				else if (i < nservers)
179456893Sfenner					printf(" %lu", j);
179556893Sfenner				bp += sizeof(int32_t);
179656893Sfenner			}
179775115Sfenner			TCHECK2(bp[0], 13 * sizeof(int32_t));
179856893Sfenner			bp += 13 * sizeof(int32_t);
179956893Sfenner			printf(" rwvol");
180056893Sfenner			UINTOUT();
180156893Sfenner			printf(" rovol");
180256893Sfenner			UINTOUT();
180356893Sfenner			printf(" backup");
180456893Sfenner			UINTOUT();
180556893Sfenner		}
180656893Sfenner		default:
180756893Sfenner			;
180856893Sfenner		}
180956893Sfenner
181056893Sfenner	else {
181156893Sfenner		/*
181256893Sfenner		 * Otherwise, just print out the return code
181356893Sfenner		 */
181456893Sfenner		printf(" errcode");
181556893Sfenner		INTOUT();
181656893Sfenner	}
181756893Sfenner
181856893Sfenner	return;
181956893Sfenner
182056893Sfennertrunc:
182156893Sfenner	printf(" [|vldb]");
182256893Sfenner}
182356893Sfenner
182456893Sfenner/*
182556893Sfenner * Handle calls to the AFS Kerberos Authentication service
182656893Sfenner */
182756893Sfenner
182856893Sfennerstatic void
182956893Sfennerkauth_print(register const u_char *bp, int length)
183056893Sfenner{
183156893Sfenner	int kauth_op;
183256893Sfenner
183356893Sfenner	if (length <= sizeof(struct rx_header))
183456893Sfenner		return;
183556893Sfenner
183656893Sfenner	if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) {
183756893Sfenner		goto trunc;
183856893Sfenner	}
183956893Sfenner
184056893Sfenner	/*
184156893Sfenner	 * Print out the afs call we're invoking.  The table used here was
184256893Sfenner	 * gleaned from kauth/kauth.rg
184356893Sfenner	 */
184456893Sfenner
184575115Sfenner	kauth_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
184656893Sfenner
184756893Sfenner	printf(" kauth");
184856893Sfenner
184956893Sfenner	if (is_ubik(kauth_op)) {
185056893Sfenner		ubik_print(bp, length);
185156893Sfenner		return;
185256893Sfenner	}
185356893Sfenner
185456893Sfenner
185556893Sfenner	printf(" call %s", tok2str(kauth_req, "op#%d", kauth_op));
185656893Sfenner
185756893Sfenner	/*
185856893Sfenner	 * Decode some of the arguments to the KA calls
185956893Sfenner	 */
186056893Sfenner
186156893Sfenner	bp += sizeof(struct rx_header) + 4;
186256893Sfenner
186356893Sfenner	switch (kauth_op) {
186456893Sfenner		case 1:		/* Authenticate old */;
186556893Sfenner		case 21:	/* Authenticate */
186656893Sfenner		case 22:	/* Authenticate-V2 */
186756893Sfenner		case 2:		/* Change PW */
186856893Sfenner		case 5:		/* Set fields */
186956893Sfenner		case 6:		/* Create user */
187056893Sfenner		case 7:		/* Delete user */
187156893Sfenner		case 8:		/* Get entry */
187256893Sfenner		case 14:	/* Unlock */
187356893Sfenner		case 15:	/* Lock status */
187456893Sfenner			printf(" principal");
187556893Sfenner			STROUT(KANAMEMAX);
187656893Sfenner			STROUT(KANAMEMAX);
187756893Sfenner			break;
187856893Sfenner		case 3:		/* GetTicket-old */
187956893Sfenner		case 23:	/* GetTicket */
188056893Sfenner		{
188156893Sfenner			int i;
188256893Sfenner			printf(" kvno");
188356893Sfenner			INTOUT();
188456893Sfenner			printf(" domain");
188556893Sfenner			STROUT(KANAMEMAX);
188675115Sfenner			TCHECK2(bp[0], sizeof(int32_t));
188775115Sfenner			i = (int) EXTRACT_32BITS(bp);
188856893Sfenner			bp += sizeof(int32_t);
188975115Sfenner			TCHECK2(bp[0], i);
189056893Sfenner			bp += i;
189156893Sfenner			printf(" principal");
189256893Sfenner			STROUT(KANAMEMAX);
189356893Sfenner			STROUT(KANAMEMAX);
189456893Sfenner			break;
189556893Sfenner		}
189656893Sfenner		case 4:		/* Set Password */
189756893Sfenner			printf(" principal");
189856893Sfenner			STROUT(KANAMEMAX);
189956893Sfenner			STROUT(KANAMEMAX);
190056893Sfenner			printf(" kvno");
190156893Sfenner			INTOUT();
190256893Sfenner			break;
190356893Sfenner		case 12:	/* Get password */
190456893Sfenner			printf(" name");
190556893Sfenner			STROUT(KANAMEMAX);
190656893Sfenner			break;
190756893Sfenner		default:
190856893Sfenner			;
190956893Sfenner	}
191056893Sfenner
191156893Sfenner	return;
191256893Sfenner
191356893Sfennertrunc:
191456893Sfenner	printf(" [|kauth]");
191556893Sfenner}
191656893Sfenner
191756893Sfenner/*
191856893Sfenner * Handle replies to the AFS Kerberos Authentication Service
191956893Sfenner */
192056893Sfenner
192156893Sfennerstatic void
192256893Sfennerkauth_reply_print(register const u_char *bp, int length, int32_t opcode)
192356893Sfenner{
192456893Sfenner	struct rx_header *rxh;
192556893Sfenner
192656893Sfenner	if (length <= sizeof(struct rx_header))
192756893Sfenner		return;
192856893Sfenner
192956893Sfenner	rxh = (struct rx_header *) bp;
193056893Sfenner
193156893Sfenner	/*
193256893Sfenner	 * Print out the afs call we're invoking.  The table used here was
193356893Sfenner	 * gleaned from kauth/kauth.rg
193456893Sfenner	 */
193556893Sfenner
193656893Sfenner	printf(" kauth");
193756893Sfenner
193856893Sfenner	if (is_ubik(opcode)) {
193956893Sfenner		ubik_reply_print(bp, length, opcode);
194056893Sfenner		return;
194156893Sfenner	}
194256893Sfenner
194356893Sfenner	printf(" reply %s", tok2str(kauth_req, "op#%d", opcode));
194456893Sfenner
194556893Sfenner	bp += sizeof(struct rx_header);
194656893Sfenner
194756893Sfenner	/*
194856893Sfenner	 * If it was a data packet, interpret the response.
194956893Sfenner	 */
195056893Sfenner
195156893Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA)
195256893Sfenner		/* Well, no, not really.  Leave this for later */
195356893Sfenner		;
195456893Sfenner	else {
195556893Sfenner		/*
195656893Sfenner		 * Otherwise, just print out the return code
195756893Sfenner		 */
195856893Sfenner		printf(" errcode");
195956893Sfenner		INTOUT();
196056893Sfenner	}
196156893Sfenner
196256893Sfenner	return;
196356893Sfenner
196456893Sfennertrunc:
196556893Sfenner	printf(" [|kauth]");
196656893Sfenner}
196756893Sfenner
196856893Sfenner/*
196956893Sfenner * Handle calls to the AFS Volume location service
197056893Sfenner */
197156893Sfenner
197256893Sfennerstatic void
197356893Sfennervol_print(register const u_char *bp, int length)
197456893Sfenner{
197556893Sfenner	int vol_op;
197656893Sfenner
197756893Sfenner	if (length <= sizeof(struct rx_header))
197856893Sfenner		return;
197956893Sfenner
198056893Sfenner	if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) {
198156893Sfenner		goto trunc;
198256893Sfenner	}
198356893Sfenner
198456893Sfenner	/*
198556893Sfenner	 * Print out the afs call we're invoking.  The table used here was
198656893Sfenner	 * gleaned from volser/volint.xg
198756893Sfenner	 */
198856893Sfenner
198975115Sfenner	vol_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
199056893Sfenner
199156893Sfenner	printf(" vol call %s", tok2str(vol_req, "op#%d", vol_op));
199256893Sfenner
199356893Sfenner	/*
199456893Sfenner	 * Normally there would be a switch statement here to decode the
199556893Sfenner	 * arguments to the AFS call, but since I don't have access to
199656893Sfenner	 * an AFS server (yet) and I'm not an AFS admin, I can't
199756893Sfenner	 * test any of these calls.  Leave this blank for now.
199856893Sfenner	 */
199956893Sfenner
200056893Sfenner	return;
200156893Sfenner
200256893Sfennertrunc:
200356893Sfenner	printf(" [|vol]");
200456893Sfenner}
200556893Sfenner
200656893Sfenner/*
200756893Sfenner * Handle replies to the AFS Volume Service
200856893Sfenner */
200956893Sfenner
201056893Sfennerstatic void
201156893Sfennervol_reply_print(register const u_char *bp, int length, int32_t opcode)
201256893Sfenner{
201356893Sfenner	struct rx_header *rxh;
201456893Sfenner
201556893Sfenner	if (length <= sizeof(struct rx_header))
201656893Sfenner		return;
201756893Sfenner
201856893Sfenner	rxh = (struct rx_header *) bp;
201956893Sfenner
202056893Sfenner	/*
202156893Sfenner	 * Print out the afs call we're invoking.  The table used here was
202256893Sfenner	 * gleaned from volser/volint.xg
202356893Sfenner	 */
202456893Sfenner
202556893Sfenner	printf(" vol reply %s", tok2str(vol_req, "op#%d", opcode));
202656893Sfenner
202756893Sfenner	bp += sizeof(struct rx_header);
202856893Sfenner
202956893Sfenner	/*
203056893Sfenner	 * If it was a data packet, interpret the response.
203156893Sfenner	 */
203256893Sfenner
203356893Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA)
203456893Sfenner		/* Well, no, not really.  Leave this for later */
203556893Sfenner		;
203656893Sfenner	else {
203756893Sfenner		/*
203856893Sfenner		 * Otherwise, just print out the return code
203956893Sfenner		 */
204056893Sfenner		printf(" errcode");
204156893Sfenner		INTOUT();
204256893Sfenner	}
204356893Sfenner
204456893Sfenner	return;
204556893Sfenner
204656893Sfennertrunc:
204756893Sfenner	printf(" [|vol]");
204856893Sfenner}
204956893Sfenner
205056893Sfenner/*
205156893Sfenner * Handle calls to the AFS BOS service
205256893Sfenner */
205356893Sfenner
205456893Sfennerstatic void
205556893Sfennerbos_print(register const u_char *bp, int length)
205656893Sfenner{
205756893Sfenner	int bos_op;
205856893Sfenner
205956893Sfenner	if (length <= sizeof(struct rx_header))
206056893Sfenner		return;
206156893Sfenner
206256893Sfenner	if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) {
206356893Sfenner		goto trunc;
206456893Sfenner	}
206556893Sfenner
206656893Sfenner	/*
206756893Sfenner	 * Print out the afs call we're invoking.  The table used here was
206856893Sfenner	 * gleaned from bozo/bosint.xg
206956893Sfenner	 */
207056893Sfenner
207175115Sfenner	bos_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
207256893Sfenner
207356893Sfenner	printf(" bos call %s", tok2str(bos_req, "op#%d", bos_op));
207456893Sfenner
207556893Sfenner	/*
207656893Sfenner	 * Decode some of the arguments to the BOS calls
207756893Sfenner	 */
207856893Sfenner
207956893Sfenner	bp += sizeof(struct rx_header) + 4;
208056893Sfenner
208156893Sfenner	switch (bos_op) {
208256893Sfenner		case 80:	/* Create B node */
208356893Sfenner			printf(" type");
208456893Sfenner			STROUT(BOSNAMEMAX);
208556893Sfenner			printf(" instance");
208656893Sfenner			STROUT(BOSNAMEMAX);
208756893Sfenner			break;
208856893Sfenner		case 81:	/* Delete B node */
208956893Sfenner		case 83:	/* Get status */
209056893Sfenner		case 85:	/* Get instance info */
209156893Sfenner		case 87:	/* Add super user */
209256893Sfenner		case 88:	/* Delete super user */
209356893Sfenner		case 93:	/* Set cell name */
209456893Sfenner		case 96:	/* Add cell host */
209556893Sfenner		case 97:	/* Delete cell host */
209656893Sfenner		case 104:	/* Restart */
209756893Sfenner		case 106:	/* Uninstall */
209856893Sfenner		case 108:	/* Exec */
209956893Sfenner		case 112:	/* Getlog */
210056893Sfenner		case 114:	/* Get instance strings */
210156893Sfenner			STROUT(BOSNAMEMAX);
210256893Sfenner			break;
210356893Sfenner		case 82:	/* Set status */
210456893Sfenner		case 98:	/* Set T status */
210556893Sfenner			STROUT(BOSNAMEMAX);
210656893Sfenner			printf(" status");
210756893Sfenner			INTOUT();
210856893Sfenner			break;
210956893Sfenner		case 86:	/* Get instance parm */
211056893Sfenner			STROUT(BOSNAMEMAX);
211156893Sfenner			printf(" num");
211256893Sfenner			INTOUT();
211356893Sfenner			break;
211456893Sfenner		case 84:	/* Enumerate instance */
211556893Sfenner		case 89:	/* List super users */
211656893Sfenner		case 90:	/* List keys */
211756893Sfenner		case 91:	/* Add key */
211856893Sfenner		case 92:	/* Delete key */
211956893Sfenner		case 95:	/* Get cell host */
212056893Sfenner			INTOUT();
212156893Sfenner			break;
212256893Sfenner		case 105:	/* Install */
212356893Sfenner			STROUT(BOSNAMEMAX);
212456893Sfenner			printf(" size");
212556893Sfenner			INTOUT();
212656893Sfenner			printf(" flags");
212756893Sfenner			INTOUT();
212856893Sfenner			printf(" date");
212956893Sfenner			INTOUT();
213056893Sfenner			break;
213156893Sfenner		default:
213256893Sfenner			;
213356893Sfenner	}
213456893Sfenner
213556893Sfenner	return;
213656893Sfenner
213756893Sfennertrunc:
213856893Sfenner	printf(" [|bos]");
213956893Sfenner}
214056893Sfenner
214156893Sfenner/*
214256893Sfenner * Handle replies to the AFS BOS Service
214356893Sfenner */
214456893Sfenner
214556893Sfennerstatic void
214656893Sfennerbos_reply_print(register const u_char *bp, int length, int32_t opcode)
214756893Sfenner{
214856893Sfenner	struct rx_header *rxh;
214956893Sfenner
215056893Sfenner	if (length <= sizeof(struct rx_header))
215156893Sfenner		return;
215256893Sfenner
215356893Sfenner	rxh = (struct rx_header *) bp;
215456893Sfenner
215556893Sfenner	/*
215656893Sfenner	 * Print out the afs call we're invoking.  The table used here was
215756893Sfenner	 * gleaned from volser/volint.xg
215856893Sfenner	 */
215956893Sfenner
216056893Sfenner	printf(" bos reply %s", tok2str(bos_req, "op#%d", opcode));
216156893Sfenner
216256893Sfenner	bp += sizeof(struct rx_header);
216356893Sfenner
216456893Sfenner	/*
216556893Sfenner	 * If it was a data packet, interpret the response.
216656893Sfenner	 */
216756893Sfenner
216856893Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA)
216956893Sfenner		/* Well, no, not really.  Leave this for later */
217056893Sfenner		;
217156893Sfenner	else {
217256893Sfenner		/*
217356893Sfenner		 * Otherwise, just print out the return code
217456893Sfenner		 */
217556893Sfenner		printf(" errcode");
217656893Sfenner		INTOUT();
217756893Sfenner	}
217856893Sfenner
217956893Sfenner	return;
218056893Sfenner
218156893Sfennertrunc:
218256893Sfenner	printf(" [|bos]");
218356893Sfenner}
218456893Sfenner
218556893Sfenner/*
218656893Sfenner * Check to see if this is a Ubik opcode.
218756893Sfenner */
218856893Sfenner
218956893Sfennerstatic int
219056893Sfenneris_ubik(u_int32_t opcode)
219156893Sfenner{
219256893Sfenner	if ((opcode >= VOTE_LOW && opcode <= VOTE_HIGH) ||
219356893Sfenner	    (opcode >= DISK_LOW && opcode <= DISK_HIGH))
219456893Sfenner		return(1);
219556893Sfenner	else
219656893Sfenner		return(0);
219756893Sfenner}
219856893Sfenner
219956893Sfenner/*
220056893Sfenner * Handle Ubik opcodes to any one of the replicated database services
220156893Sfenner */
220256893Sfenner
220356893Sfennerstatic void
220456893Sfennerubik_print(register const u_char *bp, int length)
220556893Sfenner{
220656893Sfenner	int ubik_op;
220756893Sfenner	int32_t temp;
220856893Sfenner
220956893Sfenner	/*
221056893Sfenner	 * Print out the afs call we're invoking.  The table used here was
221156893Sfenner	 * gleaned from ubik/ubik_int.xg
221256893Sfenner	 */
221356893Sfenner
221475115Sfenner	ubik_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
221556893Sfenner
221656893Sfenner	printf(" ubik call %s", tok2str(ubik_req, "op#%d", ubik_op));
221756893Sfenner
221856893Sfenner	/*
221956893Sfenner	 * Decode some of the arguments to the Ubik calls
222056893Sfenner	 */
222156893Sfenner
222256893Sfenner	bp += sizeof(struct rx_header) + 4;
222356893Sfenner
222456893Sfenner	switch (ubik_op) {
222556893Sfenner		case 10000:		/* Beacon */
222675115Sfenner			TCHECK2(bp[0], 4);
222775115Sfenner			temp = EXTRACT_32BITS(bp);
222856893Sfenner			bp += sizeof(int32_t);
222956893Sfenner			printf(" syncsite %s", temp ? "yes" : "no");
223056893Sfenner			printf(" votestart");
223156893Sfenner			DATEOUT();
223256893Sfenner			printf(" dbversion");
223356893Sfenner			UBIK_VERSIONOUT();
223456893Sfenner			printf(" tid");
223556893Sfenner			UBIK_VERSIONOUT();
223656893Sfenner			break;
223756893Sfenner		case 10003:		/* Get sync site */
223856893Sfenner			printf(" site");
223956893Sfenner			UINTOUT();
224056893Sfenner			break;
224156893Sfenner		case 20000:		/* Begin */
224256893Sfenner		case 20001:		/* Commit */
224356893Sfenner		case 20007:		/* Abort */
224456893Sfenner		case 20008:		/* Release locks */
224556893Sfenner		case 20010:		/* Writev */
224656893Sfenner			printf(" tid");
224756893Sfenner			UBIK_VERSIONOUT();
224856893Sfenner			break;
224956893Sfenner		case 20002:		/* Lock */
225056893Sfenner			printf(" tid");
225156893Sfenner			UBIK_VERSIONOUT();
225256893Sfenner			printf(" file");
225356893Sfenner			INTOUT();
225456893Sfenner			printf(" pos");
225556893Sfenner			INTOUT();
225656893Sfenner			printf(" length");
225756893Sfenner			INTOUT();
225875115Sfenner			temp = EXTRACT_32BITS(bp);
225956893Sfenner			bp += sizeof(int32_t);
226056893Sfenner			tok2str(ubik_lock_types, "type %d", temp);
226156893Sfenner			break;
226256893Sfenner		case 20003:		/* Write */
226356893Sfenner			printf(" tid");
226456893Sfenner			UBIK_VERSIONOUT();
226556893Sfenner			printf(" file");
226656893Sfenner			INTOUT();
226756893Sfenner			printf(" pos");
226856893Sfenner			INTOUT();
226956893Sfenner			break;
227056893Sfenner		case 20005:		/* Get file */
227156893Sfenner			printf(" file");
227256893Sfenner			INTOUT();
227356893Sfenner			break;
227456893Sfenner		case 20006:		/* Send file */
227556893Sfenner			printf(" file");
227656893Sfenner			INTOUT();
227756893Sfenner			printf(" length");
227856893Sfenner			INTOUT();
227956893Sfenner			printf(" dbversion");
228056893Sfenner			UBIK_VERSIONOUT();
228156893Sfenner			break;
228256893Sfenner		case 20009:		/* Truncate */
228356893Sfenner			printf(" tid");
228456893Sfenner			UBIK_VERSIONOUT();
228556893Sfenner			printf(" file");
228656893Sfenner			INTOUT();
228756893Sfenner			printf(" length");
228856893Sfenner			INTOUT();
228956893Sfenner			break;
229056893Sfenner		case 20012:		/* Set version */
229156893Sfenner			printf(" tid");
229256893Sfenner			UBIK_VERSIONOUT();
229356893Sfenner			printf(" oldversion");
229456893Sfenner			UBIK_VERSIONOUT();
229556893Sfenner			printf(" newversion");
229656893Sfenner			UBIK_VERSIONOUT();
229756893Sfenner			break;
229856893Sfenner		default:
229956893Sfenner			;
230056893Sfenner	}
230156893Sfenner
230256893Sfenner	return;
230356893Sfenner
230456893Sfennertrunc:
230556893Sfenner	printf(" [|ubik]");
230656893Sfenner}
230756893Sfenner
230856893Sfenner/*
230956893Sfenner * Handle Ubik replies to any one of the replicated database services
231056893Sfenner */
231156893Sfenner
231256893Sfennerstatic void
231356893Sfennerubik_reply_print(register const u_char *bp, int length, int32_t opcode)
231456893Sfenner{
231556893Sfenner	struct rx_header *rxh;
231656893Sfenner
231756893Sfenner	if (length < sizeof(struct rx_header))
231856893Sfenner		return;
231956893Sfenner
232056893Sfenner	rxh = (struct rx_header *) bp;
232156893Sfenner
232256893Sfenner	/*
232356893Sfenner	 * Print out the ubik call we're invoking.  This table was gleaned
232456893Sfenner	 * from ubik/ubik_int.xg
232556893Sfenner	 */
232656893Sfenner
232756893Sfenner	printf(" ubik reply %s", tok2str(ubik_req, "op#%d", opcode));
232856893Sfenner
232956893Sfenner	bp += sizeof(struct rx_header);
233056893Sfenner
233156893Sfenner	/*
233256893Sfenner	 * If it was a data packet, print out the arguments to the Ubik calls
233356893Sfenner	 */
233456893Sfenner
233556893Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA)
233656893Sfenner		switch (opcode) {
233756893Sfenner		case 10000:		/* Beacon */
233856893Sfenner			printf(" vote no");
233956893Sfenner			break;
234056893Sfenner		case 20004:		/* Get version */
234156893Sfenner			printf(" dbversion");
234256893Sfenner			UBIK_VERSIONOUT();
234356893Sfenner			break;
234456893Sfenner		default:
234556893Sfenner			;
234656893Sfenner		}
234756893Sfenner
234856893Sfenner	/*
234956893Sfenner	 * Otherwise, print out "yes" it it was a beacon packet (because
235056893Sfenner	 * that's how yes votes are returned, go figure), otherwise
235156893Sfenner	 * just print out the error code.
235256893Sfenner	 */
235356893Sfenner
235456893Sfenner	else
235556893Sfenner		switch (opcode) {
235656893Sfenner		case 10000:		/* Beacon */
235756893Sfenner			printf(" vote yes until");
235856893Sfenner			DATEOUT();
235956893Sfenner			break;
236056893Sfenner		default:
236156893Sfenner			printf(" errcode");
236256893Sfenner			INTOUT();
236356893Sfenner		}
236456893Sfenner
236556893Sfenner	return;
236656893Sfenner
236756893Sfennertrunc:
236856893Sfenner	printf(" [|ubik]");
236956893Sfenner}
237075115Sfenner
237175115Sfenner/*
237275115Sfenner * Handle RX ACK packets.
237375115Sfenner */
237475115Sfenner
237575115Sfennerstatic void
237675115Sfennerrx_ack_print(register const u_char *bp, int length)
237775115Sfenner{
237875115Sfenner	struct rx_ackPacket *rxa;
237975115Sfenner	int i, start, last;
238075115Sfenner
238175115Sfenner	if (length < sizeof(struct rx_header))
238275115Sfenner		return;
238375115Sfenner
238475115Sfenner	bp += sizeof(struct rx_header);
238575115Sfenner
238675115Sfenner	/*
238775115Sfenner	 * This may seem a little odd .... the rx_ackPacket structure
238875115Sfenner	 * contains an array of individual packet acknowledgements
238975115Sfenner	 * (used for selective ack/nack), but since it's variable in size,
239075115Sfenner	 * we don't want to truncate based on the size of the whole
239175115Sfenner	 * rx_ackPacket structure.
239275115Sfenner	 */
239375115Sfenner
239475115Sfenner	TCHECK2(bp[0], sizeof(struct rx_ackPacket) - RX_MAXACKS);
239575115Sfenner
239675115Sfenner	rxa = (struct rx_ackPacket *) bp;
239775115Sfenner	bp += (sizeof(struct rx_ackPacket) - RX_MAXACKS);
239875115Sfenner
239975115Sfenner	/*
240075115Sfenner	 * Print out a few useful things from the ack packet structure
240175115Sfenner	 */
240275115Sfenner
240375115Sfenner	if (vflag > 2)
240475115Sfenner		printf(" bufspace %d maxskew %d",
240575115Sfenner		       (int) EXTRACT_16BITS(&rxa->bufferSpace),
240675115Sfenner		       (int) EXTRACT_16BITS(&rxa->maxSkew));
240775115Sfenner
240875115Sfenner	printf(" first %d serial %d reason %s",
240975115Sfenner	       EXTRACT_32BITS(&rxa->firstPacket), EXTRACT_32BITS(&rxa->serial),
241075115Sfenner	       tok2str(rx_ack_reasons, "#%d", (int) rxa->reason));
241175115Sfenner
241275115Sfenner	/*
241375115Sfenner	 * Okay, now we print out the ack array.  The way _this_ works
241475115Sfenner	 * is that we start at "first", and step through the ack array.
241575115Sfenner	 * If we have a contiguous range of acks/nacks, try to
241675115Sfenner	 * collapse them into a range.
241775115Sfenner	 *
241875115Sfenner	 * If you're really clever, you might have noticed that this
241975115Sfenner	 * doesn't seem quite correct.  Specifically, due to structure
242075115Sfenner	 * padding, sizeof(struct rx_ackPacket) - RX_MAXACKS won't actually
242175115Sfenner	 * yield the start of the ack array (because RX_MAXACKS is 255
242275115Sfenner	 * and the structure will likely get padded to a 2 or 4 byte
242375115Sfenner	 * boundary).  However, this is the way it's implemented inside
242475115Sfenner	 * of AFS - the start of the extra fields are at
242575115Sfenner	 * sizeof(struct rx_ackPacket) - RX_MAXACKS + nAcks, which _isn't_
242675115Sfenner	 * the exact start of the ack array.  Sigh.  That's why we aren't
242775115Sfenner	 * using bp, but instead use rxa->acks[].  But nAcks gets added
242875115Sfenner	 * to bp after this, so bp ends up at the right spot.  Go figure.
242975115Sfenner	 */
243075115Sfenner
243175115Sfenner	if (rxa->nAcks != 0) {
243275115Sfenner
243375115Sfenner		TCHECK2(bp[0], rxa->nAcks);
243475115Sfenner
243575115Sfenner		/*
243675115Sfenner		 * Sigh, this is gross, but it seems to work to collapse
243775115Sfenner		 * ranges correctly.
243875115Sfenner		 */
243975115Sfenner
244075115Sfenner		for (i = 0, start = last = -2; i < rxa->nAcks; i++)
244175115Sfenner			if (rxa->acks[i] == RX_ACK_TYPE_ACK) {
244275115Sfenner
244375115Sfenner				/*
244475115Sfenner				 * I figured this deserved _some_ explanation.
244575115Sfenner				 * First, print "acked" and the packet seq
244675115Sfenner				 * number if this is the first time we've
244775115Sfenner				 * seen an acked packet.
244875115Sfenner				 */
244975115Sfenner
245075115Sfenner				if (last == -2) {
245175115Sfenner					printf(" acked %d",
245275115Sfenner					       rxa->firstPacket + i);
245375115Sfenner					start = i;
245475115Sfenner				}
245575115Sfenner
245675115Sfenner				/*
245775115Sfenner				 * Otherwise, if the there is a skip in
245875115Sfenner				 * the range (such as an nacked packet in
245975115Sfenner				 * the middle of some acked packets),
246075115Sfenner				 * then print the current packet number
246175115Sfenner				 * seperated from the last number by
246275115Sfenner				 * a comma.
246375115Sfenner				 */
246475115Sfenner
246575115Sfenner				else if (last != i - 1) {
246675115Sfenner					printf(",%d", rxa->firstPacket + i);
246775115Sfenner					start = i;
246875115Sfenner				}
246975115Sfenner
247075115Sfenner				/*
247175115Sfenner				 * We always set last to the value of
247275115Sfenner				 * the last ack we saw.  Conversely, start
247375115Sfenner				 * is set to the value of the first ack
247475115Sfenner				 * we saw in a range.
247575115Sfenner				 */
247675115Sfenner
247775115Sfenner				last = i;
247875115Sfenner
247975115Sfenner				/*
248075115Sfenner				 * Okay, this bit a code gets executed when
248175115Sfenner				 * we hit a nack ... in _this_ case we
248275115Sfenner				 * want to print out the range of packets
248375115Sfenner				 * that were acked, so we need to print
248475115Sfenner				 * the _previous_ packet number seperated
248575115Sfenner				 * from the first by a dash (-).  Since we
248675115Sfenner				 * already printed the first packet above,
248775115Sfenner				 * just print the final packet.  Don't
248875115Sfenner				 * do this if there will be a single-length
248975115Sfenner				 * range.
249075115Sfenner				 */
249175115Sfenner			} else if (last == i - 1 && start != last)
249275115Sfenner				printf("-%d", rxa->firstPacket + i - 1);
249375115Sfenner
249475115Sfenner		/*
249575115Sfenner		 * So, what's going on here?  We ran off the end of the
249675115Sfenner		 * ack list, and if we got a range we need to finish it up.
249775115Sfenner		 * So we need to determine if the last packet in the list
249875115Sfenner		 * was an ack (if so, then last will be set to it) and
249975115Sfenner		 * we need to see if the last range didn't start with the
250075115Sfenner		 * last packet (because if it _did_, then that would mean
250175115Sfenner		 * that the packet number has already been printed and
250275115Sfenner		 * we don't need to print it again).
250375115Sfenner		 */
250475115Sfenner
250575115Sfenner		if (last == i - 1 && start != last)
250675115Sfenner			printf("-%d", rxa->firstPacket + i - 1);
250775115Sfenner
250875115Sfenner		/*
250975115Sfenner		 * Same as above, just without comments
251075115Sfenner		 */
251175115Sfenner
251275115Sfenner		for (i = 0, start = last = -2; i < rxa->nAcks; i++)
251375115Sfenner			if (rxa->acks[i] == RX_ACK_TYPE_NACK) {
251475115Sfenner				if (last == -2) {
251575115Sfenner					printf(" nacked %d",
251675115Sfenner					       rxa->firstPacket + i);
251775115Sfenner					start = i;
251875115Sfenner				} else if (last != i - 1) {
251975115Sfenner					printf(",%d", rxa->firstPacket + i);
252075115Sfenner					start = i;
252175115Sfenner				}
252275115Sfenner				last = i;
252375115Sfenner			} else if (last == i - 1 && start != last)
252475115Sfenner				printf("-%d", rxa->firstPacket + i - 1);
252575115Sfenner
252675115Sfenner		if (last == i - 1 && start != last)
252775115Sfenner			printf("-%d", rxa->firstPacket + i - 1);
252875115Sfenner
252975115Sfenner		bp += rxa->nAcks;
253075115Sfenner	}
253175115Sfenner
253275115Sfenner
253375115Sfenner	/*
253475115Sfenner	 * These are optional fields; depending on your version of AFS,
253575115Sfenner	 * you may or may not see them
253675115Sfenner	 */
253775115Sfenner
253875115Sfenner#define TRUNCRET(n)	if (snapend - bp + 1 <= n) return;
253975115Sfenner
254075115Sfenner	if (vflag > 1) {
254175115Sfenner		TRUNCRET(4);
254275115Sfenner		printf(" ifmtu");
254375115Sfenner		INTOUT();
254475115Sfenner
254575115Sfenner		TRUNCRET(4);
254675115Sfenner		printf(" maxmtu");
254775115Sfenner		INTOUT();
254875115Sfenner
254975115Sfenner		TRUNCRET(4);
255075115Sfenner		printf(" rwind");
255175115Sfenner		INTOUT();
255275115Sfenner
255375115Sfenner		TRUNCRET(4);
255475115Sfenner		printf(" maxpackets");
255575115Sfenner		INTOUT();
255675115Sfenner	}
255775115Sfenner
255875115Sfenner	return;
255975115Sfenner
256075115Sfennertrunc:
256175115Sfenner	printf(" [|ack]");
256275115Sfenner}
256375115Sfenner#undef TRUNCRET
2564