#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-pgm.c,v 1.1.2.1 2005-05-20 21:15:47 hannes Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-pgm.c,v 1.1.2.5 2005-06-07 22:06:16 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]; */
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 */
};
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;
pgm = (struct pgm_header *)bp;
ip = (struct ip *)bp2;
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;
}
(void)printf("[|OPT]");
return;
}
- while (TTEST2(*bp, PGM_MIN_OPT_LEN)) {
- u_int8_t opt_type, opt_len, flags1, flags2;
- u_int32_t seq, len, offset;
+ /*
+ * That option header MUST be an OPT_LENGTH option
+ * (see the first paragraph of section 9.1 in RFC 3208).
+ */
+ 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 & PGM_OPT_MASK);
+ return;
+ }
+ opt_len = *bp++;
+ if (opt_len != 4) {
+ (void)printf("[Bad OPT_LENGTH option, length %u != 4]", opt_len);
+ return;
+ }
+ opts_len = EXTRACT_16BITS(bp);
+ if (opts_len < 4) {
+ (void)printf("[Bad total option length %u < 4]", opts_len);
+ return;
+ }
+ bp += sizeof(u_int16_t);
+ (void)printf(" OPTS LEN %d", opts_len);
+ opts_len -= 4;
+
+ while (opts_len) {
+ if (opts_len < PGM_MIN_OPT_LEN) {
+ (void)printf("[Total option length leaves no room for final option]");
+ return;
+ }
opt_type = *bp++;
opt_len = *bp++;
+ if (opt_len < PGM_MIN_OPT_LEN) {
+ (void)printf("[Bad option, length %u < %u]", opt_len,
+ PGM_MIN_OPT_LEN);
+ break;
+ }
+ if (opts_len < opt_len) {
+ (void)printf("[Total option length leaves no room for final option]");
+ return;
+ }
+ if (!TTEST2(*bp, opt_len - 2)) {
+ (void)printf(" [|OPT]");
+ return;
+ }
switch (opt_type & PGM_OPT_MASK) {
case PGM_OPT_LENGTH:
- len = EXTRACT_16BITS(bp);
+ if (opt_len != 4) {
+ (void)printf("[Bad OPT_LENGTH option, length %u != 4]", opt_len);
+ return;
+ }
+ (void)printf(" OPTS LEN (extra?) %d", EXTRACT_16BITS(bp));
bp += sizeof(u_int16_t);
- (void)printf(" OPT[%d] %d", opt_len, len);
+ opts_len -= 4;
break;
case PGM_OPT_FRAGMENT:
+ 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 -= 16;
break;
case PGM_OPT_NAK_LIST:
opt_len -= sizeof(u_int32_t); /* option header */
(void)printf(" NAK LIST");
while (opt_len) {
+ if (opt_len < sizeof(u_int32_t)) {
+ (void)printf("[Option length not a multiple of 4]");
+ 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);
}
break;
case PGM_OPT_JOIN:
+ if (opt_len != 8) {
+ (void)printf("[Bad OPT_JOIN option, length %u != 8]", opt_len);
+ return;
+ }
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;
break;
case PGM_OPT_NAK_BO_IVL:
+ if (opt_len != 12) {
+ (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;
break;
case PGM_OPT_NAK_BO_RNG:
+ if (opt_len != 12) {
+ (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;
break;
case PGM_OPT_REDIRECT:
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 != 4 + addr_size) {
+ (void)printf("[Bad OPT_REDIRECT option, length %u != 4 + 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(" REDIRECT %s", (char *)nla);
+ opts_len -= 4 + addr_size;
break;
case PGM_OPT_PARITY_PRM:
+ if (opt_len != 8) {
+ (void)printf("[Bad OPT_PARITY_PRM 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 MAXTGS %u", len);
+ opts_len -= 8;
break;
case PGM_OPT_PARITY_GRP:
+ if (opt_len != 8) {
+ (void)printf("[Bad OPT_PARITY_GRP option, length %u != 8]", opt_len);
+ return;
+ }
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;
break;
case PGM_OPT_CURR_TGSIZE:
+ if (opt_len != 8) {
+ (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;
break;
case PGM_OPT_NBR_UNREACH:
+ if (opt_len != 4) {
+ (void)printf("[Bad OPT_NBR_UNREACH option, length %u != 4]", opt_len);
+ return;
+ }
flags1 = *bp++;
flags2 = *bp++;
(void)printf(" NBR_UNREACH");
+ opts_len -= 4;
break;
case PGM_OPT_PATH_NLA:
(void)printf(" PATH_NLA [%d]", opt_len);
bp += opt_len;
+ opts_len -= opt_len;
break;
case PGM_OPT_SYN:
+ if (opt_len != 4) {
+ (void)printf("[Bad OPT_SYN option, length %u != 4]", opt_len);
+ return;
+ }
flags1 = *bp++;
flags2 = *bp++;
(void)printf(" SYN");
+ opts_len -= 4;
break;
case PGM_OPT_FIN:
+ if (opt_len != 4) {
+ (void)printf("[Bad OPT_FIN option, length %u != 4]", opt_len);
+ return;
+ }
flags1 = *bp++;
flags2 = *bp++;
(void)printf(" FIN");
+ opts_len -= 4;
break;
case PGM_OPT_RST:
+ if (opt_len != 4) {
+ (void)printf("[Bad OPT_RST option, length %u != 4]", opt_len);
+ return;
+ }
flags1 = *bp++;
flags2 = *bp++;
(void)printf(" RST");
+ opts_len -= 4;
break;
case PGM_OPT_CR:
(void)printf(" CR");
bp += opt_len;
+ opts_len -= opt_len;
break;
case PGM_OPT_CRQST:
+ if (opt_len != 4) {
+ (void)printf("[Bad OPT_CRQST option, length %u != 4]", opt_len);
+ return;
+ }
flags1 = *bp++;
flags2 = *bp++;
(void)printf(" CRQST");
+ opts_len -= 4;
break;
default:
- if (!TTEST2(*bp, opt_len)) {
- (void)printf(" [|OPT]");
- return;
- }
(void)printf(" OPT_%02X [%d] ", opt_type, opt_len);
bp += opt_len;
+ opts_len -= opt_len;
break;
}