2 * Routines for the disassembly of the "Cisco Discovery Protocol"
3 * (c) Copyright Hannes R. Boehm <hannes@boehm.org>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
31 #include <epan/packet.h>
32 #include <epan/to_str.h>
33 #include <epan/in_cksum.h>
34 #include <epan/wmem/wmem.h>
37 #include <epan/nlpid.h>
43 * http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm#xtocid12
45 * for some information on CDP.
49 * http://www.cisco.com/en/US/products/hw/switches/ps663/products_tech_note09186a0080094713.shtml#cdp
51 * for some more information on CDP version 2.
54 void proto_register_cdp(void);
55 void proto_reg_handoff_cdp(void);
57 /* Offsets in TLV structure. */
61 static int proto_cdp
= -1;
62 static int hf_cdp_version
= -1;
63 static int hf_cdp_checksum
= -1;
64 static int hf_cdp_checksum_good
= -1;
65 static int hf_cdp_checksum_bad
= -1;
66 static int hf_cdp_ttl
= -1;
67 static int hf_cdp_tlvtype
= -1;
68 static int hf_cdp_tlvlength
= -1;
69 static int hf_cdp_deviceid
= -1;
70 static int hf_cdp_platform
= -1;
71 static int hf_cdp_portid
= -1;
72 static int hf_cdp_capabilities
= -1;
73 static int hf_cdp_capabilities_router
= -1;
74 static int hf_cdp_capabilities_trans_bridge
= -1;
75 static int hf_cdp_capabilities_src_bridge
= -1;
76 static int hf_cdp_capabilities_switch
= -1;
77 static int hf_cdp_capabilities_host
= -1;
78 static int hf_cdp_capabilities_igmp_capable
= -1;
79 static int hf_cdp_capabilities_repeater
= -1;
80 static int hf_cdp_spare_poe_tlv
= -1;
81 static int hf_cdp_spare_poe_tlv_poe
= -1;
82 static int hf_cdp_spare_poe_tlv_spare_pair_arch
= -1;
83 static int hf_cdp_spare_poe_tlv_req_spare_pair_poe
= -1;
84 static int hf_cdp_spare_poe_tlv_pse_spare_pair_poe
= -1;
86 static gint ett_cdp
= -1;
87 static gint ett_cdp_tlv
= -1;
88 static gint ett_cdp_nrgyz_tlv
= -1;
89 static gint ett_cdp_address
= -1;
90 static gint ett_cdp_capabilities
= -1;
91 static gint ett_cdp_spare_poe_tlv
= -1;
92 static gint ett_cdp_checksum
= -1;
94 static dissector_handle_t data_handle
;
97 dissect_address_tlv(tvbuff_t
*tvb
, int offset
, int length
, proto_tree
*tree
);
99 dissect_capabilities(tvbuff_t
*tvb
, int offset
, int length
, proto_tree
*tree
);
101 dissect_nrgyz_tlv(tvbuff_t
*tvb
, int offset
, guint16 length
, guint16 num
,
104 dissect_spare_poe_tlv(tvbuff_t
*tvb
, int offset
, int length
, proto_tree
*tree
);
106 add_multi_line_string_to_tree(proto_tree
*tree
, tvbuff_t
*tvb
, gint start
,
107 gint len
, const gchar
*prefix
);
109 #define TYPE_DEVICE_ID 0x0001
110 #define TYPE_ADDRESS 0x0002
111 #define TYPE_PORT_ID 0x0003
112 #define TYPE_CAPABILITIES 0x0004
113 #define TYPE_IOS_VERSION 0x0005
114 #define TYPE_PLATFORM 0x0006
115 #define TYPE_IP_PREFIX 0x0007
116 #define TYPE_PROTOCOL_HELLO 0x0008 /* Protocol Hello */
117 #define TYPE_VTP_MGMT_DOMAIN 0x0009 /* VTP Domain, CTPv2 - see second URL */
118 #define TYPE_NATIVE_VLAN 0x000a /* Native VLAN, CTPv2 - see second URL */
119 #define TYPE_DUPLEX 0x000b /* Full/Half Duplex - see second URL */
122 #define TYPE_VOIP_VLAN_REPLY 0x000e /* VoIP VLAN reply */
123 #define TYPE_VOIP_VLAN_QUERY 0x000f /* VoIP VLAN query */
124 #define TYPE_POWER 0x0010 /* Power consumption */
125 #define TYPE_MTU 0x0011 /* MTU */
126 #define TYPE_TRUST_BITMAP 0x0012 /* Trust bitmap */
127 #define TYPE_UNTRUSTED_COS 0x0013 /* Untrusted port CoS */
128 #define TYPE_SYSTEM_NAME 0x0014 /* System Name */
129 #define TYPE_SYSTEM_OID 0x0015 /* System OID */
130 #define TYPE_MANAGEMENT_ADDR 0x0016 /* Management Address(es) */
131 #define TYPE_LOCATION 0x0017 /* Location */
132 #define TYPE_EXT_PORT_ID 0x0018 /* External Port-ID */
133 #define TYPE_POWER_REQUESTED 0x0019 /* Power Requested */
134 #define TYPE_POWER_AVAILABLE 0x001a /* Power Available */
135 #define TYPE_PORT_UNIDIR 0x001b /* Port Unidirectional */
136 #define TYPE_NRGYZ 0x001d /* EnergyWise over CDP */
137 #define TYPE_SPARE_POE 0x001f /* Spare Pair PoE */
139 static const value_string type_vals
[] = {
140 { TYPE_DEVICE_ID
, "Device ID" },
141 { TYPE_ADDRESS
, "Addresses" },
142 { TYPE_PORT_ID
, "Port ID" },
143 { TYPE_CAPABILITIES
, "Capabilities" },
144 { TYPE_IOS_VERSION
, "Software version" },
145 { TYPE_PLATFORM
, "Platform" },
146 { TYPE_IP_PREFIX
, "IP Prefix/Gateway (used for ODR)" },
147 { TYPE_PROTOCOL_HELLO
, "Protocol Hello" },
148 { TYPE_VTP_MGMT_DOMAIN
, "VTP Management Domain" },
149 { TYPE_NATIVE_VLAN
, "Native VLAN" },
150 { TYPE_DUPLEX
, "Duplex" },
151 { TYPE_VOIP_VLAN_REPLY
, "VoIP VLAN Reply" },
152 { TYPE_VOIP_VLAN_QUERY
, "VoIP VLAN Query" },
153 { TYPE_POWER
, "Power consumption" },
155 { TYPE_TRUST_BITMAP
, "Trust Bitmap" },
156 { TYPE_UNTRUSTED_COS
, "Untrusted Port CoS" },
157 { TYPE_SYSTEM_NAME
, "System Name" },
158 { TYPE_SYSTEM_OID
, "System Object ID" },
159 { TYPE_MANAGEMENT_ADDR
, "Management Address" },
160 { TYPE_LOCATION
, "Location" },
161 { TYPE_EXT_PORT_ID
, "External Port-ID" },
162 { TYPE_POWER_REQUESTED
, "Power Requested" },
163 { TYPE_POWER_AVAILABLE
, "Power Available" },
164 { TYPE_PORT_UNIDIR
, "Port Unidirectional" },
165 { TYPE_NRGYZ
, "EnergyWise" },
166 { TYPE_SPARE_POE
, "Spare PoE" },
170 #define TYPE_HELLO_CLUSTER_MGMT 0x0112
172 static const value_string type_hello_vals
[] = {
173 { TYPE_HELLO_CLUSTER_MGMT
, "Cluster Management" },
177 #define TYPE_NRGYZ_ROLE 0x00000007
178 #define TYPE_NRGYZ_DOMAIN 0x00000008
179 #define TYPE_NRGYZ_NAME 0x00000009
180 #define TYPE_NRGYZ_REPLYTO 0x00000017
182 static const value_string type_nrgyz_vals
[] = {
183 { TYPE_NRGYZ_ROLE
, "Role" },
184 { TYPE_NRGYZ_DOMAIN
, "Domain" },
185 { TYPE_NRGYZ_NAME
, "Name" },
186 { TYPE_NRGYZ_REPLYTO
, "Reply To" },
191 dissect_cdp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
193 proto_item
*ti
, *checksum_item
;
194 proto_tree
*cdp_tree
= NULL
, *checksum_tree
;
197 guint16 length
, packet_checksum
, computed_checksum
, data_length
;
198 gboolean checksum_good
, checksum_bad
;
199 proto_item
*tlvi
= NULL
;
200 proto_tree
*tlv_tree
= NULL
;
203 guint32 power_avail_len
, power_avail
;
204 guint32 power_req_len
, power_req
;
209 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "CDP");
210 col_clear(pinfo
->cinfo
, COL_INFO
);
213 ti
= proto_tree_add_item(tree
, proto_cdp
, tvb
, offset
, -1, ENC_NA
);
214 cdp_tree
= proto_item_add_subtree(ti
, ett_cdp
);
217 proto_tree_add_item(cdp_tree
, hf_cdp_version
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
220 proto_tree_add_uint_format_value(cdp_tree
, hf_cdp_ttl
, tvb
, offset
, 1,
221 tvb_get_guint8(tvb
, offset
),
223 tvb_get_guint8(tvb
, offset
));
226 offset
+= 2; /* The version/ttl fields from above */
229 /* Checksum display & verification code */
230 packet_checksum
= tvb_get_ntohs(tvb
, offset
);
232 data_length
= tvb_reported_length(tvb
);
234 /* CDP doesn't adhere to RFC 1071 section 2. (B). It incorrectly assumes
235 * checksums are calculated on a big endian platform, therefore i.s.o.
236 * padding odd sized data with a zero byte _at the end_ it sets the last
237 * big endian _word_ to contain the last network _octet_. This byteswap
238 * has to be done on the last octet of network data before feeding it to
239 * the Internet checksum routine.
240 * CDP checksumming code has a bug in the addition of this last _word_
241 * as a signed number into the long word intermediate checksum. When
242 * reducing this long to word size checksum an off-by-one error can be
243 * made. This off-by-one error is compensated for in the last _word_ of
246 if (data_length
& 1) {
247 guint8
*padded_buffer
;
248 /* Allocate new buffer */
249 padded_buffer
= (guint8
*)wmem_alloc(wmem_packet_scope(), data_length
+1);
250 tvb_memcpy(tvb
, padded_buffer
, 0, data_length
);
251 /* Swap bytes in last word */
252 padded_buffer
[data_length
] = padded_buffer
[data_length
-1];
253 padded_buffer
[data_length
-1] = 0;
254 /* Compensate off-by-one error */
255 if (padded_buffer
[data_length
] & 0x80) {
256 padded_buffer
[data_length
]--;
257 padded_buffer
[data_length
-1]--;
259 /* Setup checksum routine data buffer */
260 cksum_vec
[0].ptr
= padded_buffer
;
261 cksum_vec
[0].len
= data_length
+1;
263 /* Setup checksum routine data buffer */
264 cksum_vec
[0].ptr
= tvb_get_ptr(tvb
, 0, data_length
);
265 cksum_vec
[0].len
= data_length
;
268 computed_checksum
= in_cksum(cksum_vec
, 1);
269 checksum_good
= (computed_checksum
== 0);
270 checksum_bad
= !checksum_good
;
272 checksum_item
= proto_tree_add_uint_format_value(cdp_tree
,
273 hf_cdp_checksum
, tvb
, offset
, 2, packet_checksum
,
274 "0x%04x [correct]", packet_checksum
);
276 checksum_item
= proto_tree_add_uint_format_value(cdp_tree
,
277 hf_cdp_checksum
, tvb
, offset
, 2, packet_checksum
,
278 "0x%04x [incorrect, should be 0x%04x]",
280 in_cksum_shouldbe(packet_checksum
, computed_checksum
));
283 checksum_tree
= proto_item_add_subtree(checksum_item
, ett_cdp_checksum
);
284 checksum_item
= proto_tree_add_boolean(checksum_tree
, hf_cdp_checksum_good
,
285 tvb
, offset
, 2, checksum_good
);
286 PROTO_ITEM_SET_GENERATED(checksum_item
);
287 checksum_item
= proto_tree_add_boolean(checksum_tree
, hf_cdp_checksum_bad
,
288 tvb
, offset
, 2, checksum_bad
);
289 PROTO_ITEM_SET_GENERATED(checksum_item
);
293 while (tvb_reported_length_remaining(tvb
, offset
) != 0) {
294 type
= tvb_get_ntohs(tvb
, offset
+ TLV_TYPE
);
295 length
= tvb_get_ntohs(tvb
, offset
+ TLV_LENGTH
);
298 tlvi
= proto_tree_add_text(cdp_tree
, tvb
, offset
, 4,
299 "TLV with invalid length %u (< 4)",
301 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
302 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
303 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
314 col_append_fstr(pinfo
->cinfo
, COL_INFO
,
316 tvb_format_stringzpad(tvb
, offset
+ 4, length
- 4));
319 tlvi
= proto_tree_add_text(cdp_tree
, tvb
, offset
,
320 length
, "Device ID: %s",
321 tvb_format_stringzpad(tvb
, offset
+ 4, length
- 4));
322 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
323 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
324 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
325 proto_tree_add_item(tlv_tree
, hf_cdp_deviceid
, tvb
, offset
+ 4, length
- 4, ENC_ASCII
|ENC_NA
);
331 real_length
= length
;
332 if (tvb_get_guint8(tvb
, offset
+ real_length
) != 0x00) {
333 /* The length in the TLV doesn't appear to be the
334 length of the TLV, as the byte just past it
335 isn't the first byte of a 2-byte big-endian
336 small integer; make the length of the TLV the length
337 in the TLV, plus 4 bytes for the TLV type and length,
338 minus 1 because that's what makes one capture work. */
339 real_length
= length
+ 3;
342 col_append_fstr(pinfo
->cinfo
, COL_INFO
,
344 tvb_format_stringzpad(tvb
, offset
+ 4,
348 tlvi
= proto_tree_add_text(cdp_tree
, tvb
, offset
,
349 real_length
, "Port ID: %s",
350 tvb_format_text(tvb
, offset
+ 4, real_length
- 4));
351 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
352 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
353 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
354 proto_tree_add_item(tlv_tree
, hf_cdp_portid
, tvb
, offset
+ 4, real_length
- 4, ENC_ASCII
|ENC_NA
);
356 offset
+= real_length
;
362 tlvi
= proto_tree_add_text(cdp_tree
, tvb
, offset
,
363 length
, "Addresses");
364 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
365 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
366 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
370 naddresses
= tvb_get_ntohl(tvb
, offset
);
372 proto_tree_add_text(tlv_tree
, tvb
, offset
, 4,
373 "Number of addresses: %u", naddresses
);
377 while (naddresses
!= 0) {
378 addr_length
= dissect_address_tlv(tvb
, offset
, length
,
382 offset
+= addr_length
;
383 length
-= addr_length
;
390 case TYPE_CAPABILITIES
:
392 tlvi
= proto_tree_add_text(cdp_tree
, tvb
, offset
,
393 length
, "Capabilities");
394 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
395 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
396 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
400 dissect_capabilities(tvb
, offset
, length
, tlv_tree
);
404 case TYPE_IOS_VERSION
:
406 tlvi
= proto_tree_add_text(cdp_tree
, tvb
, offset
,
407 length
, "Software Version");
408 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
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 add_multi_line_string_to_tree(tlv_tree
, tvb
, offset
+ 4,
412 length
- 4, "Software Version: ");
420 tlvi
= proto_tree_add_text(cdp_tree
, tvb
,
421 offset
, length
, "Platform: %s",
422 tvb_format_text(tvb
, offset
+ 4, length
- 4));
423 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
424 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
425 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
426 proto_tree_add_item(tlv_tree
, hf_cdp_platform
, tvb
, offset
+ 4, length
- 4, ENC_ASCII
|ENC_NA
);
433 /* if length is 8 then this is default gw not prefix */
435 tlvi
= proto_tree_add_text(cdp_tree
, tvb
, offset
,
436 length
, "ODR Default gateway: %s",
437 tvb_ip_to_str(tvb
, offset
+4));
438 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
439 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
440 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
441 proto_tree_add_text(tlv_tree
, tvb
, offset
+4, 4,
442 "ODR Default gateway = %s",
443 tvb_ip_to_str(tvb
, offset
+4));
448 tlvi
= proto_tree_add_text(cdp_tree
, tvb
, offset
,
449 length
, "IP Prefixes: %d",length
/5);
451 /* the actual number of prefixes is (length-4)/5
452 but if the variable is not a "float" but "integer"
453 then length/5=(length-4)/5 :) */
455 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
456 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
457 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
463 proto_tree_add_text(tlv_tree
, tvb
, offset
, 5,
465 tvb_ip_to_str(tvb
, offset
),
466 tvb_get_guint8(tvb
,offset
+4));
474 case TYPE_PROTOCOL_HELLO
:
476 tlvi
= proto_tree_add_text(cdp_tree
, tvb
,
477 offset
,length
, "Protocol Hello: %s",
478 val_to_str(tvb_get_ntohs(tvb
, offset
+7), type_hello_vals
, "Unknown (0x%04x)"));
479 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
480 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
481 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
482 proto_tree_add_text(tlv_tree
, tvb
, offset
+4, 3,
484 tvb_get_ntoh24(tvb
,offset
+4),
485 val_to_str_const(tvb_get_ntoh24(tvb
,offset
+4), oui_vals
, "Unknown"));
486 proto_tree_add_text(tlv_tree
, tvb
, offset
+7, 2,
487 "Protocol ID: 0x%04X (%s)",
488 tvb_get_ntohs(tvb
, offset
+7),
489 val_to_str_const(tvb_get_ntohs(tvb
, offset
+7), type_hello_vals
, "Unknown"));
491 switch(tvb_get_ntohs(tvb
, offset
+7)) {
493 case TYPE_HELLO_CLUSTER_MGMT
:
494 /* proto_tree_add_text(tlv_tree, tvb, offset+9,
495 length - 9, "Cluster Management");
497 ip_addr
= tvb_get_ipv4(tvb
, offset
+9);
498 proto_tree_add_text(tlv_tree
, tvb
, offset
+9, 4,
499 "Cluster Master IP: %s",ip_to_str((guint8
*)&ip_addr
));
500 ip_addr
= tvb_get_ipv4(tvb
, offset
+13);
501 proto_tree_add_text(tlv_tree
, tvb
, offset
+13, 4,
502 "UNKNOWN (IP?): 0x%08X (%s)",
503 ip_addr
, ip_to_str((guint8
*)&ip_addr
));
504 proto_tree_add_text(tlv_tree
, tvb
, offset
+17, 1,
506 tvb_get_guint8(tvb
, offset
+17));
507 proto_tree_add_text(tlv_tree
, tvb
, offset
+18, 1,
508 "Sub Version?: 0x%02X",
509 tvb_get_guint8(tvb
, offset
+18));
510 proto_tree_add_text(tlv_tree
, tvb
, offset
+19, 1,
512 tvb_get_guint8(tvb
, offset
+19));
513 proto_tree_add_text(tlv_tree
, tvb
, offset
+20, 1,
515 tvb_get_guint8(tvb
, offset
+20));
516 proto_tree_add_text(tlv_tree
, tvb
, offset
+21, 6,
517 "Cluster Commander MAC: %s",
518 tvb_ether_to_str(tvb
, offset
+21));
519 proto_tree_add_text(tlv_tree
, tvb
, offset
+27, 6,
521 tvb_ether_to_str(tvb
, offset
+27));
522 proto_tree_add_text(tlv_tree
, tvb
, offset
+33, 1,
524 tvb_get_guint8(tvb
, offset
+33));
525 proto_tree_add_text(tlv_tree
, tvb
, offset
+34, 2,
526 "Management VLAN: %d",
527 tvb_get_ntohs(tvb
, offset
+34));
530 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 9,
531 length
- 9, "Unknown");
538 case TYPE_VTP_MGMT_DOMAIN
:
540 tlvi
= proto_tree_add_text(cdp_tree
, tvb
,
541 offset
, length
, "VTP Management Domain: %s",
542 tvb_format_text(tvb
, offset
+ 4, length
- 4));
543 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
544 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
545 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
546 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 4,
547 length
- 4, "VTP Management Domain: %s",
548 tvb_format_text(tvb
, offset
+ 4, length
- 4));
553 case TYPE_NATIVE_VLAN
:
555 tlvi
= proto_tree_add_text(cdp_tree
, tvb
,
556 offset
, length
, "Native VLAN: %u",
557 tvb_get_ntohs(tvb
, offset
+ 4));
558 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
559 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
560 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
561 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 4,
562 length
- 4, "Native VLAN: %u",
563 tvb_get_ntohs(tvb
, offset
+ 4));
570 tlvi
= proto_tree_add_text(cdp_tree
, tvb
,
571 offset
, length
, "Duplex: %s",
572 tvb_get_guint8(tvb
, offset
+ 4) ?
574 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
575 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
576 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
577 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 4,
578 length
- 4, "Duplex: %s",
579 tvb_get_guint8(tvb
, offset
+ 4) ?
585 case TYPE_VOIP_VLAN_REPLY
:
588 tlvi
= proto_tree_add_text(cdp_tree
, tvb
, offset
, length
,
589 "VoIP VLAN Reply: %u", tvb_get_ntohs(tvb
, offset
+ 5));
592 * XXX - what are these? I've seen them in some captures;
593 * they have a length of 6, and run up to the end of
594 * the packet, so if we try to dissect it the same way
595 * we dissect the 7-byte ones, we report a malformed
598 tlvi
= proto_tree_add_text(cdp_tree
, tvb
,
599 offset
, length
, "VoIP VLAN Reply");
601 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
602 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
603 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
604 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 4,
607 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 5,
609 tvb_get_ntohs(tvb
, offset
+ 5));
615 case TYPE_VOIP_VLAN_QUERY
:
618 tlvi
= proto_tree_add_text(cdp_tree
, tvb
,
619 offset
, length
, "VoIP VLAN Query: %u", tvb_get_ntohs(tvb
, offset
+ 5));
622 * XXX - what are these? I've seen them in some captures;
623 * they have a length of 6, and run up to the end of
624 * the packet, so if we try to dissect it the same way
625 * we dissect the 7-byte ones, we report a malformed
628 tlvi
= proto_tree_add_text(cdp_tree
, tvb
,
629 offset
, length
, "VoIP VLAN Query");
631 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
632 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
633 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
634 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 4,
637 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 5,
639 tvb_get_ntohs(tvb
, offset
+ 5));
647 tlvi
= proto_tree_add_text(cdp_tree
, tvb
,
648 offset
, length
, "Power Consumption: %u mW",
649 tvb_get_ntohs(tvb
, offset
+ 4));
650 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
651 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
652 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
653 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 4,
654 length
- 4, "Power Consumption: %u mW",
655 tvb_get_ntohs(tvb
, offset
+ 4));
662 tlvi
= proto_tree_add_text(cdp_tree
, tvb
,
663 offset
, length
, "MTU: %u",
664 tvb_get_ntohl(tvb
,offset
+ 4));
665 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
666 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
667 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
668 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 4,
669 length
- 4, "MTU: %u",
670 tvb_get_ntohl(tvb
,offset
+ 4));
675 case TYPE_TRUST_BITMAP
:
677 tlvi
= proto_tree_add_text(cdp_tree
, tvb
,
678 offset
, length
, "Trust Bitmap: 0x%02X",
679 tvb_get_guint8(tvb
, offset
+ 4));
680 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
681 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
682 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
683 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 4,
684 length
- 4, "Trust Bitmap: %02x",
685 tvb_get_guint8(tvb
, offset
+ 4));
690 case TYPE_UNTRUSTED_COS
:
692 tlvi
= proto_tree_add_text(cdp_tree
, tvb
,
693 offset
, length
, "Untrusted port CoS: 0x%02X",
694 tvb_get_guint8(tvb
, offset
+ 4));
695 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
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_text(tlv_tree
, tvb
, offset
+ 4,
699 length
- 4, "Untrusted port CoS: %02x",
700 tvb_get_guint8(tvb
, offset
+ 4));
705 case TYPE_SYSTEM_NAME
:
707 tlvi
= proto_tree_add_text(cdp_tree
, tvb
,
708 offset
, length
, "System Name: %s",
709 tvb_format_text(tvb
, offset
+ 4, length
- 4));
710 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
711 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
712 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
713 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 4,
714 length
- 4, "System Name: %s",
715 tvb_format_text(tvb
, offset
+ 4, length
- 4));
720 case TYPE_SYSTEM_OID
:
722 tlvi
= proto_tree_add_text(cdp_tree
, tvb
,
723 offset
, length
, "System Object Identifier");
724 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
725 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
726 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
727 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 4,
728 length
- 4, "System Object Identifier: %s",
729 tvb_bytes_to_str(tvb
, offset
+ 4, length
- 4));
734 case TYPE_MANAGEMENT_ADDR
:
736 tlvi
= proto_tree_add_text(cdp_tree
, tvb
,
737 offset
, length
, "Management Addresses");
738 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
739 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
740 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
744 naddresses
= tvb_get_ntohl(tvb
, offset
);
746 proto_tree_add_text(tlv_tree
, tvb
, offset
, 4,
747 "Number of addresses: %u", naddresses
);
751 while (naddresses
!= 0) {
752 addr_length
= dissect_address_tlv(tvb
, offset
, length
,
756 offset
+= addr_length
;
757 length
-= addr_length
;
766 tlvi
= proto_tree_add_text(cdp_tree
, tvb
,
767 offset
, length
, "Location: %s",
768 tvb_format_text(tvb
, offset
+ 5, length
- 5));
769 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
770 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
771 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
772 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 4,
773 1 , "UNKNOWN: 0x%02X",
774 tvb_get_guint8(tvb
, offset
+ 4));
775 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 5,
776 length
- 5, "Location: %s",
777 tvb_format_text(tvb
, offset
+ 5, length
- 5));
782 case TYPE_POWER_REQUESTED
:
784 tlvi
= proto_tree_add_text(cdp_tree
, tvb
,
785 offset
, length
, "Power Request: ");
786 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
787 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
788 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
789 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 4,
791 tvb_get_ntohs(tvb
, offset
+ 4));
792 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 6,
793 2, "Management-ID: %u",
794 tvb_get_ntohs(tvb
, offset
+ 6));
796 power_req_len
= (tvb_get_ntohs(tvb
, offset
+ TLV_LENGTH
)) - 8;
797 /* Move offset to where the list of Power Request Values Exist */
799 while(power_req_len
) {
800 if (power_req_len
> 4) {
801 power_req
= tvb_get_ntohl(tvb
, offset
);
803 proto_tree_add_text(tlv_tree
, tvb
, offset
,
804 4, "Power Requested: %u mW", power_req
);
805 proto_item_append_text(tlvi
, "%u mW, ", power_req
);
810 if (power_req_len
== 4) {
811 power_req
= tvb_get_ntohl(tvb
, offset
);
813 proto_tree_add_text(tlv_tree
, tvb
, offset
,
814 4, "Power Requested: %u mW", power_req
);
815 proto_item_append_text(tlvi
, "%u mW", power_req
);
818 offset
+= power_req_len
;
824 case TYPE_POWER_AVAILABLE
:
826 tlvi
= proto_tree_add_text(cdp_tree
, tvb
,
827 offset
, length
, "Power Available: ");
828 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
829 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
830 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
831 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 4,
833 tvb_get_ntohs(tvb
, offset
+ 4));
834 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 6,
835 2, "Management-ID: %u",
836 tvb_get_ntohs(tvb
, offset
+ 6));
838 power_avail_len
= (tvb_get_ntohs(tvb
, offset
+ TLV_LENGTH
)) - 8;
839 /* Move offset to where the list of Power Available Values Exist */
841 while(power_avail_len
) {
842 if (power_avail_len
>= 4) {
843 power_avail
= tvb_get_ntohl(tvb
, offset
);
845 proto_tree_add_text(tlv_tree
, tvb
, offset
,
846 4, "Power Available: %u mW", power_avail
);
847 proto_item_append_text(tlvi
, "%u mW, ", power_avail
);
849 power_avail_len
-= 4;
852 offset
+= power_avail_len
;
860 tlvi
= proto_tree_add_text(cdp_tree
, tvb
,
861 offset
, length
, "EnergyWise");
862 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
863 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
864 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
865 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 4,
866 20, "Encrypted Data");
867 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 24,
868 4, "Unknown (Seen Sequence?): %u",
869 tvb_get_ntohl(tvb
, offset
+ 24));
870 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 28,
871 4, "Sequence Number: %u",
872 tvb_get_ntohl(tvb
, offset
+ 28));
873 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 32,
874 16, "Model Number: %s",
875 tvb_format_stringzpad(tvb
, offset
+ 32, 16));
876 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 48,
877 2, "Unknown Pad: %x",
878 tvb_get_ntohs(tvb
, offset
+ 48));
879 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 50,
880 3, "Hardware Version ID: %s",
881 tvb_format_stringzpad(tvb
, offset
+ 50, 3));
882 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 53,
883 11, "System Serial Number: %s",
884 tvb_format_stringzpad(tvb
, offset
+ 53, 11));
885 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 64,
886 8, "Unknown Values");
887 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 72,
888 2, "Length of TLV table: %u",
889 tvb_get_ntohs(tvb
, offset
+ 72));
890 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 74,
891 2, "Number of TLVs in table: %u",
892 tvb_get_ntohs(tvb
, offset
+ 74));
894 proto_tree_add_text(tlv_tree, tvb,
895 offset + 76, length - 76,
896 "EnergyWise TLV Table");
898 dissect_nrgyz_tlv(tvb
, offset
+ 76,
899 tvb_get_ntohs(tvb
, offset
+ 72),
900 tvb_get_ntohs(tvb
, offset
+ 74),
910 tlvi
= proto_tree_add_text(cdp_tree
, tvb
, offset
, length
,
912 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
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
);
919 dissect_spare_poe_tlv(tvb
, offset
, length
, tlv_tree
);
925 tlvi
= proto_tree_add_text(cdp_tree
, tvb
, offset
,
926 length
, "Type: %s, length: %u",
927 val_to_str(type
, type_vals
, "Unknown (0x%04x)"),
929 tlv_tree
= proto_item_add_subtree(tlvi
, ett_cdp_tlv
);
930 proto_tree_add_item(tlv_tree
, hf_cdp_tlvtype
, tvb
, offset
+ TLV_TYPE
, 2, ENC_BIG_ENDIAN
);
931 proto_tree_add_item(tlv_tree
, hf_cdp_tlvlength
, tvb
, offset
+ TLV_LENGTH
, 2, ENC_BIG_ENDIAN
);
933 proto_tree_add_text(tlv_tree
, tvb
, offset
+ 4,
942 call_dissector(data_handle
, tvb_new_subset_remaining(tvb
, offset
), pinfo
, cdp_tree
);
945 #define PROTO_TYPE_NLPID 1
946 #define PROTO_TYPE_IEEE_802_2 2
948 static const value_string proto_type_vals
[] = {
949 { PROTO_TYPE_NLPID
, "NLPID" },
950 { PROTO_TYPE_IEEE_802_2
, "802.2" },
955 dissect_address_tlv(tvbuff_t
*tvb
, int offset
, int length
, proto_tree
*tree
)
958 proto_tree
*address_tree
;
959 guint8 protocol_type
;
960 guint8 protocol_length
;
962 const char *protocol_str
;
963 guint16 address_length
;
964 const char *address_type_str
;
965 const char *address_str
;
969 ti
= proto_tree_add_text(tree
, tvb
, offset
, length
, "Truncated address");
970 address_tree
= proto_item_add_subtree(ti
, ett_cdp_address
);
971 protocol_type
= tvb_get_guint8(tvb
, offset
);
972 proto_tree_add_text(address_tree
, tvb
, offset
, 1, "Protocol type: %s",
973 val_to_str(protocol_type
, proto_type_vals
, "Unknown (0x%02x)"));
979 protocol_length
= tvb_get_guint8(tvb
, offset
);
980 proto_tree_add_text(address_tree
, tvb
, offset
, 1, "Protocol length: %u",
985 if (length
< protocol_length
) {
987 proto_tree_add_text(address_tree
, tvb
, offset
, length
,
988 "Protocol: %s (truncated)",
989 tvb_bytes_to_str(tvb
, offset
, length
));
994 if ((protocol_type
== PROTO_TYPE_NLPID
) && (protocol_length
== 1)) {
995 nlpid
= tvb_get_guint8(tvb
, offset
);
996 protocol_str
= val_to_str(nlpid
, nlpid_vals
, "Unknown (0x%02x)");
999 if (protocol_str
== NULL
)
1000 protocol_str
= tvb_bytes_to_str(tvb
, offset
, protocol_length
);
1001 proto_tree_add_text(address_tree
, tvb
, offset
, protocol_length
,
1002 "Protocol: %s", protocol_str
);
1003 offset
+= protocol_length
;
1004 length
-= protocol_length
;
1008 address_length
= tvb_get_ntohs(tvb
, offset
);
1009 proto_tree_add_text(address_tree
, tvb
, offset
, 2, "Address length: %u",
1014 if (length
< address_length
) {
1016 proto_tree_add_text(address_tree
, tvb
, offset
, length
,
1017 "Address: %s (truncated)",
1018 tvb_bytes_to_str(tvb
, offset
, length
));
1022 /* XXX - the Cisco document seems to be saying that, for 802.2-format
1023 protocol types, 0xAAAA03 0x000000 0x0800 is IPv6, but 0x0800 is
1024 the Ethernet protocol type for IPv4. */
1025 address_type_str
= NULL
;
1027 if ((protocol_type
== PROTO_TYPE_NLPID
) && (protocol_length
== 1)) {
1030 /* XXX - dissect NLPID_ISO8473_CLNP as OSI CLNP address? */
1033 if (address_length
== 4) {
1034 /* The address is an IP address. */
1035 address_type_str
= "IP address";
1036 address_str
= tvb_ip_to_str(tvb
, offset
);
1041 if (address_type_str
== NULL
)
1042 address_type_str
= "Address";
1043 if (address_str
== NULL
) {
1044 address_str
= tvb_bytes_to_str(tvb
, offset
, address_length
);
1046 proto_item_set_text(ti
, "%s: %s", address_type_str
, address_str
);
1047 proto_tree_add_text(address_tree
, tvb
, offset
, address_length
, "%s: %s",
1048 address_type_str
, address_str
);
1049 return 2 + protocol_length
+ 2 + address_length
;
1053 dissect_capabilities(tvbuff_t
*tvb
, int offset
, int length
, proto_tree
*tree
)
1056 proto_tree
*capabilities_tree
;
1060 ti
= proto_tree_add_item(tree
, hf_cdp_capabilities
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1061 capabilities_tree
= proto_item_add_subtree(ti
, ett_cdp_capabilities
);
1062 proto_tree_add_item(capabilities_tree
, hf_cdp_capabilities_router
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1063 proto_tree_add_item(capabilities_tree
, hf_cdp_capabilities_trans_bridge
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1064 proto_tree_add_item(capabilities_tree
, hf_cdp_capabilities_src_bridge
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1065 proto_tree_add_item(capabilities_tree
, hf_cdp_capabilities_switch
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1066 proto_tree_add_item(capabilities_tree
, hf_cdp_capabilities_host
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1067 proto_tree_add_item(capabilities_tree
, hf_cdp_capabilities_igmp_capable
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1068 proto_tree_add_item(capabilities_tree
, hf_cdp_capabilities_repeater
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1072 dissect_nrgyz_tlv(tvbuff_t
*tvb
, int offset
, guint16 length
, guint16 num
,
1075 guint32 tlvt
, tlvl
, ip_addr
;
1076 proto_item
*it
= NULL
;
1077 proto_tree
*etree
= NULL
;
1078 char const *ttext
= NULL
;
1080 while (num
-- && (length
>= 8)) {
1081 tlvt
= tvb_get_ntohl(tvb
, offset
);
1082 tlvl
= tvb_get_ntohl(tvb
, offset
+ 4);
1089 proto_tree_add_text(tree
, tvb
, offset
, 8,
1090 "TLV with invalid length %u (< 8)",
1096 ttext
= val_to_str(tlvt
, type_nrgyz_vals
, "Unknown (0x%04x)");
1098 case TYPE_NRGYZ_ROLE
:
1099 case TYPE_NRGYZ_DOMAIN
:
1100 case TYPE_NRGYZ_NAME
:
1101 it
= proto_tree_add_text(tree
, tvb
, offset
,
1102 tlvl
, "EnergyWise %s: %s", ttext
,
1103 tvb_format_stringzpad(tvb
, offset
+ 8, tlvl
- 8)
1106 case TYPE_NRGYZ_REPLYTO
:
1107 ip_addr
= tvb_get_ipv4(tvb
, offset
+ 12);
1108 it
= proto_tree_add_text(tree
, tvb
, offset
,
1109 tlvl
, "EnergyWise %s: %s port %u",
1111 ip_to_str((guint8
*)&ip_addr
),
1112 tvb_get_ntohs(tvb
, offset
+ 10)
1116 it
= proto_tree_add_text(tree
, tvb
, offset
,
1117 tlvl
, "EnergyWise %s TLV", ttext
);
1119 etree
= proto_item_add_subtree(it
, ett_cdp_nrgyz_tlv
);
1120 proto_tree_add_text(etree
, tvb
, offset
, 4,
1121 "TLV Type: %x (%s)", tlvt
, ttext
);
1122 proto_tree_add_text(etree
, tvb
, offset
+ 4, 4,
1123 "TLV Length: %u", tlvl
);
1125 case TYPE_NRGYZ_ROLE
:
1126 case TYPE_NRGYZ_DOMAIN
:
1127 case TYPE_NRGYZ_NAME
:
1128 proto_tree_add_text(etree
, tvb
, offset
+ 8,
1129 tlvl
- 8, "%s %s", ttext
,
1130 tvb_format_stringzpad(tvb
, offset
+ 8, tlvl
- 8)
1133 case TYPE_NRGYZ_REPLYTO
:
1134 ip_addr
= tvb_get_ipv4(tvb
, offset
+ 12);
1135 proto_tree_add_text(etree
, tvb
, offset
+ 8, 2,
1137 proto_tree_add_text(etree
, tvb
, offset
+ 10, 2,
1139 tvb_get_ntohs(tvb
, offset
+ 10)
1141 proto_tree_add_text(etree
, tvb
, offset
+ 12, 4,
1143 ip_to_str((guint8
*)&ip_addr
)
1145 proto_tree_add_text(etree
, tvb
, offset
+ 16, 2,
1146 "Unknown Field (Backup server Port?)");
1147 proto_tree_add_text(etree
, tvb
, offset
+ 18, 4,
1148 "Unknown Field (Backup Server IP?)");
1152 proto_tree_add_text(etree
, tvb
, offset
+ 8,
1160 proto_tree_add_text(tree
, tvb
, offset
, length
,
1161 "Invalid garbage at end");
1166 dissect_spare_poe_tlv(tvbuff_t
*tvb
, int offset
, int length
,
1170 proto_tree
*tlv_tree
;
1176 ti
= proto_tree_add_item(tree
, hf_cdp_spare_poe_tlv
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1177 tlv_tree
= proto_item_add_subtree(ti
, ett_cdp_spare_poe_tlv
);
1178 proto_tree_add_item(tlv_tree
, hf_cdp_spare_poe_tlv_poe
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1179 proto_tree_add_item(tlv_tree
, hf_cdp_spare_poe_tlv_spare_pair_arch
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1180 proto_tree_add_item(tlv_tree
, hf_cdp_spare_poe_tlv_req_spare_pair_poe
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1181 proto_tree_add_item(tlv_tree
, hf_cdp_spare_poe_tlv_pse_spare_pair_poe
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1185 add_multi_line_string_to_tree(proto_tree
*tree
, tvbuff_t
*tvb
, gint start
,
1186 gint len
, const gchar
*prefix
)
1195 prefix_len
= (int)strlen(prefix
);
1196 if (prefix_len
> 64)
1198 for (i
= 0; i
< prefix_len
; i
++)
1202 line_len
= tvb_find_line_end(tvb
, start
, len
, &next
, FALSE
);
1203 data_len
= next
- start
;
1204 proto_tree_add_text(tree
, tvb
, start
, data_len
, "%s%s", prefix
,
1205 tvb_format_stringzpad(tvb
, start
, line_len
));
1213 proto_register_cdp(void)
1215 static hf_register_info hf
[] = {
1217 { "Version", "cdp.version", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1221 { "TTL", "cdp.ttl", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1225 { "Checksum", "cdp.checksum", FT_UINT16
, BASE_HEX
, NULL
, 0x0,
1228 { &hf_cdp_checksum_good
,
1229 { "Good", "cdp.checksum_good", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1230 "True: checksum matches packet content; False: doesn't match content or not checked", HFILL
}},
1232 { &hf_cdp_checksum_bad
,
1233 { "Bad", "cdp.checksum_bad", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1234 "True: checksum doesn't match packet content; False: matches content or not checked", HFILL
}},
1237 { "Type", "cdp.tlv.type", FT_UINT16
, BASE_HEX
, VALS(type_vals
), 0x0,
1240 { &hf_cdp_tlvlength
,
1241 { "Length", "cdp.tlv.len", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1245 {"Device ID", "cdp.deviceid", FT_STRING
, BASE_NONE
,
1246 NULL
, 0, NULL
, HFILL
}},
1249 {"Platform", "cdp.platform", FT_STRING
, BASE_NONE
,
1250 NULL
, 0, NULL
, HFILL
}},
1253 {"Sent through Interface", "cdp.portid", FT_STRING
, BASE_NONE
,
1254 NULL
, 0, NULL
, HFILL
}},
1256 { &hf_cdp_capabilities
,
1257 {"Capabilities", "cdp.capabilities", FT_UINT32
, BASE_HEX
,
1258 NULL
, 0, NULL
, HFILL
}},
1260 { &hf_cdp_capabilities_router
,
1261 {"Router", "cdp.capabilities.router", FT_BOOLEAN
, 32,
1262 TFS(&tfs_yes_no
), 0x01, NULL
, HFILL
}},
1264 { &hf_cdp_capabilities_trans_bridge
,
1265 {"Transparent Bridge", "cdp.capabilities.trans_bridge", FT_BOOLEAN
, 32,
1266 TFS(&tfs_yes_no
), 0x02, NULL
, HFILL
}},
1268 { &hf_cdp_capabilities_src_bridge
,
1269 {"Source Route Bridge", "cdp.capabilities.src_bridge", FT_BOOLEAN
, 32,
1270 TFS(&tfs_yes_no
), 0x04, NULL
, HFILL
}},
1272 { &hf_cdp_capabilities_switch
,
1273 {"Switch", "cdp.capabilities.switch", FT_BOOLEAN
, 32,
1274 TFS(&tfs_yes_no
), 0x08, NULL
, HFILL
}},
1276 { &hf_cdp_capabilities_host
,
1277 {"Host", "cdp.capabilities.host", FT_BOOLEAN
, 32,
1278 TFS(&tfs_yes_no
), 0x10, NULL
, HFILL
}},
1280 { &hf_cdp_capabilities_igmp_capable
,
1281 {"IGMP capable", "cdp.capabilities.igmp_capable", FT_BOOLEAN
, 32,
1282 TFS(&tfs_yes_no
), 0x20, NULL
, HFILL
}},
1284 { &hf_cdp_capabilities_repeater
,
1285 {"Repeater", "cdp.capabilities.repeater", FT_BOOLEAN
, 32,
1286 TFS(&tfs_yes_no
), 0x40, NULL
, HFILL
}},
1288 { &hf_cdp_spare_poe_tlv
,
1289 { "Spare Pair PoE", "cdp.spare_poe_tlv", FT_UINT8
, BASE_HEX
,
1290 NULL
, 0x0, NULL
, HFILL
}
1293 { &hf_cdp_spare_poe_tlv_poe
,
1294 { "PSE Four-Wire PoE", "cdp.spare_poe_tlv.poe", FT_BOOLEAN
, 8,
1295 TFS(&tfs_supported_not_supported
), 0x01, NULL
, HFILL
}
1298 { &hf_cdp_spare_poe_tlv_spare_pair_arch
,
1299 { "PD Spare Pair Architecture", "cdp.spare_poe_tlv.spare_pair_arch", FT_BOOLEAN
, 8,
1300 TFS(&tfs_shared_independent
), 0x02, NULL
, HFILL
}
1303 { &hf_cdp_spare_poe_tlv_req_spare_pair_poe
,
1304 { "PD Request Spare Pair PoE", "cdp.spare_poe_tlv.req_spare_pair_poe", FT_BOOLEAN
, 8,
1305 TFS(&tfs_on_off
), 0x04, NULL
, HFILL
}
1308 { &hf_cdp_spare_poe_tlv_pse_spare_pair_poe
,
1309 { "PSE Spare Pair PoE", "cdp.spare_poe_tlv.pse_spare_pair_poe", FT_BOOLEAN
, 8,
1310 TFS(&tfs_on_off
), 0x08, NULL
, HFILL
}
1314 static gint
*ett
[] = {
1319 &ett_cdp_capabilities
,
1321 &ett_cdp_spare_poe_tlv
1324 proto_cdp
= proto_register_protocol("Cisco Discovery Protocol",
1326 proto_register_field_array(proto_cdp
, hf
, array_length(hf
));
1327 proto_register_subtree_array(ett
, array_length(ett
));
1331 proto_reg_handoff_cdp(void)
1333 dissector_handle_t cdp_handle
;
1335 data_handle
= find_dissector("data");
1336 cdp_handle
= create_dissector_handle(dissect_cdp
, proto_cdp
);
1337 dissector_add_uint("llc.cisco_pid", 0x2000, cdp_handle
);
1338 dissector_add_uint("chdlc.protocol", 0x2000, cdp_handle
);
1339 dissector_add_uint("ppp.protocol", 0x0207, cdp_handle
);