diff options
author | pkelsey <pkelsey@FreeBSD.org> | 2015-07-08 16:19:32 +0000 |
---|---|---|
committer | pkelsey <pkelsey@FreeBSD.org> | 2015-07-08 16:19:32 +0000 |
commit | 7e965066ede451d7a551dd68d6c59acf32e4846e (patch) | |
tree | f0c2243cc0a2a59f3eb1354ba3987d4cbcb788bc /contrib/tcpdump/print-geneve.c | |
parent | 732211dc794db586649eabfc1d517b8a477440f5 (diff) | |
parent | c2704d8ede887d9fe69a9a11fe0755b09ec6895d (diff) | |
download | FreeBSD-src-7e965066ede451d7a551dd68d6c59acf32e4846e.zip FreeBSD-src-7e965066ede451d7a551dd68d6c59acf32e4846e.tar.gz |
MFV r285191: tcpdump 4.7.4.
Also, the changes made in r272451 and r272653 that were lost in the
merge of 4.6.2 (r276788) have been restored.
PR: 199568
Differential Revision: https://reviews.freebsd.org/D3007
Reviewed by: brooks, hiren
Approved by: jmallett (mentor)
MFC after: 1 month
Diffstat (limited to 'contrib/tcpdump/print-geneve.c')
-rw-r--r-- | contrib/tcpdump/print-geneve.c | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/contrib/tcpdump/print-geneve.c b/contrib/tcpdump/print-geneve.c new file mode 100644 index 0000000..2187ab8 --- /dev/null +++ b/contrib/tcpdump/print-geneve.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2014 VMware, Inc. All Rights Reserved. + * + * Jesse Gross <jesse@nicira.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code + * distributions retain the above copyright notice and this paragraph + * in its entirety, and (2) distributions including binary code include + * the above copyright notice and this paragraph in its entirety in + * the documentation or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND + * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT + * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + */ + +#define NETDISSECT_REWORKED +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <tcpdump-stdinc.h> + +#include "interface.h" +#include "extract.h" +#include "ethertype.h" + +/* + * Geneve header, draft-gross-geneve-02 + * + * 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |Ver| Opt Len |O|C| Rsvd. | Protocol Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Virtual Network Identifier (VNI) | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Variable Length Options | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Options: + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Option Class | Type |R|R|R| Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Variable Option Data | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define VER_SHIFT 6 +#define HDR_OPTS_LEN_MASK 0x3F + +#define FLAG_OAM (1 << 7) +#define FLAG_CRITICAL (1 << 6) +#define FLAG_R1 (1 << 5) +#define FLAG_R2 (1 << 4) +#define FLAG_R3 (1 << 3) +#define FLAG_R4 (1 << 2) +#define FLAG_R5 (1 << 1) +#define FLAG_R6 (1 << 0) + +#define OPT_TYPE_CRITICAL (1 << 7) +#define OPT_LEN_MASK 0x1F + +static const struct tok geneve_flag_values[] = { + { FLAG_OAM, "O" }, + { FLAG_CRITICAL, "C" }, + { FLAG_R1, "R1" }, + { FLAG_R2, "R2" }, + { FLAG_R3, "R3" }, + { FLAG_R4, "R4" }, + { FLAG_R5, "R5" }, + { FLAG_R6, "R6" }, + { 0, NULL } +}; + +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"; +} + +static void +geneve_opts_print(netdissect_options *ndo, const u_char *bp, u_int len) +{ + const char *sep = ""; + + while (len > 0) { + uint16_t opt_class; + uint8_t opt_type; + uint8_t opt_len; + + ND_PRINT((ndo, "%s", sep)); + sep = ", "; + + opt_class = EXTRACT_16BITS(bp); + opt_type = *(bp + 2); + opt_len = 4 + ((*(bp + 3) & OPT_LEN_MASK) * 4); + + ND_PRINT((ndo, "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)); + + if (opt_len > len) { + ND_PRINT((ndo, " [bad length]")); + return; + } + + if (ndo->ndo_vflag > 1 && opt_len > 4) { + uint32_t *print_data = (uint32_t *)(bp + 4); + int i; + + ND_PRINT((ndo, " data")); + + for (i = 4; i < opt_len; i += 4) { + ND_PRINT((ndo, " %08x", EXTRACT_32BITS(print_data))); + print_data++; + } + } + + bp += opt_len; + len -= opt_len; + } +} + +void +geneve_print(netdissect_options *ndo, const u_char *bp, u_int len) +{ + uint8_t ver_opt; + uint version; + uint8_t flags; + uint16_t prot; + uint32_t vni; + uint8_t reserved; + u_int opts_len; + + ND_PRINT((ndo, "Geneve")); + + ND_TCHECK2(*bp, 8); + + ver_opt = *bp; + bp += 1; + len -= 1; + + version = ver_opt >> VER_SHIFT; + if (version != 0) { + ND_PRINT((ndo, " ERROR: unknown-version %u", version)); + return; + } + + flags = *bp; + bp += 1; + len -= 1; + + prot = EXTRACT_16BITS(bp); + bp += 2; + len -= 2; + + vni = EXTRACT_24BITS(bp); + bp += 3; + len -= 3; + + reserved = *bp; + bp += 1; + len -= 1; + + ND_PRINT((ndo, ", Flags [%s]", + bittok2str_nosep(geneve_flag_values, "none", flags))); + ND_PRINT((ndo, ", vni 0x%x", vni)); + + if (reserved) + ND_PRINT((ndo, ", rsvd 0x%x", reserved)); + + if (ndo->ndo_eflag) + ND_PRINT((ndo, ", 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)); + return; + } + + ND_TCHECK2(*bp, opts_len); + + if (opts_len > 0) { + ND_PRINT((ndo, ", options [")); + + if (ndo->ndo_vflag) + geneve_opts_print(ndo, bp, opts_len); + else + ND_PRINT((ndo, "%u bytes", opts_len)); + + ND_PRINT((ndo, "]")); + } + + bp += opts_len; + len -= opts_len; + + if (ndo->ndo_vflag < 1) + ND_PRINT((ndo, ": ")); + else + ND_PRINT((ndo, "\n\t")); + + if (ethertype_print(ndo, prot, bp, len, len) == 0) { + if (prot == ETHERTYPE_TEB) + ether_print(ndo, bp, len, len, NULL, NULL); + else + ND_PRINT((ndo, "geneve-proto-0x%x", prot)); + } + + return; + +trunc: + ND_PRINT((ndo, " [|geneve]")); +} |