xref: /minix3/external/bsd/tcpdump/dist/print-geneve.c (revision b636d99d91c3d54204248f643c14627405d4afd1)
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