+/*
+ * Copyright: (c) 2000 United States Government as represented by the
+ * Secretary of the Navy. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. The names of the authors may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
/*
* This code unmangles RX packets. RX is the mutant form of RPC that AFS
* uses to communicate between clients and servers.
* Bah. If I never look at rx_packet.h again, it will be too soon.
*
- *
*/
-#ifndef lint
-static const char rcsid[] =
- "@(#) $Header: /tcpdump/master/tcpdump/print-rx.c,v 1.7 2000-01-09 21:34:19 fenner Exp $";
-#endif
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
+#include <stdlib.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 <tcpdump-stdinc.h>
#include "interface.h"
#include "addrtoname.h"
+#include "extract.h"
+
+#include "ip.h"
+
+#define FS_RX_PORT 7000
+#define CB_RX_PORT 7001
+#define PROT_RX_PORT 7002
+#define VLDB_RX_PORT 7003
+#define KAUTH_RX_PORT 7004
+#define VOL_RX_PORT 7005
+#define ERROR_RX_PORT 7006 /* Doesn't seem to be used */
+#define BOS_RX_PORT 7007
+
+#define AFSNAMEMAX 256
+#define AFSOPAQUEMAX 1024
+#define PRNAMEMAX 64
+#define VLNAMEMAX 65
+#define KANAMEMAX 64
+#define BOSNAMEMAX 256
+
+#define PRSFS_READ 1 /* Read files */
+#define PRSFS_WRITE 2 /* Write files */
+#define PRSFS_INSERT 4 /* Insert files into a directory */
+#define PRSFS_LOOKUP 8 /* Lookup files into a directory */
+#define PRSFS_DELETE 16 /* Delete files */
+#define PRSFS_LOCK 32 /* Lock files */
+#define PRSFS_ADMINISTER 64 /* Change ACL's */
+
+struct rx_header {
+ u_int32_t epoch;
+ u_int32_t cid;
+ u_int32_t callNumber;
+ u_int32_t seq;
+ u_int32_t serial;
+ u_int8_t type;
+#define RX_PACKET_TYPE_DATA 1
+#define RX_PACKET_TYPE_ACK 2
+#define RX_PACKET_TYPE_BUSY 3
+#define RX_PACKET_TYPE_ABORT 4
+#define RX_PACKET_TYPE_ACKALL 5
+#define RX_PACKET_TYPE_CHALLENGE 6
+#define RX_PACKET_TYPE_RESPONSE 7
+#define RX_PACKET_TYPE_DEBUG 8
+#define RX_PACKET_TYPE_PARAMS 9
+#define RX_PACKET_TYPE_VERSION 13
+ u_int8_t flags;
+#define RX_CLIENT_INITIATED 1
+#define RX_REQUEST_ACK 2
+#define RX_LAST_PACKET 4
+#define RX_MORE_PACKETS 8
+#define RX_FREE_PACKET 16
+#define RX_SLOW_START_OK 32
+#define RX_JUMBO_PACKET 32
+ u_int8_t userStatus;
+ u_int8_t securityIndex;
+ u_int16_t spare; /* How clever: even though the AFS */
+ u_int16_t serviceId; /* header files indicate that the */
+}; /* serviceId is first, it's really */
+ /* encoded _after_ the spare field */
+ /* I wasted a day figuring that out! */
+
+#define NUM_RX_FLAGS 7
+
+#define RX_MAXACKS 255
+
+struct rx_ackPacket {
+ u_int16_t bufferSpace; /* Number of packet buffers available */
+ u_int16_t maxSkew; /* Max diff between ack'd packet and */
+ /* highest packet received */
+ u_int32_t firstPacket; /* The first packet in ack list */
+ u_int32_t previousPacket; /* Previous packet recv'd (obsolete) */
+ u_int32_t serial; /* # of packet that prompted the ack */
+ u_int8_t reason; /* Reason for acknowledgement */
+ u_int8_t nAcks; /* Number of acknowledgements */
+ u_int8_t acks[RX_MAXACKS]; /* Up to RX_MAXACKS acknowledgements */
+};
-#undef NOERROR /* Solaris sucks */
-#include <arpa/nameser.h>
+/*
+ * Values for the acks array
+ */
-#include "rx.h"
+#define RX_ACK_TYPE_NACK 0 /* Don't have this packet */
+#define RX_ACK_TYPE_ACK 1 /* I have this packet */
-static struct tok rx_types[] = {
+static const struct tok rx_types[] = {
{ RX_PACKET_TYPE_DATA, "data" },
{ RX_PACKET_TYPE_ACK, "ack" },
{ RX_PACKET_TYPE_BUSY, "busy" },
{ 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 const struct double_tok {
+ int flag; /* Rx flag */
+ int packetType; /* Packet type */
+ const char *s; /* Flag string */
+} rx_flags[] = {
+ { RX_CLIENT_INITIATED, 0, "client-init" },
+ { RX_REQUEST_ACK, 0, "req-ack" },
+ { RX_LAST_PACKET, 0, "last-pckt" },
+ { RX_MORE_PACKETS, 0, "more-pckts" },
+ { RX_FREE_PACKET, 0, "free-pckt" },
+ { RX_SLOW_START_OK, RX_PACKET_TYPE_ACK, "slow-start" },
+ { RX_JUMBO_PACKET, RX_PACKET_TYPE_DATA, "jumbogram" }
};
-static struct tok fs_req[] = {
+static const struct tok fs_req[] = {
{ 130, "fetch-data" },
{ 131, "fetch-acl" },
{ 132, "fetch-status" },
{ 161, "dfs-lookup" },
{ 162, "dfs-flushcps" },
{ 163, "dfs-symlink" },
+ { 220, "residency" },
+ { 65536, "inline-bulk-status" },
+ { 65537, "fetch-data-64" },
+ { 65538, "store-data-64" },
+ { 65539, "give-up-all-cbs" },
+ { 65540, "get-caps" },
+ { 65541, "cb-rx-conn-addr" },
{ 0, NULL },
};
-static struct tok cb_req[] = {
+static const struct tok cb_req[] = {
{ 204, "callback" },
{ 205, "initcb" },
{ 206, "probe" },
{ 212, "whoareyou" },
{ 213, "initcb3" },
{ 214, "probeuuid" },
+ { 215, "getsrvprefs" },
+ { 216, "getcellservdb" },
+ { 217, "getlocalcell" },
+ { 218, "getcacheconf" },
+ { 65536, "getce64" },
+ { 65537, "getcellbynum" },
+ { 65538, "tellmeaboutyourself" },
{ 0, NULL },
};
-static struct tok pt_req[] = {
+static const struct tok pt_req[] = {
{ 500, "new-user" },
{ 501, "where-is-it" },
{ 502, "dump-entry" },
{ 518, "get-cps2" },
{ 519, "get-host-cps" },
{ 520, "update-entry" },
+ { 521, "list-entries" },
+ { 530, "list-super-groups" },
{ 0, NULL },
};
-static struct tok vldb_req[] = {
+static const struct tok vldb_req[] = {
{ 501, "create-entry" },
{ 502, "delete-entry" },
{ 503, "get-entry-by-id" },
{ 531, "linked-list-u" },
{ 532, "regaddr" },
{ 533, "get-addrs-u" },
+ { 534, "list-attrib-n2" },
{ 0, NULL },
};
-static struct tok kauth_req[] = {
+static const struct tok kauth_req[] = {
{ 1, "auth-old" },
{ 21, "authenticate" },
{ 22, "authenticate-v2" },
{ 0, NULL },
};
-static struct tok vol_req[] = {
+static const struct tok vol_req[] = {
{ 100, "create-volume" },
{ 101, "delete-volume" },
{ 102, "restore" },
{ 126, "set-info" },
{ 127, "x-list-partitions" },
{ 128, "forward-multiple" },
+ { 65536, "convert-ro" },
+ { 65537, "get-size" },
+ { 65538, "dump-v2" },
{ 0, NULL },
};
-static struct tok bos_req[] = {
+static const struct tok bos_req[] = {
{ 80, "create-bnode" },
{ 81, "delete-bnode" },
{ 82, "set-status" },
{ 112, "start-bozo-log" },
{ 113, "wait-all" },
{ 114, "get-instance-strings" },
+ { 115, "get-restricted" },
+ { 116, "set-restricted" },
{ 0, NULL },
};
-static struct tok ubik_req[] = {
+static const struct tok ubik_req[] = {
{ 10000, "vote-beacon" },
{ 10001, "vote-debug-old" },
{ 10002, "vote-sdebug-old" },
{ 10003, "vote-getsyncsite" },
{ 10004, "vote-debug" },
{ 10005, "vote-sdebug" },
+ { 10006, "vote-xdebug" },
+ { 10007, "vote-xsdebug" },
{ 20000, "disk-begin" },
{ 20001, "disk-commit" },
{ 20002, "disk-lock" },
};
#define VOTE_LOW 10000
-#define VOTE_HIGH 10005
+#define VOTE_HIGH 10007
#define DISK_LOW 20000
#define DISK_HIGH 20013
-static struct tok cb_types[] = {
+static const struct tok cb_types[] = {
{ 1, "exclusive" },
{ 2, "shared" },
{ 3, "dropped" },
{ 0, NULL },
};
-static struct tok ubik_lock_types[] = {
+static const struct tok ubik_lock_types[] = {
{ 1, "read" },
{ 2, "write" },
{ 3, "wait" },
{ 0, NULL },
};
-static char *voltype[] = { "read-write", "read-only", "backup" };
+static const char *voltype[] = { "read-write", "read-only", "backup" };
-static struct tok afs_fs_errors[] = {
+static const struct tok afs_fs_errors[] = {
{ 101, "salvage volume" },
{ 102, "no such vnode" },
{ 103, "no such volume" },
{ 0, NULL }
};
+/*
+ * Reasons for acknowledging a packet
+ */
+
+static const struct tok rx_ack_reasons[] = {
+ { 1, "ack requested" },
+ { 2, "duplicate packet" },
+ { 3, "out of sequence" },
+ { 4, "exceeds window" },
+ { 5, "no buffer space" },
+ { 6, "ping" },
+ { 7, "ping response" },
+ { 8, "delay" },
+ { 9, "idle" },
+ { 0, NULL },
+};
+
/*
* 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.
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 void rx_cache_insert(const u_char *, const struct ip *, int);
static int rx_cache_find(const struct rx_header *, const struct ip *,
int, int32_t *);
static void fs_print(const u_char *, int);
static void fs_reply_print(const u_char *, int, int32_t);
-static void acl_print(u_char *, u_char *);
+static void acl_print(u_char *, int, u_char *);
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 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_print(const u_char *);
static void ubik_reply_print(const u_char *, int, int32_t);
+static void rx_ack_print(const u_char *, int);
+
static int is_ubik(u_int32_t);
/*
int i;
int32_t opcode;
- if (snapend - bp < sizeof (struct rx_header)) {
+ if (snapend - bp < (int)sizeof (struct rx_header)) {
printf(" [|rx] (%d)", length);
return;
}
printf(" rx %s", tok2str(rx_types, "type %d", rxh->type));
- if (vflag > 1) {
+ if (vflag) {
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 > 1)
+ printf(" cid %08x call# %d",
+ (int) EXTRACT_32BITS(&rxh->cid),
+ (int) EXTRACT_32BITS(&rxh->callNumber));
+
+ printf(" seq %d ser %d",
+ (int) EXTRACT_32BITS(&rxh->seq),
+ (int) EXTRACT_32BITS(&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;
- printf(" ");
- } else {
- printf(",");
+ EXTRACT_16BITS(&rxh->serviceId));
+
+ if (vflag > 1)
+ for (i = 0; i < NUM_RX_FLAGS; i++) {
+ if (rxh->flags & rx_flags[i].flag &&
+ (!rx_flags[i].packetType ||
+ rxh->type == rx_flags[i].packetType)) {
+ if (!firstflag) {
+ firstflag = 1;
+ printf(" ");
+ } else {
+ printf(",");
+ }
+ printf("<%s>", rx_flags[i].s);
}
- printf("<%s>", rx_flags[i].s);
}
- }
}
/*
* as well.
*/
- if (rxh->type == RX_PACKET_TYPE_DATA && ntohl(rxh->seq) == 1 &&
+ if (rxh->type == RX_PACKET_TYPE_DATA &&
+ EXTRACT_32BITS(&rxh->seq) == 1 &&
rxh->flags & RX_CLIENT_INITIATED) {
/*
* have a chance to print out replies
*/
- rx_cache_insert(bp, (const struct ip *) bp2, dport, length);
+ rx_cache_insert(bp, (const struct ip *) bp2, dport);
switch (dport) {
case FS_RX_PORT: /* AFS file service */
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
*/
} else if (((rxh->type == RX_PACKET_TYPE_DATA &&
- ntohl(rxh->seq) == 1) ||
+ EXTRACT_32BITS(&rxh->seq) == 1) ||
rxh->type == RX_PACKET_TYPE_ABORT) &&
(rxh->flags & RX_CLIENT_INITIATED) == 0 &&
rx_cache_find(rxh, (const struct ip *) bp2,
default:
;
}
- }
+
+ /*
+ * If it's an RX ack packet, then use the appropriate ack decoding
+ * function (there isn't any service-specific information in the
+ * ack packet, so we can use one for all AFS services)
+ */
+
+ } else if (rxh->type == RX_PACKET_TYPE_ACK)
+ rx_ack_print(bp, length);
printf(" (%d)", length);
*/
static void
-rx_cache_insert(const u_char *bp, const struct ip *ip, int dport,
- int length)
+rx_cache_insert(const u_char *bp, const struct ip *ip, int dport)
{
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))
+ if (snapend - bp + 1 <= (int)(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))));
+ rxent->opcode = EXTRACT_32BITS(bp + sizeof(struct rx_header));
}
/*
rxent = &rx_cache[i];
if (rxent->callnum == rxh->callNumber &&
rxent->client.s_addr == clip &&
- rxent->server.s_addr == sip &&
+ rxent->server.s_addr == sip &&
rxent->serviceId == rxh->serviceId &&
rxent->dport == sport) {
*opcode = rxent->opcode;
return(1);
}
- if (++i > RX_CACHE_SIZE)
+ if (++i >= RX_CACHE_SIZE)
i = 0;
} while (i != rx_cache_hint);
* These extrememly grody macros handle the printing of various AFS stuff.
*/
-#define TRUNC(n) if (snapend - bp + 1 <= n) goto trunc;
#define FIDOUT() { unsigned long n1, n2, n3; \
- TRUNC(sizeof(int32_t) * 3); \
- n1 = ntohl(*((int *) bp)); \
+ TCHECK2(bp[0], sizeof(int32_t) * 3); \
+ n1 = EXTRACT_32BITS(bp); \
bp += sizeof(int32_t); \
- n2 = ntohl(*((int *) bp)); \
+ n2 = EXTRACT_32BITS(bp); \
bp += sizeof(int32_t); \
- n3 = ntohl(*((int *) bp)); \
+ n3 = EXTRACT_32BITS(bp); \
bp += sizeof(int32_t); \
printf(" fid %d/%d/%d", (int) n1, (int) n2, (int) n3); \
}
-#define STROUT(MAX) { int i; \
- TRUNC(sizeof(int32_t)); \
- i = (int) ntohl(*((int *) bp)); \
+#define STROUT(MAX) { unsigned int i; \
+ TCHECK2(bp[0], sizeof(int32_t)); \
+ i = EXTRACT_32BITS(bp); \
+ if (i > (MAX)) \
+ goto trunc; \
bp += sizeof(int32_t); \
- TRUNC(i); \
- strncpy(s, bp, min(MAX, i)); \
- s[i] = '\0'; \
- printf(" \"%s\"", s); \
+ printf(" \""); \
+ if (fn_printn(bp, i, snapend)) \
+ goto trunc; \
+ printf("\""); \
bp += ((i + sizeof(int32_t) - 1) / sizeof(int32_t)) * sizeof(int32_t); \
}
#define INTOUT() { int i; \
- TRUNC(sizeof(int32_t)); \
- i = (int) ntohl(*((int *) bp)); \
+ TCHECK2(bp[0], sizeof(int32_t)); \
+ i = (int) EXTRACT_32BITS(bp); \
bp += sizeof(int32_t); \
printf(" %d", i); \
}
#define UINTOUT() { unsigned long i; \
- TRUNC(sizeof(int32_t)); \
- i = ntohl(*((int *) bp)); \
+ TCHECK2(bp[0], sizeof(int32_t)); \
+ i = EXTRACT_32BITS(bp); \
bp += sizeof(int32_t); \
printf(" %lu", i); \
}
+#define UINT64OUT() { u_int64_t i; \
+ TCHECK2(bp[0], sizeof(u_int64_t)); \
+ i = EXTRACT_64BITS(bp); \
+ bp += sizeof(u_int64_t); \
+ printf(" %" PRIu64, i); \
+ }
+
#define DATEOUT() { time_t t; struct tm *tm; char str[256]; \
- TRUNC(sizeof(int32_t)); \
- t = (time_t) ntohl(*((int *) bp)); \
+ TCHECK2(bp[0], sizeof(int32_t)); \
+ t = (time_t) EXTRACT_32BITS(bp); \
bp += sizeof(int32_t); \
tm = localtime(&t); \
strftime(str, 256, "%Y/%m/%d %T", tm); \
}
#define STOREATTROUT() { unsigned long mask, i; \
- TRUNC((sizeof(int32_t)*6)); \
- mask = ntohl(*((int *) bp)); bp += sizeof(int32_t); \
+ TCHECK2(bp[0], (sizeof(int32_t)*6)); \
+ mask = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
if (mask) printf (" StoreStatus"); \
- if (mask & 1) { printf(" date"); DATEOUT(); } \
+ if (mask & 1) { printf(" date"); DATEOUT(); } \
else bp += sizeof(int32_t); \
- i = ntohl(*((int *) bp)); bp += sizeof(int32_t); \
- if (mask & 2) printf(" owner %lu", i); \
- i = ntohl(*((int32_t *) bp)); bp += sizeof(int32_t); \
- if (mask & 4) printf(" group %lu", i); \
- i = ntohl(*((int32_t *) bp)); bp += sizeof(int32_t); \
- if (mask & 8) printf(" mode %lo", i & 07777); \
- i = ntohl(*((int32_t *) bp)); bp += sizeof(int32_t); \
- if (mask & 16) printf(" segsize %lu", i); \
+ i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
+ if (mask & 2) printf(" owner %lu", i); \
+ i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
+ if (mask & 4) printf(" group %lu", i); \
+ i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
+ if (mask & 8) printf(" mode %lo", i & 07777); \
+ i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \
+ if (mask & 16) printf(" segsize %lu", i); \
/* undocumented in 3.3 docu */ \
- if (mask & 1024) printf(" fsync"); \
+ if (mask & 1024) printf(" fsync"); \
}
#define UBIK_VERSIONOUT() {int32_t epoch; int32_t counter; \
- TRUNC(sizeof(int32_t) * 2); \
- epoch = ntohl(*((int *) bp)); \
+ TCHECK2(bp[0], sizeof(int32_t) * 2); \
+ epoch = EXTRACT_32BITS(bp); \
bp += sizeof(int32_t); \
- counter = ntohl(*((int *) bp)); \
+ counter = EXTRACT_32BITS(bp); \
bp += sizeof(int32_t); \
printf(" %d.%d", epoch, counter); \
}
#define AFSUUIDOUT() {u_int32_t temp; int i; \
- TRUNC(11*sizeof(u_int32_t)); \
- temp = ntohl(*((int *) bp)); \
+ TCHECK2(bp[0], 11*sizeof(u_int32_t)); \
+ temp = EXTRACT_32BITS(bp); \
bp += sizeof(u_int32_t); \
printf(" %08x", temp); \
- temp = ntohl(*((int *) bp)); \
+ temp = EXTRACT_32BITS(bp); \
bp += sizeof(u_int32_t); \
printf("%04x", temp); \
- temp = ntohl(*((int *) bp)); \
+ temp = EXTRACT_32BITS(bp); \
bp += sizeof(u_int32_t); \
printf("%04x", temp); \
for (i = 0; i < 8; i++) { \
- temp = ntohl(*((int *) bp)); \
+ temp = EXTRACT_32BITS(bp); \
bp += sizeof(u_int32_t); \
printf("%02x", (unsigned char) temp); \
} \
* This is the sickest one of all
*/
-#define VECOUT(MAX) { char *sp; \
+#define VECOUT(MAX) { u_char *sp; \
+ u_char s[AFSNAMEMAX]; \
int k; \
- TRUNC(MAX * sizeof(int32_t)); \
+ if ((MAX) + 1 > sizeof(s)) \
+ goto trunc; \
+ TCHECK2(bp[0], (MAX) * sizeof(int32_t)); \
sp = s; \
- for (k = 0; k < MAX; k++) { \
- *sp++ = (char) ntohl(*((int *) bp)); \
+ for (k = 0; k < (MAX); k++) { \
+ *sp++ = (u_char) EXTRACT_32BITS(bp); \
bp += sizeof(int32_t); \
} \
- s[MAX] = '\0'; \
- printf(" \"%s\"", s); \
+ s[(MAX)] = '\0'; \
+ printf(" \""); \
+ fn_print(s, NULL); \
+ printf("\""); \
+ }
+
+#define DESTSERVEROUT() { unsigned long n1, n2, n3; \
+ TCHECK2(bp[0], sizeof(int32_t) * 3); \
+ n1 = EXTRACT_32BITS(bp); \
+ bp += sizeof(int32_t); \
+ n2 = EXTRACT_32BITS(bp); \
+ bp += sizeof(int32_t); \
+ n3 = EXTRACT_32BITS(bp); \
+ bp += sizeof(int32_t); \
+ printf(" server %d:%d:%d", (int) n1, (int) n2, (int) n3); \
}
/*
* Handle calls to the AFS file service (fs)
*/
-void
+static void
fs_print(register const u_char *bp, int length)
{
int fs_op;
unsigned long i;
- char s[AFSNAMEMAX];
- if (length <= sizeof(struct rx_header))
+ if (length <= (int)sizeof(struct rx_header))
return;
- if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) {
+ if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
goto trunc;
}
* gleaned from fsint/afsint.xg
*/
- fs_op = ntohl(*((int *) (bp + sizeof(struct rx_header))));
+ fs_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
printf(" fs call %s", tok2str(fs_req, "op#%d", fs_op));
break;
case 134: /* Store ACL */
{
- char a[AFSOPAQUEMAX];
+ char a[AFSOPAQUEMAX+1];
FIDOUT();
- TRUNC(4);
- i = ntohl(*((int *) bp));
+ TCHECK2(bp[0], 4);
+ i = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
- TRUNC(i);
- strncpy(a, bp, min(AFSOPAQUEMAX, i));
+ TCHECK2(bp[0], i);
+ i = min(AFSOPAQUEMAX, i);
+ strncpy(a, (char *) bp, i);
a[i] = '\0';
- acl_print((u_char *) a, (u_char *) a + i);
+ acl_print((u_char *) a, sizeof(a), (u_char *) a + i);
break;
}
case 137: /* Create file */
STROUT(AFSNAMEMAX);
break;
case 155: /* Bulk stat */
+ case 65536: /* Inline bulk stat */
{
unsigned long j;
- TRUNC(4);
- j = ntohl(*((int *) bp));
+ TCHECK2(bp[0], 4);
+ j = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
for (i = 0; i < j; i++) {
if (j == 0)
printf(" <none!>");
}
+ case 65537: /* Fetch data 64 */
+ FIDOUT();
+ printf(" offset");
+ UINT64OUT();
+ printf(" length");
+ UINT64OUT();
+ break;
+ case 65538: /* Store data 64 */
+ FIDOUT();
+ STOREATTROUT();
+ printf(" offset");
+ UINT64OUT();
+ printf(" length");
+ UINT64OUT();
+ printf(" flen");
+ UINT64OUT();
+ break;
+ case 65541: /* CallBack rx conn address */
+ printf(" addr");
+ UINTOUT();
default:
;
}
fs_reply_print(register const u_char *bp, int length, int32_t opcode)
{
unsigned long i;
- char s[AFSNAMEMAX];
struct rx_header *rxh;
- if (length <= sizeof(struct rx_header))
+ if (length <= (int)sizeof(struct rx_header))
return;
rxh = (struct rx_header *) bp;
switch (opcode) {
case 131: /* Fetch ACL */
{
- char a[AFSOPAQUEMAX];
- TRUNC(4);
- i = ntohl(*((int *) bp));
+ char a[AFSOPAQUEMAX+1];
+ TCHECK2(bp[0], 4);
+ i = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
- TRUNC(i);
- strncpy(a, bp, min(AFSOPAQUEMAX, i));
+ TCHECK2(bp[0], i);
+ i = min(AFSOPAQUEMAX, i);
+ strncpy(a, (char *) bp, i);
a[i] = '\0';
- acl_print((u_char *) a, (u_char *) a + i);
+ acl_print((u_char *) a, sizeof(a), (u_char *) a + i);
break;
}
case 137: /* Create file */
} else if (rxh->type == RX_PACKET_TYPE_ABORT) {
int i;
- /*
- * Otherwise, just print out the return code
- */
- TRUNC(sizeof(int32_t));
- i = (int) ntohl(*((int *) bp));
- bp += sizeof(int32_t);
+ /*
+ * Otherwise, just print out the return code
+ */
+ TCHECK2(bp[0], sizeof(int32_t));
+ i = (int) EXTRACT_32BITS(bp);
+ bp += sizeof(int32_t);
printf(" error %s", tok2str(afs_fs_errors, "#%d", i));
} else {
* <positive> <negative>
* <uid1> <aclbits1>
* ....
- *
+ *
* "positive" and "negative" are integers which contain the number of
* positive and negative ACL's in the string. The uid/aclbits pair are
* ASCII strings containing the UID/PTS record and and a ascii number
*/
static void
-acl_print(u_char *s, u_char *end)
+acl_print(u_char *s, int maxsize, u_char *end)
{
int pos, neg, acl;
int n, i;
- char user[128];
+ char *user;
+ char fmt[1024];
- if (sscanf((char *) s, "%d %d\n%n", &pos, &neg, &n) != 2)
+ if ((user = (char *)malloc(maxsize)) == NULL)
return;
-
+
+ if (sscanf((char *) s, "%d %d\n%n", &pos, &neg, &n) != 2)
+ goto finish;
+
s += n;
if (s > end)
- return;
+ goto finish;
/*
* This wacky order preserves the order used by the "fs" command
printf("a");
for (i = 0; i < pos; i++) {
- if (sscanf((char *) s, "%s %d\n%n", user, &acl, &n) != 2)
- return;
+ snprintf(fmt, sizeof(fmt), "%%%ds %%d\n%%n", maxsize - 1);
+ if (sscanf((char *) s, fmt, user, &acl, &n) != 2)
+ goto finish;
s += n;
- printf(" +{%s ", user);
+ printf(" +{");
+ fn_print((u_char *)user, NULL);
+ printf(" ");
ACLOUT(acl);
printf("}");
if (s > end)
- return;
+ goto finish;
}
for (i = 0; i < neg; i++) {
- if (sscanf((char *) s, "%s %d\n%n", user, &acl, &n) != 2)
- return;
+ snprintf(fmt, sizeof(fmt), "%%%ds %%d\n%%n", maxsize - 1);
+ if (sscanf((char *) s, fmt, user, &acl, &n) != 2)
+ goto finish;
s += n;
- printf(" -{%s ", user);
+ printf(" -{");
+ fn_print((u_char *)user, NULL);
+ printf(" ");
ACLOUT(acl);
printf("}");
if (s > end)
- return;
+ goto finish;
}
+
+finish:
+ free(user);
+ return;
}
#undef ACLOUT
int cb_op;
unsigned long i;
- if (length <= sizeof(struct rx_header))
+ if (length <= (int)sizeof(struct rx_header))
return;
- if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) {
+ if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
goto trunc;
}
* gleaned from fsint/afscbint.xg
*/
- cb_op = ntohl(*((int *) (bp + sizeof(struct rx_header))));
+ cb_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
printf(" cb call %s", tok2str(cb_req, "op#%d", cb_op));
case 204: /* Callback */
{
unsigned long j, t;
- TRUNC(4);
- j = ntohl(*((int *) bp));
+ TCHECK2(bp[0], 4);
+ j = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
for (i = 0; i < j; i++) {
if (j == 0)
printf(" <none!>");
- j = ntohl(*((int *) bp));
+ j = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
if (j != 0)
INTOUT();
printf(" expires");
DATEOUT();
- TRUNC(4);
- t = ntohl(*((int *) bp));
+ TCHECK2(bp[0], 4);
+ t = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
tok2str(cb_types, "type %d", t);
}
{
struct rx_header *rxh;
- if (length <= sizeof(struct rx_header))
+ if (length <= (int)sizeof(struct rx_header))
return;
rxh = (struct rx_header *) bp;
* Print out the afs call we're invoking. The table used here was
* gleaned from fsint/afscbint.xg
*/
-
+
printf(" cb reply %s", tok2str(cb_req, "op#%d", opcode));
bp += sizeof(struct rx_header);
prot_print(register const u_char *bp, int length)
{
unsigned long i;
- char s[AFSNAMEMAX];
int pt_op;
- if (length <= sizeof(struct rx_header))
+ if (length <= (int)sizeof(struct rx_header))
return;
- if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) {
+ if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
goto trunc;
}
* gleaned from ptserver/ptint.xg
*/
- pt_op = ntohl(*((int *) (bp + sizeof(struct rx_header))));
+ pt_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
printf(" pt");
if (is_ubik(pt_op)) {
- ubik_print(bp, length);
+ ubik_print(bp);
return;
}
case 517: /* List owned */
case 518: /* Get CPS2 */
case 519: /* Get host CPS */
+ case 530: /* List super groups */
printf(" id");
INTOUT();
break;
case 504: /* Name to ID */
{
unsigned long j;
- TRUNC(4);
- j = ntohl(*((int *) bp));
+ TCHECK2(bp[0], 4);
+ j = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
/*
{
unsigned long j;
printf(" ids:");
- TRUNC(4);
- i = ntohl(*((int *) bp));
+ TCHECK2(bp[0], 4);
+ i = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
for (j = 0; j < i; j++)
INTOUT();
{
struct rx_header *rxh;
unsigned long i;
- char s[AFSNAMEMAX];
- if (length < sizeof(struct rx_header))
+ if (length < (int)sizeof(struct rx_header))
return;
rxh = (struct rx_header *) bp;
{
unsigned long j;
printf(" ids:");
- TRUNC(4);
- i = ntohl(*((int *) bp));
+ TCHECK2(bp[0], 4);
+ i = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
for (j = 0; j < i; j++)
INTOUT();
case 505: /* ID to name */
{
unsigned long j;
- TRUNC(4);
- j = ntohl(*((int *) bp));
+ TCHECK2(bp[0], 4);
+ j = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
/*
case 519: /* Get host CPS */
{
unsigned long j;
- TRUNC(4);
- j = ntohl(*((int *) bp));
+ TCHECK2(bp[0], 4);
+ j = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
for (i = 0; i < j; i++) {
INTOUT();
{
int vldb_op;
unsigned long i;
- char s[AFSNAMEMAX];
- if (length <= sizeof(struct rx_header))
+ if (length <= (int)sizeof(struct rx_header))
return;
- if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) {
+ if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
goto trunc;
}
* gleaned from vlserver/vldbint.xg
*/
- vldb_op = ntohl(*((int *) (bp + sizeof(struct rx_header))));
+ vldb_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
printf(" vldb");
if (is_ubik(vldb_op)) {
- ubik_print(bp, length);
+ ubik_print(bp);
return;
}
printf(" call %s", tok2str(vldb_req, "op#%d", vldb_op));
case 518: /* Get entry by ID N */
printf(" volid");
INTOUT();
- TRUNC(sizeof(int32_t));
- i = ntohl(*((int *) bp));
+ TCHECK2(bp[0], sizeof(int32_t));
+ i = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
if (i <= 2)
printf(" type %s", voltype[i]);
case 520: /* Replace entry N */
printf(" volid");
INTOUT();
- TRUNC(sizeof(int32_t));
- i = ntohl(*((int *) bp));
+ TCHECK2(bp[0], sizeof(int32_t));
+ i = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
if (i <= 2)
printf(" type %s", voltype[i]);
{
struct rx_header *rxh;
unsigned long i;
- char s[AFSNAMEMAX];
- if (length < sizeof(struct rx_header))
+ if (length < (int)sizeof(struct rx_header))
return;
rxh = (struct rx_header *) bp;
case 504: /* Get entry by name */
{ unsigned long nservers, j;
VECOUT(VLNAMEMAX);
- TRUNC(sizeof(int32_t));
+ TCHECK2(bp[0], sizeof(int32_t));
bp += sizeof(int32_t);
printf(" numservers");
- TRUNC(sizeof(int32_t));
- nservers = ntohl(*((int *) bp));
+ TCHECK2(bp[0], sizeof(int32_t));
+ nservers = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
printf(" %lu", nservers);
printf(" servers");
for (i = 0; i < 8; i++) {
- TRUNC(sizeof(int32_t));
+ TCHECK2(bp[0], sizeof(int32_t));
if (i < nservers)
printf(" %s",
- inet_ntoa(*((struct in_addr *) bp)));
+ intoa(((struct in_addr *) bp)->s_addr));
bp += sizeof(int32_t);
}
printf(" partitions");
for (i = 0; i < 8; i++) {
- TRUNC(sizeof(int32_t));
- j = ntohl(*((int *) bp));
+ TCHECK2(bp[0], sizeof(int32_t));
+ j = EXTRACT_32BITS(bp);
if (i < nservers && j <= 26)
printf(" %c", 'a' + (int)j);
else if (i < nservers)
printf(" %lu", j);
bp += sizeof(int32_t);
}
- TRUNC(8 * sizeof(int32_t));
+ TCHECK2(bp[0], 8 * sizeof(int32_t));
bp += 8 * sizeof(int32_t);
printf(" rwvol");
UINTOUT();
{ unsigned long nservers, j;
VECOUT(VLNAMEMAX);
printf(" numservers");
- TRUNC(sizeof(int32_t));
- nservers = ntohl(*((int *) bp));
+ TCHECK2(bp[0], sizeof(int32_t));
+ nservers = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
printf(" %lu", nservers);
printf(" servers");
for (i = 0; i < 13; i++) {
- TRUNC(sizeof(int32_t));
+ TCHECK2(bp[0], sizeof(int32_t));
if (i < nservers)
printf(" %s",
- inet_ntoa(*((struct in_addr *) bp)));
+ intoa(((struct in_addr *) bp)->s_addr));
bp += sizeof(int32_t);
}
printf(" partitions");
for (i = 0; i < 13; i++) {
- TRUNC(sizeof(int32_t));
- j = ntohl(*((int *) bp));
+ TCHECK2(bp[0], sizeof(int32_t));
+ j = EXTRACT_32BITS(bp);
if (i < nservers && j <= 26)
printf(" %c", 'a' + (int)j);
else if (i < nservers)
printf(" %lu", j);
bp += sizeof(int32_t);
}
- TRUNC(13 * sizeof(int32_t));
+ TCHECK2(bp[0], 13 * sizeof(int32_t));
bp += 13 * sizeof(int32_t);
printf(" rwvol");
UINTOUT();
{ unsigned long nservers, j;
VECOUT(VLNAMEMAX);
printf(" numservers");
- TRUNC(sizeof(int32_t));
- nservers = ntohl(*((int *) bp));
+ TCHECK2(bp[0], sizeof(int32_t));
+ nservers = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
printf(" %lu", nservers);
printf(" servers");
printf(" afsuuid");
AFSUUIDOUT();
} else {
- TRUNC(44);
+ TCHECK2(bp[0], 44);
bp += 44;
}
}
- TRUNC(4 * 13);
+ TCHECK2(bp[0], 4 * 13);
bp += 4 * 13;
printf(" partitions");
for (i = 0; i < 13; i++) {
- TRUNC(sizeof(int32_t));
- j = ntohl(*((int *) bp));
+ TCHECK2(bp[0], sizeof(int32_t));
+ j = EXTRACT_32BITS(bp);
if (i < nservers && j <= 26)
printf(" %c", 'a' + (int)j);
else if (i < nservers)
printf(" %lu", j);
bp += sizeof(int32_t);
}
- TRUNC(13 * sizeof(int32_t));
+ TCHECK2(bp[0], 13 * sizeof(int32_t));
bp += 13 * sizeof(int32_t);
printf(" rwvol");
UINTOUT();
default:
;
}
-
+
else {
/*
* Otherwise, just print out the return code
kauth_print(register const u_char *bp, int length)
{
int kauth_op;
- char s[AFSNAMEMAX];
- if (length <= sizeof(struct rx_header))
+ if (length <= (int)sizeof(struct rx_header))
return;
- if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) {
+ if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
goto trunc;
}
* gleaned from kauth/kauth.rg
*/
- kauth_op = ntohl(*((int *) (bp + sizeof(struct rx_header))));
+ kauth_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
printf(" kauth");
if (is_ubik(kauth_op)) {
- ubik_print(bp, length);
+ ubik_print(bp);
return;
}
INTOUT();
printf(" domain");
STROUT(KANAMEMAX);
- TRUNC(sizeof(int32_t));
- i = (int) ntohl(*((int *) bp));
+ TCHECK2(bp[0], sizeof(int32_t));
+ i = (int) EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
- TRUNC(i);
+ TCHECK2(bp[0], i);
bp += i;
printf(" principal");
STROUT(KANAMEMAX);
{
struct rx_header *rxh;
- if (length <= sizeof(struct rx_header))
+ if (length <= (int)sizeof(struct rx_header))
return;
rxh = (struct rx_header *) bp;
* Print out the afs call we're invoking. The table used here was
* gleaned from kauth/kauth.rg
*/
-
+
printf(" kauth");
if (is_ubik(opcode)) {
{
int vol_op;
- if (length <= sizeof(struct rx_header))
+ if (length <= (int)sizeof(struct rx_header))
return;
- if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) {
+ if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
goto trunc;
}
* gleaned from volser/volint.xg
*/
- vol_op = ntohl(*((int *) (bp + sizeof(struct rx_header))));
+ vol_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
printf(" vol call %s", tok2str(vol_req, "op#%d", vol_op));
- /*
- * Normally there would be a switch statement here to decode the
- * arguments to the AFS call, but since I don't have access to
- * an AFS server (yet) and I'm not an AFS admin, I can't
- * test any of these calls. Leave this blank for now.
- */
+ bp += sizeof(struct rx_header) + 4;
+ switch (vol_op) {
+ case 100: /* Create volume */
+ printf(" partition");
+ UINTOUT();
+ printf(" name");
+ STROUT(AFSNAMEMAX);
+ printf(" type");
+ UINTOUT();
+ printf(" parent");
+ UINTOUT();
+ break;
+ case 101: /* Delete volume */
+ case 107: /* Get flags */
+ printf(" trans");
+ UINTOUT();
+ break;
+ case 102: /* Restore */
+ printf(" totrans");
+ UINTOUT();
+ printf(" flags");
+ UINTOUT();
+ break;
+ case 103: /* Forward */
+ printf(" fromtrans");
+ UINTOUT();
+ printf(" fromdate");
+ DATEOUT();
+ DESTSERVEROUT();
+ printf(" desttrans");
+ INTOUT();
+ break;
+ case 104: /* End trans */
+ printf(" trans");
+ UINTOUT();
+ break;
+ case 105: /* Clone */
+ printf(" trans");
+ UINTOUT();
+ printf(" purgevol");
+ UINTOUT();
+ printf(" newtype");
+ UINTOUT();
+ printf(" newname");
+ STROUT(AFSNAMEMAX);
+ break;
+ case 106: /* Set flags */
+ printf(" trans");
+ UINTOUT();
+ printf(" flags");
+ UINTOUT();
+ break;
+ case 108: /* Trans create */
+ printf(" vol");
+ UINTOUT();
+ printf(" partition");
+ UINTOUT();
+ printf(" flags");
+ UINTOUT();
+ break;
+ case 109: /* Dump */
+ case 655537: /* Get size */
+ printf(" fromtrans");
+ UINTOUT();
+ printf(" fromdate");
+ DATEOUT();
+ break;
+ case 110: /* Get n-th volume */
+ printf(" index");
+ UINTOUT();
+ break;
+ case 111: /* Set forwarding */
+ printf(" tid");
+ UINTOUT();
+ printf(" newsite");
+ UINTOUT();
+ break;
+ case 112: /* Get name */
+ case 113: /* Get status */
+ printf(" tid");
+ break;
+ case 114: /* Signal restore */
+ printf(" name");
+ STROUT(AFSNAMEMAX);
+ printf(" type");
+ UINTOUT();
+ printf(" pid");
+ UINTOUT();
+ printf(" cloneid");
+ UINTOUT();
+ break;
+ case 116: /* List volumes */
+ printf(" partition");
+ UINTOUT();
+ printf(" flags");
+ UINTOUT();
+ break;
+ case 117: /* Set id types */
+ printf(" tid");
+ UINTOUT();
+ printf(" name");
+ STROUT(AFSNAMEMAX);
+ printf(" type");
+ UINTOUT();
+ printf(" pid");
+ UINTOUT();
+ printf(" clone");
+ UINTOUT();
+ printf(" backup");
+ UINTOUT();
+ break;
+ case 119: /* Partition info */
+ printf(" name");
+ STROUT(AFSNAMEMAX);
+ break;
+ case 120: /* Reclone */
+ printf(" tid");
+ UINTOUT();
+ break;
+ case 121: /* List one volume */
+ case 122: /* Nuke volume */
+ case 124: /* Extended List volumes */
+ case 125: /* Extended List one volume */
+ case 65536: /* Convert RO to RW volume */
+ printf(" partid");
+ UINTOUT();
+ printf(" volid");
+ UINTOUT();
+ break;
+ case 123: /* Set date */
+ printf(" tid");
+ UINTOUT();
+ printf(" date");
+ DATEOUT();
+ break;
+ case 126: /* Set info */
+ printf(" tid");
+ UINTOUT();
+ break;
+ case 128: /* Forward multiple */
+ printf(" fromtrans");
+ UINTOUT();
+ printf(" fromdate");
+ DATEOUT();
+ {
+ unsigned long i, j;
+ TCHECK2(bp[0], 4);
+ j = EXTRACT_32BITS(bp);
+ bp += sizeof(int32_t);
+ for (i = 0; i < j; i++) {
+ DESTSERVEROUT();
+ if (i != j - 1)
+ printf(",");
+ }
+ if (j == 0)
+ printf(" <none!>");
+ }
+ break;
+ case 65538: /* Dump version 2 */
+ printf(" fromtrans");
+ UINTOUT();
+ printf(" fromdate");
+ DATEOUT();
+ printf(" flags");
+ UINTOUT();
+ break;
+ default:
+ ;
+ }
return;
trunc:
{
struct rx_header *rxh;
- if (length <= sizeof(struct rx_header))
+ if (length <= (int)sizeof(struct rx_header))
return;
rxh = (struct rx_header *) bp;
* Print out the afs call we're invoking. The table used here was
* gleaned from volser/volint.xg
*/
-
+
printf(" vol reply %s", tok2str(vol_req, "op#%d", opcode));
bp += sizeof(struct rx_header);
* If it was a data packet, interpret the response.
*/
- if (rxh->type == RX_PACKET_TYPE_DATA)
- /* Well, no, not really. Leave this for later */
- ;
- else {
+ if (rxh->type == RX_PACKET_TYPE_DATA) {
+ switch (opcode) {
+ case 100: /* Create volume */
+ printf(" volid");
+ UINTOUT();
+ printf(" trans");
+ UINTOUT();
+ break;
+ case 104: /* End transaction */
+ UINTOUT();
+ break;
+ case 105: /* Clone */
+ printf(" newvol");
+ UINTOUT();
+ break;
+ case 107: /* Get flags */
+ UINTOUT();
+ break;
+ case 108: /* Transaction create */
+ printf(" trans");
+ UINTOUT();
+ break;
+ case 110: /* Get n-th volume */
+ printf(" volume");
+ UINTOUT();
+ printf(" partition");
+ UINTOUT();
+ break;
+ case 112: /* Get name */
+ STROUT(AFSNAMEMAX);
+ break;
+ case 113: /* Get status */
+ printf(" volid");
+ UINTOUT();
+ printf(" nextuniq");
+ UINTOUT();
+ printf(" type");
+ UINTOUT();
+ printf(" parentid");
+ UINTOUT();
+ printf(" clone");
+ UINTOUT();
+ printf(" backup");
+ UINTOUT();
+ printf(" restore");
+ UINTOUT();
+ printf(" maxquota");
+ UINTOUT();
+ printf(" minquota");
+ UINTOUT();
+ printf(" owner");
+ UINTOUT();
+ printf(" create");
+ DATEOUT();
+ printf(" access");
+ DATEOUT();
+ printf(" update");
+ DATEOUT();
+ printf(" expire");
+ DATEOUT();
+ printf(" backup");
+ DATEOUT();
+ printf(" copy");
+ DATEOUT();
+ break;
+ case 115: /* Old list partitions */
+ break;
+ case 116: /* List volumes */
+ case 121: /* List one volume */
+ {
+ unsigned long i, j;
+ TCHECK2(bp[0], 4);
+ j = EXTRACT_32BITS(bp);
+ bp += sizeof(int32_t);
+ for (i = 0; i < j; i++) {
+ printf(" name");
+ VECOUT(32);
+ printf(" volid");
+ UINTOUT();
+ printf(" type");
+ bp += sizeof(int32_t) * 21;
+ if (i != j - 1)
+ printf(",");
+ }
+ if (j == 0)
+ printf(" <none!>");
+ }
+ break;
+
+
+ default:
+ ;
+ }
+ } else {
/*
* Otherwise, just print out the return code
*/
bos_print(register const u_char *bp, int length)
{
int bos_op;
- char s[BOSNAMEMAX];
- if (length <= sizeof(struct rx_header))
+ if (length <= (int)sizeof(struct rx_header))
return;
- if (snapend - bp + 1 <= sizeof(struct rx_header) + sizeof(int32_t)) {
+ if (snapend - bp + 1 <= (int)(sizeof(struct rx_header) + sizeof(int32_t))) {
goto trunc;
}
* gleaned from bozo/bosint.xg
*/
- bos_op = ntohl(*((int *) (bp + sizeof(struct rx_header))));
+ bos_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
printf(" bos call %s", tok2str(bos_req, "op#%d", bos_op));
{
struct rx_header *rxh;
- if (length <= sizeof(struct rx_header))
+ if (length <= (int)sizeof(struct rx_header))
return;
rxh = (struct rx_header *) bp;
* Print out the afs call we're invoking. The table used here was
* gleaned from volser/volint.xg
*/
-
+
printf(" bos reply %s", tok2str(bos_req, "op#%d", opcode));
bp += sizeof(struct rx_header);
*/
static void
-ubik_print(register const u_char *bp, int length)
+ubik_print(register const u_char *bp)
{
int ubik_op;
int32_t temp;
* gleaned from ubik/ubik_int.xg
*/
- ubik_op = ntohl(*((int *) (bp + sizeof(struct rx_header))));
+ ubik_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
printf(" ubik call %s", tok2str(ubik_req, "op#%d", ubik_op));
switch (ubik_op) {
case 10000: /* Beacon */
- TRUNC(4);
- temp = ntohl(*((int *) bp));
+ TCHECK2(bp[0], 4);
+ temp = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
printf(" syncsite %s", temp ? "yes" : "no");
printf(" votestart");
INTOUT();
printf(" length");
INTOUT();
- temp = ntohl(*((int *) bp));
+ temp = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
tok2str(ubik_lock_types, "type %d", temp);
break;
{
struct rx_header *rxh;
- if (length < sizeof(struct rx_header))
+ if (length < (int)sizeof(struct rx_header))
return;
rxh = (struct rx_header *) bp;
/*
* If it was a data packet, print out the arguments to the Ubik calls
*/
-
+
if (rxh->type == RX_PACKET_TYPE_DATA)
switch (opcode) {
case 10000: /* Beacon */
default:
;
}
-
+
/*
* Otherwise, print out "yes" it it was a beacon packet (because
* that's how yes votes are returned, go figure), otherwise
trunc:
printf(" [|ubik]");
}
+
+/*
+ * Handle RX ACK packets.
+ */
+
+static void
+rx_ack_print(register const u_char *bp, int length)
+{
+ struct rx_ackPacket *rxa;
+ int i, start, last;
+ u_int32_t firstPacket;
+
+ if (length < (int)sizeof(struct rx_header))
+ return;
+
+ bp += sizeof(struct rx_header);
+
+ /*
+ * This may seem a little odd .... the rx_ackPacket structure
+ * contains an array of individual packet acknowledgements
+ * (used for selective ack/nack), but since it's variable in size,
+ * we don't want to truncate based on the size of the whole
+ * rx_ackPacket structure.
+ */
+
+ TCHECK2(bp[0], sizeof(struct rx_ackPacket) - RX_MAXACKS);
+
+ rxa = (struct rx_ackPacket *) bp;
+ bp += (sizeof(struct rx_ackPacket) - RX_MAXACKS);
+
+ /*
+ * Print out a few useful things from the ack packet structure
+ */
+
+ if (vflag > 2)
+ printf(" bufspace %d maxskew %d",
+ (int) EXTRACT_16BITS(&rxa->bufferSpace),
+ (int) EXTRACT_16BITS(&rxa->maxSkew));
+
+ firstPacket = EXTRACT_32BITS(&rxa->firstPacket);
+ printf(" first %d serial %d reason %s",
+ firstPacket, EXTRACT_32BITS(&rxa->serial),
+ tok2str(rx_ack_reasons, "#%d", (int) rxa->reason));
+
+ /*
+ * Okay, now we print out the ack array. The way _this_ works
+ * is that we start at "first", and step through the ack array.
+ * If we have a contiguous range of acks/nacks, try to
+ * collapse them into a range.
+ *
+ * If you're really clever, you might have noticed that this
+ * doesn't seem quite correct. Specifically, due to structure
+ * padding, sizeof(struct rx_ackPacket) - RX_MAXACKS won't actually
+ * yield the start of the ack array (because RX_MAXACKS is 255
+ * and the structure will likely get padded to a 2 or 4 byte
+ * boundary). However, this is the way it's implemented inside
+ * of AFS - the start of the extra fields are at
+ * sizeof(struct rx_ackPacket) - RX_MAXACKS + nAcks, which _isn't_
+ * the exact start of the ack array. Sigh. That's why we aren't
+ * using bp, but instead use rxa->acks[]. But nAcks gets added
+ * to bp after this, so bp ends up at the right spot. Go figure.
+ */
+
+ if (rxa->nAcks != 0) {
+
+ TCHECK2(bp[0], rxa->nAcks);
+
+ /*
+ * Sigh, this is gross, but it seems to work to collapse
+ * ranges correctly.
+ */
+
+ for (i = 0, start = last = -2; i < rxa->nAcks; i++)
+ if (rxa->acks[i] == RX_ACK_TYPE_ACK) {
+
+ /*
+ * I figured this deserved _some_ explanation.
+ * First, print "acked" and the packet seq
+ * number if this is the first time we've
+ * seen an acked packet.
+ */
+
+ if (last == -2) {
+ printf(" acked %d",
+ firstPacket + i);
+ start = i;
+ }
+
+ /*
+ * Otherwise, if the there is a skip in
+ * the range (such as an nacked packet in
+ * the middle of some acked packets),
+ * then print the current packet number
+ * seperated from the last number by
+ * a comma.
+ */
+
+ else if (last != i - 1) {
+ printf(",%d", firstPacket + i);
+ start = i;
+ }
+
+ /*
+ * We always set last to the value of
+ * the last ack we saw. Conversely, start
+ * is set to the value of the first ack
+ * we saw in a range.
+ */
+
+ last = i;
+
+ /*
+ * Okay, this bit a code gets executed when
+ * we hit a nack ... in _this_ case we
+ * want to print out the range of packets
+ * that were acked, so we need to print
+ * the _previous_ packet number seperated
+ * from the first by a dash (-). Since we
+ * already printed the first packet above,
+ * just print the final packet. Don't
+ * do this if there will be a single-length
+ * range.
+ */
+ } else if (last == i - 1 && start != last)
+ printf("-%d", firstPacket + i - 1);
+
+ /*
+ * So, what's going on here? We ran off the end of the
+ * ack list, and if we got a range we need to finish it up.
+ * So we need to determine if the last packet in the list
+ * was an ack (if so, then last will be set to it) and
+ * we need to see if the last range didn't start with the
+ * last packet (because if it _did_, then that would mean
+ * that the packet number has already been printed and
+ * we don't need to print it again).
+ */
+
+ if (last == i - 1 && start != last)
+ printf("-%d", firstPacket + i - 1);
+
+ /*
+ * Same as above, just without comments
+ */
+
+ for (i = 0, start = last = -2; i < rxa->nAcks; i++)
+ if (rxa->acks[i] == RX_ACK_TYPE_NACK) {
+ if (last == -2) {
+ printf(" nacked %d",
+ firstPacket + i);
+ start = i;
+ } else if (last != i - 1) {
+ printf(",%d", firstPacket + i);
+ start = i;
+ }
+ last = i;
+ } else if (last == i - 1 && start != last)
+ printf("-%d", firstPacket + i - 1);
+
+ if (last == i - 1 && start != last)
+ printf("-%d", firstPacket + i - 1);
+
+ bp += rxa->nAcks;
+ }
+
+
+ /*
+ * These are optional fields; depending on your version of AFS,
+ * you may or may not see them
+ */
+
+#define TRUNCRET(n) if (snapend - bp + 1 <= n) return;
+
+ if (vflag > 1) {
+ TRUNCRET(4);
+ printf(" ifmtu");
+ INTOUT();
+
+ TRUNCRET(4);
+ printf(" maxmtu");
+ INTOUT();
+
+ TRUNCRET(4);
+ printf(" rwind");
+ INTOUT();
+
+ TRUNCRET(4);
+ printf(" maxpackets");
+ INTOUT();
+ }
+
+ return;
+
+trunc:
+ printf(" [|ack]");
+}
+#undef TRUNCRET