Skip to content

Commit 36b6a5d

Browse files
committed
erspan: add support for ERSPAN type III.
1 parent 852b62a commit 36b6a5d

File tree

7 files changed

+380
-3
lines changed

7 files changed

+380
-3
lines changed

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
DayOfTheWeek, Month DD, YYYY / The Tcpdump Group
22
Summary for 5.0.0 tcpdump release (so far!)
3+
Add protocol decoding for:
4+
ERSPAN: Add support
35
Refine protocol decoding for:
46
BFD: Add support for S-BFD and spell LAG in uppercase.
57
BGP: Parse BGP extended message support capability

netdissect.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,8 @@ extern void eap_print(netdissect_options *, const u_char *, const u_int);
642642
extern void eapol_print(netdissect_options *, const u_char *);
643643
extern void egp_print(netdissect_options *, const u_char *, u_int);
644644
extern void eigrp_print(netdissect_options *, const u_char *, u_int);
645-
extern void erspan_print(netdissect_options *, uint16_t, const u_char *, u_int);
645+
extern void erspan_print_i_ii(netdissect_options *, uint16_t, const u_char *, u_int);
646+
extern void erspan_print_iii(netdissect_options *, const u_char *, u_int);
646647
extern void esp_print(netdissect_options *, const u_char *, u_int, const u_char *, u_int, int, u_int);
647648
extern u_int ether_print(netdissect_options *, const u_char *, u_int, u_int, void (*)(netdissect_options *, const u_char *), const u_char *);
648649
extern u_int ether_switch_tag_print(netdissect_options *, const u_char *, u_int, u_int, void (*)(netdissect_options *, const u_char *), u_int);

print-erspan.c

Lines changed: 131 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@
4141
#include "extract.h"
4242
#include "gre.h"
4343

44+
/*
45+
* ERSPAN Type II.
46+
*/
4447
#define ERSPAN2_VER_SHIFT 28
4548
#define ERSPAN2_VER_MASK (0xfU << ERSPAN2_VER_SHIFT)
4649
#define ERSPAN2_VER (0x1U << ERSPAN2_VER_SHIFT)
@@ -63,26 +66,35 @@
6366
#define ERSPAN2_INDEX_MASK (0xfffffU << ERSPAN2_INDEX_SHIFT)
6467

6568
void
66-
erspan_print(netdissect_options *ndo, uint16_t flags, const u_char *bp, u_int len)
69+
erspan_print_i_ii(netdissect_options *ndo, uint16_t flags, const u_char *bp, u_int len)
6770
{
6871
uint32_t hdr, ver, vlan, cos, en, sid, index;
6972

7073
ndo->ndo_protocol = "erspan";
7174
nd_print_protocol(ndo);
7275

7376
if (!(flags & GRE_SP)) {
77+
/*
78+
* ERSPAN Type I; no header, just a raw Ethernet frame.
79+
*/
7480
ND_PRINT(" type1: ");
7581
ether_print(ndo, bp, len, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL);
7682
return;
7783
}
7884

85+
/*
86+
* ERSPAN Type II.
87+
*/
7988
ND_ICHECK_U(len, <, 4);
8089
hdr = GET_BE_U_4(bp);
8190
bp += 4;
8291
len -= 4;
8392

8493
ver = hdr & ERSPAN2_VER_MASK;
8594
if (ver != ERSPAN2_VER) {
95+
/*
96+
* Not Type II.
97+
*/
8698
ver >>= ERSPAN2_VER_SHIFT;
8799
ND_PRINT(" erspan-unknown-version-%x", ver);
88100
return;
@@ -135,3 +147,121 @@ erspan_print(netdissect_options *ndo, uint16_t flags, const u_char *bp, u_int le
135147
invalid:
136148
nd_print_invalid(ndo);
137149
}
150+
151+
/*
152+
* ERSPAN Type III.
153+
*/
154+
#define ERSPAN3_VER_SHIFT 28
155+
#define ERSPAN3_VER_MASK (0xfU << ERSPAN3_VER_SHIFT)
156+
#define ERSPAN3_VER (0x2U << ERSPAN3_VER_SHIFT)
157+
#define ERSPAN3_VLAN_SHIFT 16
158+
#define ERSPAN3_VLAN_MASK (0xfffU << ERSPAN3_VLAN_SHIFT)
159+
#define ERSPAN3_COS_SHIFT 13
160+
#define ERSPAN3_COS_MASK (0x7U << ERSPAN3_COS_SHIFT)
161+
#define ERSPAN3_BSO_SHIFT 11
162+
#define ERSPAN3_BSO_MASK (0x3U << ERSPAN3_BSO_SHIFT)
163+
#define ERSPAN3_BSO_GOOD_UNKNOWN 0x0U
164+
#define ERSPAN3_BSO_BAD 0x3U
165+
#define ERSPAN3_BSO_SHORT 0x1U
166+
#define ERSPAN3_BSO_OVERSIZED 0x2U
167+
#define ERSPAN3_T_SHIFT 10
168+
#define ERSPAN3_T_MASK (0x1U << ERSPAN3_T_SHIFT)
169+
#define ERSPAN3_SID_SHIFT 0
170+
#define ERSPAN3_SID_MASK (0x3ffU << ERSPAN3_SID_SHIFT)
171+
#define ERSPAN3_P_SHIFT 15
172+
#define ERSPAN3_P_MASK (0x1U << ERSPAN3_P_MASK)
173+
#define ERSPAN3_FT_SHIFT 10
174+
#define ERSPAN3_FT_MASK (0x1fU << ERSPAN3_FT_MASK)
175+
#define ERSPAN3_HW_ID_SHIFT 4
176+
#define ERSPAN3_HW_ID_MASK (0x3fU << ERSPAN3_HW_ID_MASK)
177+
#define ERSPAN3_D_SHIFT 3
178+
#define ERSPAN3_D_MASK (0x1U << ERSPAN3_D_SHIFT)
179+
#define ERSPAN3_GRA_SHIFT 1
180+
#define ERSPAN3_GRA_MASK (0x3U << ERSPAN3_GRA_MASK)
181+
#define ERSPAN3_O_SHIFT 0
182+
#define ERSPAN3_O_MASK (0x1U << ERSPAN3_O_SHIFT)
183+
184+
static const struct tok erspan3_bso_values[] = {
185+
{ ERSPAN3_BSO_GOOD_UNKNOWN, "Good/unknown" },
186+
{ ERSPAN3_BSO_BAD, "Bad" },
187+
{ ERSPAN3_BSO_SHORT, "Short" },
188+
{ ERSPAN3_BSO_OVERSIZED, "Oversized" },
189+
{ 0, NULL }
190+
};
191+
192+
void
193+
erspan_print_iii(netdissect_options *ndo, const u_char *bp, u_int len)
194+
{
195+
uint32_t hdr, hdr2, ver, cos, sid;
196+
197+
ndo->ndo_protocol = "erspan";
198+
nd_print_protocol(ndo);
199+
200+
/*
201+
* We do not check the GRE flags; ERSPAN Type III always
202+
* has an ERSPAN header.
203+
*/
204+
ND_ICHECK_U(len, <, 4);
205+
hdr = GET_BE_U_4(bp);
206+
bp += 4;
207+
len -= 4;
208+
209+
ver = hdr & ERSPAN3_VER_MASK;
210+
if (ver != ERSPAN3_VER) {
211+
/*
212+
* Not Type III.
213+
*/
214+
ver >>= ERSPAN3_VER_SHIFT;
215+
ND_PRINT(" erspan-unknown-version-%x", ver);
216+
return;
217+
}
218+
219+
if (ndo->ndo_vflag)
220+
ND_PRINT(" type3");
221+
222+
sid = (hdr & ERSPAN3_SID_MASK) >> ERSPAN3_SID_SHIFT;
223+
ND_PRINT(" session %u", sid);
224+
225+
ND_PRINT(" bso %s",
226+
tok2str(erspan3_bso_values, "unknown %x",
227+
(hdr & ERSPAN3_BSO_MASK) >> ERSPAN3_BSO_SHIFT));
228+
229+
if (ndo->ndo_vflag) {
230+
cos = (hdr & ERSPAN3_COS_MASK) >> ERSPAN3_COS_SHIFT;
231+
ND_PRINT(" cos %u", cos);
232+
233+
if (hdr & ERSPAN3_T_MASK)
234+
ND_PRINT(" truncated");
235+
}
236+
237+
/* Skip timestamp */
238+
ND_ICHECK_U(len, <, 4);
239+
bp += 4;
240+
len -= 4;
241+
242+
/* Skip SGT */
243+
ND_ICHECK_U(len, <, 2);
244+
bp += 2;
245+
len -= 2;
246+
247+
/* Additional fields */
248+
ND_ICHECK_U(len, <, 2);
249+
hdr2 = GET_BE_U_2(bp);
250+
bp += 2;
251+
len -= 2;
252+
253+
/* Do we have the platform-specific header? */
254+
if (hdr2 & ERSPAN3_O_MASK) {
255+
/* Yes. Skip it. */
256+
ND_ICHECK_U(len, <, 8);
257+
bp += 8;
258+
len -= 8;
259+
}
260+
261+
ND_PRINT(": ");
262+
ether_print(ndo, bp, len, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL);
263+
return;
264+
265+
invalid:
266+
nd_print_invalid(ndo);
267+
}

print-gre.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,10 @@ gre_print_0(netdissect_options *ndo, const u_char *bp, u_int length)
303303
nsh_print(ndo, bp, len);
304304
break;
305305
case GRE_ERSPAN_I_II:
306-
erspan_print(ndo, flags, bp, len);
306+
erspan_print_i_ii(ndo, flags, bp, len);
307+
break;
308+
case GRE_ERSPAN_III:
309+
erspan_print_iii(ndo, bp, len);
307310
break;
308311
case GRE_CDP:
309312
cdp_print(ndo, bp, len);

tests/TESTLIST

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,7 @@ erspan-type-i-4 erspan-type-i-4.pcap erspan-type-i-4.out -v
582582
erspan-type-ii-1 erspan-type-ii-1.pcap erspan-type-ii-1.out -v
583583
erspan-type-ii-2 erspan-type-ii-2.pcap erspan-type-ii-2.out -v
584584
erspan-type-ii-3 erspan-type-ii-3.pcap erspan-type-ii-3.out -v
585+
erspan-type-iii-1 erspan-type-iii-1.pcap erspan-type-iii-1.out -v
585586

586587
# bad packets from Hanno Böck
587588
# heap-overflow-1 is in non-bsd.tests

0 commit comments

Comments
 (0)