epan/dissectors/pidl/samr/samr.cnf cnf_dissect_lsa_BinaryString => lsarpc_dissect_str...
[wireshark-sm.git] / epan / dissectors / packet-pagp.c
blob6769fcb21462c8627f724a7b59134a9573c22dee
1 /* packet-pagp.c
2 * Routines for PAgP (Port Aggregation Protocol - aka FEC) dissection
3 * Original Author Mark C. Brown <mbrown@hp.com>
4 * Copyright (C) 2004 Hewlett-Packard Development Company, L.P.
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * Copied from packet-slowprotocols.c
12 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include "config.h"
17 #include <epan/packet.h>
18 #include <epan/expert.h>
19 #include <epan/to_str.h>
20 #include <epan/cisco_pid.h>
21 #include <epan/tfs.h>
22 #include <wsutil/array.h>
24 void proto_register_pagp(void);
25 void proto_reg_handoff_pagp(void);
27 static dissector_handle_t pagp_handle;
29 /* Offsets of fields within a PagP PDU */
31 #define PAGP_VERSION_NUMBER 0
33 #define PAGP_FLAGS 1
34 #define PAGP_LOCAL_DEVICE_ID 2
35 #define PAGP_LOCAL_LEARN_CAP 8
36 #define PAGP_LOCAL_PORT_PRIORITY 9
37 #define PAGP_LOCAL_SENT_PORT_IFINDEX 10
38 #define PAGP_LOCAL_GROUP_CAPABILITY 14
39 #define PAGP_LOCAL_GROUP_IFINDEX 18
40 #define PAGP_PARTNER_DEVICE_ID 22
41 #define PAGP_PARTNER_LEARN_CAP 28
42 #define PAGP_PARTNER_PORT_PRIORITY 29
43 #define PAGP_PARTNER_SENT_PORT_IFINDEX 30
44 #define PAGP_PARTNER_GROUP_CAPABILITY 34
45 #define PAGP_PARTNER_GROUP_IFINDEX 38
46 #define PAGP_PARTNER_COUNT 42
47 #define PAGP_NUM_TLVS 44
48 #define PAGP_FIRST_TLV 46
50 #define PAGP_FLUSH_LOCAL_DEVICE_ID 2
51 #define PAGP_FLUSH_PARTNER_DEVICE_ID 8
52 #define PAGP_FLUSH_TRANSACTION_ID 14
54 /* PDU Versions */
56 #define PAGP_INFO_PDU 1
57 #define PAGP_FLUSH_PDU 2
59 /* Flag bits */
61 #define PAGP_FLAGS_SLOW_HELLO 0x01
62 #define PAGP_FLAGS_AUTO_MODE 0x02
63 #define PAGP_FLAGS_CONSISTENT_STATE 0x04
65 /* TLV Types */
68 #define PAGP_TLV_DEVICE_NAME 1
69 #define PAGP_TLV_PORT_NAME 2
70 #define PAGP_TLV_AGPORT_MAC 3
71 #define PAGP_TLV_RESERVED 4
73 /* Initialise the protocol and registered fields */
75 static int proto_pagp;
77 static int hf_pagp_version_number;
79 static int hf_pagp_flags;
80 static int hf_pagp_flags_slow_hello;
81 static int hf_pagp_flags_auto_mode;
82 static int hf_pagp_flags_consistent_state;
83 static int hf_pagp_local_device_id;
84 static int hf_pagp_local_learn_cap;
85 static int hf_pagp_local_port_priority;
86 static int hf_pagp_local_sent_port_ifindex;
87 static int hf_pagp_local_group_capability;
88 static int hf_pagp_local_group_ifindex;
89 static int hf_pagp_partner_device_id;
90 static int hf_pagp_partner_learn_cap;
91 static int hf_pagp_partner_port_priority;
92 static int hf_pagp_partner_sent_port_ifindex;
93 static int hf_pagp_partner_group_capability;
94 static int hf_pagp_partner_group_ifindex;
95 static int hf_pagp_partner_count;
96 static int hf_pagp_num_tlvs;
97 static int hf_pagp_tlv;
98 static int hf_pagp_tlv_length;
99 static int hf_pagp_tlv_device_name;
100 static int hf_pagp_tlv_port_name;
101 static int hf_pagp_tlv_agport_mac;
103 static int hf_pagp_flush_local_device_id;
104 static int hf_pagp_flush_partner_device_id;
105 static int hf_pagp_flush_transaction_id;
107 /* Initialise the subtree pointers */
109 static int ett_pagp;
110 static int ett_pagp_flags;
111 static int ett_pagp_tlvs;
113 static expert_field ei_pagp_tlv_length;
115 /* General declarations and macros */
117 static const value_string pdu_vers[] = {
118 { 1, "Info PDU" },
119 { 2, "Flush PDU" },
120 { 0, NULL }
123 static const value_string learn_cap[] = {
124 { 1, "Source-based Distribution" },
125 { 2, "Arbitrary Distribution" },
126 { 0, NULL }
129 static const value_string tlv_types[] = {
130 { 1, "Device Name TLV" },
131 { 2, "Physical Port Name TLV" },
132 { 3, "Agport MAC Address" },
133 { 4, "Reserved" },
134 { 0, NULL }
137 static const true_false_string automode = {
138 "Yes",
139 "Desirable Mode"
142 /* Code to actually dissect the PAGP packets */
143 static int
144 dissect_pagp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
146 uint32_t raw_word;
147 uint16_t num_tlvs;
148 uint16_t tlv;
149 uint16_t len;
150 uint16_t ii;
151 uint16_t offset = PAGP_FIRST_TLV;
152 uint8_t raw_octet;
154 uint8_t flags;
156 proto_tree *pagp_tree = NULL;
157 proto_item *pagp_item, *len_item;
158 proto_tree *tlv_tree;
159 static int * const pagp_flags[] = {
160 &hf_pagp_flags_slow_hello,
161 &hf_pagp_flags_auto_mode,
162 &hf_pagp_flags_consistent_state,
163 NULL,
167 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PAGP"); /* PAGP Protocol */
169 col_clear(pinfo->cinfo, COL_INFO);
171 raw_octet = tvb_get_uint8(tvb, PAGP_VERSION_NUMBER);
172 if (tree) {
173 pagp_item = proto_tree_add_protocol_format(tree, proto_pagp, tvb,
174 0, -1, "Port Aggregation Protocol");
175 pagp_tree = proto_item_add_subtree(pagp_item, ett_pagp);
176 proto_tree_add_uint(pagp_tree, hf_pagp_version_number, tvb,
177 PAGP_VERSION_NUMBER, 1, raw_octet);
179 col_append_str(pinfo->cinfo, COL_INFO,
180 val_to_str_const(raw_octet, pdu_vers, "Unknown PDU version"));
182 if (raw_octet == PAGP_FLUSH_PDU) {
184 col_append_fstr(pinfo->cinfo, COL_INFO, "; Local DevID: %s",
185 tvb_ether_to_str(pinfo->pool, tvb, PAGP_FLUSH_LOCAL_DEVICE_ID));
187 proto_tree_add_item(pagp_tree, hf_pagp_flush_local_device_id, tvb,
188 PAGP_FLUSH_LOCAL_DEVICE_ID, 6, ENC_NA);
190 col_append_fstr(pinfo->cinfo, COL_INFO, ", Partner DevID: %s",
191 tvb_ether_to_str(pinfo->pool, tvb, PAGP_FLUSH_PARTNER_DEVICE_ID));
193 proto_tree_add_item(pagp_tree, hf_pagp_flush_partner_device_id, tvb,
194 PAGP_FLUSH_PARTNER_DEVICE_ID, 6, ENC_NA);
196 raw_word = tvb_get_ntohl(tvb, PAGP_FLUSH_TRANSACTION_ID);
197 col_append_fstr(pinfo->cinfo, COL_INFO, "; Transaction ID: 0x%x ", raw_word);
199 proto_tree_add_uint(pagp_tree, hf_pagp_flush_transaction_id, tvb,
200 PAGP_FLUSH_TRANSACTION_ID, 4, raw_word);
201 return tvb_captured_length(tvb);
204 /* Info PDU */
206 flags = tvb_get_uint8(tvb, PAGP_FLAGS);
207 col_append_fstr(pinfo->cinfo, COL_INFO, "; Flags 0x%x", flags);
209 proto_tree_add_bitmask(pagp_tree, tvb, PAGP_FLAGS, hf_pagp_flags, ett_pagp_flags, pagp_flags, ENC_NA);
211 col_append_fstr(pinfo->cinfo, COL_INFO, "; Local DevID: %s",
212 tvb_ether_to_str(pinfo->pool, tvb, PAGP_LOCAL_DEVICE_ID));
214 proto_tree_add_item(pagp_tree, hf_pagp_local_device_id, tvb,
215 PAGP_LOCAL_DEVICE_ID, 6, ENC_NA);
217 if (tree) {
218 proto_tree_add_item(pagp_tree, hf_pagp_local_learn_cap, tvb,
219 PAGP_LOCAL_LEARN_CAP, 1, ENC_NA);
221 proto_tree_add_item(pagp_tree, hf_pagp_local_port_priority, tvb,
222 PAGP_LOCAL_PORT_PRIORITY, 1, ENC_NA);
224 proto_tree_add_item(pagp_tree, hf_pagp_local_sent_port_ifindex, tvb,
225 PAGP_LOCAL_SENT_PORT_IFINDEX, 4, ENC_BIG_ENDIAN);
227 proto_tree_add_item(pagp_tree, hf_pagp_local_group_capability, tvb,
228 PAGP_LOCAL_GROUP_CAPABILITY, 4, ENC_BIG_ENDIAN);
230 proto_tree_add_item(pagp_tree, hf_pagp_local_group_ifindex, tvb,
231 PAGP_LOCAL_GROUP_IFINDEX, 4, ENC_BIG_ENDIAN);
234 col_append_fstr(pinfo->cinfo, COL_INFO, ", Partner DevID: %s",
235 tvb_ether_to_str(pinfo->pool, tvb, PAGP_PARTNER_DEVICE_ID));
237 proto_tree_add_item(pagp_tree, hf_pagp_partner_device_id, tvb,
238 PAGP_PARTNER_DEVICE_ID, 6, ENC_NA);
240 proto_tree_add_item(pagp_tree, hf_pagp_partner_learn_cap, tvb,
241 PAGP_PARTNER_LEARN_CAP, 1, ENC_NA);
243 proto_tree_add_item(pagp_tree, hf_pagp_partner_port_priority, tvb,
244 PAGP_PARTNER_PORT_PRIORITY, 1, ENC_NA);
246 proto_tree_add_item(pagp_tree, hf_pagp_partner_sent_port_ifindex, tvb,
247 PAGP_PARTNER_SENT_PORT_IFINDEX, 4, ENC_BIG_ENDIAN);
249 proto_tree_add_item(pagp_tree, hf_pagp_partner_group_capability, tvb,
250 PAGP_PARTNER_GROUP_CAPABILITY, 4, ENC_BIG_ENDIAN);
252 proto_tree_add_item(pagp_tree, hf_pagp_partner_group_ifindex, tvb,
253 PAGP_PARTNER_GROUP_IFINDEX, 4, ENC_BIG_ENDIAN);
255 proto_tree_add_item(pagp_tree, hf_pagp_partner_count, tvb,
256 PAGP_PARTNER_COUNT, 2, ENC_BIG_ENDIAN);
258 num_tlvs = tvb_get_ntohs(tvb, PAGP_NUM_TLVS);
259 proto_tree_add_uint(pagp_tree, hf_pagp_num_tlvs, tvb,
260 PAGP_NUM_TLVS, 2, num_tlvs);
262 /* dump TLV entries */
264 for ( ii = 0; ii < num_tlvs; ii++ ) {
266 tlv = tvb_get_ntohs(tvb, offset);
267 len = tvb_get_ntohs(tvb, offset + 2);
269 tlv_tree = proto_tree_add_subtree_format(pagp_tree, tvb, offset, len,
270 ett_pagp_tlvs, NULL, "TLV Entry #%d", ii+1);
272 proto_tree_add_uint(tlv_tree, hf_pagp_tlv, tvb, offset, 2, tlv);
273 len_item = proto_tree_add_uint(tlv_tree, hf_pagp_tlv_length, tvb, offset+2, 2, len);
274 if ( len == 0 ) {
275 expert_add_info_format(pinfo, len_item, &ei_pagp_tlv_length,
276 "Unknown data - TLV len=0");
277 return offset;
279 if ( tvb_reported_length_remaining(tvb, offset) < len ) {
280 expert_add_info_format(pinfo, len_item, &ei_pagp_tlv_length,
281 "TLV length too large");
282 return offset;
285 switch (tlv) {
286 case PAGP_TLV_DEVICE_NAME:
287 proto_tree_add_item(tlv_tree, hf_pagp_tlv_device_name,
288 tvb, offset+4, len-4, ENC_NA|ENC_ASCII);
289 break;
290 case PAGP_TLV_PORT_NAME:
291 proto_tree_add_item(tlv_tree, hf_pagp_tlv_port_name,
292 tvb, offset+4, len-4, ENC_NA|ENC_ASCII);
293 break;
294 case PAGP_TLV_AGPORT_MAC:
295 proto_tree_add_item(tlv_tree, hf_pagp_tlv_agport_mac,
296 tvb, offset+4, 6, ENC_NA);
297 break;
298 case PAGP_TLV_RESERVED:
299 break;
302 offset += len;
305 return tvb_captured_length(tvb);
309 /* Register the protocol with Wireshark */
311 void
312 proto_register_pagp(void)
314 /* Setup list of header fields */
316 static hf_register_info hf[] = {
318 { &hf_pagp_version_number,
319 { "Version", "pagp.version",
320 FT_UINT8, BASE_HEX, VALS(pdu_vers), 0x0,
321 "Identifies the PAgP PDU version: 1 = Info, 2 = Flush", HFILL }},
323 { &hf_pagp_flags,
324 { "Flags", "pagp.flags",
325 FT_UINT8, BASE_HEX, NULL, 0x0,
326 "Information flags", HFILL }},
328 { &hf_pagp_flags_slow_hello,
329 { "Slow Hello", "pagp.flags.slowhello",
330 FT_BOOLEAN, 8, TFS(&tfs_yes_no), PAGP_FLAGS_SLOW_HELLO,
331 "1 = using Slow Hello, 0 = Slow Hello disabled", HFILL }},
333 { &hf_pagp_flags_auto_mode,
334 { "Auto Mode", "pagp.flags.automode",
335 FT_BOOLEAN, 8, TFS(&automode), PAGP_FLAGS_AUTO_MODE,
336 "1 = Auto Mode enabled, 0 = Desirable Mode", HFILL }},
338 { &hf_pagp_flags_consistent_state,
339 { "Consistent State", "pagp.flags.state",
340 FT_BOOLEAN, 8, NULL, PAGP_FLAGS_CONSISTENT_STATE,
341 "1 = Consistent State, 0 = Not Ready", HFILL }},
343 { &hf_pagp_local_device_id,
344 { "Local Device ID", "pagp.localdevid",
345 FT_ETHER, BASE_NONE, NULL, 0x0,
346 NULL, HFILL }},
348 { &hf_pagp_local_learn_cap,
349 { "Local Learn Capability", "pagp.localearncap",
350 FT_UINT8, BASE_HEX, VALS(learn_cap), 0x0,
351 NULL, HFILL }},
353 { &hf_pagp_local_port_priority,
354 { "Local Port Hot Standby Priority", "pagp.localportpri",
355 FT_UINT8, BASE_DEC, NULL, 0x0,
356 "The local hot standby priority assigned to this port", HFILL }},
358 { &hf_pagp_local_sent_port_ifindex,
359 { "Local Sent Port ifindex", "pagp.localsentportifindex",
360 FT_UINT32, BASE_DEC, NULL, 0x0,
361 "The interface index of the local port used to send PDU", HFILL }},
363 { &hf_pagp_local_group_capability,
364 { "Local Group Capability", "pagp.localgroupcap",
365 FT_UINT32, BASE_HEX, NULL, 0x0,
366 "The local group capability", HFILL }},
368 { &hf_pagp_local_group_ifindex,
369 { "Local Group ifindex", "pagp.localgroupifindex",
370 FT_UINT32, BASE_DEC, NULL, 0x0,
371 "The local group interface index", HFILL }},
373 { &hf_pagp_partner_device_id,
374 { "Partner Device ID", "pagp.partnerdevid",
375 FT_ETHER, BASE_NONE, NULL, 0x0,
376 "Remote Device ID (MAC)", HFILL }},
378 { &hf_pagp_partner_learn_cap,
379 { "Partner Learn Capability", "pagp.partnerlearncap",
380 FT_UINT8, BASE_HEX, VALS(learn_cap), 0x0,
381 "Remote learn capability", HFILL }},
383 { &hf_pagp_partner_port_priority,
384 { "Partner Port Hot Standby Priority", "pagp.partnerportpri",
385 FT_UINT8, BASE_DEC, NULL, 0x0,
386 "Remote port priority", HFILL }},
388 { &hf_pagp_partner_sent_port_ifindex,
389 { "Partner Sent Port ifindex", "pagp.partnersentportifindex",
390 FT_UINT32, BASE_DEC, NULL, 0x0,
391 "Remote port interface index sent", HFILL }},
393 { &hf_pagp_partner_group_capability,
394 { "Partner Group Capability", "pagp.partnergroupcap",
395 FT_UINT32, BASE_HEX, NULL, 0x0,
396 "Remote group capability", HFILL }},
398 { &hf_pagp_partner_group_ifindex,
399 { "Partner Group ifindex", "pagp.partnergroupifindex",
400 FT_UINT32, BASE_DEC, NULL, 0x0,
401 "Remote group interface index", HFILL }},
403 { &hf_pagp_partner_count,
404 { "Partner Count", "pagp.partnercount",
405 FT_UINT16, BASE_DEC, NULL, 0x0,
406 NULL, HFILL }},
408 { &hf_pagp_num_tlvs,
409 { "Number of TLVs", "pagp.numtlvs",
410 FT_UINT16, BASE_DEC, NULL, 0x0,
411 "Number of TLVs following", HFILL }},
413 { &hf_pagp_tlv,
414 { "Type", "pagp.tlv",
415 FT_UINT16, BASE_DEC, VALS(tlv_types), 0x0,
416 "Type/Length/Value", HFILL }},
418 { &hf_pagp_tlv_length,
419 { "Length", "pagp.tlv_length",
420 FT_UINT16, BASE_DEC, NULL, 0x0,
421 NULL, HFILL }},
423 { &hf_pagp_tlv_device_name,
424 { "Device Name", "pagp.tlvdevname",
425 FT_STRING, BASE_NONE, NULL, 0x0,
426 "sysName of device", HFILL }},
428 { &hf_pagp_tlv_port_name,
429 { "Physical Port Name", "pagp.tlvportname",
430 FT_STRING, BASE_NONE, NULL, 0x0,
431 "Name of port used to send PDU", HFILL }},
433 { &hf_pagp_tlv_agport_mac,
434 { "Agport MAC Address", "pagp.tlvagportmac",
435 FT_ETHER, BASE_NONE, NULL, 0x0,
436 "Source MAC on frames for this aggregate", HFILL }},
438 { &hf_pagp_flush_local_device_id,
439 { "Flush Local Device ID", "pagp.flushlocaldevid",
440 FT_ETHER, BASE_NONE, NULL, 0x0,
441 NULL, HFILL }},
443 { &hf_pagp_flush_partner_device_id,
444 { "Flush Partner Device ID", "pagp.flushpartnerdevid",
445 FT_ETHER, BASE_NONE, NULL, 0x0,
446 "Flush remote device ID", HFILL }},
448 { &hf_pagp_flush_transaction_id,
449 { "Transaction ID", "pagp.transid",
450 FT_UINT32, BASE_HEX, NULL, 0x0,
451 "Flush transaction ID", HFILL }},
455 /* Setup protocol subtree array */
457 static int *ett[] = {
458 &ett_pagp,
459 &ett_pagp_flags,
460 &ett_pagp_tlvs,
463 static ei_register_info ei[] = {
464 { &ei_pagp_tlv_length, { "pagp.tlv_length.invalid", PI_PROTOCOL, PI_WARN, "Invalid TLV length", EXPFILL }},
466 expert_module_t* expert_pagp;
468 /* Register the protocol name and description */
470 proto_pagp = proto_register_protocol("Port Aggregation Protocol", "PAGP", "pagp");
472 /* Required function calls to register the header fields and subtrees used */
474 proto_register_field_array(proto_pagp, hf, array_length(hf));
475 proto_register_subtree_array(ett, array_length(ett));
476 expert_pagp = expert_register_protocol(proto_pagp);
477 expert_register_field_array(expert_pagp, ei, array_length(ei));
478 pagp_handle = register_dissector("pagp", dissect_pagp, proto_pagp);
482 void
483 proto_reg_handoff_pagp(void)
485 dissector_add_uint("llc.cisco_pid", CISCO_PID_PAGP, pagp_handle);
489 * Editor modelines - https://www.wireshark.org/tools/modelines.html
491 * Local variables:
492 * c-basic-offset: 4
493 * tab-width: 8
494 * indent-tabs-mode: nil
495 * End:
497 * vi: set shiftwidth=4 tabstop=8 expandtab:
498 * :indentSize=4:tabSize=8:noTabs=true: