Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-maccontrol.c
blob8254e89a7015f4fe7361cf65a9b935e3e4b340c5
1 /* packet-maccontrol.c
2 * Routines for MAC Control ethernet header disassembly
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
12 * 04/26/2010: WMeier: "Class-Based Flow Control [CBFC] Pause Frame" dissection added
13 * See: http://www.ieee802.org/1/files/public/docs2007/new-cm-barrass-pause-proposal.pdf
14 * 2014-04: David Miller <d.miller[at]cablelabs.com> and
15 * Philip Rosenberg-Watt <p.rosenberg-watt[at]cablelabs.com>
16 * + Added MPCP Gate, Report, and Register messages.
19 #include "config.h"
21 #include <epan/packet.h>
22 #include <epan/expert.h>
23 #include <epan/etypes.h>
25 void proto_register_macctrl(void);
26 void proto_reg_handoff_macctrl(void);
28 static dissector_handle_t macctrl_handle;
30 static int proto_macctrl;
32 static int hf_macctrl_opcode;
33 static int hf_macctrl_timestamp;
34 static int hf_macctrl_pause_time;
35 static int hf_macctrl_cbfc_enbv;
36 static int hf_macctrl_cbfc_enbv_c0;
37 static int hf_macctrl_cbfc_enbv_c1;
38 static int hf_macctrl_cbfc_enbv_c2;
39 static int hf_macctrl_cbfc_enbv_c3;
40 static int hf_macctrl_cbfc_enbv_c4;
41 static int hf_macctrl_cbfc_enbv_c5;
42 static int hf_macctrl_cbfc_enbv_c6;
43 static int hf_macctrl_cbfc_enbv_c7;
44 static int hf_macctrl_cbfc_pause_time_c0;
45 static int hf_macctrl_cbfc_pause_time_c1;
46 static int hf_macctrl_cbfc_pause_time_c2;
47 static int hf_macctrl_cbfc_pause_time_c3;
48 static int hf_macctrl_cbfc_pause_time_c4;
49 static int hf_macctrl_cbfc_pause_time_c5;
50 static int hf_macctrl_cbfc_pause_time_c6;
51 static int hf_macctrl_cbfc_pause_time_c7;
53 static int hf_reg_flags;
54 static int hf_reg_req_grants;
55 static int hf_reg_grants;
56 static int hf_reg_port;
57 static int hf_reg_ack_port;
58 static int hf_reg_time;
59 static int hf_reg_ack_time;
61 static int ett_macctrl;
62 static int ett_macctrl_cbfc_enbv;
63 static int ett_macctrl_cbfc_pause_times;
65 static expert_field ei_macctrl_opcode;
66 static expert_field ei_macctrl_cbfc_enbv;
67 static expert_field ei_macctrl_dst_address;
69 static int * const macctrl_cbfc_enbv_list[] = {
70 &hf_macctrl_cbfc_enbv_c0,
71 &hf_macctrl_cbfc_enbv_c1,
72 &hf_macctrl_cbfc_enbv_c2,
73 &hf_macctrl_cbfc_enbv_c3,
74 &hf_macctrl_cbfc_enbv_c4,
75 &hf_macctrl_cbfc_enbv_c5,
76 &hf_macctrl_cbfc_enbv_c6,
77 &hf_macctrl_cbfc_enbv_c7,
78 NULL
81 static int * const macctrl_cbfc_pause_times_list[] = {
82 &hf_macctrl_cbfc_pause_time_c0,
83 &hf_macctrl_cbfc_pause_time_c1,
84 &hf_macctrl_cbfc_pause_time_c2,
85 &hf_macctrl_cbfc_pause_time_c3,
86 &hf_macctrl_cbfc_pause_time_c4,
87 &hf_macctrl_cbfc_pause_time_c5,
88 &hf_macctrl_cbfc_pause_time_c6,
89 &hf_macctrl_cbfc_pause_time_c7
92 #define MACCTRL_PAUSE 0x0001
93 #define MACCTRL_GATE 0x0002
94 #define MACCTRL_REPORT 0x0003
95 #define MACCTRL_REGISTER_REQ 0x0004
96 #define MACCTRL_REGISTER 0x0005
97 #define MACCTRL_REGISTER_ACK 0x0006
98 #define MACCTRL_CLASS_BASED_FLOW_CNTRL_PAUSE 0x0101
100 static const value_string opcode_vals[] = {
101 { MACCTRL_PAUSE, "Pause" },
102 { MACCTRL_GATE, "Gate" },
103 { MACCTRL_REPORT, "Report" },
104 { MACCTRL_REGISTER_REQ, "Register Req" },
105 { MACCTRL_REGISTER, "Register" },
106 { MACCTRL_REGISTER_ACK, "Register Ack" },
107 { MACCTRL_CLASS_BASED_FLOW_CNTRL_PAUSE, "Class Based Flow Control [CBFC] Pause" },
108 { 0, NULL }
111 static const value_string reg_flags_vals[] = {
112 { 1, "Register" },
113 { 2, "Deregister" },
114 { 3, "Ack" },
115 { 4, "Nack" },
116 { 0, NULL }
119 static const uint8_t dst_addr[] = {0x01, 0x80, 0xC2, 0x00, 0x00, 0x01};
120 static const address macctrl_dst_address = ADDRESS_INIT(AT_ETHER, 6, dst_addr);
122 static int
123 dissect_macctrl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
125 proto_item *ti, *opcode_item;
126 proto_tree *macctrl_tree = NULL;
127 proto_tree *pause_times_tree = NULL;
128 uint16_t opcode;
129 uint16_t pause_time;
130 int i;
131 int offset = 0;
133 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC CTRL");
134 col_clear(pinfo->cinfo, COL_INFO);
136 opcode = tvb_get_ntohs(tvb, 0);
138 ti = proto_tree_add_item(tree, proto_macctrl, tvb, 0, 46, ENC_NA);
139 macctrl_tree = proto_item_add_subtree(ti, ett_macctrl);
141 opcode_item = proto_tree_add_uint(macctrl_tree, hf_macctrl_opcode, tvb, offset, 2, opcode);
142 offset += 2;
143 if ((opcode >= MACCTRL_GATE) && (opcode <= MACCTRL_REGISTER_ACK)) {
144 proto_tree_add_item(macctrl_tree, hf_macctrl_timestamp, tvb, offset, 4, ENC_BIG_ENDIAN);
145 offset += 4;
147 col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(opcode, opcode_vals, "Unknown"));
149 switch (opcode) {
151 case MACCTRL_PAUSE:
152 if (!addresses_equal(&pinfo->dst, &macctrl_dst_address)) {
153 expert_add_info(pinfo, opcode_item, &ei_macctrl_dst_address);
156 pause_time = tvb_get_ntohs(tvb, offset);
157 col_append_fstr(pinfo->cinfo, COL_INFO, ": pause_time: %u quanta",
158 pause_time);
159 proto_tree_add_uint(macctrl_tree, hf_macctrl_pause_time, tvb, offset, 2,
160 pause_time);
161 break;
163 case MACCTRL_GATE:
164 break;
166 case MACCTRL_REPORT:
167 break;
169 case MACCTRL_REGISTER_REQ:
170 /* Flags */
171 proto_tree_add_item(macctrl_tree, hf_reg_flags, tvb,
172 offset, 1, ENC_BIG_ENDIAN);
173 offset++;
175 /* Pending Grants */
176 proto_tree_add_item(macctrl_tree, hf_reg_req_grants, tvb,
177 offset, 1, ENC_BIG_ENDIAN);
178 break;
180 case MACCTRL_REGISTER:
182 /* Assigned Port */
183 proto_tree_add_item(macctrl_tree, hf_reg_port, tvb,
184 offset, 2, ENC_BIG_ENDIAN);
185 offset += 2;
187 /* Flags */
188 proto_tree_add_item(macctrl_tree, hf_reg_flags, tvb,
189 offset, 1, ENC_BIG_ENDIAN);
190 offset++;
192 /* Synch Time */
193 proto_tree_add_item(macctrl_tree, hf_reg_time, tvb,
194 offset, 2, ENC_BIG_ENDIAN);
195 offset += 2;
197 /* Echoed Pending Grants */
198 proto_tree_add_item(macctrl_tree, hf_reg_grants, tvb,
199 offset, 1, ENC_BIG_ENDIAN);
200 break;
202 case MACCTRL_REGISTER_ACK:
204 /* Flags */
205 proto_tree_add_item(macctrl_tree, hf_reg_flags, tvb,
206 offset, 1, ENC_BIG_ENDIAN);
207 offset++;
209 /* Echoed Assigned Port */
210 proto_tree_add_item(macctrl_tree, hf_reg_ack_port, tvb,
211 offset, 2, ENC_BIG_ENDIAN);
212 offset += 2;
214 /* Echoed Synch Time */
215 proto_tree_add_item(macctrl_tree, hf_reg_ack_time, tvb,
216 offset, 2, ENC_BIG_ENDIAN);
217 break;
219 case MACCTRL_CLASS_BASED_FLOW_CNTRL_PAUSE:
220 if (!addresses_equal(&pinfo->dst, &macctrl_dst_address)) {
221 expert_add_info(pinfo, opcode_item, &ei_macctrl_dst_address);
224 ti = proto_tree_add_bitmask(macctrl_tree, tvb, offset, hf_macctrl_cbfc_enbv,
225 ett_macctrl_cbfc_enbv, macctrl_cbfc_enbv_list, ENC_BIG_ENDIAN);
226 if (tvb_get_uint8(tvb, offset) != 0) {
227 expert_add_info(pinfo, ti, &ei_macctrl_cbfc_enbv);
229 offset += 2;
231 pause_times_tree = proto_tree_add_subtree(macctrl_tree, tvb, offset, 8*2, ett_macctrl_cbfc_pause_times, NULL, "CBFC Class Pause Times");
233 for (i=0; i<8; i++) {
234 proto_tree_add_item(pause_times_tree, *macctrl_cbfc_pause_times_list[i], tvb, offset, 2, ENC_BIG_ENDIAN);
235 offset += 2;
237 break;
239 default:
240 expert_add_info(pinfo, opcode_item, &ei_macctrl_opcode);
241 break;
243 return tvb_captured_length(tvb);
246 void
247 proto_register_macctrl(void)
249 static hf_register_info hf[] = {
250 { &hf_macctrl_opcode,
251 { "Opcode", "macc.opcode", FT_UINT16, BASE_HEX,
252 VALS(opcode_vals), 0x0, "MAC Control Opcode", HFILL}},
254 { &hf_macctrl_timestamp,
255 { "Timestamp", "macc.timestamp", FT_UINT32, BASE_DEC,
256 NULL, 0x0, "MAC Control Timestamp", HFILL }},
258 { &hf_macctrl_pause_time,
259 { "pause_time", "macc.pause_time", FT_UINT16, BASE_DEC,
260 NULL, 0x0, "MAC control PAUSE frame pause_time", HFILL }},
262 { &hf_macctrl_cbfc_enbv,
263 { "CBFC Class Enable Vector", "macc.cbfc.enbv", FT_UINT16, BASE_HEX,
264 NULL, 0x0, NULL, HFILL }},
266 { &hf_macctrl_cbfc_enbv_c0,
267 { "C0", "macc.cbfc.enbv.c0", FT_BOOLEAN, 16,
268 NULL, 0x0001, NULL, HFILL }},
270 { &hf_macctrl_cbfc_enbv_c1,
271 { "C1", "macc.cbfc.enbv.c1", FT_BOOLEAN, 16,
272 NULL, 0x0002, NULL, HFILL }},
274 { &hf_macctrl_cbfc_enbv_c2,
275 { "C2", "macc.cbfc.enbv.c2", FT_BOOLEAN, 16,
276 NULL, 0x0004, NULL, HFILL }},
278 { &hf_macctrl_cbfc_enbv_c3,
279 { "C3", "macc.cbfc.enbv.c3", FT_BOOLEAN, 16,
280 NULL, 0x0008, NULL, HFILL }},
282 { &hf_macctrl_cbfc_enbv_c4,
283 { "C4", "macc.cbfc.enbv.c4", FT_BOOLEAN, 16,
284 NULL, 0x0010, NULL, HFILL }},
286 { &hf_macctrl_cbfc_enbv_c5,
287 { "C5", "macc.cbfc.enbv.c5", FT_BOOLEAN, 16,
288 NULL, 0x0020, NULL, HFILL }},
290 { &hf_macctrl_cbfc_enbv_c6,
291 { "C6", "macc.cbfc.enbv.c6", FT_BOOLEAN, 16,
292 NULL, 0x0040, NULL, HFILL }},
294 { &hf_macctrl_cbfc_enbv_c7,
295 { "C7", "macc.cbfc.enbv.c7", FT_BOOLEAN, 16,
296 NULL, 0x0080, NULL, HFILL }},
298 { &hf_macctrl_cbfc_pause_time_c0,
299 { "C0", "macc.cbfc.pause_time.c0", FT_UINT16, BASE_DEC,
300 NULL, 0x0, NULL, HFILL }},
302 { &hf_macctrl_cbfc_pause_time_c1,
303 { "C1", "macc.cbfc.pause_time.c1", FT_UINT16, BASE_DEC,
304 NULL, 0x0, NULL, HFILL }},
306 { &hf_macctrl_cbfc_pause_time_c2,
307 { "C2", "macc.cbfc.pause_time.c2", FT_UINT16, BASE_DEC,
308 NULL, 0x0, NULL, HFILL }},
310 { &hf_macctrl_cbfc_pause_time_c3,
311 { "C3", "macc.cbfc.pause_time.c3", FT_UINT16, BASE_DEC,
312 NULL, 0x0, NULL, HFILL }},
314 { &hf_macctrl_cbfc_pause_time_c4,
315 { "C4", "macc.cbfc.pause_time.c4", FT_UINT16, BASE_DEC,
316 NULL, 0x0, NULL, HFILL }},
318 { &hf_macctrl_cbfc_pause_time_c5,
319 { "C5", "macc.cbfc.pause_time.c5", FT_UINT16, BASE_DEC,
320 NULL, 0x0, NULL, HFILL }},
322 { &hf_macctrl_cbfc_pause_time_c6,
323 { "C6", "macc.cbfc.pause_time.c6", FT_UINT16, BASE_DEC,
324 NULL, 0x0, NULL, HFILL }},
326 { &hf_macctrl_cbfc_pause_time_c7,
327 { "C7", "macc.cbfc.pause_time.c7", FT_UINT16, BASE_DEC,
328 NULL, 0x0, NULL, HFILL }},
330 { &hf_reg_flags,
331 { "Flags", "macc.reg.flags", FT_UINT8, BASE_HEX,
332 VALS(reg_flags_vals), 0x0, NULL, HFILL }},
334 { &hf_reg_req_grants,
335 { "Pending Grants", "macc.regreq.grants", FT_UINT8, BASE_DEC,
336 NULL, 0x0, NULL, HFILL }},
338 { &hf_reg_grants,
339 { "Echoed Pending Grants", "macc.reg.grants", FT_UINT8, BASE_DEC,
340 NULL, 0x0, NULL, HFILL }},
342 { &hf_reg_port,
343 { "Assigned Port (LLID)", "macc.reg.assignedport", FT_UINT16, BASE_DEC,
344 NULL, 0x0, NULL, HFILL }},
346 { &hf_reg_ack_port,
347 { "Echoed Assigned Port (LLID)", "macc.regack.assignedport", FT_UINT16, BASE_DEC,
348 NULL, 0x0, NULL, HFILL }},
350 { &hf_reg_time,
351 { "Sync Time", "macc.reg.synctime", FT_UINT16, BASE_DEC,
352 NULL, 0x0, NULL, HFILL }},
354 { &hf_reg_ack_time,
355 { "Echoed Sync Time", "macc.regack.synctime", FT_UINT16, BASE_DEC,
356 NULL, 0x0, NULL, HFILL }}
359 static int *ett[] = {
360 &ett_macctrl,
361 &ett_macctrl_cbfc_enbv,
362 &ett_macctrl_cbfc_pause_times
365 static ei_register_info ei[] = {
366 { &ei_macctrl_opcode, { "macc.opcode.unknown", PI_PROTOCOL, PI_WARN, "Unknown opcode", EXPFILL }},
367 { &ei_macctrl_cbfc_enbv, { "macc.cbfc.enbv.not_zero", PI_PROTOCOL, PI_WARN, "8 MSbs of ENBV must be 0", EXPFILL }},
368 { &ei_macctrl_dst_address, { "macc.dst_address_invalid", PI_PROTOCOL, PI_WARN, "Destination address must be 01-80-C2-00-00-01", EXPFILL }},
371 expert_module_t* expert_macctrl;
373 proto_macctrl = proto_register_protocol("MAC Control", "MACC", "macc");
374 proto_register_field_array(proto_macctrl, hf, array_length(hf));
375 proto_register_subtree_array(ett, array_length(ett));
376 expert_macctrl = expert_register_protocol(proto_macctrl);
377 expert_register_field_array(expert_macctrl, ei, array_length(ei));
379 macctrl_handle = register_dissector("macc", dissect_macctrl, proto_macctrl);
382 void
383 proto_reg_handoff_macctrl(void)
385 dissector_add_uint("ethertype", ETHERTYPE_MAC_CONTROL, macctrl_handle);
389 * Editor modelines
391 * Local Variables:
392 * c-basic-offset: 2
393 * tab-width: 8
394 * indent-tabs-mode: nil
395 * End:
397 * ex: set shiftwidth=2 tabstop=8 expandtab:
398 * :indentSize=2:tabSize=8:noTabs=true: