2 * Routines for LLDP dissection
3 * By Juan Gonzalez <juan.gonzalez@pikatech.com>
7 * Modified by: Brian Bogora <brian_bogora@mitel.com>
9 * Ethereal - Network traffic analyzer
10 * By Gerald Combs <gerald@ethereal.com>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
39 #include <epan/packet.h>
40 #include <epan/prefs.h>
41 #include <epan/emem.h>
42 #include <epan/etypes.h>
46 #define END_OF_LLDPDU_TLV_TYPE 0x00 /* Mandatory */
47 #define CHASSIS_ID_TLV_TYPE 0x01 /* Mandatory */
48 #define PORT_ID_TLV_TYPE 0x02 /* Mandatory */
49 #define TIME_TO_LIVE_TLV_TYPE 0x03 /* Mandatory */
50 #define PORT_DESCRIPTION_TLV_TYPE 0x04
51 #define SYSTEM_NAME_TLV_TYPE 0x05
52 #define SYSTEM_DESCRIPTION_TLV_TYPE 0x06
53 #define SYSTEM_CAPABILITIES_TLV_TYPE 0x07
54 #define MANAGEMENT_ADDR_TLV_TYPE 0x08
55 #define ORGANIZATION_SPECIFIC_TLV_TYPE 0x7F
58 #define TLV_TYPE_MASK 0xFE00
59 #define TLV_TYPE(value) (((value) & TLV_TYPE_MASK) >> 9)
60 #define TLV_INFO_LEN_MASK 0x01FF
61 #define TLV_INFO_LEN(value) ((value) & TLV_INFO_LEN_MASK)
63 /* Initialize the protocol and registered fields */
64 static int proto_lldp = -1;
65 static int hf_lldp_tlv_type = -1;
66 static int hf_lldp_tlv_len = -1;
67 static int hf_chassis_id_subtype = -1;
68 static int hf_chassis_id = -1;
69 static int hf_chassis_id_mac = -1;
70 static int hf_chassis_id_ip4 = -1;
71 static int hf_chassis_id_ip6 = -1;
72 static int hf_port_id_subtype = -1;
73 static int hf_port_id_mac = -1;
74 static int hf_port_id_ip4 = -1;
75 static int hf_port_id_ip6 = -1;
76 static int hf_time_to_live = -1;
77 static int hf_mgn_addr_ipv4 = -1;
78 static int hf_mgn_addr_ipv6 = -1;
79 static int hf_mgn_addr_hex = -1;
80 static int hf_mgn_obj_id = -1;
81 static int hf_org_spc_oui = -1;
82 static int hf_ieee_802_1_subtype = -1;
83 static int hf_ieee_802_3_subtype = -1;
84 static int hf_media_tlv_subtype = -1;
86 /* Initialize the subtree pointers */
87 static gint ett_lldp = -1;
88 static gint ett_chassis_id = -1;
89 static gint ett_port_id = -1;
90 static gint ett_time_to_live = -1;
91 static gint ett_end_of_lldpdu = -1;
92 static gint ett_port_description = -1;
93 static gint ett_system_name = -1;
94 static gint ett_system_cap = -1;
95 static gint ett_system_cap_summary = -1;
96 static gint ett_system_cap_enabled = -1;
97 static gint ett_management_address = -1;
98 static gint ett_unknown_tlv = -1;
99 static gint ett_org_spc_tlv = -1;
100 static gint ett_port_vlan_flags = -1;
101 static gint ett_802_3_flags = -1;
102 static gint ett_802_3_power = -1;
103 static gint ett_802_3_aggregation = -1;
104 static gint ett_media_capabilities = -1;
106 const value_string tlv_types[] = {
107 { END_OF_LLDPDU_TLV_TYPE, "End of LLDPDU"},
108 { CHASSIS_ID_TLV_TYPE, "Chassis Id"},
109 { PORT_ID_TLV_TYPE, "Port Id"},
110 { TIME_TO_LIVE_TLV_TYPE, "Time to Live"},
111 { PORT_DESCRIPTION_TLV_TYPE, "Port Description"},
112 { SYSTEM_NAME_TLV_TYPE, "System Name"},
113 { SYSTEM_DESCRIPTION_TLV_TYPE, "System Description"},
114 { SYSTEM_CAPABILITIES_TLV_TYPE, "System Capabilities"},
115 { MANAGEMENT_ADDR_TLV_TYPE, "Management Address"},
116 { ORGANIZATION_SPECIFIC_TLV_TYPE, "Organization Specific"},
120 const value_string chassis_id_subtypes[] = {
122 { 1, "Chassis component"},
123 { 2, "Interface alias"},
124 { 3, "Port component"},
126 { 5, "Network address"},
127 { 6, "Interface name"},
128 { 7, "Locally assigned"},
132 const value_string port_id_subtypes[] = {
134 { 1, "Interface alias"},
135 { 2, "Port component"},
137 { 4, "Network address"},
138 { 5, "Interface name"},
139 { 6, "Agent circuit Id"},
140 { 7, "Locally assigned"},
144 const value_string management_addr_values[] = {
149 { 4, "HDLC (8-bit multidrop)"},
151 { 6, "802 (includes all 802 media plus Ethernet)"},
153 { 8, "E.164 (SMDS, Frame Relay, ATM)"},
154 { 9, "F.69 (Telex)"},
155 { 10, "X.121 (X.25, Frame Relay)"},
159 { 14, "Banyan Vines"},
160 { 15, "E.164 with NSAP format subaddress"},
161 { 16, "DNS (Domain Name System)"},
162 { 17, "Distinguished Name"},
164 { 19, "XTP over IP version 4"},
165 { 20, "XTP over IP version 6"},
166 { 21, "XTP native mode XTP"},
167 { 22, "Fibre Channel World-Wide Port Name"},
168 { 23, "Fibre Channel World-Wide Node Name"},
173 const value_string interface_subtype_values[] = {
176 { 3, "System port number"},
180 const value_string tlv_oui_subtype_vals[] = {
181 { OUI_IEEE_802_1, "IEEE 802.1" },
182 { OUI_IEEE_802_3, "IEEE 802.3" },
183 { OUI_MEDIA_ENDPOINT, "TIA" },
187 /* IEEE 802.1 Subtypes */
188 const value_string ieee_802_1_subtypes[] = {
189 { 0x01, "Port VLAN ID" },
190 { 0x02, "Port and Protocol VLAN ID" },
191 { 0x03, "VLAN Name" },
192 { 0x04, "Protocol Identity" },
196 /* IEEE 802.3 Subtypes */
197 const value_string ieee_802_3_subtypes[] = {
198 { 0x01, "MAC/PHY Configuration/Status" },
199 { 0x02, "Power Via MDI" },
200 { 0x03, "Link Aggregation" },
201 { 0x04, "Maximum Frame Size" },
206 const value_string media_subtypes[] = {
207 { 1, "Media Capabilities" },
208 { 2, "Network Policy" },
209 { 3, "Location Identification" },
210 { 4, "Extended Power-via-MDI" },
211 { 5, "Inventory - Hardware Revision" },
212 { 6, "Inventory - Firmware Revision" },
213 { 7, "Inventory - Software Revision" },
214 { 8, "Inventory - Serial Number" },
215 { 9, "Inventory - Manufacturer Name" },
216 { 10, "Inventory - Model Name" },
217 { 11, "Inventory - Asset ID" },
221 /* Media Class Values */
222 const value_string media_class_values[] = {
223 { 0, "Type Not Defined" },
224 { 1, "Endpoint Class I" },
225 { 2, "Endpoint Class II" },
226 { 3, "Endpoint Class III" },
227 { 4, "Network Connectivity" },
231 /* Media Application Types */
232 const value_string media_application_type[] = {
235 { 2, "Voice Signaling" },
236 { 3, "Guest Voice" },
237 { 4, "Guest Voice Signaling" },
238 { 5, "Softphone Voice" },
239 { 6, "Video Conferencing" },
240 { 7, "Streaming Video" },
241 { 8, "Video Signaling" },
246 const value_string media_power_type[] = {
253 const value_string media_power_priority[] = {
262 const value_string media_power_pd_device[] = {
266 { 3, "PSE and Local" },
269 const value_string media_power_pse_device[] = {
271 { 1, "Primary Power Source" },
272 { 2, "Backup Power Source" },
276 /* Location data format */
277 const value_string location_data_format[] = {
279 { 1, "Coordinate-based LCI" },
280 { 2, "Civic Address LCI" },
285 /* Civic Address LCI - What field */
286 const value_string civic_address_what_values[] = {
287 { 0, "Location of the DHCP server" },
288 { 1, "Location of the network element believed to be closest to the client" },
289 { 2, "Location of the client"},
293 /* Civic Address Type field */
294 const value_string civic_address_type_values[] = {
296 { 1, "National subdivisions (province, state, etc)" },
297 { 2, "County, parish, district" },
298 { 3, "City, township" },
299 { 4, "City division, borough, ward" },
300 { 5, "Neighborhood, block" },
302 { 16, "Leading street direction" },
303 { 17, "Trailing street suffix" },
304 { 18, "Street suffix" },
305 { 19, "House number" },
306 { 20, "House number suffix" },
307 { 21, "Landmark or vanity address" },
308 { 22, "Additional location information" },
310 { 24, "Postal/ZIP code" },
314 { 28, "Room number" },
315 { 29, "Place type" },
320 /* System Capabilities */
321 #define SYSTEM_CAPABILITY_OTHER 0x0001
322 #define SYSTEM_CAPABILITY_REPEATER 0x0002
323 #define SYSTEM_CAPABILITY_BRIDGE 0x0004
324 #define SYSTEM_CAPABILITY_WLAN 0x0008
325 #define SYSTEM_CAPABILITY_ROUTER 0x0010
326 #define SYSTEM_CAPABILITY_TELEPHONE 0x0020
327 #define SYSTEM_CAPABILITY_DOCSIS 0x0040
328 #define SYSTEM_CAPABILITY_STATION 0x0080
330 /* Media Capabilities */
331 #define MEDIA_CAPABILITY_LLDP 0x0001
332 #define MEDIA_CAPABILITY_NETWORK_POLICY 0x0002
333 #define MEDIA_CAPABILITY_LOCATION_ID 0x0004
334 #define MEDIA_CAPABILITY_MDI_PSE 0x0008
335 #define MEDIA_CAPABILITY_MDI_PD 0x0010
336 #define MEDIA_CAPABILITY_INVENTORY 0x0020
338 #define MAX_MAC_LEN 6
340 /* Calculate Latitude and Longitude string */
343 option = 0 -> Latitude
344 option = 1 -> Longitude
347 get_latitude_or_longitude(int option, guint64 value)
349 guint64 tempValue = value;
350 gboolean negativeNum = FALSE;
351 guint32 integerPortion = 0;
352 const char *direction;
354 /* The latitude and longitude are 34 bit fixed point value consisting
355 of 9 bits of integer and 25 bits of fraction.
356 When option is equal to 0, positive numbers are represent a location
357 north of the equator and negative (2s complement) numbers are south of the equator.
358 When option is equal to 1, positive values are east of the prime
359 meridian and negative (2s complement) numbers are west of the prime meridian.
362 if (value & G_GINT64_CONSTANT(0x0000000200000000))
364 /* Have a negative number (2s complement) */
371 /* Get the integer portion */
372 integerPortion = (guint32)((tempValue & G_GINT64_CONSTANT(0x00000003FE000000)) >> 25);
374 /* Calculate decimal portion (using 25 bits for fraction) */
375 tempValue = (tempValue & G_GINT64_CONSTANT(0x0000000001FFFFFF))/33554432;
379 /* Latitude - north/south directions */
387 /* Longitude - east/west directions */
394 return ep_strdup_printf("%u.%04" PRIu64 " degrees %s",
395 integerPortion, tempValue, direction);
398 /* Dissect Chassis Id TLV (Mandatory) */
400 dissect_lldp_chassis_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
406 guint8 incorrectLen = 0; /* incorrect length if 1 */
408 const guint8 *mac_addr = NULL;
410 struct e_in6_addr ip6_addr;
412 proto_tree *chassis_tree = NULL;
413 proto_item *tf = NULL;
416 tempShort = tvb_get_ntohs(tvb, offset);
417 tempType = TLV_TYPE(tempShort);
418 if (tempType != CHASSIS_ID_TLV_TYPE)
422 tf = proto_tree_add_text(tree, tvb, offset, 2, "Invalid Chassis ID (0x%02X)", tempType);
423 chassis_tree = proto_item_add_subtree(tf, ett_chassis_id);
424 proto_tree_add_text(chassis_tree, tvb, offset, 2, "%s Invalid Chassis ID (%u)",
425 decode_boolean_bitfield(tempType, TLV_TYPE_MASK, 16, "", ""), tempType);
432 tempLen = TLV_INFO_LEN(tempShort);
437 tf = proto_tree_add_text(tree, tvb, offset, 2, "Invalid Chassis ID Length (%u)", tempLen);
438 chassis_tree = proto_item_add_subtree(tf, ett_chassis_id);
439 proto_tree_add_item(chassis_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
440 proto_tree_add_text(chassis_tree, tvb, offset, 2, "%s Invalid Length: %u",
441 decode_boolean_bitfield(tempLen, TLV_INFO_LEN_MASK, 16, "", ""), tempLen);
447 /* Get tlv subtype */
448 tempType = tvb_get_guint8(tvb, (offset+2));
452 case 4: /* MAC address */
456 incorrectLen = 1; /* Invalid length */
460 mac_addr=tvb_get_ptr(tvb, (offset+3), 6);
461 strPtr = ether_to_str(mac_addr);
465 case 5: /* Network address */
467 /* Check for IPv4 or IPv6 */
470 ip_addr = tvb_get_ipv4(tvb, (offset+3));
471 strPtr = ip_to_str((guint8 *)&ip_addr);
473 else if (tempLen == 17)
475 tvb_get_ipv6(tvb, (offset+3), &ip6_addr);
476 strPtr = ip6_to_str(&ip6_addr);
480 incorrectLen = 1; /* Invalid length */
486 case 2: /* Interface alias */
487 case 6: /* Interface name */
488 case 7: /* Locally assigned */
492 incorrectLen = 1; /* Invalid length */
496 strPtr = tvb_format_stringzpad(tvb, (offset+3), (tempLen-1));
500 case 1: /* Chassis component */
501 case 3: /* Port component */
505 incorrectLen = 1; /* Invalid length */
509 strPtr = tvb_bytes_to_str(tvb, (offset+3), (tempLen-1));
512 default: /* Reserved types */
516 incorrectLen = 1; /* Invalid length */
526 if (incorrectLen == 1)
530 tf = proto_tree_add_text(tree, tvb, offset, 2, "Invalid Chassis ID Length (%u)", tempLen);
531 chassis_tree = proto_item_add_subtree(tf, ett_chassis_id);
532 proto_tree_add_item(chassis_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
533 proto_tree_add_text(chassis_tree, tvb, offset, 2, "%s Invalid Length: %u",
534 decode_boolean_bitfield(tempLen, TLV_INFO_LEN_MASK, 16, "", ""), tempLen);
535 /* Get chassis id subtype */
536 proto_tree_add_item(chassis_tree, hf_chassis_id_subtype, tvb, (offset+2), 1, FALSE);
543 if (check_col(pinfo->cinfo, COL_INFO))
544 col_add_fstr(pinfo->cinfo, COL_INFO, "Chassis Id = %s ", strPtr);
548 /* Set chassis tree */
549 tf = proto_tree_add_text(tree, tvb, offset, (tempLen + 2), "Chassis Subtype = %s",
550 val_to_str(tempType, chassis_id_subtypes, "Reserved" ));
551 chassis_tree = proto_item_add_subtree(tf, ett_chassis_id);
553 proto_tree_add_item(chassis_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
554 proto_tree_add_item(chassis_tree, hf_lldp_tlv_len, tvb, offset, 2, FALSE);
556 /* Get chassis id subtype */
557 proto_tree_add_item(chassis_tree, hf_chassis_id_subtype, tvb, (offset+2), 1, FALSE);
562 case 4: /* MAC address */
563 proto_tree_add_ether(chassis_tree, hf_chassis_id_mac, tvb, (offset+3), 6, mac_addr);
565 case 5: /* Network address */
567 proto_tree_add_ipv4(chassis_tree, hf_chassis_id_ip4, tvb, (offset+3), 4, ip_addr);
569 proto_tree_add_ipv6(chassis_tree, hf_chassis_id_ip6, tvb, (offset+3), 16, ip6_addr.bytes);
571 case 2: /* Interface alias */
572 case 6: /* Interface name */
573 case 7: /* Locally assigned */
574 proto_tree_add_text(chassis_tree, tvb, (offset+3), (tempLen-1), "Chassis Id: %s", strPtr);
576 case 1: /* Chassis component */
577 case 3: /* Port component */
578 proto_tree_add_item(chassis_tree, hf_chassis_id, tvb, (offset+3), (tempLen-1), FALSE);
583 return (tempLen + 2);
586 /* Dissect Port Id TLV (Mandatory) */
588 dissect_lldp_port_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
594 const guint8 *mac_addr = NULL;
596 struct e_in6_addr ip6_addr;
598 proto_tree *port_tree = NULL;
599 proto_item *tf = NULL;
602 tempShort = tvb_get_ntohs(tvb, offset);
603 tempType = TLV_TYPE(tempShort);
604 if (tempType != PORT_ID_TLV_TYPE)
607 /* Get tlv length and subtype */
608 tempLen = TLV_INFO_LEN(tempShort);
609 tempType = tvb_get_guint8(tvb, (offset+2));
614 case 3: /* MAC address */
617 return -1; /* Invalid port id */
619 mac_addr=tvb_get_ptr(tvb, (offset+3), 6);
620 strPtr = ether_to_str(mac_addr);
624 case 4: /* Network address */
626 /* Check for IPv4 or IPv6 */
629 ip_addr = tvb_get_ipv4(tvb, (offset+3));
630 strPtr = ip_to_str((guint8 *)&ip_addr);
632 else if (tempLen == 17)
634 tvb_get_ipv6(tvb, (offset+3), &ip6_addr);
635 strPtr = ip6_to_str(&ip6_addr);
638 return -1; /* Invalid chassis id */
644 strPtr = tvb_format_stringzpad(tvb, (offset+3), (tempLen-1));
650 if (check_col(pinfo->cinfo, COL_INFO))
651 col_append_fstr(pinfo->cinfo, COL_INFO, "Port Id = %s ", strPtr);
656 tf = proto_tree_add_text(tree, tvb, offset, (tempLen + 2), "Port Subtype = %s",
657 val_to_str(tempType, port_id_subtypes, "Unknown" ));
658 port_tree = proto_item_add_subtree(tf, ett_port_id);
660 proto_tree_add_item(port_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
661 proto_tree_add_item(port_tree, hf_lldp_tlv_len, tvb, offset, 2, FALSE);
663 /* Get port id subtype */
664 proto_tree_add_item(port_tree, hf_port_id_subtype, tvb, (offset+2), 1, FALSE);
667 /*proto_tree_add_text(port_tree, tvb, (offset+3), (tempLen-1), "Port Id: %s", strPtr);*/
670 case 3: /* MAC address */
671 proto_tree_add_ether(port_tree, hf_port_id_mac, tvb, (offset+3), 6, mac_addr);
673 case 4: /* Network address */
675 proto_tree_add_ipv4(port_tree, hf_port_id_ip4, tvb, (offset+3), 4, ip_addr);
677 proto_tree_add_ipv6(port_tree, hf_port_id_ip6, tvb, (offset+3), 16, ip6_addr.bytes);
680 proto_tree_add_text(port_tree, tvb, (offset+3), (tempLen-1), "Port Id: %s", strPtr);
686 return (tempLen + 2);
689 /* Dissect Time To Live TLV (Mandatory) */
691 dissect_lldp_time_to_live(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
697 proto_tree *time_to_live_tree = NULL;
698 proto_item *tf = NULL;
701 tempShort = tvb_get_ntohs(tvb, offset);
702 tempType = TLV_TYPE(tempShort);
703 if (tempType != TIME_TO_LIVE_TLV_TYPE)
706 /* Get tlv length and seconds field */
707 tempLen = TLV_INFO_LEN(tempShort);
708 tempShort = tvb_get_ntohs(tvb, (offset+2));
710 if (check_col(pinfo->cinfo, COL_INFO))
711 col_append_fstr(pinfo->cinfo, COL_INFO, "TTL = %u ", tempShort);
716 tf = proto_tree_add_text(tree, tvb, offset, (tempLen + 2), "Time To Live = %u sec", tempShort);
717 time_to_live_tree = proto_item_add_subtree(tf, ett_time_to_live);
719 proto_tree_add_item(time_to_live_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
720 proto_tree_add_item(time_to_live_tree, hf_lldp_tlv_len, tvb, offset, 2, FALSE);
722 /* Display time to live information */
723 proto_tree_add_item(time_to_live_tree, hf_time_to_live, tvb, (offset+2), 2, FALSE);
726 return (tempLen + 2);
729 /* Dissect End of LLDPDU TLV (Mandatory) */
731 dissect_lldp_end_of_lldpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
736 proto_tree *end_of_lldpdu_tree = NULL;
737 proto_item *tf = NULL;
739 /* Get tlv type and length */
740 tempShort = tvb_get_ntohs(tvb, offset);
743 tempLen = TLV_INFO_LEN(tempShort);
748 tf = proto_tree_add_text(tree, tvb, offset, (tempLen + 2), "End of LLDPDU");
749 end_of_lldpdu_tree = proto_item_add_subtree(tf, ett_end_of_lldpdu);
751 proto_tree_add_item(end_of_lldpdu_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
752 proto_tree_add_item(end_of_lldpdu_tree, hf_lldp_tlv_len, tvb, offset, 2, FALSE);
755 return -1; /* Force the lldp dissector to terminate */
758 /* Dissect Port Description TLV */
760 dissect_lldp_port_desc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
766 proto_tree *port_desc_tree = NULL;
767 proto_item *tf = NULL;
769 /* Get tlv type and length */
770 tempShort = tvb_get_ntohs(tvb, offset);
773 tempLen = TLV_INFO_LEN(tempShort);
777 strPtr = tvb_format_stringzpad(tvb, (offset+2), tempLen);
780 tf = proto_tree_add_text(tree, tvb, offset, (tempLen + 2), "Port Description = %s", strPtr);
781 port_desc_tree = proto_item_add_subtree(tf, ett_port_description);
783 proto_tree_add_item(port_desc_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
784 proto_tree_add_item(port_desc_tree, hf_lldp_tlv_len, tvb, offset, 2, FALSE);
786 /* Display port description information */
787 proto_tree_add_text(port_desc_tree, tvb, (offset+2), tempLen, "Port Description: %s",
791 return (tempLen + 2);
794 /* Dissect System Name and description TLV */
796 dissect_lldp_system_name(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
803 proto_tree *system_name_tree = NULL;
804 proto_item *tf = NULL;
806 /* Get tlv type and length */
807 tempShort = tvb_get_ntohs(tvb, offset);
808 tempType = TLV_TYPE(tempShort);
811 tempLen = TLV_INFO_LEN(tempShort);
815 strPtr = tvb_format_stringzpad(tvb, (offset+2), tempLen);
817 /* Set system name tree */
818 if (tempType == SYSTEM_NAME_TLV_TYPE)
819 tf = proto_tree_add_text(tree, tvb, offset, (tempLen + 2), "System Name = %s", strPtr);
821 tf = proto_tree_add_text(tree, tvb, offset, (tempLen + 2), "System Description = %s", strPtr);
822 system_name_tree = proto_item_add_subtree(tf, ett_system_name);
824 proto_tree_add_item(system_name_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
825 proto_tree_add_item(system_name_tree, hf_lldp_tlv_len, tvb, offset, 2, FALSE);
827 /* Display system name information */
828 proto_tree_add_text(system_name_tree, tvb, (offset+2), tempLen, "%s = %s",
829 ((tempType == SYSTEM_NAME_TLV_TYPE) ? "System Name" : "System Description"),
833 return (tempLen + 2);
836 /* Dissect System Capabilities TLV */
838 dissect_lldp_system_capabilities(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
842 guint16 tempCapability;
844 proto_tree *system_capabilities_tree = NULL;
845 proto_tree *capabilities_summary_tree = NULL;
846 proto_tree *capabilities_enabled_tree = NULL;
847 proto_item *tf = NULL;
849 /* Get tlv type and length */
850 tempShort = tvb_get_ntohs(tvb, offset);
853 tempLen = TLV_INFO_LEN(tempShort);
855 /* Get system capabilities */
856 tempCapability = tvb_get_ntohs(tvb, (offset+2));
860 /* Set system capabilities tree */
861 tf = proto_tree_add_text(tree, tvb, offset, (tempLen + 2), "Capabilities");
862 system_capabilities_tree = proto_item_add_subtree(tf, ett_system_cap);
864 proto_tree_add_item(system_capabilities_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
865 proto_tree_add_item(system_capabilities_tree, hf_lldp_tlv_len, tvb, offset, 2, FALSE);
867 /* Display system capability information */
868 tf = proto_tree_add_text(system_capabilities_tree, tvb, (offset+2), 2, "Capabilities: 0x%04x", tempCapability);
869 capabilities_summary_tree = proto_item_add_subtree(tf, ett_system_cap_summary);
870 /* Add capabilities to summary tree */
871 if (tempCapability & SYSTEM_CAPABILITY_OTHER)
872 proto_tree_add_text(capabilities_summary_tree, tvb, (offset+2), 2, "%s",
873 decode_boolean_bitfield(tempCapability, SYSTEM_CAPABILITY_OTHER,
875 if (tempCapability & SYSTEM_CAPABILITY_REPEATER)
876 proto_tree_add_text(capabilities_summary_tree, tvb, (offset+2), 2, "%s",
877 decode_boolean_bitfield(tempCapability, SYSTEM_CAPABILITY_REPEATER,
878 16, "Repeater", ""));
879 if (tempCapability & SYSTEM_CAPABILITY_BRIDGE)
880 proto_tree_add_text(capabilities_summary_tree, tvb, (offset+2), 2, "%s",
881 decode_boolean_bitfield(tempCapability, SYSTEM_CAPABILITY_BRIDGE,
883 if (tempCapability & SYSTEM_CAPABILITY_WLAN)
884 proto_tree_add_text(capabilities_summary_tree, tvb, (offset+2), 2, "%s",
885 decode_boolean_bitfield(tempCapability, SYSTEM_CAPABILITY_WLAN,
886 16, "WLAN access point", ""));
887 if (tempCapability & SYSTEM_CAPABILITY_ROUTER)
888 proto_tree_add_text(capabilities_summary_tree, tvb, (offset+2), 2, "%s",
889 decode_boolean_bitfield(tempCapability, SYSTEM_CAPABILITY_ROUTER,
891 if (tempCapability & SYSTEM_CAPABILITY_TELEPHONE)
892 proto_tree_add_text(capabilities_summary_tree, tvb, (offset+2), 2, "%s",
893 decode_boolean_bitfield(tempCapability, SYSTEM_CAPABILITY_TELEPHONE,
894 16, "Telephone", ""));
895 if (tempCapability & SYSTEM_CAPABILITY_DOCSIS)
896 proto_tree_add_text(capabilities_summary_tree, tvb, (offset+2), 2, "%s",
897 decode_boolean_bitfield(tempCapability, SYSTEM_CAPABILITY_DOCSIS,
898 16, "DOCSIS cable device", ""));
899 if (tempCapability & SYSTEM_CAPABILITY_STATION)
900 proto_tree_add_text(capabilities_summary_tree, tvb, (offset+2), 2, "%s",
901 decode_boolean_bitfield(tempCapability, SYSTEM_CAPABILITY_STATION,
902 16, "Station only", ""));
904 /* Get enabled summary */
905 tempShort = tvb_get_ntohs(tvb, (offset+4));
907 /* Display system capability information */
908 tf = proto_tree_add_text(system_capabilities_tree, tvb, (offset+4), 2, "Enabled Capabilities: 0x%04x", tempShort);
909 capabilities_enabled_tree = proto_item_add_subtree(tf, ett_system_cap_enabled);
910 /* Add capabilities to summary tree */
911 if (tempShort & SYSTEM_CAPABILITY_OTHER)
912 proto_tree_add_text(capabilities_enabled_tree, tvb, (offset+4), 2, "%s",
913 decode_boolean_bitfield(tempShort, SYSTEM_CAPABILITY_OTHER,
915 if (tempShort & SYSTEM_CAPABILITY_REPEATER)
916 proto_tree_add_text(capabilities_enabled_tree, tvb, (offset+4), 2, "%s",
917 decode_boolean_bitfield(tempShort, SYSTEM_CAPABILITY_REPEATER,
918 16, "Repeater", ""));
919 if (tempShort & SYSTEM_CAPABILITY_BRIDGE)
920 proto_tree_add_text(capabilities_enabled_tree, tvb, (offset+4), 2, "%s",
921 decode_boolean_bitfield(tempShort, SYSTEM_CAPABILITY_BRIDGE,
923 if (tempShort & SYSTEM_CAPABILITY_WLAN)
924 proto_tree_add_text(capabilities_enabled_tree, tvb, (offset+4), 2, "%s",
925 decode_boolean_bitfield(tempShort, SYSTEM_CAPABILITY_WLAN,
926 16, "WLAN access point", ""));
927 if (tempShort & SYSTEM_CAPABILITY_ROUTER)
928 proto_tree_add_text(capabilities_enabled_tree, tvb, (offset+4), 2, "%s",
929 decode_boolean_bitfield(tempShort, SYSTEM_CAPABILITY_ROUTER,
931 if (tempShort & SYSTEM_CAPABILITY_TELEPHONE)
932 proto_tree_add_text(capabilities_enabled_tree, tvb, (offset+4), 2, "%s",
933 decode_boolean_bitfield(tempShort, SYSTEM_CAPABILITY_TELEPHONE,
934 16, "Telephone", ""));
935 if (tempShort & SYSTEM_CAPABILITY_DOCSIS)
936 proto_tree_add_text(capabilities_enabled_tree, tvb, (offset+4), 2, "%s",
937 decode_boolean_bitfield(tempShort, SYSTEM_CAPABILITY_DOCSIS,
938 16, "DOCSIS cable device", ""));
939 if (tempShort & SYSTEM_CAPABILITY_STATION)
940 proto_tree_add_text(capabilities_enabled_tree, tvb, (offset+4), 2, "%s",
941 decode_boolean_bitfield(tempShort, SYSTEM_CAPABILITY_STATION,
942 16, "Station only", ""));
945 return (tempLen + 2);
948 /* Dissect Management Address TLV */
950 dissect_lldp_management_address(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
955 guint8 stringLen = 0;
956 guint32 tempOffset = offset;
959 proto_tree *system_mgm_addr = NULL;
960 proto_item *tf = NULL;
962 /* Get tlv type and length */
963 tempShort = tvb_get_ntohs(tvb, tempOffset);
966 tempLen = TLV_INFO_LEN(tempShort);
970 /* Set system capabilities tree */
971 tf = proto_tree_add_text(tree, tvb, tempOffset, (tempLen + 2), "Management Address");
972 system_mgm_addr = proto_item_add_subtree(tf, ett_management_address);
974 proto_tree_add_item(system_mgm_addr, hf_lldp_tlv_type, tvb, tempOffset, 2, FALSE);
975 proto_tree_add_item(system_mgm_addr, hf_lldp_tlv_len, tvb, tempOffset, 2, FALSE);
979 /* Get management address string length */
980 stringLen = tvb_get_guint8(tvb, tempOffset);
981 proto_tree_add_text(system_mgm_addr, tvb, tempOffset, 1, "Address String Length: %u", stringLen);
985 /* Get management address subtype */
986 tempByte = tvb_get_guint8(tvb, tempOffset);
987 proto_tree_add_text(system_mgm_addr, tvb, tempOffset, 1, "Address Subtype: %s (%u)",
988 val_to_str(tempByte, management_addr_values, "Undefined"),
997 proto_tree_add_item(system_mgm_addr, hf_mgn_addr_ipv4, tvb, tempOffset, 4, FALSE);
1000 proto_tree_add_item(system_mgm_addr, hf_mgn_addr_ipv6, tvb, tempOffset, (stringLen-1), FALSE);
1003 proto_tree_add_item(system_mgm_addr, hf_mgn_addr_hex, tvb, tempOffset, (stringLen-1), FALSE);
1007 tempOffset += (stringLen-1);
1009 /* Get interface numbering subtype */
1010 tempByte = tvb_get_guint8(tvb, tempOffset);
1011 proto_tree_add_text(system_mgm_addr, tvb, tempOffset, 1, "Interface Subtype: %s (%u)",
1012 val_to_str(tempByte, interface_subtype_values, "Undefined"),
1017 /* Get interface number */
1018 tempLong = tvb_get_ntohl(tvb, tempOffset);
1019 proto_tree_add_text(system_mgm_addr, tvb, tempOffset, 4, "Interface Number: %u", tempLong);
1023 /* Get OID string length */
1024 stringLen = tvb_get_guint8(tvb, tempOffset);
1025 proto_tree_add_text(system_mgm_addr, tvb, tempOffset, 1, "OID String Length: %u", stringLen);
1031 /* Get OID identifier */
1032 proto_tree_add_item(system_mgm_addr, hf_mgn_obj_id, tvb, tempOffset, stringLen, FALSE);
1036 return (tempLen + 2);
1039 /* Dissect IEEE 802.1 TLVs */
1041 dissect_ieee_802_1_tlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
1046 guint32 tempOffset = offset;
1048 proto_tree *vlan_flags = NULL;
1049 proto_item *tf = NULL;
1052 subType = tvb_get_guint8(tvb, tempOffset);
1055 proto_tree_add_item(tree, hf_ieee_802_1_subtype, tvb, tempOffset, 1, FALSE);
1061 case 0x01: /* Port VLAN ID */
1063 /* Get port vland id */
1064 tempShort = tvb_get_ntohs(tvb, tempOffset);
1066 proto_tree_add_text(tree, tvb, tempOffset, 2, "Port VLAN Identifier: 0x%04X", tempShort);
1070 case 0x02: /* Port and Protocol VLAN ID */
1073 tempByte = tvb_get_guint8(tvb, tempOffset);
1076 tf = proto_tree_add_text(tree, tvb, tempOffset, 1, "Flags: 0x%02x", tempByte);
1077 vlan_flags = proto_item_add_subtree(tf, ett_port_vlan_flags);
1079 /* Get supported flag */
1080 proto_tree_add_text(vlan_flags, tvb, tempOffset, 1, "%s",
1081 decode_boolean_bitfield(tempByte, 0x01, 8, "Port and Protocol VLAN: Supported",
1082 "Port and Protocol VLAN: Not Supported"));
1084 /* Get enabled flag */
1085 proto_tree_add_text(vlan_flags, tvb, tempOffset, 1, "%s",
1086 decode_boolean_bitfield(tempByte, 0x02, 8, "Port and Protocol VLAN: Enabled",
1087 "Port and Protocol VLAN: Not Enabled"));
1092 /* Get port and protocol vlan id */
1093 tempShort = tvb_get_ntohs(tvb, tempOffset);
1095 proto_tree_add_text(tree, tvb, tempOffset, 2, "Port and Protocol VLAN Identifier: 0x%04X", tempShort);
1099 case 0x03: /* VLAN Name */
1102 tempShort = tvb_get_ntohs(tvb, tempOffset);
1104 proto_tree_add_text(tree, tvb, tempOffset, 2, "VLAN Identifier: 0x%04X", tempShort);
1108 /* Get vlan name length */
1109 tempByte = tvb_get_guint8(tvb, tempOffset);
1111 proto_tree_add_text(tree, tvb, tempOffset, 1, "VLAN Name Length: %u", tempByte);
1118 proto_tree_add_text(tree, tvb, tempOffset, tempByte, "VLAN Name: %s",
1119 tvb_format_stringzpad(tvb, tempOffset, tempByte));
1124 case 0x04: /* Protocol ID */
1126 /* Get protocal id length */
1127 tempByte = tvb_get_guint8(tvb, tempOffset);
1129 proto_tree_add_text(tree, tvb, tempOffset, 1, "Protocol Identity Length: %u", tempByte);
1136 proto_tree_add_text(tree, tvb, tempOffset, tempByte, "Protocol Identity: %s",
1137 tvb_bytes_to_str(tvb, tempOffset, tempByte));
1147 /* Dissect IEEE 802.3 TLVs */
1149 dissect_ieee_802_3_tlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
1155 guint32 tempOffset = offset;
1157 proto_tree *mac_phy_flags = NULL;
1158 proto_item *tf = NULL;
1161 subType = tvb_get_guint8(tvb, tempOffset);
1164 proto_tree_add_item(tree, hf_ieee_802_3_subtype, tvb, tempOffset, 1, FALSE);
1170 case 0x01: /* MAC/PHY Configuration/Status */
1172 /* Get auto-negotiation info */
1173 tempByte = tvb_get_guint8(tvb, tempOffset);
1176 tf = proto_tree_add_text(tree, tvb, tempOffset, 1, "Auto-Negotiation Support/Status: 0x%02x", tempByte);
1177 mac_phy_flags = proto_item_add_subtree(tf, ett_802_3_flags);
1179 /* Get supported flag */
1180 proto_tree_add_text(mac_phy_flags, tvb, tempOffset, 1, "%s",
1181 decode_boolean_bitfield(tempByte, 0x01, 8, "Auto-Negotiation: Supported",
1182 "Auto-Negotiation: Not Supported"));
1184 /* Get enabled flag */
1185 proto_tree_add_text(mac_phy_flags, tvb, tempOffset, 1, "%s",
1186 decode_boolean_bitfield(tempByte, 0x02, 8, "Auto-Negotiation: Enabled",
1187 "Auto-Negotiation: Not Enabled"));
1192 /* Get pmd auto-negotiation advertised capability */
1193 tempShort = tvb_get_ntohs(tvb, tempOffset);
1195 proto_tree_add_text(tree, tvb, tempOffset, 2, "PMD Auto-Negotiation Advertised Capability: 0x%04X", tempShort);
1199 /* Get operational MAU type */
1200 tempShort = tvb_get_ntohs(tvb, tempOffset);
1202 proto_tree_add_text(tree, tvb, tempOffset, 2, "Operational MAU Type: 0x%04X", tempShort);
1208 case 0x02: /* MDI Power Support */
1210 /* Get MDI power support info */
1211 tempByte = tvb_get_guint8(tvb, tempOffset);
1214 tf = proto_tree_add_text(tree, tvb, tempOffset, 1, "MDI Power Support: 0x%02x", tempByte);
1215 mac_phy_flags = proto_item_add_subtree(tf, ett_802_3_power);
1217 /* Get port class */
1218 proto_tree_add_text(mac_phy_flags, tvb, tempOffset, 1, "%s",
1219 decode_boolean_bitfield(tempByte, 0x01, 8, "Port Class: PSE",
1222 /* Get PSE MDI power support */
1223 proto_tree_add_text(mac_phy_flags, tvb, tempOffset, 1, "%s",
1224 decode_boolean_bitfield(tempByte, 0x02, 8, "PSE MDI Power: Supported",
1225 "PSE MDI Power: Not Supported"));
1227 /* Get PSE MDI power state */
1228 proto_tree_add_text(mac_phy_flags, tvb, tempOffset, 1, "%s",
1229 decode_boolean_bitfield(tempByte, 0x04, 8, "PSE MDI Power Enabled: Yes",
1230 "PSE MDI Power Enabled: No"));
1232 /* Get PSE pairs control ability */
1233 proto_tree_add_text(mac_phy_flags, tvb, tempOffset, 1, "%s",
1234 decode_boolean_bitfield(tempByte, 0x08, 8, "PSE Pairs Control Ability: Yes",
1235 "PSE Pairs Control Ability: No"));
1240 /* Get PSE power pair */
1241 tempByte = tvb_get_guint8(tvb, tempOffset);
1243 proto_tree_add_text(tree, tvb, tempOffset, 1, "PSE Power Pair: %u", tempByte);
1247 /* Get power class */
1248 tempByte = tvb_get_guint8(tvb, tempOffset);
1250 proto_tree_add_text(tree, tvb, tempOffset, 1, "Power Class: %u", tempByte);
1256 case 0x03: /* Link Aggregation */
1258 /* Get aggregation status */
1259 tempByte = tvb_get_guint8(tvb, tempOffset);
1262 tf = proto_tree_add_text(tree, tvb, tempOffset, 1, "Aggregation Status: 0x%02x", tempByte);
1263 mac_phy_flags = proto_item_add_subtree(tf, ett_802_3_aggregation);
1265 /* Get aggregation capability */
1266 proto_tree_add_text(mac_phy_flags, tvb, tempOffset, 1, "%s",
1267 decode_boolean_bitfield(tempByte, 0x01, 8, "Aggregation Capability: Yes",
1268 "Aggregation Capability: No"));
1270 /* Get aggregation status */
1271 proto_tree_add_text(mac_phy_flags, tvb, tempOffset, 1, "%s",
1272 decode_boolean_bitfield(tempByte, 0x02, 8, "Aggregation Status: Enabled",
1273 "Aggregation Status: Not Enabled"));
1278 /* Get aggregated port id */
1279 tempLong = tvb_get_ntohl(tvb, tempOffset);
1281 proto_tree_add_text(tree, tvb, tempOffset, 4, "Aggregated Port Id: %u", tempLong);
1287 case 0x04: /* Maximum Frame Size */
1289 /* Get maximum frame size */
1290 tempShort = tvb_get_ntohs(tvb, tempOffset);
1292 proto_tree_add_text(tree, tvb, tempOffset, 2, "Maximum Frame Size: %u", tempShort);
1303 /* Dissect Media TLVs */
1305 dissect_media_tlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset, guint16 tlvLen)
1307 guint32 tempOffset = offset;
1315 guint64 temp64bit = 0;
1317 proto_tree *media_flags = NULL;
1318 proto_item *tf = NULL;
1321 subType = tvb_get_guint8(tvb, tempOffset);
1323 proto_tree_add_item(tree, hf_media_tlv_subtype, tvb, tempOffset, 1, FALSE);
1329 case 1: /* LLDP-MED Capabilities */
1331 /* Get capabilities */
1334 proto_tree_add_text(tree, tvb, tempOffset, 0, "TLV too short");
1337 tempShort = tvb_get_ntohs(tvb, tempOffset);
1340 tf = proto_tree_add_text(tree, tvb, tempOffset, 2, "Capabilities: 0x%04x", tempShort);
1341 media_flags = proto_item_add_subtree(tf, ett_media_capabilities);
1342 if (tempShort & MEDIA_CAPABILITY_LLDP)
1343 proto_tree_add_text(media_flags, tvb, tempOffset, 2, "%s",
1344 decode_boolean_bitfield(tempShort, MEDIA_CAPABILITY_LLDP, 16,
1345 "LLDP-MED Capabilities", ""));
1346 if (tempShort & MEDIA_CAPABILITY_NETWORK_POLICY)
1347 proto_tree_add_text(media_flags, tvb, tempOffset, 2, "%s",
1348 decode_boolean_bitfield(tempShort, MEDIA_CAPABILITY_NETWORK_POLICY, 16,
1349 "Network Policy", ""));
1350 if (tempShort & MEDIA_CAPABILITY_LOCATION_ID)
1351 proto_tree_add_text(media_flags, tvb, tempOffset, 2, "%s",
1352 decode_boolean_bitfield(tempShort, MEDIA_CAPABILITY_LOCATION_ID, 16,
1353 "Location Identification", ""));
1354 if (tempShort & MEDIA_CAPABILITY_MDI_PSE)
1355 proto_tree_add_text(media_flags, tvb, tempOffset, 2, "%s",
1356 decode_boolean_bitfield(tempShort, MEDIA_CAPABILITY_MDI_PSE, 16,
1357 "Extended Power via MDI-PSE", ""));
1358 if (tempShort & MEDIA_CAPABILITY_MDI_PD)
1359 proto_tree_add_text(media_flags, tvb, tempOffset, 2, "%s",
1360 decode_boolean_bitfield(tempShort, MEDIA_CAPABILITY_MDI_PD, 16,
1361 "Extended Power via MDI-PD", ""));
1362 if (tempShort & MEDIA_CAPABILITY_INVENTORY)
1363 proto_tree_add_text(media_flags, tvb, tempOffset, 2, "%s",
1364 decode_boolean_bitfield(tempShort, MEDIA_CAPABILITY_INVENTORY, 16,
1370 /* Get Class type */
1373 proto_tree_add_text(tree, tvb, tempOffset, 0, "TLV too short");
1376 tempByte = tvb_get_guint8(tvb, tempOffset);
1378 proto_tree_add_text(tree, tvb, tempOffset, 1, "Class Type: %s", val_to_str(tempByte, media_class_values, "Unknown"));
1384 case 2: /* Network Policy */
1386 /* Get application type */
1389 proto_tree_add_text(tree, tvb, tempOffset, 0, "TLV too short");
1392 tempByte = tvb_get_guint8(tvb, tempOffset);
1394 proto_tree_add_text(tree, tvb, tempOffset, 1, "Applicaton Type: %s (%u)",
1395 val_to_str(tempByte, media_application_type, "Unknown"), tempByte);
1402 proto_tree_add_text(tree, tvb, tempOffset, 0, "TLV too short");
1405 tempByte = tvb_get_guint8(tvb, tempOffset);
1407 /* Unknown policy flag */
1409 proto_tree_add_text(tree, tvb, tempOffset, 1, "%s",
1410 decode_boolean_bitfield(tempByte, 0x80, 8,"Policy: Unknown", "Policy: Defined"));
1414 proto_tree_add_text(tree, tvb, tempOffset, 1, "%s",
1415 decode_boolean_bitfield(tempByte, 0x40, 8,"Tagged: Yes", "Tagged: No"));
1422 proto_tree_add_text(tree, tvb, tempOffset, 0, "TLV too short");
1425 tempShort = tvb_get_ntohs(tvb, tempOffset);
1426 tempVLAN = (tempShort & 0x1FFE) >> 1;
1428 proto_tree_add_text(tree, tvb, tempOffset, 2, "%s %u",
1429 decode_boolean_bitfield(tempShort, 0x1FFE, 16, "VLAN Id:", "VLAN Id:"), tempVLAN);
1433 /* Get L2 priority */
1436 proto_tree_add_text(tree, tvb, tempOffset, 0, "TLV too short");
1439 tempShort = tvb_get_ntohs(tvb, tempOffset);
1441 proto_tree_add_text(tree, tvb, tempOffset, 2, "%s %u",
1442 decode_boolean_bitfield(tempShort, 0x01C0, 16, "L2 Priority:", "L2 Priority:"),
1443 ((tempShort & 0x01C0) >> 6));
1447 /* Get DSCP value */
1448 tempByte = tvb_get_guint8(tvb, tempOffset);
1450 proto_tree_add_text(tree, tvb, tempOffset, 1, "%s %u",
1451 decode_boolean_bitfield(tempByte, 0x3F, 8, "DSCP Value:", "DSCP Value:"),
1456 case 3: /* Location Identification */
1458 /* Get location data format */
1461 proto_tree_add_text(tree, tvb, tempOffset, 0, "TLV too short");
1464 tempByte = tvb_get_guint8(tvb, tempOffset);
1466 proto_tree_add_text(tree, tvb, tempOffset, 1, "Location Data Format: %s (%u)",
1467 val_to_str(tempByte, location_data_format, "Unknown"), tempByte);
1473 case 1: /* Coordinate-based LCI */
1477 * XXX - should this be handled by the BOOTP
1478 * dissector, and exported to us?
1482 proto_tree_add_text(tree, tvb, tempOffset, 0, "TLV too short");
1486 /* Get latitude resolution */
1487 tempByte = tvb_get_guint8(tvb, tempOffset);
1489 proto_tree_add_text(tree, tvb, tempOffset, 1, "%s %u",
1490 decode_boolean_bitfield(tempByte, 0xFC, 8, "Latitude Resolution:", "Latitude Resolution:"),
1491 ((tempByte & 0xFC) >> 2));
1494 temp64bit = tvb_get_ntoh64(tvb, tempOffset);
1495 temp64bit = (temp64bit & G_GINT64_CONSTANT(0x03FFFFFFFF000000)) >> 24;
1497 proto_tree_add_text(tree, tvb, tempOffset, 5, "Latitude: %s (0x%16" PRIX64 ")",
1498 get_latitude_or_longitude(0, temp64bit),
1503 /* Get longitude resolution */
1504 tempByte = tvb_get_guint8(tvb, tempOffset);
1506 proto_tree_add_text(tree, tvb, tempOffset, 1, "%s %u",
1507 decode_boolean_bitfield(tempByte, 0xFC, 8, "Longitude Resolution:", "Longitude Resolution:"),
1508 ((tempByte & 0xFC) >> 2));
1511 temp64bit = tvb_get_ntoh64(tvb, tempOffset);
1512 temp64bit = (temp64bit & G_GINT64_CONSTANT(0x03FFFFFFFF000000)) >> 24;
1515 proto_tree_add_text(tree, tvb, tempOffset, 5, "Longitude: %s (0x%16" PRIX64 ")",
1516 get_latitude_or_longitude(1,temp64bit),
1522 tempByte = tvb_get_guint8(tvb, tempOffset);
1525 tf = proto_tree_add_text(tree, tvb, tempOffset, 1, "%s",
1526 decode_boolean_bitfield(tempByte, 0xF0, 8, "Altitude Type: ", "Altitude Type: "));
1528 switch ((tempByte >> 4))
1531 proto_item_append_text(tf, "Meters (1)");
1534 proto_item_append_text(tf, "Floors (2)");
1537 proto_item_append_text(tf, " Unknown (%u)", (tempByte >> 4));
1542 /* Get Altitude Resolution */
1543 tempShort = tvb_get_ntohs(tvb, tempOffset);
1545 proto_tree_add_text(tree, tvb, tempOffset, 2, "%s %u",
1546 decode_boolean_bitfield(tempShort, 0x0FC0, 16, "Altitude Resolution: ", "Altitude Type: "),
1547 ((tempShort & 0x0FC0) >> 6));
1552 tempLong = (tvb_get_ntohl(tvb, tempOffset) & 0x03FFFFFFF);
1554 proto_tree_add_text(tree, tvb, tempOffset, 4, "Altitude: 0x%08X", tempLong);
1559 tempByte = tvb_get_guint8(tvb, tempOffset);
1561 proto_tree_add_text(tree, tvb, tempOffset, 1, "Datum: %u", tempByte);
1565 case 2: /* Civic Address LCI */
1568 * See draft-ietf-geopriv-dhcp-civil-07.
1569 * XXX - should this be handled by the BOOTP
1570 * dissector, and exported to us?
1574 proto_tree_add_text(tree, tvb, tempOffset, 0, "TLV too short");
1578 /* Get LCI length */
1579 tempByte = tvb_get_guint8(tvb, tempOffset);
1581 if (tempByte > tlvLen)
1584 proto_tree_add_text(tree, tvb, tempOffset, 1, "LCI Length: %u (greater than TLV length)", tempByte);
1590 proto_tree_add_text(tree, tvb, tempOffset, 1, "LCI Length: %u", tempByte);
1592 LCI_Length = (guint32)tempByte;
1596 /* Get what value */
1599 proto_tree_add_text(tree, tvb, tempOffset, 0, "LCI Length too short");
1602 tempByte = tvb_get_guint8(tvb, tempOffset);
1604 proto_tree_add_text(tree, tvb, tempOffset, 1, "What: %s (%u)",
1605 val_to_str(tempByte,civic_address_what_values,"Unknown"),
1610 /* Get country code */
1613 proto_tree_add_text(tree, tvb, tempOffset, 0, "LCI Length too short");
1617 proto_tree_add_text(tree, tvb, tempOffset, 2, "Country: %s",
1618 tvb_format_text(tvb, tempOffset, 2));
1623 while (LCI_Length > 0)
1628 proto_tree_add_text(tree, tvb, tempOffset, 0, "LCI Length too short");
1631 tempByte = tvb_get_guint8(tvb, tempOffset);
1633 proto_tree_add_text(tree, tvb, tempOffset, 1, "CA Type: %s (%u)",
1634 val_to_str(tempByte,civic_address_type_values,"Unknown"),
1643 proto_tree_add_text(tree, tvb, tempOffset, 0, "LCI Length too short");
1646 tempByte = tvb_get_guint8(tvb, tempOffset);
1648 proto_tree_add_text(tree, tvb, tempOffset, 1, "CA Length: %u", tempByte);
1653 /* Make sure the CA value is within the specified length */
1654 if (tempByte > LCI_Length)
1661 proto_tree_add_text(tree, tvb, tempOffset, tempByte, "CA Value: %s",
1662 tvb_format_stringzpad(tvb, tempOffset, tempByte));
1664 tempOffset += tempByte;
1665 LCI_Length -= tempByte;
1671 case 3: /* ECS ELIN */
1676 proto_tree_add_text(tree, tvb, tempOffset, tlvLen, "ELIN: %s",
1677 tvb_format_stringzpad(tvb, tempOffset, tlvLen));
1687 case 4: /* Extended Power-via-MDI */
1689 /* Get first byte */
1690 tempByte = tvb_get_guint8(tvb, tempOffset);
1692 /* Determine power type */
1693 subType = ((tempByte & 0xC0) >> 6);
1695 proto_tree_add_text(tree, tvb, tempOffset, 1, "%s %s",
1696 decode_boolean_bitfield(tempByte, 0xC0, 8, "Power Type:", "Power Type:"),
1697 val_to_str(subType, media_power_type, "Unknown"));
1699 /* Determine power source */
1704 subType = ((tempByte & 0x30) >> 4);
1705 strPtr = val_to_str(subType, media_power_pse_device, "Reserved");
1711 subType = ((tempByte & 0x30) >> 4);
1712 strPtr = val_to_str(subType, media_power_pd_device, "Reserved");
1723 proto_tree_add_text(tree, tvb, tempOffset, 1, "%s %s",
1724 decode_boolean_bitfield(tempByte, 0x30, 8, "Power Source:", "Power Source:"),
1727 /* Determine power priority */
1728 subType = (tempByte & 0x0F);
1730 proto_tree_add_text(tree, tvb, tempOffset, 1, "%s %s",
1731 decode_boolean_bitfield(tempByte, 0x0F, 8, "Power Priority:", "Power Priority:"),
1732 val_to_str(subType, media_power_priority, "Reserved"));
1736 /* Get power value */
1737 tempShort = tvb_get_ntohs(tvb, tempOffset);
1739 proto_tree_add_text(tree, tvb, tempOffset, 2, "Power Value: %u", tempShort);
1743 case 5: /* Hardware Revision */
1745 /* Figure out the length of the hardware revision field */
1749 proto_tree_add_text(tree, tvb, tempOffset, tlvLen, "Hardware Revision: %s",
1750 tvb_format_stringzpad(tvb, tempOffset, tlvLen));
1755 case 6: /* Firmware Revision */
1757 /* Figure out the length of the firmware revision field */
1761 proto_tree_add_text(tree, tvb, tempOffset, tlvLen, "Firmware Revision: %s",
1762 tvb_format_stringzpad(tvb, tempOffset, tlvLen));
1767 case 7: /* Software Revision */
1769 /* Figure out the length of the software revision field */
1773 proto_tree_add_text(tree, tvb, tempOffset, tlvLen, "Software Revision: %s",
1774 tvb_format_stringzpad(tvb, tempOffset, tlvLen));
1779 case 8: /* Serial Number */
1781 /* Figure out the length of the serial number field */
1785 proto_tree_add_text(tree, tvb, tempOffset, tlvLen, "Serial Number: %s",
1786 tvb_format_stringzpad(tvb, tempOffset, tlvLen));
1791 case 9: /* Manufacturer Name */
1793 /* Figure out the length of the manufacturer name field */
1797 proto_tree_add_text(tree, tvb, tempOffset, tlvLen, "Manufacturer Name: %s",
1798 tvb_format_stringzpad(tvb, tempOffset, tlvLen));
1803 case 10: /* Model Name */
1805 /* Figure out the length of the model name field */
1809 proto_tree_add_text(tree, tvb, tempOffset, tlvLen, "Model Name: %s",
1810 tvb_format_stringzpad(tvb, tempOffset, tlvLen));
1815 case 11: /* Asset ID */
1817 /* Figure out the length of the asset id field */
1821 proto_tree_add_text(tree, tvb, tempOffset, tlvLen, "Asset ID: %s",
1822 tvb_format_stringzpad(tvb, tempOffset, tlvLen));
1832 /* Dissect Organizational Specific TLV */
1834 dissect_organizational_specific_tlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
1841 const char *subTypeStr;
1843 proto_tree *org_tlv_tree = NULL;
1844 proto_item *tf = NULL;
1846 /* Get tlv type and length */
1847 tempShort = tvb_get_ntohs(tvb, offset);
1849 /* Get tlv length */
1850 tempLen = TLV_INFO_LEN(tempShort);
1853 oui = tvb_get_ntoh24(tvb, (offset+2));
1854 subType = tvb_get_guint8(tvb, (offset+5));
1856 ouiStr = val_to_str(oui, tlv_oui_subtype_vals, "Unknown");
1859 case OUI_IEEE_802_1:
1860 subTypeStr = val_to_str(subType, ieee_802_1_subtypes, "Unknown");
1862 case OUI_IEEE_802_3:
1863 subTypeStr = val_to_str(subType, ieee_802_3_subtypes, "Unknown");
1865 case OUI_MEDIA_ENDPOINT:
1866 subTypeStr = val_to_str(subType, media_subtypes, "Unknown");
1869 subTypeStr = "Unknown";
1875 tf = proto_tree_add_text(tree, tvb, offset, (tempLen + 2), "%s - %s",
1876 ouiStr, subTypeStr);
1877 org_tlv_tree = proto_item_add_subtree(tf, ett_org_spc_tlv);
1879 proto_tree_add_item(org_tlv_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
1884 proto_tree_add_uint_format(org_tlv_tree, hf_lldp_tlv_len, tvb, offset, 2,
1885 tempShort, "TLV Length: %u (too short, must be >= 4)", tempLen);
1887 return (tempLen + 2);
1891 proto_tree_add_item(org_tlv_tree, hf_lldp_tlv_len, tvb, offset, 2, FALSE);
1893 /* Display organizational unique id */
1894 proto_tree_add_uint(org_tlv_tree, hf_org_spc_oui, tvb, (offset+2), 3, oui);
1899 case OUI_IEEE_802_1:
1900 dissect_ieee_802_1_tlv(tvb, pinfo, org_tlv_tree, (offset+5));
1902 case OUI_IEEE_802_3:
1903 dissect_ieee_802_3_tlv(tvb, pinfo, org_tlv_tree, (offset+5));
1905 case OUI_MEDIA_ENDPOINT:
1906 dissect_media_tlv(tvb, pinfo, org_tlv_tree, (offset+5), (tempLen-3));
1910 return (tempLen + 2);
1913 /* Dissect Unknown TLV */
1915 dissect_lldp_unknown_tlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
1920 proto_tree *unknown_tlv_tree = NULL;
1921 proto_item *tf = NULL;
1923 /* Get tlv type and length */
1924 tempShort = tvb_get_ntohs(tvb, offset);
1926 /* Get tlv length */
1927 tempLen = TLV_INFO_LEN(tempShort);
1931 tf = proto_tree_add_text(tree, tvb, offset, (tempLen + 2), "Unknown TLV");
1932 unknown_tlv_tree = proto_item_add_subtree(tf, ett_unknown_tlv);
1934 proto_tree_add_item(unknown_tlv_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
1935 proto_tree_add_item(unknown_tlv_tree, hf_lldp_tlv_len, tvb, offset, 2, FALSE);
1938 return (tempLen + 2);
1942 /* Dissect LLDP packets */
1944 dissect_lldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1947 proto_tree *lldp_tree = NULL;
1950 gint32 rtnValue = 0;
1953 gboolean reachedEnd = FALSE;
1955 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1956 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LLDP");
1958 /* Clear the information column on summary display */
1959 if (check_col(pinfo->cinfo, COL_INFO)) {
1960 col_clear(pinfo->cinfo, COL_INFO);
1965 ti = proto_tree_add_item(tree, proto_lldp, tvb, offset, -1, FALSE);
1966 lldp_tree = proto_item_add_subtree(ti, ett_lldp);
1969 /* Get chassis id tlv */
1970 rtnValue = dissect_lldp_chassis_id(tvb, pinfo, lldp_tree, offset);
1973 if (check_col(pinfo->cinfo, COL_INFO))
1974 col_set_str(pinfo->cinfo, COL_INFO, "Invalid Chassis ID TLV");
1981 /* Get port id tlv */
1982 rtnValue = dissect_lldp_port_id(tvb, pinfo, lldp_tree, offset);
1985 if (check_col(pinfo->cinfo, COL_INFO))
1986 col_set_str(pinfo->cinfo, COL_INFO, "Invalid Port ID TLV");
1993 /* Get time to live tlv */
1994 rtnValue = dissect_lldp_time_to_live(tvb, pinfo, lldp_tree, offset);
1997 if (check_col(pinfo->cinfo, COL_INFO))
1998 col_set_str(pinfo->cinfo, COL_INFO, "Invalid Time-to-Live TLV");
2005 /* Dissect optional tlv's until end-of-lldpdu is reached */
2008 tempShort = tvb_get_ntohs(tvb, offset);
2009 tempType = TLV_TYPE(tempShort);
2013 case CHASSIS_ID_TLV_TYPE:
2014 rtnValue = dissect_lldp_chassis_id(tvb, pinfo, lldp_tree, offset);
2015 rtnValue = -1; /* Duplicate chassis id tlv */
2016 if (check_col(pinfo->cinfo, COL_INFO))
2017 col_set_str(pinfo->cinfo, COL_INFO, "Duplicate Chassis ID TLV");
2019 case PORT_ID_TLV_TYPE:
2020 rtnValue = dissect_lldp_port_id(tvb, pinfo, lldp_tree, offset);
2021 rtnValue = -1; /* Duplicate port id tlv */
2022 if (check_col(pinfo->cinfo, COL_INFO))
2023 col_set_str(pinfo->cinfo, COL_INFO, "Duplicate Port ID TLV");
2025 case TIME_TO_LIVE_TLV_TYPE:
2026 rtnValue = dissect_lldp_time_to_live(tvb, pinfo, lldp_tree, offset);
2027 rtnValue = -1; /* Duplicate time-to-live tlv */
2028 if (check_col(pinfo->cinfo, COL_INFO))
2029 col_set_str(pinfo->cinfo, COL_INFO, "Duplicate Time-To-Live TLV");
2031 case END_OF_LLDPDU_TLV_TYPE:
2032 rtnValue = dissect_lldp_end_of_lldpdu(tvb, pinfo, lldp_tree, offset);
2034 case PORT_DESCRIPTION_TLV_TYPE:
2035 rtnValue = dissect_lldp_port_desc(tvb, pinfo, lldp_tree, offset);
2037 case SYSTEM_NAME_TLV_TYPE:
2038 case SYSTEM_DESCRIPTION_TLV_TYPE:
2039 rtnValue = dissect_lldp_system_name(tvb, pinfo, lldp_tree, offset);
2041 case SYSTEM_CAPABILITIES_TLV_TYPE:
2042 rtnValue = dissect_lldp_system_capabilities(tvb, pinfo, lldp_tree, offset);
2044 case MANAGEMENT_ADDR_TLV_TYPE:
2045 rtnValue = dissect_lldp_management_address(tvb, pinfo, lldp_tree, offset);
2047 case ORGANIZATION_SPECIFIC_TLV_TYPE:
2048 rtnValue = dissect_organizational_specific_tlv(tvb, pinfo, lldp_tree, offset);
2051 rtnValue = dissect_lldp_unknown_tlv(tvb, pinfo, lldp_tree, offset);
2063 /* Register the protocol with Ethereal */
2065 proto_register_lldp(void)
2067 /* Setup list of header fields */
2068 static hf_register_info hf[] = {
2069 { &hf_lldp_tlv_type,
2070 { "TLV Type", "lldp.tlv.type", FT_UINT16, BASE_DEC,
2071 VALS(tlv_types), TLV_TYPE_MASK, "", HFILL }
2074 { "TLV Length", "lldp.tlv.len", FT_UINT16, BASE_DEC,
2075 NULL, TLV_INFO_LEN_MASK, "", HFILL }
2077 { &hf_chassis_id_subtype,
2078 { "Chassis Id Subtype", "lldp.chassis.subtype", FT_UINT8, BASE_DEC,
2079 VALS(chassis_id_subtypes), 0, "", HFILL }
2082 { "Chassis Id", "lldp.chassis.id", FT_BYTES, BASE_HEX,
2083 NULL, 0, "", HFILL }
2085 { &hf_chassis_id_mac,
2086 { "Chassis Id", "lldp.chassis.id.mac", FT_ETHER, BASE_NONE,
2087 NULL, 0, "", HFILL }
2089 { &hf_chassis_id_ip4,
2090 { "Chassis Id", "lldp.chassis.id.ip4", FT_IPv4, BASE_NONE,
2091 NULL, 0, "", HFILL }
2093 { &hf_chassis_id_ip6,
2094 { "Chassis Id", "lldp.chassis.id.ip6", FT_IPv6, BASE_NONE,
2095 NULL, 0, "", HFILL }
2097 { &hf_port_id_subtype,
2098 { "Port Id Subtype", "lldp.port.subtype", FT_UINT8, BASE_DEC,
2099 VALS(port_id_subtypes), 0, "", HFILL }
2102 { "Port Id", "lldp.port.id.mac", FT_ETHER, BASE_NONE,
2103 NULL, 0, "", HFILL }
2106 { "Port Id", "lldp.port.id.ip4", FT_IPv4, BASE_NONE,
2107 NULL, 0, "", HFILL }
2110 { "Port Id", "lldp.port.id.ip6", FT_IPv6, BASE_NONE,
2111 NULL, 0, "", HFILL }
2114 { "Seconds", "lldp.time_to_live", FT_UINT16, BASE_DEC,
2115 NULL, 0, "", HFILL }
2117 { &hf_mgn_addr_ipv4,
2118 { "Management Address", "lldp.mgn.addr.ip4", FT_IPv4, BASE_NONE,
2119 NULL, 0, "", HFILL }
2121 { &hf_mgn_addr_ipv6,
2122 { "Management Address", "lldp.mgn.addr.ip6", FT_IPv6, BASE_NONE,
2123 NULL, 0, "", HFILL }
2126 { "Management Address", "lldp.mgn.addr.hex", FT_BYTES, BASE_HEX,
2127 NULL, 0, "", HFILL }
2130 { "Object Identifier", "lldp.mgn.obj.id", FT_BYTES, BASE_HEX,
2131 NULL, 0, "", HFILL }
2134 { "Organization Unique Code", "lldp.orgtlv.oui", FT_UINT24, BASE_HEX,
2135 VALS(tlv_oui_subtype_vals), 0x0, "", HFILL }
2137 { &hf_ieee_802_1_subtype,
2138 { "IEEE 802.1 Subtype", "lldp.ieee.802_1.subtype", FT_UINT8, BASE_HEX,
2139 VALS(ieee_802_1_subtypes), 0x0, "", HFILL }
2141 { &hf_ieee_802_3_subtype,
2142 { "IEEE 802.3 Subtype", "lldp.ieee.802_3.subtype", FT_UINT8, BASE_HEX,
2143 VALS(ieee_802_3_subtypes), 0x0, "", HFILL }
2145 { &hf_media_tlv_subtype,
2146 { "Media Subtype", "lldp.media.subtype", FT_UINT8, BASE_HEX,
2147 VALS(media_subtypes), 0x0, "", HFILL }
2151 /* Setup protocol subtree array */
2152 static gint *ett[] = {
2158 &ett_port_description,
2161 &ett_system_cap_summary,
2162 &ett_system_cap_enabled,
2163 &ett_management_address,
2166 &ett_port_vlan_flags,
2169 &ett_802_3_aggregation,
2170 &ett_media_capabilities,
2173 /* Register the protocol name and description */
2174 proto_lldp = proto_register_protocol("Link Layer Discovery Protocol", "LLDP", "lldp");
2176 /* Required function calls to register the header fields and subtrees used */
2177 proto_register_field_array(proto_lldp, hf, array_length(hf));
2178 proto_register_subtree_array(ett, array_length(ett));
2182 proto_reg_handoff_lldp(void)
2184 dissector_handle_t lldp_handle;
2186 lldp_handle = create_dissector_handle(dissect_lldp,proto_lldp);
2187 dissector_add("ethertype", ETHERTYPE_LLDP, lldp_handle);