+/*
+ * 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.9 2000-02-09 16:00:50 kenh Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-rx.c,v 1.29 2002-04-30 06:45:08 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
#endif
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#ifdef TIME_WITH_SYS_TIME
+#include <time.h>
+#endif
#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 "interface.h"
#include "addrtoname.h"
#include "extract.h"
-#undef NOERROR /* Solaris sucks */
-#include <arpa/nameser.h>
-
#include "rx.h"
+#include "ip.h"
+
static struct tok rx_types[] = {
{ RX_PACKET_TYPE_DATA, "data" },
{ RX_PACKET_TYPE_ACK, "ack" },
{ 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 double_tok {
+ int flag; /* Rx flag */
+ int packetType; /* Packet type */
+ 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[] = {
{ 161, "dfs-lookup" },
{ 162, "dfs-flushcps" },
{ 163, "dfs-symlink" },
+ { 220, "residency" },
{ 0, NULL },
};
{ 212, "whoareyou" },
{ 213, "initcb3" },
{ 214, "probeuuid" },
+ { 215, "getsrvprefs" },
+ { 216, "getcellservdb" },
+ { 217, "getlocalcell" },
+ { 218, "getcacheconf" },
{ 0, NULL },
};
{ 518, "get-cps2" },
{ 519, "get-host-cps" },
{ 520, "update-entry" },
+ { 521, "list-entries" },
{ 0, NULL },
};
{ 531, "linked-list-u" },
{ 532, "regaddr" },
{ 533, "get-addrs-u" },
+ { 534, "list-attrib-n2" },
{ 0, NULL },
};
{ 112, "start-bozo-log" },
{ 113, "wait-all" },
{ 114, "get-instance-strings" },
+ { 115, "get-restricted" },
+ { 116, "set-restricted" },
{ 0, NULL },
};
static int rx_cache_find(const struct rx_header *, const struct ip *,
int, int32_t *);
+static void ack_print(const u_char *, int);
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);
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) EXTRACT_32BITS(&rxh->cid),
- (int) EXTRACT_32BITS(&rxh->callNumber),
+
+ 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,
EXTRACT_16BITS(&rxh->serviceId));
- for (i = 0; i < NUM_RX_FLAGS; i++) {
- if (rxh->flags & rx_flags[i].v) {
- if (!firstflag) {
- firstflag = 1;
- printf(" ");
- } else {
- printf(",");
+
+ 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 &&
+ if (rxh->type == RX_PACKET_TYPE_ACK)
+ ack_print(bp, length);
+ else if (rxh->type == RX_PACKET_TYPE_DATA &&
EXTRACT_32BITS(&rxh->seq) == 1 &&
rxh->flags & RX_CLIENT_INITIATED) {
* 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); \
+ TCHECK2(bp[0], sizeof(int32_t) * 3); \
n1 = EXTRACT_32BITS(bp); \
bp += sizeof(int32_t); \
n2 = EXTRACT_32BITS(bp); \
printf(" fid %d/%d/%d", (int) n1, (int) n2, (int) n3); \
}
-#define STROUT(MAX) { int i; \
- TRUNC(sizeof(int32_t)); \
- i = (int) EXTRACT_32BITS(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, (char *) 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)); \
+ 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)); \
+ TCHECK2(bp[0], sizeof(int32_t)); \
i = EXTRACT_32BITS(bp); \
bp += sizeof(int32_t); \
printf(" %lu", i); \
}
#define DATEOUT() { time_t t; struct tm *tm; char str[256]; \
- TRUNC(sizeof(int32_t)); \
+ TCHECK2(bp[0], sizeof(int32_t)); \
t = (time_t) EXTRACT_32BITS(bp); \
bp += sizeof(int32_t); \
tm = localtime(&t); \
}
#define STOREATTROUT() { unsigned long mask, i; \
- TRUNC((sizeof(int32_t)*6)); \
+ 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(); } \
}
#define UBIK_VERSIONOUT() {int32_t epoch; int32_t counter; \
- TRUNC(sizeof(int32_t) * 2); \
+ TCHECK2(bp[0], sizeof(int32_t) * 2); \
epoch = EXTRACT_32BITS(bp); \
bp += sizeof(int32_t); \
counter = EXTRACT_32BITS(bp); \
}
#define AFSUUIDOUT() {u_int32_t temp; int i; \
- TRUNC(11*sizeof(u_int32_t)); \
+ TCHECK2(bp[0], 11*sizeof(u_int32_t)); \
temp = EXTRACT_32BITS(bp); \
bp += sizeof(u_int32_t); \
printf(" %08x", 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) EXTRACT_32BITS(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("\""); \
}
+static void
+ack_print(register const u_char *bp, int length)
+{
+ u_char nAcks;
+ int i;
+
+ if (vflag <= 1)
+ return;
+
+ if (length <= sizeof(struct rx_header))
+ return;
+
+ bp += sizeof(struct rx_header);
+
+ /*
+ * Packets < firstPacket are implicitly acknowledged and may
+ * be discarded by the sender.
+ *
+ * Packets >= firstPacket+nAcks are implicitly NOT acknowledged.
+ *
+ * No packets with sequence numbers >= firstPacket should be
+ * discarded by the sender (they may thrown out at any time by
+ * the receiver)
+ */
+#define RX_ACK_REASONS "RDOXSprn"
+ /* Requested, Duplicate, Out_of_sequence, eXceeds_window, no_Space,
+ * Ping, ping_Response, No_{progress, particular_reason}.
+ */
+#if 0
+ struct rx_ackPacket {
+ u_short bufferSpace; /* Skip! */
+ u_short maxSkew; /* Skip! */
+ u_long firstPacket;
+ u_long previousPacket; /* Obsolete! */
+ u_long serial; /* Serial that prompted the ack, */
+ u_char reason; /* and the reason why. */
+ u_char nAcks;
+ u_char acks[RX_MAXACKS]; /* Selective acks (not a bitmap). */
+ };
+#endif
+#define RX_ACK_TYPE_NACK 0
+
+ TCHECK2(bp[0], 8); /* bufferSpace and maxSkew */
+ bp += 4;
+ printf(" fir %u", (unsigned)EXTRACT_32BITS(bp));
+ bp += 4;
+ TCHECK2(bp[0], 8); /* previousPacket and serial */
+ bp += 4;
+ printf(" %u", (unsigned)EXTRACT_32BITS(bp));
+ bp += 4;
+ TCHECK2(bp[0], 1);
+ printf("%c", RX_ACK_REASONS[(*bp - 1) & 07u]);
+ bp += 1; /* reason */
+ TCHECK2(bp[0], 1);
+ nAcks = *bp;
+ bp += 1; /* nAcks */
+
+ for (i = 0; i < nAcks; i++) {
+ TCHECK2(bp[0], 1);
+ putchar(*bp == RX_ACK_TYPE_NACK? '-' : '*');
+ bp += 1;
+ }
+
+ return;
+
+trunc:
+ printf(" [|ack]");
+}
+
/*
* 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))
return;
break;
case 134: /* Store ACL */
{
- char a[AFSOPAQUEMAX];
+ char a[AFSOPAQUEMAX+1];
FIDOUT();
- TRUNC(4);
+ TCHECK2(bp[0], 4);
i = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
- TRUNC(i);
- strncpy(a, (char *) 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 */
case 155: /* Bulk stat */
{
unsigned long j;
- TRUNC(4);
+ TCHECK2(bp[0], 4);
j = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
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))
switch (opcode) {
case 131: /* Fetch ACL */
{
- char a[AFSOPAQUEMAX];
- TRUNC(4);
+ char a[AFSOPAQUEMAX+1];
+ TCHECK2(bp[0], 4);
i = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
- TRUNC(i);
- strncpy(a, (char *) 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 */
/*
* Otherwise, just print out the return code
*/
- TRUNC(sizeof(int32_t));
+ TCHECK2(bp[0], sizeof(int32_t));
i = (int) EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
*/
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;
- 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
for (i = 0; i < pos; i++) {
if (sscanf((char *) s, "%s %d\n%n", user, &acl, &n) != 2)
- return;
+ 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;
+ 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
case 204: /* Callback */
{
unsigned long j, t;
- TRUNC(4);
+ TCHECK2(bp[0], 4);
j = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
INTOUT();
printf(" expires");
DATEOUT();
- TRUNC(4);
+ TCHECK2(bp[0], 4);
t = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
tok2str(cb_types, "type %d", t);
prot_print(register const u_char *bp, int length)
{
unsigned long i;
- char s[AFSNAMEMAX];
int pt_op;
if (length <= sizeof(struct rx_header))
case 504: /* Name to ID */
{
unsigned long j;
- TRUNC(4);
+ TCHECK2(bp[0], 4);
j = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
{
unsigned long j;
printf(" ids:");
- TRUNC(4);
+ TCHECK2(bp[0], 4);
i = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
for (j = 0; j < i; j++)
{
struct rx_header *rxh;
unsigned long i;
- char s[AFSNAMEMAX];
if (length < sizeof(struct rx_header))
return;
{
unsigned long j;
printf(" ids:");
- TRUNC(4);
+ TCHECK2(bp[0], 4);
i = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
for (j = 0; j < i; j++)
case 505: /* ID to name */
{
unsigned long j;
- TRUNC(4);
+ TCHECK2(bp[0], 4);
j = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
case 519: /* Get host CPS */
{
unsigned long j;
- TRUNC(4);
+ TCHECK2(bp[0], 4);
j = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
for (i = 0; i < j; i++) {
{
int vldb_op;
unsigned long i;
- char s[AFSNAMEMAX];
if (length <= sizeof(struct rx_header))
return;
case 518: /* Get entry by ID N */
printf(" volid");
INTOUT();
- TRUNC(sizeof(int32_t));
+ TCHECK2(bp[0], sizeof(int32_t));
i = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
if (i <= 2)
case 520: /* Replace entry N */
printf(" volid");
INTOUT();
- TRUNC(sizeof(int32_t));
+ TCHECK2(bp[0], sizeof(int32_t));
i = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
if (i <= 2)
{
struct rx_header *rxh;
unsigned long i;
- char s[AFSNAMEMAX];
if (length < sizeof(struct rx_header))
return;
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));
+ 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)));
}
printf(" partitions");
for (i = 0; i < 8; i++) {
- TRUNC(sizeof(int32_t));
+ TCHECK2(bp[0], sizeof(int32_t));
j = EXTRACT_32BITS(bp);
if (i < nservers && j <= 26)
printf(" %c", 'a' + (int)j);
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));
+ 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)));
}
printf(" partitions");
for (i = 0; i < 13; i++) {
- TRUNC(sizeof(int32_t));
+ TCHECK2(bp[0], sizeof(int32_t));
j = EXTRACT_32BITS(bp);
if (i < nservers && j <= 26)
printf(" %c", 'a' + (int)j);
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));
+ TCHECK2(bp[0], sizeof(int32_t));
nservers = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
printf(" %lu", nservers);
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));
+ TCHECK2(bp[0], sizeof(int32_t));
j = EXTRACT_32BITS(bp);
if (i < nservers && j <= 26)
printf(" %c", 'a' + (int)j);
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();
kauth_print(register const u_char *bp, int length)
{
int kauth_op;
- char s[AFSNAMEMAX];
if (length <= sizeof(struct rx_header))
return;
INTOUT();
printf(" domain");
STROUT(KANAMEMAX);
- TRUNC(sizeof(int32_t));
+ 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);
bos_print(register const u_char *bp, int length)
{
int bos_op;
- char s[BOSNAMEMAX];
if (length <= sizeof(struct rx_header))
return;
switch (ubik_op) {
case 10000: /* Beacon */
- TRUNC(4);
+ TCHECK2(bp[0], 4);
temp = EXTRACT_32BITS(bp);
bp += sizeof(int32_t);
printf(" syncsite %s", temp ? "yes" : "no");
* Handle RX ACK packets.
*/
-void
+static void
rx_ack_print(register const u_char *bp, int length)
{
struct rx_ackPacket *rxa;
* rx_ackPacket structure.
*/
- TRUNC(sizeof(struct rx_ackPacket) - RX_MAXACKS);
+ TCHECK2(bp[0], sizeof(struct rx_ackPacket) - RX_MAXACKS);
rxa = (struct rx_ackPacket *) bp;
bp += (sizeof(struct rx_ackPacket) - RX_MAXACKS);
if (rxa->nAcks != 0) {
- TRUNC(rxa->nAcks);
+ TCHECK2(bp[0], rxa->nAcks);
/*
* Sigh, this is gross, but it seems to work to collapse
* the _previous_ packet number seperated
* from the first by a dash (-). Since we
* already printed the first packet above,
- * just print the final packet.
+ * just print the final packet. Don't
+ * do this if there will be a single-length
+ * range.
*/
- } else if (last == i - 1)
+ } else if (last == i - 1 && start != last)
printf("-%d", rxa->firstPacket + i - 1);
/*
start = i;
}
last = i;
- } else if (last == i - 1)
+ } else if (last == i - 1 && start != last)
printf("-%d", rxa->firstPacket + i - 1);
if (last == i - 1 && start != last)