#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-pgm.c,v 1.2 2005-05-23 21:38:06 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-pgm.c,v 1.5 2005-06-07 22:05:58 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
#include "addrtoname.h"
#include "ip.h"
+#ifdef INET6
#include "ip6.h"
+#endif
#include "ipproto.h"
/*
u_int32_t pgms_leadseq;
u_int16_t pgms_nla_afi;
u_int16_t pgms_reserved;
- u_int8_t pgms_nla[0];
+ /* ... u_int8_t pgms_nla[0]; */
/* ... options */
};
u_int32_t pgmn_seq;
u_int16_t pgmn_source_afi;
u_int16_t pgmn_reserved;
- u_int8_t pgmn_source[0];
+ /* ... u_int8_t pgmn_source[0]; */
/* ... u_int16_t pgmn_group_afi */
/* ... u_int16_t pgmn_reserved2; */
/* ... u_int8_t pgmn_group[0]; */
/* ... options */
};
+struct pgm_ack {
+ u_int32_t pgma_rx_max_seq;
+ u_int32_t pgma_bitmap;
+ /* ... options */
+};
+
struct pgm_poll {
u_int32_t pgmp_seq;
u_int16_t pgmp_round;
u_int16_t pgmp_subtype;
u_int16_t pgmp_nla_afi;
u_int16_t pgmp_reserved;
- u_int8_t pgmp_nla[0];
+ /* ... u_int8_t pgmp_nla[0]; */
/* ... options */
};
#define PGM_OPT_RST 0x0F
#define PGM_OPT_CR 0x10
#define PGM_OPT_CRQST 0x11
+
+#define PGM_OPT_PGMCC_DATA 0x12
+#define PGM_OPT_PGMCC_FEEDBACK 0x13
#define PGM_OPT_MASK 0x7f
int addr_size;
const void *nla;
int nla_af;
- char nla_buf[INET6_ADDRSTRLEN];
#ifdef INET6
+ char nla_buf[INET6_ADDRSTRLEN];
register const struct ip6_hdr *ip6;
+#else
+ char nla_buf[INET_ADDRSTRLEN];
#endif
u_int8_t opt_type, opt_len, flags1, flags2;
u_int32_t seq, opts_len, len, offset;
ip6 = (struct ip6_hdr *)bp2;
else
ip6 = NULL;
-#endif /*INET6*/
+#else /* INET6 */
+ if (IP_V(ip) == 6) {
+ (void)printf("Can't handle IPv6");
+ return;
+ }
+#endif /* INET6 */
ch = '\0';
if (!TTEST(pgm->pgm_dport)) {
#ifdef INET6
addr_size = sizeof(struct in_addr);
nla_af = AF_INET;
break;
+#ifdef INET6
case AFI_IP6:
addr_size = sizeof(struct in6_addr);
nla_af = AF_INET6;
break;
+#endif
default:
goto trunc;
break;
(void)printf("POLL seq %u round %u",
EXTRACT_32BITS(&poll->pgmp_seq),
EXTRACT_16BITS(&poll->pgmp_round));
+ bp = (u_char *) (poll + 1);
break;
}
case PGM_POLR: {
addr_size = sizeof(struct in_addr);
nla_af = AF_INET;
break;
+#ifdef INET6
case AFI_IP6:
addr_size = sizeof(struct in6_addr);
nla_af = AF_INET6;
break;
+#endif
default:
goto trunc;
break;
inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf));
TCHECK2(*bp, sizeof(u_int32_t));
- ivl = EXTRACT_32BITS(*(u_int32_t *)bp);
+ ivl = EXTRACT_32BITS(bp);
bp += sizeof(u_int32_t);
TCHECK2(*bp, sizeof(u_int32_t));
- rnd = EXTRACT_32BITS(*(u_int32_t *)bp);
+ rnd = EXTRACT_32BITS(bp);
bp += sizeof(u_int32_t);
TCHECK2(*bp, sizeof(u_int32_t));
- mask = EXTRACT_32BITS(*(u_int32_t *)bp);
+ mask = EXTRACT_32BITS(bp);
bp += sizeof(u_int32_t);
(void)printf("POLR seq %u round %u nla %s ivl %u rnd 0x%08x "
- "mask 0x%08x", EXTRACT_32BITS(polr->pgmp_seq),
+ "mask 0x%08x", EXTRACT_32BITS(&polr->pgmp_seq),
EXTRACT_16BITS(&polr->pgmp_round), nla_buf, ivl, rnd, mask);
break;
}
odata = (struct pgm_data *)(pgm + 1);
TCHECK(*odata);
(void)printf("ODATA trail %u seq %u",
- EXTRACT_32BITS(odata->pgmd_trailseq), EXTRACT_32BITS(odata->pgmd_seq));
+ EXTRACT_32BITS(&odata->pgmd_trailseq),
+ EXTRACT_32BITS(&odata->pgmd_seq));
+ bp = (u_char *) (odata + 1);
break;
}
rdata = (struct pgm_data *)(pgm + 1);
TCHECK(*rdata);
(void)printf("RDATA trail %u seq %u",
- EXTRACT_32BITS(rdata->pgmd_trailseq), EXTRACT_32BITS(rdata->pgmd_seq));
+ EXTRACT_32BITS(&rdata->pgmd_trailseq),
+ EXTRACT_32BITS(&rdata->pgmd_seq));
+ bp = (u_char *) (rdata + 1);
break;
}
struct pgm_nak *nak;
const void *source, *group;
int source_af, group_af;
+#ifdef INET6
char source_buf[INET6_ADDRSTRLEN], group_buf[INET6_ADDRSTRLEN];
+#else
+ char source_buf[INET_ADDRSTRLEN], group_buf[INET_ADDRSTRLEN];
+#endif
nak = (struct pgm_nak *)(pgm + 1);
TCHECK(*nak);
addr_size = sizeof(struct in_addr);
source_af = AF_INET;
break;
+#ifdef INET6
case AFI_IP6:
addr_size = sizeof(struct in6_addr);
source_af = AF_INET6;
break;
+#endif
default:
goto trunc;
break;
addr_size = sizeof(struct in_addr);
group_af = AF_INET;
break;
+#ifdef INET6
case AFI_IP6:
addr_size = sizeof(struct in6_addr);
group_af = AF_INET6;
break;
+#endif
default:
goto trunc;
break;
break;
}
(void)printf("(%s -> %s), seq %u",
- source_buf, group_buf, EXTRACT_32BITS(nak->pgmn_seq));
+ source_buf, group_buf, EXTRACT_32BITS(&nak->pgmn_seq));
+ break;
+ }
+
+ case PGM_ACK: {
+ struct pgm_ack *ack;
+
+ ack = (struct pgm_ack *)(pgm + 1);
+ TCHECK(*ack);
+ (void)printf("ACK seq %u",
+ EXTRACT_32BITS(&ack->pgma_rx_max_seq));
+ bp = (u_char *) (ack + 1);
break;
}
*/
opt_type = *bp++;
if ((opt_type & PGM_OPT_MASK) != PGM_OPT_LENGTH) {
- (void)printf("[First option bad, should be PGM_OPT_LENGTH, is %u]", opt_type);
+ (void)printf("[First option bad, should be PGM_OPT_LENGTH, is %u]", opt_type & PGM_OPT_MASK);
return;
}
opt_len = *bp++;
break;
case PGM_OPT_FRAGMENT:
- if (opt_len != 12) {
- (void)printf("[Bad OPT_FRAGMENT option, length %u != 12]", opt_len);
+ if (opt_len != 16) {
+ (void)printf("[Bad OPT_FRAGMENT option, length %u != 16]", opt_len);
return;
}
flags1 = *bp++;
flags2 = *bp++;
- seq = EXTRACT_32BITS(*(u_int32_t *)bp);
+ seq = EXTRACT_32BITS(bp);
bp += sizeof(u_int32_t);
- offset = EXTRACT_32BITS(*(u_int32_t *)bp);
+ offset = EXTRACT_32BITS(bp);
bp += sizeof(u_int32_t);
- len = EXTRACT_32BITS(*(u_int32_t *)bp);
+ len = EXTRACT_32BITS(bp);
bp += sizeof(u_int32_t);
(void)printf(" FRAG seq %u off %u len %u", seq, offset, len);
- opts_len -= 12;
+ opts_len -= 16;
break;
case PGM_OPT_NAK_LIST:
return;
}
TCHECK2(*bp, sizeof(u_int32_t));
- (void)printf(" %u", EXTRACT_32BITS(*(u_int32_t *)bp));
+ (void)printf(" %u", EXTRACT_32BITS(bp));
bp += sizeof(u_int32_t);
opt_len -= sizeof(u_int32_t);
opts_len -= sizeof(u_int32_t);
}
flags1 = *bp++;
flags2 = *bp++;
- seq = EXTRACT_32BITS(*(u_int32_t *)bp);
+ seq = EXTRACT_32BITS(bp);
bp += sizeof(u_int32_t);
(void)printf(" JOIN %u", seq);
opts_len -= 8;
case PGM_OPT_NAK_BO_IVL:
if (opt_len != 12) {
- (void)printf("[Bad OPT_FRAGMENT option, length %u != 12]", opt_len);
+ (void)printf("[Bad OPT_NAK_BO_IVL option, length %u != 12]", opt_len);
return;
}
flags1 = *bp++;
flags2 = *bp++;
- offset = EXTRACT_32BITS(*(u_int32_t *)bp);
+ offset = EXTRACT_32BITS(bp);
bp += sizeof(u_int32_t);
- seq = EXTRACT_32BITS(*(u_int32_t *)bp);
+ seq = EXTRACT_32BITS(bp);
bp += sizeof(u_int32_t);
(void)printf(" BACKOFF ivl %u ivlseq %u", offset, seq);
opts_len -= 12;
case PGM_OPT_NAK_BO_RNG:
if (opt_len != 12) {
- (void)printf("[Bad OPT_FRAGMENT option, length %u != 12]", opt_len);
+ (void)printf("[Bad OPT_NAK_BO_RNG option, length %u != 12]", opt_len);
return;
}
flags1 = *bp++;
flags2 = *bp++;
- offset = EXTRACT_32BITS(*(u_int32_t *)bp);
+ offset = EXTRACT_32BITS(bp);
bp += sizeof(u_int32_t);
- seq = EXTRACT_32BITS(*(u_int32_t *)bp);
+ seq = EXTRACT_32BITS(bp);
bp += sizeof(u_int32_t);
(void)printf(" BACKOFF max %u min %u", offset, seq);
opts_len -= 12;
addr_size = sizeof(struct in_addr);
nla_af = AF_INET;
break;
+#ifdef INET6
case AFI_IP6:
addr_size = sizeof(struct in6_addr);
nla_af = AF_INET6;
break;
+#endif
default:
goto trunc;
break;
}
flags1 = *bp++;
flags2 = *bp++;
- len = EXTRACT_32BITS(*(u_int32_t *)bp);
+ len = EXTRACT_32BITS(bp);
bp += sizeof(u_int32_t);
(void)printf(" PARITY MAXTGS %u", len);
opts_len -= 8;
}
flags1 = *bp++;
flags2 = *bp++;
- seq = EXTRACT_32BITS(*(u_int32_t *)bp);
+ seq = EXTRACT_32BITS(bp);
bp += sizeof(u_int32_t);
(void)printf(" PARITY GROUP %u", seq);
opts_len -= 8;
case PGM_OPT_CURR_TGSIZE:
if (opt_len != 8) {
- (void)printf("[Bad OPT_PARITY_GRP option, length %u != 8]", opt_len);
+ (void)printf("[Bad OPT_CURR_TGSIZE option, length %u != 8]", opt_len);
return;
}
flags1 = *bp++;
flags2 = *bp++;
- len = EXTRACT_32BITS(*(u_int32_t *)bp);
+ len = EXTRACT_32BITS(bp);
bp += sizeof(u_int32_t);
(void)printf(" PARITY ATGS %u", len);
opts_len -= 8;
case PGM_OPT_FIN:
if (opt_len != 4) {
- (void)printf("[Bad OPT_RST option, length %u != 4]", opt_len);
+ (void)printf("[Bad OPT_FIN option, length %u != 4]", opt_len);
return;
}
flags1 = *bp++;
opts_len -= 4;
break;
+ case PGM_OPT_PGMCC_DATA:
+ flags1 = *bp++;
+ flags2 = *bp++;
+ offset = EXTRACT_32BITS(bp);
+ bp += sizeof(u_int32_t);
+ switch (EXTRACT_16BITS(bp)) {
+ case AFI_IP:
+ addr_size = sizeof(struct in_addr);
+ nla_af = AF_INET;
+ break;
+#ifdef INET6
+ case AFI_IP6:
+ addr_size = sizeof(struct in6_addr);
+ nla_af = AF_INET6;
+ break;
+#endif
+ default:
+ goto trunc;
+ break;
+ }
+ bp += (2 * sizeof(u_int16_t));
+ if (opt_len != 12 + addr_size) {
+ (void)printf("[Bad OPT_PGMCC_DATA option, length %u != 12 + address size]", opt_len);
+ return;
+ }
+ TCHECK2(*bp, addr_size);
+ nla = bp;
+ bp += addr_size;
+
+ inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf));
+ (void)printf(" PGMCC DATA %u %s", offset, (char*)nla);
+ opts_len -= 16;
+ break;
+
+ case PGM_OPT_PGMCC_FEEDBACK:
+ flags1 = *bp++;
+ flags2 = *bp++;
+ offset = EXTRACT_32BITS(bp);
+ bp += sizeof(u_int32_t);
+ switch (EXTRACT_16BITS(bp)) {
+ case AFI_IP:
+ addr_size = sizeof(struct in_addr);
+ nla_af = AF_INET;
+ break;
+#ifdef INET6
+ case AFI_IP6:
+ addr_size = sizeof(struct in6_addr);
+ nla_af = AF_INET6;
+ break;
+#endif
+ default:
+ goto trunc;
+ break;
+ }
+ bp += (2 * sizeof(u_int16_t));
+ if (opt_len != 12 + addr_size) {
+ (void)printf("[Bad OPT_PGMCC_FEEDBACK option, length %u != 12 + address size]", opt_len);
+ return;
+ }
+ TCHECK2(*bp, addr_size);
+ nla = bp;
+ bp += addr_size;
+
+ inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf));
+ (void)printf(" PGMCC FEEDBACK %u %s", offset, (char*)nla);
+ opts_len -= 16;
+ break;
+
default:
(void)printf(" OPT_%02X [%d] ", opt_type, opt_len);
bp += opt_len;