Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-cdp.c
blob7b275b879368313ad81ed90f588ae3002e331658
1 /* packet-cdp.c
2 * Routines for the disassembly of the "Cisco Discovery Protocol"
3 * (c) Copyright Hannes R. Boehm <hannes@boehm.org>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
14 #include <epan/packet.h>
15 #include <epan/expert.h>
16 #include <epan/to_str.h>
17 #include <epan/in_cksum.h>
18 #include <epan/nlpid.h>
19 #include <epan/etypes.h>
20 #include <epan/cisco_pid.h>
21 #include <epan/tfs.h>
22 #include <epan/unit_strings.h>
26 * See
28 * https://web.archive.org/web/20000914194913/http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.pdf
30 * for some documentation on CDP.
32 * See
34 * http://www.cisco.com/c/en/us/td/docs/ios-xml/ios/cdp/configuration/15-mt/cdp-15-mt-book/nm-cdp-discover.html#GUID-84FBA50B-677C-4D90-AF56-2FB96F2DC085
36 * and
38 * http://www.cisco.com/c/en/us/support/docs/switches/catalyst-4500-series-switches/13414-103.html#cdp
40 * for some more information on CDP version 2 (a superset of version 1).
42 * Also see
44 * https://web.archive.org/web/20220711213555/http://www.rhyshaden.com/cdp.htm
47 void proto_register_cdp(void);
48 void proto_reg_handoff_cdp(void);
50 static dissector_handle_t cdp_handle;
52 /* Offsets in TLV structure. */
53 #define TLV_TYPE 0
54 #define TLV_LENGTH 2
56 static int proto_cdp;
57 static int hf_cdp_version;
58 static int hf_cdp_checksum;
59 static int hf_cdp_checksum_status;
60 static int hf_cdp_ttl;
61 static int hf_cdp_tlvtype;
62 static int hf_cdp_tlvlength;
63 static int hf_cdp_nrgyz_tlvtype;
64 static int hf_cdp_nrgyz_tlvlength;
65 static int hf_cdp_deviceid;
66 static int hf_cdp_platform;
67 static int hf_cdp_portid;
68 static int hf_cdp_capabilities;
69 static int hf_cdp_capabilities_router;
70 static int hf_cdp_capabilities_trans_bridge;
71 static int hf_cdp_capabilities_src_bridge;
72 static int hf_cdp_capabilities_switch;
73 static int hf_cdp_capabilities_host;
74 static int hf_cdp_capabilities_igmp_capable;
75 static int hf_cdp_capabilities_repeater;
76 static int hf_cdp_capabilities_voip_phone;
77 static int hf_cdp_capabilities_remote;
78 static int hf_cdp_capabilities_cvta;
79 static int hf_cdp_capabilities_mac_relay;
80 static int hf_cdp_spare_poe_tlv;
81 static int hf_cdp_spare_poe_tlv_poe;
82 static int hf_cdp_spare_poe_tlv_spare_pair_arch;
83 static int hf_cdp_spare_poe_tlv_req_spare_pair_poe;
84 static int hf_cdp_spare_poe_tlv_pse_spare_pair_poe;
86 /* Generated from convert_proto_tree_add_text.pl */
87 static int hf_cdp_num_tlvs_table;
88 static int hf_cdp_encrypted_data;
89 static int hf_cdp_cluster_ip;
90 static int hf_cdp_nrgyz_reply_to_backup_server_ip;
91 static int hf_cdp_nrgyz_reply_to_port;
92 static int hf_cdp_unknown_pad;
93 static int hf_cdp_cluster_version;
94 static int hf_cdp_hello_unknown;
95 static int hf_cdp_management_id;
96 static int hf_cdp_data;
97 static int hf_cdp_nrgyz_reply_to_ip_address;
98 static int hf_cdp_nrgyz_reply_to_name;
99 static int hf_cdp_nrgyz_reply_to_domain;
100 static int hf_cdp_nrgyz_reply_to_role;
101 static int hf_cdp_nrgyz_ip_address;
102 static int hf_cdp_nrgyz_ip6_address;
103 static int hf_cdp_model_number;
104 static int hf_cdp_nrgyz_reply_to_unknown_field;
105 static int hf_cdp_len_tlv_table;
106 static int hf_cdp_vtp_management_domain;
107 static int hf_cdp_hardware_version_id;
108 static int hf_cdp_cluster_unknown;
109 static int hf_cdp_native_vlan;
110 static int hf_cdp_ip_prefix;
111 static int hf_cdp_odr_default_gateway;
112 static int hf_cdp_power_consumption;
113 static int hf_cdp_cluster_status;
114 static int hf_cdp_power_requested;
115 static int hf_cdp_trust_bitmap;
116 static int hf_cdp_seen_sequence;
117 static int hf_cdp_system_name;
118 static int hf_cdp_power_available;
119 static int hf_cdp_cluster_commander_mac;
120 static int hf_cdp_mtu;
121 static int hf_cdp_protocol_length;
122 static int hf_cdp_system_serial_number;
123 static int hf_cdp_sequence_number;
124 static int hf_cdp_duplex;
125 static int hf_cdp_voice_vlan;
126 static int hf_cdp_request_id;
127 static int hf_cdp_cluster_sub_version;
128 static int hf_cdp_oui;
129 static int hf_cdp_nrgyz_reply_to_backup_server_port;
130 static int hf_cdp_cluster_master_ip;
131 static int hf_cdp_protocol;
132 static int hf_cdp_protocol_type;
133 static int hf_cdp_address;
134 static int hf_cdp_system_object_identifier;
135 static int hf_cdp_location_unknown;
136 static int hf_cdp_nrgyz_unknown_values;
137 static int hf_cdp_address_length;
138 static int hf_cdp_protocol_id;
139 static int hf_cdp_cluster_switch_mac;
140 static int hf_cdp_location;
141 static int hf_cdp_untrusted_port_cos;
142 static int hf_cdp_number_of_addresses;
143 static int hf_cdp_cluster_management_vlan;
144 static int hf_cdp_software_version;
146 static int ett_cdp;
147 static int ett_cdp_tlv;
148 static int ett_cdp_nrgyz_tlv;
149 static int ett_cdp_address;
150 static int ett_cdp_capabilities;
151 static int ett_cdp_spare_poe_tlv;
152 static int ett_cdp_checksum;
154 static expert_field ei_cdp_invalid_data;
155 static expert_field ei_cdp_nrgyz_tlvlength;
156 static expert_field ei_cdp_checksum;
158 static int
159 dissect_address_tlv(tvbuff_t *tvb, packet_info* pinfo, int offset, int length, proto_tree *tree);
160 static void
161 dissect_capabilities(tvbuff_t *tvb, int offset, int length, proto_tree *tree);
162 static void
163 dissect_nrgyz_tlv(tvbuff_t *tvb, packet_info* pinfo, int offset, uint16_t length, uint16_t num,
164 proto_tree *tree);
165 static void
166 dissect_spare_poe_tlv(tvbuff_t *tvb, int offset, int length, proto_tree *tree);
167 static void
168 add_multi_line_string_to_tree(wmem_allocator_t *scope, proto_tree *tree, tvbuff_t *tvb, int start,
169 int len, int hf);
171 #define TYPE_DEVICE_ID 0x0001
172 #define TYPE_ADDRESS 0x0002
173 #define TYPE_PORT_ID 0x0003
174 #define TYPE_CAPABILITIES 0x0004
175 #define TYPE_IOS_VERSION 0x0005
176 #define TYPE_PLATFORM 0x0006
177 #define TYPE_IP_PREFIX 0x0007
178 #define TYPE_PROTOCOL_HELLO 0x0008 /* Protocol Hello */
179 #define TYPE_VTP_MGMT_DOMAIN 0x0009 /* VTP Domain, CTPv2 - see second URL */
180 #define TYPE_NATIVE_VLAN 0x000a /* Native VLAN, CTPv2 - see second URL */
181 #define TYPE_DUPLEX 0x000b /* Full/Half Duplex - see second URL */
182 /* 0x000c */
183 /* 0x000d */
184 #define TYPE_VOIP_VLAN_REPLY 0x000e /* VoIP VLAN reply */
185 #define TYPE_VOIP_VLAN_QUERY 0x000f /* VoIP VLAN query */
186 #define TYPE_POWER 0x0010 /* Power consumption */
187 #define TYPE_MTU 0x0011 /* MTU */
188 #define TYPE_TRUST_BITMAP 0x0012 /* Trust bitmap */
189 #define TYPE_UNTRUSTED_COS 0x0013 /* Untrusted port CoS */
190 #define TYPE_SYSTEM_NAME 0x0014 /* System Name */
191 #define TYPE_SYSTEM_OID 0x0015 /* System OID */
192 #define TYPE_MANAGEMENT_ADDR 0x0016 /* Management Address(es) */
193 #define TYPE_LOCATION 0x0017 /* Location */
194 #define TYPE_EXT_PORT_ID 0x0018 /* External Port-ID */
195 #define TYPE_POWER_REQUESTED 0x0019 /* Power Requested */
196 #define TYPE_POWER_AVAILABLE 0x001a /* Power Available */
197 #define TYPE_PORT_UNIDIR 0x001b /* Port Unidirectional */
198 #define TYPE_NRGYZ 0x001d /* EnergyWise over CDP */
199 #define TYPE_SPARE_POE 0x001f /* Spare Pair PoE */
201 #define TYPE_HP_BSSID 0x1000 /* BSSID */
202 #define TYPE_HP_SERIAL 0x1001 /* Serial number */
203 #define TYPE_HP_SSID 0x1002 /* SSID */
204 #define TYPE_HP_RADIO1_CH 0x1003 /* Radio1 channel */
205 /* 0x1004 */
206 /* 0x1005 */
207 #define TYPE_HP_SNMP_PORT 0x1006 /* SNMP listening UDP port */
208 #define TYPE_HP_MGMT_PORT 0x1007 /* Web interface TCP port */
209 #define TYPE_HP_SOURCE_MAC 0x1008 /* Sender MAC address for the AP, bouth wired and wireless */
210 #define TYPE_HP_RADIO2_CH 0x1009 /* Radio2 channel */
211 #define TYPE_HP_RADIO1_OMODE 0x100A /* Radio1 Operating mode */
212 #define TYPE_HP_RADIO2_OMODE 0x100B /* Radio2 Operating mode */
213 #define TYPE_HP_RADIO1_RMODE 0x100C /* Radio1 Radio mode */
214 #define TYPE_HP_RADIO2_RMODE 0x100D /* Radio2 Radio mode */
216 static const value_string type_vals[] = {
217 { TYPE_DEVICE_ID, "Device ID" },
218 { TYPE_ADDRESS, "Addresses" },
219 { TYPE_PORT_ID, "Port ID" },
220 { TYPE_CAPABILITIES, "Capabilities" },
221 { TYPE_IOS_VERSION, "Software version" },
222 { TYPE_PLATFORM, "Platform" },
223 { TYPE_IP_PREFIX, "IP Prefix/Gateway (used for ODR)" },
224 { TYPE_PROTOCOL_HELLO, "Protocol Hello" },
225 { TYPE_VTP_MGMT_DOMAIN, "VTP Management Domain" },
226 { TYPE_NATIVE_VLAN, "Native VLAN" },
227 { TYPE_DUPLEX, "Duplex" },
228 { TYPE_VOIP_VLAN_REPLY, "VoIP VLAN Reply" },
229 { TYPE_VOIP_VLAN_QUERY, "VoIP VLAN Query" },
230 { TYPE_POWER, "Power consumption" },
231 { TYPE_MTU, "MTU"},
232 { TYPE_TRUST_BITMAP, "Trust Bitmap" },
233 { TYPE_UNTRUSTED_COS, "Untrusted Port CoS" },
234 { TYPE_SYSTEM_NAME, "System Name" },
235 { TYPE_SYSTEM_OID, "System Object ID" },
236 { TYPE_MANAGEMENT_ADDR, "Management Address" },
237 { TYPE_LOCATION, "Location" },
238 { TYPE_EXT_PORT_ID, "External Port-ID" },
239 { TYPE_POWER_REQUESTED, "Power Requested" },
240 { TYPE_POWER_AVAILABLE, "Power Available" },
241 { TYPE_PORT_UNIDIR, "Port Unidirectional" },
242 { TYPE_NRGYZ, "EnergyWise" },
243 { TYPE_SPARE_POE, "Spare PoE" },
244 { TYPE_HP_BSSID, "BSSID" },
245 { TYPE_HP_SERIAL, "Serial number" },
246 { TYPE_HP_SSID, "SSID" },
247 { TYPE_HP_RADIO1_CH, "Radio1 channel" },
248 { TYPE_HP_SNMP_PORT, "SNMP UDP port" },
249 { TYPE_HP_MGMT_PORT, "Web TCP port" },
250 { TYPE_HP_SOURCE_MAC, "Source MAC address" },
251 { TYPE_HP_RADIO2_CH, "Radio2 channel" },
252 { TYPE_HP_RADIO1_OMODE, "Radio1 Operating mode" },
253 { TYPE_HP_RADIO2_OMODE, "Radio2 Operating mode" },
254 { TYPE_HP_RADIO1_RMODE, "Radio1 Radio mode" },
255 { TYPE_HP_RADIO2_RMODE, "Radio2 Radio mode" },
256 { 0, NULL }
259 #define TYPE_HELLO_CLUSTER_MGMT 0x0112
261 static const value_string type_hello_vals[] = {
262 { TYPE_HELLO_CLUSTER_MGMT, "Cluster Management" },
263 { 0, NULL }
266 #define TYPE_NRGYZ_ROLE 0x00000007
267 #define TYPE_NRGYZ_DOMAIN 0x00000008
268 #define TYPE_NRGYZ_NAME 0x00000009
269 #define TYPE_NRGYZ_REPLYTO 0x00000017
271 static const value_string type_nrgyz_vals[] = {
272 { TYPE_NRGYZ_ROLE, "Role" },
273 { TYPE_NRGYZ_DOMAIN, "Domain" },
274 { TYPE_NRGYZ_NAME, "Name" },
275 { TYPE_NRGYZ_REPLYTO, "Reply To" },
276 { 0, NULL }
279 static int
280 dissect_cdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
282 proto_item *ti;
283 proto_tree *cdp_tree;
284 int offset = 0;
285 uint16_t type;
286 uint16_t length, data_length;
287 proto_item *tlvi;
288 proto_tree *tlv_tree;
289 int real_length;
290 uint32_t naddresses;
291 uint32_t power_avail_len, power_avail;
292 uint32_t power_req_len, power_req;
293 bool first;
294 int addr_length;
295 vec_t cksum_vec[1];
297 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CDP");
298 col_clear(pinfo->cinfo, COL_INFO);
300 ti = proto_tree_add_item(tree, proto_cdp, tvb, offset, -1, ENC_NA);
301 cdp_tree = proto_item_add_subtree(ti, ett_cdp);
303 /* CDP header */
304 proto_tree_add_item(cdp_tree, hf_cdp_version, tvb, offset, 1, ENC_BIG_ENDIAN);
305 offset += 1;
307 proto_tree_add_item(cdp_tree, hf_cdp_ttl, tvb, offset, 1, ENC_NA);
308 offset += 1;
310 /* Checksum display & verification code */
312 data_length = tvb_reported_length(tvb);
314 /* CDP doesn't adhere to RFC 1071 section 2. (B). It incorrectly assumes
315 * checksums are calculated on a big endian platform, therefore i.s.o.
316 * padding odd sized data with a zero byte _at the end_ it sets the last
317 * big endian _word_ to contain the last network _octet_. This byteswap
318 * has to be done on the last octet of network data before feeding it to
319 * the Internet checksum routine.
320 * CDP checksumming code has a bug in the addition of this last _word_
321 * as a signed number into the long word intermediate checksum. When
322 * reducing this long to word size checksum an off-by-one error can be
323 * made. This off-by-one error is compensated for in the last _word_ of
324 * the network data.
326 if (data_length & 1) {
327 uint8_t *padded_buffer;
328 /* Allocate new buffer */
329 padded_buffer = (uint8_t *)wmem_alloc(pinfo->pool, data_length+1);
330 tvb_memcpy(tvb, padded_buffer, 0, data_length);
331 /* Swap bytes in last word */
332 padded_buffer[data_length] = padded_buffer[data_length-1];
333 padded_buffer[data_length-1] = 0;
334 /* Compensate off-by-one error */
335 if (padded_buffer[data_length] & 0x80) {
336 padded_buffer[data_length]--;
337 padded_buffer[data_length-1]--;
339 /* Setup checksum routine data buffer */
340 SET_CKSUM_VEC_PTR(cksum_vec[0], padded_buffer, data_length+1);
341 } else {
342 /* Setup checksum routine data buffer */
343 SET_CKSUM_VEC_TVB(cksum_vec[0], tvb, 0, data_length);
346 proto_tree_add_checksum(cdp_tree, tvb, offset, hf_cdp_checksum, hf_cdp_checksum_status, &ei_cdp_checksum, pinfo, in_cksum(cksum_vec, 1),
347 ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM);
348 offset += 2;
350 while (tvb_reported_length_remaining(tvb, offset) != 0) {
351 tlv_tree = NULL;
352 type = tvb_get_ntohs(tvb, offset + TLV_TYPE);
353 length = tvb_get_ntohs(tvb, offset + TLV_LENGTH);
354 if (length < 4) {
355 if (tree) {
356 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb, offset, 4,
357 ett_cdp_tlv, NULL, "TLV with invalid length %u (< 4)",
358 length);
359 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
360 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
362 offset += 4;
363 break;
366 switch (type) {
368 case TYPE_DEVICE_ID:
369 /* Device ID */
371 col_append_fstr(pinfo->cinfo, COL_INFO,
372 "Device ID: %s ",
373 tvb_format_stringzpad(pinfo->pool, tvb, offset + 4, length - 4));
375 if (tree) {
376 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb, offset,
377 length, ett_cdp_tlv, NULL, "Device ID: %s",
378 tvb_format_stringzpad(pinfo->pool, tvb, offset + 4, length - 4));
379 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
380 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
381 proto_tree_add_item(tlv_tree, hf_cdp_deviceid, tvb, offset + 4, length - 4, ENC_ASCII);
383 offset += length;
384 break;
386 case TYPE_PORT_ID:
387 real_length = length;
388 if ((tvb_reported_length_remaining(tvb, offset) >= length + 3) &&
389 (tvb_get_uint8(tvb, offset + real_length) != 0x00) &&
390 (tvb_get_uint8(tvb, offset + real_length) != 0x10)) {
391 /* The length in the TLV doesn't appear to be the
392 length of the TLV, as the byte just past it
393 isn't the first byte of a 2-byte big-endian
394 small integer; make the length of the TLV the length
395 in the TLV, plus 4 bytes for the TLV type and length,
396 minus 1 because that's what makes one capture work. */
397 real_length = length + 3;
400 col_append_fstr(pinfo->cinfo, COL_INFO,
401 "Port ID: %s ",
402 tvb_format_stringzpad(pinfo->pool, tvb, offset + 4,
403 length - 4));
405 if (tree) {
406 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb, offset,
407 real_length, ett_cdp_tlv, NULL, "Port ID: %s",
408 tvb_format_text(pinfo->pool, tvb, offset + 4, real_length - 4));
409 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
410 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
411 proto_tree_add_item(tlv_tree, hf_cdp_portid, tvb, offset + 4, real_length - 4, ENC_ASCII);
413 offset += real_length;
414 break;
416 case TYPE_ADDRESS:
417 /* Addresses */
418 if (tree) {
419 tlv_tree = proto_tree_add_subtree(cdp_tree, tvb, offset,
420 length, ett_cdp_tlv, NULL, "Addresses");
421 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
422 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
424 offset += 4;
425 length -= 4;
426 naddresses = tvb_get_ntohl(tvb, offset);
427 proto_tree_add_item(tlv_tree, hf_cdp_number_of_addresses, tvb, offset, 4, ENC_BIG_ENDIAN);
428 offset += 4;
429 length -= 4;
430 while (naddresses != 0) {
431 addr_length = dissect_address_tlv(tvb, pinfo, offset, length,
432 tlv_tree);
433 if (addr_length < 0)
434 break;
435 offset += addr_length;
436 length -= addr_length;
438 naddresses--;
440 offset += length;
441 break;
443 case TYPE_CAPABILITIES:
444 if (tree) {
445 tlv_tree = proto_tree_add_subtree(cdp_tree, tvb, offset,
446 length, ett_cdp_tlv, NULL, "Capabilities");
447 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
448 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
450 offset += 4;
451 length -= 4;
452 dissect_capabilities(tvb, offset, length, tlv_tree);
453 offset += length;
454 break;
456 case TYPE_IOS_VERSION:
457 if (tree) {
458 tlv_tree = proto_tree_add_subtree(cdp_tree, tvb, offset,
459 length, ett_cdp_tlv, NULL, "Software Version");
460 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
461 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
462 add_multi_line_string_to_tree(pinfo->pool, tlv_tree, tvb, offset + 4,
463 length - 4, hf_cdp_software_version);
465 offset += length;
466 break;
468 case TYPE_PLATFORM:
469 /* ??? platform */
470 if (tree) {
471 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
472 offset, length, ett_cdp_tlv, NULL, "Platform: %s",
473 tvb_format_text(pinfo->pool, tvb, offset + 4, length - 4));
474 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
475 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
476 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII);
478 offset += length;
479 break;
481 case TYPE_IP_PREFIX:
482 if (length == 8) {
483 /* if length is 8 then this is default gw not prefix */
484 if (tree) {
485 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb, offset,
486 length, ett_cdp_tlv, NULL, "ODR Default gateway: %s",
487 tvb_ip_to_str(pinfo->pool, tvb, offset+4));
488 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
489 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
490 proto_tree_add_item(tlv_tree, hf_cdp_odr_default_gateway, tvb, offset+4, 4, ENC_BIG_ENDIAN);
492 offset += 8;
493 } else {
494 if (tree) {
495 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb, offset,
496 length, ett_cdp_tlv, NULL, "IP Prefixes: %d",length/5);
498 /* the actual number of prefixes is (length-4)/5
499 but if the variable is not a "float" but "integer"
500 then length/5=(length-4)/5 :) */
502 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
503 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
505 offset += 4;
506 length -= 4;
507 while (length > 0) {
508 proto_tree_add_ipv4_format_value(tlv_tree, hf_cdp_ip_prefix, tvb, offset, 5, tvb_get_ntohl(tvb, offset),
509 "%s/%u", tvb_ip_to_str(pinfo->pool, tvb, offset), tvb_get_uint8(tvb,offset+4));
510 offset += 5;
511 length -= 5;
514 break;
516 case TYPE_PROTOCOL_HELLO:
517 if (tree) {
518 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
519 offset,length, ett_cdp_tlv, NULL, "Protocol Hello: %s",
520 val_to_str(tvb_get_ntohs(tvb, offset+7), type_hello_vals, "Unknown (0x%04x)"));
521 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
522 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
523 proto_tree_add_item(tlv_tree, hf_cdp_oui, tvb, offset+4, 3, ENC_BIG_ENDIAN);
524 proto_tree_add_item(tlv_tree, hf_cdp_protocol_id, tvb, offset+7, 2, ENC_BIG_ENDIAN);
526 switch(tvb_get_ntohs(tvb, offset+7)) {
528 case TYPE_HELLO_CLUSTER_MGMT:
529 proto_tree_add_item(tlv_tree, hf_cdp_cluster_master_ip, tvb, offset+9, 4, ENC_BIG_ENDIAN);
530 proto_tree_add_item(tlv_tree, hf_cdp_cluster_ip, tvb, offset+13, 4, ENC_BIG_ENDIAN);
531 proto_tree_add_item(tlv_tree, hf_cdp_cluster_version, tvb, offset+17, 1, ENC_BIG_ENDIAN);
532 proto_tree_add_item(tlv_tree, hf_cdp_cluster_sub_version, tvb, offset+18, 1, ENC_BIG_ENDIAN);
533 proto_tree_add_item(tlv_tree, hf_cdp_cluster_status, tvb, offset+19, 1, ENC_BIG_ENDIAN);
534 proto_tree_add_item(tlv_tree, hf_cdp_cluster_unknown, tvb, offset+20, 1, ENC_BIG_ENDIAN);
535 proto_tree_add_item(tlv_tree, hf_cdp_cluster_commander_mac, tvb, offset+21, 6, ENC_NA);
536 proto_tree_add_item(tlv_tree, hf_cdp_cluster_switch_mac, tvb, offset+27, 6, ENC_NA);
537 proto_tree_add_item(tlv_tree, hf_cdp_cluster_unknown, tvb, offset+33, 1, ENC_BIG_ENDIAN);
538 proto_tree_add_item(tlv_tree, hf_cdp_cluster_management_vlan, tvb, offset+34, 2, ENC_BIG_ENDIAN);
539 break;
540 default:
541 proto_tree_add_item(tlv_tree, hf_cdp_hello_unknown, tvb, offset + 9, length - 9, ENC_NA);
542 break;
545 offset += length;
546 break;
548 case TYPE_VTP_MGMT_DOMAIN:
549 if (tree) {
550 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
551 offset, length, ett_cdp_tlv, NULL, "VTP Management Domain: %s",
552 tvb_format_text(pinfo->pool, tvb, offset + 4, length - 4));
553 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
554 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
555 proto_tree_add_item(tlv_tree, hf_cdp_vtp_management_domain, tvb, offset + 4, length - 4, ENC_NA|ENC_ASCII);
557 offset += length;
558 break;
560 case TYPE_NATIVE_VLAN:
561 if (tree) {
562 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
563 offset, length, ett_cdp_tlv, NULL, "Native VLAN: %u",
564 tvb_get_ntohs(tvb, offset + 4));
565 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
566 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
567 proto_tree_add_item(tlv_tree, hf_cdp_native_vlan, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
569 offset += length;
570 break;
572 case TYPE_DUPLEX:
573 if (tree) {
574 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
575 offset, length, ett_cdp_tlv, NULL, "Duplex: %s",
576 tvb_get_uint8(tvb, offset + 4) ?
577 "Full" : "Half" );
578 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
579 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
580 proto_tree_add_item(tlv_tree, hf_cdp_duplex, tvb, offset + 4, 1, ENC_NA);
582 offset += length;
583 break;
585 case TYPE_VOIP_VLAN_REPLY:
586 tlvi = NULL;
587 if (tree) {
588 uint32_t vlan_id;
590 tlv_tree = proto_tree_add_subtree(cdp_tree, tvb,
591 offset, length, ett_cdp_tlv, &tlvi,
592 "VoIP VLAN Reply");
593 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
594 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
595 if (length == 6) {
597 * XXX - this doesn't appear to happen, so report it
598 * as an error.
600 proto_tree_add_item(tlv_tree, hf_cdp_data, tvb, offset + 4, 2, ENC_NA);
601 } else {
603 * XXX - the first byte appears to be a 1-byte
604 * "appliance type" code.
606 proto_tree_add_item(tlv_tree, hf_cdp_data, tvb, offset + 4, 1, ENC_NA);
607 proto_tree_add_item_ret_uint(tlv_tree, hf_cdp_voice_vlan, tvb, offset + 5, 2, ENC_BIG_ENDIAN, &vlan_id);
608 proto_item_append_text(tlvi, ": VLAN %u", vlan_id);
611 offset += length;
612 break;
614 case TYPE_VOIP_VLAN_QUERY:
615 tlvi = NULL;
616 if (tree) {
617 uint32_t vlan_id;
619 tlv_tree = proto_tree_add_subtree(cdp_tree, tvb,
620 offset, length, ett_cdp_tlv, &tlvi,
621 "VoIP VLAN Query");
622 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
623 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
624 if (length == 6) {
626 * This is some unknown value; it's typically 0x20 0x00,
627 * which, as a big-endian value, is not a VLAN ID, as
628 * VLAN IDs are 12 bits long.
630 proto_tree_add_item(tlv_tree, hf_cdp_data, tvb, offset + 4, 2, ENC_NA);
631 } else {
633 * XXX - is this a 1-byte "appliance type" code?
635 proto_tree_add_item(tlv_tree, hf_cdp_data, tvb, offset + 4, 1, ENC_NA);
636 proto_tree_add_item_ret_uint(tlv_tree, hf_cdp_voice_vlan, tvb, offset + 5, 2, ENC_BIG_ENDIAN, &vlan_id);
637 proto_item_append_text(tlvi, ": VLAN %u", vlan_id);
640 offset += length;
641 break;
643 case TYPE_POWER:
644 if (tree) {
645 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
646 offset, length, ett_cdp_tlv, NULL, "Power Consumption: %u mW",
647 tvb_get_ntohs(tvb, offset + 4));
648 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
649 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
650 proto_tree_add_item(tlv_tree, hf_cdp_power_consumption, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
652 offset += length;
653 break;
655 case TYPE_MTU:
656 if (tree) {
657 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
658 offset, length, ett_cdp_tlv, NULL, "MTU: %u",
659 tvb_get_ntohl(tvb,offset + 4));
660 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
661 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
662 proto_tree_add_item(tlv_tree, hf_cdp_mtu, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
664 offset += length;
665 break;
667 case TYPE_TRUST_BITMAP:
668 if (tree) {
669 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
670 offset, length, ett_cdp_tlv, NULL, "Trust Bitmap: 0x%02X",
671 tvb_get_uint8(tvb, offset + 4));
672 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
673 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
674 proto_tree_add_item(tlv_tree, hf_cdp_trust_bitmap, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
676 offset += length;
677 break;
679 case TYPE_UNTRUSTED_COS:
680 if (tree) {
681 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
682 offset, length, ett_cdp_tlv, NULL, "Untrusted port CoS: 0x%02X",
683 tvb_get_uint8(tvb, offset + 4));
684 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
685 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
686 proto_tree_add_item(tlv_tree, hf_cdp_untrusted_port_cos, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
688 offset += length;
689 break;
691 case TYPE_SYSTEM_NAME:
692 if (tree) {
693 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
694 offset, length, ett_cdp_tlv, NULL, "System Name: %s",
695 tvb_format_text(pinfo->pool, tvb, offset + 4, length - 4));
696 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
697 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
698 proto_tree_add_item(tlv_tree, hf_cdp_system_name, tvb, offset + 4, length - 4, ENC_NA|ENC_ASCII);
700 offset += length;
701 break;
703 case TYPE_SYSTEM_OID:
704 if (tree) {
705 tlv_tree = proto_tree_add_subtree(cdp_tree, tvb,
706 offset, length, ett_cdp_tlv, NULL, "System Object Identifier");
707 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
708 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
709 proto_tree_add_item(tlv_tree, hf_cdp_system_object_identifier, tvb, offset + 4, length - 4, ENC_NA);
711 offset += length;
712 break;
714 case TYPE_MANAGEMENT_ADDR:
715 if (tree) {
716 tlv_tree = proto_tree_add_subtree(cdp_tree, tvb,
717 offset, length, ett_cdp_tlv, NULL, "Management Addresses");
718 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
719 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
721 offset += 4;
722 length -= 4;
723 naddresses = tvb_get_ntohl(tvb, offset);
724 if (tree) {
725 proto_tree_add_item(tlv_tree, hf_cdp_number_of_addresses, tvb, offset, 4, ENC_BIG_ENDIAN);
727 offset += 4;
728 length -= 4;
729 while (naddresses != 0) {
730 addr_length = dissect_address_tlv(tvb, pinfo, offset, length,
731 tlv_tree);
732 if (addr_length < 0)
733 break;
734 offset += addr_length;
735 length -= addr_length;
737 naddresses--;
739 offset += length;
740 break;
742 case TYPE_LOCATION:
743 if (tree) {
744 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
745 offset, length, ett_cdp_tlv, NULL, "Location: %s",
746 tvb_format_text(pinfo->pool, tvb, offset + 5, length - 5));
747 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
748 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
749 proto_tree_add_item(tlv_tree, hf_cdp_location_unknown, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
750 proto_tree_add_item(tlv_tree, hf_cdp_location, tvb, offset + 5, length - 5, ENC_NA|ENC_ASCII);
752 offset += length;
753 break;
755 case TYPE_POWER_REQUESTED:
756 tlvi = NULL;
757 if (tree) {
758 tlv_tree = proto_tree_add_subtree(cdp_tree, tvb,
759 offset, length, ett_cdp_tlv, &tlvi,
760 "Power Request");
761 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
762 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
763 proto_tree_add_item(tlv_tree, hf_cdp_request_id, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
764 proto_tree_add_item(tlv_tree, hf_cdp_management_id, tvb, offset + 6, 2, ENC_BIG_ENDIAN);
766 power_req_len = tvb_get_ntohs(tvb, offset + TLV_LENGTH);
767 if (power_req_len < 8) {
768 offset += power_req_len;
769 break;
771 power_req_len -= 8;
772 /* Move offset to where the list of Power Request Values Exist */
773 offset += 8;
774 first = true;
775 while (power_req_len >= 4) {
776 proto_tree_add_item_ret_uint(tlv_tree, hf_cdp_power_requested, tvb, offset, 4, ENC_BIG_ENDIAN, &power_req);
777 if (first) {
778 proto_item_append_text(tlvi, ": %u mW", power_req);
779 first = false;
780 } else
781 proto_item_append_text(tlvi, ", %u mW", power_req);
782 power_req_len -= 4;
783 offset += 4;
785 offset += power_req_len;
786 break;
788 case TYPE_POWER_AVAILABLE:
789 tlvi = NULL;
790 if (tree) {
791 tlv_tree = proto_tree_add_subtree(cdp_tree, tvb,
792 offset, length, ett_cdp_tlv, &tlvi,
793 "Power Available");
794 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
795 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
796 proto_tree_add_item(tlv_tree, hf_cdp_request_id, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
797 proto_tree_add_item(tlv_tree, hf_cdp_management_id, tvb, offset + 6, 2, ENC_BIG_ENDIAN);
799 power_avail_len = tvb_get_ntohs(tvb, offset + TLV_LENGTH);
800 if (power_avail_len < 8) {
801 offset += power_avail_len;
802 break;
804 power_avail_len -= 8;
805 /* Move offset to where the list of Power Available Values Exist */
806 offset += 8;
807 first = true;
808 while (power_avail_len >= 4) {
809 proto_tree_add_item_ret_uint(tlv_tree, hf_cdp_power_available, tvb, offset, 4, ENC_BIG_ENDIAN, &power_avail);
810 if (first) {
811 proto_item_append_text(tlvi, ": %u mW", power_avail);
812 first = false;
813 } else
814 proto_item_append_text(tlvi, ", %u mW", power_avail);
815 power_avail_len -= 4;
816 offset += 4;
818 offset += power_avail_len;
819 break;
821 case TYPE_NRGYZ:
822 if (tree) {
823 tlv_tree = proto_tree_add_subtree(cdp_tree, tvb,
824 offset, length, ett_cdp_tlv, NULL, "EnergyWise");
825 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
826 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
827 proto_tree_add_item(tlv_tree, hf_cdp_encrypted_data, tvb, offset + 4, 20, ENC_NA);
828 proto_tree_add_item(tlv_tree, hf_cdp_seen_sequence, tvb, offset + 24, 4, ENC_BIG_ENDIAN);
829 proto_tree_add_item(tlv_tree, hf_cdp_sequence_number, tvb, offset + 28, 4, ENC_BIG_ENDIAN);
830 proto_tree_add_item(tlv_tree, hf_cdp_model_number, tvb, offset + 32, 16, ENC_NA|ENC_ASCII);
831 proto_tree_add_item(tlv_tree, hf_cdp_unknown_pad, tvb, offset + 48, 2, ENC_BIG_ENDIAN);
832 proto_tree_add_item(tlv_tree, hf_cdp_hardware_version_id, tvb, offset + 50, 3, ENC_NA|ENC_ASCII);
833 proto_tree_add_item(tlv_tree, hf_cdp_system_serial_number, tvb, offset + 53, 11, ENC_NA|ENC_ASCII);
834 proto_tree_add_item(tlv_tree, hf_cdp_nrgyz_unknown_values, tvb, offset + 64, 8, ENC_NA);
835 proto_tree_add_item(tlv_tree, hf_cdp_len_tlv_table, tvb, offset + 72, 2, ENC_BIG_ENDIAN);
836 proto_tree_add_item(tlv_tree, hf_cdp_num_tlvs_table, tvb, offset + 74, 2, ENC_BIG_ENDIAN);
838 dissect_nrgyz_tlv(tvb, pinfo, offset + 76,
839 tvb_get_ntohs(tvb, offset + 72),
840 tvb_get_ntohs(tvb, offset + 74),
841 tlv_tree);
845 offset += length;
846 break;
848 case TYPE_SPARE_POE:
849 if (tree) {
850 tlv_tree = proto_tree_add_subtree(cdp_tree, tvb, offset, length,
851 ett_cdp_tlv, NULL, "Spare Pair PoE");
853 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
854 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
856 offset += 4;
857 length -= 4;
858 dissect_spare_poe_tlv(tvb, offset, length, tlv_tree);
859 offset += length;
860 break;
862 case TYPE_HP_BSSID:
863 /* BSSID */
864 if (tree) {
865 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
866 offset, length, ett_cdp_tlv, NULL, "BSSID: %s",
867 tvb_format_text(pinfo->pool, tvb, offset + 4, length - 4));
868 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
869 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
870 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII);
872 offset += length;
873 break;
875 case TYPE_HP_SERIAL:
876 /* Serial number */
877 if (tree) {
878 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
879 offset, length, ett_cdp_tlv, NULL, "Serial: %s",
880 tvb_format_text(pinfo->pool, tvb, offset + 4, length - 4));
881 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
882 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
883 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII);
885 offset += length;
886 break;
888 case TYPE_HP_SSID:
889 /* SSID */
890 if (tree) {
891 if (length == 4) {
892 tlv_tree = proto_tree_add_subtree(cdp_tree, tvb,
893 offset, length, ett_cdp_tlv, NULL, "SSID: [Empty]");
894 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
895 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
896 } else {
897 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
898 offset, length, ett_cdp_tlv, NULL, "SSID: %s",
899 tvb_format_text(pinfo->pool, tvb, offset + 4, length - 4));
900 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
901 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
902 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII);
905 offset += length;
906 break;
908 case TYPE_HP_RADIO1_CH:
909 /* Radio1 channel */
910 if (tree) {
911 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
912 offset, length, ett_cdp_tlv, NULL, "Radio 1 channel: %s",
913 tvb_format_text(pinfo->pool, tvb, offset + 4, length - 4));
914 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
915 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
916 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII);
918 offset += length;
919 break;
921 case TYPE_HP_SNMP_PORT:
922 /* SNMP listening UDP port */
923 if (tree) {
924 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
925 offset, length, ett_cdp_tlv, NULL, "SNMP port: %s",
926 tvb_format_text(pinfo->pool, tvb, offset + 4, length - 4));
927 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
928 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
929 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII);
931 offset += length;
932 break;
934 case TYPE_HP_MGMT_PORT:
935 /* Web interface TCP port */
936 if (tree) {
937 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
938 offset, length, ett_cdp_tlv, NULL, "Web mgmt port: %s",
939 tvb_format_text(pinfo->pool, tvb, offset + 4, length - 4));
940 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
941 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
942 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII);
944 offset += length;
945 break;
947 case TYPE_HP_SOURCE_MAC:
948 /* Sender MAC address for the AP, bouth wired and wireless */
949 if (tree) {
950 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
951 offset, length, ett_cdp_tlv, NULL, "Source MAC: %s",
952 tvb_format_text(pinfo->pool, tvb, offset + 4, length - 4));
953 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
954 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
955 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII);
957 offset += length;
958 break;
960 case TYPE_HP_RADIO2_CH:
961 /* Radio2 channel */
962 if (tree) {
963 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
964 offset, length, ett_cdp_tlv, NULL, "Radio 2 channel: %s",
965 tvb_format_text(pinfo->pool, tvb, offset + 4, length - 4));
966 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
967 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
968 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII);
970 offset += length;
971 break;
973 case TYPE_HP_RADIO1_OMODE:
974 /* Radio1 Operating mode */
975 if (tree) {
976 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
977 offset, length, ett_cdp_tlv, NULL, "Radio 1 operating mode: %s",
978 tvb_format_text(pinfo->pool, tvb, offset + 4, length - 4));
979 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
980 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
981 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII);
983 offset += length;
984 break;
986 case TYPE_HP_RADIO2_OMODE:
987 /* Radio2 Operating mode */
988 if (tree) {
989 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
990 offset, length, ett_cdp_tlv, NULL, "Radio 2 operating mode: %s",
991 tvb_format_text(pinfo->pool, tvb, offset + 4, length - 4));
992 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
993 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
994 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII);
996 offset += length;
997 break;
999 case TYPE_HP_RADIO1_RMODE:
1000 /* Radio1 Radio mode */
1001 if (tree) {
1002 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
1003 offset, length, ett_cdp_tlv, NULL, "Radio 1 radio mode: %s",
1004 tvb_format_text(pinfo->pool, tvb, offset + 4, length - 4));
1005 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
1006 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
1007 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII);
1009 offset += length;
1010 break;
1012 case TYPE_HP_RADIO2_RMODE:
1013 /* Radio2 Radio mode */
1014 if (tree) {
1015 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb,
1016 offset, length, ett_cdp_tlv, NULL, "Radio 2 radio mode: %s",
1017 tvb_format_text(pinfo->pool, tvb, offset + 4, length - 4));
1018 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
1019 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
1020 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII);
1022 offset += length;
1023 break;
1025 default:
1026 if (tree) {
1027 tlv_tree = proto_tree_add_subtree_format(cdp_tree, tvb, offset,
1028 length, ett_cdp_tlv, NULL, "Type: %s, length: %u",
1029 val_to_str(type, type_vals, "Unknown (0x%04x)"),
1030 length);
1031 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
1032 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
1033 if (length > 4) {
1034 proto_tree_add_item(tlv_tree, hf_cdp_data, tvb, offset + 4, length - 4, ENC_NA);
1035 } else {
1036 return tvb_captured_length(tvb);
1039 offset += length;
1042 call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, cdp_tree);
1043 return tvb_captured_length(tvb);
1046 #define PROTO_TYPE_NLPID 1
1047 #define PROTO_TYPE_IEEE_802_2 2
1049 static const value_string proto_type_vals[] = {
1050 { PROTO_TYPE_NLPID, "NLPID" },
1051 { PROTO_TYPE_IEEE_802_2, "802.2" },
1052 { 0, NULL }
1055 static int
1056 dissect_address_tlv(tvbuff_t *tvb, packet_info* pinfo, int offset, int length, proto_tree *tree)
1058 proto_item *ti;
1059 proto_tree *address_tree;
1060 uint8_t protocol_type;
1061 uint8_t protocol_length;
1062 int nlpid = 0;
1063 uint16_t address_length;
1064 uint16_t etypeid = 0;
1065 int hf_addr = 0;
1067 if (length < 1)
1068 return -1;
1069 address_tree = proto_tree_add_subtree(tree, tvb, offset, length, ett_cdp_address, &ti, "Truncated address");
1070 protocol_type = tvb_get_uint8(tvb, offset);
1071 proto_tree_add_item(address_tree, hf_cdp_protocol_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1072 offset += 1;
1073 length -= 1;
1075 if (length < 1)
1076 return -1;
1077 protocol_length = tvb_get_uint8(tvb, offset);
1078 proto_tree_add_item(address_tree, hf_cdp_protocol_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1079 offset += 1;
1080 length -= 1;
1082 if (length < protocol_length) {
1083 if (length != 0) {
1084 ti = proto_tree_add_item(address_tree, hf_cdp_protocol, tvb, offset, length, ENC_NA);
1085 proto_item_append_text(ti, " (truncated)");
1087 return -1;
1090 if ((protocol_type == PROTO_TYPE_NLPID) && (protocol_length == 1)) {
1091 nlpid = tvb_get_uint8(tvb, offset);
1092 proto_tree_add_bytes_format_value(address_tree, hf_cdp_protocol, tvb, offset, protocol_length, NULL, "%s",
1093 val_to_str(nlpid, nlpid_vals, "Unknown (0x%02x)"));
1094 } else if ((protocol_type == PROTO_TYPE_IEEE_802_2) && (protocol_length == 8) && (tvb_get_ntoh48(tvb, offset) == 0xAAAA03000000)) {
1095 etypeid = tvb_get_ntohs(tvb, offset + 6);
1096 proto_tree_add_bytes_format_value(address_tree, hf_cdp_protocol, tvb, offset, protocol_length, NULL, "%s",
1097 val_to_str(etypeid, etype_vals, "Unknown (0x%04x)"));
1098 } else {
1099 nlpid = -1;
1100 proto_tree_add_item(address_tree, hf_cdp_protocol, tvb, offset, protocol_length, ENC_NA);
1102 offset += protocol_length;
1103 length -= protocol_length;
1105 if (length < 2)
1106 return -1;
1107 address_length = tvb_get_ntohs(tvb, offset);
1108 proto_tree_add_item(address_tree, hf_cdp_address_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1109 offset += 2;
1110 length -= 2;
1112 if (length < address_length) {
1113 if (length != 0) {
1114 ti = proto_tree_add_item(address_tree, hf_cdp_address, tvb, offset, length, ENC_NA);
1115 proto_item_append_text(ti, " (truncated)");
1117 return -1;
1119 /* XXX - the Cisco document seems to be saying that, for 802.2-format
1120 protocol types, 0xAAAA03 0x000000 0x0800 is IPv6, but 0x0800 is
1121 the Ethernet protocol type for IPv4. */
1122 if ((protocol_type == PROTO_TYPE_NLPID) && (protocol_length == 1)) {
1123 switch (nlpid) {
1125 /* XXX - dissect NLPID_ISO8473_CLNP as OSI CLNP address? */
1127 case NLPID_IP:
1128 if (address_length == 4) {
1129 /* The address is an IP address. */
1130 proto_item_set_text(ti, "IP address: %s", tvb_ip_to_str(pinfo->pool, tvb, offset));
1131 hf_addr = hf_cdp_nrgyz_ip_address;
1132 proto_tree_add_item(address_tree, hf_cdp_nrgyz_ip_address, tvb, offset, address_length, ENC_BIG_ENDIAN);
1134 break;
1137 if ((protocol_type == PROTO_TYPE_IEEE_802_2) && (protocol_length == 8) && (etypeid > 0)) {
1139 * See also:
1141 * http://www.rhyshaden.com/cdp.htm
1143 * where other Ethertypes are mentioned.
1145 switch (etypeid) {
1147 case ETHERTYPE_IPv6:
1148 if (address_length == 16) {
1149 /* The address is an IPv6 address. */
1150 proto_item_set_text(ti, "IPv6 address: %s", tvb_ip6_to_str(pinfo->pool, tvb, offset));
1151 hf_addr = hf_cdp_nrgyz_ip6_address;
1152 proto_tree_add_item(address_tree, hf_cdp_nrgyz_ip6_address, tvb, offset, address_length, ENC_NA);
1154 break;
1158 if (hf_addr == 0)
1160 proto_tree_add_item(address_tree, hf_cdp_address, tvb, offset, address_length, ENC_NA);
1161 if(address_length)
1163 proto_item_set_text(ti, "Address: %s", tvb_bytes_to_str(pinfo->pool, tvb, offset, address_length));
1167 return 2 + protocol_length + 2 + address_length;
1170 static void
1171 dissect_capabilities(tvbuff_t *tvb, int offset, int length, proto_tree *tree)
1173 proto_item *ti;
1174 proto_tree *capabilities_tree;
1176 if (length < 4)
1177 return;
1178 ti = proto_tree_add_item(tree, hf_cdp_capabilities, tvb, offset, 4, ENC_BIG_ENDIAN);
1179 capabilities_tree = proto_item_add_subtree(ti, ett_cdp_capabilities);
1180 proto_tree_add_item(capabilities_tree, hf_cdp_capabilities_router, tvb, offset, 4, ENC_BIG_ENDIAN);
1181 proto_tree_add_item(capabilities_tree, hf_cdp_capabilities_trans_bridge, tvb, offset, 4, ENC_BIG_ENDIAN);
1182 proto_tree_add_item(capabilities_tree, hf_cdp_capabilities_src_bridge, tvb, offset, 4, ENC_BIG_ENDIAN);
1183 proto_tree_add_item(capabilities_tree, hf_cdp_capabilities_switch, tvb, offset, 4, ENC_BIG_ENDIAN);
1184 proto_tree_add_item(capabilities_tree, hf_cdp_capabilities_host, tvb, offset, 4, ENC_BIG_ENDIAN);
1185 proto_tree_add_item(capabilities_tree, hf_cdp_capabilities_igmp_capable, tvb, offset, 4, ENC_BIG_ENDIAN);
1186 proto_tree_add_item(capabilities_tree, hf_cdp_capabilities_repeater, tvb, offset, 4, ENC_BIG_ENDIAN);
1187 proto_tree_add_item(capabilities_tree, hf_cdp_capabilities_voip_phone , tvb, offset, 4, ENC_BIG_ENDIAN);
1188 proto_tree_add_item(capabilities_tree, hf_cdp_capabilities_remote, tvb, offset, 4, ENC_BIG_ENDIAN);
1189 proto_tree_add_item(capabilities_tree, hf_cdp_capabilities_cvta, tvb, offset, 4, ENC_BIG_ENDIAN);
1190 proto_tree_add_item(capabilities_tree, hf_cdp_capabilities_mac_relay, tvb, offset, 4, ENC_BIG_ENDIAN);
1193 static void
1194 dissect_nrgyz_tlv(tvbuff_t *tvb, packet_info* pinfo, int offset, uint16_t length, uint16_t num,
1195 proto_tree *tree)
1197 uint32_t tlvt, tlvl;
1198 proto_tree *etree = NULL;
1199 char const *ttext = NULL;
1201 while (num-- && (length >= 8)) {
1202 tlvt = tvb_get_ntohl(tvb, offset);
1203 tlvl = tvb_get_ntohl(tvb, offset + 4);
1205 if (length < tlvl)
1206 break;
1207 length -= tlvl;
1209 if (tlvl < 8) {
1210 proto_tree_add_expert_format(tree, pinfo, &ei_cdp_nrgyz_tlvlength, tvb, offset, 8, "TLV with invalid length %u (< 8)", tlvl);
1211 offset += 8;
1212 break;
1214 else {
1215 ttext = val_to_str(tlvt, type_nrgyz_vals, "Unknown (0x%04x)");
1216 switch (tlvt) {
1217 case TYPE_NRGYZ_ROLE:
1218 case TYPE_NRGYZ_DOMAIN:
1219 case TYPE_NRGYZ_NAME:
1220 etree = proto_tree_add_subtree_format(tree, tvb, offset,
1221 tlvl, ett_cdp_nrgyz_tlv, NULL, "EnergyWise %s: %s", ttext,
1222 tvb_format_stringzpad(pinfo->pool, tvb, offset + 8, tlvl - 8)
1224 break;
1225 case TYPE_NRGYZ_REPLYTO:
1226 etree = proto_tree_add_subtree_format(tree, tvb, offset,
1227 tlvl, ett_cdp_nrgyz_tlv, NULL, "EnergyWise %s: %s port %u",
1228 ttext,
1229 tvb_ip_to_str(pinfo->pool, tvb, offset + 12),
1230 tvb_get_ntohs(tvb, offset + 10)
1232 break;
1233 default:
1234 etree = proto_tree_add_subtree_format(tree, tvb, offset,
1235 tlvl, ett_cdp_nrgyz_tlv, NULL, "EnergyWise %s TLV", ttext);
1237 proto_tree_add_item(etree, hf_cdp_nrgyz_tlvtype, tvb, offset, 4, ENC_BIG_ENDIAN);
1238 proto_tree_add_item(etree, hf_cdp_nrgyz_tlvlength, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
1239 switch (tlvt) {
1240 case TYPE_NRGYZ_ROLE:
1241 proto_tree_add_item(etree, hf_cdp_nrgyz_reply_to_role, tvb, offset + 8, tlvl - 8, ENC_NA|ENC_ASCII);
1242 break;
1243 case TYPE_NRGYZ_DOMAIN:
1244 proto_tree_add_item(etree, hf_cdp_nrgyz_reply_to_domain, tvb, offset + 8, tlvl - 8, ENC_NA|ENC_ASCII);
1245 break;
1246 case TYPE_NRGYZ_NAME:
1247 proto_tree_add_item(etree, hf_cdp_nrgyz_reply_to_name, tvb, offset + 8, tlvl - 8, ENC_NA|ENC_ASCII);
1248 break;
1249 case TYPE_NRGYZ_REPLYTO:
1250 proto_tree_add_item(etree, hf_cdp_nrgyz_reply_to_unknown_field, tvb, offset + 8, 2, ENC_BIG_ENDIAN);
1251 proto_tree_add_item(etree, hf_cdp_nrgyz_reply_to_port, tvb, offset + 10, 2, ENC_BIG_ENDIAN);
1252 proto_tree_add_item(etree, hf_cdp_nrgyz_reply_to_ip_address, tvb, offset + 12, 4, ENC_BIG_ENDIAN);
1253 proto_tree_add_item(etree, hf_cdp_nrgyz_reply_to_backup_server_port, tvb, offset + 16, 2, ENC_BIG_ENDIAN);
1254 proto_tree_add_item(etree, hf_cdp_nrgyz_reply_to_backup_server_ip, tvb, offset + 18, 4, ENC_BIG_ENDIAN);
1255 break;
1256 default:
1257 if (tlvl > 8) {
1258 proto_tree_add_item(etree, hf_cdp_data, tvb, offset + 8, tlvl - 8, ENC_NA);
1261 offset += tlvl;
1264 if (length) {
1265 proto_tree_add_expert(tree, pinfo, &ei_cdp_invalid_data, tvb, offset, length);
1269 static void
1270 dissect_spare_poe_tlv(tvbuff_t *tvb, int offset, int length,
1271 proto_tree *tree)
1273 proto_item *ti;
1274 proto_tree *tlv_tree;
1276 if (length == 0) {
1277 return;
1280 ti = proto_tree_add_item(tree, hf_cdp_spare_poe_tlv, tvb, offset, 1, ENC_BIG_ENDIAN);
1281 tlv_tree = proto_item_add_subtree(ti, ett_cdp_spare_poe_tlv);
1282 proto_tree_add_item(tlv_tree, hf_cdp_spare_poe_tlv_poe, tvb, offset, 1, ENC_BIG_ENDIAN);
1283 proto_tree_add_item(tlv_tree, hf_cdp_spare_poe_tlv_spare_pair_arch, tvb, offset, 1, ENC_BIG_ENDIAN);
1284 proto_tree_add_item(tlv_tree, hf_cdp_spare_poe_tlv_req_spare_pair_poe, tvb, offset, 1, ENC_BIG_ENDIAN);
1285 proto_tree_add_item(tlv_tree, hf_cdp_spare_poe_tlv_pse_spare_pair_poe, tvb, offset, 1, ENC_BIG_ENDIAN);
1288 static void
1289 add_multi_line_string_to_tree(wmem_allocator_t *scope, proto_tree *tree, tvbuff_t *tvb, int start,
1290 int len, int hf)
1292 int next;
1293 int line_len;
1294 int data_len;
1296 while (len > 0) {
1297 line_len = tvb_find_line_end(tvb, start, len, &next, false);
1298 data_len = next - start;
1299 proto_tree_add_string(tree, hf, tvb, start, data_len, tvb_format_stringzpad(scope, tvb, start, line_len));
1300 start += data_len;
1301 len -= data_len;
1305 void
1306 proto_register_cdp(void)
1308 static hf_register_info hf[] = {
1309 { &hf_cdp_version,
1310 { "Version", "cdp.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1311 NULL, HFILL }},
1313 { &hf_cdp_ttl,
1314 { "TTL", "cdp.ttl", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_second_seconds), 0x0,
1315 NULL, HFILL }},
1317 { &hf_cdp_checksum,
1318 { "Checksum", "cdp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1319 NULL, HFILL }},
1321 { &hf_cdp_checksum_status,
1322 { "Checksum Status", "cdp.checksum.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
1323 NULL, HFILL }},
1325 { &hf_cdp_tlvtype,
1326 { "Type", "cdp.tlv.type", FT_UINT16, BASE_HEX, VALS(type_vals), 0x0,
1327 NULL, HFILL }},
1329 { &hf_cdp_tlvlength,
1330 { "Length", "cdp.tlv.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1331 NULL, HFILL }},
1333 { &hf_cdp_nrgyz_tlvtype,
1334 { "TLV Type", "cdp.nrgyz.tlv.type", FT_UINT32, BASE_HEX, VALS(type_nrgyz_vals), 0x0,
1335 NULL, HFILL }},
1337 { &hf_cdp_nrgyz_tlvlength,
1338 { "TLV Length", "cdp.nrgyz.tlv.len", FT_UINT32, BASE_DEC, NULL, 0x0,
1339 NULL, HFILL }},
1341 { &hf_cdp_deviceid,
1342 {"Device ID", "cdp.deviceid", FT_STRING, BASE_NONE,
1343 NULL, 0, NULL, HFILL }},
1345 { &hf_cdp_platform,
1346 {"Platform", "cdp.platform", FT_STRING, BASE_NONE,
1347 NULL, 0, NULL, HFILL }},
1349 { &hf_cdp_portid,
1350 {"Sent through Interface", "cdp.portid", FT_STRING, BASE_NONE,
1351 NULL, 0, NULL, HFILL }},
1353 { &hf_cdp_capabilities,
1354 {"Capabilities", "cdp.capabilities", FT_UINT32, BASE_HEX,
1355 NULL, 0, NULL, HFILL }},
1357 { &hf_cdp_capabilities_router,
1358 {"Router", "cdp.capabilities.router", FT_BOOLEAN, 32,
1359 TFS(&tfs_yes_no), 0x00000001, NULL, HFILL }},
1361 { &hf_cdp_capabilities_trans_bridge,
1362 {"Transparent Bridge", "cdp.capabilities.trans_bridge", FT_BOOLEAN, 32,
1363 TFS(&tfs_yes_no), 0x00000002, NULL, HFILL }},
1365 { &hf_cdp_capabilities_src_bridge,
1366 {"Source Route Bridge", "cdp.capabilities.src_bridge", FT_BOOLEAN, 32,
1367 TFS(&tfs_yes_no), 0x00000004, NULL, HFILL }},
1369 { &hf_cdp_capabilities_switch,
1370 {"Switch", "cdp.capabilities.switch", FT_BOOLEAN, 32,
1371 TFS(&tfs_yes_no), 0x00000008, NULL, HFILL }},
1373 { &hf_cdp_capabilities_host,
1374 {"Host", "cdp.capabilities.host", FT_BOOLEAN, 32,
1375 TFS(&tfs_yes_no), 0x00000010, NULL, HFILL }},
1377 { &hf_cdp_capabilities_igmp_capable,
1378 {"IGMP capable", "cdp.capabilities.igmp_capable", FT_BOOLEAN, 32,
1379 TFS(&tfs_yes_no), 0x00000020, NULL, HFILL }},
1381 { &hf_cdp_capabilities_repeater,
1382 {"Repeater", "cdp.capabilities.repeater", FT_BOOLEAN, 32,
1383 TFS(&tfs_yes_no), 0x00000040, NULL, HFILL }},
1385 { &hf_cdp_capabilities_voip_phone,
1386 {"VoIP Phone", "cdp.capabilities.voip_phone", FT_BOOLEAN, 32,
1387 TFS(&tfs_yes_no), 0x00000080, NULL, HFILL }},
1389 { &hf_cdp_capabilities_remote,
1390 {"Remotely Managed Device", "cdp.capabilities.remote", FT_BOOLEAN, 32,
1391 TFS(&tfs_yes_no), 0x00000100, NULL, HFILL }},
1393 { &hf_cdp_capabilities_cvta,
1394 {"CVTA/STP Dispute Resolution/Cisco VT Camera", "cdp.capabilities.cvta", FT_BOOLEAN, 32,
1395 TFS(&tfs_yes_no), 0x00000200, NULL, HFILL }},
1397 { &hf_cdp_capabilities_mac_relay,
1398 {"Two Port Mac Relay", "cdp.capabilities.mac_relay", FT_BOOLEAN, 32,
1399 TFS(&tfs_yes_no), 0x00000400, NULL, HFILL }},
1401 { &hf_cdp_spare_poe_tlv,
1402 { "Spare Pair PoE", "cdp.spare_poe_tlv", FT_UINT8, BASE_HEX,
1403 NULL, 0x0, NULL, HFILL }
1406 { &hf_cdp_spare_poe_tlv_poe,
1407 { "PSE Four-Wire PoE", "cdp.spare_poe_tlv.poe", FT_BOOLEAN, 8,
1408 TFS(&tfs_supported_not_supported), 0x01, NULL, HFILL }
1411 { &hf_cdp_spare_poe_tlv_spare_pair_arch,
1412 { "PD Spare Pair Architecture", "cdp.spare_poe_tlv.spare_pair_arch", FT_BOOLEAN, 8,
1413 TFS(&tfs_shared_independent), 0x02, NULL, HFILL }
1416 { &hf_cdp_spare_poe_tlv_req_spare_pair_poe,
1417 { "PD Request Spare Pair PoE", "cdp.spare_poe_tlv.req_spare_pair_poe", FT_BOOLEAN, 8,
1418 TFS(&tfs_on_off), 0x04, NULL, HFILL }
1421 { &hf_cdp_spare_poe_tlv_pse_spare_pair_poe,
1422 { "PSE Spare Pair PoE", "cdp.spare_poe_tlv.pse_spare_pair_poe", FT_BOOLEAN, 8,
1423 TFS(&tfs_on_off), 0x08, NULL, HFILL }
1426 /* Generated from convert_proto_tree_add_text.pl */
1427 { &hf_cdp_number_of_addresses, { "Number of addresses", "cdp.number_of_addresses", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1428 { &hf_cdp_odr_default_gateway, { "ODR Default gateway", "cdp.odr_default_gateway", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1429 { &hf_cdp_ip_prefix, { "IP Prefix", "cdp.ip_prefix", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1430 { &hf_cdp_oui, { "OUI", "cdp.oui", FT_UINT24, BASE_OUI, NULL, 0x0, NULL, HFILL }},
1431 { &hf_cdp_protocol_id, { "Protocol ID", "cdp.protocol_id", FT_UINT16, BASE_HEX, VALS(type_hello_vals), 0x0, NULL, HFILL }},
1432 { &hf_cdp_cluster_master_ip, { "Cluster Master IP", "cdp.cluster.master_ip", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1433 { &hf_cdp_cluster_ip, { "IP?", "cdp.cluster.ip", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1434 { &hf_cdp_cluster_version, { "Version?", "cdp.cluster.version", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1435 { &hf_cdp_cluster_sub_version, { "Sub Version?", "cdp.cluster.sub_version", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1436 { &hf_cdp_cluster_status, { "Status?", "cdp.cluster.status", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1437 { &hf_cdp_cluster_unknown, { "UNKNOWN", "cdp.cluster.unknown", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1438 { &hf_cdp_cluster_commander_mac, { "Cluster Commander MAC", "cdp.cluster.commander_mac", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1439 { &hf_cdp_cluster_switch_mac, { "Switch's MAC", "cdp.cluster.switch_mac", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1440 { &hf_cdp_cluster_management_vlan, { "Management VLAN", "cdp.cluster.management_vlan", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1441 { &hf_cdp_hello_unknown, { "Unknown", "cdp.hello.unknown", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1442 { &hf_cdp_vtp_management_domain, { "VTP Management Domain", "cdp.vtp_management_domain", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1443 { &hf_cdp_native_vlan, { "Native VLAN", "cdp.native_vlan", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1444 { &hf_cdp_duplex, { "Duplex", "cdp.duplex", FT_BOOLEAN, BASE_NONE, TFS(&tfs_full_half), 0x0, NULL, HFILL }},
1445 { &hf_cdp_data, { "Data", "cdp.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1446 { &hf_cdp_voice_vlan, { "Voice VLAN", "cdp.voice_vlan", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1447 { &hf_cdp_power_consumption, { "Power Consumption", "cdp.power_consumption", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_milliwatt), 0x0, NULL, HFILL }},
1448 { &hf_cdp_mtu, { "MTU", "cdp.mtu", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1449 { &hf_cdp_trust_bitmap, { "Trust Bitmap", "cdp.trust_bitmap", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1450 { &hf_cdp_untrusted_port_cos, { "Untrusted port CoS", "cdp.untrusted_port_cos", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1451 { &hf_cdp_system_name, { "System Name", "cdp.system_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1452 { &hf_cdp_system_object_identifier, { "System Object Identifier", "cdp.system_object_identifier", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1453 { &hf_cdp_location_unknown, { "UNKNOWN", "cdp.location.unknown", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1454 { &hf_cdp_location, { "Location", "cdp.location", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1455 { &hf_cdp_request_id, { "Request-ID", "cdp.request_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1456 { &hf_cdp_management_id, { "Management-ID", "cdp.management_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1457 { &hf_cdp_power_requested, { "Power Requested", "cdp.power_requested", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_milliwatt), 0x0, NULL, HFILL }},
1458 { &hf_cdp_power_available, { "Power Available", "cdp.power_available", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_milliwatt), 0x0, NULL, HFILL }},
1459 { &hf_cdp_encrypted_data, { "Encrypted Data", "cdp.encrypted_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1460 { &hf_cdp_seen_sequence, { "Seen Sequence?", "cdp.seen_sequence", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1461 { &hf_cdp_sequence_number, { "Sequence Number", "cdp.sequence_number", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1462 { &hf_cdp_model_number, { "Model Number", "cdp.model_number", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1463 { &hf_cdp_unknown_pad, { "Unknown Pad", "cdp.unknown_pad", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1464 { &hf_cdp_hardware_version_id, { "Hardware Version ID", "cdp.hardware_version_id", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1465 { &hf_cdp_system_serial_number, { "System Serial Number", "cdp.system_serial_number", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1466 { &hf_cdp_nrgyz_unknown_values, { "Unknown Values", "cdp.nrgyz_unknown_values", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1467 { &hf_cdp_len_tlv_table, { "Length of TLV table", "cdp.len_tlv_table", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1468 { &hf_cdp_num_tlvs_table, { "Number of TLVs in table", "cdp.num_tlvs_table", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1469 { &hf_cdp_protocol, { "Protocol", "cdp.protocol", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1470 { &hf_cdp_protocol_type, { "Protocol type", "cdp.protocol_type", FT_UINT8, BASE_HEX, VALS(proto_type_vals), 0x0, NULL, HFILL }},
1471 { &hf_cdp_protocol_length, { "Protocol length", "cdp.protocol_length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1472 { &hf_cdp_address, { "Address", "cdp.address", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1473 { &hf_cdp_address_length, { "Address length", "cdp.address_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1474 { &hf_cdp_nrgyz_reply_to_unknown_field, { "Unknown Field", "cdp.nrgyz_reply_to.unknown_field", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1475 { &hf_cdp_nrgyz_reply_to_port, { "Port", "cdp.nrgyz_reply_to.port", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1476 { &hf_cdp_nrgyz_ip_address, { "IP Address", "cdp.nrgyz.ip_address", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1477 { &hf_cdp_nrgyz_ip6_address, { "IPv6 Address", "cdp.nrgyz.ipv6_address", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1478 { &hf_cdp_nrgyz_reply_to_ip_address, { "IP Address", "cdp.nrgyz_reply_to.ip_address", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1479 { &hf_cdp_nrgyz_reply_to_backup_server_port, { "Backup server Port?", "cdp.nrgyz_reply_to.backup_server_port", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1480 { &hf_cdp_nrgyz_reply_to_backup_server_ip, { "Backup Server IP?", "cdp.nrgyz_reply_to.backup_server_ip", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1481 { &hf_cdp_nrgyz_reply_to_name, { "Name", "cdp.nrgyz_reply_to.name", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1482 { &hf_cdp_nrgyz_reply_to_domain, { "Domain", "cdp.nrgyz_reply_to.domain", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1483 { &hf_cdp_nrgyz_reply_to_role, { "Role", "cdp.nrgyz_reply_to.role", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1484 { &hf_cdp_software_version, { "Software version", "cdp.software_version", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1487 static int *ett[] = {
1488 &ett_cdp,
1489 &ett_cdp_tlv,
1490 &ett_cdp_nrgyz_tlv,
1491 &ett_cdp_address,
1492 &ett_cdp_capabilities,
1493 &ett_cdp_checksum,
1494 &ett_cdp_spare_poe_tlv
1497 static ei_register_info ei[] = {
1498 { &ei_cdp_invalid_data, { "cdp.invalid_data", PI_MALFORMED, PI_ERROR, "Invalid bytes at end", EXPFILL }},
1499 { &ei_cdp_nrgyz_tlvlength, { "cdp.nrgyz_tlv.length.invalid", PI_MALFORMED, PI_ERROR, "TLV with invalid length", EXPFILL }},
1500 { &ei_cdp_checksum, { "cdp.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
1503 expert_module_t* expert_cdp;
1505 proto_cdp = proto_register_protocol("Cisco Discovery Protocol", "CDP", "cdp");
1506 cdp_handle = register_dissector("cdp", dissect_cdp, proto_cdp);
1508 proto_register_field_array(proto_cdp, hf, array_length(hf));
1509 proto_register_subtree_array(ett, array_length(ett));
1510 expert_cdp = expert_register_protocol(proto_cdp);
1511 expert_register_field_array(expert_cdp, ei, array_length(ei));
1514 void
1515 proto_reg_handoff_cdp(void)
1517 dissector_add_uint("llc.cisco_pid", CISCO_PID_CDP, cdp_handle);
1518 dissector_add_uint("chdlc.protocol", 0x2000, cdp_handle);
1519 dissector_add_uint("ppp.protocol", 0x0207, cdp_handle);
1520 dissector_add_uint("gre.proto", 0x2000, cdp_handle);
1524 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1526 * Local variables:
1527 * c-basic-offset: 4
1528 * tab-width: 8
1529 * indent-tabs-mode: nil
1530 * End:
1532 * vi: set shiftwidth=4 tabstop=8 expandtab:
1533 * :indentSize=4:tabSize=8:noTabs=true: