Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-foundry.c
blob12fa9b3c93b97fb2bebe22b0209c7c873091a156
1 /* packet-foundry.c
2 * Routines for the disassembly of Foundry LLC messages (currently
3 * Foundry Discovery Protocol - FDP only)
5 * Copyright 2012 Joerg Mayer (see AUTHORS file)
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include "config.h"
16 #include <epan/packet.h>
17 #include <epan/expert.h>
18 #include <epan/strutil.h>
19 #include "packet-llc.h"
20 #include <epan/oui.h>
22 void proto_register_fdp(void);
23 void proto_reg_handoff_fdp(void);
25 static dissector_handle_t fdp_handle;
27 static int hf_llc_foundry_pid;
29 static int proto_fdp;
30 /* FDP header */
31 static int hf_fdp_version;
32 static int hf_fdp_holdtime;
33 static int hf_fdp_checksum;
34 /* TLV header */
35 static int hf_fdp_tlv_type;
36 static int hf_fdp_tlv_length;
37 /* Unknown element */
38 static int hf_fdp_unknown;
39 static int hf_fdp_unknown_data;
40 /* Port Tag element */
41 static int hf_fdp_tag;
42 static int hf_fdp_tag_native;
43 static int hf_fdp_tag_type;
44 static int hf_fdp_tag_unknown;
45 /* VLAN Bitmap */
46 static int hf_fdp_vlanmap;
47 static int hf_fdp_vlanmap_vlan;
48 /* String element */
49 static int hf_fdp_string;
50 static int hf_fdp_string_data;
51 static int hf_fdp_string_text;
52 /* Net? element */
53 static int hf_fdp_net;
54 static int hf_fdp_net_unknown;
55 static int hf_fdp_net_ip;
56 static int hf_fdp_net_iplength;
58 static int ett_fdp;
59 static int ett_fdp_tlv_header;
60 static int ett_fdp_unknown;
61 static int ett_fdp_string;
62 static int ett_fdp_net;
63 static int ett_fdp_tag;
64 static int ett_fdp_vlanmap;
66 static expert_field ei_fdp_tlv_length;
68 #define PROTO_SHORT_NAME "FDP"
69 #define PROTO_LONG_NAME "Foundry Discovery Protocol"
71 static const value_string foundry_pid_vals[] = {
72 { 0x2000, "FDP" },
74 { 0, NULL }
77 typedef enum {
78 FDP_TYPE_NAME = 1,
79 FDP_TYPE_NET = 2,
80 FDP_TYPE_PORT = 3,
81 FDP_TYPE_CAPABILITIES = 4,
82 FDP_TYPE_VERSION = 5,
83 FDP_TYPE_MODEL = 6,
84 FDP_TYPE_VLANMAP = 0x0101,
85 FDP_TYPE_TAG = 0x0102
86 } fdp_type_t;
88 static const value_string fdp_type_vals[] = {
89 { FDP_TYPE_NAME, "DeviceID"},
90 { FDP_TYPE_NET, "Net?"},
91 { FDP_TYPE_PORT, "Interface"},
92 { FDP_TYPE_CAPABILITIES, "Capabilities"},
93 { FDP_TYPE_VERSION, "Version"},
94 { FDP_TYPE_MODEL, "Platform"},
95 { FDP_TYPE_VLANMAP, "VLAN-Bitmap"},
96 { FDP_TYPE_TAG, "Tagging-Info"},
98 { 0, NULL }
101 static int
102 dissect_tlv_header(tvbuff_t *tvb, packet_info *pinfo _U_, int offset, int length _U_, proto_tree *tree)
104 proto_tree *tlv_tree;
105 uint16_t tlv_type;
106 uint16_t tlv_length;
108 tlv_type = tvb_get_ntohs(tvb, offset);
109 tlv_length = tvb_get_ntohs(tvb, offset + 2);
111 tlv_tree = proto_tree_add_subtree_format(tree, tvb, offset, 4,
112 ett_fdp_tlv_header, NULL, "Length %d, type %d = %s",
113 tlv_length, tlv_type,
114 val_to_str(tlv_type, fdp_type_vals, "Unknown (%d)"));
116 proto_tree_add_uint(tlv_tree, hf_fdp_tlv_type, tvb, offset, 2, tlv_type);
117 offset += 2;
119 proto_tree_add_uint(tlv_tree, hf_fdp_tlv_length, tvb, offset, 2, tlv_length);
120 offset += 2;
122 return offset;
125 static int
126 dissect_string_tlv(tvbuff_t *tvb, packet_info *pinfo, int offset, int length, proto_tree *tree, const char* type_string)
128 proto_item *string_item;
129 proto_tree *string_tree;
130 const uint8_t *string_value;
132 string_item = proto_tree_add_protocol_format(tree, hf_fdp_string,
133 tvb, offset, length, "%s", type_string);
135 string_tree = proto_item_add_subtree(string_item, ett_fdp_string);
137 dissect_tlv_header(tvb, pinfo, offset, 4, string_tree);
138 offset += 4;
139 length -= 4;
141 proto_tree_add_item(string_tree, hf_fdp_string_data, tvb, offset, length, ENC_NA);
142 proto_tree_add_item_ret_string(string_tree, hf_fdp_string_text, tvb, offset, length, ENC_ASCII|ENC_NA, pinfo->pool, &string_value);
143 proto_item_append_text(string_item, ": \"%s\"",
144 format_text(pinfo->pool, string_value, strlen(string_value)));
146 return offset;
149 static void
150 dissect_net_tlv(tvbuff_t *tvb, packet_info *pinfo, int offset, int length, proto_tree *tree)
152 proto_item *net_item;
153 proto_tree *net_tree;
155 net_item = proto_tree_add_protocol_format(tree, hf_fdp_net,
156 tvb, offset, length, "Net?");
158 net_tree = proto_item_add_subtree(net_item, ett_fdp_net);
160 dissect_tlv_header(tvb, pinfo, offset, 4, net_tree);
161 offset += 4;
162 length -= 4;
164 proto_tree_add_item(net_tree, hf_fdp_net_unknown, tvb, offset, 7, ENC_NA);
165 offset += 7;
166 length -= 7;
168 /* Length of IP address block in bytes */
169 proto_tree_add_item(net_tree, hf_fdp_net_iplength, tvb, offset, 2, ENC_BIG_ENDIAN);
170 offset += 2;
171 length -= 2;
173 while (length >= 4) {
174 proto_tree_add_item(net_tree, hf_fdp_net_ip, tvb, offset, 4, ENC_NA);
175 offset += 4;
176 length -= 4;
180 static void
181 dissect_vlanmap_tlv(tvbuff_t *tvb, packet_info *pinfo, int offset, int length, proto_tree *tree)
183 proto_item *vlanmap_item;
184 proto_tree *vlanmap_tree;
185 unsigned vlan, voffset;
186 unsigned bitoffset, byteoffset;
188 vlanmap_item = proto_tree_add_protocol_format(tree, hf_fdp_vlanmap,
189 tvb, offset, length, "VLAN-Map");
191 vlanmap_tree = proto_item_add_subtree(vlanmap_item, ett_fdp_vlanmap);
193 dissect_tlv_header(tvb, pinfo, offset, 4, vlanmap_tree);
194 offset += 4;
195 length -= 4;
197 voffset = 1;
198 for (vlan = 1; vlan <= (unsigned)length*8; vlan++) {
199 byteoffset = (vlan - voffset) / 8;
200 bitoffset = (vlan - voffset) % 8;
201 if (tvb_get_uint8(tvb, offset + byteoffset) & (1 << bitoffset)) {
203 proto_tree_add_uint(vlanmap_tree, hf_fdp_vlanmap_vlan, tvb,
204 offset + byteoffset, 1, vlan);
209 static void
210 dissect_tag_tlv(tvbuff_t *tvb, packet_info *pinfo, int offset, int length, proto_tree *tree)
212 proto_item *tag_item;
213 proto_tree *tag_tree;
215 tag_item = proto_tree_add_protocol_format(tree, hf_fdp_tag,
216 tvb, offset, length, "Port tag");
218 tag_tree = proto_item_add_subtree(tag_item, ett_fdp_tag);
220 dissect_tlv_header(tvb, pinfo, offset, 4, tag_tree);
221 offset += 4;
222 length -= 4;
223 proto_tree_add_item(tag_tree, hf_fdp_tag_native, tvb, offset, 2, ENC_BIG_ENDIAN);
224 offset += 2;
225 length -= 2;
226 proto_tree_add_item(tag_tree, hf_fdp_tag_type, tvb, offset, 2, ENC_BIG_ENDIAN);
227 offset += 2;
228 length -= 2;
229 proto_tree_add_item(tag_tree, hf_fdp_tag_unknown, tvb, offset, length, ENC_NA);
232 static void
233 dissect_unknown_tlv(tvbuff_t *tvb, packet_info *pinfo, int offset, int length, proto_tree *tree)
235 proto_item *unknown_item;
236 proto_tree *unknown_tree;
237 uint16_t tlv_type;
239 tlv_type = tvb_get_ntohs(tvb, offset);
241 unknown_item = proto_tree_add_protocol_format(tree, hf_fdp_unknown,
242 tvb, offset, length, "Unknown element [%u]", tlv_type);
244 unknown_tree = proto_item_add_subtree(unknown_item, ett_fdp_unknown);
246 dissect_tlv_header(tvb, pinfo, offset, 4, unknown_tree);
247 offset += 4;
248 length -= 4;
250 proto_tree_add_item(unknown_tree, hf_fdp_unknown_data, tvb, offset, length, ENC_NA);
253 static int
254 dissect_fdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
256 proto_item *ti;
257 proto_tree *fdp_tree = NULL;
258 int offset = 0;
259 uint16_t tlv_type;
260 uint16_t tlv_length;
261 int data_length;
262 const char *type_string;
264 col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_SHORT_NAME);
265 col_set_str(pinfo->cinfo, COL_INFO, PROTO_SHORT_NAME ":");
267 if (tree) {
268 data_length = tvb_reported_length_remaining(tvb, offset);
270 ti = proto_tree_add_item(tree, proto_fdp, tvb, offset, -1, ENC_NA);
271 fdp_tree = proto_item_add_subtree(ti, ett_fdp);
273 proto_tree_add_item(fdp_tree, hf_fdp_version, tvb, offset, 1, ENC_BIG_ENDIAN);
274 offset += 1;
275 proto_tree_add_item(fdp_tree, hf_fdp_holdtime, tvb, offset, 1, ENC_BIG_ENDIAN);
276 offset += 1;
277 proto_tree_add_checksum(fdp_tree, tvb, offset, hf_fdp_checksum, -1, NULL, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
278 offset += 2;
280 /* Decode the individual TLVs */
281 while (offset < data_length) {
282 if (data_length - offset < 4) {
283 proto_tree_add_expert_format(fdp_tree, pinfo, &ei_fdp_tlv_length, tvb, offset, 4,
284 "Too few bytes left for TLV: %u (< 4)", data_length - offset);
285 break;
287 tlv_type = tvb_get_ntohs(tvb, offset);
288 tlv_length = tvb_get_ntohs(tvb, offset + 2);
290 if ((tlv_length < 4) || (tlv_length > (data_length - offset))) {
291 proto_tree_add_expert_format(fdp_tree, pinfo, &ei_fdp_tlv_length, tvb, offset, 0,
292 "TLV with invalid length: %u", tlv_length);
293 break;
295 type_string = val_to_str(tlv_type, fdp_type_vals, "[%u]");
296 col_append_fstr(pinfo->cinfo, COL_INFO, " %s", type_string);
298 switch (tlv_type) {
299 case FDP_TYPE_NAME:
300 case FDP_TYPE_PORT:
301 case FDP_TYPE_CAPABILITIES:
302 case FDP_TYPE_VERSION:
303 case FDP_TYPE_MODEL:
304 dissect_string_tlv(tvb, pinfo, offset, tlv_length, fdp_tree, type_string);
305 break;
306 case FDP_TYPE_NET:
307 dissect_net_tlv(tvb, pinfo, offset, tlv_length, fdp_tree);
308 break;
309 case FDP_TYPE_TAG:
310 dissect_tag_tlv(tvb, pinfo, offset, tlv_length, fdp_tree);
311 break;
312 case FDP_TYPE_VLANMAP:
313 dissect_vlanmap_tlv(tvb, pinfo, offset, tlv_length, fdp_tree);
314 break;
315 default:
316 dissect_unknown_tlv(tvb, pinfo, offset, tlv_length, fdp_tree);
317 break;
319 offset += tlv_length;
323 return tvb_captured_length(tvb);
326 void
327 proto_register_fdp(void)
329 static hf_register_info hf[] = {
331 /* FDP header */
332 { &hf_fdp_version,
333 { "Version?", "fdp.version", FT_UINT8, BASE_DEC, NULL,
334 0x0, NULL, HFILL }},
336 { &hf_fdp_holdtime,
337 { "Holdtime", "fdp.holdtime", FT_UINT8, BASE_DEC, NULL,
338 0x0, NULL, HFILL }},
340 { &hf_fdp_checksum,
341 { "Checksum?", "fdp.checksum", FT_UINT16, BASE_HEX, NULL,
342 0x0, NULL, HFILL }},
344 /* TLV header */
345 { &hf_fdp_tlv_type,
346 { "TLV type", "fdp.tlv.type", FT_UINT16, BASE_DEC, VALS(fdp_type_vals),
347 0x0, NULL, HFILL }},
349 { &hf_fdp_tlv_length,
350 { "TLV length", "fdp.tlv.length", FT_UINT16, BASE_DEC, NULL,
351 0x0, NULL, HFILL }},
353 /* Unknown element */
354 { &hf_fdp_unknown,
355 { "Unknown", "fdp.unknown", FT_PROTOCOL, BASE_NONE, NULL,
356 0x0, NULL, HFILL }},
358 { &hf_fdp_unknown_data,
359 { "Unknown", "fdp.unknown.data", FT_BYTES, BASE_NONE, NULL,
360 0x0, NULL, HFILL }},
362 /* String element */
363 { &hf_fdp_string,
364 { "DeviceID", "fdp.deviceid", FT_PROTOCOL, BASE_NONE, NULL,
365 0x0, NULL, HFILL }},
367 { &hf_fdp_string_data,
368 { "Data", "fdp.string.data", FT_BYTES, BASE_NONE, NULL,
369 0x0, NULL, HFILL }},
371 { &hf_fdp_string_text,
372 { "Text", "fdp.string.text", FT_STRING, BASE_NONE, NULL,
373 0x0, NULL, HFILL }},
375 /* Net? element */
376 { &hf_fdp_net,
377 { "Net?", "fdp.net", FT_PROTOCOL, BASE_NONE, NULL,
378 0x0, NULL, HFILL }},
380 { &hf_fdp_net_unknown,
381 { "Net Unknown?", "fdp.net.unknown", FT_BYTES, BASE_NONE, NULL,
382 0x0, NULL, HFILL }},
384 { &hf_fdp_net_iplength,
385 { "Net IP Bytes?", "fdp.net.iplength", FT_UINT16, BASE_DEC, NULL,
386 0x0, "Number of bytes carrying IP addresses", HFILL }},
388 { &hf_fdp_net_ip,
389 { "Net IP Address?", "fdp.net.ip", FT_IPv4, BASE_NONE, NULL,
390 0x0, NULL, HFILL }},
392 /* VLAN Bitmap */
393 { &hf_fdp_vlanmap,
394 { "VLAN Map", "fdp.vlanmap", FT_PROTOCOL, BASE_NONE, NULL,
395 0x0, NULL, HFILL }},
397 { &hf_fdp_vlanmap_vlan,
398 { "VLAN", "fdp.vlanmap.vlan", FT_UINT16, BASE_DEC, NULL,
399 0x0, NULL, HFILL }},
401 /* Port Tag element */
402 { &hf_fdp_tag,
403 { "Tag", "fdp.tag", FT_PROTOCOL, BASE_NONE, NULL,
404 0x0, NULL, HFILL }},
406 { &hf_fdp_tag_native,
407 { "Native", "fdp.tag.native", FT_UINT16, BASE_DEC, NULL,
408 0x0, NULL, HFILL }},
410 { &hf_fdp_tag_type,
411 { "Type", "fdp.tag.type", FT_UINT16, BASE_HEX, NULL,
412 0x0, NULL, HFILL }},
414 { &hf_fdp_tag_unknown,
415 { "Unknown", "fdp.tag.unknown", FT_BYTES, BASE_NONE, NULL,
416 0x0, NULL, HFILL }},
420 static hf_register_info oui_hf[] = {
421 { &hf_llc_foundry_pid,
422 { "PID", "llc.foundry_pid", FT_UINT16, BASE_HEX,
423 VALS(foundry_pid_vals), 0x0, NULL, HFILL }
427 static int *ett[] = {
428 &ett_fdp,
429 &ett_fdp_tlv_header,
430 &ett_fdp_unknown,
431 &ett_fdp_string,
432 &ett_fdp_net,
433 &ett_fdp_tag,
434 &ett_fdp_vlanmap,
437 static ei_register_info ei[] = {
438 { &ei_fdp_tlv_length, { "fdp.tlv.length.invalid", PI_MALFORMED, PI_ERROR, "Invalid length", EXPFILL }},
441 expert_module_t* expert_fdp;
443 proto_fdp = proto_register_protocol(PROTO_LONG_NAME, PROTO_SHORT_NAME, "fdp");
445 proto_register_field_array(proto_fdp, hf, array_length(hf));
446 proto_register_subtree_array(ett, array_length(ett));
447 expert_fdp = expert_register_protocol(proto_fdp);
448 expert_register_field_array(expert_fdp, ei, array_length(ei));
450 llc_add_oui(OUI_FOUNDRY, "llc.foundry_pid", "LLC Foundry OUI PID", oui_hf, proto_fdp);
452 fdp_handle = register_dissector("fdp", dissect_fdp, proto_fdp);
455 void
456 proto_reg_handoff_fdp(void)
458 dissector_add_uint("llc.foundry_pid", 0x2000, fdp_handle);
462 * Editor modelines - https://www.wireshark.org/tools/modelines.html
464 * Local variables:
465 * c-basic-offset: 8
466 * tab-width: 8
467 * indent-tabs-mode: t
468 * End:
470 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
471 * :indentSize=8:tabSize=8:noTabs=false: