#include "netdissect-stdinc.h"
-#include <string.h>
-
+#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "addrtostr.h"
#include "extract.h"
#define GRE_KP 0x2000 /* key present */
#define GRE_SP 0x1000 /* sequence# present */
#define GRE_sP 0x0800 /* source routing */
-#define GRE_RECRS 0x0700 /* recursion count */
#define GRE_AP 0x0080 /* acknowledgment# present */
static const struct tok gre_flag_values[] = {
{ GRE_KP, "key present"},
{ GRE_SP, "sequence# present"},
{ GRE_sP, "source routing present"},
- { GRE_RECRS, "recursion count"},
{ GRE_AP, "ack present"},
{ 0, NULL }
};
+#define GRE_RECRS_MASK 0x0700 /* recursion count */
#define GRE_VERS_MASK 0x0007 /* protocol version */
/* source route entry types */
void
gre_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
- u_int len = length, vers;
+ u_int vers;
ndo->ndo_protocol = "gre";
- ND_TCHECK_2(bp);
- if (len < 2)
- goto trunc;
+ nd_print_protocol_caps(ndo);
+ ND_ICHECK_U(length, <, 2);
vers = GET_BE_U_2(bp) & GRE_VERS_MASK;
- ND_PRINT("GREv%u",vers);
+ ND_PRINT("v%u",vers);
switch(vers) {
case 0:
- gre_print_0(ndo, bp, len);
+ gre_print_0(ndo, bp, length);
break;
case 1:
- gre_print_1(ndo, bp, len);
+ gre_print_1(ndo, bp, length);
break;
default:
ND_PRINT(" ERROR: unknown-version");
}
return;
-trunc:
- nd_print_trunc(ndo);
+invalid:
+ nd_print_invalid(ndo);
}
static void
u_int len = length;
uint16_t flags, prot;
- /* 16 bits ND_TCHECKed in gre_print() */
+ ND_ICHECK_U(len, <, 2);
flags = GET_BE_U_2(bp);
if (ndo->ndo_vflag)
ND_PRINT(", Flags [%s]",
len -= 2;
bp += 2;
- ND_TCHECK_2(bp);
- if (len < 2)
- goto trunc;
+ ND_ICHECK_U(len, <, 2);
prot = GET_BE_U_2(bp);
len -= 2;
bp += 2;
if ((flags & GRE_CP) | (flags & GRE_RP)) {
- ND_TCHECK_2(bp);
- if (len < 2)
- goto trunc;
+ uint16_t sum;
+
+ ND_ICHECK_U(len, <, 2);
+ sum = GET_BE_U_2(bp);
if (ndo->ndo_vflag)
- ND_PRINT(", sum 0x%x", GET_BE_U_2(bp));
+ ND_PRINT(", sum 0x%x", sum);
bp += 2;
len -= 2;
- ND_TCHECK_2(bp);
- if (len < 2)
- goto trunc;
+ ND_ICHECK_U(len, <, 2);
ND_PRINT(", off 0x%x", GET_BE_U_2(bp));
bp += 2;
len -= 2;
}
if (flags & GRE_KP) {
- ND_TCHECK_4(bp);
- if (len < 4)
- goto trunc;
+ ND_ICHECK_U(len, <, 4);
ND_PRINT(", key=0x%x", GET_BE_U_4(bp));
bp += 4;
len -= 4;
}
if (flags & GRE_SP) {
- ND_TCHECK_4(bp);
- if (len < 4)
- goto trunc;
+ ND_ICHECK_U(len, <, 4);
ND_PRINT(", seq %u", GET_BE_U_4(bp));
bp += 4;
len -= 4;
uint8_t sreoff;
uint8_t srelen;
- ND_TCHECK_4(bp);
- if (len < 4)
- goto trunc;
+ ND_ICHECK_U(len, <, 4);
af = GET_BE_U_2(bp);
sreoff = GET_U_1(bp + 2);
srelen = GET_U_1(bp + 3);
break;
if (!gre_sre_print(ndo, af, sreoff, srelen, bp, len))
- goto trunc;
+ goto invalid;
- if (len < srelen)
- goto trunc;
+ ND_ICHECK_U(len, <, srelen);
bp += srelen;
len -= srelen;
}
}
return;
-trunc:
- nd_print_trunc(ndo);
+invalid:
+ nd_print_invalid(ndo);
}
static void
u_int len = length;
uint16_t flags, prot;
- /* 16 bits ND_TCHECKed in gre_print() */
+ ND_ICHECK_U(len, <, 2);
flags = GET_BE_U_2(bp);
len -= 2;
bp += 2;
ND_PRINT(", Flags [%s]",
bittok2str(gre_flag_values,"none",flags));
- ND_TCHECK_2(bp);
- if (len < 2)
- goto trunc;
+ ND_ICHECK_U(len, <, 2);
prot = GET_BE_U_2(bp);
len -= 2;
bp += 2;
if (flags & GRE_KP) {
uint32_t k;
- ND_TCHECK_4(bp);
- if (len < 4)
- goto trunc;
+ ND_ICHECK_U(len, <, 4);
k = GET_BE_U_4(bp);
ND_PRINT(", call %u", k & 0xffff);
len -= 4;
}
if (flags & GRE_SP) {
- ND_TCHECK_4(bp);
- if (len < 4)
- goto trunc;
+ ND_ICHECK_U(len, <, 4);
ND_PRINT(", seq %u", GET_BE_U_4(bp));
bp += 4;
len -= 4;
}
if (flags & GRE_AP) {
- ND_TCHECK_4(bp);
- if (len < 4)
- goto trunc;
+ ND_ICHECK_U(len, <, 4);
ND_PRINT(", ack %u", GET_BE_U_4(bp));
bp += 4;
len -= 4;
}
return;
-trunc:
- nd_print_trunc(ndo);
+invalid:
+ nd_print_invalid(ndo);
}
static int
if (sreoff & 3) {
ND_PRINT(", badoffset=%u", sreoff);
- return (1);
+ goto invalid;
}
if (srelen & 3) {
ND_PRINT(", badlength=%u", srelen);
- return (1);
+ goto invalid;
}
if (sreoff >= srelen) {
ND_PRINT(", badoff/len=%u/%u", sreoff, srelen);
- return (1);
+ goto invalid;
}
while (srelen != 0) {
- ND_TCHECK_4(bp);
- if (len < 4)
- return (0);
+ ND_ICHECK_U(len, <, 4);
+ ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
addrtostr(bp, buf, sizeof(buf));
ND_PRINT(" %s%s",
((bp - up) == sreoff) ? "*" : "", buf);
len -= 4;
srelen -= 4;
}
- return (1);
-trunc:
+ return 1;
+
+invalid:
return 0;
}
if (sreoff & 1) {
ND_PRINT(", badoffset=%u", sreoff);
- return (1);
+ goto invalid;
}
if (srelen & 1) {
ND_PRINT(", badlength=%u", srelen);
- return (1);
+ goto invalid;
}
if (sreoff >= srelen) {
ND_PRINT(", badoff/len=%u/%u", sreoff, srelen);
- return (1);
+ goto invalid;
}
while (srelen != 0) {
- ND_TCHECK_2(bp);
- if (len < 2)
- return (0);
+ ND_ICHECK_U(len, <, 2);
ND_PRINT(" %s%x",
((bp - up) == sreoff) ? "*" : "", GET_BE_U_2(bp));
len -= 2;
srelen -= 2;
}
- return (1);
-trunc:
+ return 1;
+
+invalid:
return 0;
}