Coverage Report

Created: 2026-07-12 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-extreme-exeh.c
Line
Count
Source
1
/* packet-extreme-exeh.c
2
 * Routines for the disassembly of Extreme Networks internal
3
 * Ethernet capture headers
4
 *
5
 * Copyright 2021 Joerg Mayer (see AUTHORS file)
6
 *
7
 * Wireshark - Network traffic analyzer
8
 * By Gerald Combs <gerald@wireshark.org>
9
 * Copyright 1998 Gerald Combs
10
 *
11
 * SPDX-License-Identifier: GPL-2.0-or-later
12
 */
13
14
/*
15
 * It is possible to create internal capture in EXOS with
16
 * debug packet capture ...
17
 *
18
 * List of interfaces on all VRs:
19
 * run script shell.py cat /proc/net/dev
20
 * on older software the following should work as well:
21
 * debug packet capture on cmd-args "-D -1"
22
 *
23
 * See:
24
 *  https://extremeportal.force.com/ExtrArticleDetail?an=000079573
25
 *  https://extremeportal.force.com/ExtrArticleDetail?an=000082238
26
 *  https://extremeportal.force.com/ExtrArticleDetail?an=000079220
27
 *
28
 * This capture begins with an internal header (maybe containing some HiGig variant?),
29
 * followed by the "original" Ethernet frame.
30
 */
31
32
/*
33
 * TODO
34
 * 00 - 01: Unknown
35
 *          always zero for incoming(?)
36
 *          often non-zero for outgoing
37
 * 10 - 23: Unknown (traffic properties?)
38
 * 28 - 29: Unknown
39
 *          always zero(?)
40
 * 32 - 33: Unknown
41
 *          always zero(?)
42
 */
43
44
#include "config.h"
45
46
#include <epan/packet.h>
47
#include <epan/etypes.h>
48
#include <epan/expert.h>
49
#include <epan/tfs.h>
50
51
void proto_register_exeh(void);
52
void proto_reg_handoff_exeh(void);
53
54
static dissector_handle_t exeh_handle;
55
56
static dissector_handle_t ethnofcs_handle;
57
58
static int proto_exeh;
59
/* EXEH data */
60
static int hf_exeh_unknown_00_01;
61
static int hf_exeh_module1;
62
static int hf_exeh_port1;
63
static int hf_exeh_module2; /* m2 + p2 always zero for outgoing(?) */
64
static int hf_exeh_port2;
65
static int hf_exeh_unknown_10_16;
66
static int hf_exeh_unknown_17_0xfd;
67
static int hf_exeh_unknown_17_0x02;
68
static int hf_exeh_unknown_18_21;
69
static int hf_exeh_unknown_22_23;
70
static int hf_exeh_incoming_framesource;
71
static int hf_exeh_outgoing_framesource;
72
static int hf_exeh_vlan;
73
static int hf_exeh_unknown_28_29;
74
static int hf_exeh_dir;
75
static int hf_exeh_unknown_32_33;
76
static int hf_exeh_etype;
77
static int hf_exeh_etypelen;
78
static int hf_exeh_etypedata;
79
80
static expert_field ei_exeh_unexpected_value;
81
static expert_field ei_exeh_unequal_ports;
82
static expert_field ei_exeh_incoming_framesource;
83
static expert_field ei_exeh_outgoing_framesource;
84
85
static int ett_exeh;
86
87
static const value_string exeh_direction_vals[] = {
88
  {0x07, "Incoming"},
89
  {0xff, "Outgoing"},
90
91
  {0, NULL},
92
};
93
94
static const value_string exeh_outgoing_vlanid_vals[] = {
95
  {0x0000, "No tag or VLAN ID = 0"},
96
  {0x000f, "Has VLAN ID"},
97
98
  {0, NULL},
99
};
100
101
static const value_string exeh_incoming_framesource_vals[] = {
102
  {0x0000, "N/A"},
103
104
  {0, NULL},
105
};
106
107
static const value_string exeh_outgoing_framesource_vals[] = {
108
  {0x0000, "CPU"},
109
  {0x4248, "Broadcom Hardware"},
110
111
  {0, NULL},
112
};
113
114
115
static int
116
dissect_exeh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
117
18
{
118
18
  proto_item *ti;
119
18
  proto_tree *exeh_tree;
120
18
  uint32_t offset = 0;
121
18
  uint32_t etype, module1, port1, module2, port2, direction, framesource;
122
18
  int32_t databytes;
123
18
  tvbuff_t *frame_tvb;
124
125
18
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "EXEH");
126
18
  col_set_str(pinfo->cinfo, COL_INFO, "EXEH:");
127
128
18
  ti = proto_tree_add_item(tree, proto_exeh, tvb, offset, -1,
129
18
         ENC_NA);
130
18
  exeh_tree = proto_item_add_subtree(ti, ett_exeh);
131
132
18
  direction = tvb_get_ntohs(tvb, 30);
133
18
  proto_tree_add_item(exeh_tree, hf_exeh_unknown_00_01, tvb, offset, 2, ENC_NA);
134
18
  offset += 2;
135
18
  proto_tree_add_item_ret_uint(exeh_tree, hf_exeh_module1, tvb, offset, 2, ENC_BIG_ENDIAN, &module1);
136
18
  offset += 2;
137
18
  proto_tree_add_item_ret_uint(exeh_tree, hf_exeh_port1, tvb, offset, 2, ENC_BIG_ENDIAN, &port1);
138
18
  offset += 2;
139
18
  proto_tree_add_item_ret_uint(exeh_tree, hf_exeh_module2, tvb, offset, 2, ENC_BIG_ENDIAN, &module2);
140
18
  offset += 2;
141
18
  ti = proto_tree_add_item_ret_uint(exeh_tree, hf_exeh_port2, tvb, offset, 2, ENC_BIG_ENDIAN, &port2);
142
18
  if ( !(direction == 255 && module2 == 0) && (module1 != module2 || port1 != port2) )
143
13
      expert_add_info(pinfo, ti, &ei_exeh_unequal_ports);
144
18
  offset += 2;
145
18
  proto_tree_add_item(exeh_tree, hf_exeh_unknown_10_16, tvb, offset, 7, ENC_NA);
146
18
  offset += 7;
147
18
  proto_tree_add_item(exeh_tree, hf_exeh_unknown_17_0xfd, tvb, offset, 1, ENC_NA);
148
18
  proto_tree_add_item(exeh_tree, hf_exeh_unknown_17_0x02, tvb, offset, 1, ENC_NA);
149
18
  offset += 1;
150
18
  proto_tree_add_item(exeh_tree, hf_exeh_unknown_18_21, tvb, offset, 4, ENC_NA);
151
18
  offset += 4;
152
18
  proto_tree_add_item(exeh_tree, hf_exeh_unknown_22_23, tvb, offset, 2, ENC_BIG_ENDIAN);
153
18
  offset += 2;
154
18
  if ( direction == 7 ) {
155
0
    ti = proto_tree_add_item_ret_uint(exeh_tree, hf_exeh_incoming_framesource, tvb, offset, 2, ENC_BIG_ENDIAN, &framesource);
156
0
    if ( framesource != 0 )
157
0
      expert_add_info(pinfo, ti, &ei_exeh_incoming_framesource);
158
18
  } else { /* Direction == 255 */
159
18
    ti = proto_tree_add_item_ret_uint(exeh_tree, hf_exeh_outgoing_framesource, tvb, offset, 2, ENC_BIG_ENDIAN, &framesource);
160
18
    if ( framesource != 0 && framesource != 0x4248 )
161
8
      expert_add_info(pinfo, ti, &ei_exeh_outgoing_framesource);
162
18
  }
163
18
  offset += 2;
164
18
  proto_tree_add_item(exeh_tree, hf_exeh_vlan, tvb, offset, 2, ENC_BIG_ENDIAN);
165
18
  offset += 2;
166
18
  proto_tree_add_item(exeh_tree, hf_exeh_unknown_28_29, tvb, offset, 2, ENC_NA);
167
18
  offset += 2;
168
18
  proto_tree_add_item(exeh_tree, hf_exeh_dir, tvb, offset, 2, ENC_BIG_ENDIAN);
169
18
  offset += 2;
170
18
  proto_tree_add_item(exeh_tree, hf_exeh_unknown_32_33, tvb, offset, 2, ENC_NA);
171
18
  offset += 2;
172
18
  proto_tree_add_item_ret_uint(exeh_tree, hf_exeh_etype, tvb, offset, 2, ENC_BIG_ENDIAN, &etype);
173
18
  switch (etype) {
174
0
  case 0x8100: /* VLAN/VMAN Tag */
175
0
    ti = proto_tree_add_item_ret_int(exeh_tree, hf_exeh_etypelen, tvb, offset+2, 2, ENC_BIG_ENDIAN, &databytes);
176
0
    if ((int)tvb_reported_length_remaining(tvb, offset) != databytes)
177
0
      expert_add_info(pinfo, ti, &ei_exeh_unexpected_value);
178
0
    break;
179
15
  default:
180
15
    proto_tree_add_item(exeh_tree, hf_exeh_etypedata, tvb, offset+2, 2, ENC_BIG_ENDIAN);
181
18
  }
182
13
  offset += 4;
183
184
13
  frame_tvb = tvb_new_subset_remaining(tvb, offset);
185
13
  call_dissector(ethnofcs_handle, frame_tvb, pinfo, tree);
186
187
13
  return tvb_captured_length(tvb);
188
18
}
189
190
void
191
proto_register_exeh(void)
192
15
{
193
15
  static hf_register_info hf[] = {
194
195
  /* EXEH data */
196
15
    { &hf_exeh_unknown_00_01,
197
15
    { "Unknown_00", "exeh.unknown00", FT_BYTES, BASE_NONE, NULL,
198
15
      0x0, NULL, HFILL }},
199
200
15
    { &hf_exeh_module1,
201
15
    { "Module", "exeh.module1", FT_UINT16, BASE_DEC, NULL,
202
15
      0x0, NULL, HFILL }},
203
204
15
    { &hf_exeh_port1,
205
15
    { "Port", "exeh.port1", FT_UINT16, BASE_DEC, NULL,
206
15
      0x0, NULL, HFILL }},
207
208
15
    { &hf_exeh_module2,
209
15
    { "Module", "exeh.module2", FT_UINT16, BASE_DEC, NULL,
210
15
      0x0, NULL, HFILL }},
211
212
15
    { &hf_exeh_port2,
213
15
    { "Port", "exeh.port2", FT_UINT16, BASE_DEC, NULL,
214
15
      0x0, NULL, HFILL }},
215
216
15
    { &hf_exeh_unknown_10_16,
217
15
    { "Unknown_10 (incoming specific?)",  "exeh.unknown10", FT_BYTES, BASE_NONE, NULL,
218
15
      0x0, NULL, HFILL }},
219
220
15
    { &hf_exeh_unknown_17_0xfd,
221
15
    { "Unknown_17", "exeh.unknown17", FT_UINT8, BASE_HEX, NULL,
222
15
      0xfd, NULL, HFILL }},
223
224
15
    { &hf_exeh_unknown_17_0x02,
225
15
    { "Unknown_17 (Add dot1Q?)",  "exeh.unknown17.dot1q", FT_BOOLEAN, 8, TFS(&tfs_no_yes),
226
15
      0x02, NULL, HFILL }},
227
228
15
    { &hf_exeh_unknown_18_21,
229
15
    { "Unknown_18 (outgoing specific?)",  "exeh.unknown18", FT_BYTES, BASE_NONE, NULL,
230
15
      0x0, NULL, HFILL }},
231
232
15
    { &hf_exeh_unknown_22_23,
233
15
    { "Add VLAN ID?", "exeh.unknown22", FT_UINT16, BASE_NONE, VALS(exeh_outgoing_vlanid_vals),
234
15
      0x0, NULL, HFILL }},
235
236
15
    { &hf_exeh_incoming_framesource,
237
15
    { "Frame source", "exeh.framesource", FT_UINT16, BASE_HEX, VALS(exeh_incoming_framesource_vals),
238
15
      0x0, NULL, HFILL }},
239
240
15
    { &hf_exeh_outgoing_framesource,
241
15
    { "Frame source", "exeh.framesource", FT_UINT16, BASE_HEX, VALS(exeh_outgoing_framesource_vals),
242
15
      0x0, NULL, HFILL }},
243
244
15
    { &hf_exeh_vlan,
245
15
    { "Transport VLAN", "exeh.vlan", FT_UINT16, BASE_DEC, NULL,
246
15
      0x0, NULL, HFILL }},
247
248
15
    { &hf_exeh_unknown_28_29,
249
15
    { "Unknown_28", "exeh.unknown28", FT_BYTES, BASE_NONE, NULL,
250
15
      0x0, NULL, HFILL }},
251
252
15
    { &hf_exeh_dir,
253
15
    { "Direction",  "exeh.direction", FT_UINT16, BASE_HEX, VALS(exeh_direction_vals),
254
15
      0x0, NULL, HFILL }},
255
256
15
    { &hf_exeh_unknown_32_33,
257
15
    { "Unknown_32", "exeh.unknown32", FT_BYTES, BASE_NONE, NULL,
258
15
      0x0, NULL, HFILL }},
259
260
15
    { &hf_exeh_etype,
261
15
    { "Etype",  "exeh.etype", FT_UINT16, BASE_HEX, NULL,
262
15
      0x0, NULL, HFILL }},
263
264
15
    { &hf_exeh_etypedata,
265
15
    { "Etype data", "exeh.etypedata", FT_UINT16, BASE_HEX, NULL,
266
15
      0x0, NULL, HFILL }},
267
268
15
    { &hf_exeh_etypelen,
269
15
    { "Length", "exeh.etypelen", FT_INT16, BASE_DEC, NULL,
270
15
      0x0, "Bytes from 8100 to end of frame", HFILL }},
271
15
  };
272
273
274
15
  static int *ett[] = {
275
15
    &ett_exeh,
276
15
  };
277
278
15
  static ei_register_info ei[] = {
279
15
    { &ei_exeh_unexpected_value, { "exeh.unexpected_value", PI_PROTOCOL, PI_WARN, "Unexpected length", EXPFILL }},
280
15
    { &ei_exeh_unequal_ports, { "exeh.unequal_ports", PI_PROTOCOL, PI_WARN, "Unequal ports", EXPFILL }},
281
15
    { &ei_exeh_incoming_framesource, { "exeh.incoming_framesource", PI_PROTOCOL, PI_WARN, "Incoming framesource non-zero", EXPFILL }},
282
15
    { &ei_exeh_outgoing_framesource, { "exeh.outgoing_framesource", PI_PROTOCOL, PI_WARN, "Outgoing framesource unknown magic", EXPFILL }},
283
15
  };
284
285
15
  expert_module_t* expert_exeh;
286
287
15
  proto_exeh = proto_register_protocol("EXtreme extra Eth Header", "EXEH", "exeh");
288
15
  proto_register_field_array(proto_exeh, hf, array_length(hf));
289
15
  proto_register_subtree_array(ett, array_length(ett));
290
15
  expert_exeh = expert_register_protocol(proto_exeh);
291
15
  expert_register_field_array(expert_exeh, ei, array_length(ei));
292
293
15
  exeh_handle = register_dissector("exeh", dissect_exeh, proto_exeh);
294
15
}
295
296
void
297
proto_reg_handoff_exeh(void)
298
15
{
299
15
  ethnofcs_handle = find_dissector_add_dependency("eth_withoutfcs", proto_exeh);
300
301
15
  dissector_add_uint("ethertype", ETHERTYPE_EXEH, exeh_handle);
302
15
}
303
304
/*
305
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
306
 *
307
 * Local variables:
308
 * c-basic-offset: 8
309
 * tab-width: 8
310
 * indent-tabs-mode: t
311
 * End:
312
 *
313
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
314
 * :indentSize=8:tabSize=8:noTabs=false:
315
 */