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 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
29 #include <epan/packet.h>
30 #include <epan/to_str.h>
31 #include <epan/in_cksum.h>
32 #include <epan/wmem/wmem.h>
35 #include <epan/nlpid.h>
41 * http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm#xtocid12
43 * for some information on CDP.
47 * http://www.cisco.com/en/US/products/hw/switches/ps663/products_tech_note09186a0080094713.shtml#cdp
49 * for some more information on CDP version 2.
52 void proto_register_cdp(void);
53 void proto_reg_handoff_cdp(void);
55 /* Offsets in TLV structure. */
59 static int proto_cdp = -1;
60 static int hf_cdp_version = -1;
61 static int hf_cdp_checksum = -1;
62 static int hf_cdp_checksum_good = -1;
63 static int hf_cdp_checksum_bad = -1;
64 static int hf_cdp_ttl = -1;
65 static int hf_cdp_tlvtype = -1;
66 static int hf_cdp_tlvlength = -1;
67 static int hf_cdp_deviceid = -1;
68 static int hf_cdp_platform = -1;
69 static int hf_cdp_portid = -1;
70 static int hf_cdp_capabilities = -1;
71 static int hf_cdp_capabilities_router = -1;
72 static int hf_cdp_capabilities_trans_bridge = -1;
73 static int hf_cdp_capabilities_src_bridge = -1;
74 static int hf_cdp_capabilities_switch = -1;
75 static int hf_cdp_capabilities_host = -1;
76 static int hf_cdp_capabilities_igmp_capable = -1;
77 static int hf_cdp_capabilities_repeater = -1;
78 static int hf_cdp_spare_poe_tlv = -1;
79 static int hf_cdp_spare_poe_tlv_poe = -1;
80 static int hf_cdp_spare_poe_tlv_spare_pair_arch = -1;
81 static int hf_cdp_spare_poe_tlv_req_spare_pair_poe = -1;
82 static int hf_cdp_spare_poe_tlv_pse_spare_pair_poe = -1;
84 static gint ett_cdp = -1;
85 static gint ett_cdp_tlv = -1;
86 static gint ett_cdp_nrgyz_tlv = -1;
87 static gint ett_cdp_address = -1;
88 static gint ett_cdp_capabilities = -1;
89 static gint ett_cdp_spare_poe_tlv = -1;
90 static gint ett_cdp_checksum = -1;
92 static dissector_handle_t data_handle;
95 dissect_address_tlv(tvbuff_t *tvb, int offset, int length, proto_tree *tree);
97 dissect_capabilities(tvbuff_t *tvb, int offset, int length, proto_tree *tree);
99 dissect_nrgyz_tlv(tvbuff_t *tvb, int offset, guint16 length, guint16 num,
102 dissect_spare_poe_tlv(tvbuff_t *tvb, int offset, int length, proto_tree *tree);
104 add_multi_line_string_to_tree(proto_tree *tree, tvbuff_t *tvb, gint start,
105 gint len, const gchar *prefix);
107 #define TYPE_DEVICE_ID 0x0001
108 #define TYPE_ADDRESS 0x0002
109 #define TYPE_PORT_ID 0x0003
110 #define TYPE_CAPABILITIES 0x0004
111 #define TYPE_IOS_VERSION 0x0005
112 #define TYPE_PLATFORM 0x0006
113 #define TYPE_IP_PREFIX 0x0007
114 #define TYPE_PROTOCOL_HELLO 0x0008 /* Protocol Hello */
115 #define TYPE_VTP_MGMT_DOMAIN 0x0009 /* VTP Domain, CTPv2 - see second URL */
116 #define TYPE_NATIVE_VLAN 0x000a /* Native VLAN, CTPv2 - see second URL */
117 #define TYPE_DUPLEX 0x000b /* Full/Half Duplex - see second URL */
120 #define TYPE_VOIP_VLAN_REPLY 0x000e /* VoIP VLAN reply */
121 #define TYPE_VOIP_VLAN_QUERY 0x000f /* VoIP VLAN query */
122 #define TYPE_POWER 0x0010 /* Power consumption */
123 #define TYPE_MTU 0x0011 /* MTU */
124 #define TYPE_TRUST_BITMAP 0x0012 /* Trust bitmap */
125 #define TYPE_UNTRUSTED_COS 0x0013 /* Untrusted port CoS */
126 #define TYPE_SYSTEM_NAME 0x0014 /* System Name */
127 #define TYPE_SYSTEM_OID 0x0015 /* System OID */
128 #define TYPE_MANAGEMENT_ADDR 0x0016 /* Management Address(es) */
129 #define TYPE_LOCATION 0x0017 /* Location */
130 #define TYPE_EXT_PORT_ID 0x0018 /* External Port-ID */
131 #define TYPE_POWER_REQUESTED 0x0019 /* Power Requested */
132 #define TYPE_POWER_AVAILABLE 0x001a /* Power Available */
133 #define TYPE_PORT_UNIDIR 0x001b /* Port Unidirectional */
134 #define TYPE_NRGYZ 0x001d /* EnergyWise over CDP */
135 #define TYPE_SPARE_POE 0x001f /* Spare Pair PoE */
137 #define TYPE_HP_BSSID 0x1000 /* BSSID */
138 #define TYPE_HP_SERIAL 0x1001 /* Serial number */
139 #define TYPE_HP_SSID 0x1002 /* SSID */
140 #define TYPE_HP_RADIO1_CH 0x1003 /* Radio1 channel */
143 #define TYPE_HP_SNMP_PORT 0x1006 /* SNMP listening UDP port */
144 #define TYPE_HP_MGMT_PORT 0x1007 /* Web interface TCP port */
145 #define TYPE_HP_SOURCE_MAC 0x1008 /* Sender MAC address for the AP, bouth wired and wireless */
146 #define TYPE_HP_RADIO2_CH 0x1009 /* Radio2 channel */
147 #define TYPE_HP_RADIO1_OMODE 0x100A /* Radio1 Operating mode */
148 #define TYPE_HP_RADIO2_OMODE 0x100B /* Radio2 Operating mode */
149 #define TYPE_HP_RADIO1_RMODE 0x100C /* Radio1 Radio mode */
150 #define TYPE_HP_RADIO2_RMODE 0x100D /* Radio2 Radio mode */
152 static const value_string type_vals[] = {
153 { TYPE_DEVICE_ID, "Device ID" },
154 { TYPE_ADDRESS, "Addresses" },
155 { TYPE_PORT_ID, "Port ID" },
156 { TYPE_CAPABILITIES, "Capabilities" },
157 { TYPE_IOS_VERSION, "Software version" },
158 { TYPE_PLATFORM, "Platform" },
159 { TYPE_IP_PREFIX, "IP Prefix/Gateway (used for ODR)" },
160 { TYPE_PROTOCOL_HELLO, "Protocol Hello" },
161 { TYPE_VTP_MGMT_DOMAIN, "VTP Management Domain" },
162 { TYPE_NATIVE_VLAN, "Native VLAN" },
163 { TYPE_DUPLEX, "Duplex" },
164 { TYPE_VOIP_VLAN_REPLY, "VoIP VLAN Reply" },
165 { TYPE_VOIP_VLAN_QUERY, "VoIP VLAN Query" },
166 { TYPE_POWER, "Power consumption" },
168 { TYPE_TRUST_BITMAP, "Trust Bitmap" },
169 { TYPE_UNTRUSTED_COS, "Untrusted Port CoS" },
170 { TYPE_SYSTEM_NAME, "System Name" },
171 { TYPE_SYSTEM_OID, "System Object ID" },
172 { TYPE_MANAGEMENT_ADDR, "Management Address" },
173 { TYPE_LOCATION, "Location" },
174 { TYPE_EXT_PORT_ID, "External Port-ID" },
175 { TYPE_POWER_REQUESTED, "Power Requested" },
176 { TYPE_POWER_AVAILABLE, "Power Available" },
177 { TYPE_PORT_UNIDIR, "Port Unidirectional" },
178 { TYPE_NRGYZ, "EnergyWise" },
179 { TYPE_SPARE_POE, "Spare PoE" },
180 { TYPE_HP_BSSID, "BSSID" },
181 { TYPE_HP_SERIAL, "Serial number" },
182 { TYPE_HP_SSID, "SSID" },
183 { TYPE_HP_RADIO1_CH, "Radio1 channel" },
184 { TYPE_HP_SNMP_PORT, "SNMP UDP port" },
185 { TYPE_HP_MGMT_PORT, "Web TCP port" },
186 { TYPE_HP_SOURCE_MAC, "Source MAC address" },
187 { TYPE_HP_RADIO2_CH, "Radio2 channel" },
188 { TYPE_HP_RADIO1_OMODE, "Radio1 Operating mode" },
189 { TYPE_HP_RADIO2_OMODE, "Radio2 Operating mode" },
190 { TYPE_HP_RADIO1_RMODE, "Radio1 Radio mode" },
191 { TYPE_HP_RADIO2_RMODE, "Radio2 Radio mode" },
195 #define TYPE_HELLO_CLUSTER_MGMT 0x0112
197 static const value_string type_hello_vals[] = {
198 { TYPE_HELLO_CLUSTER_MGMT, "Cluster Management" },
202 #define TYPE_NRGYZ_ROLE 0x00000007
203 #define TYPE_NRGYZ_DOMAIN 0x00000008
204 #define TYPE_NRGYZ_NAME 0x00000009
205 #define TYPE_NRGYZ_REPLYTO 0x00000017
207 static const value_string type_nrgyz_vals[] = {
208 { TYPE_NRGYZ_ROLE, "Role" },
209 { TYPE_NRGYZ_DOMAIN, "Domain" },
210 { TYPE_NRGYZ_NAME, "Name" },
211 { TYPE_NRGYZ_REPLYTO, "Reply To" },
216 dissect_cdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
218 proto_item *ti, *checksum_item;
219 proto_tree *cdp_tree = NULL, *checksum_tree;
222 guint16 length, packet_checksum, computed_checksum, data_length;
223 gboolean checksum_good, checksum_bad;
224 proto_item *tlvi = NULL;
225 proto_tree *tlv_tree = NULL;
228 guint32 power_avail_len, power_avail;
229 guint32 power_req_len, power_req;
234 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CDP");
235 col_clear(pinfo->cinfo, COL_INFO);
238 ti = proto_tree_add_item(tree, proto_cdp, tvb, offset, -1, ENC_NA);
239 cdp_tree = proto_item_add_subtree(ti, ett_cdp);
242 proto_tree_add_item(cdp_tree, hf_cdp_version, tvb, offset, 1, ENC_BIG_ENDIAN);
245 proto_tree_add_uint_format_value(cdp_tree, hf_cdp_ttl, tvb, offset, 1,
246 tvb_get_guint8(tvb, offset),
248 tvb_get_guint8(tvb, offset));
251 offset += 2; /* The version/ttl fields from above */
254 /* Checksum display & verification code */
255 packet_checksum = tvb_get_ntohs(tvb, offset);
257 data_length = tvb_reported_length(tvb);
259 /* CDP doesn't adhere to RFC 1071 section 2. (B). It incorrectly assumes
260 * checksums are calculated on a big endian platform, therefore i.s.o.
261 * padding odd sized data with a zero byte _at the end_ it sets the last
262 * big endian _word_ to contain the last network _octet_. This byteswap
263 * has to be done on the last octet of network data before feeding it to
264 * the Internet checksum routine.
265 * CDP checksumming code has a bug in the addition of this last _word_
266 * as a signed number into the long word intermediate checksum. When
267 * reducing this long to word size checksum an off-by-one error can be
268 * made. This off-by-one error is compensated for in the last _word_ of
271 if (data_length & 1) {
272 guint8 *padded_buffer;
273 /* Allocate new buffer */
274 padded_buffer = (guint8 *)wmem_alloc(wmem_packet_scope(), data_length+1);
275 tvb_memcpy(tvb, padded_buffer, 0, data_length);
276 /* Swap bytes in last word */
277 padded_buffer[data_length] = padded_buffer[data_length-1];
278 padded_buffer[data_length-1] = 0;
279 /* Compensate off-by-one error */
280 if (padded_buffer[data_length] & 0x80) {
281 padded_buffer[data_length]--;
282 padded_buffer[data_length-1]--;
284 /* Setup checksum routine data buffer */
285 cksum_vec[0].ptr = padded_buffer;
286 cksum_vec[0].len = data_length+1;
288 /* Setup checksum routine data buffer */
289 cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, data_length);
290 cksum_vec[0].len = data_length;
293 computed_checksum = in_cksum(cksum_vec, 1);
294 checksum_good = (computed_checksum == 0);
295 checksum_bad = !checksum_good;
297 checksum_item = proto_tree_add_uint_format_value(cdp_tree,
298 hf_cdp_checksum, tvb, offset, 2, packet_checksum,
299 "0x%04x [correct]", packet_checksum);
301 checksum_item = proto_tree_add_uint_format_value(cdp_tree,
302 hf_cdp_checksum, tvb, offset, 2, packet_checksum,
303 "0x%04x [incorrect, should be 0x%04x]",
305 in_cksum_shouldbe(packet_checksum, computed_checksum));
308 checksum_tree = proto_item_add_subtree(checksum_item, ett_cdp_checksum);
309 checksum_item = proto_tree_add_boolean(checksum_tree, hf_cdp_checksum_good,
310 tvb, offset, 2, checksum_good);
311 PROTO_ITEM_SET_GENERATED(checksum_item);
312 checksum_item = proto_tree_add_boolean(checksum_tree, hf_cdp_checksum_bad,
313 tvb, offset, 2, checksum_bad);
314 PROTO_ITEM_SET_GENERATED(checksum_item);
318 while (tvb_reported_length_remaining(tvb, offset) != 0) {
319 type = tvb_get_ntohs(tvb, offset + TLV_TYPE);
320 length = tvb_get_ntohs(tvb, offset + TLV_LENGTH);
323 tlvi = proto_tree_add_text(cdp_tree, tvb, offset, 4,
324 "TLV with invalid length %u (< 4)",
326 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
327 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
328 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
339 col_append_fstr(pinfo->cinfo, COL_INFO,
341 tvb_format_stringzpad(tvb, offset + 4, length - 4));
344 tlvi = proto_tree_add_text(cdp_tree, tvb, offset,
345 length, "Device ID: %s",
346 tvb_format_stringzpad(tvb, offset + 4, length - 4));
347 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
348 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
349 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
350 proto_tree_add_item(tlv_tree, hf_cdp_deviceid, tvb, offset + 4, length - 4, ENC_ASCII|ENC_NA);
356 real_length = length;
357 if (tvb_get_guint8(tvb, offset + real_length) != 0x00) {
358 /* The length in the TLV doesn't appear to be the
359 length of the TLV, as the byte just past it
360 isn't the first byte of a 2-byte big-endian
361 small integer; make the length of the TLV the length
362 in the TLV, plus 4 bytes for the TLV type and length,
363 minus 1 because that's what makes one capture work. */
364 real_length = length + 3;
367 col_append_fstr(pinfo->cinfo, COL_INFO,
369 tvb_format_stringzpad(tvb, offset + 4,
373 tlvi = proto_tree_add_text(cdp_tree, tvb, offset,
374 real_length, "Port ID: %s",
375 tvb_format_text(tvb, offset + 4, real_length - 4));
376 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
377 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
378 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
379 proto_tree_add_item(tlv_tree, hf_cdp_portid, tvb, offset + 4, real_length - 4, ENC_ASCII|ENC_NA);
381 offset += real_length;
387 tlvi = proto_tree_add_text(cdp_tree, tvb, offset,
388 length, "Addresses");
389 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
390 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
391 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
395 naddresses = tvb_get_ntohl(tvb, offset);
397 proto_tree_add_text(tlv_tree, tvb, offset, 4,
398 "Number of addresses: %u", naddresses);
402 while (naddresses != 0) {
403 addr_length = dissect_address_tlv(tvb, offset, length,
407 offset += addr_length;
408 length -= addr_length;
415 case TYPE_CAPABILITIES:
417 tlvi = proto_tree_add_text(cdp_tree, tvb, offset,
418 length, "Capabilities");
419 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
420 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
421 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
425 dissect_capabilities(tvb, offset, length, tlv_tree);
429 case TYPE_IOS_VERSION:
431 tlvi = proto_tree_add_text(cdp_tree, tvb, offset,
432 length, "Software Version");
433 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
434 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
435 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
436 add_multi_line_string_to_tree(tlv_tree, tvb, offset + 4,
437 length - 4, "Software Version: ");
445 tlvi = proto_tree_add_text(cdp_tree, tvb,
446 offset, length, "Platform: %s",
447 tvb_format_text(tvb, offset + 4, length - 4));
448 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
449 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
450 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
451 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII|ENC_NA);
458 /* if length is 8 then this is default gw not prefix */
460 tlvi = proto_tree_add_text(cdp_tree, tvb, offset,
461 length, "ODR Default gateway: %s",
462 tvb_ip_to_str(tvb, offset+4));
463 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
464 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
465 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
466 proto_tree_add_text(tlv_tree, tvb, offset+4, 4,
467 "ODR Default gateway = %s",
468 tvb_ip_to_str(tvb, offset+4));
473 tlvi = proto_tree_add_text(cdp_tree, tvb, offset,
474 length, "IP Prefixes: %d",length/5);
476 /* the actual number of prefixes is (length-4)/5
477 but if the variable is not a "float" but "integer"
478 then length/5=(length-4)/5 :) */
480 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
481 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
482 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
488 proto_tree_add_text(tlv_tree, tvb, offset, 5,
490 tvb_ip_to_str(tvb, offset),
491 tvb_get_guint8(tvb,offset+4));
499 case TYPE_PROTOCOL_HELLO:
501 tlvi = proto_tree_add_text(cdp_tree, tvb,
502 offset,length, "Protocol Hello: %s",
503 val_to_str(tvb_get_ntohs(tvb, offset+7), type_hello_vals, "Unknown (0x%04x)"));
504 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
505 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
506 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
507 proto_tree_add_text(tlv_tree, tvb, offset+4, 3,
509 tvb_get_ntoh24(tvb,offset+4),
510 val_to_str_const(tvb_get_ntoh24(tvb,offset+4), oui_vals, "Unknown"));
511 proto_tree_add_text(tlv_tree, tvb, offset+7, 2,
512 "Protocol ID: 0x%04X (%s)",
513 tvb_get_ntohs(tvb, offset+7),
514 val_to_str_const(tvb_get_ntohs(tvb, offset+7), type_hello_vals, "Unknown"));
516 switch(tvb_get_ntohs(tvb, offset+7)) {
518 case TYPE_HELLO_CLUSTER_MGMT:
519 /* proto_tree_add_text(tlv_tree, tvb, offset+9,
520 length - 9, "Cluster Management");
522 ip_addr = tvb_get_ipv4(tvb, offset+9);
523 proto_tree_add_text(tlv_tree, tvb, offset+9, 4,
524 "Cluster Master IP: %s",ip_to_str((guint8 *)&ip_addr));
525 ip_addr = tvb_get_ipv4(tvb, offset+13);
526 proto_tree_add_text(tlv_tree, tvb, offset+13, 4,
527 "UNKNOWN (IP?): 0x%08X (%s)",
528 ip_addr, ip_to_str((guint8 *)&ip_addr));
529 proto_tree_add_text(tlv_tree, tvb, offset+17, 1,
531 tvb_get_guint8(tvb, offset+17));
532 proto_tree_add_text(tlv_tree, tvb, offset+18, 1,
533 "Sub Version?: 0x%02X",
534 tvb_get_guint8(tvb, offset+18));
535 proto_tree_add_text(tlv_tree, tvb, offset+19, 1,
537 tvb_get_guint8(tvb, offset+19));
538 proto_tree_add_text(tlv_tree, tvb, offset+20, 1,
540 tvb_get_guint8(tvb, offset+20));
541 proto_tree_add_text(tlv_tree, tvb, offset+21, 6,
542 "Cluster Commander MAC: %s",
543 tvb_ether_to_str(tvb, offset+21));
544 proto_tree_add_text(tlv_tree, tvb, offset+27, 6,
546 tvb_ether_to_str(tvb, offset+27));
547 proto_tree_add_text(tlv_tree, tvb, offset+33, 1,
549 tvb_get_guint8(tvb, offset+33));
550 proto_tree_add_text(tlv_tree, tvb, offset+34, 2,
551 "Management VLAN: %d",
552 tvb_get_ntohs(tvb, offset+34));
555 proto_tree_add_text(tlv_tree, tvb, offset + 9,
556 length - 9, "Unknown");
563 case TYPE_VTP_MGMT_DOMAIN:
565 tlvi = proto_tree_add_text(cdp_tree, tvb,
566 offset, length, "VTP Management Domain: %s",
567 tvb_format_text(tvb, offset + 4, length - 4));
568 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
569 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
570 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
571 proto_tree_add_text(tlv_tree, tvb, offset + 4,
572 length - 4, "VTP Management Domain: %s",
573 tvb_format_text(tvb, offset + 4, length - 4));
578 case TYPE_NATIVE_VLAN:
580 tlvi = proto_tree_add_text(cdp_tree, tvb,
581 offset, length, "Native VLAN: %u",
582 tvb_get_ntohs(tvb, offset + 4));
583 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
584 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
585 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
586 proto_tree_add_text(tlv_tree, tvb, offset + 4,
587 length - 4, "Native VLAN: %u",
588 tvb_get_ntohs(tvb, offset + 4));
595 tlvi = proto_tree_add_text(cdp_tree, tvb,
596 offset, length, "Duplex: %s",
597 tvb_get_guint8(tvb, offset + 4) ?
599 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
600 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
601 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
602 proto_tree_add_text(tlv_tree, tvb, offset + 4,
603 length - 4, "Duplex: %s",
604 tvb_get_guint8(tvb, offset + 4) ?
610 case TYPE_VOIP_VLAN_REPLY:
613 tlvi = proto_tree_add_text(cdp_tree, tvb, offset, length,
614 "VoIP VLAN Reply: %u", tvb_get_ntohs(tvb, offset + 5));
617 * XXX - what are these? I've seen them in some captures;
618 * they have a length of 6, and run up to the end of
619 * the packet, so if we try to dissect it the same way
620 * we dissect the 7-byte ones, we report a malformed
623 tlvi = proto_tree_add_text(cdp_tree, tvb,
624 offset, length, "VoIP VLAN Reply");
626 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
627 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
628 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
629 proto_tree_add_text(tlv_tree, tvb, offset + 4,
632 proto_tree_add_text(tlv_tree, tvb, offset + 5,
634 tvb_get_ntohs(tvb, offset + 5));
640 case TYPE_VOIP_VLAN_QUERY:
643 tlvi = proto_tree_add_text(cdp_tree, tvb,
644 offset, length, "VoIP VLAN Query: %u", tvb_get_ntohs(tvb, offset + 5));
647 * XXX - what are these? I've seen them in some captures;
648 * they have a length of 6, and run up to the end of
649 * the packet, so if we try to dissect it the same way
650 * we dissect the 7-byte ones, we report a malformed
653 tlvi = proto_tree_add_text(cdp_tree, tvb,
654 offset, length, "VoIP VLAN Query");
656 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
657 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
658 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
659 proto_tree_add_text(tlv_tree, tvb, offset + 4,
662 proto_tree_add_text(tlv_tree, tvb, offset + 5,
664 tvb_get_ntohs(tvb, offset + 5));
672 tlvi = proto_tree_add_text(cdp_tree, tvb,
673 offset, length, "Power Consumption: %u mW",
674 tvb_get_ntohs(tvb, offset + 4));
675 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
676 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
677 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
678 proto_tree_add_text(tlv_tree, tvb, offset + 4,
679 length - 4, "Power Consumption: %u mW",
680 tvb_get_ntohs(tvb, offset + 4));
687 tlvi = proto_tree_add_text(cdp_tree, tvb,
688 offset, length, "MTU: %u",
689 tvb_get_ntohl(tvb,offset + 4));
690 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
691 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
692 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
693 proto_tree_add_text(tlv_tree, tvb, offset + 4,
694 length - 4, "MTU: %u",
695 tvb_get_ntohl(tvb,offset + 4));
700 case TYPE_TRUST_BITMAP:
702 tlvi = proto_tree_add_text(cdp_tree, tvb,
703 offset, length, "Trust Bitmap: 0x%02X",
704 tvb_get_guint8(tvb, offset + 4));
705 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
706 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
707 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
708 proto_tree_add_text(tlv_tree, tvb, offset + 4,
709 length - 4, "Trust Bitmap: %02x",
710 tvb_get_guint8(tvb, offset + 4));
715 case TYPE_UNTRUSTED_COS:
717 tlvi = proto_tree_add_text(cdp_tree, tvb,
718 offset, length, "Untrusted port CoS: 0x%02X",
719 tvb_get_guint8(tvb, offset + 4));
720 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
721 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
722 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
723 proto_tree_add_text(tlv_tree, tvb, offset + 4,
724 length - 4, "Untrusted port CoS: %02x",
725 tvb_get_guint8(tvb, offset + 4));
730 case TYPE_SYSTEM_NAME:
732 tlvi = proto_tree_add_text(cdp_tree, tvb,
733 offset, length, "System Name: %s",
734 tvb_format_text(tvb, offset + 4, length - 4));
735 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
736 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
737 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
738 proto_tree_add_text(tlv_tree, tvb, offset + 4,
739 length - 4, "System Name: %s",
740 tvb_format_text(tvb, offset + 4, length - 4));
745 case TYPE_SYSTEM_OID:
747 tlvi = proto_tree_add_text(cdp_tree, tvb,
748 offset, length, "System Object Identifier");
749 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
750 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
751 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
752 proto_tree_add_text(tlv_tree, tvb, offset + 4,
753 length - 4, "System Object Identifier: %s",
754 tvb_bytes_to_ep_str(tvb, offset + 4, length - 4));
759 case TYPE_MANAGEMENT_ADDR:
761 tlvi = proto_tree_add_text(cdp_tree, tvb,
762 offset, length, "Management Addresses");
763 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
764 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
765 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
769 naddresses = tvb_get_ntohl(tvb, offset);
771 proto_tree_add_text(tlv_tree, tvb, offset, 4,
772 "Number of addresses: %u", naddresses);
776 while (naddresses != 0) {
777 addr_length = dissect_address_tlv(tvb, offset, length,
781 offset += addr_length;
782 length -= addr_length;
791 tlvi = proto_tree_add_text(cdp_tree, tvb,
792 offset, length, "Location: %s",
793 tvb_format_text(tvb, offset + 5, length - 5));
794 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
795 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
796 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
797 proto_tree_add_text(tlv_tree, tvb, offset + 4,
798 1 , "UNKNOWN: 0x%02X",
799 tvb_get_guint8(tvb, offset + 4));
800 proto_tree_add_text(tlv_tree, tvb, offset + 5,
801 length - 5, "Location: %s",
802 tvb_format_text(tvb, offset + 5, length - 5));
807 case TYPE_POWER_REQUESTED:
809 tlvi = proto_tree_add_text(cdp_tree, tvb,
810 offset, length, "Power Request: ");
811 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
812 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
813 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
814 proto_tree_add_text(tlv_tree, tvb, offset + 4,
816 tvb_get_ntohs(tvb, offset + 4));
817 proto_tree_add_text(tlv_tree, tvb, offset + 6,
818 2, "Management-ID: %u",
819 tvb_get_ntohs(tvb, offset + 6));
821 power_req_len = (tvb_get_ntohs(tvb, offset + TLV_LENGTH)) - 8;
822 /* Move offset to where the list of Power Request Values Exist */
824 while(power_req_len) {
825 if (power_req_len > 4) {
826 power_req = tvb_get_ntohl(tvb, offset);
828 proto_tree_add_text(tlv_tree, tvb, offset,
829 4, "Power Requested: %u mW", power_req);
830 proto_item_append_text(tlvi, "%u mW, ", power_req);
835 if (power_req_len == 4) {
836 power_req = tvb_get_ntohl(tvb, offset);
838 proto_tree_add_text(tlv_tree, tvb, offset,
839 4, "Power Requested: %u mW", power_req);
840 proto_item_append_text(tlvi, "%u mW", power_req);
843 offset += power_req_len;
849 case TYPE_POWER_AVAILABLE:
851 tlvi = proto_tree_add_text(cdp_tree, tvb,
852 offset, length, "Power Available: ");
853 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
854 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
855 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
856 proto_tree_add_text(tlv_tree, tvb, offset + 4,
858 tvb_get_ntohs(tvb, offset + 4));
859 proto_tree_add_text(tlv_tree, tvb, offset + 6,
860 2, "Management-ID: %u",
861 tvb_get_ntohs(tvb, offset + 6));
863 power_avail_len = (tvb_get_ntohs(tvb, offset + TLV_LENGTH)) - 8;
864 /* Move offset to where the list of Power Available Values Exist */
866 while(power_avail_len) {
867 if (power_avail_len >= 4) {
868 power_avail = tvb_get_ntohl(tvb, offset);
870 proto_tree_add_text(tlv_tree, tvb, offset,
871 4, "Power Available: %u mW", power_avail);
872 proto_item_append_text(tlvi, "%u mW, ", power_avail);
874 power_avail_len -= 4;
877 offset += power_avail_len;
885 tlvi = proto_tree_add_text(cdp_tree, tvb,
886 offset, length, "EnergyWise");
887 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
888 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
889 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
890 proto_tree_add_text(tlv_tree, tvb, offset + 4,
891 20, "Encrypted Data");
892 proto_tree_add_text(tlv_tree, tvb, offset + 24,
893 4, "Unknown (Seen Sequence?): %u",
894 tvb_get_ntohl(tvb, offset + 24));
895 proto_tree_add_text(tlv_tree, tvb, offset + 28,
896 4, "Sequence Number: %u",
897 tvb_get_ntohl(tvb, offset + 28));
898 proto_tree_add_text(tlv_tree, tvb, offset + 32,
899 16, "Model Number: %s",
900 tvb_format_stringzpad(tvb, offset + 32, 16));
901 proto_tree_add_text(tlv_tree, tvb, offset + 48,
902 2, "Unknown Pad: %x",
903 tvb_get_ntohs(tvb, offset + 48));
904 proto_tree_add_text(tlv_tree, tvb, offset + 50,
905 3, "Hardware Version ID: %s",
906 tvb_format_stringzpad(tvb, offset + 50, 3));
907 proto_tree_add_text(tlv_tree, tvb, offset + 53,
908 11, "System Serial Number: %s",
909 tvb_format_stringzpad(tvb, offset + 53, 11));
910 proto_tree_add_text(tlv_tree, tvb, offset + 64,
911 8, "Unknown Values");
912 proto_tree_add_text(tlv_tree, tvb, offset + 72,
913 2, "Length of TLV table: %u",
914 tvb_get_ntohs(tvb, offset + 72));
915 proto_tree_add_text(tlv_tree, tvb, offset + 74,
916 2, "Number of TLVs in table: %u",
917 tvb_get_ntohs(tvb, offset + 74));
919 proto_tree_add_text(tlv_tree, tvb,
920 offset + 76, length - 76,
921 "EnergyWise TLV Table");
923 dissect_nrgyz_tlv(tvb, offset + 76,
924 tvb_get_ntohs(tvb, offset + 72),
925 tvb_get_ntohs(tvb, offset + 74),
935 tlvi = proto_tree_add_text(cdp_tree, tvb, offset, length,
937 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
939 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
940 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
944 dissect_spare_poe_tlv(tvb, offset, length, tlv_tree);
951 tlvi = proto_tree_add_text(cdp_tree, tvb,
952 offset, length, "BSSID: %s",
953 tvb_format_text(tvb, offset + 4, length - 4));
954 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
955 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
956 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
957 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII|ENC_NA);
965 tlvi = proto_tree_add_text(cdp_tree, tvb,
966 offset, length, "Serial: %s",
967 tvb_format_text(tvb, offset + 4, length - 4));
968 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
969 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
970 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
971 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII|ENC_NA);
980 tlvi = proto_tree_add_text(cdp_tree, tvb,
981 offset, length, "SSID: [Empty]");
982 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
983 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
984 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
986 tlvi = proto_tree_add_text(cdp_tree, tvb,
987 offset, length, "SSID: %s",
988 tvb_format_text(tvb, offset + 4, length - 4));
989 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
990 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
991 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
992 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII|ENC_NA);
998 case TYPE_HP_RADIO1_CH:
1001 tlvi = proto_tree_add_text(cdp_tree, tvb,
1002 offset, length, "Radio 1 channel: %s",
1003 tvb_format_text(tvb, offset + 4, length - 4));
1004 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
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|ENC_NA);
1012 case TYPE_HP_SNMP_PORT:
1013 /* SNMP listening UDP port */
1015 tlvi = proto_tree_add_text(cdp_tree, tvb,
1016 offset, length, "SNMP port: %s",
1017 tvb_format_text(tvb, offset + 4, length - 4));
1018 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
1019 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
1020 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
1021 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII|ENC_NA);
1026 case TYPE_HP_MGMT_PORT:
1027 /* Web interface TCP port */
1029 tlvi = proto_tree_add_text(cdp_tree, tvb,
1030 offset, length, "Web mgmt port: %s",
1031 tvb_format_text(tvb, offset + 4, length - 4));
1032 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
1033 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
1034 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
1035 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII|ENC_NA);
1040 case TYPE_HP_SOURCE_MAC:
1041 /* Sender MAC address for the AP, bouth wired and wireless */
1043 tlvi = proto_tree_add_text(cdp_tree, tvb,
1044 offset, length, "Source MAC: %s",
1045 tvb_format_text(tvb, offset + 4, length - 4));
1046 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
1047 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
1048 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
1049 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII|ENC_NA);
1054 case TYPE_HP_RADIO2_CH:
1055 /* Radio2 channel */
1057 tlvi = proto_tree_add_text(cdp_tree, tvb,
1058 offset, length, "Radio 2 channel: %s",
1059 tvb_format_text(tvb, offset + 4, length - 4));
1060 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
1061 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
1062 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
1063 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII|ENC_NA);
1068 case TYPE_HP_RADIO1_OMODE:
1069 /* Radio1 Operating mode */
1071 tlvi = proto_tree_add_text(cdp_tree, tvb,
1072 offset, length, "Radio 1 operating mode: %s",
1073 tvb_format_text(tvb, offset + 4, length - 4));
1074 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
1075 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
1076 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
1077 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII|ENC_NA);
1082 case TYPE_HP_RADIO2_OMODE:
1083 /* Radio2 Operating mode */
1085 tlvi = proto_tree_add_text(cdp_tree, tvb,
1086 offset, length, "Radio 2 operating mode: %s",
1087 tvb_format_text(tvb, offset + 4, length - 4));
1088 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
1089 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
1090 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
1091 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII|ENC_NA);
1096 case TYPE_HP_RADIO1_RMODE:
1097 /* Radio1 Radio mode */
1099 tlvi = proto_tree_add_text(cdp_tree, tvb,
1100 offset, length, "Radio 1 radio mode: %s",
1101 tvb_format_text(tvb, offset + 4, length - 4));
1102 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
1103 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
1104 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
1105 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII|ENC_NA);
1110 case TYPE_HP_RADIO2_RMODE:
1111 /* Radio2 Radio mode */
1113 tlvi = proto_tree_add_text(cdp_tree, tvb,
1114 offset, length, "Radio 2 radio mode: %s",
1115 tvb_format_text(tvb, offset + 4, length - 4));
1116 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
1117 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
1118 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
1119 proto_tree_add_item(tlv_tree, hf_cdp_platform, tvb, offset + 4, length - 4, ENC_ASCII|ENC_NA);
1126 tlvi = proto_tree_add_text(cdp_tree, tvb, offset,
1127 length, "Type: %s, length: %u",
1128 val_to_str(type, type_vals, "Unknown (0x%04x)"),
1130 tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
1131 proto_tree_add_item(tlv_tree, hf_cdp_tlvtype, tvb, offset + TLV_TYPE, 2, ENC_BIG_ENDIAN);
1132 proto_tree_add_item(tlv_tree, hf_cdp_tlvlength, tvb, offset + TLV_LENGTH, 2, ENC_BIG_ENDIAN);
1134 proto_tree_add_text(tlv_tree, tvb, offset + 4,
1135 length - 4, "Data");
1143 call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, cdp_tree);
1146 #define PROTO_TYPE_NLPID 1
1147 #define PROTO_TYPE_IEEE_802_2 2
1149 static const value_string proto_type_vals[] = {
1150 { PROTO_TYPE_NLPID, "NLPID" },
1151 { PROTO_TYPE_IEEE_802_2, "802.2" },
1156 dissect_address_tlv(tvbuff_t *tvb, int offset, int length, proto_tree *tree)
1159 proto_tree *address_tree;
1160 guint8 protocol_type;
1161 guint8 protocol_length;
1163 const char *protocol_str;
1164 guint16 address_length;
1165 const char *address_type_str;
1166 const char *address_str;
1170 ti = proto_tree_add_text(tree, tvb, offset, length, "Truncated address");
1171 address_tree = proto_item_add_subtree(ti, ett_cdp_address);
1172 protocol_type = tvb_get_guint8(tvb, offset);
1173 proto_tree_add_text(address_tree, tvb, offset, 1, "Protocol type: %s",
1174 val_to_str(protocol_type, proto_type_vals, "Unknown (0x%02x)"));
1180 protocol_length = tvb_get_guint8(tvb, offset);
1181 proto_tree_add_text(address_tree, tvb, offset, 1, "Protocol length: %u",
1186 if (length < protocol_length) {
1188 proto_tree_add_text(address_tree, tvb, offset, length,
1189 "Protocol: %s (truncated)",
1190 tvb_bytes_to_ep_str(tvb, offset, length));
1194 protocol_str = NULL;
1195 if ((protocol_type == PROTO_TYPE_NLPID) && (protocol_length == 1)) {
1196 nlpid = tvb_get_guint8(tvb, offset);
1197 protocol_str = val_to_str(nlpid, nlpid_vals, "Unknown (0x%02x)");
1200 if (protocol_str == NULL)
1201 protocol_str = tvb_bytes_to_ep_str(tvb, offset, protocol_length);
1202 proto_tree_add_text(address_tree, tvb, offset, protocol_length,
1203 "Protocol: %s", protocol_str);
1204 offset += protocol_length;
1205 length -= protocol_length;
1209 address_length = tvb_get_ntohs(tvb, offset);
1210 proto_tree_add_text(address_tree, tvb, offset, 2, "Address length: %u",
1215 if (length < address_length) {
1217 proto_tree_add_text(address_tree, tvb, offset, length,
1218 "Address: %s (truncated)",
1219 tvb_bytes_to_ep_str(tvb, offset, length));
1223 /* XXX - the Cisco document seems to be saying that, for 802.2-format
1224 protocol types, 0xAAAA03 0x000000 0x0800 is IPv6, but 0x0800 is
1225 the Ethernet protocol type for IPv4. */
1226 address_type_str = NULL;
1228 if ((protocol_type == PROTO_TYPE_NLPID) && (protocol_length == 1)) {
1231 /* XXX - dissect NLPID_ISO8473_CLNP as OSI CLNP address? */
1234 if (address_length == 4) {
1235 /* The address is an IP address. */
1236 address_type_str = "IP address";
1237 address_str = tvb_ip_to_str(tvb, offset);
1242 if (address_type_str == NULL)
1243 address_type_str = "Address";
1244 if (address_str == NULL) {
1245 address_str = tvb_bytes_to_ep_str(tvb, offset, address_length);
1247 proto_item_set_text(ti, "%s: %s", address_type_str, address_str);
1248 proto_tree_add_text(address_tree, tvb, offset, address_length, "%s: %s",
1249 address_type_str, address_str);
1250 return 2 + protocol_length + 2 + address_length;
1254 dissect_capabilities(tvbuff_t *tvb, int offset, int length, proto_tree *tree)
1257 proto_tree *capabilities_tree;
1261 ti = proto_tree_add_item(tree, hf_cdp_capabilities, tvb, offset, 4, ENC_BIG_ENDIAN);
1262 capabilities_tree = proto_item_add_subtree(ti, ett_cdp_capabilities);
1263 proto_tree_add_item(capabilities_tree, hf_cdp_capabilities_router, tvb, offset, 4, ENC_BIG_ENDIAN);
1264 proto_tree_add_item(capabilities_tree, hf_cdp_capabilities_trans_bridge, tvb, offset, 4, ENC_BIG_ENDIAN);
1265 proto_tree_add_item(capabilities_tree, hf_cdp_capabilities_src_bridge, tvb, offset, 4, ENC_BIG_ENDIAN);
1266 proto_tree_add_item(capabilities_tree, hf_cdp_capabilities_switch, tvb, offset, 4, ENC_BIG_ENDIAN);
1267 proto_tree_add_item(capabilities_tree, hf_cdp_capabilities_host, tvb, offset, 4, ENC_BIG_ENDIAN);
1268 proto_tree_add_item(capabilities_tree, hf_cdp_capabilities_igmp_capable, tvb, offset, 4, ENC_BIG_ENDIAN);
1269 proto_tree_add_item(capabilities_tree, hf_cdp_capabilities_repeater, tvb, offset, 4, ENC_BIG_ENDIAN);
1273 dissect_nrgyz_tlv(tvbuff_t *tvb, int offset, guint16 length, guint16 num,
1276 guint32 tlvt, tlvl, ip_addr;
1277 proto_item *it = NULL;
1278 proto_tree *etree = NULL;
1279 char const *ttext = NULL;
1281 while (num-- && (length >= 8)) {
1282 tlvt = tvb_get_ntohl(tvb, offset);
1283 tlvl = tvb_get_ntohl(tvb, offset + 4);
1290 proto_tree_add_text(tree, tvb, offset, 8,
1291 "TLV with invalid length %u (< 8)",
1297 ttext = val_to_str(tlvt, type_nrgyz_vals, "Unknown (0x%04x)");
1299 case TYPE_NRGYZ_ROLE:
1300 case TYPE_NRGYZ_DOMAIN:
1301 case TYPE_NRGYZ_NAME:
1302 it = proto_tree_add_text(tree, tvb, offset,
1303 tlvl, "EnergyWise %s: %s", ttext,
1304 tvb_format_stringzpad(tvb, offset + 8, tlvl - 8)
1307 case TYPE_NRGYZ_REPLYTO:
1308 ip_addr = tvb_get_ipv4(tvb, offset + 12);
1309 it = proto_tree_add_text(tree, tvb, offset,
1310 tlvl, "EnergyWise %s: %s port %u",
1312 ip_to_str((guint8 *)&ip_addr),
1313 tvb_get_ntohs(tvb, offset + 10)
1317 it = proto_tree_add_text(tree, tvb, offset,
1318 tlvl, "EnergyWise %s TLV", ttext);
1320 etree = proto_item_add_subtree(it, ett_cdp_nrgyz_tlv);
1321 proto_tree_add_text(etree, tvb, offset, 4,
1322 "TLV Type: %x (%s)", tlvt, ttext);
1323 proto_tree_add_text(etree, tvb, offset + 4, 4,
1324 "TLV Length: %u", tlvl);
1326 case TYPE_NRGYZ_ROLE:
1327 case TYPE_NRGYZ_DOMAIN:
1328 case TYPE_NRGYZ_NAME:
1329 proto_tree_add_text(etree, tvb, offset + 8,
1330 tlvl - 8, "%s %s", ttext,
1331 tvb_format_stringzpad(tvb, offset + 8, tlvl - 8)
1334 case TYPE_NRGYZ_REPLYTO:
1335 ip_addr = tvb_get_ipv4(tvb, offset + 12);
1336 proto_tree_add_text(etree, tvb, offset + 8, 2,
1338 proto_tree_add_text(etree, tvb, offset + 10, 2,
1340 tvb_get_ntohs(tvb, offset + 10)
1342 proto_tree_add_text(etree, tvb, offset + 12, 4,
1344 ip_to_str((guint8 *)&ip_addr)
1346 proto_tree_add_text(etree, tvb, offset + 16, 2,
1347 "Unknown Field (Backup server Port?)");
1348 proto_tree_add_text(etree, tvb, offset + 18, 4,
1349 "Unknown Field (Backup Server IP?)");
1353 proto_tree_add_text(etree, tvb, offset + 8,
1361 proto_tree_add_text(tree, tvb, offset, length,
1362 "Invalid garbage at end");
1367 dissect_spare_poe_tlv(tvbuff_t *tvb, int offset, int length,
1371 proto_tree *tlv_tree;
1377 ti = proto_tree_add_item(tree, hf_cdp_spare_poe_tlv, tvb, offset, 1, ENC_BIG_ENDIAN);
1378 tlv_tree = proto_item_add_subtree(ti, ett_cdp_spare_poe_tlv);
1379 proto_tree_add_item(tlv_tree, hf_cdp_spare_poe_tlv_poe, tvb, offset, 1, ENC_BIG_ENDIAN);
1380 proto_tree_add_item(tlv_tree, hf_cdp_spare_poe_tlv_spare_pair_arch, tvb, offset, 1, ENC_BIG_ENDIAN);
1381 proto_tree_add_item(tlv_tree, hf_cdp_spare_poe_tlv_req_spare_pair_poe, tvb, offset, 1, ENC_BIG_ENDIAN);
1382 proto_tree_add_item(tlv_tree, hf_cdp_spare_poe_tlv_pse_spare_pair_poe, tvb, offset, 1, ENC_BIG_ENDIAN);
1386 add_multi_line_string_to_tree(proto_tree *tree, tvbuff_t *tvb, gint start,
1387 gint len, const gchar *prefix)
1396 prefix_len = (int)strlen(prefix);
1397 if (prefix_len > 64)
1399 for (i = 0; i < prefix_len; i++)
1403 line_len = tvb_find_line_end(tvb, start, len, &next, FALSE);
1404 data_len = next - start;
1405 proto_tree_add_text(tree, tvb, start, data_len, "%s%s", prefix,
1406 tvb_format_stringzpad(tvb, start, line_len));
1414 proto_register_cdp(void)
1416 static hf_register_info hf[] = {
1418 { "Version", "cdp.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1422 { "TTL", "cdp.ttl", FT_UINT16, BASE_DEC, NULL, 0x0,
1426 { "Checksum", "cdp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1429 { &hf_cdp_checksum_good,
1430 { "Good", "cdp.checksum_good", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1431 "True: checksum matches packet content; False: doesn't match content or not checked", HFILL }},
1433 { &hf_cdp_checksum_bad,
1434 { "Bad", "cdp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1435 "True: checksum doesn't match packet content; False: matches content or not checked", HFILL }},
1438 { "Type", "cdp.tlv.type", FT_UINT16, BASE_HEX, VALS(type_vals), 0x0,
1441 { &hf_cdp_tlvlength,
1442 { "Length", "cdp.tlv.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1446 {"Device ID", "cdp.deviceid", FT_STRING, BASE_NONE,
1447 NULL, 0, NULL, HFILL }},
1450 {"Platform", "cdp.platform", FT_STRING, BASE_NONE,
1451 NULL, 0, NULL, HFILL }},
1454 {"Sent through Interface", "cdp.portid", FT_STRING, BASE_NONE,
1455 NULL, 0, NULL, HFILL }},
1457 { &hf_cdp_capabilities,
1458 {"Capabilities", "cdp.capabilities", FT_UINT32, BASE_HEX,
1459 NULL, 0, NULL, HFILL }},
1461 { &hf_cdp_capabilities_router,
1462 {"Router", "cdp.capabilities.router", FT_BOOLEAN, 32,
1463 TFS(&tfs_yes_no), 0x01, NULL, HFILL }},
1465 { &hf_cdp_capabilities_trans_bridge,
1466 {"Transparent Bridge", "cdp.capabilities.trans_bridge", FT_BOOLEAN, 32,
1467 TFS(&tfs_yes_no), 0x02, NULL, HFILL }},
1469 { &hf_cdp_capabilities_src_bridge,
1470 {"Source Route Bridge", "cdp.capabilities.src_bridge", FT_BOOLEAN, 32,
1471 TFS(&tfs_yes_no), 0x04, NULL, HFILL }},
1473 { &hf_cdp_capabilities_switch,
1474 {"Switch", "cdp.capabilities.switch", FT_BOOLEAN, 32,
1475 TFS(&tfs_yes_no), 0x08, NULL, HFILL }},
1477 { &hf_cdp_capabilities_host,
1478 {"Host", "cdp.capabilities.host", FT_BOOLEAN, 32,
1479 TFS(&tfs_yes_no), 0x10, NULL, HFILL }},
1481 { &hf_cdp_capabilities_igmp_capable,
1482 {"IGMP capable", "cdp.capabilities.igmp_capable", FT_BOOLEAN, 32,
1483 TFS(&tfs_yes_no), 0x20, NULL, HFILL }},
1485 { &hf_cdp_capabilities_repeater,
1486 {"Repeater", "cdp.capabilities.repeater", FT_BOOLEAN, 32,
1487 TFS(&tfs_yes_no), 0x40, NULL, HFILL }},
1489 { &hf_cdp_spare_poe_tlv,
1490 { "Spare Pair PoE", "cdp.spare_poe_tlv", FT_UINT8, BASE_HEX,
1491 NULL, 0x0, NULL, HFILL }
1494 { &hf_cdp_spare_poe_tlv_poe,
1495 { "PSE Four-Wire PoE", "cdp.spare_poe_tlv.poe", FT_BOOLEAN, 8,
1496 TFS(&tfs_supported_not_supported), 0x01, NULL, HFILL }
1499 { &hf_cdp_spare_poe_tlv_spare_pair_arch,
1500 { "PD Spare Pair Architecture", "cdp.spare_poe_tlv.spare_pair_arch", FT_BOOLEAN, 8,
1501 TFS(&tfs_shared_independent), 0x02, NULL, HFILL }
1504 { &hf_cdp_spare_poe_tlv_req_spare_pair_poe,
1505 { "PD Request Spare Pair PoE", "cdp.spare_poe_tlv.req_spare_pair_poe", FT_BOOLEAN, 8,
1506 TFS(&tfs_on_off), 0x04, NULL, HFILL }
1509 { &hf_cdp_spare_poe_tlv_pse_spare_pair_poe,
1510 { "PSE Spare Pair PoE", "cdp.spare_poe_tlv.pse_spare_pair_poe", FT_BOOLEAN, 8,
1511 TFS(&tfs_on_off), 0x08, NULL, HFILL }
1515 static gint *ett[] = {
1520 &ett_cdp_capabilities,
1522 &ett_cdp_spare_poe_tlv
1525 proto_cdp = proto_register_protocol("Cisco Discovery Protocol",
1527 proto_register_field_array(proto_cdp, hf, array_length(hf));
1528 proto_register_subtree_array(ett, array_length(ett));
1532 proto_reg_handoff_cdp(void)
1534 dissector_handle_t cdp_handle;
1536 data_handle = find_dissector("data");
1537 cdp_handle = create_dissector_handle(dissect_cdp, proto_cdp);
1538 dissector_add_uint("llc.cisco_pid", 0x2000, cdp_handle);
1539 dissector_add_uint("chdlc.protocol", 0x2000, cdp_handle);
1540 dissector_add_uint("ppp.protocol", 0x0207, cdp_handle);