print-rx.c revision 172683
156893Sfenner/*
298524Sfenner * Copyright: (c) 2000 United States Government as represented by the
398524Sfenner *	Secretary of the Navy. All rights reserved.
498524Sfenner *
598524Sfenner * Redistribution and use in source and binary forms, with or without
698524Sfenner * modification, are permitted provided that the following conditions
798524Sfenner * are met:
8127668Sbms *
998524Sfenner *   1. Redistributions of source code must retain the above copyright
1098524Sfenner *      notice, this list of conditions and the following disclaimer.
1198524Sfenner *   2. Redistributions in binary form must reproduce the above copyright
1298524Sfenner *      notice, this list of conditions and the following disclaimer in
1398524Sfenner *      the documentation and/or other materials provided with the
1498524Sfenner *      distribution.
1598524Sfenner *   3. The names of the authors may not be used to endorse or promote
1698524Sfenner *      products derived from this software without specific prior
1798524Sfenner *      written permission.
18127668Sbms *
1998524Sfenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2098524Sfenner * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2198524Sfenner * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2298524Sfenner */
2398524Sfenner/*
2456893Sfenner * This code unmangles RX packets.  RX is the mutant form of RPC that AFS
2556893Sfenner * uses to communicate between clients and servers.
2656893Sfenner *
2756893Sfenner * In this code, I mainly concern myself with decoding the AFS calls, not
2856893Sfenner * with the guts of RX, per se.
2956893Sfenner *
3056893Sfenner * Bah.  If I never look at rx_packet.h again, it will be too soon.
3156893Sfenner *
3256893Sfenner * Ken Hornstein <kenh@cmf.nrl.navy.mil>
3356893Sfenner */
3456893Sfenner
3556893Sfenner#ifndef lint
36127668Sbmsstatic const char rcsid[] _U_ =
37172683Smlaier    "@(#) $Header: /tcpdump/master/tcpdump/print-rx.c,v 1.37.2.2 2007/06/15 19:43:15 guy Exp $";
3856893Sfenner#endif
3956893Sfenner
4056893Sfenner#ifdef HAVE_CONFIG_H
4156893Sfenner#include "config.h"
4256893Sfenner#endif
4356893Sfenner
4456893Sfenner#include <stdio.h>
4575115Sfenner#include <stdlib.h>
4656893Sfenner#include <string.h>
47127668Sbms#include <tcpdump-stdinc.h>
4856893Sfenner
4956893Sfenner#include "interface.h"
5056893Sfenner#include "addrtoname.h"
5175115Sfenner#include "extract.h"
5256893Sfenner
5356893Sfenner#include "rx.h"
5456893Sfenner
5575115Sfenner#include "ip.h"
5675115Sfenner
5756893Sfennerstatic struct tok rx_types[] = {
5856893Sfenner	{ RX_PACKET_TYPE_DATA,		"data" },
5956893Sfenner	{ RX_PACKET_TYPE_ACK,		"ack" },
6056893Sfenner	{ RX_PACKET_TYPE_BUSY,		"busy" },
6156893Sfenner	{ RX_PACKET_TYPE_ABORT,		"abort" },
6256893Sfenner	{ RX_PACKET_TYPE_ACKALL,	"ackall" },
6356893Sfenner	{ RX_PACKET_TYPE_CHALLENGE,	"challenge" },
6456893Sfenner	{ RX_PACKET_TYPE_RESPONSE,	"response" },
6556893Sfenner	{ RX_PACKET_TYPE_DEBUG,		"debug" },
6656893Sfenner	{ RX_PACKET_TYPE_PARAMS,	"params" },
6756893Sfenner	{ RX_PACKET_TYPE_VERSION,	"version" },
6856893Sfenner	{ 0,				NULL },
6956893Sfenner};
7056893Sfenner
7198524Sfennerstatic struct double_tok {
7298524Sfenner	int flag;		/* Rx flag */
7398524Sfenner	int packetType;		/* Packet type */
74127668Sbms	const char *s;		/* Flag string */
7598524Sfenner} rx_flags[] = {
7698524Sfenner	{ RX_CLIENT_INITIATED,	0,			"client-init" },
7798524Sfenner	{ RX_REQUEST_ACK,	0,			"req-ack" },
7898524Sfenner	{ RX_LAST_PACKET,	0,			"last-pckt" },
7998524Sfenner	{ RX_MORE_PACKETS,	0,			"more-pckts" },
8098524Sfenner	{ RX_FREE_PACKET,	0,			"free-pckt" },
8198524Sfenner	{ RX_SLOW_START_OK,	RX_PACKET_TYPE_ACK,	"slow-start" },
8298524Sfenner	{ RX_JUMBO_PACKET,	RX_PACKET_TYPE_DATA,	"jumbogram" }
8356893Sfenner};
8456893Sfenner
8556893Sfennerstatic struct tok fs_req[] = {
8656893Sfenner	{ 130,		"fetch-data" },
8756893Sfenner	{ 131,		"fetch-acl" },
8856893Sfenner	{ 132,		"fetch-status" },
8956893Sfenner	{ 133,		"store-data" },
9056893Sfenner	{ 134,		"store-acl" },
9156893Sfenner	{ 135,		"store-status" },
9256893Sfenner	{ 136,		"remove-file" },
9356893Sfenner	{ 137,		"create-file" },
9456893Sfenner	{ 138,		"rename" },
9556893Sfenner	{ 139,		"symlink" },
9656893Sfenner	{ 140,		"link" },
9756893Sfenner	{ 141,		"makedir" },
9856893Sfenner	{ 142,		"rmdir" },
9956893Sfenner	{ 143,		"oldsetlock" },
10056893Sfenner	{ 144,		"oldextlock" },
10156893Sfenner	{ 145,		"oldrellock" },
10256893Sfenner	{ 146,		"get-stats" },
10356893Sfenner	{ 147,		"give-cbs" },
10456893Sfenner	{ 148,		"get-vlinfo" },
10556893Sfenner	{ 149,		"get-vlstats" },
10656893Sfenner	{ 150,		"set-vlstats" },
10756893Sfenner	{ 151,		"get-rootvl" },
10856893Sfenner	{ 152,		"check-token" },
10956893Sfenner	{ 153,		"get-time" },
11056893Sfenner	{ 154,		"nget-vlinfo" },
11156893Sfenner	{ 155,		"bulk-stat" },
11256893Sfenner	{ 156,		"setlock" },
11356893Sfenner	{ 157,		"extlock" },
11456893Sfenner	{ 158,		"rellock" },
11556893Sfenner	{ 159,		"xstat-ver" },
11656893Sfenner	{ 160,		"get-xstat" },
11756893Sfenner	{ 161,		"dfs-lookup" },
11856893Sfenner	{ 162,		"dfs-flushcps" },
11956893Sfenner	{ 163,		"dfs-symlink" },
12098524Sfenner	{ 220,		"residency" },
12156893Sfenner	{ 0,		NULL },
12256893Sfenner};
12356893Sfenner
12456893Sfennerstatic struct tok cb_req[] = {
12556893Sfenner	{ 204,		"callback" },
12656893Sfenner	{ 205,		"initcb" },
12756893Sfenner	{ 206,		"probe" },
12856893Sfenner	{ 207,		"getlock" },
12956893Sfenner	{ 208,		"getce" },
13056893Sfenner	{ 209,		"xstatver" },
13156893Sfenner	{ 210,		"getxstat" },
13256893Sfenner	{ 211,		"initcb2" },
13356893Sfenner	{ 212,		"whoareyou" },
13456893Sfenner	{ 213,		"initcb3" },
13556893Sfenner	{ 214,		"probeuuid" },
13698524Sfenner	{ 215,		"getsrvprefs" },
13798524Sfenner	{ 216,		"getcellservdb" },
13898524Sfenner	{ 217,		"getlocalcell" },
13998524Sfenner	{ 218,		"getcacheconf" },
14056893Sfenner	{ 0,		NULL },
14156893Sfenner};
14256893Sfenner
14356893Sfennerstatic struct tok pt_req[] = {
14456893Sfenner	{ 500,		"new-user" },
14556893Sfenner	{ 501,		"where-is-it" },
14656893Sfenner	{ 502,		"dump-entry" },
14756893Sfenner	{ 503,		"add-to-group" },
14856893Sfenner	{ 504,		"name-to-id" },
14956893Sfenner	{ 505,		"id-to-name" },
15056893Sfenner	{ 506,		"delete" },
15156893Sfenner	{ 507,		"remove-from-group" },
15256893Sfenner	{ 508,		"get-cps" },
15356893Sfenner	{ 509,		"new-entry" },
15456893Sfenner	{ 510,		"list-max" },
15556893Sfenner	{ 511,		"set-max" },
15656893Sfenner	{ 512,		"list-entry" },
15756893Sfenner	{ 513,		"change-entry" },
15856893Sfenner	{ 514,		"list-elements" },
15956893Sfenner	{ 515,		"same-mbr-of" },
16056893Sfenner	{ 516,		"set-fld-sentry" },
16156893Sfenner	{ 517,		"list-owned" },
16256893Sfenner	{ 518,		"get-cps2" },
16356893Sfenner	{ 519,		"get-host-cps" },
16456893Sfenner	{ 520,		"update-entry" },
16598524Sfenner	{ 521,		"list-entries" },
16656893Sfenner	{ 0,		NULL },
16756893Sfenner};
16856893Sfenner
16956893Sfennerstatic struct tok vldb_req[] = {
17056893Sfenner	{ 501,		"create-entry" },
17156893Sfenner	{ 502,		"delete-entry" },
17256893Sfenner	{ 503,		"get-entry-by-id" },
17356893Sfenner	{ 504,		"get-entry-by-name" },
17456893Sfenner	{ 505,		"get-new-volume-id" },
17556893Sfenner	{ 506,		"replace-entry" },
17656893Sfenner	{ 507,		"update-entry" },
17756893Sfenner	{ 508,		"setlock" },
17856893Sfenner	{ 509,		"releaselock" },
17956893Sfenner	{ 510,		"list-entry" },
18056893Sfenner	{ 511,		"list-attrib" },
18156893Sfenner	{ 512,		"linked-list" },
18256893Sfenner	{ 513,		"get-stats" },
18356893Sfenner	{ 514,		"probe" },
18456893Sfenner	{ 515,		"get-addrs" },
18556893Sfenner	{ 516,		"change-addr" },
18656893Sfenner	{ 517,		"create-entry-n" },
18756893Sfenner	{ 518,		"get-entry-by-id-n" },
18856893Sfenner	{ 519,		"get-entry-by-name-n" },
18956893Sfenner	{ 520,		"replace-entry-n" },
19056893Sfenner	{ 521,		"list-entry-n" },
19156893Sfenner	{ 522,		"list-attrib-n" },
19256893Sfenner	{ 523,		"linked-list-n" },
19356893Sfenner	{ 524,		"update-entry-by-name" },
19456893Sfenner	{ 525,		"create-entry-u" },
19556893Sfenner	{ 526,		"get-entry-by-id-u" },
19656893Sfenner	{ 527,		"get-entry-by-name-u" },
19756893Sfenner	{ 528,		"replace-entry-u" },
19856893Sfenner	{ 529,		"list-entry-u" },
19956893Sfenner	{ 530,		"list-attrib-u" },
20056893Sfenner	{ 531,		"linked-list-u" },
20156893Sfenner	{ 532,		"regaddr" },
20256893Sfenner	{ 533,		"get-addrs-u" },
20398524Sfenner	{ 534,		"list-attrib-n2" },
20456893Sfenner	{ 0,		NULL },
20556893Sfenner};
20656893Sfenner
20756893Sfennerstatic struct tok kauth_req[] = {
20856893Sfenner	{ 1,		"auth-old" },
20956893Sfenner	{ 21,		"authenticate" },
21056893Sfenner	{ 22,		"authenticate-v2" },
21156893Sfenner	{ 2,		"change-pw" },
21256893Sfenner	{ 3,		"get-ticket-old" },
21356893Sfenner	{ 23,		"get-ticket" },
21456893Sfenner	{ 4,		"set-pw" },
21556893Sfenner	{ 5,		"set-fields" },
21656893Sfenner	{ 6,		"create-user" },
21756893Sfenner	{ 7,		"delete-user" },
21856893Sfenner	{ 8,		"get-entry" },
21956893Sfenner	{ 9,		"list-entry" },
22056893Sfenner	{ 10,		"get-stats" },
22156893Sfenner	{ 11,		"debug" },
22256893Sfenner	{ 12,		"get-pw" },
22356893Sfenner	{ 13,		"get-random-key" },
22456893Sfenner	{ 14,		"unlock" },
22556893Sfenner	{ 15,		"lock-status" },
22656893Sfenner	{ 0,		NULL },
22756893Sfenner};
22856893Sfenner
22956893Sfennerstatic struct tok vol_req[] = {
23056893Sfenner	{ 100,		"create-volume" },
23156893Sfenner	{ 101,		"delete-volume" },
23256893Sfenner	{ 102,		"restore" },
23356893Sfenner	{ 103,		"forward" },
23456893Sfenner	{ 104,		"end-trans" },
23556893Sfenner	{ 105,		"clone" },
23656893Sfenner	{ 106,		"set-flags" },
23756893Sfenner	{ 107,		"get-flags" },
23856893Sfenner	{ 108,		"trans-create" },
23956893Sfenner	{ 109,		"dump" },
24056893Sfenner	{ 110,		"get-nth-volume" },
24156893Sfenner	{ 111,		"set-forwarding" },
24256893Sfenner	{ 112,		"get-name" },
24356893Sfenner	{ 113,		"get-status" },
24456893Sfenner	{ 114,		"sig-restore" },
24556893Sfenner	{ 115,		"list-partitions" },
24656893Sfenner	{ 116,		"list-volumes" },
24756893Sfenner	{ 117,		"set-id-types" },
24856893Sfenner	{ 118,		"monitor" },
24956893Sfenner	{ 119,		"partition-info" },
25056893Sfenner	{ 120,		"reclone" },
25156893Sfenner	{ 121,		"list-one-volume" },
25256893Sfenner	{ 122,		"nuke" },
25356893Sfenner	{ 123,		"set-date" },
25456893Sfenner	{ 124,		"x-list-volumes" },
25556893Sfenner	{ 125,		"x-list-one-volume" },
25656893Sfenner	{ 126,		"set-info" },
25756893Sfenner	{ 127,		"x-list-partitions" },
25856893Sfenner	{ 128,		"forward-multiple" },
25956893Sfenner	{ 0,		NULL },
26056893Sfenner};
26156893Sfenner
26256893Sfennerstatic struct tok bos_req[] = {
26356893Sfenner	{ 80,		"create-bnode" },
26456893Sfenner	{ 81,		"delete-bnode" },
26556893Sfenner	{ 82,		"set-status" },
26656893Sfenner	{ 83,		"get-status" },
26756893Sfenner	{ 84,		"enumerate-instance" },
26856893Sfenner	{ 85,		"get-instance-info" },
26956893Sfenner	{ 86,		"get-instance-parm" },
27056893Sfenner	{ 87,		"add-superuser" },
27156893Sfenner	{ 88,		"delete-superuser" },
27256893Sfenner	{ 89,		"list-superusers" },
27356893Sfenner	{ 90,		"list-keys" },
27456893Sfenner	{ 91,		"add-key" },
27556893Sfenner	{ 92,		"delete-key" },
27656893Sfenner	{ 93,		"set-cell-name" },
27756893Sfenner	{ 94,		"get-cell-name" },
27856893Sfenner	{ 95,		"get-cell-host" },
27956893Sfenner	{ 96,		"add-cell-host" },
28056893Sfenner	{ 97,		"delete-cell-host" },
28156893Sfenner	{ 98,		"set-t-status" },
28256893Sfenner	{ 99,		"shutdown-all" },
28356893Sfenner	{ 100,		"restart-all" },
28456893Sfenner	{ 101,		"startup-all" },
28556893Sfenner	{ 102,		"set-noauth-flag" },
28656893Sfenner	{ 103,		"re-bozo" },
28756893Sfenner	{ 104,		"restart" },
28856893Sfenner	{ 105,		"start-bozo-install" },
28956893Sfenner	{ 106,		"uninstall" },
29056893Sfenner	{ 107,		"get-dates" },
29156893Sfenner	{ 108,		"exec" },
29256893Sfenner	{ 109,		"prune" },
29356893Sfenner	{ 110,		"set-restart-time" },
29456893Sfenner	{ 111,		"get-restart-time" },
29556893Sfenner	{ 112,		"start-bozo-log" },
29656893Sfenner	{ 113,		"wait-all" },
29756893Sfenner	{ 114,		"get-instance-strings" },
29898524Sfenner	{ 115,		"get-restricted" },
29998524Sfenner	{ 116,		"set-restricted" },
30056893Sfenner	{ 0,		NULL },
30156893Sfenner};
30256893Sfenner
30356893Sfennerstatic struct tok ubik_req[] = {
30456893Sfenner	{ 10000,	"vote-beacon" },
30556893Sfenner	{ 10001,	"vote-debug-old" },
30656893Sfenner	{ 10002,	"vote-sdebug-old" },
30756893Sfenner	{ 10003,	"vote-getsyncsite" },
30856893Sfenner	{ 10004,	"vote-debug" },
30956893Sfenner	{ 10005,	"vote-sdebug" },
31056893Sfenner	{ 20000,	"disk-begin" },
31156893Sfenner	{ 20001,	"disk-commit" },
31256893Sfenner	{ 20002,	"disk-lock" },
31356893Sfenner	{ 20003,	"disk-write" },
31456893Sfenner	{ 20004,	"disk-getversion" },
31556893Sfenner	{ 20005,	"disk-getfile" },
31656893Sfenner	{ 20006,	"disk-sendfile" },
31756893Sfenner	{ 20007,	"disk-abort" },
31856893Sfenner	{ 20008,	"disk-releaselocks" },
31956893Sfenner	{ 20009,	"disk-truncate" },
32056893Sfenner	{ 20010,	"disk-probe" },
32156893Sfenner	{ 20011,	"disk-writev" },
32256893Sfenner	{ 20012,	"disk-interfaceaddr" },
32356893Sfenner	{ 20013,	"disk-setversion" },
32456893Sfenner	{ 0,		NULL },
32556893Sfenner};
32656893Sfenner
32756893Sfenner#define VOTE_LOW	10000
32856893Sfenner#define VOTE_HIGH	10005
32956893Sfenner#define DISK_LOW	20000
33056893Sfenner#define DISK_HIGH	20013
33156893Sfenner
33256893Sfennerstatic struct tok cb_types[] = {
33356893Sfenner	{ 1,		"exclusive" },
33456893Sfenner	{ 2,		"shared" },
33556893Sfenner	{ 3,		"dropped" },
33656893Sfenner	{ 0,		NULL },
33756893Sfenner};
33856893Sfenner
33956893Sfennerstatic struct tok ubik_lock_types[] = {
34056893Sfenner	{ 1,		"read" },
34156893Sfenner	{ 2,		"write" },
34256893Sfenner	{ 3,		"wait" },
34356893Sfenner	{ 0,		NULL },
34456893Sfenner};
34556893Sfenner
346127668Sbmsstatic const char *voltype[] = { "read-write", "read-only", "backup" };
34756893Sfenner
34875115Sfennerstatic struct tok afs_fs_errors[] = {
34975115Sfenner	{ 101,		"salvage volume" },
35075115Sfenner	{ 102, 		"no such vnode" },
35175115Sfenner	{ 103, 		"no such volume" },
35275115Sfenner	{ 104, 		"volume exist" },
35375115Sfenner	{ 105, 		"no service" },
35475115Sfenner	{ 106, 		"volume offline" },
35575115Sfenner	{ 107, 		"voline online" },
35675115Sfenner	{ 108, 		"diskfull" },
35775115Sfenner	{ 109, 		"diskquota exceeded" },
35875115Sfenner	{ 110, 		"volume busy" },
35975115Sfenner	{ 111, 		"volume moved" },
36075115Sfenner	{ 112, 		"AFS IO error" },
36175115Sfenner	{ -100,		"restarting fileserver" },
36275115Sfenner	{ 0,		NULL }
36375115Sfenner};
36475115Sfenner
36556893Sfenner/*
36675115Sfenner * Reasons for acknowledging a packet
36775115Sfenner */
36875115Sfenner
36975115Sfennerstatic struct tok rx_ack_reasons[] = {
37075115Sfenner	{ 1,		"ack requested" },
37175115Sfenner	{ 2,		"duplicate packet" },
37275115Sfenner	{ 3,		"out of sequence" },
37375115Sfenner	{ 4,		"exceeds window" },
37475115Sfenner	{ 5,		"no buffer space" },
37575115Sfenner	{ 6,		"ping" },
37675115Sfenner	{ 7,		"ping response" },
37775115Sfenner	{ 8,		"delay" },
378127668Sbms	{ 9,		"idle" },
37975115Sfenner	{ 0,		NULL },
38075115Sfenner};
38175115Sfenner
38275115Sfenner/*
38356893Sfenner * Cache entries we keep around so we can figure out the RX opcode
38456893Sfenner * numbers for replies.  This allows us to make sense of RX reply packets.
38556893Sfenner */
38656893Sfenner
38756893Sfennerstruct rx_cache_entry {
38856893Sfenner	u_int32_t	callnum;	/* Call number (net order) */
38956893Sfenner	struct in_addr	client;		/* client IP address (net order) */
39056893Sfenner	struct in_addr	server;		/* server IP address (net order) */
39156893Sfenner	int		dport;		/* server port (host order) */
39256893Sfenner	u_short		serviceId;	/* Service identifier (net order) */
39356893Sfenner	u_int32_t	opcode;		/* RX opcode (host order) */
39456893Sfenner};
39556893Sfenner
39656893Sfenner#define RX_CACHE_SIZE	64
39756893Sfenner
39856893Sfennerstatic struct rx_cache_entry	rx_cache[RX_CACHE_SIZE];
39956893Sfenner
40056893Sfennerstatic int	rx_cache_next = 0;
40156893Sfennerstatic int	rx_cache_hint = 0;
402127668Sbmsstatic void	rx_cache_insert(const u_char *, const struct ip *, int);
40356893Sfennerstatic int	rx_cache_find(const struct rx_header *, const struct ip *,
40456893Sfenner			      int, int32_t *);
40556893Sfenner
40656893Sfennerstatic void fs_print(const u_char *, int);
40756893Sfennerstatic void fs_reply_print(const u_char *, int, int32_t);
40875115Sfennerstatic void acl_print(u_char *, int, u_char *);
40956893Sfennerstatic void cb_print(const u_char *, int);
41056893Sfennerstatic void cb_reply_print(const u_char *, int, int32_t);
41156893Sfennerstatic void prot_print(const u_char *, int);
41256893Sfennerstatic void prot_reply_print(const u_char *, int, int32_t);
41356893Sfennerstatic void vldb_print(const u_char *, int);
41456893Sfennerstatic void vldb_reply_print(const u_char *, int, int32_t);
41556893Sfennerstatic void kauth_print(const u_char *, int);
41656893Sfennerstatic void kauth_reply_print(const u_char *, int, int32_t);
41756893Sfennerstatic void vol_print(const u_char *, int);
41856893Sfennerstatic void vol_reply_print(const u_char *, int, int32_t);
41956893Sfennerstatic void bos_print(const u_char *, int);
42056893Sfennerstatic void bos_reply_print(const u_char *, int, int32_t);
421127668Sbmsstatic void ubik_print(const u_char *);
42256893Sfennerstatic void ubik_reply_print(const u_char *, int, int32_t);
42356893Sfenner
42475115Sfennerstatic void rx_ack_print(const u_char *, int);
42575115Sfenner
42656893Sfennerstatic int is_ubik(u_int32_t);
42756893Sfenner
42856893Sfenner/*
42956893Sfenner * Handle the rx-level packet.  See if we know what port it's going to so
43056893Sfenner * we can peek at the afs call inside
43156893Sfenner */
43256893Sfenner
43356893Sfennervoid
43456893Sfennerrx_print(register const u_char *bp, int length, int sport, int dport,
43556893Sfenner	 u_char *bp2)
43656893Sfenner{
43756893Sfenner	register struct rx_header *rxh;
43856893Sfenner	int i;
43956893Sfenner	int32_t opcode;
44056893Sfenner
441127668Sbms	if (snapend - bp < (int)sizeof (struct rx_header)) {
44256893Sfenner		printf(" [|rx] (%d)", length);
44356893Sfenner		return;
44456893Sfenner	}
44556893Sfenner
44656893Sfenner	rxh = (struct rx_header *) bp;
44756893Sfenner
44856893Sfenner	printf(" rx %s", tok2str(rx_types, "type %d", rxh->type));
44956893Sfenner
45075115Sfenner	if (vflag) {
45156893Sfenner		int firstflag = 0;
45275115Sfenner
45375115Sfenner		if (vflag > 1)
45475115Sfenner			printf(" cid %08x call# %d",
45575115Sfenner			       (int) EXTRACT_32BITS(&rxh->cid),
45675115Sfenner			       (int) EXTRACT_32BITS(&rxh->callNumber));
45775115Sfenner
45875115Sfenner		printf(" seq %d ser %d",
45975115Sfenner		       (int) EXTRACT_32BITS(&rxh->seq),
46075115Sfenner		       (int) EXTRACT_32BITS(&rxh->serial));
46175115Sfenner
46256893Sfenner		if (vflag > 2)
46356893Sfenner			printf(" secindex %d serviceid %hu",
46456893Sfenner				(int) rxh->securityIndex,
46575115Sfenner				EXTRACT_16BITS(&rxh->serviceId));
46675115Sfenner
46775115Sfenner		if (vflag > 1)
46875115Sfenner			for (i = 0; i < NUM_RX_FLAGS; i++) {
46998524Sfenner				if (rxh->flags & rx_flags[i].flag &&
47098524Sfenner				    (!rx_flags[i].packetType ||
47198524Sfenner				     rxh->type == rx_flags[i].packetType)) {
47275115Sfenner					if (!firstflag) {
47375115Sfenner						firstflag = 1;
47475115Sfenner						printf(" ");
47575115Sfenner					} else {
47675115Sfenner						printf(",");
47775115Sfenner					}
47875115Sfenner					printf("<%s>", rx_flags[i].s);
47956893Sfenner				}
48056893Sfenner			}
48156893Sfenner	}
48256893Sfenner
48356893Sfenner	/*
48456893Sfenner	 * Try to handle AFS calls that we know about.  Check the destination
48556893Sfenner	 * port and make sure it's a data packet.  Also, make sure the
48656893Sfenner	 * seq number is 1 (because otherwise it's a continuation packet,
48756893Sfenner	 * and we can't interpret that).  Also, seems that reply packets
48856893Sfenner	 * do not have the client-init flag set, so we check for that
48956893Sfenner	 * as well.
49056893Sfenner	 */
49156893Sfenner
492127668Sbms	if (rxh->type == RX_PACKET_TYPE_DATA &&
49375115Sfenner	    EXTRACT_32BITS(&rxh->seq) == 1 &&
49456893Sfenner	    rxh->flags & RX_CLIENT_INITIATED) {
49556893Sfenner
49656893Sfenner		/*
49756893Sfenner		 * Insert this call into the call cache table, so we
49856893Sfenner		 * have a chance to print out replies
49956893Sfenner		 */
50056893Sfenner
501127668Sbms		rx_cache_insert(bp, (const struct ip *) bp2, dport);
50256893Sfenner
50356893Sfenner		switch (dport) {
50456893Sfenner			case FS_RX_PORT:	/* AFS file service */
50556893Sfenner				fs_print(bp, length);
50656893Sfenner				break;
50756893Sfenner			case CB_RX_PORT:	/* AFS callback service */
50856893Sfenner				cb_print(bp, length);
50956893Sfenner				break;
51056893Sfenner			case PROT_RX_PORT:	/* AFS protection service */
51156893Sfenner				prot_print(bp, length);
51256893Sfenner				break;
51356893Sfenner			case VLDB_RX_PORT:	/* AFS VLDB service */
51456893Sfenner				vldb_print(bp, length);
51556893Sfenner				break;
51656893Sfenner			case KAUTH_RX_PORT:	/* AFS Kerberos auth service */
51756893Sfenner				kauth_print(bp, length);
51856893Sfenner				break;
51956893Sfenner			case VOL_RX_PORT:	/* AFS Volume service */
52056893Sfenner				vol_print(bp, length);
52156893Sfenner				break;
52256893Sfenner			case BOS_RX_PORT:	/* AFS BOS service */
52356893Sfenner				bos_print(bp, length);
52456893Sfenner				break;
52556893Sfenner			default:
52656893Sfenner				;
52756893Sfenner		}
528127668Sbms
52956893Sfenner	/*
53056893Sfenner	 * If it's a reply (client-init is _not_ set, but seq is one)
53156893Sfenner	 * then look it up in the cache.  If we find it, call the reply
53256893Sfenner	 * printing functions  Note that we handle abort packets here,
53356893Sfenner	 * because printing out the return code can be useful at times.
53456893Sfenner	 */
53556893Sfenner
53656893Sfenner	} else if (((rxh->type == RX_PACKET_TYPE_DATA &&
53775115Sfenner					EXTRACT_32BITS(&rxh->seq) == 1) ||
53856893Sfenner		    rxh->type == RX_PACKET_TYPE_ABORT) &&
53956893Sfenner		   (rxh->flags & RX_CLIENT_INITIATED) == 0 &&
54056893Sfenner		   rx_cache_find(rxh, (const struct ip *) bp2,
54156893Sfenner				 sport, &opcode)) {
54256893Sfenner
54356893Sfenner		switch (sport) {
54456893Sfenner			case FS_RX_PORT:	/* AFS file service */
54556893Sfenner				fs_reply_print(bp, length, opcode);
54656893Sfenner				break;
54756893Sfenner			case CB_RX_PORT:	/* AFS callback service */
54856893Sfenner				cb_reply_print(bp, length, opcode);
54956893Sfenner				break;
55056893Sfenner			case PROT_RX_PORT:	/* AFS PT service */
55156893Sfenner				prot_reply_print(bp, length, opcode);
55256893Sfenner				break;
55356893Sfenner			case VLDB_RX_PORT:	/* AFS VLDB service */
55456893Sfenner				vldb_reply_print(bp, length, opcode);
55556893Sfenner				break;
55656893Sfenner			case KAUTH_RX_PORT:	/* AFS Kerberos auth service */
55756893Sfenner				kauth_reply_print(bp, length, opcode);
55856893Sfenner				break;
55956893Sfenner			case VOL_RX_PORT:	/* AFS Volume service */
56056893Sfenner				vol_reply_print(bp, length, opcode);
56156893Sfenner				break;
56256893Sfenner			case BOS_RX_PORT:	/* AFS BOS service */
56356893Sfenner				bos_reply_print(bp, length, opcode);
56456893Sfenner				break;
56556893Sfenner			default:
56656893Sfenner				;
56756893Sfenner		}
56856893Sfenner
56975115Sfenner	/*
57075115Sfenner	 * If it's an RX ack packet, then use the appropriate ack decoding
57175115Sfenner	 * function (there isn't any service-specific information in the
57275115Sfenner	 * ack packet, so we can use one for all AFS services)
57375115Sfenner	 */
57456893Sfenner
57575115Sfenner	} else if (rxh->type == RX_PACKET_TYPE_ACK)
57675115Sfenner		rx_ack_print(bp, length);
57775115Sfenner
57875115Sfenner
57956893Sfenner	printf(" (%d)", length);
58056893Sfenner}
58156893Sfenner
58256893Sfenner/*
58356893Sfenner * Insert an entry into the cache.  Taken from print-nfs.c
58456893Sfenner */
58556893Sfenner
58656893Sfennerstatic void
587127668Sbmsrx_cache_insert(const u_char *bp, const struct ip *ip, int dport)
58856893Sfenner{
58956893Sfenner	struct rx_cache_entry *rxent;
59056893Sfenner	const struct rx_header *rxh = (const struct rx_header *) bp;
59156893Sfenner
592127668Sbms	if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t)))
59356893Sfenner		return;
59456893Sfenner
59556893Sfenner	rxent = &rx_cache[rx_cache_next];
59656893Sfenner
59756893Sfenner	if (++rx_cache_next >= RX_CACHE_SIZE)
59856893Sfenner		rx_cache_next = 0;
599127668Sbms
60056893Sfenner	rxent->callnum = rxh->callNumber;
60156893Sfenner	rxent->client = ip->ip_src;
60256893Sfenner	rxent->server = ip->ip_dst;
60356893Sfenner	rxent->dport = dport;
60456893Sfenner	rxent->serviceId = rxh->serviceId;
60575115Sfenner	rxent->opcode = EXTRACT_32BITS(bp + sizeof(struct rx_header));
60656893Sfenner}
60756893Sfenner
60856893Sfenner/*
60956893Sfenner * Lookup an entry in the cache.  Also taken from print-nfs.c
61056893Sfenner *
61156893Sfenner * Note that because this is a reply, we're looking at the _source_
61256893Sfenner * port.
61356893Sfenner */
61456893Sfenner
61556893Sfennerstatic int
61656893Sfennerrx_cache_find(const struct rx_header *rxh, const struct ip *ip, int sport,
61756893Sfenner	      int32_t *opcode)
61856893Sfenner{
61956893Sfenner	int i;
62056893Sfenner	struct rx_cache_entry *rxent;
62156893Sfenner	u_int32_t clip = ip->ip_dst.s_addr;
62256893Sfenner	u_int32_t sip = ip->ip_src.s_addr;
62356893Sfenner
62456893Sfenner	/* Start the search where we last left off */
62556893Sfenner
62656893Sfenner	i = rx_cache_hint;
62756893Sfenner	do {
62856893Sfenner		rxent = &rx_cache[i];
62956893Sfenner		if (rxent->callnum == rxh->callNumber &&
63056893Sfenner		    rxent->client.s_addr == clip &&
631127668Sbms		    rxent->server.s_addr == sip &&
63256893Sfenner		    rxent->serviceId == rxh->serviceId &&
63356893Sfenner		    rxent->dport == sport) {
63456893Sfenner
63556893Sfenner			/* We got a match! */
63656893Sfenner
63756893Sfenner			rx_cache_hint = i;
63856893Sfenner			*opcode = rxent->opcode;
63956893Sfenner			return(1);
64056893Sfenner		}
64156893Sfenner		if (++i > RX_CACHE_SIZE)
64256893Sfenner			i = 0;
64356893Sfenner	} while (i != rx_cache_hint);
64456893Sfenner
64556893Sfenner	/* Our search failed */
64656893Sfenner	return(0);
64756893Sfenner}
64856893Sfenner
64956893Sfenner/*
65056893Sfenner * These extrememly grody macros handle the printing of various AFS stuff.
65156893Sfenner */
65256893Sfenner
65356893Sfenner#define FIDOUT() { unsigned long n1, n2, n3; \
65475115Sfenner			TCHECK2(bp[0], sizeof(int32_t) * 3); \
65575115Sfenner			n1 = EXTRACT_32BITS(bp); \
65656893Sfenner			bp += sizeof(int32_t); \
65775115Sfenner			n2 = EXTRACT_32BITS(bp); \
65856893Sfenner			bp += sizeof(int32_t); \
65975115Sfenner			n3 = EXTRACT_32BITS(bp); \
66056893Sfenner			bp += sizeof(int32_t); \
66156893Sfenner			printf(" fid %d/%d/%d", (int) n1, (int) n2, (int) n3); \
66256893Sfenner		}
66356893Sfenner
66480231Sfenner#define STROUT(MAX) { unsigned int i; \
66575115Sfenner			TCHECK2(bp[0], sizeof(int32_t)); \
66680231Sfenner			i = EXTRACT_32BITS(bp); \
66798524Sfenner			if (i > (MAX)) \
66880231Sfenner				goto trunc; \
66956893Sfenner			bp += sizeof(int32_t); \
67080231Sfenner			printf(" \""); \
67180231Sfenner			if (fn_printn(bp, i, snapend)) \
67280231Sfenner				goto trunc; \
67380231Sfenner			printf("\""); \
67456893Sfenner			bp += ((i + sizeof(int32_t) - 1) / sizeof(int32_t)) * sizeof(int32_t); \
67556893Sfenner		}
67656893Sfenner
67756893Sfenner#define INTOUT() { int i; \
67875115Sfenner			TCHECK2(bp[0], sizeof(int32_t)); \
67975115Sfenner			i = (int) EXTRACT_32BITS(bp); \
68056893Sfenner			bp += sizeof(int32_t); \
68156893Sfenner			printf(" %d", i); \
68256893Sfenner		}
68356893Sfenner
68456893Sfenner#define UINTOUT() { unsigned long i; \
68575115Sfenner			TCHECK2(bp[0], sizeof(int32_t)); \
68675115Sfenner			i = EXTRACT_32BITS(bp); \
68756893Sfenner			bp += sizeof(int32_t); \
68856893Sfenner			printf(" %lu", i); \
68956893Sfenner		}
69056893Sfenner
69156893Sfenner#define DATEOUT() { time_t t; struct tm *tm; char str[256]; \
69275115Sfenner			TCHECK2(bp[0], sizeof(int32_t)); \
69375115Sfenner			t = (time_t) EXTRACT_32BITS(bp); \
69456893Sfenner			bp += sizeof(int32_t); \
69556893Sfenner			tm = localtime(&t); \
69656893Sfenner			strftime(str, 256, "%Y/%m/%d %T", tm); \
69756893Sfenner			printf(" %s", str); \
69856893Sfenner		}
69956893Sfenner
70056893Sfenner#define STOREATTROUT() { unsigned long mask, i; \
70175115Sfenner			TCHECK2(bp[0], (sizeof(int32_t)*6)); \
70275115Sfenner			mask = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
70356893Sfenner			if (mask) printf (" StoreStatus"); \
704127668Sbms		        if (mask & 1) { printf(" date"); DATEOUT(); } \
70556893Sfenner			else bp += sizeof(int32_t); \
70675115Sfenner			i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
707127668Sbms		        if (mask & 2) printf(" owner %lu", i);  \
70875115Sfenner			i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
709127668Sbms		        if (mask & 4) printf(" group %lu", i); \
71075115Sfenner			i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
711127668Sbms		        if (mask & 8) printf(" mode %lo", i & 07777); \
71275115Sfenner			i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
713127668Sbms		        if (mask & 16) printf(" segsize %lu", i); \
71456893Sfenner			/* undocumented in 3.3 docu */ \
715127668Sbms		        if (mask & 1024) printf(" fsync");  \
71656893Sfenner		}
71756893Sfenner
71856893Sfenner#define UBIK_VERSIONOUT() {int32_t epoch; int32_t counter; \
71975115Sfenner			TCHECK2(bp[0], sizeof(int32_t) * 2); \
72075115Sfenner			epoch = EXTRACT_32BITS(bp); \
72156893Sfenner			bp += sizeof(int32_t); \
72275115Sfenner			counter = EXTRACT_32BITS(bp); \
72356893Sfenner			bp += sizeof(int32_t); \
72456893Sfenner			printf(" %d.%d", epoch, counter); \
72556893Sfenner		}
72656893Sfenner
72756893Sfenner#define AFSUUIDOUT() {u_int32_t temp; int i; \
72875115Sfenner			TCHECK2(bp[0], 11*sizeof(u_int32_t)); \
72975115Sfenner			temp = EXTRACT_32BITS(bp); \
73056893Sfenner			bp += sizeof(u_int32_t); \
73156893Sfenner			printf(" %08x", temp); \
73275115Sfenner			temp = EXTRACT_32BITS(bp); \
73356893Sfenner			bp += sizeof(u_int32_t); \
73456893Sfenner			printf("%04x", temp); \
73575115Sfenner			temp = EXTRACT_32BITS(bp); \
73656893Sfenner			bp += sizeof(u_int32_t); \
73756893Sfenner			printf("%04x", temp); \
73856893Sfenner			for (i = 0; i < 8; i++) { \
73975115Sfenner				temp = EXTRACT_32BITS(bp); \
74056893Sfenner				bp += sizeof(u_int32_t); \
74156893Sfenner				printf("%02x", (unsigned char) temp); \
74256893Sfenner			} \
74356893Sfenner		}
74456893Sfenner
74556893Sfenner/*
74656893Sfenner * This is the sickest one of all
74756893Sfenner */
74856893Sfenner
749111726Sfenner#define VECOUT(MAX) { u_char *sp; \
750111726Sfenner			u_char s[AFSNAMEMAX]; \
75156893Sfenner			int k; \
75298524Sfenner			if ((MAX) + 1 > sizeof(s)) \
75398524Sfenner				goto trunc; \
75498524Sfenner			TCHECK2(bp[0], (MAX) * sizeof(int32_t)); \
75556893Sfenner			sp = s; \
75698524Sfenner			for (k = 0; k < (MAX); k++) { \
757111726Sfenner				*sp++ = (u_char) EXTRACT_32BITS(bp); \
75856893Sfenner				bp += sizeof(int32_t); \
75956893Sfenner			} \
76098524Sfenner			s[(MAX)] = '\0'; \
76180231Sfenner			printf(" \""); \
76280231Sfenner			fn_print(s, NULL); \
76380231Sfenner			printf("\""); \
76456893Sfenner		}
76556893Sfenner
76656893Sfenner/*
76756893Sfenner * Handle calls to the AFS file service (fs)
76856893Sfenner */
76956893Sfenner
77075115Sfennerstatic void
77156893Sfennerfs_print(register const u_char *bp, int length)
77256893Sfenner{
77356893Sfenner	int fs_op;
77456893Sfenner	unsigned long i;
77556893Sfenner
776127668Sbms	if (length <= (int)sizeof(struct rx_header))
77756893Sfenner		return;
77856893Sfenner
779127668Sbms	if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
78056893Sfenner		goto trunc;
78156893Sfenner	}
78256893Sfenner
78356893Sfenner	/*
78456893Sfenner	 * Print out the afs call we're invoking.  The table used here was
78556893Sfenner	 * gleaned from fsint/afsint.xg
78656893Sfenner	 */
78756893Sfenner
78875115Sfenner	fs_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
78956893Sfenner
79056893Sfenner	printf(" fs call %s", tok2str(fs_req, "op#%d", fs_op));
79156893Sfenner
79256893Sfenner	/*
79356893Sfenner	 * Print out arguments to some of the AFS calls.  This stuff is
79456893Sfenner	 * all from afsint.xg
79556893Sfenner	 */
79656893Sfenner
79756893Sfenner	bp += sizeof(struct rx_header) + 4;
79856893Sfenner
79956893Sfenner	/*
80056893Sfenner	 * Sigh.  This is gross.  Ritchie forgive me.
80156893Sfenner	 */
80256893Sfenner
80356893Sfenner	switch (fs_op) {
80456893Sfenner		case 130:	/* Fetch data */
80556893Sfenner			FIDOUT();
80656893Sfenner			printf(" offset");
80756893Sfenner			UINTOUT();
80856893Sfenner			printf(" length");
80956893Sfenner			UINTOUT();
81056893Sfenner			break;
81156893Sfenner		case 131:	/* Fetch ACL */
81256893Sfenner		case 132:	/* Fetch Status */
81356893Sfenner		case 143:	/* Old set lock */
81456893Sfenner		case 144:	/* Old extend lock */
81556893Sfenner		case 145:	/* Old release lock */
81656893Sfenner		case 156:	/* Set lock */
81756893Sfenner		case 157:	/* Extend lock */
81856893Sfenner		case 158:	/* Release lock */
81956893Sfenner			FIDOUT();
82056893Sfenner			break;
82156893Sfenner		case 135:	/* Store status */
82256893Sfenner			FIDOUT();
82356893Sfenner			STOREATTROUT();
82456893Sfenner			break;
82556893Sfenner		case 133:	/* Store data */
82656893Sfenner			FIDOUT();
82756893Sfenner			STOREATTROUT();
82856893Sfenner			printf(" offset");
82956893Sfenner			UINTOUT();
83056893Sfenner			printf(" length");
83156893Sfenner			UINTOUT();
83256893Sfenner			printf(" flen");
83356893Sfenner			UINTOUT();
83456893Sfenner			break;
83556893Sfenner		case 134:	/* Store ACL */
83656893Sfenner		{
83775115Sfenner			char a[AFSOPAQUEMAX+1];
83856893Sfenner			FIDOUT();
83975115Sfenner			TCHECK2(bp[0], 4);
84075115Sfenner			i = EXTRACT_32BITS(bp);
84156893Sfenner			bp += sizeof(int32_t);
84275115Sfenner			TCHECK2(bp[0], i);
84375115Sfenner			i = min(AFSOPAQUEMAX, i);
84475115Sfenner			strncpy(a, (char *) bp, i);
84556893Sfenner			a[i] = '\0';
84675115Sfenner			acl_print((u_char *) a, sizeof(a), (u_char *) a + i);
84756893Sfenner			break;
84856893Sfenner		}
84956893Sfenner		case 137:	/* Create file */
85056893Sfenner		case 141:	/* MakeDir */
85156893Sfenner			FIDOUT();
85256893Sfenner			STROUT(AFSNAMEMAX);
85356893Sfenner			STOREATTROUT();
85456893Sfenner			break;
85556893Sfenner		case 136:	/* Remove file */
85656893Sfenner		case 142:	/* Remove directory */
85756893Sfenner			FIDOUT();
85856893Sfenner			STROUT(AFSNAMEMAX);
85956893Sfenner			break;
86056893Sfenner		case 138:	/* Rename file */
86156893Sfenner			printf(" old");
86256893Sfenner			FIDOUT();
86356893Sfenner			STROUT(AFSNAMEMAX);
86456893Sfenner			printf(" new");
86556893Sfenner			FIDOUT();
86656893Sfenner			STROUT(AFSNAMEMAX);
86756893Sfenner			break;
86856893Sfenner		case 139:	/* Symlink */
86956893Sfenner			FIDOUT();
87056893Sfenner			STROUT(AFSNAMEMAX);
87156893Sfenner			printf(" link to");
87256893Sfenner			STROUT(AFSNAMEMAX);
87356893Sfenner			break;
87456893Sfenner		case 140:	/* Link */
87556893Sfenner			FIDOUT();
87656893Sfenner			STROUT(AFSNAMEMAX);
87756893Sfenner			printf(" link to");
87856893Sfenner			FIDOUT();
87956893Sfenner			break;
88056893Sfenner		case 148:	/* Get volume info */
88156893Sfenner			STROUT(AFSNAMEMAX);
88256893Sfenner			break;
88356893Sfenner		case 149:	/* Get volume stats */
88456893Sfenner		case 150:	/* Set volume stats */
88556893Sfenner			printf(" volid");
88656893Sfenner			UINTOUT();
88756893Sfenner			break;
88856893Sfenner		case 154:	/* New get volume info */
88956893Sfenner			printf(" volname");
89056893Sfenner			STROUT(AFSNAMEMAX);
89156893Sfenner			break;
89256893Sfenner		case 155:	/* Bulk stat */
89356893Sfenner		{
89456893Sfenner			unsigned long j;
89575115Sfenner			TCHECK2(bp[0], 4);
89675115Sfenner			j = EXTRACT_32BITS(bp);
89756893Sfenner			bp += sizeof(int32_t);
89856893Sfenner
89956893Sfenner			for (i = 0; i < j; i++) {
90056893Sfenner				FIDOUT();
90156893Sfenner				if (i != j - 1)
90256893Sfenner					printf(",");
90356893Sfenner			}
90456893Sfenner			if (j == 0)
90556893Sfenner				printf(" <none!>");
90656893Sfenner		}
90756893Sfenner		default:
90856893Sfenner			;
90956893Sfenner	}
91056893Sfenner
91156893Sfenner	return;
91256893Sfenner
91356893Sfennertrunc:
91456893Sfenner	printf(" [|fs]");
91556893Sfenner}
91656893Sfenner
91756893Sfenner/*
91856893Sfenner * Handle replies to the AFS file service
91956893Sfenner */
92056893Sfenner
92156893Sfennerstatic void
92256893Sfennerfs_reply_print(register const u_char *bp, int length, int32_t opcode)
92356893Sfenner{
92456893Sfenner	unsigned long i;
92556893Sfenner	struct rx_header *rxh;
92656893Sfenner
927127668Sbms	if (length <= (int)sizeof(struct rx_header))
92856893Sfenner		return;
92956893Sfenner
93056893Sfenner	rxh = (struct rx_header *) bp;
93156893Sfenner
93256893Sfenner	/*
93356893Sfenner	 * Print out the afs call we're invoking.  The table used here was
93456893Sfenner	 * gleaned from fsint/afsint.xg
93556893Sfenner	 */
93656893Sfenner
93756893Sfenner	printf(" fs reply %s", tok2str(fs_req, "op#%d", opcode));
93856893Sfenner
93956893Sfenner	bp += sizeof(struct rx_header);
94056893Sfenner
94156893Sfenner	/*
94256893Sfenner	 * If it was a data packet, interpret the response
94356893Sfenner	 */
94456893Sfenner
94575115Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA) {
94656893Sfenner		switch (opcode) {
94756893Sfenner		case 131:	/* Fetch ACL */
94856893Sfenner		{
94975115Sfenner			char a[AFSOPAQUEMAX+1];
95075115Sfenner			TCHECK2(bp[0], 4);
95175115Sfenner			i = EXTRACT_32BITS(bp);
95256893Sfenner			bp += sizeof(int32_t);
95375115Sfenner			TCHECK2(bp[0], i);
95475115Sfenner			i = min(AFSOPAQUEMAX, i);
95575115Sfenner			strncpy(a, (char *) bp, i);
95656893Sfenner			a[i] = '\0';
95775115Sfenner			acl_print((u_char *) a, sizeof(a), (u_char *) a + i);
95856893Sfenner			break;
95956893Sfenner		}
96056893Sfenner		case 137:	/* Create file */
96156893Sfenner		case 141:	/* MakeDir */
96256893Sfenner			printf(" new");
96356893Sfenner			FIDOUT();
96456893Sfenner			break;
96556893Sfenner		case 151:	/* Get root volume */
96656893Sfenner			printf(" root volume");
96756893Sfenner			STROUT(AFSNAMEMAX);
96856893Sfenner			break;
96956893Sfenner		case 153:	/* Get time */
97056893Sfenner			DATEOUT();
97156893Sfenner			break;
97256893Sfenner		default:
97356893Sfenner			;
97456893Sfenner		}
97575115Sfenner	} else if (rxh->type == RX_PACKET_TYPE_ABORT) {
97675115Sfenner		int i;
97775115Sfenner
978127668Sbms		/*
979127668Sbms		 * Otherwise, just print out the return code
980127668Sbms		 */
981127668Sbms		TCHECK2(bp[0], sizeof(int32_t));
982127668Sbms		i = (int) EXTRACT_32BITS(bp);
983127668Sbms		bp += sizeof(int32_t);
98475115Sfenner
98575115Sfenner		printf(" error %s", tok2str(afs_fs_errors, "#%d", i));
98675115Sfenner	} else {
98775115Sfenner		printf(" strange fs reply of type %d", rxh->type);
98856893Sfenner	}
98956893Sfenner
99056893Sfenner	return;
99156893Sfenner
99256893Sfennertrunc:
99356893Sfenner	printf(" [|fs]");
99456893Sfenner}
99556893Sfenner
99656893Sfenner/*
99756893Sfenner * Print out an AFS ACL string.  An AFS ACL is a string that has the
99856893Sfenner * following format:
99956893Sfenner *
100056893Sfenner * <positive> <negative>
100156893Sfenner * <uid1> <aclbits1>
100256893Sfenner * ....
1003127668Sbms *
100456893Sfenner * "positive" and "negative" are integers which contain the number of
100556893Sfenner * positive and negative ACL's in the string.  The uid/aclbits pair are
100656893Sfenner * ASCII strings containing the UID/PTS record and and a ascii number
100756893Sfenner * representing a logical OR of all the ACL permission bits
100856893Sfenner */
100956893Sfenner
101056893Sfennerstatic void
101175115Sfenneracl_print(u_char *s, int maxsize, u_char *end)
101256893Sfenner{
101356893Sfenner	int pos, neg, acl;
101456893Sfenner	int n, i;
101575115Sfenner	char *user;
1016172683Smlaier	char fmt[1024];
101756893Sfenner
101875115Sfenner	if ((user = (char *)malloc(maxsize)) == NULL)
101975115Sfenner		return;
102075115Sfenner
102156893Sfenner	if (sscanf((char *) s, "%d %d\n%n", &pos, &neg, &n) != 2)
102275115Sfenner		goto finish;
1023127668Sbms
102456893Sfenner	s += n;
102556893Sfenner
102656893Sfenner	if (s > end)
102775115Sfenner		goto finish;
102856893Sfenner
102956893Sfenner	/*
103056893Sfenner	 * This wacky order preserves the order used by the "fs" command
103156893Sfenner	 */
103256893Sfenner
103356893Sfenner#define ACLOUT(acl) \
103456893Sfenner	if (acl & PRSFS_READ) \
103556893Sfenner		printf("r"); \
103656893Sfenner	if (acl & PRSFS_LOOKUP) \
103756893Sfenner		printf("l"); \
103856893Sfenner	if (acl & PRSFS_INSERT) \
103956893Sfenner		printf("i"); \
104056893Sfenner	if (acl & PRSFS_DELETE) \
104156893Sfenner		printf("d"); \
104256893Sfenner	if (acl & PRSFS_WRITE) \
104356893Sfenner		printf("w"); \
104456893Sfenner	if (acl & PRSFS_LOCK) \
104556893Sfenner		printf("k"); \
104656893Sfenner	if (acl & PRSFS_ADMINISTER) \
104756893Sfenner		printf("a");
104856893Sfenner
104956893Sfenner	for (i = 0; i < pos; i++) {
1050172683Smlaier		snprintf(fmt, sizeof(fmt), "%%%ds %%d\n%%n", maxsize - 1);
1051172683Smlaier		if (sscanf((char *) s, fmt, user, &acl, &n) != 2)
105275115Sfenner			goto finish;
105356893Sfenner		s += n;
105480231Sfenner		printf(" +{");
1055111726Sfenner		fn_print((u_char *)user, NULL);
105680231Sfenner		printf(" ");
105756893Sfenner		ACLOUT(acl);
105856893Sfenner		printf("}");
105956893Sfenner		if (s > end)
106075115Sfenner			goto finish;
106156893Sfenner	}
106256893Sfenner
106356893Sfenner	for (i = 0; i < neg; i++) {
1064172683Smlaier		snprintf(fmt, sizeof(fmt), "%%%ds %%d\n%%n", maxsize - 1);
1065172683Smlaier		if (sscanf((char *) s, fmt, user, &acl, &n) != 2)
106675115Sfenner			goto finish;
106756893Sfenner		s += n;
106880231Sfenner		printf(" -{");
1069111726Sfenner		fn_print((u_char *)user, NULL);
107080231Sfenner		printf(" ");
107156893Sfenner		ACLOUT(acl);
107256893Sfenner		printf("}");
107356893Sfenner		if (s > end)
107475115Sfenner			goto finish;
107556893Sfenner	}
107675115Sfenner
107775115Sfennerfinish:
107875115Sfenner	free(user);
107975115Sfenner	return;
108056893Sfenner}
108156893Sfenner
108256893Sfenner#undef ACLOUT
108356893Sfenner
108456893Sfenner/*
108556893Sfenner * Handle calls to the AFS callback service
108656893Sfenner */
108756893Sfenner
108856893Sfennerstatic void
108956893Sfennercb_print(register const u_char *bp, int length)
109056893Sfenner{
109156893Sfenner	int cb_op;
109256893Sfenner	unsigned long i;
109356893Sfenner
1094127668Sbms	if (length <= (int)sizeof(struct rx_header))
109556893Sfenner		return;
109656893Sfenner
1097127668Sbms	if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
109856893Sfenner		goto trunc;
109956893Sfenner	}
110056893Sfenner
110156893Sfenner	/*
110256893Sfenner	 * Print out the afs call we're invoking.  The table used here was
110356893Sfenner	 * gleaned from fsint/afscbint.xg
110456893Sfenner	 */
110556893Sfenner
110675115Sfenner	cb_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
110756893Sfenner
110856893Sfenner	printf(" cb call %s", tok2str(cb_req, "op#%d", cb_op));
110956893Sfenner
111056893Sfenner	bp += sizeof(struct rx_header) + 4;
111156893Sfenner
111256893Sfenner	/*
111356893Sfenner	 * Print out the afs call we're invoking.  The table used here was
111456893Sfenner	 * gleaned from fsint/afscbint.xg
111556893Sfenner	 */
111656893Sfenner
111756893Sfenner	switch (cb_op) {
111856893Sfenner		case 204:		/* Callback */
111956893Sfenner		{
112056893Sfenner			unsigned long j, t;
112175115Sfenner			TCHECK2(bp[0], 4);
112275115Sfenner			j = EXTRACT_32BITS(bp);
112356893Sfenner			bp += sizeof(int32_t);
112456893Sfenner
112556893Sfenner			for (i = 0; i < j; i++) {
112656893Sfenner				FIDOUT();
112756893Sfenner				if (i != j - 1)
112856893Sfenner					printf(",");
112956893Sfenner			}
113056893Sfenner
113156893Sfenner			if (j == 0)
113256893Sfenner				printf(" <none!>");
113356893Sfenner
113475115Sfenner			j = EXTRACT_32BITS(bp);
113556893Sfenner			bp += sizeof(int32_t);
113656893Sfenner
113756893Sfenner			if (j != 0)
113856893Sfenner				printf(";");
113956893Sfenner
114056893Sfenner			for (i = 0; i < j; i++) {
114156893Sfenner				printf(" ver");
114256893Sfenner				INTOUT();
114356893Sfenner				printf(" expires");
114456893Sfenner				DATEOUT();
114575115Sfenner				TCHECK2(bp[0], 4);
114675115Sfenner				t = EXTRACT_32BITS(bp);
114756893Sfenner				bp += sizeof(int32_t);
114856893Sfenner				tok2str(cb_types, "type %d", t);
114956893Sfenner			}
115056893Sfenner		}
115156893Sfenner		case 214: {
115256893Sfenner			printf(" afsuuid");
115356893Sfenner			AFSUUIDOUT();
115456893Sfenner			break;
115556893Sfenner		}
115656893Sfenner		default:
115756893Sfenner			;
115856893Sfenner	}
115956893Sfenner
116056893Sfenner	return;
116156893Sfenner
116256893Sfennertrunc:
116356893Sfenner	printf(" [|cb]");
116456893Sfenner}
116556893Sfenner
116656893Sfenner/*
116756893Sfenner * Handle replies to the AFS Callback Service
116856893Sfenner */
116956893Sfenner
117056893Sfennerstatic void
117156893Sfennercb_reply_print(register const u_char *bp, int length, int32_t opcode)
117256893Sfenner{
117356893Sfenner	struct rx_header *rxh;
117456893Sfenner
1175127668Sbms	if (length <= (int)sizeof(struct rx_header))
117656893Sfenner		return;
117756893Sfenner
117856893Sfenner	rxh = (struct rx_header *) bp;
117956893Sfenner
118056893Sfenner	/*
118156893Sfenner	 * Print out the afs call we're invoking.  The table used here was
118256893Sfenner	 * gleaned from fsint/afscbint.xg
118356893Sfenner	 */
1184127668Sbms
118556893Sfenner	printf(" cb reply %s", tok2str(cb_req, "op#%d", opcode));
118656893Sfenner
118756893Sfenner	bp += sizeof(struct rx_header);
118856893Sfenner
118956893Sfenner	/*
119056893Sfenner	 * If it was a data packet, interpret the response.
119156893Sfenner	 */
119256893Sfenner
119356893Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA)
119456893Sfenner		switch (opcode) {
119556893Sfenner		case 213:	/* InitCallBackState3 */
119656893Sfenner			AFSUUIDOUT();
119756893Sfenner			break;
119856893Sfenner		default:
119956893Sfenner		;
120056893Sfenner		}
120156893Sfenner	else {
120256893Sfenner		/*
120356893Sfenner		 * Otherwise, just print out the return code
120456893Sfenner		 */
120556893Sfenner		printf(" errcode");
120656893Sfenner		INTOUT();
120756893Sfenner	}
120856893Sfenner
120956893Sfenner	return;
121056893Sfenner
121156893Sfennertrunc:
121256893Sfenner	printf(" [|cb]");
121356893Sfenner}
121456893Sfenner
121556893Sfenner/*
121656893Sfenner * Handle calls to the AFS protection database server
121756893Sfenner */
121856893Sfenner
121956893Sfennerstatic void
122056893Sfennerprot_print(register const u_char *bp, int length)
122156893Sfenner{
122256893Sfenner	unsigned long i;
122356893Sfenner	int pt_op;
122456893Sfenner
1225127668Sbms	if (length <= (int)sizeof(struct rx_header))
122656893Sfenner		return;
122756893Sfenner
1228127668Sbms	if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
122956893Sfenner		goto trunc;
123056893Sfenner	}
123156893Sfenner
123256893Sfenner	/*
123356893Sfenner	 * Print out the afs call we're invoking.  The table used here was
123456893Sfenner	 * gleaned from ptserver/ptint.xg
123556893Sfenner	 */
123656893Sfenner
123775115Sfenner	pt_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
123856893Sfenner
123956893Sfenner	printf(" pt");
124056893Sfenner
124156893Sfenner	if (is_ubik(pt_op)) {
1242127668Sbms		ubik_print(bp);
124356893Sfenner		return;
124456893Sfenner	}
124556893Sfenner
124656893Sfenner	printf(" call %s", tok2str(pt_req, "op#%d", pt_op));
124756893Sfenner
124856893Sfenner	/*
124956893Sfenner	 * Decode some of the arguments to the PT calls
125056893Sfenner	 */
125156893Sfenner
125256893Sfenner	bp += sizeof(struct rx_header) + 4;
125356893Sfenner
125456893Sfenner	switch (pt_op) {
125556893Sfenner		case 500:	/* I New User */
125656893Sfenner			STROUT(PRNAMEMAX);
125756893Sfenner			printf(" id");
125856893Sfenner			INTOUT();
125956893Sfenner			printf(" oldid");
126056893Sfenner			INTOUT();
126156893Sfenner			break;
126256893Sfenner		case 501:	/* Where is it */
126356893Sfenner		case 506:	/* Delete */
126456893Sfenner		case 508:	/* Get CPS */
126556893Sfenner		case 512:	/* List entry */
126656893Sfenner		case 514:	/* List elements */
126756893Sfenner		case 517:	/* List owned */
126856893Sfenner		case 518:	/* Get CPS2 */
126956893Sfenner		case 519:	/* Get host CPS */
127056893Sfenner			printf(" id");
127156893Sfenner			INTOUT();
127256893Sfenner			break;
127356893Sfenner		case 502:	/* Dump entry */
127456893Sfenner			printf(" pos");
127556893Sfenner			INTOUT();
127656893Sfenner			break;
127756893Sfenner		case 503:	/* Add to group */
127856893Sfenner		case 507:	/* Remove from group */
127956893Sfenner		case 515:	/* Is a member of? */
128056893Sfenner			printf(" uid");
128156893Sfenner			INTOUT();
128256893Sfenner			printf(" gid");
128356893Sfenner			INTOUT();
128456893Sfenner			break;
128556893Sfenner		case 504:	/* Name to ID */
128656893Sfenner		{
128756893Sfenner			unsigned long j;
128875115Sfenner			TCHECK2(bp[0], 4);
128975115Sfenner			j = EXTRACT_32BITS(bp);
129056893Sfenner			bp += sizeof(int32_t);
129156893Sfenner
129256893Sfenner			/*
129356893Sfenner			 * Who designed this chicken-shit protocol?
129456893Sfenner			 *
129556893Sfenner			 * Each character is stored as a 32-bit
129656893Sfenner			 * integer!
129756893Sfenner			 */
129856893Sfenner
129956893Sfenner			for (i = 0; i < j; i++) {
130056893Sfenner				VECOUT(PRNAMEMAX);
130156893Sfenner			}
130256893Sfenner			if (j == 0)
130356893Sfenner				printf(" <none!>");
130456893Sfenner		}
130556893Sfenner			break;
130656893Sfenner		case 505:	/* Id to name */
130756893Sfenner		{
130856893Sfenner			unsigned long j;
130956893Sfenner			printf(" ids:");
131075115Sfenner			TCHECK2(bp[0], 4);
131175115Sfenner			i = EXTRACT_32BITS(bp);
131256893Sfenner			bp += sizeof(int32_t);
131356893Sfenner			for (j = 0; j < i; j++)
131456893Sfenner				INTOUT();
131556893Sfenner			if (j == 0)
131656893Sfenner				printf(" <none!>");
131756893Sfenner		}
131856893Sfenner			break;
131956893Sfenner		case 509:	/* New entry */
132056893Sfenner			STROUT(PRNAMEMAX);
132156893Sfenner			printf(" flag");
132256893Sfenner			INTOUT();
132356893Sfenner			printf(" oid");
132456893Sfenner			INTOUT();
132556893Sfenner			break;
132656893Sfenner		case 511:	/* Set max */
132756893Sfenner			printf(" id");
132856893Sfenner			INTOUT();
132956893Sfenner			printf(" gflag");
133056893Sfenner			INTOUT();
133156893Sfenner			break;
133256893Sfenner		case 513:	/* Change entry */
133356893Sfenner			printf(" id");
133456893Sfenner			INTOUT();
133556893Sfenner			STROUT(PRNAMEMAX);
133656893Sfenner			printf(" oldid");
133756893Sfenner			INTOUT();
133856893Sfenner			printf(" newid");
133956893Sfenner			INTOUT();
134056893Sfenner			break;
134156893Sfenner		case 520:	/* Update entry */
134256893Sfenner			printf(" id");
134356893Sfenner			INTOUT();
134456893Sfenner			STROUT(PRNAMEMAX);
134556893Sfenner			break;
134656893Sfenner		default:
134756893Sfenner			;
134856893Sfenner	}
134956893Sfenner
135056893Sfenner
135156893Sfenner	return;
135256893Sfenner
135356893Sfennertrunc:
135456893Sfenner	printf(" [|pt]");
135556893Sfenner}
135656893Sfenner
135756893Sfenner/*
135856893Sfenner * Handle replies to the AFS protection service
135956893Sfenner */
136056893Sfenner
136156893Sfennerstatic void
136256893Sfennerprot_reply_print(register const u_char *bp, int length, int32_t opcode)
136356893Sfenner{
136456893Sfenner	struct rx_header *rxh;
136556893Sfenner	unsigned long i;
136656893Sfenner
1367127668Sbms	if (length < (int)sizeof(struct rx_header))
136856893Sfenner		return;
136956893Sfenner
137056893Sfenner	rxh = (struct rx_header *) bp;
137156893Sfenner
137256893Sfenner	/*
137356893Sfenner	 * Print out the afs call we're invoking.  The table used here was
137456893Sfenner	 * gleaned from ptserver/ptint.xg.  Check to see if it's a
137556893Sfenner	 * Ubik call, however.
137656893Sfenner	 */
137756893Sfenner
137856893Sfenner	printf(" pt");
137956893Sfenner
138056893Sfenner	if (is_ubik(opcode)) {
138156893Sfenner		ubik_reply_print(bp, length, opcode);
138256893Sfenner		return;
138356893Sfenner	}
138456893Sfenner
138556893Sfenner	printf(" reply %s", tok2str(pt_req, "op#%d", opcode));
138656893Sfenner
138756893Sfenner	bp += sizeof(struct rx_header);
138856893Sfenner
138956893Sfenner	/*
139056893Sfenner	 * If it was a data packet, interpret the response
139156893Sfenner	 */
139256893Sfenner
139356893Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA)
139456893Sfenner		switch (opcode) {
139556893Sfenner		case 504:		/* Name to ID */
139656893Sfenner		{
139756893Sfenner			unsigned long j;
139856893Sfenner			printf(" ids:");
139975115Sfenner			TCHECK2(bp[0], 4);
140075115Sfenner			i = EXTRACT_32BITS(bp);
140156893Sfenner			bp += sizeof(int32_t);
140256893Sfenner			for (j = 0; j < i; j++)
140356893Sfenner				INTOUT();
140456893Sfenner			if (j == 0)
140556893Sfenner				printf(" <none!>");
140656893Sfenner		}
140756893Sfenner			break;
140856893Sfenner		case 505:		/* ID to name */
140956893Sfenner		{
141056893Sfenner			unsigned long j;
141175115Sfenner			TCHECK2(bp[0], 4);
141275115Sfenner			j = EXTRACT_32BITS(bp);
141356893Sfenner			bp += sizeof(int32_t);
141456893Sfenner
141556893Sfenner			/*
141656893Sfenner			 * Who designed this chicken-shit protocol?
141756893Sfenner			 *
141856893Sfenner			 * Each character is stored as a 32-bit
141956893Sfenner			 * integer!
142056893Sfenner			 */
142156893Sfenner
142256893Sfenner			for (i = 0; i < j; i++) {
142356893Sfenner				VECOUT(PRNAMEMAX);
142456893Sfenner			}
142556893Sfenner			if (j == 0)
142656893Sfenner				printf(" <none!>");
142756893Sfenner		}
142856893Sfenner			break;
142956893Sfenner		case 508:		/* Get CPS */
143056893Sfenner		case 514:		/* List elements */
143156893Sfenner		case 517:		/* List owned */
143256893Sfenner		case 518:		/* Get CPS2 */
143356893Sfenner		case 519:		/* Get host CPS */
143456893Sfenner		{
143556893Sfenner			unsigned long j;
143675115Sfenner			TCHECK2(bp[0], 4);
143775115Sfenner			j = EXTRACT_32BITS(bp);
143856893Sfenner			bp += sizeof(int32_t);
143956893Sfenner			for (i = 0; i < j; i++) {
144056893Sfenner				INTOUT();
144156893Sfenner			}
144256893Sfenner			if (j == 0)
144356893Sfenner				printf(" <none!>");
144456893Sfenner		}
144556893Sfenner			break;
144656893Sfenner		case 510:		/* List max */
144756893Sfenner			printf(" maxuid");
144856893Sfenner			INTOUT();
144956893Sfenner			printf(" maxgid");
145056893Sfenner			INTOUT();
145156893Sfenner			break;
145256893Sfenner		default:
145356893Sfenner			;
145456893Sfenner		}
145556893Sfenner	else {
145656893Sfenner		/*
145756893Sfenner		 * Otherwise, just print out the return code
145856893Sfenner		 */
145956893Sfenner		printf(" errcode");
146056893Sfenner		INTOUT();
146156893Sfenner	}
146256893Sfenner
146356893Sfenner	return;
146456893Sfenner
146556893Sfennertrunc:
146656893Sfenner	printf(" [|pt]");
146756893Sfenner}
146856893Sfenner
146956893Sfenner/*
147056893Sfenner * Handle calls to the AFS volume location database service
147156893Sfenner */
147256893Sfenner
147356893Sfennerstatic void
147456893Sfennervldb_print(register const u_char *bp, int length)
147556893Sfenner{
147656893Sfenner	int vldb_op;
147756893Sfenner	unsigned long i;
147856893Sfenner
1479127668Sbms	if (length <= (int)sizeof(struct rx_header))
148056893Sfenner		return;
148156893Sfenner
1482127668Sbms	if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
148356893Sfenner		goto trunc;
148456893Sfenner	}
148556893Sfenner
148656893Sfenner	/*
148756893Sfenner	 * Print out the afs call we're invoking.  The table used here was
148856893Sfenner	 * gleaned from vlserver/vldbint.xg
148956893Sfenner	 */
149056893Sfenner
149175115Sfenner	vldb_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
149256893Sfenner
149356893Sfenner	printf(" vldb");
149456893Sfenner
149556893Sfenner	if (is_ubik(vldb_op)) {
1496127668Sbms		ubik_print(bp);
149756893Sfenner		return;
149856893Sfenner	}
149956893Sfenner	printf(" call %s", tok2str(vldb_req, "op#%d", vldb_op));
150056893Sfenner
150156893Sfenner	/*
150256893Sfenner	 * Decode some of the arguments to the VLDB calls
150356893Sfenner	 */
150456893Sfenner
150556893Sfenner	bp += sizeof(struct rx_header) + 4;
150656893Sfenner
150756893Sfenner	switch (vldb_op) {
150856893Sfenner		case 501:	/* Create new volume */
150956893Sfenner		case 517:	/* Create entry N */
151056893Sfenner			VECOUT(VLNAMEMAX);
151156893Sfenner			break;
151256893Sfenner		case 502:	/* Delete entry */
151356893Sfenner		case 503:	/* Get entry by ID */
151456893Sfenner		case 507:	/* Update entry */
151556893Sfenner		case 508:	/* Set lock */
151656893Sfenner		case 509:	/* Release lock */
151756893Sfenner		case 518:	/* Get entry by ID N */
151856893Sfenner			printf(" volid");
151956893Sfenner			INTOUT();
152075115Sfenner			TCHECK2(bp[0], sizeof(int32_t));
152175115Sfenner			i = EXTRACT_32BITS(bp);
152256893Sfenner			bp += sizeof(int32_t);
152356893Sfenner			if (i <= 2)
152456893Sfenner				printf(" type %s", voltype[i]);
152556893Sfenner			break;
152656893Sfenner		case 504:	/* Get entry by name */
152756893Sfenner		case 519:	/* Get entry by name N */
152856893Sfenner		case 524:	/* Update entry by name */
152956893Sfenner		case 527:	/* Get entry by name U */
153056893Sfenner			STROUT(VLNAMEMAX);
153156893Sfenner			break;
153256893Sfenner		case 505:	/* Get new vol id */
153356893Sfenner			printf(" bump");
153456893Sfenner			INTOUT();
153556893Sfenner			break;
153656893Sfenner		case 506:	/* Replace entry */
153756893Sfenner		case 520:	/* Replace entry N */
153856893Sfenner			printf(" volid");
153956893Sfenner			INTOUT();
154075115Sfenner			TCHECK2(bp[0], sizeof(int32_t));
154175115Sfenner			i = EXTRACT_32BITS(bp);
154256893Sfenner			bp += sizeof(int32_t);
154356893Sfenner			if (i <= 2)
154456893Sfenner				printf(" type %s", voltype[i]);
154556893Sfenner			VECOUT(VLNAMEMAX);
154656893Sfenner			break;
154756893Sfenner		case 510:	/* List entry */
154856893Sfenner		case 521:	/* List entry N */
154956893Sfenner			printf(" index");
155056893Sfenner			INTOUT();
155156893Sfenner			break;
155256893Sfenner		default:
155356893Sfenner			;
155456893Sfenner	}
155556893Sfenner
155656893Sfenner	return;
155756893Sfenner
155856893Sfennertrunc:
155956893Sfenner	printf(" [|vldb]");
156056893Sfenner}
156156893Sfenner
156256893Sfenner/*
156356893Sfenner * Handle replies to the AFS volume location database service
156456893Sfenner */
156556893Sfenner
156656893Sfennerstatic void
156756893Sfennervldb_reply_print(register const u_char *bp, int length, int32_t opcode)
156856893Sfenner{
156956893Sfenner	struct rx_header *rxh;
157056893Sfenner	unsigned long i;
157156893Sfenner
1572127668Sbms	if (length < (int)sizeof(struct rx_header))
157356893Sfenner		return;
157456893Sfenner
157556893Sfenner	rxh = (struct rx_header *) bp;
157656893Sfenner
157756893Sfenner	/*
157856893Sfenner	 * Print out the afs call we're invoking.  The table used here was
157956893Sfenner	 * gleaned from vlserver/vldbint.xg.  Check to see if it's a
158056893Sfenner	 * Ubik call, however.
158156893Sfenner	 */
158256893Sfenner
158356893Sfenner	printf(" vldb");
158456893Sfenner
158556893Sfenner	if (is_ubik(opcode)) {
158656893Sfenner		ubik_reply_print(bp, length, opcode);
158756893Sfenner		return;
158856893Sfenner	}
158956893Sfenner
159056893Sfenner	printf(" reply %s", tok2str(vldb_req, "op#%d", opcode));
159156893Sfenner
159256893Sfenner	bp += sizeof(struct rx_header);
159356893Sfenner
159456893Sfenner	/*
159556893Sfenner	 * If it was a data packet, interpret the response
159656893Sfenner	 */
159756893Sfenner
159856893Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA)
159956893Sfenner		switch (opcode) {
160056893Sfenner		case 510:	/* List entry */
160156893Sfenner			printf(" count");
160256893Sfenner			INTOUT();
160356893Sfenner			printf(" nextindex");
160456893Sfenner			INTOUT();
160556893Sfenner		case 503:	/* Get entry by id */
160656893Sfenner		case 504:	/* Get entry by name */
160756893Sfenner		{	unsigned long nservers, j;
160856893Sfenner			VECOUT(VLNAMEMAX);
160975115Sfenner			TCHECK2(bp[0], sizeof(int32_t));
161056893Sfenner			bp += sizeof(int32_t);
161156893Sfenner			printf(" numservers");
161275115Sfenner			TCHECK2(bp[0], sizeof(int32_t));
161375115Sfenner			nservers = EXTRACT_32BITS(bp);
161456893Sfenner			bp += sizeof(int32_t);
161556893Sfenner			printf(" %lu", nservers);
161656893Sfenner			printf(" servers");
161756893Sfenner			for (i = 0; i < 8; i++) {
161875115Sfenner				TCHECK2(bp[0], sizeof(int32_t));
161956893Sfenner				if (i < nservers)
162056893Sfenner					printf(" %s",
1621127668Sbms					   intoa(((struct in_addr *) bp)->s_addr));
162256893Sfenner				bp += sizeof(int32_t);
162356893Sfenner			}
162456893Sfenner			printf(" partitions");
162556893Sfenner			for (i = 0; i < 8; i++) {
162675115Sfenner				TCHECK2(bp[0], sizeof(int32_t));
162775115Sfenner				j = EXTRACT_32BITS(bp);
162856893Sfenner				if (i < nservers && j <= 26)
162956893Sfenner					printf(" %c", 'a' + (int)j);
163056893Sfenner				else if (i < nservers)
163156893Sfenner					printf(" %lu", j);
163256893Sfenner				bp += sizeof(int32_t);
163356893Sfenner			}
163475115Sfenner			TCHECK2(bp[0], 8 * sizeof(int32_t));
163556893Sfenner			bp += 8 * sizeof(int32_t);
163656893Sfenner			printf(" rwvol");
163756893Sfenner			UINTOUT();
163856893Sfenner			printf(" rovol");
163956893Sfenner			UINTOUT();
164056893Sfenner			printf(" backup");
164156893Sfenner			UINTOUT();
164256893Sfenner		}
164356893Sfenner			break;
164456893Sfenner		case 505:	/* Get new volume ID */
164556893Sfenner			printf(" newvol");
164656893Sfenner			UINTOUT();
164756893Sfenner			break;
164856893Sfenner		case 521:	/* List entry */
164956893Sfenner		case 529:	/* List entry U */
165056893Sfenner			printf(" count");
165156893Sfenner			INTOUT();
165256893Sfenner			printf(" nextindex");
165356893Sfenner			INTOUT();
165456893Sfenner		case 518:	/* Get entry by ID N */
165556893Sfenner		case 519:	/* Get entry by name N */
165656893Sfenner		{	unsigned long nservers, j;
165756893Sfenner			VECOUT(VLNAMEMAX);
165856893Sfenner			printf(" numservers");
165975115Sfenner			TCHECK2(bp[0], sizeof(int32_t));
166075115Sfenner			nservers = EXTRACT_32BITS(bp);
166156893Sfenner			bp += sizeof(int32_t);
166256893Sfenner			printf(" %lu", nservers);
166356893Sfenner			printf(" servers");
166456893Sfenner			for (i = 0; i < 13; i++) {
166575115Sfenner				TCHECK2(bp[0], sizeof(int32_t));
166656893Sfenner				if (i < nservers)
166756893Sfenner					printf(" %s",
1668127668Sbms					   intoa(((struct in_addr *) bp)->s_addr));
166956893Sfenner				bp += sizeof(int32_t);
167056893Sfenner			}
167156893Sfenner			printf(" partitions");
167256893Sfenner			for (i = 0; i < 13; i++) {
167375115Sfenner				TCHECK2(bp[0], sizeof(int32_t));
167475115Sfenner				j = EXTRACT_32BITS(bp);
167556893Sfenner				if (i < nservers && j <= 26)
167656893Sfenner					printf(" %c", 'a' + (int)j);
167756893Sfenner				else if (i < nservers)
167856893Sfenner					printf(" %lu", j);
167956893Sfenner				bp += sizeof(int32_t);
168056893Sfenner			}
168175115Sfenner			TCHECK2(bp[0], 13 * sizeof(int32_t));
168256893Sfenner			bp += 13 * sizeof(int32_t);
168356893Sfenner			printf(" rwvol");
168456893Sfenner			UINTOUT();
168556893Sfenner			printf(" rovol");
168656893Sfenner			UINTOUT();
168756893Sfenner			printf(" backup");
168856893Sfenner			UINTOUT();
168956893Sfenner		}
169056893Sfenner			break;
169156893Sfenner		case 526:	/* Get entry by ID U */
169256893Sfenner		case 527:	/* Get entry by name U */
169356893Sfenner		{	unsigned long nservers, j;
169456893Sfenner			VECOUT(VLNAMEMAX);
169556893Sfenner			printf(" numservers");
169675115Sfenner			TCHECK2(bp[0], sizeof(int32_t));
169775115Sfenner			nservers = EXTRACT_32BITS(bp);
169856893Sfenner			bp += sizeof(int32_t);
169956893Sfenner			printf(" %lu", nservers);
170056893Sfenner			printf(" servers");
170156893Sfenner			for (i = 0; i < 13; i++) {
170256893Sfenner				if (i < nservers) {
170356893Sfenner					printf(" afsuuid");
170456893Sfenner					AFSUUIDOUT();
170556893Sfenner				} else {
170675115Sfenner					TCHECK2(bp[0], 44);
170756893Sfenner					bp += 44;
170856893Sfenner				}
170956893Sfenner			}
171075115Sfenner			TCHECK2(bp[0], 4 * 13);
171156893Sfenner			bp += 4 * 13;
171256893Sfenner			printf(" partitions");
171356893Sfenner			for (i = 0; i < 13; i++) {
171475115Sfenner				TCHECK2(bp[0], sizeof(int32_t));
171575115Sfenner				j = EXTRACT_32BITS(bp);
171656893Sfenner				if (i < nservers && j <= 26)
171756893Sfenner					printf(" %c", 'a' + (int)j);
171856893Sfenner				else if (i < nservers)
171956893Sfenner					printf(" %lu", j);
172056893Sfenner				bp += sizeof(int32_t);
172156893Sfenner			}
172275115Sfenner			TCHECK2(bp[0], 13 * sizeof(int32_t));
172356893Sfenner			bp += 13 * sizeof(int32_t);
172456893Sfenner			printf(" rwvol");
172556893Sfenner			UINTOUT();
172656893Sfenner			printf(" rovol");
172756893Sfenner			UINTOUT();
172856893Sfenner			printf(" backup");
172956893Sfenner			UINTOUT();
173056893Sfenner		}
173156893Sfenner		default:
173256893Sfenner			;
173356893Sfenner		}
1734127668Sbms
173556893Sfenner	else {
173656893Sfenner		/*
173756893Sfenner		 * Otherwise, just print out the return code
173856893Sfenner		 */
173956893Sfenner		printf(" errcode");
174056893Sfenner		INTOUT();
174156893Sfenner	}
174256893Sfenner
174356893Sfenner	return;
174456893Sfenner
174556893Sfennertrunc:
174656893Sfenner	printf(" [|vldb]");
174756893Sfenner}
174856893Sfenner
174956893Sfenner/*
175056893Sfenner * Handle calls to the AFS Kerberos Authentication service
175156893Sfenner */
175256893Sfenner
175356893Sfennerstatic void
175456893Sfennerkauth_print(register const u_char *bp, int length)
175556893Sfenner{
175656893Sfenner	int kauth_op;
175756893Sfenner
1758127668Sbms	if (length <= (int)sizeof(struct rx_header))
175956893Sfenner		return;
176056893Sfenner
1761127668Sbms	if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
176256893Sfenner		goto trunc;
176356893Sfenner	}
176456893Sfenner
176556893Sfenner	/*
176656893Sfenner	 * Print out the afs call we're invoking.  The table used here was
176756893Sfenner	 * gleaned from kauth/kauth.rg
176856893Sfenner	 */
176956893Sfenner
177075115Sfenner	kauth_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
177156893Sfenner
177256893Sfenner	printf(" kauth");
177356893Sfenner
177456893Sfenner	if (is_ubik(kauth_op)) {
1775127668Sbms		ubik_print(bp);
177656893Sfenner		return;
177756893Sfenner	}
177856893Sfenner
177956893Sfenner
178056893Sfenner	printf(" call %s", tok2str(kauth_req, "op#%d", kauth_op));
178156893Sfenner
178256893Sfenner	/*
178356893Sfenner	 * Decode some of the arguments to the KA calls
178456893Sfenner	 */
178556893Sfenner
178656893Sfenner	bp += sizeof(struct rx_header) + 4;
178756893Sfenner
178856893Sfenner	switch (kauth_op) {
178956893Sfenner		case 1:		/* Authenticate old */;
179056893Sfenner		case 21:	/* Authenticate */
179156893Sfenner		case 22:	/* Authenticate-V2 */
179256893Sfenner		case 2:		/* Change PW */
179356893Sfenner		case 5:		/* Set fields */
179456893Sfenner		case 6:		/* Create user */
179556893Sfenner		case 7:		/* Delete user */
179656893Sfenner		case 8:		/* Get entry */
179756893Sfenner		case 14:	/* Unlock */
179856893Sfenner		case 15:	/* Lock status */
179956893Sfenner			printf(" principal");
180056893Sfenner			STROUT(KANAMEMAX);
180156893Sfenner			STROUT(KANAMEMAX);
180256893Sfenner			break;
180356893Sfenner		case 3:		/* GetTicket-old */
180456893Sfenner		case 23:	/* GetTicket */
180556893Sfenner		{
180656893Sfenner			int i;
180756893Sfenner			printf(" kvno");
180856893Sfenner			INTOUT();
180956893Sfenner			printf(" domain");
181056893Sfenner			STROUT(KANAMEMAX);
181175115Sfenner			TCHECK2(bp[0], sizeof(int32_t));
181275115Sfenner			i = (int) EXTRACT_32BITS(bp);
181356893Sfenner			bp += sizeof(int32_t);
181475115Sfenner			TCHECK2(bp[0], i);
181556893Sfenner			bp += i;
181656893Sfenner			printf(" principal");
181756893Sfenner			STROUT(KANAMEMAX);
181856893Sfenner			STROUT(KANAMEMAX);
181956893Sfenner			break;
182056893Sfenner		}
182156893Sfenner		case 4:		/* Set Password */
182256893Sfenner			printf(" principal");
182356893Sfenner			STROUT(KANAMEMAX);
182456893Sfenner			STROUT(KANAMEMAX);
182556893Sfenner			printf(" kvno");
182656893Sfenner			INTOUT();
182756893Sfenner			break;
182856893Sfenner		case 12:	/* Get password */
182956893Sfenner			printf(" name");
183056893Sfenner			STROUT(KANAMEMAX);
183156893Sfenner			break;
183256893Sfenner		default:
183356893Sfenner			;
183456893Sfenner	}
183556893Sfenner
183656893Sfenner	return;
183756893Sfenner
183856893Sfennertrunc:
183956893Sfenner	printf(" [|kauth]");
184056893Sfenner}
184156893Sfenner
184256893Sfenner/*
184356893Sfenner * Handle replies to the AFS Kerberos Authentication Service
184456893Sfenner */
184556893Sfenner
184656893Sfennerstatic void
184756893Sfennerkauth_reply_print(register const u_char *bp, int length, int32_t opcode)
184856893Sfenner{
184956893Sfenner	struct rx_header *rxh;
185056893Sfenner
1851127668Sbms	if (length <= (int)sizeof(struct rx_header))
185256893Sfenner		return;
185356893Sfenner
185456893Sfenner	rxh = (struct rx_header *) bp;
185556893Sfenner
185656893Sfenner	/*
185756893Sfenner	 * Print out the afs call we're invoking.  The table used here was
185856893Sfenner	 * gleaned from kauth/kauth.rg
185956893Sfenner	 */
1860127668Sbms
186156893Sfenner	printf(" kauth");
186256893Sfenner
186356893Sfenner	if (is_ubik(opcode)) {
186456893Sfenner		ubik_reply_print(bp, length, opcode);
186556893Sfenner		return;
186656893Sfenner	}
186756893Sfenner
186856893Sfenner	printf(" reply %s", tok2str(kauth_req, "op#%d", opcode));
186956893Sfenner
187056893Sfenner	bp += sizeof(struct rx_header);
187156893Sfenner
187256893Sfenner	/*
187356893Sfenner	 * If it was a data packet, interpret the response.
187456893Sfenner	 */
187556893Sfenner
187656893Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA)
187756893Sfenner		/* Well, no, not really.  Leave this for later */
187856893Sfenner		;
187956893Sfenner	else {
188056893Sfenner		/*
188156893Sfenner		 * Otherwise, just print out the return code
188256893Sfenner		 */
188356893Sfenner		printf(" errcode");
188456893Sfenner		INTOUT();
188556893Sfenner	}
188656893Sfenner
188756893Sfenner	return;
188856893Sfenner
188956893Sfennertrunc:
189056893Sfenner	printf(" [|kauth]");
189156893Sfenner}
189256893Sfenner
189356893Sfenner/*
189456893Sfenner * Handle calls to the AFS Volume location service
189556893Sfenner */
189656893Sfenner
189756893Sfennerstatic void
189856893Sfennervol_print(register const u_char *bp, int length)
189956893Sfenner{
190056893Sfenner	int vol_op;
190156893Sfenner
1902127668Sbms	if (length <= (int)sizeof(struct rx_header))
190356893Sfenner		return;
190456893Sfenner
1905127668Sbms	if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
190656893Sfenner		goto trunc;
190756893Sfenner	}
190856893Sfenner
190956893Sfenner	/*
191056893Sfenner	 * Print out the afs call we're invoking.  The table used here was
191156893Sfenner	 * gleaned from volser/volint.xg
191256893Sfenner	 */
191356893Sfenner
191475115Sfenner	vol_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
191556893Sfenner
191656893Sfenner	printf(" vol call %s", tok2str(vol_req, "op#%d", vol_op));
191756893Sfenner
191856893Sfenner	/*
191956893Sfenner	 * Normally there would be a switch statement here to decode the
192056893Sfenner	 * arguments to the AFS call, but since I don't have access to
192156893Sfenner	 * an AFS server (yet) and I'm not an AFS admin, I can't
192256893Sfenner	 * test any of these calls.  Leave this blank for now.
192356893Sfenner	 */
192456893Sfenner
192556893Sfenner	return;
192656893Sfenner
192756893Sfennertrunc:
192856893Sfenner	printf(" [|vol]");
192956893Sfenner}
193056893Sfenner
193156893Sfenner/*
193256893Sfenner * Handle replies to the AFS Volume Service
193356893Sfenner */
193456893Sfenner
193556893Sfennerstatic void
193656893Sfennervol_reply_print(register const u_char *bp, int length, int32_t opcode)
193756893Sfenner{
193856893Sfenner	struct rx_header *rxh;
193956893Sfenner
1940127668Sbms	if (length <= (int)sizeof(struct rx_header))
194156893Sfenner		return;
194256893Sfenner
194356893Sfenner	rxh = (struct rx_header *) bp;
194456893Sfenner
194556893Sfenner	/*
194656893Sfenner	 * Print out the afs call we're invoking.  The table used here was
194756893Sfenner	 * gleaned from volser/volint.xg
194856893Sfenner	 */
1949127668Sbms
195056893Sfenner	printf(" vol reply %s", tok2str(vol_req, "op#%d", opcode));
195156893Sfenner
195256893Sfenner	bp += sizeof(struct rx_header);
195356893Sfenner
195456893Sfenner	/*
195556893Sfenner	 * If it was a data packet, interpret the response.
195656893Sfenner	 */
195756893Sfenner
195856893Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA)
195956893Sfenner		/* Well, no, not really.  Leave this for later */
196056893Sfenner		;
196156893Sfenner	else {
196256893Sfenner		/*
196356893Sfenner		 * Otherwise, just print out the return code
196456893Sfenner		 */
196556893Sfenner		printf(" errcode");
196656893Sfenner		INTOUT();
196756893Sfenner	}
196856893Sfenner
196956893Sfenner	return;
197056893Sfenner
197156893Sfennertrunc:
197256893Sfenner	printf(" [|vol]");
197356893Sfenner}
197456893Sfenner
197556893Sfenner/*
197656893Sfenner * Handle calls to the AFS BOS service
197756893Sfenner */
197856893Sfenner
197956893Sfennerstatic void
198056893Sfennerbos_print(register const u_char *bp, int length)
198156893Sfenner{
198256893Sfenner	int bos_op;
198356893Sfenner
1984127668Sbms	if (length <= (int)sizeof(struct rx_header))
198556893Sfenner		return;
198656893Sfenner
1987127668Sbms	if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
198856893Sfenner		goto trunc;
198956893Sfenner	}
199056893Sfenner
199156893Sfenner	/*
199256893Sfenner	 * Print out the afs call we're invoking.  The table used here was
199356893Sfenner	 * gleaned from bozo/bosint.xg
199456893Sfenner	 */
199556893Sfenner
199675115Sfenner	bos_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
199756893Sfenner
199856893Sfenner	printf(" bos call %s", tok2str(bos_req, "op#%d", bos_op));
199956893Sfenner
200056893Sfenner	/*
200156893Sfenner	 * Decode some of the arguments to the BOS calls
200256893Sfenner	 */
200356893Sfenner
200456893Sfenner	bp += sizeof(struct rx_header) + 4;
200556893Sfenner
200656893Sfenner	switch (bos_op) {
200756893Sfenner		case 80:	/* Create B node */
200856893Sfenner			printf(" type");
200956893Sfenner			STROUT(BOSNAMEMAX);
201056893Sfenner			printf(" instance");
201156893Sfenner			STROUT(BOSNAMEMAX);
201256893Sfenner			break;
201356893Sfenner		case 81:	/* Delete B node */
201456893Sfenner		case 83:	/* Get status */
201556893Sfenner		case 85:	/* Get instance info */
201656893Sfenner		case 87:	/* Add super user */
201756893Sfenner		case 88:	/* Delete super user */
201856893Sfenner		case 93:	/* Set cell name */
201956893Sfenner		case 96:	/* Add cell host */
202056893Sfenner		case 97:	/* Delete cell host */
202156893Sfenner		case 104:	/* Restart */
202256893Sfenner		case 106:	/* Uninstall */
202356893Sfenner		case 108:	/* Exec */
202456893Sfenner		case 112:	/* Getlog */
202556893Sfenner		case 114:	/* Get instance strings */
202656893Sfenner			STROUT(BOSNAMEMAX);
202756893Sfenner			break;
202856893Sfenner		case 82:	/* Set status */
202956893Sfenner		case 98:	/* Set T status */
203056893Sfenner			STROUT(BOSNAMEMAX);
203156893Sfenner			printf(" status");
203256893Sfenner			INTOUT();
203356893Sfenner			break;
203456893Sfenner		case 86:	/* Get instance parm */
203556893Sfenner			STROUT(BOSNAMEMAX);
203656893Sfenner			printf(" num");
203756893Sfenner			INTOUT();
203856893Sfenner			break;
203956893Sfenner		case 84:	/* Enumerate instance */
204056893Sfenner		case 89:	/* List super users */
204156893Sfenner		case 90:	/* List keys */
204256893Sfenner		case 91:	/* Add key */
204356893Sfenner		case 92:	/* Delete key */
204456893Sfenner		case 95:	/* Get cell host */
204556893Sfenner			INTOUT();
204656893Sfenner			break;
204756893Sfenner		case 105:	/* Install */
204856893Sfenner			STROUT(BOSNAMEMAX);
204956893Sfenner			printf(" size");
205056893Sfenner			INTOUT();
205156893Sfenner			printf(" flags");
205256893Sfenner			INTOUT();
205356893Sfenner			printf(" date");
205456893Sfenner			INTOUT();
205556893Sfenner			break;
205656893Sfenner		default:
205756893Sfenner			;
205856893Sfenner	}
205956893Sfenner
206056893Sfenner	return;
206156893Sfenner
206256893Sfennertrunc:
206356893Sfenner	printf(" [|bos]");
206456893Sfenner}
206556893Sfenner
206656893Sfenner/*
206756893Sfenner * Handle replies to the AFS BOS Service
206856893Sfenner */
206956893Sfenner
207056893Sfennerstatic void
207156893Sfennerbos_reply_print(register const u_char *bp, int length, int32_t opcode)
207256893Sfenner{
207356893Sfenner	struct rx_header *rxh;
207456893Sfenner
2075127668Sbms	if (length <= (int)sizeof(struct rx_header))
207656893Sfenner		return;
207756893Sfenner
207856893Sfenner	rxh = (struct rx_header *) bp;
207956893Sfenner
208056893Sfenner	/*
208156893Sfenner	 * Print out the afs call we're invoking.  The table used here was
208256893Sfenner	 * gleaned from volser/volint.xg
208356893Sfenner	 */
2084127668Sbms
208556893Sfenner	printf(" bos reply %s", tok2str(bos_req, "op#%d", opcode));
208656893Sfenner
208756893Sfenner	bp += sizeof(struct rx_header);
208856893Sfenner
208956893Sfenner	/*
209056893Sfenner	 * If it was a data packet, interpret the response.
209156893Sfenner	 */
209256893Sfenner
209356893Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA)
209456893Sfenner		/* Well, no, not really.  Leave this for later */
209556893Sfenner		;
209656893Sfenner	else {
209756893Sfenner		/*
209856893Sfenner		 * Otherwise, just print out the return code
209956893Sfenner		 */
210056893Sfenner		printf(" errcode");
210156893Sfenner		INTOUT();
210256893Sfenner	}
210356893Sfenner
210456893Sfenner	return;
210556893Sfenner
210656893Sfennertrunc:
210756893Sfenner	printf(" [|bos]");
210856893Sfenner}
210956893Sfenner
211056893Sfenner/*
211156893Sfenner * Check to see if this is a Ubik opcode.
211256893Sfenner */
211356893Sfenner
211456893Sfennerstatic int
211556893Sfenneris_ubik(u_int32_t opcode)
211656893Sfenner{
211756893Sfenner	if ((opcode >= VOTE_LOW && opcode <= VOTE_HIGH) ||
211856893Sfenner	    (opcode >= DISK_LOW && opcode <= DISK_HIGH))
211956893Sfenner		return(1);
212056893Sfenner	else
212156893Sfenner		return(0);
212256893Sfenner}
212356893Sfenner
212456893Sfenner/*
212556893Sfenner * Handle Ubik opcodes to any one of the replicated database services
212656893Sfenner */
212756893Sfenner
212856893Sfennerstatic void
2129127668Sbmsubik_print(register const u_char *bp)
213056893Sfenner{
213156893Sfenner	int ubik_op;
213256893Sfenner	int32_t temp;
213356893Sfenner
213456893Sfenner	/*
213556893Sfenner	 * Print out the afs call we're invoking.  The table used here was
213656893Sfenner	 * gleaned from ubik/ubik_int.xg
213756893Sfenner	 */
213856893Sfenner
213975115Sfenner	ubik_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
214056893Sfenner
214156893Sfenner	printf(" ubik call %s", tok2str(ubik_req, "op#%d", ubik_op));
214256893Sfenner
214356893Sfenner	/*
214456893Sfenner	 * Decode some of the arguments to the Ubik calls
214556893Sfenner	 */
214656893Sfenner
214756893Sfenner	bp += sizeof(struct rx_header) + 4;
214856893Sfenner
214956893Sfenner	switch (ubik_op) {
215056893Sfenner		case 10000:		/* Beacon */
215175115Sfenner			TCHECK2(bp[0], 4);
215275115Sfenner			temp = EXTRACT_32BITS(bp);
215356893Sfenner			bp += sizeof(int32_t);
215456893Sfenner			printf(" syncsite %s", temp ? "yes" : "no");
215556893Sfenner			printf(" votestart");
215656893Sfenner			DATEOUT();
215756893Sfenner			printf(" dbversion");
215856893Sfenner			UBIK_VERSIONOUT();
215956893Sfenner			printf(" tid");
216056893Sfenner			UBIK_VERSIONOUT();
216156893Sfenner			break;
216256893Sfenner		case 10003:		/* Get sync site */
216356893Sfenner			printf(" site");
216456893Sfenner			UINTOUT();
216556893Sfenner			break;
216656893Sfenner		case 20000:		/* Begin */
216756893Sfenner		case 20001:		/* Commit */
216856893Sfenner		case 20007:		/* Abort */
216956893Sfenner		case 20008:		/* Release locks */
217056893Sfenner		case 20010:		/* Writev */
217156893Sfenner			printf(" tid");
217256893Sfenner			UBIK_VERSIONOUT();
217356893Sfenner			break;
217456893Sfenner		case 20002:		/* Lock */
217556893Sfenner			printf(" tid");
217656893Sfenner			UBIK_VERSIONOUT();
217756893Sfenner			printf(" file");
217856893Sfenner			INTOUT();
217956893Sfenner			printf(" pos");
218056893Sfenner			INTOUT();
218156893Sfenner			printf(" length");
218256893Sfenner			INTOUT();
218375115Sfenner			temp = EXTRACT_32BITS(bp);
218456893Sfenner			bp += sizeof(int32_t);
218556893Sfenner			tok2str(ubik_lock_types, "type %d", temp);
218656893Sfenner			break;
218756893Sfenner		case 20003:		/* Write */
218856893Sfenner			printf(" tid");
218956893Sfenner			UBIK_VERSIONOUT();
219056893Sfenner			printf(" file");
219156893Sfenner			INTOUT();
219256893Sfenner			printf(" pos");
219356893Sfenner			INTOUT();
219456893Sfenner			break;
219556893Sfenner		case 20005:		/* Get file */
219656893Sfenner			printf(" file");
219756893Sfenner			INTOUT();
219856893Sfenner			break;
219956893Sfenner		case 20006:		/* Send file */
220056893Sfenner			printf(" file");
220156893Sfenner			INTOUT();
220256893Sfenner			printf(" length");
220356893Sfenner			INTOUT();
220456893Sfenner			printf(" dbversion");
220556893Sfenner			UBIK_VERSIONOUT();
220656893Sfenner			break;
220756893Sfenner		case 20009:		/* Truncate */
220856893Sfenner			printf(" tid");
220956893Sfenner			UBIK_VERSIONOUT();
221056893Sfenner			printf(" file");
221156893Sfenner			INTOUT();
221256893Sfenner			printf(" length");
221356893Sfenner			INTOUT();
221456893Sfenner			break;
221556893Sfenner		case 20012:		/* Set version */
221656893Sfenner			printf(" tid");
221756893Sfenner			UBIK_VERSIONOUT();
221856893Sfenner			printf(" oldversion");
221956893Sfenner			UBIK_VERSIONOUT();
222056893Sfenner			printf(" newversion");
222156893Sfenner			UBIK_VERSIONOUT();
222256893Sfenner			break;
222356893Sfenner		default:
222456893Sfenner			;
222556893Sfenner	}
222656893Sfenner
222756893Sfenner	return;
222856893Sfenner
222956893Sfennertrunc:
223056893Sfenner	printf(" [|ubik]");
223156893Sfenner}
223256893Sfenner
223356893Sfenner/*
223456893Sfenner * Handle Ubik replies to any one of the replicated database services
223556893Sfenner */
223656893Sfenner
223756893Sfennerstatic void
223856893Sfennerubik_reply_print(register const u_char *bp, int length, int32_t opcode)
223956893Sfenner{
224056893Sfenner	struct rx_header *rxh;
224156893Sfenner
2242127668Sbms	if (length < (int)sizeof(struct rx_header))
224356893Sfenner		return;
224456893Sfenner
224556893Sfenner	rxh = (struct rx_header *) bp;
224656893Sfenner
224756893Sfenner	/*
224856893Sfenner	 * Print out the ubik call we're invoking.  This table was gleaned
224956893Sfenner	 * from ubik/ubik_int.xg
225056893Sfenner	 */
225156893Sfenner
225256893Sfenner	printf(" ubik reply %s", tok2str(ubik_req, "op#%d", opcode));
225356893Sfenner
225456893Sfenner	bp += sizeof(struct rx_header);
225556893Sfenner
225656893Sfenner	/*
225756893Sfenner	 * If it was a data packet, print out the arguments to the Ubik calls
225856893Sfenner	 */
2259127668Sbms
226056893Sfenner	if (rxh->type == RX_PACKET_TYPE_DATA)
226156893Sfenner		switch (opcode) {
226256893Sfenner		case 10000:		/* Beacon */
226356893Sfenner			printf(" vote no");
226456893Sfenner			break;
226556893Sfenner		case 20004:		/* Get version */
226656893Sfenner			printf(" dbversion");
226756893Sfenner			UBIK_VERSIONOUT();
226856893Sfenner			break;
226956893Sfenner		default:
227056893Sfenner			;
227156893Sfenner		}
2272127668Sbms
227356893Sfenner	/*
227456893Sfenner	 * Otherwise, print out "yes" it it was a beacon packet (because
227556893Sfenner	 * that's how yes votes are returned, go figure), otherwise
227656893Sfenner	 * just print out the error code.
227756893Sfenner	 */
227856893Sfenner
227956893Sfenner	else
228056893Sfenner		switch (opcode) {
228156893Sfenner		case 10000:		/* Beacon */
228256893Sfenner			printf(" vote yes until");
228356893Sfenner			DATEOUT();
228456893Sfenner			break;
228556893Sfenner		default:
228656893Sfenner			printf(" errcode");
228756893Sfenner			INTOUT();
228856893Sfenner		}
228956893Sfenner
229056893Sfenner	return;
229156893Sfenner
229256893Sfennertrunc:
229356893Sfenner	printf(" [|ubik]");
229456893Sfenner}
229575115Sfenner
229675115Sfenner/*
229775115Sfenner * Handle RX ACK packets.
229875115Sfenner */
229975115Sfenner
230075115Sfennerstatic void
230175115Sfennerrx_ack_print(register const u_char *bp, int length)
230275115Sfenner{
230375115Sfenner	struct rx_ackPacket *rxa;
230475115Sfenner	int i, start, last;
2305172683Smlaier	u_int32_t firstPacket;
230675115Sfenner
2307127668Sbms	if (length < (int)sizeof(struct rx_header))
230875115Sfenner		return;
230975115Sfenner
231075115Sfenner	bp += sizeof(struct rx_header);
231175115Sfenner
231275115Sfenner	/*
231375115Sfenner	 * This may seem a little odd .... the rx_ackPacket structure
231475115Sfenner	 * contains an array of individual packet acknowledgements
231575115Sfenner	 * (used for selective ack/nack), but since it's variable in size,
231675115Sfenner	 * we don't want to truncate based on the size of the whole
231775115Sfenner	 * rx_ackPacket structure.
231875115Sfenner	 */
231975115Sfenner
232075115Sfenner	TCHECK2(bp[0], sizeof(struct rx_ackPacket) - RX_MAXACKS);
232175115Sfenner
232275115Sfenner	rxa = (struct rx_ackPacket *) bp;
232375115Sfenner	bp += (sizeof(struct rx_ackPacket) - RX_MAXACKS);
232475115Sfenner
232575115Sfenner	/*
232675115Sfenner	 * Print out a few useful things from the ack packet structure
232775115Sfenner	 */
232875115Sfenner
232975115Sfenner	if (vflag > 2)
233075115Sfenner		printf(" bufspace %d maxskew %d",
233175115Sfenner		       (int) EXTRACT_16BITS(&rxa->bufferSpace),
233275115Sfenner		       (int) EXTRACT_16BITS(&rxa->maxSkew));
2333127668Sbms
2334172683Smlaier	firstPacket = EXTRACT_32BITS(&rxa->firstPacket);
233575115Sfenner	printf(" first %d serial %d reason %s",
2336172683Smlaier	       firstPacket, EXTRACT_32BITS(&rxa->serial),
233775115Sfenner	       tok2str(rx_ack_reasons, "#%d", (int) rxa->reason));
2338127668Sbms
233975115Sfenner	/*
234075115Sfenner	 * Okay, now we print out the ack array.  The way _this_ works
234175115Sfenner	 * is that we start at "first", and step through the ack array.
234275115Sfenner	 * If we have a contiguous range of acks/nacks, try to
234375115Sfenner	 * collapse them into a range.
234475115Sfenner	 *
234575115Sfenner	 * If you're really clever, you might have noticed that this
234675115Sfenner	 * doesn't seem quite correct.  Specifically, due to structure
234775115Sfenner	 * padding, sizeof(struct rx_ackPacket) - RX_MAXACKS won't actually
234875115Sfenner	 * yield the start of the ack array (because RX_MAXACKS is 255
234975115Sfenner	 * and the structure will likely get padded to a 2 or 4 byte
235075115Sfenner	 * boundary).  However, this is the way it's implemented inside
2351127668Sbms	 * of AFS - the start of the extra fields are at
235275115Sfenner	 * sizeof(struct rx_ackPacket) - RX_MAXACKS + nAcks, which _isn't_
235375115Sfenner	 * the exact start of the ack array.  Sigh.  That's why we aren't
235475115Sfenner	 * using bp, but instead use rxa->acks[].  But nAcks gets added
235575115Sfenner	 * to bp after this, so bp ends up at the right spot.  Go figure.
235675115Sfenner	 */
235775115Sfenner
235875115Sfenner	if (rxa->nAcks != 0) {
235975115Sfenner
236075115Sfenner		TCHECK2(bp[0], rxa->nAcks);
236175115Sfenner
236275115Sfenner		/*
236375115Sfenner		 * Sigh, this is gross, but it seems to work to collapse
236475115Sfenner		 * ranges correctly.
236575115Sfenner		 */
236675115Sfenner
236775115Sfenner		for (i = 0, start = last = -2; i < rxa->nAcks; i++)
236875115Sfenner			if (rxa->acks[i] == RX_ACK_TYPE_ACK) {
236975115Sfenner
237075115Sfenner				/*
237175115Sfenner				 * I figured this deserved _some_ explanation.
237275115Sfenner				 * First, print "acked" and the packet seq
237375115Sfenner				 * number if this is the first time we've
237475115Sfenner				 * seen an acked packet.
237575115Sfenner				 */
237675115Sfenner
237775115Sfenner				if (last == -2) {
237875115Sfenner					printf(" acked %d",
2379172683Smlaier					       firstPacket + i);
238075115Sfenner					start = i;
238175115Sfenner				}
238275115Sfenner
238375115Sfenner				/*
238475115Sfenner				 * Otherwise, if the there is a skip in
238575115Sfenner				 * the range (such as an nacked packet in
238675115Sfenner				 * the middle of some acked packets),
238775115Sfenner				 * then print the current packet number
238875115Sfenner				 * seperated from the last number by
238975115Sfenner				 * a comma.
239075115Sfenner				 */
239175115Sfenner
239275115Sfenner				else if (last != i - 1) {
2393172683Smlaier					printf(",%d", firstPacket + i);
239475115Sfenner					start = i;
239575115Sfenner				}
239675115Sfenner
239775115Sfenner				/*
239875115Sfenner				 * We always set last to the value of
239975115Sfenner				 * the last ack we saw.  Conversely, start
240075115Sfenner				 * is set to the value of the first ack
240175115Sfenner				 * we saw in a range.
240275115Sfenner				 */
240375115Sfenner
240475115Sfenner				last = i;
240575115Sfenner
240675115Sfenner				/*
240775115Sfenner				 * Okay, this bit a code gets executed when
240875115Sfenner				 * we hit a nack ... in _this_ case we
240975115Sfenner				 * want to print out the range of packets
241075115Sfenner				 * that were acked, so we need to print
241175115Sfenner				 * the _previous_ packet number seperated
241275115Sfenner				 * from the first by a dash (-).  Since we
241375115Sfenner				 * already printed the first packet above,
241475115Sfenner				 * just print the final packet.  Don't
241575115Sfenner				 * do this if there will be a single-length
241675115Sfenner				 * range.
241775115Sfenner				 */
241875115Sfenner			} else if (last == i - 1 && start != last)
2419172683Smlaier				printf("-%d", firstPacket + i - 1);
2420127668Sbms
242175115Sfenner		/*
242275115Sfenner		 * So, what's going on here?  We ran off the end of the
242375115Sfenner		 * ack list, and if we got a range we need to finish it up.
242475115Sfenner		 * So we need to determine if the last packet in the list
242575115Sfenner		 * was an ack (if so, then last will be set to it) and
242675115Sfenner		 * we need to see if the last range didn't start with the
242775115Sfenner		 * last packet (because if it _did_, then that would mean
242875115Sfenner		 * that the packet number has already been printed and
242975115Sfenner		 * we don't need to print it again).
243075115Sfenner		 */
243175115Sfenner
243275115Sfenner		if (last == i - 1 && start != last)
2433172683Smlaier			printf("-%d", firstPacket + i - 1);
243475115Sfenner
243575115Sfenner		/*
243675115Sfenner		 * Same as above, just without comments
243775115Sfenner		 */
2438127668Sbms
243975115Sfenner		for (i = 0, start = last = -2; i < rxa->nAcks; i++)
244075115Sfenner			if (rxa->acks[i] == RX_ACK_TYPE_NACK) {
244175115Sfenner				if (last == -2) {
244275115Sfenner					printf(" nacked %d",
2443172683Smlaier					       firstPacket + i);
244475115Sfenner					start = i;
244575115Sfenner				} else if (last != i - 1) {
2446172683Smlaier					printf(",%d", firstPacket + i);
244775115Sfenner					start = i;
244875115Sfenner				}
244975115Sfenner				last = i;
245075115Sfenner			} else if (last == i - 1 && start != last)
2451172683Smlaier				printf("-%d", firstPacket + i - 1);
2452127668Sbms
245375115Sfenner		if (last == i - 1 && start != last)
2454172683Smlaier			printf("-%d", firstPacket + i - 1);
245575115Sfenner
245675115Sfenner		bp += rxa->nAcks;
245775115Sfenner	}
245875115Sfenner
245975115Sfenner
246075115Sfenner	/*
246175115Sfenner	 * These are optional fields; depending on your version of AFS,
246275115Sfenner	 * you may or may not see them
246375115Sfenner	 */
246475115Sfenner
246575115Sfenner#define TRUNCRET(n)	if (snapend - bp + 1 <= n) return;
246675115Sfenner
246775115Sfenner	if (vflag > 1) {
246875115Sfenner		TRUNCRET(4);
246975115Sfenner		printf(" ifmtu");
247075115Sfenner		INTOUT();
247175115Sfenner
247275115Sfenner		TRUNCRET(4);
247375115Sfenner		printf(" maxmtu");
247475115Sfenner		INTOUT();
247575115Sfenner
247675115Sfenner		TRUNCRET(4);
247775115Sfenner		printf(" rwind");
247875115Sfenner		INTOUT();
247975115Sfenner
248075115Sfenner		TRUNCRET(4);
248175115Sfenner		printf(" maxpackets");
248275115Sfenner		INTOUT();
248375115Sfenner	}
248475115Sfenner
248575115Sfenner	return;
248675115Sfenner
248775115Sfennertrunc:
248875115Sfenner	printf(" [|ack]");
248975115Sfenner}
249075115Sfenner#undef TRUNCRET
2491