1*b636d99dSDavid van Moolenbroek /*
2*b636d99dSDavid van Moolenbroek * Copyright (c) 2014 VMware, Inc. All Rights Reserved.
3*b636d99dSDavid van Moolenbroek *
4*b636d99dSDavid van Moolenbroek * Jesse Gross <jesse@nicira.com>
5*b636d99dSDavid van Moolenbroek *
6*b636d99dSDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
7*b636d99dSDavid van Moolenbroek * modification, are permitted provided that: (1) source code
8*b636d99dSDavid van Moolenbroek * distributions retain the above copyright notice and this paragraph
9*b636d99dSDavid van Moolenbroek * in its entirety, and (2) distributions including binary code include
10*b636d99dSDavid van Moolenbroek * the above copyright notice and this paragraph in its entirety in
11*b636d99dSDavid van Moolenbroek * the documentation or other materials provided with the distribution.
12*b636d99dSDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
13*b636d99dSDavid van Moolenbroek * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
14*b636d99dSDavid van Moolenbroek * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
15*b636d99dSDavid van Moolenbroek * FOR A PARTICULAR PURPOSE.
16*b636d99dSDavid van Moolenbroek */
17*b636d99dSDavid van Moolenbroek
18*b636d99dSDavid van Moolenbroek #define NETDISSECT_REWORKED
19*b636d99dSDavid van Moolenbroek #ifdef HAVE_CONFIG_H
20*b636d99dSDavid van Moolenbroek #include "config.h"
21*b636d99dSDavid van Moolenbroek #endif
22*b636d99dSDavid van Moolenbroek
23*b636d99dSDavid van Moolenbroek #include <tcpdump-stdinc.h>
24*b636d99dSDavid van Moolenbroek
25*b636d99dSDavid van Moolenbroek #include "interface.h"
26*b636d99dSDavid van Moolenbroek #include "extract.h"
27*b636d99dSDavid van Moolenbroek #include "ethertype.h"
28*b636d99dSDavid van Moolenbroek
29*b636d99dSDavid van Moolenbroek /*
30*b636d99dSDavid van Moolenbroek * Geneve header, draft-gross-geneve-02
31*b636d99dSDavid van Moolenbroek *
32*b636d99dSDavid van Moolenbroek * 0 1 2 3
33*b636d99dSDavid van Moolenbroek * 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
34*b636d99dSDavid van Moolenbroek * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35*b636d99dSDavid van Moolenbroek * |Ver| Opt Len |O|C| Rsvd. | Protocol Type |
36*b636d99dSDavid van Moolenbroek * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37*b636d99dSDavid van Moolenbroek * | Virtual Network Identifier (VNI) | Reserved |
38*b636d99dSDavid van Moolenbroek * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39*b636d99dSDavid van Moolenbroek * | Variable Length Options |
40*b636d99dSDavid van Moolenbroek * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41*b636d99dSDavid van Moolenbroek *
42*b636d99dSDavid van Moolenbroek * Options:
43*b636d99dSDavid van Moolenbroek * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44*b636d99dSDavid van Moolenbroek * | Option Class | Type |R|R|R| Length |
45*b636d99dSDavid van Moolenbroek * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46*b636d99dSDavid van Moolenbroek * | Variable Option Data |
47*b636d99dSDavid van Moolenbroek * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48*b636d99dSDavid van Moolenbroek */
49*b636d99dSDavid van Moolenbroek
50*b636d99dSDavid van Moolenbroek #define VER_SHIFT 6
51*b636d99dSDavid van Moolenbroek #define HDR_OPTS_LEN_MASK 0x3F
52*b636d99dSDavid van Moolenbroek
53*b636d99dSDavid van Moolenbroek #define FLAG_OAM (1 << 7)
54*b636d99dSDavid van Moolenbroek #define FLAG_CRITICAL (1 << 6)
55*b636d99dSDavid van Moolenbroek #define FLAG_R1 (1 << 5)
56*b636d99dSDavid van Moolenbroek #define FLAG_R2 (1 << 4)
57*b636d99dSDavid van Moolenbroek #define FLAG_R3 (1 << 3)
58*b636d99dSDavid van Moolenbroek #define FLAG_R4 (1 << 2)
59*b636d99dSDavid van Moolenbroek #define FLAG_R5 (1 << 1)
60*b636d99dSDavid van Moolenbroek #define FLAG_R6 (1 << 0)
61*b636d99dSDavid van Moolenbroek
62*b636d99dSDavid van Moolenbroek #define OPT_TYPE_CRITICAL (1 << 7)
63*b636d99dSDavid van Moolenbroek #define OPT_LEN_MASK 0x1F
64*b636d99dSDavid van Moolenbroek
65*b636d99dSDavid van Moolenbroek static const struct tok geneve_flag_values[] = {
66*b636d99dSDavid van Moolenbroek { FLAG_OAM, "O" },
67*b636d99dSDavid van Moolenbroek { FLAG_CRITICAL, "C" },
68*b636d99dSDavid van Moolenbroek { FLAG_R1, "R1" },
69*b636d99dSDavid van Moolenbroek { FLAG_R2, "R2" },
70*b636d99dSDavid van Moolenbroek { FLAG_R3, "R3" },
71*b636d99dSDavid van Moolenbroek { FLAG_R4, "R4" },
72*b636d99dSDavid van Moolenbroek { FLAG_R5, "R5" },
73*b636d99dSDavid van Moolenbroek { FLAG_R6, "R6" },
74*b636d99dSDavid van Moolenbroek { 0, NULL }
75*b636d99dSDavid van Moolenbroek };
76*b636d99dSDavid van Moolenbroek
77*b636d99dSDavid van Moolenbroek static const char *
format_opt_class(uint16_t opt_class)78*b636d99dSDavid van Moolenbroek format_opt_class(uint16_t opt_class)
79*b636d99dSDavid van Moolenbroek {
80*b636d99dSDavid van Moolenbroek if (opt_class <= 0xff)
81*b636d99dSDavid van Moolenbroek return "Standard";
82*b636d99dSDavid van Moolenbroek else if (opt_class == 0xffff)
83*b636d99dSDavid van Moolenbroek return "Experimental";
84*b636d99dSDavid van Moolenbroek else
85*b636d99dSDavid van Moolenbroek return "Unknown";
86*b636d99dSDavid van Moolenbroek }
87*b636d99dSDavid van Moolenbroek
88*b636d99dSDavid van Moolenbroek static void
geneve_opts_print(netdissect_options * ndo,const u_char * bp,u_int len)89*b636d99dSDavid van Moolenbroek geneve_opts_print(netdissect_options *ndo, const u_char *bp, u_int len)
90*b636d99dSDavid van Moolenbroek {
91*b636d99dSDavid van Moolenbroek const char *sep = "";
92*b636d99dSDavid van Moolenbroek
93*b636d99dSDavid van Moolenbroek while (len > 0) {
94*b636d99dSDavid van Moolenbroek uint16_t opt_class;
95*b636d99dSDavid van Moolenbroek uint8_t opt_type;
96*b636d99dSDavid van Moolenbroek uint8_t opt_len;
97*b636d99dSDavid van Moolenbroek
98*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "%s", sep));
99*b636d99dSDavid van Moolenbroek sep = ", ";
100*b636d99dSDavid van Moolenbroek
101*b636d99dSDavid van Moolenbroek opt_class = EXTRACT_16BITS(bp);
102*b636d99dSDavid van Moolenbroek opt_type = *(bp + 2);
103*b636d99dSDavid van Moolenbroek opt_len = 4 + ((*(bp + 3) & OPT_LEN_MASK) * 4);
104*b636d99dSDavid van Moolenbroek
105*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "class %s (0x%x) type 0x%x%s len %u",
106*b636d99dSDavid van Moolenbroek format_opt_class(opt_class), opt_class, opt_type,
107*b636d99dSDavid van Moolenbroek opt_type & OPT_TYPE_CRITICAL ? "(C)" : "", opt_len));
108*b636d99dSDavid van Moolenbroek
109*b636d99dSDavid van Moolenbroek if (opt_len > len) {
110*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, " [bad length]"));
111*b636d99dSDavid van Moolenbroek return;
112*b636d99dSDavid van Moolenbroek }
113*b636d99dSDavid van Moolenbroek
114*b636d99dSDavid van Moolenbroek if (ndo->ndo_vflag > 1 && opt_len > 4) {
115*b636d99dSDavid van Moolenbroek uint32_t *print_data = (uint32_t *)(bp + 4);
116*b636d99dSDavid van Moolenbroek int i;
117*b636d99dSDavid van Moolenbroek
118*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, " data"));
119*b636d99dSDavid van Moolenbroek
120*b636d99dSDavid van Moolenbroek for (i = 4; i < opt_len; i += 4) {
121*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, " %08x", EXTRACT_32BITS(print_data)));
122*b636d99dSDavid van Moolenbroek print_data++;
123*b636d99dSDavid van Moolenbroek }
124*b636d99dSDavid van Moolenbroek }
125*b636d99dSDavid van Moolenbroek
126*b636d99dSDavid van Moolenbroek bp += opt_len;
127*b636d99dSDavid van Moolenbroek len -= opt_len;
128*b636d99dSDavid van Moolenbroek }
129*b636d99dSDavid van Moolenbroek }
130*b636d99dSDavid van Moolenbroek
131*b636d99dSDavid van Moolenbroek void
geneve_print(netdissect_options * ndo,const u_char * bp,u_int len)132*b636d99dSDavid van Moolenbroek geneve_print(netdissect_options *ndo, const u_char *bp, u_int len)
133*b636d99dSDavid van Moolenbroek {
134*b636d99dSDavid van Moolenbroek uint8_t ver_opt;
135*b636d99dSDavid van Moolenbroek uint version;
136*b636d99dSDavid van Moolenbroek uint8_t flags;
137*b636d99dSDavid van Moolenbroek uint16_t prot;
138*b636d99dSDavid van Moolenbroek uint32_t vni;
139*b636d99dSDavid van Moolenbroek uint8_t reserved;
140*b636d99dSDavid van Moolenbroek u_int opts_len;
141*b636d99dSDavid van Moolenbroek
142*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "Geneve"));
143*b636d99dSDavid van Moolenbroek
144*b636d99dSDavid van Moolenbroek ND_TCHECK2(*bp, 8);
145*b636d99dSDavid van Moolenbroek
146*b636d99dSDavid van Moolenbroek ver_opt = *bp;
147*b636d99dSDavid van Moolenbroek bp += 1;
148*b636d99dSDavid van Moolenbroek len -= 1;
149*b636d99dSDavid van Moolenbroek
150*b636d99dSDavid van Moolenbroek version = ver_opt >> VER_SHIFT;
151*b636d99dSDavid van Moolenbroek if (version != 0) {
152*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, " ERROR: unknown-version %u", version));
153*b636d99dSDavid van Moolenbroek return;
154*b636d99dSDavid van Moolenbroek }
155*b636d99dSDavid van Moolenbroek
156*b636d99dSDavid van Moolenbroek flags = *bp;
157*b636d99dSDavid van Moolenbroek bp += 1;
158*b636d99dSDavid van Moolenbroek len -= 1;
159*b636d99dSDavid van Moolenbroek
160*b636d99dSDavid van Moolenbroek prot = EXTRACT_16BITS(bp);
161*b636d99dSDavid van Moolenbroek bp += 2;
162*b636d99dSDavid van Moolenbroek len -= 2;
163*b636d99dSDavid van Moolenbroek
164*b636d99dSDavid van Moolenbroek vni = EXTRACT_24BITS(bp);
165*b636d99dSDavid van Moolenbroek bp += 3;
166*b636d99dSDavid van Moolenbroek len -= 3;
167*b636d99dSDavid van Moolenbroek
168*b636d99dSDavid van Moolenbroek reserved = *bp;
169*b636d99dSDavid van Moolenbroek bp += 1;
170*b636d99dSDavid van Moolenbroek len -= 1;
171*b636d99dSDavid van Moolenbroek
172*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", Flags [%s]",
173*b636d99dSDavid van Moolenbroek bittok2str_nosep(geneve_flag_values, "none", flags)));
174*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", vni 0x%x", vni));
175*b636d99dSDavid van Moolenbroek
176*b636d99dSDavid van Moolenbroek if (reserved)
177*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", rsvd 0x%x", reserved));
178*b636d99dSDavid van Moolenbroek
179*b636d99dSDavid van Moolenbroek if (ndo->ndo_eflag)
180*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", proto %s (0x%04x)",
181*b636d99dSDavid van Moolenbroek tok2str(ethertype_values, "unknown", prot), prot));
182*b636d99dSDavid van Moolenbroek
183*b636d99dSDavid van Moolenbroek opts_len = (ver_opt & HDR_OPTS_LEN_MASK) * 4;
184*b636d99dSDavid van Moolenbroek
185*b636d99dSDavid van Moolenbroek if (len < opts_len) {
186*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, " truncated-geneve - %u bytes missing",
187*b636d99dSDavid van Moolenbroek len - opts_len));
188*b636d99dSDavid van Moolenbroek return;
189*b636d99dSDavid van Moolenbroek }
190*b636d99dSDavid van Moolenbroek
191*b636d99dSDavid van Moolenbroek ND_TCHECK2(*bp, opts_len);
192*b636d99dSDavid van Moolenbroek
193*b636d99dSDavid van Moolenbroek if (opts_len > 0) {
194*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ", options ["));
195*b636d99dSDavid van Moolenbroek
196*b636d99dSDavid van Moolenbroek if (ndo->ndo_vflag)
197*b636d99dSDavid van Moolenbroek geneve_opts_print(ndo, bp, opts_len);
198*b636d99dSDavid van Moolenbroek else
199*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "%u bytes", opts_len));
200*b636d99dSDavid van Moolenbroek
201*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "]"));
202*b636d99dSDavid van Moolenbroek }
203*b636d99dSDavid van Moolenbroek
204*b636d99dSDavid van Moolenbroek bp += opts_len;
205*b636d99dSDavid van Moolenbroek len -= opts_len;
206*b636d99dSDavid van Moolenbroek
207*b636d99dSDavid van Moolenbroek if (ndo->ndo_vflag < 1)
208*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, ": "));
209*b636d99dSDavid van Moolenbroek else
210*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "\n\t"));
211*b636d99dSDavid van Moolenbroek
212*b636d99dSDavid van Moolenbroek if (ethertype_print(ndo, prot, bp, len, len) == 0) {
213*b636d99dSDavid van Moolenbroek if (prot == ETHERTYPE_TEB)
214*b636d99dSDavid van Moolenbroek ether_print(ndo, bp, len, len, NULL, NULL);
215*b636d99dSDavid van Moolenbroek else
216*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, "geneve-proto-0x%x", prot));
217*b636d99dSDavid van Moolenbroek }
218*b636d99dSDavid van Moolenbroek
219*b636d99dSDavid van Moolenbroek return;
220*b636d99dSDavid van Moolenbroek
221*b636d99dSDavid van Moolenbroek trunc:
222*b636d99dSDavid van Moolenbroek ND_PRINT((ndo, " [|geneve]"));
223*b636d99dSDavid van Moolenbroek }
224