📄 _rx.c
字号:
/*
* This code unmangles RX packets. RX is the mutant form of RPC that AFS
* uses to communicate between clients and servers.
*
* In this code, I mainly concern myself with decoding the AFS calls, not
* with the guts of RX, per se.
*
* Bah. If I never look at rx_packet.h again, it will be too soon.
*
* Ken Hornstein <kenh@cmf.nrl.navy.mil>
*
*/
#if 0
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/tcpdump/print-rx.c,v 1.5.2.1 2000/01/11 06:58:27 fenner Exp $";
#endif
#include <stdio.h>
#include <string.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include "interfac.h"
#include "a2name.h"
#include "rx.h"
#ifdef OLD_RX_PRINTER
static struct tok rx_types[] = {
{ RX_PACKET_TYPE_DATA, "data" },
{ RX_PACKET_TYPE_ACK, "ack" },
{ RX_PACKET_TYPE_BUSY, "busy" },
{ RX_PACKET_TYPE_ABORT, "abort" },
{ RX_PACKET_TYPE_ACKALL, "ackall" },
{ RX_PACKET_TYPE_CHALLENGE, "challenge" },
{ RX_PACKET_TYPE_RESPONSE, "response" },
{ RX_PACKET_TYPE_DEBUG, "debug" },
{ RX_PACKET_TYPE_PARAMS, "params" },
{ RX_PACKET_TYPE_VERSION, "version" },
{ 0, NULL },
};
static struct tok rx_flags[] = {
{ RX_CLIENT_INITIATED, "client-init" },
{ RX_REQUEST_ACK, "req-ack" },
{ RX_LAST_PACKET, "last-pckt" },
{ RX_MORE_PACKETS, "more-pckts" },
{ RX_FREE_PACKET, "free-pckt"}
};
static struct tok fs_req[] = {
{ 130, "fetch-data" },
{ 131, "fetch-acl" },
{ 132, "fetch-status" },
{ 133, "store-data" },
{ 134, "store-acl" },
{ 135, "store-status" },
{ 136, "remove-file" },
{ 137, "create-file" },
{ 138, "rename" },
{ 139, "symlink" },
{ 140, "link" },
{ 141, "makedir" },
{ 142, "rmdir" },
{ 143, "oldsetlock" },
{ 144, "oldextlock" },
{ 145, "oldrellock" },
{ 146, "get-stats" },
{ 147, "give-cbs" },
{ 148, "get-vlinfo" },
{ 149, "get-vlstats" },
{ 150, "set-vlstats" },
{ 151, "get-rootvl" },
{ 152, "check-token" },
{ 153, "get-time" },
{ 154, "nget-vlinfo" },
{ 155, "bulk-stat" },
{ 156, "setlock" },
{ 157, "extlock" },
{ 158, "rellock" },
{ 159, "xstat-ver" },
{ 160, "get-xstat" },
{ 161, "dfs-lookup" },
{ 162, "dfs-flushcps" },
{ 163, "dfs-symlink" },
{ 0, NULL },
};
static struct tok cb_req[] = {
{ 204, "callback" },
{ 205, "initcb" },
{ 206, "probe" },
{ 207, "getlock" },
{ 208, "getce" },
{ 209, "xstatver" },
{ 210, "getxstat" },
{ 211, "initcb2" },
{ 212, "whoareyou" },
{ 213, "initcb3" },
{ 214, "probeuuid" },
{ 0, NULL },
};
static struct tok pt_req[] = {
{ 500, "new-user" },
{ 501, "where-is-it" },
{ 502, "dump-entry" },
{ 503, "add-to-group" },
{ 504, "name-to-id" },
{ 505, "id-to-name" },
{ 506, "delete" },
{ 507, "remove-from-group" },
{ 508, "get-cps" },
{ 509, "new-entry" },
{ 510, "list-max" },
{ 511, "set-max" },
{ 512, "list-entry" },
{ 513, "change-entry" },
{ 514, "list-elements" },
{ 515, "same-mbr-of" },
{ 516, "set-fld-sentry" },
{ 517, "list-owned" },
{ 518, "get-cps2" },
{ 519, "get-host-cps" },
{ 520, "update-entry" },
{ 0, NULL },
};
static struct tok vldb_req[] = {
{ 501, "create-entry" },
{ 502, "delete-entry" },
{ 503, "get-entry-by-id" },
{ 504, "get-entry-by-name" },
{ 505, "get-new-volume-id" },
{ 506, "replace-entry" },
{ 507, "update-entry" },
{ 508, "setlock" },
{ 509, "releaselock" },
{ 510, "list-entry" },
{ 511, "list-attrib" },
{ 512, "linked-list" },
{ 513, "get-stats" },
{ 514, "probe" },
{ 515, "get-addrs" },
{ 516, "change-addr" },
{ 517, "create-entry-n" },
{ 518, "get-entry-by-id-n" },
{ 519, "get-entry-by-name-n" },
{ 520, "replace-entry-n" },
{ 521, "list-entry-n" },
{ 522, "list-attrib-n" },
{ 523, "linked-list-n" },
{ 524, "update-entry-by-name" },
{ 525, "create-entry-u" },
{ 526, "get-entry-by-id-u" },
{ 527, "get-entry-by-name-u" },
{ 528, "replace-entry-u" },
{ 529, "list-entry-u" },
{ 530, "list-attrib-u" },
{ 531, "linked-list-u" },
{ 532, "regaddr" },
{ 533, "get-addrs-u" },
{ 0, NULL },
};
static struct tok kauth_req[] = {
{ 1, "auth-old" },
{ 21, "authenticate" },
{ 22, "authenticate-v2" },
{ 2, "change-pw" },
{ 3, "get-ticket-old" },
{ 23, "get-ticket" },
{ 4, "set-pw" },
{ 5, "set-fields" },
{ 6, "create-user" },
{ 7, "delete-user" },
{ 8, "get-entry" },
{ 9, "list-entry" },
{ 10, "get-stats" },
{ 11, "debug" },
{ 12, "get-pw" },
{ 13, "get-random-key" },
{ 14, "unlock" },
{ 15, "lock-status" },
{ 0, NULL },
};
static struct tok vol_req[] = {
{ 100, "create-volume" },
{ 101, "delete-volume" },
{ 102, "restore" },
{ 103, "forward" },
{ 104, "end-trans" },
{ 105, "clone" },
{ 106, "set-flags" },
{ 107, "get-flags" },
{ 108, "trans-create" },
{ 109, "dump" },
{ 110, "get-nth-volume" },
{ 111, "set-forwarding" },
{ 112, "get-name" },
{ 113, "get-status" },
{ 114, "sig-restore" },
{ 115, "list-partitions" },
{ 116, "list-volumes" },
{ 117, "set-id-types" },
{ 118, "monitor" },
{ 119, "partition-info" },
{ 120, "reclone" },
{ 121, "list-one-volume" },
{ 122, "nuke" },
{ 123, "set-date" },
{ 124, "x-list-volumes" },
{ 125, "x-list-one-volume" },
{ 126, "set-info" },
{ 127, "x-list-partitions" },
{ 128, "forward-multiple" },
{ 0, NULL },
};
static struct tok bos_req[] = {
{ 80, "create-bnode" },
{ 81, "delete-bnode" },
{ 82, "set-status" },
{ 83, "get-status" },
{ 84, "enumerate-instance" },
{ 85, "get-instance-info" },
{ 86, "get-instance-parm" },
{ 87, "add-superuser" },
{ 88, "delete-superuser" },
{ 89, "list-superusers" },
{ 90, "list-keys" },
{ 91, "add-key" },
{ 92, "delete-key" },
{ 93, "set-cell-name" },
{ 94, "get-cell-name" },
{ 95, "get-cell-host" },
{ 96, "add-cell-host" },
{ 97, "delete-cell-host" },
{ 98, "set-t-status" },
{ 99, "shutdown-all" },
{ 100, "restart-all" },
{ 101, "startup-all" },
{ 102, "set-noauth-flag" },
{ 103, "re-bozo" },
{ 104, "restart" },
{ 105, "start-bozo-install" },
{ 106, "uninstall" },
{ 107, "get-dates" },
{ 108, "exec" },
{ 109, "prune" },
{ 110, "set-restart-time" },
{ 111, "get-restart-time" },
{ 112, "start-bozo-log" },
{ 113, "wait-all" },
{ 114, "get-instance-strings" },
{ 0, NULL },
};
static struct tok ubik_req[] = {
{ 10000, "vote-beacon" },
{ 10001, "vote-debug-old" },
{ 10002, "vote-sdebug-old" },
{ 10003, "vote-getsyncsite" },
{ 10004, "vote-debug" },
{ 10005, "vote-sdebug" },
{ 20000, "disk-begin" },
{ 20001, "disk-commit" },
{ 20002, "disk-lock" },
{ 20003, "disk-write" },
{ 20004, "disk-getversion" },
{ 20005, "disk-getfile" },
{ 20006, "disk-sendfile" },
{ 20007, "disk-abort" },
{ 20008, "disk-releaselocks" },
{ 20009, "disk-truncate" },
{ 20010, "disk-probe" },
{ 20011, "disk-writev" },
{ 20012, "disk-interfaceaddr" },
{ 20013, "disk-setversion" },
{ 0, NULL },
};
#define VOTE_LOW 10000
#define VOTE_HIGH 10005
#define DISK_LOW 20000
#define DISK_HIGH 20013
static struct tok cb_types[] = {
{ 1, "exclusive" },
{ 2, "shared" },
{ 3, "dropped" },
{ 0, NULL },
};
static struct tok ubik_lock_types[] = {
{ 1, "read" },
{ 2, "write" },
{ 3, "wait" },
{ 0, NULL },
};
static char *voltype[] = {
"read-write",
"read-only",
"backup"
};
/*
* Cache entries we keep around so we can figure out the RX opcode
* numbers for replies. This allows us to make sense of RX reply packets.
*/
struct rx_cache_entry
{
u_int32_t callnum; /* Call number (net order) */
struct in_addr client; /* client IP address (net order) */
struct in_addr server; /* server IP address (net order) */
int dport; /* server port (host order) */
u_short serviceId; /* Service identifier (net order) */
u_int32_t opcode; /* RX opcode (host order) */
};
#define RX_CACHE_SIZE 64
static struct rx_cache_entry rx_cache[RX_CACHE_SIZE];
static int rx_cache_next = 0;
static int rx_cache_hint = 0;
static void rx_cache_insert (const u_char *, const struct ip *, int, int);
static int rx_cache_find (const struct rx_header *, const struct ip *, int, int32_t *);
static void acl_print (u_char *, u_char *);
static void fs_print (const u_char *, int);
static void fs_reply_print (const u_char *, int, int32_t);
static void cb_print (const u_char *, int);
static void cb_reply_print (const u_char *, int, int32_t);
static void prot_print (const u_char *, int);
static void prot_reply_print (const u_char *, int, int32_t);
static void vldb_print (const u_char *, int);
static void vldb_reply_print (const u_char *, int, int32_t);
static void kauth_print (const u_char *, int);
static void kauth_reply_print(const u_char *, int, int32_t);
static void vol_print (const u_char *, int);
static void vol_reply_print (const u_char *, int, int32_t);
static void bos_print (const u_char *, int);
static void bos_reply_print (const u_char *, int, int32_t);
static void ubik_print (const u_char *, int);
static void ubik_reply_print (const u_char *, int, int32_t);
/*
* Check to see if this is a Ubik opcode.
*/
static __inline int is_ubik (u_int32_t opcode)
{
if ((opcode >= VOTE_LOW && opcode <= VOTE_HIGH) ||
(opcode >= DISK_LOW && opcode <= DISK_HIGH))
return (1);
return (0);
}
/*
* Handle the rx-level packet. See if we know what port it's going to so
* we can peek at the afs call inside
*/
void rx_print (const u_char *bp, u_int length, u_int sport, u_int dport,
u_char *bp2)
{
struct rx_header *rxh;
int i;
int32_t opcode;
if (snapend - bp < sizeof(struct rx_header))
{
PRINTF (" [|rx] (%d)", length);
return;
}
rxh = (struct rx_header *) bp;
PRINTF (" rx %s", tok2str (rx_types, "type %d", rxh->type));
if (vflag > 1)
{
int firstflag = 0;
PRINTF (" cid %08x call# %d seq %d ser %d",
(int)ntohl(rxh->cid), (int)ntohl(rxh->callNumber),
(int)ntohl(rxh->seq), (int)ntohl(rxh->serial));
if (vflag > 2)
PRINTF (" secindex %d serviceid %hu",
(int)rxh->securityIndex, ntohs(rxh->serviceId));
for (i = 0; i < NUM_RX_FLAGS; i++)
{
if (rxh->flags & rx_flags[i].v)
{
if (!firstflag)
{
firstflag = 1;
PUTCHAR (' ');
}
else
PUTCHAR (',');
PRINTF ("<%s>", rx_flags[i].s);
}
}
}
/*
* Try to handle AFS calls that we know about. Check the destination
* port and make sure it's a data packet. Also, make sure the
* seq number is 1 (because otherwise it's a continuation packet,
* and we can't interpret that). Also, seems that reply packets
* do not have the client-init flag set, so we check for that
* as well.
*/
if (rxh->type == RX_PACKET_TYPE_DATA && ntohl(rxh->seq) == 1 &&
rxh->flags & RX_CLIENT_INITIATED)
{
/*
* Insert this call into the call cache table, so we
* have a chance to print out replies
*/
rx_cache_insert (bp, (const struct ip*)bp2, dport, length);
switch (dport)
{
case FS_RX_PORT: /* AFS file service */
fs_print (bp, length);
break;
case CB_RX_PORT: /* AFS callback service */
cb_print (bp, length);
break;
case PROT_RX_PORT: /* AFS protection service */
prot_print (bp, length);
break;
case VLDB_RX_PORT: /* AFS VLDB service */
vldb_print (bp, length);
break;
case KAUTH_RX_PORT: /* AFS Kerberos auth service */
kauth_print (bp, length);
break;
case VOL_RX_PORT: /* AFS Volume service */
vol_print (bp, length);
break;
case BOS_RX_PORT: /* AFS BOS service */
bos_print (bp, length);
break;
default:
;
}
/*
* If it's a reply (client-init is _not_ set, but seq is one)
* then look it up in the cache. If we find it, call the reply
* printing functions Note that we handle abort packets here,
* because printing out the return code can be useful at times.
*/
}
else if (((rxh->type == RX_PACKET_TYPE_DATA && ntohl(rxh->seq) == 1) ||
rxh->type == RX_PACKET_TYPE_ABORT) &&
(rxh->flags & RX_CLIENT_INITIATED) == 0 &&
rx_cache_find (rxh, (const struct ip*)bp2, sport, &opcode))
{
switch (sport)
{
case FS_RX_PORT: /* AFS file service */
fs_reply_print (bp, length, opcode);
break;
case CB_RX_PORT: /* AFS callback service */
cb_reply_print (bp, length, opcode);
break;
case PROT_RX_PORT: /* AFS PT service */
prot_reply_print (bp, length, opcode);
break;
case VLDB_RX_PORT: /* AFS VLDB service */
vldb_reply_print (bp, length, opcode);
break;
case KAUTH_RX_PORT: /* AFS Kerberos auth service */
kauth_reply_print (bp, length, opcode);
break;
case VOL_RX_PORT: /* AFS Volume service */
vol_reply_print (bp, length, opcode);
break;
case BOS_RX_PORT: /* AFS BOS service */
bos_reply_print (bp, length, opcode);
break;
}
}
PRINTF (" (%d)", length);
}
/*
* Insert an entry into the cache. Taken from print-nfs.c
*/
static void rx_cache_insert (const u_char *bp, const struct ip *ip, int dport, int length)
{
struct rx_cache_entry *rxent;
const struct rx_header *rxh = (const struct rx_header *) bp;
if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t))
return;
rxent = &rx_cache[rx_cache_next];
if (++rx_cache_next >= RX_CACHE_SIZE)
rx_cache_next = 0;
rxent->callnum = rxh->callNumber;
rxent->client = ip->ip_src;
rxent->server = ip->ip_dst;
rxent->dport = dport;
rxent->serviceId = rxh->serviceId;
rxent->opcode = ntohl (*((int*)(bp+sizeof(struct rx_header))));
}
/*
* Lookup an entry in the cache. Also taken from print-nfs.c
*
* Note that because this is a reply, we're looking at the _source_
* port.
*/
static int rx_cache_find (const struct rx_header *rxh, const struct ip *ip, int sport, int32_t *opcode)
{
struct rx_cache_entry *rxent;
u_int32_t clip = ip->ip_dst.s_addr;
u_int32_t sip = ip->ip_src.s_addr;
/* Start the search where we last left off
*/
int i = rx_cache_hint;
do
{
rxent = &rx_cache[i];
if (rxent->callnum == rxh->callNumber &&
rxent->client.s_addr == clip &&
rxent->server.s_addr == sip &&
rxent->serviceId == rxh->serviceId &&
rxent->dport == sport)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -