*/
/* \summary: Generic Network Virtualization Encapsulation (Geneve) printer */
+/* specification: RFC 8926 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
+#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "ethertype.h"
/*
- * Geneve header, draft-ietf-nvo3-geneve
+ * Geneve header:
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Virtual Network Identifier (VNI) | Reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Variable Length Options |
+ * | |
+ * ~ Variable-Length Options ~
+ * | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Options:
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Option Class | Type |R|R|R| Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Variable Option Data |
+ * | |
+ * ~ Variable-Length Option Data ~
+ * | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
};
static const char *
-format_opt_class(uint16_t opt_class)
+format_opt_class(const uint16_t opt_class)
{
switch (opt_class) {
case 0x0100:
return "In-band Network Telemetry (INT)";
case 0x0104:
return "VMware";
+ case 0x0105:
+ case 0x0108:
+ case 0x0109:
+ case 0x010A:
+ case 0x010B:
+ case 0x010C:
+ case 0x010D:
+ case 0x010E:
+ case 0x010F:
+ case 0x0110:
+ return "Amazon";
+ case 0x0106:
+ case 0x0130:
+ case 0x0131:
+ return "Cisco";
+ case 0x0107:
+ return "Oracle";
+ case 0x0111:
+ case 0x0112:
+ case 0x0113:
+ case 0x0114:
+ case 0x0115:
+ case 0x0116:
+ case 0x0117:
+ case 0x0118:
+ return "IBM";
+ case 0x0119:
+ case 0x011A:
+ case 0x011B:
+ case 0x011C:
+ case 0x011D:
+ case 0x011E:
+ case 0x011F:
+ case 0x0120:
+ case 0x0121:
+ case 0x0122:
+ case 0x0123:
+ case 0x0124:
+ case 0x0125:
+ case 0x0126:
+ case 0x0127:
+ case 0x0128:
+ return "Ericsson";
+ case 0x0129:
+ return "Oxide";
+ case 0x0132:
+ case 0x0133:
+ case 0x0134:
+ case 0x0135:
+ return "Google";
+ case 0x0136:
+ return "InfoQuick";
default:
if (opt_class <= 0x00ff)
return "Standard";
return "Unknown";
}
-static void
+static unsigned
geneve_opts_print(netdissect_options *ndo, const u_char *bp, u_int len)
{
const char *sep = "";
- while (len > 0) {
+ while (len != 0) {
uint16_t opt_class;
uint8_t opt_type;
uint8_t opt_len;
+ ND_ICHECKMSG_U("remaining options length", len, <, 4);
ND_PRINT("%s", sep);
sep = ", ";
if (opt_len > len) {
ND_PRINT(" [bad length]");
- return;
+ goto invalid;
}
if (ndo->ndo_vflag > 1 && opt_len > 4) {
ND_PRINT(" %08x", GET_BE_U_4(data));
data++;
}
- }
+ } else
+ ND_TCHECK_LEN(bp, opt_len);
bp += opt_len;
len -= opt_len;
}
+ return 1;
+invalid:
+ ND_TCHECK_LEN(bp, len);
+ return 0;
}
void
ndo->ndo_protocol = "geneve";
ND_PRINT("Geneve");
- if (len < 8) {
- ND_PRINT(" [length %u < 8]", len);
- nd_print_invalid(ndo);
- return;
- }
-
- ND_TCHECK_8(bp);
+ ND_ICHECK_U(len, <, 8);
ver_opt = GET_U_1(bp);
bp += 1;
version = ver_opt >> VER_SHIFT;
if (version != 0) {
ND_PRINT(" ERROR: unknown-version %u", version);
- return;
+ goto invalid;
}
flags = GET_U_1(bp);
opts_len = (ver_opt & HDR_OPTS_LEN_MASK) * 4;
if (len < opts_len) {
- ND_PRINT(" truncated-geneve - %u bytes missing",
- opts_len - len);
- return;
+ ND_PRINT(" (opts_len %u > %u", opts_len, len);
+ goto invalid;
}
- ND_TCHECK_LEN(bp, opts_len);
-
if (opts_len > 0) {
ND_PRINT(", options [");
- if (ndo->ndo_vflag)
- geneve_opts_print(ndo, bp, opts_len);
- else
+ if (ndo->ndo_vflag) {
+ if (! geneve_opts_print(ndo, bp, opts_len))
+ goto invalid;
+ } else {
+ ND_TCHECK_LEN(bp, opts_len);
ND_PRINT("%u bytes", opts_len);
+ }
ND_PRINT("]");
}
if (ethertype_print(ndo, prot, bp, len, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL) == 0) {
if (prot == ETHERTYPE_TEB)
ether_print(ndo, bp, len, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL);
- else
+ else {
ND_PRINT("geneve-proto-0x%x", prot);
+ ND_TCHECK_LEN(bp, len);
+ }
}
return;
-trunc:
- nd_print_trunc(ndo);
+invalid:
+ nd_print_invalid(ndo);
}