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