From ace14a2b50f2cc05c079d0b9137b49066dbb1206 Mon Sep 17 00:00:00 2001 From: fenner Date: Tue, 3 Apr 2001 07:45:48 +0000 Subject: Virgin import of tcpdump.org tcpdump v3.6.2 --- contrib/tcpdump/print-rx.c | 611 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 473 insertions(+), 138 deletions(-) (limited to 'contrib/tcpdump/print-rx.c') diff --git a/contrib/tcpdump/print-rx.c b/contrib/tcpdump/print-rx.c index 5f42ce7..aa36124 100644 --- a/contrib/tcpdump/print-rx.c +++ b/contrib/tcpdump/print-rx.c @@ -13,7 +13,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/print-rx.c,v 1.5.2.1 2000/01/11 06:58:27 fenner Exp $"; + "@(#) $Header: /tcpdump/master/tcpdump/print-rx.c,v 1.20 2001/01/10 08:12:01 fenner Exp $"; #endif #ifdef HAVE_CONFIG_H @@ -21,24 +21,27 @@ static const char rcsid[] = #endif #include +#include #include +#include #include #include #include #include #include -#include -#include #include #include "interface.h" #include "addrtoname.h" +#include "extract.h" #undef NOERROR /* Solaris sucks */ #include #include "rx.h" +#include "ip.h" + static struct tok rx_types[] = { { RX_PACKET_TYPE_DATA, "data" }, { RX_PACKET_TYPE_ACK, "ack" }, @@ -315,6 +318,39 @@ static struct tok ubik_lock_types[] = { static char *voltype[] = { "read-write", "read-only", "backup" }; +static struct tok afs_fs_errors[] = { + { 101, "salvage volume" }, + { 102, "no such vnode" }, + { 103, "no such volume" }, + { 104, "volume exist" }, + { 105, "no service" }, + { 106, "volume offline" }, + { 107, "voline online" }, + { 108, "diskfull" }, + { 109, "diskquota exceeded" }, + { 110, "volume busy" }, + { 111, "volume moved" }, + { 112, "AFS IO error" }, + { -100, "restarting fileserver" }, + { 0, NULL } +}; + +/* + * Reasons for acknowledging a packet + */ + +static 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" }, + { 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. @@ -339,9 +375,10 @@ 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 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); @@ -357,6 +394,8 @@ 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); +static void rx_ack_print(const u_char *, int); + static int is_ubik(u_int32_t); /* @@ -381,28 +420,35 @@ rx_print(register const u_char *bp, int length, int sport, int dport, 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].v) { + if (!firstflag) { + firstflag = 1; + printf(" "); + } else { + printf(","); + } + printf("<%s>", rx_flags[i].s); } - printf("<%s>", rx_flags[i].s); } - } } /* @@ -414,7 +460,10 @@ rx_print(register const u_char *bp, int length, int sport, int dport, * as well. */ - if (rxh->type == RX_PACKET_TYPE_DATA && ntohl(rxh->seq) == 1 && + 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) { /* @@ -458,7 +507,7 @@ rx_print(register const u_char *bp, int length, int sport, int dport, */ } 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, @@ -489,7 +538,15 @@ rx_print(register const u_char *bp, int length, int sport, int dport, 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); @@ -519,7 +576,7 @@ rx_cache_insert(const u_char *bp, const struct ip *ip, int dport, 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)); } /* @@ -567,46 +624,45 @@ rx_cache_find(const struct rx_header *rxh, const struct ip *ip, int sport, * 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)); \ + TCHECK2(bp[0], sizeof(int32_t)); \ + i = (int) EXTRACT_32BITS(bp); \ bp += sizeof(int32_t); \ - TRUNC(i); \ - strncpy(s, bp, min(MAX, i)); \ + TCHECK2(bp[0], i); \ + strncpy(s, (char *) bp, min(MAX, i)); \ s[i] = '\0'; \ printf(" \"%s\"", s); \ 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 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); \ @@ -614,45 +670,45 @@ rx_cache_find(const struct rx_header *rxh, const struct ip *ip, int sport, } #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(); } \ else bp += sizeof(int32_t); \ - i = ntohl(*((int *) bp)); bp += sizeof(int32_t); \ + i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \ if (mask & 2) printf(" owner %lu", i); \ - i = ntohl(*((int32_t *) bp)); bp += sizeof(int32_t); \ + i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \ if (mask & 4) printf(" group %lu", i); \ - i = ntohl(*((int32_t *) bp)); bp += sizeof(int32_t); \ + i = EXTRACT_32BITS(bp); bp += sizeof(int32_t); \ if (mask & 8) printf(" mode %lo", i & 07777); \ - i = ntohl(*((int32_t *) bp)); bp += sizeof(int32_t); \ + 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"); \ } #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); \ } \ @@ -664,21 +720,90 @@ rx_cache_find(const struct rx_header *rxh, const struct ip *ip, int sport, #define VECOUT(MAX) { char *sp; \ int k; \ - TRUNC(MAX * sizeof(int32_t)); \ + TCHECK2(bp[0], MAX * sizeof(int32_t)); \ sp = s; \ for (k = 0; k < MAX; k++) { \ - *sp++ = (char) ntohl(*((int *) bp)); \ + *sp++ = (char) EXTRACT_32BITS(bp); \ bp += sizeof(int32_t); \ } \ s[MAX] = '\0'; \ printf(" \"%s\"", s); \ } +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; @@ -697,7 +822,7 @@ fs_print(register const u_char *bp, int length) * 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)); @@ -746,15 +871,16 @@ fs_print(register const u_char *bp, int length) 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 */ @@ -803,8 +929,8 @@ fs_print(register const u_char *bp, int length) case 155: /* 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++) { @@ -854,18 +980,19 @@ fs_reply_print(register const u_char *bp, int length, int32_t opcode) * If it was a data packet, interpret the response */ - if (rxh->type == RX_PACKET_TYPE_DATA) + if (rxh->type == RX_PACKET_TYPE_DATA) { 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 */ @@ -883,12 +1010,19 @@ fs_reply_print(register const u_char *bp, int length, int32_t opcode) default: ; } - else { - /* - * Otherwise, just print out the return code - */ - printf(" errcode"); - INTOUT(); + } else if (rxh->type == RX_PACKET_TYPE_ABORT) { + int i; + + /* + * 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 { + printf(" strange fs reply of type %d", rxh->type); } return; @@ -912,19 +1046,22 @@ trunc: */ 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 @@ -948,25 +1085,29 @@ acl_print(u_char *s, u_char *end) 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); 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); ACLOUT(acl); printf("}"); if (s > end) - return; + goto finish; } + +finish: + free(user); + return; } #undef ACLOUT @@ -993,7 +1134,7 @@ cb_print(register const u_char *bp, int length) * 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)); @@ -1008,8 +1149,8 @@ cb_print(register const u_char *bp, int length) 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++) { @@ -1021,7 +1162,7 @@ cb_print(register const u_char *bp, int length) if (j == 0) printf(" "); - j = ntohl(*((int *) bp)); + j = EXTRACT_32BITS(bp); bp += sizeof(int32_t); if (j != 0) @@ -1032,8 +1173,8 @@ cb_print(register const u_char *bp, int length) 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); } @@ -1125,7 +1266,7 @@ prot_print(register const u_char *bp, int length) * 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"); @@ -1176,8 +1317,8 @@ prot_print(register const u_char *bp, int length) 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); /* @@ -1198,8 +1339,8 @@ prot_print(register const u_char *bp, int length) { 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(); @@ -1288,8 +1429,8 @@ prot_reply_print(register const u_char *bp, int length, int32_t opcode) { 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(); @@ -1300,8 +1441,8 @@ prot_reply_print(register const u_char *bp, int length, int32_t opcode) 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); /* @@ -1325,8 +1466,8 @@ prot_reply_print(register const u_char *bp, int length, int32_t opcode) 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(); @@ -1381,7 +1522,7 @@ vldb_print(register const u_char *bp, int length) * 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"); @@ -1410,8 +1551,8 @@ vldb_print(register const u_char *bp, int length) 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]); @@ -1430,8 +1571,8 @@ vldb_print(register const u_char *bp, int length) 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]); @@ -1500,16 +1641,16 @@ vldb_reply_print(register const u_char *bp, int length, int32_t opcode) 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))); @@ -1517,15 +1658,15 @@ vldb_reply_print(register const u_char *bp, int length, int32_t opcode) } 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(); @@ -1550,13 +1691,13 @@ vldb_reply_print(register const u_char *bp, int length, int32_t opcode) { 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))); @@ -1564,15 +1705,15 @@ vldb_reply_print(register const u_char *bp, int length, int32_t opcode) } 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(); @@ -1587,8 +1728,8 @@ vldb_reply_print(register const u_char *bp, int length, int32_t opcode) { 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"); @@ -1597,23 +1738,23 @@ vldb_reply_print(register const u_char *bp, int length, int32_t opcode) 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(); @@ -1662,7 +1803,7 @@ kauth_print(register const u_char *bp, int length) * 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"); @@ -1703,10 +1844,10 @@ kauth_print(register const u_char *bp, int length) 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); @@ -1806,7 +1947,7 @@ vol_print(register const u_char *bp, int length) * 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)); @@ -1889,7 +2030,7 @@ bos_print(register const u_char *bp, int length) * 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)); @@ -2032,7 +2173,7 @@ ubik_print(register const u_char *bp, int length) * 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)); @@ -2044,8 +2185,8 @@ ubik_print(register const u_char *bp, int length) 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"); @@ -2076,7 +2217,7 @@ ubik_print(register const u_char *bp, int length) INTOUT(); printf(" length"); INTOUT(); - temp = ntohl(*((int *) bp)); + temp = EXTRACT_32BITS(bp); bp += sizeof(int32_t); tok2str(ubik_lock_types, "type %d", temp); break; @@ -2188,3 +2329,197 @@ ubik_reply_print(register const u_char *bp, int length, int32_t opcode) 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; + + if (length < 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)); + + printf(" first %d serial %d reason %s", + EXTRACT_32BITS(&rxa->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", + rxa->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", rxa->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", rxa->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", rxa->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", + rxa->firstPacket + i); + start = i; + } else if (last != i - 1) { + printf(",%d", rxa->firstPacket + i); + start = i; + } + last = i; + } else if (last == i - 1 && start != last) + printf("-%d", rxa->firstPacket + i - 1); + + if (last == i - 1 && start != last) + printf("-%d", rxa->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 -- cgit v1.1