X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/7b2c5a11a7bc236d72b440c4db5263edb23b4880..d2777156522f139a858bd6b5b51e364826bc95a7:/print-geneve.c diff --git a/print-geneve.c b/print-geneve.c index 56b9f2b5..0b7ff6e5 100644 --- a/print-geneve.c +++ b/print-geneve.c @@ -15,18 +15,20 @@ * FOR A PARTICULAR PURPOSE. */ +/* \summary: Generic Network Virtualization Encapsulation (Geneve) printer */ + #ifdef HAVE_CONFIG_H -#include "config.h" +#include #endif -#include +#include "netdissect-stdinc.h" -#include "interface.h" +#include "netdissect.h" #include "extract.h" #include "ethertype.h" /* - * Geneve header, draft-gross-geneve-02 + * Geneve header, draft-ietf-nvo3-geneve * * 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 @@ -76,12 +78,25 @@ static const struct tok geneve_flag_values[] = { static const char * format_opt_class(uint16_t opt_class) { - if (opt_class <= 0xff) - return "Standard"; - else if (opt_class == 0xffff) - return "Experimental"; - else - return "Unknown"; + switch (opt_class) { + case 0x0100: + return "Linux"; + case 0x0101: + return "Open vSwitch"; + case 0x0102: + return "Open Virtual Networking (OVN)"; + case 0x0103: + return "In-band Network Telemetry (INT)"; + case 0x0104: + return "VMware"; + default: + if (opt_class <= 0x00ff) + return "Standard"; + else if (opt_class >= 0xfff0) + return "Experimental"; + } + + return "Unknown"; } static void @@ -94,31 +109,31 @@ geneve_opts_print(netdissect_options *ndo, const u_char *bp, u_int len) uint8_t opt_type; uint8_t opt_len; - ND_PRINT((ndo, "%s", sep)); + ND_PRINT("%s", sep); sep = ", "; - opt_class = EXTRACT_16BITS(bp); - opt_type = *(bp + 2); - opt_len = 4 + ((*(bp + 3) & OPT_LEN_MASK) * 4); + opt_class = GET_BE_U_2(bp); + opt_type = GET_U_1(bp + 2); + opt_len = 4 + ((GET_U_1(bp + 3) & OPT_LEN_MASK) * 4); - ND_PRINT((ndo, "class %s (0x%x) type 0x%x%s len %u", + ND_PRINT("class %s (0x%x) type 0x%x%s len %u", format_opt_class(opt_class), opt_class, opt_type, - opt_type & OPT_TYPE_CRITICAL ? "(C)" : "", opt_len)); + opt_type & OPT_TYPE_CRITICAL ? "(C)" : "", opt_len); if (opt_len > len) { - ND_PRINT((ndo, " [bad length]")); + ND_PRINT(" [bad length]"); return; } if (ndo->ndo_vflag > 1 && opt_len > 4) { - uint32_t *print_data = (uint32_t *)(bp + 4); + const uint32_t *data = (const uint32_t *)(bp + 4); int i; - ND_PRINT((ndo, " data")); + ND_PRINT(" data"); for (i = 4; i < opt_len; i += 4) { - ND_PRINT((ndo, " %08x", EXTRACT_32BITS(print_data))); - print_data++; + ND_PRINT(" %08x", GET_BE_U_4(data)); + data++; } } @@ -131,92 +146,99 @@ void geneve_print(netdissect_options *ndo, const u_char *bp, u_int len) { uint8_t ver_opt; - uint version; + u_int version; uint8_t flags; uint16_t prot; uint32_t vni; uint8_t reserved; u_int opts_len; - ND_PRINT((ndo, "Geneve")); + ndo->ndo_protocol = "geneve"; + ND_PRINT("Geneve"); + + if (len < 8) { + ND_PRINT(" [length %u < 8]", len); + nd_print_invalid(ndo); + return; + } - ND_TCHECK2(*bp, 8); + ND_TCHECK_8(bp); - ver_opt = *bp; + ver_opt = GET_U_1(bp); bp += 1; len -= 1; version = ver_opt >> VER_SHIFT; if (version != 0) { - ND_PRINT((ndo, " ERROR: unknown-version %u", version)); + ND_PRINT(" ERROR: unknown-version %u", version); return; } - flags = *bp; + flags = GET_U_1(bp); bp += 1; len -= 1; - prot = EXTRACT_16BITS(bp); + prot = GET_BE_U_2(bp); bp += 2; len -= 2; - vni = EXTRACT_24BITS(bp); + vni = GET_BE_U_3(bp); bp += 3; len -= 3; - reserved = *bp; + reserved = GET_U_1(bp); bp += 1; len -= 1; - ND_PRINT((ndo, ", Flags [%s]", - bittok2str_nosep(geneve_flag_values, "none", flags))); - ND_PRINT((ndo, ", vni 0x%x", vni)); + ND_PRINT(", Flags [%s]", + bittok2str_nosep(geneve_flag_values, "none", flags)); + ND_PRINT(", vni 0x%x", vni); if (reserved) - ND_PRINT((ndo, ", rsvd 0x%x", reserved)); + ND_PRINT(", rsvd 0x%x", reserved); if (ndo->ndo_eflag) - ND_PRINT((ndo, ", proto %s (0x%04x)", - tok2str(ethertype_values, "unknown", prot), prot)); + ND_PRINT(", proto %s (0x%04x)", + tok2str(ethertype_values, "unknown", prot), prot); opts_len = (ver_opt & HDR_OPTS_LEN_MASK) * 4; if (len < opts_len) { - ND_PRINT((ndo, " truncated-geneve - %u bytes missing", - len - opts_len)); + ND_PRINT(" truncated-geneve - %u bytes missing", + opts_len - len); return; } - ND_TCHECK2(*bp, opts_len); + ND_TCHECK_LEN(bp, opts_len); if (opts_len > 0) { - ND_PRINT((ndo, ", options [")); + ND_PRINT(", options ["); if (ndo->ndo_vflag) geneve_opts_print(ndo, bp, opts_len); else - ND_PRINT((ndo, "%u bytes", opts_len)); + ND_PRINT("%u bytes", opts_len); - ND_PRINT((ndo, "]")); + ND_PRINT("]"); } bp += opts_len; len -= opts_len; if (ndo->ndo_vflag < 1) - ND_PRINT((ndo, ": ")); + ND_PRINT(": "); else - ND_PRINT((ndo, "\n\t")); + ND_PRINT("\n\t"); - if (ethertype_print(ndo, prot, bp, len, len) == 0) { + if (ethertype_print(ndo, prot, bp, len, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL) == 0) { if (prot == ETHERTYPE_TEB) - ether_print(ndo, bp, len, len, NULL, NULL); + ether_print(ndo, bp, len, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL); else - ND_PRINT((ndo, "geneve-proto-0x%x", prot)); + ND_PRINT("geneve-proto-0x%x", prot); } return; trunc: - ND_PRINT((ndo, " [|geneve]")); + nd_print_trunc(ndo); }