2 * Routines for LLDP dissection
3 * By Juan Gonzalez <juan.gonzalez@pikatech.com>
7 * Modified by: Brian Bogora <brian_bogora@mitel.com>
11 * Wireshark - Network traffic analyzer
12 * By Gerald Combs <gerald@wireshark.org>
13 * Copyright 1998 Gerald Combs
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
37 #include <epan/packet.h>
38 #include <epan/emem.h>
39 #include <epan/etypes.h>
44 #define END_OF_LLDPDU_TLV_TYPE 0x00 /* Mandatory */
45 #define CHASSIS_ID_TLV_TYPE 0x01 /* Mandatory */
46 #define PORT_ID_TLV_TYPE 0x02 /* Mandatory */
47 #define TIME_TO_LIVE_TLV_TYPE 0x03 /* Mandatory */
48 #define PORT_DESCRIPTION_TLV_TYPE 0x04
49 #define SYSTEM_NAME_TLV_TYPE 0x05
50 #define SYSTEM_DESCRIPTION_TLV_TYPE 0x06
51 #define SYSTEM_CAPABILITIES_TLV_TYPE 0x07
52 #define MANAGEMENT_ADDR_TLV_TYPE 0x08
53 #define ORGANIZATION_SPECIFIC_TLV_TYPE 0x7F
56 #define TLV_TYPE_MASK 0xFE00
57 #define TLV_TYPE(value) (((value) & TLV_TYPE_MASK) >> 9)
58 #define TLV_INFO_LEN_MASK 0x01FF
59 #define TLV_INFO_LEN(value) ((value) & TLV_INFO_LEN_MASK)
61 /* Initialize the protocol and registered fields */
62 static int proto_lldp = -1;
63 static int hf_lldp_tlv_type = -1;
64 static int hf_lldp_tlv_len = -1;
65 static int hf_chassis_id_subtype = -1;
66 static int hf_chassis_id = -1;
67 static int hf_chassis_id_mac = -1;
68 static int hf_chassis_id_ip4 = -1;
69 static int hf_chassis_id_ip6 = -1;
70 static int hf_port_id_subtype = -1;
71 static int hf_port_id_mac = -1;
72 static int hf_lldp_network_address_family = -1;
73 static int hf_port_id_ip4 = -1;
74 static int hf_port_id_ip6 = -1;
75 static int hf_time_to_live = -1;
76 static int hf_mgn_addr_ipv4 = -1;
77 static int hf_mgn_addr_ipv6 = -1;
78 static int hf_mgn_addr_hex = -1;
79 static int hf_mgn_obj_id = -1;
80 static int hf_org_spc_oui = -1;
81 static int hf_ieee_802_1_subtype = -1;
82 static int hf_ieee_802_3_subtype = -1;
83 static int hf_media_tlv_subtype = -1;
84 static int hf_profinet_tlv_subtype = -1;
85 static int hf_profinet_class2_port_status = -1;
86 static int hf_profinet_class3_port_status = -1;
87 static int hf_profinet_port_rx_delay_local = -1;
88 static int hf_profinet_port_rx_delay_remote = -1;
89 static int hf_profinet_port_tx_delay_local = -1;
90 static int hf_profinet_port_tx_delay_remote = -1;
91 static int hf_profinet_cable_delay_local = -1;
92 static int hf_profinet_mrp_domain_uuid = -1;
93 static int hf_profinet_mrrt_port_status = -1;
94 static int hf_profinet_cm_mac = -1;
95 static int hf_profinet_master_source_address = -1;
96 static int hf_profinet_subdomain_uuid = -1;
97 static int hf_profinet_ir_data_uuid = -1;
98 static int hf_profinet_length_of_period_valid = -1;
99 static int hf_profinet_length_of_period_length = -1;
100 static int hf_profinet_red_period_begin_valid = -1;
101 static int hf_profinet_red_period_begin_offset = -1;
102 static int hf_profinet_orange_period_begin_valid = -1;
103 static int hf_profinet_orange_period_begin_offset = -1;
104 static int hf_profinet_green_period_begin_valid = -1;
105 static int hf_profinet_green_period_begin_offset = -1;
106 static int hf_unknown_subtype = -1;
108 /* Initialize the subtree pointers */
109 static gint ett_lldp = -1;
110 static gint ett_chassis_id = -1;
111 static gint ett_port_id = -1;
112 static gint ett_time_to_live = -1;
113 static gint ett_end_of_lldpdu = -1;
114 static gint ett_port_description = -1;
115 static gint ett_system_name = -1;
116 static gint ett_system_cap = -1;
117 static gint ett_system_cap_summary = -1;
118 static gint ett_system_cap_enabled = -1;
119 static gint ett_management_address = -1;
120 static gint ett_unknown_tlv = -1;
121 static gint ett_org_spc_tlv = -1;
122 static gint ett_port_vlan_flags = -1;
123 static gint ett_802_3_flags = -1;
124 static gint ett_802_3_autoneg_advertised = -1;
125 static gint ett_802_3_power = -1;
126 static gint ett_802_3_aggregation = -1;
127 static gint ett_media_capabilities = -1;
128 static gint ett_profinet_period = -1;
130 static const value_string tlv_types[] = {
131 { END_OF_LLDPDU_TLV_TYPE, "End of LLDPDU"},
132 { CHASSIS_ID_TLV_TYPE, "Chassis Id"},
133 { PORT_ID_TLV_TYPE, "Port Id"},
134 { TIME_TO_LIVE_TLV_TYPE, "Time to Live"},
135 { PORT_DESCRIPTION_TLV_TYPE, "Port Description"},
136 { SYSTEM_NAME_TLV_TYPE, "System Name"},
137 { SYSTEM_DESCRIPTION_TLV_TYPE, "System Description"},
138 { SYSTEM_CAPABILITIES_TLV_TYPE, "System Capabilities"},
139 { MANAGEMENT_ADDR_TLV_TYPE, "Management Address"},
140 { ORGANIZATION_SPECIFIC_TLV_TYPE, "Organization Specific"},
144 static const value_string chassis_id_subtypes[] = {
146 { 1, "Chassis component"},
147 { 2, "Interface alias"},
148 { 3, "Port component"},
150 { 5, "Network address"},
151 { 6, "Interface name"},
152 { 7, "Locally assigned"},
156 static const value_string port_id_subtypes[] = {
158 { 1, "Interface alias"},
159 { 2, "Port component"},
161 { 4, "Network address"},
162 { 5, "Interface name"},
163 { 6, "Agent circuit Id"},
164 { 7, "Locally assigned"},
168 static const value_string interface_subtype_values[] = {
171 { 3, "System port number"},
175 static const value_string tlv_oui_subtype_vals[] = {
176 { OUI_IEEE_802_1, "IEEE 802.1" },
177 { OUI_IEEE_802_3, "IEEE 802.3" },
178 { OUI_MEDIA_ENDPOINT, "TIA" },
179 { OUI_PROFINET, "PROFINET" },
183 /* IEEE 802.1 Subtypes */
184 static const value_string ieee_802_1_subtypes[] = {
185 { 0x01, "Port VLAN ID" },
186 { 0x02, "Port and Protocol VLAN ID" },
187 { 0x03, "VLAN Name" },
188 { 0x04, "Protocol Identity" },
192 /* IEEE 802.3 Subtypes */
193 static const value_string ieee_802_3_subtypes[] = {
194 { 0x01, "MAC/PHY Configuration/Status" },
195 { 0x02, "Power Via MDI" },
196 { 0x03, "Link Aggregation" },
197 { 0x04, "Maximum Frame Size" },
202 static const value_string media_subtypes[] = {
203 { 1, "Media Capabilities" },
204 { 2, "Network Policy" },
205 { 3, "Location Identification" },
206 { 4, "Extended Power-via-MDI" },
207 { 5, "Inventory - Hardware Revision" },
208 { 6, "Inventory - Firmware Revision" },
209 { 7, "Inventory - Software Revision" },
210 { 8, "Inventory - Serial Number" },
211 { 9, "Inventory - Manufacturer Name" },
212 { 10, "Inventory - Model Name" },
213 { 11, "Inventory - Asset ID" },
217 /* Media Class Values */
218 static const value_string media_class_values[] = {
219 { 0, "Type Not Defined" },
220 { 1, "Endpoint Class I" },
221 { 2, "Endpoint Class II" },
222 { 3, "Endpoint Class III" },
223 { 4, "Network Connectivity" },
227 /* Media Application Types */
228 static const value_string media_application_type[] = {
231 { 2, "Voice Signaling" },
232 { 3, "Guest Voice" },
233 { 4, "Guest Voice Signaling" },
234 { 5, "Softphone Voice" },
235 { 6, "Video Conferencing" },
236 { 7, "Streaming Video" },
237 { 8, "Video Signaling" },
241 /* PROFINET subtypes */
242 static const value_string profinet_subtypes[] = {
243 { 1, "Measured Delay Values" },
244 { 2, "Port Status" },
246 { 4, "MRP Port Status" },
247 { 5, "Chassis MAC" },
248 { 6, "PTCP Status" },
252 /* 802.3 Power Type */
253 static const value_string power_type_802_3[] = {
262 static const value_string media_power_type[] = {
271 static const value_string media_power_priority[] = {
280 static const value_string media_power_pd_device[] = {
284 { 3, "PSE and Local" },
287 static const value_string media_power_pse_device[] = {
289 { 1, "Primary Power Source" },
290 { 2, "Backup Power Source" },
294 /* Location data format */
295 static const value_string location_data_format[] = {
297 { 1, "Coordinate-based LCI" },
298 { 2, "Civic Address LCI" },
303 /* Civic Address LCI - What field */
304 static const value_string civic_address_what_values[] = {
305 { 0, "Location of the DHCP server" },
306 { 1, "Location of the network element believed to be closest to the client" },
307 { 2, "Location of the client"},
311 /* Civic Address Type field */
312 static const value_string civic_address_type_values[] = {
314 { 1, "National subdivisions (province, state, etc)" },
315 { 2, "County, parish, district" },
316 { 3, "City, township" },
317 { 4, "City division, borough, ward" },
318 { 5, "Neighborhood, block" },
320 { 16, "Leading street direction" },
321 { 17, "Trailing street suffix" },
322 { 18, "Street suffix" },
323 { 19, "House number" },
324 { 20, "House number suffix" },
325 { 21, "Landmark or vanity address" },
326 { 22, "Additional location information" },
328 { 24, "Postal/ZIP code" },
332 { 28, "Room number" },
333 { 29, "Place type" },
339 * Define the text strings for the LLDP 802.3 MAC/PHY Configuration/Status
340 * Operational MAU Type field.
342 * These values are taken from the DESCRIPTION field of the dot3MauType
343 * objects defined in RFC 3636 (or subsequent revisions).
346 static const value_string operational_mau_type_values[] = {
347 { 1, "AUI - no internal MAU, view from AUI" },
348 { 2, "10Base5 - thick coax MAU" },
349 { 3, "Foirl - FOIRL MAU" },
350 { 4, "10Base2 - thin coax MAU" },
351 { 5, "10BaseT - UTP MAU" },
352 { 6, "10BaseFP - passive fiber MAU" },
353 { 7, "10BaseFB - sync fiber MAU" },
354 { 8, "10BaseFL - async fiber MAU" },
355 { 9, "10Broad36 - broadband DTE MAU" },
356 { 10, "10BaseTHD - UTP MAU, half duplex mode" },
357 { 11, "10BaseTFD - UTP MAU, full duplex mode" },
358 { 12, "10BaseFLHD - async fiber MAU, half duplex mode" },
359 { 13, "10BaseFLDF - async fiber MAU, full duplex mode" },
360 { 14, "10BaseT4 - 4 pair category 3 UTP" },
361 { 15, "100BaseTXHD - 2 pair category 5 UTP, half duplex mode" },
362 { 16, "100BaseTXFD - 2 pair category 5 UTP, full duplex mode" },
363 { 17, "100BaseFXHD - X fiber over PMT, half duplex mode" },
364 { 18, "100BaseFXFD - X fiber over PMT, full duplex mode" },
365 { 19, "100BaseT2HD - 2 pair category 3 UTP, half duplex mode" },
366 { 20, "100BaseT2DF - 2 pair category 3 UTP, full duplex mode" },
367 { 21, "1000BaseXHD - PCS/PMA, unknown PMD, half duplex mode" },
368 { 22, "1000BaseXFD - PCS/PMA, unknown PMD, full duplex mode" },
369 { 23, "1000BaseLXHD - Fiber over long-wavelength laser, half duplex mode" },
370 { 24, "1000BaseLXFD - Fiber over long-wavelength laser, full duplex mode" },
371 { 25, "1000BaseSXHD - Fiber over short-wavelength laser, half duplex mode" },
372 { 26, "1000BaseSXFD - Fiber over short-wavelength laser, full duplex mode" },
373 { 27, "1000BaseCXHD - Copper over 150-Ohm balanced cable, half duplex mode" },
374 { 28, "1000BaseCXFD - Copper over 150-Ohm balanced cable, full duplex mode" },
375 { 29, "1000BaseTHD - Four-pair Category 5 UTP, half duplex mode" },
376 { 30, "1000BaseTFD - Four-pair Category 5 UTP, full duplex mode" },
377 { 31, "10GigBaseX - X PCS/PMA, unknown PMD." },
378 { 32, "10GigBaseLX4 - X fiber over WWDM optics" },
379 { 33, "10GigBaseR - R PCS/PMA, unknown PMD." },
380 { 34, "10GigBaseER - R fiber over 1550 nm optics" },
381 { 35, "10GigBaseLR - R fiber over 1310 nm optics" },
382 { 36, "10GigBaseSR - R fiber over 850 nm optics" },
383 { 37, "10GigBaseW - W PCS/PMA, unknown PMD." },
384 { 38, "10GigBaseEW - W fiber over 1550 nm optics" },
385 { 39, "10GigBaseLW - W fiber over 1310 nm optics" },
386 { 40, "10GigBaseSW - W fiber over 850 nm optics" },
390 /* System Capabilities */
391 #define SYSTEM_CAPABILITY_OTHER 0x0001
392 #define SYSTEM_CAPABILITY_REPEATER 0x0002
393 #define SYSTEM_CAPABILITY_BRIDGE 0x0004
394 #define SYSTEM_CAPABILITY_WLAN 0x0008
395 #define SYSTEM_CAPABILITY_ROUTER 0x0010
396 #define SYSTEM_CAPABILITY_TELEPHONE 0x0020
397 #define SYSTEM_CAPABILITY_DOCSIS 0x0040
398 #define SYSTEM_CAPABILITY_STATION 0x0080
400 /* Media Capabilities */
401 #define MEDIA_CAPABILITY_LLDP 0x0001
402 #define MEDIA_CAPABILITY_NETWORK_POLICY 0x0002
403 #define MEDIA_CAPABILITY_LOCATION_ID 0x0004
404 #define MEDIA_CAPABILITY_MDI_PSE 0x0008
405 #define MEDIA_CAPABILITY_MDI_PD 0x0010
406 #define MEDIA_CAPABILITY_INVENTORY 0x0020
409 * Define constants for the LLDP 802.3 MAC/PHY Configuration/Status
410 * PMD Auto-Negotiation Advertised Capability field.
411 * These values are taken from the ifMauAutoNegCapAdvertisedBits
412 * object defined in RFC 3636.
415 #define AUTONEG_OTHER 0x8000 /* bOther(0), -- other or unknown */
416 #define AUTONEG_10BASE_T 0x4000 /* b10baseT(1), -- 10BASE-T half duplex mode */
417 #define AUTONEG_10BASET_FD 0x2000 /* b10baseTFD(2), -- 10BASE-T full duplex mode */
418 #define AUTONEG_100BASE_T4 0x1000 /* b100baseT4(3), -- 100BASE-T4 */
419 #define AUTONEG_100BASE_TX 0x0800 /* b100baseTX(4), -- 100BASE-TX half duplex mode */
420 #define AUTONEG_100BASE_TXFD 0x0400 /* b100baseTXFD(5), -- 100BASE-TX full duplex mode */
421 #define AUTONEG_100BASE_T2 0x0200 /* b100baseT2(6), -- 100BASE-T2 half duplex mode */
422 #define AUTONEG_100BASE_T2FD 0x0100 /* b100baseT2FD(7), -- 100BASE-T2 full duplex mode */
423 #define AUTONEG_FDX_PAUSE 0x0080 /* bFdxPause(8), -- PAUSE for full-duplex links */
424 #define AUTONEG_FDX_APAUSE 0x0040 /* bFdxAPause(9), -- Asymmetric PAUSE for full-duplex links */
425 #define AUTONEG_FDX_SPAUSE 0x0020 /* bFdxSPause(10), -- Symmetric PAUSE for full-duplex links */
426 #define AUTONEG_FDX_BPAUSE 0x0010 /* bFdxBPause(11), -- Asymmetric and Symmetric PAUSE for full-duplex links */
427 #define AUTONEG_1000BASE_X 0x0008 /* b1000baseX(12), -- 1000BASE-X, -LX, -SX, -CX half duplex mode */
428 #define AUTONEG_1000BASE_XFD 0x0004 /* b1000baseXFD(13), -- 1000BASE-X, -LX, -SX, -CX full duplex mode */
429 #define AUTONEG_1000BASE_T 0x0002 /* b1000baseT(14), -- 1000BASE-T half duplex mode */
430 #define AUTONEG_1000BASE_TFD 0x0001 /* b1000baseTFD(15) -- 1000BASE-T full duplex mode */
432 /* Some vendors interpreted the standard to invert the bitorder:
433 * according to a IEEE ruling, this is now officially wrong.
434 * See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=1455
435 * for all the gory details
438 #define INV_AUTONEG_OTHER 0x0001 /* bOther(0), -- other or unknown */
439 #define INV_AUTONEG_10BASE_T 0x0002 /* b10baseT(1), -- 10BASE-T half duplex mode */
440 #define INV_AUTONEG_10BASET_FD 0x0004 /* b10baseTFD(2), -- 10BASE-T full duplex mode */
441 #define INV_AUTONEG_100BASE_T4 0x0008 /* b100baseT4(3), -- 100BASE-T4 */
442 #define INV_AUTONEG_100BASE_TX 0x0010 /* b100baseTX(4), -- 100BASE-TX half duplex mode */
443 #define INV_AUTONEG_100BASE_TXFD 0x0020 /* b100baseTXFD(5), -- 100BASE-TX full duplex mode */
444 #define INV_AUTONEG_100BASE_T2 0x0040 /* b100baseT2(6), -- 100BASE-T2 half duplex mode */
445 #define INV_AUTONEG_100BASE_T2FD 0x0080 /* b100baseT2FD(7), -- 100BASE-T2 full duplex mode */
446 #define INV_AUTONEG_FDX_PAUSE 0x0100 /* bFdxPause(8), -- PAUSE for full-duplex links */
447 #define INV_AUTONEG_FDX_APAUSE 0x0200 /* bFdxAPause(9), -- Asymmetric PAUSE for full-duplex links */
448 #define INV_AUTONEG_FDX_SPAUSE 0x0400 /* bFdxSPause(10), -- Symmetric PAUSE for full-duplex links */
449 #define INV_AUTONEG_FDX_BPAUSE 0x0800 /* bFdxBPause(11), -- Asymmetric and Symmetric PAUSE for full-duplex links */
450 #define INV_AUTONEG_1000BASE_X 0x1000 /* b1000baseX(12), -- 1000BASE-X, -LX, -SX, -CX half duplex mode */
451 #define INV_AUTONEG_1000BASE_XFD 0x2000 /* b1000baseXFD(13), -- 1000BASE-X, -LX, -SX, -CX full duplex mode */
452 #define INV_AUTONEG_1000BASE_T 0x4000 /* b1000baseT(14), -- 1000BASE-T half duplex mode */
453 #define INV_AUTONEG_1000BASE_TFD 0x8000 /* b1000baseTFD(15) -- 1000BASE-T full duplex mode */
455 #define MAX_MAC_LEN 6
458 static const value_string profinet_port2_status_vals[] = {
460 { 1, "SYNCDATA_LOADED" },
461 { 2, "RTCLASS2_UP" },
463 /* all other bits reserved */
467 static const value_string profinet_port3_status_vals[] = {
469 { 1, "IRDATA_LOADED" },
470 { 2, "RTCLASS3_UP" },
471 { 3, "RTCLASS3_DOWN" },
472 { 4, "RTCLASS3_RUN" },
473 /* all other bits reserved */
477 static const value_string profinet_mrrt_port_status_vals[] = {
479 { 1, "MRRT_CONFIGURED" },
481 /* all other bits reserved */
485 /* Calculate Latitude and Longitude string */
488 option = 0 -> Latitude
489 option = 1 -> Longitude
492 get_latitude_or_longitude(int option, guint64 value)
494 guint64 tempValue = value;
495 gboolean negativeNum = FALSE;
496 guint32 integerPortion = 0;
497 const char *direction;
499 /* The latitude and longitude are 34 bit fixed point value consisting
500 of 9 bits of integer and 25 bits of fraction.
501 When option is equal to 0, positive numbers are represent a location
502 north of the equator and negative (2s complement) numbers are south of the equator.
503 When option is equal to 1, positive values are east of the prime
504 meridian and negative (2s complement) numbers are west of the prime meridian.
507 if (value & G_GINT64_CONSTANT(0x0000000200000000))
509 /* Have a negative number (2s complement) */
516 /* Get the integer portion */
517 integerPortion = (guint32)((tempValue & G_GINT64_CONSTANT(0x00000003FE000000)) >> 25);
519 /* Calculate decimal portion (using 25 bits for fraction) */
520 tempValue = (tempValue & G_GINT64_CONSTANT(0x0000000001FFFFFF))/33554432;
524 /* Latitude - north/south directions */
532 /* Longitude - east/west directions */
539 return ep_strdup_printf("%u.%04" G_GINT64_MODIFIER "u degrees %s",
540 integerPortion, tempValue, direction);
543 /* Dissect Chassis Id TLV (Mandatory) */
545 dissect_lldp_chassis_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
550 const char *strPtr=NULL;
551 guint8 incorrectLen = 0; /* incorrect length if 1 */
553 const guint8 *mac_addr = NULL;
555 struct e_in6_addr ip6_addr;
556 guint8 addr_family = 0;
558 proto_tree *chassis_tree = NULL;
559 proto_item *tf = NULL;
562 tempShort = tvb_get_ntohs(tvb, offset);
563 tempType = TLV_TYPE(tempShort);
564 if (tempType != CHASSIS_ID_TLV_TYPE)
568 tf = proto_tree_add_text(tree, tvb, offset, 2, "Invalid Chassis ID (0x%02X)", tempType);
569 chassis_tree = proto_item_add_subtree(tf, ett_chassis_id);
570 proto_tree_add_text(chassis_tree, tvb, offset, 2, "%s Invalid Chassis ID (%u)",
571 decode_boolean_bitfield(tempType, TLV_TYPE_MASK, 16, "", ""), tempType);
578 tempLen = TLV_INFO_LEN(tempShort);
583 tf = proto_tree_add_text(tree, tvb, offset, 2, "Invalid Chassis ID Length (%u)", tempLen);
584 chassis_tree = proto_item_add_subtree(tf, ett_chassis_id);
585 proto_tree_add_item(chassis_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
586 proto_tree_add_text(chassis_tree, tvb, offset, 2, "%s Invalid Length: %u",
587 decode_boolean_bitfield(tempLen, TLV_INFO_LEN_MASK, 16, "", ""), tempLen);
593 /* Get tlv subtype */
594 tempType = tvb_get_guint8(tvb, (offset+2));
598 case 4: /* MAC address */
602 incorrectLen = 1; /* Invalid length */
606 mac_addr=tvb_get_ptr(tvb, (offset+3), 6);
607 strPtr = ether_to_str(mac_addr);
611 case 5: /* Network address */
613 /* Get network address family */
614 addr_family = tvb_get_guint8(tvb,offset+3);
615 /* Check for IPv4 or IPv6 */
619 ip_addr = tvb_get_ipv4(tvb, (offset+4));
620 strPtr = ip_to_str((guint8 *)&ip_addr);
622 incorrectLen = 1; /* Invalid length */
627 tvb_get_ipv6(tvb, (offset+4), &ip6_addr);
628 strPtr = ip6_to_str(&ip6_addr);
630 incorrectLen = 1; /* Invalid length */
634 strPtr = tvb_bytes_to_str(tvb, (offset+4), (tempLen-2));
639 case 2: /* Interface alias */
640 case 6: /* Interface name */
641 case 7: /* Locally assigned */
645 incorrectLen = 1; /* Invalid length */
649 strPtr = tvb_format_stringzpad(tvb, (offset+3), (tempLen-1));
653 case 1: /* Chassis component */
654 case 3: /* Port component */
658 incorrectLen = 1; /* Invalid length */
662 strPtr = tvb_bytes_to_str(tvb, (offset+3), (tempLen-1));
665 default: /* Reserved types */
669 incorrectLen = 1; /* Invalid length */
679 if (incorrectLen == 1)
683 tf = proto_tree_add_text(tree, tvb, offset, 2, "Invalid Chassis ID Length (%u)", tempLen);
684 chassis_tree = proto_item_add_subtree(tf, ett_chassis_id);
685 proto_tree_add_item(chassis_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
686 proto_tree_add_text(chassis_tree, tvb, offset, 2, "%s Invalid Length: %u",
687 decode_boolean_bitfield(tempLen, TLV_INFO_LEN_MASK, 16, "", ""), tempLen);
688 /* Get chassis id subtype */
689 proto_tree_add_item(chassis_tree, hf_chassis_id_subtype, tvb, (offset+2), 1, FALSE);
696 if (check_col(pinfo->cinfo, COL_INFO))
697 col_add_fstr(pinfo->cinfo, COL_INFO, "Chassis Id = %s ", strPtr);
701 /* Set chassis tree */
702 tf = proto_tree_add_text(tree, tvb, offset, (tempLen + 2), "Chassis Subtype = %s",
703 val_to_str(tempType, chassis_id_subtypes, "Reserved" ));
704 chassis_tree = proto_item_add_subtree(tf, ett_chassis_id);
706 proto_tree_add_item(chassis_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
707 proto_tree_add_item(chassis_tree, hf_lldp_tlv_len, tvb, offset, 2, FALSE);
709 /* Get chassis id subtype */
710 proto_tree_add_item(chassis_tree, hf_chassis_id_subtype, tvb, (offset+2), 1, FALSE);
715 case 4: /* MAC address */
716 proto_tree_add_ether(chassis_tree, hf_chassis_id_mac, tvb, (offset+3), 6, mac_addr);
717 proto_item_append_text(tf, ", Id: %s", strPtr);
719 case 5: /* Network address */
720 proto_tree_add_item(chassis_tree, hf_lldp_network_address_family, tvb, offset+3, 1, FALSE);
723 proto_tree_add_ipv4(chassis_tree, hf_chassis_id_ip4, tvb, (offset+4), 4, ip_addr);
726 proto_tree_add_ipv6(chassis_tree, hf_chassis_id_ip6, tvb, (offset+4), 16, ip6_addr.bytes);
729 proto_tree_add_text(chassis_tree, tvb, (offset+4), (tempLen-2), "Chassis Id: %s", strPtr);
733 case 2: /* Interface alias */
734 case 6: /* Interface name */
735 case 7: /* Locally assigned */
736 proto_tree_add_text(chassis_tree, tvb, (offset+3), (tempLen-1), "Chassis Id: %s", strPtr);
737 proto_item_append_text(tf, ", Id: %s", strPtr);
739 case 1: /* Chassis component */
740 case 3: /* Port component */
741 proto_tree_add_item(chassis_tree, hf_chassis_id, tvb, (offset+3), (tempLen-1), FALSE);
746 return (tempLen + 2);
749 /* Dissect Port Id TLV (Mandatory) */
751 dissect_lldp_port_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
757 const guint8 *mac_addr = NULL;
759 struct e_in6_addr ip6_addr;
760 guint8 addr_family = 0;
762 proto_tree *port_tree = NULL;
763 proto_item *tf = NULL;
766 tempShort = tvb_get_ntohs(tvb, offset);
767 tempType = TLV_TYPE(tempShort);
768 if (tempType != PORT_ID_TLV_TYPE)
771 /* Get tlv length and subtype */
772 tempLen = TLV_INFO_LEN(tempShort);
773 tempType = tvb_get_guint8(tvb, (offset+2));
778 case 3: /* MAC address */
781 return -1; /* Invalid port id */
783 mac_addr=tvb_get_ptr(tvb, (offset+3), 6);
784 strPtr = ether_to_str(mac_addr);
788 case 4: /* Network address */
790 /* Get network address family */
791 addr_family = tvb_get_guint8(tvb,offset+3);
792 /* Check for IPv4 or IPv6 */
796 ip_addr = tvb_get_ipv4(tvb, (offset+4));
797 strPtr = ip_to_str((guint8 *)&ip_addr);
804 tvb_get_ipv6(tvb, (offset+4), &ip6_addr);
805 strPtr = ip6_to_str(&ip6_addr);
807 return -1; /* Invalid chassis id */
811 strPtr = tvb_bytes_to_str(tvb, (offset+4), (tempLen-2));
818 strPtr = tvb_format_stringzpad(tvb, (offset+3), (tempLen-1));
824 if (check_col(pinfo->cinfo, COL_INFO))
825 col_append_fstr(pinfo->cinfo, COL_INFO, "Port Id = %s ", strPtr);
830 tf = proto_tree_add_text(tree, tvb, offset, (tempLen + 2), "Port Subtype = %s",
831 val_to_str(tempType, port_id_subtypes, "Unknown" ));
832 port_tree = proto_item_add_subtree(tf, ett_port_id);
834 proto_tree_add_item(port_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
835 proto_tree_add_item(port_tree, hf_lldp_tlv_len, tvb, offset, 2, FALSE);
837 /* Get port id subtype */
838 proto_tree_add_item(port_tree, hf_port_id_subtype, tvb, (offset+2), 1, FALSE);
841 /*proto_tree_add_text(port_tree, tvb, (offset+3), (tempLen-1), "Port Id: %s", strPtr);*/
844 case 3: /* MAC address */
845 proto_tree_add_ether(port_tree, hf_port_id_mac, tvb, (offset+3), 6, mac_addr);
847 case 4: /* Network address */
849 * networkAddress is an octet string that identifies a particular network address family
850 * and an associated network address that are encoded in network octet order.
852 /* Network address family */
853 proto_tree_add_item(port_tree, hf_lldp_network_address_family, tvb, offset+3, 1, FALSE);
856 proto_tree_add_ipv4(port_tree, hf_port_id_ip4, tvb, (offset+4), 4, ip_addr);
859 proto_tree_add_ipv6(port_tree, hf_port_id_ip6, tvb, (offset+4), 16, ip6_addr.bytes);
862 proto_tree_add_text(port_tree, tvb, (offset+4), (tempLen-2), "Port Id: %s", strPtr);
867 proto_tree_add_text(port_tree, tvb, (offset+3), (tempLen-1), "Port Id: %s", strPtr);
868 proto_item_append_text(tf, ", Id: %s", strPtr);
874 return (tempLen + 2);
877 /* Dissect Time To Live TLV (Mandatory) */
879 dissect_lldp_time_to_live(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
885 proto_tree *time_to_live_tree = NULL;
886 proto_item *tf = NULL;
889 tempShort = tvb_get_ntohs(tvb, offset);
890 tempType = TLV_TYPE(tempShort);
891 if (tempType != TIME_TO_LIVE_TLV_TYPE)
894 /* Get tlv length and seconds field */
895 tempLen = TLV_INFO_LEN(tempShort);
896 tempShort = tvb_get_ntohs(tvb, (offset+2));
898 if (check_col(pinfo->cinfo, COL_INFO))
899 col_append_fstr(pinfo->cinfo, COL_INFO, "TTL = %u ", tempShort);
904 tf = proto_tree_add_text(tree, tvb, offset, (tempLen + 2), "Time To Live = %u sec", tempShort);
905 time_to_live_tree = proto_item_add_subtree(tf, ett_time_to_live);
907 proto_tree_add_item(time_to_live_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
908 proto_tree_add_item(time_to_live_tree, hf_lldp_tlv_len, tvb, offset, 2, FALSE);
910 /* Display time to live information */
911 proto_tree_add_item(time_to_live_tree, hf_time_to_live, tvb, (offset+2), 2, FALSE);
914 return (tempLen + 2);
917 /* Dissect End of LLDPDU TLV (Mandatory) */
919 dissect_lldp_end_of_lldpdu(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint32 offset)
924 proto_tree *end_of_lldpdu_tree = NULL;
925 proto_item *tf = NULL;
927 /* Get tlv type and length */
928 tempShort = tvb_get_ntohs(tvb, offset);
931 tempLen = TLV_INFO_LEN(tempShort);
936 tf = proto_tree_add_text(tree, tvb, offset, (tempLen + 2), "End of LLDPDU");
937 end_of_lldpdu_tree = proto_item_add_subtree(tf, ett_end_of_lldpdu);
939 proto_tree_add_item(end_of_lldpdu_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
940 proto_tree_add_item(end_of_lldpdu_tree, hf_lldp_tlv_len, tvb, offset, 2, FALSE);
943 return -1; /* Force the lldp dissector to terminate */
946 /* Dissect Port Description TLV */
948 dissect_lldp_port_desc(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint32 offset)
954 proto_tree *port_desc_tree = NULL;
955 proto_item *tf = NULL;
957 /* Get tlv type and length */
958 tempShort = tvb_get_ntohs(tvb, offset);
961 tempLen = TLV_INFO_LEN(tempShort);
965 strPtr = tvb_format_stringzpad(tvb, (offset+2), tempLen);
968 tf = proto_tree_add_text(tree, tvb, offset, (tempLen + 2), "Port Description = %s", strPtr);
969 port_desc_tree = proto_item_add_subtree(tf, ett_port_description);
971 proto_tree_add_item(port_desc_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
972 proto_tree_add_item(port_desc_tree, hf_lldp_tlv_len, tvb, offset, 2, FALSE);
974 /* Display port description information */
975 proto_tree_add_text(port_desc_tree, tvb, (offset+2), tempLen, "Port Description: %s",
979 return (tempLen + 2);
982 /* Dissect System Name and description TLV */
984 dissect_lldp_system_name(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint32 offset)
991 proto_tree *system_name_tree = NULL;
992 proto_item *tf = NULL;
994 /* Get tlv type and length */
995 tempShort = tvb_get_ntohs(tvb, offset);
996 tempType = TLV_TYPE(tempShort);
999 tempLen = TLV_INFO_LEN(tempShort);
1003 strPtr = tvb_format_stringzpad(tvb, (offset+2), tempLen);
1005 /* Set system name tree */
1006 if (tempType == SYSTEM_NAME_TLV_TYPE) {
1007 tf = proto_tree_add_text(tree, tvb, offset, (tempLen + 2), "System Name = %s", strPtr);
1008 if (check_col(pinfo->cinfo, COL_INFO))
1009 col_append_fstr(pinfo->cinfo, COL_INFO, "System Name = %s ", strPtr);
1011 tf = proto_tree_add_text(tree, tvb, offset, (tempLen + 2), "System Description = %s", strPtr);
1012 system_name_tree = proto_item_add_subtree(tf, ett_system_name);
1014 proto_tree_add_item(system_name_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
1015 proto_tree_add_item(system_name_tree, hf_lldp_tlv_len, tvb, offset, 2, FALSE);
1017 /* Display system name information */
1018 proto_tree_add_text(system_name_tree, tvb, (offset+2), tempLen, "%s = %s",
1019 ((tempType == SYSTEM_NAME_TLV_TYPE) ? "System Name" : "System Description"),
1023 return (tempLen + 2);
1026 /* Dissect System Capabilities TLV */
1028 dissect_lldp_system_capabilities(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint32 offset)
1031 guint32 tempLen = 0;
1032 guint16 tempCapability;
1034 proto_tree *system_capabilities_tree = NULL;
1035 proto_tree *capabilities_summary_tree = NULL;
1036 proto_tree *capabilities_enabled_tree = NULL;
1037 proto_item *tf = NULL;
1039 /* Get tlv type and length */
1040 tempShort = tvb_get_ntohs(tvb, offset);
1042 /* Get tlv length */
1043 tempLen = TLV_INFO_LEN(tempShort);
1045 /* Get system capabilities */
1046 tempCapability = tvb_get_ntohs(tvb, (offset+2));
1050 /* Set system capabilities tree */
1051 tf = proto_tree_add_text(tree, tvb, offset, (tempLen + 2), "Capabilities");
1052 system_capabilities_tree = proto_item_add_subtree(tf, ett_system_cap);
1054 proto_tree_add_item(system_capabilities_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
1055 proto_tree_add_item(system_capabilities_tree, hf_lldp_tlv_len, tvb, offset, 2, FALSE);
1057 /* Display system capability information */
1058 tf = proto_tree_add_text(system_capabilities_tree, tvb, (offset+2), 2, "Capabilities: 0x%04x", tempCapability);
1059 capabilities_summary_tree = proto_item_add_subtree(tf, ett_system_cap_summary);
1060 /* Add capabilities to summary tree */
1061 if (tempCapability & SYSTEM_CAPABILITY_OTHER)
1062 proto_tree_add_text(capabilities_summary_tree, tvb, (offset+2), 2, "%s",
1063 decode_boolean_bitfield(tempCapability, SYSTEM_CAPABILITY_OTHER,
1065 if (tempCapability & SYSTEM_CAPABILITY_REPEATER)
1066 proto_tree_add_text(capabilities_summary_tree, tvb, (offset+2), 2, "%s",
1067 decode_boolean_bitfield(tempCapability, SYSTEM_CAPABILITY_REPEATER,
1068 16, "Repeater", ""));
1069 if (tempCapability & SYSTEM_CAPABILITY_BRIDGE)
1070 proto_tree_add_text(capabilities_summary_tree, tvb, (offset+2), 2, "%s",
1071 decode_boolean_bitfield(tempCapability, SYSTEM_CAPABILITY_BRIDGE,
1073 if (tempCapability & SYSTEM_CAPABILITY_WLAN)
1074 proto_tree_add_text(capabilities_summary_tree, tvb, (offset+2), 2, "%s",
1075 decode_boolean_bitfield(tempCapability, SYSTEM_CAPABILITY_WLAN,
1076 16, "WLAN access point", ""));
1077 if (tempCapability & SYSTEM_CAPABILITY_ROUTER)
1078 proto_tree_add_text(capabilities_summary_tree, tvb, (offset+2), 2, "%s",
1079 decode_boolean_bitfield(tempCapability, SYSTEM_CAPABILITY_ROUTER,
1081 if (tempCapability & SYSTEM_CAPABILITY_TELEPHONE)
1082 proto_tree_add_text(capabilities_summary_tree, tvb, (offset+2), 2, "%s",
1083 decode_boolean_bitfield(tempCapability, SYSTEM_CAPABILITY_TELEPHONE,
1084 16, "Telephone", ""));
1085 if (tempCapability & SYSTEM_CAPABILITY_DOCSIS)
1086 proto_tree_add_text(capabilities_summary_tree, tvb, (offset+2), 2, "%s",
1087 decode_boolean_bitfield(tempCapability, SYSTEM_CAPABILITY_DOCSIS,
1088 16, "DOCSIS cable device", ""));
1089 if (tempCapability & SYSTEM_CAPABILITY_STATION)
1090 proto_tree_add_text(capabilities_summary_tree, tvb, (offset+2), 2, "%s",
1091 decode_boolean_bitfield(tempCapability, SYSTEM_CAPABILITY_STATION,
1092 16, "Station only", ""));
1094 /* Get enabled summary */
1095 tempShort = tvb_get_ntohs(tvb, (offset+4));
1097 /* Display system capability information */
1098 tf = proto_tree_add_text(system_capabilities_tree, tvb, (offset+4), 2, "Enabled Capabilities: 0x%04x", tempShort);
1099 capabilities_enabled_tree = proto_item_add_subtree(tf, ett_system_cap_enabled);
1100 /* Add capabilities to summary tree */
1101 if (tempShort & SYSTEM_CAPABILITY_OTHER)
1102 proto_tree_add_text(capabilities_enabled_tree, tvb, (offset+4), 2, "%s",
1103 decode_boolean_bitfield(tempShort, SYSTEM_CAPABILITY_OTHER,
1105 if (tempShort & SYSTEM_CAPABILITY_REPEATER)
1106 proto_tree_add_text(capabilities_enabled_tree, tvb, (offset+4), 2, "%s",
1107 decode_boolean_bitfield(tempShort, SYSTEM_CAPABILITY_REPEATER,
1108 16, "Repeater", ""));
1109 if (tempShort & SYSTEM_CAPABILITY_BRIDGE)
1110 proto_tree_add_text(capabilities_enabled_tree, tvb, (offset+4), 2, "%s",
1111 decode_boolean_bitfield(tempShort, SYSTEM_CAPABILITY_BRIDGE,
1113 if (tempShort & SYSTEM_CAPABILITY_WLAN)
1114 proto_tree_add_text(capabilities_enabled_tree, tvb, (offset+4), 2, "%s",
1115 decode_boolean_bitfield(tempShort, SYSTEM_CAPABILITY_WLAN,
1116 16, "WLAN access point", ""));
1117 if (tempShort & SYSTEM_CAPABILITY_ROUTER)
1118 proto_tree_add_text(capabilities_enabled_tree, tvb, (offset+4), 2, "%s",
1119 decode_boolean_bitfield(tempShort, SYSTEM_CAPABILITY_ROUTER,
1121 if (tempShort & SYSTEM_CAPABILITY_TELEPHONE)
1122 proto_tree_add_text(capabilities_enabled_tree, tvb, (offset+4), 2, "%s",
1123 decode_boolean_bitfield(tempShort, SYSTEM_CAPABILITY_TELEPHONE,
1124 16, "Telephone", ""));
1125 if (tempShort & SYSTEM_CAPABILITY_DOCSIS)
1126 proto_tree_add_text(capabilities_enabled_tree, tvb, (offset+4), 2, "%s",
1127 decode_boolean_bitfield(tempShort, SYSTEM_CAPABILITY_DOCSIS,
1128 16, "DOCSIS cable device", ""));
1129 if (tempShort & SYSTEM_CAPABILITY_STATION)
1130 proto_tree_add_text(capabilities_enabled_tree, tvb, (offset+4), 2, "%s",
1131 decode_boolean_bitfield(tempShort, SYSTEM_CAPABILITY_STATION,
1132 16, "Station only", ""));
1135 return (tempLen + 2);
1138 /* Dissect Management Address TLV */
1140 dissect_lldp_management_address(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint32 offset)
1143 guint32 tempLen = 0;
1145 guint8 stringLen = 0;
1146 guint32 tempOffset = offset;
1149 proto_tree *system_mgm_addr = NULL;
1150 proto_item *tf = NULL;
1152 /* Get tlv type and length */
1153 tempShort = tvb_get_ntohs(tvb, tempOffset);
1155 /* Get tlv length */
1156 tempLen = TLV_INFO_LEN(tempShort);
1160 /* Set system capabilities tree */
1161 tf = proto_tree_add_text(tree, tvb, tempOffset, (tempLen + 2), "Management Address");
1162 system_mgm_addr = proto_item_add_subtree(tf, ett_management_address);
1164 proto_tree_add_item(system_mgm_addr, hf_lldp_tlv_type, tvb, tempOffset, 2, FALSE);
1165 proto_tree_add_item(system_mgm_addr, hf_lldp_tlv_len, tvb, tempOffset, 2, FALSE);
1169 /* Get management address string length */
1170 stringLen = tvb_get_guint8(tvb, tempOffset);
1171 proto_tree_add_text(system_mgm_addr, tvb, tempOffset, 1, "Address String Length: %u", stringLen);
1175 /* Get management address subtype */
1176 tempByte = tvb_get_guint8(tvb, tempOffset);
1177 proto_tree_add_text(system_mgm_addr, tvb, tempOffset, 1, "Address Subtype: %s (%u)",
1178 val_to_str(tempByte, afn_vals, "Undefined"),
1186 /* XXX - Should we throw an exception if stringLen doesn't match our address length? */
1188 proto_tree_add_item(system_mgm_addr, hf_mgn_addr_ipv4, tvb, tempOffset, 4, FALSE);
1191 proto_tree_add_item(system_mgm_addr, hf_mgn_addr_ipv6, tvb, tempOffset, 16, FALSE);
1194 proto_tree_add_item(system_mgm_addr, hf_mgn_addr_hex, tvb, tempOffset, (stringLen-1), FALSE);
1198 tempOffset += (stringLen-1);
1200 /* Get interface numbering subtype */
1201 tempByte = tvb_get_guint8(tvb, tempOffset);
1202 proto_tree_add_text(system_mgm_addr, tvb, tempOffset, 1, "Interface Subtype: %s (%u)",
1203 val_to_str(tempByte, interface_subtype_values, "Undefined"),
1208 /* Get interface number */
1209 tempLong = tvb_get_ntohl(tvb, tempOffset);
1210 proto_tree_add_text(system_mgm_addr, tvb, tempOffset, 4, "Interface Number: %u", tempLong);
1214 /* Get OID string length */
1215 stringLen = tvb_get_guint8(tvb, tempOffset);
1216 proto_tree_add_text(system_mgm_addr, tvb, tempOffset, 1, "OID String Length: %u", stringLen);
1222 /* Get OID identifier */
1223 proto_tree_add_item(system_mgm_addr, hf_mgn_obj_id, tvb, tempOffset, stringLen, FALSE);
1227 return (tempLen + 2);
1230 /* Dissect IEEE 802.1 TLVs */
1232 dissect_ieee_802_1_tlv(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint32 offset)
1237 guint32 tempOffset = offset;
1239 proto_tree *vlan_flags = NULL;
1240 proto_item *tf = NULL;
1243 subType = tvb_get_guint8(tvb, tempOffset);
1246 proto_tree_add_item(tree, hf_ieee_802_1_subtype, tvb, tempOffset, 1, FALSE);
1252 case 0x01: /* Port VLAN ID */
1254 /* Get port vland id */
1255 tempShort = tvb_get_ntohs(tvb, tempOffset);
1257 proto_tree_add_text(tree, tvb, tempOffset, 2, "Port VLAN Identifier: %u (0x%04X)", tempShort, tempShort);
1261 case 0x02: /* Port and Protocol VLAN ID */
1264 tempByte = tvb_get_guint8(tvb, tempOffset);
1267 tf = proto_tree_add_text(tree, tvb, tempOffset, 1, "Flags: 0x%02x", tempByte);
1268 vlan_flags = proto_item_add_subtree(tf, ett_port_vlan_flags);
1270 /* Get supported flag */
1271 proto_tree_add_text(vlan_flags, tvb, tempOffset, 1, "%s",
1272 decode_boolean_bitfield(tempByte, 1 << 1, 8, "Port and Protocol VLAN: Supported",
1273 "Port and Protocol VLAN: Not Supported"));
1275 /* Get enabled flag */
1276 proto_tree_add_text(vlan_flags, tvb, tempOffset, 1, "%s",
1277 decode_boolean_bitfield(tempByte, 1 << 2, 8, "Port and Protocol VLAN: Enabled",
1278 "Port and Protocol VLAN: Not Enabled"));
1283 /* Get port and protocol vlan id */
1284 tempShort = tvb_get_ntohs(tvb, tempOffset);
1286 proto_tree_add_text(tree, tvb, tempOffset, 2, "Port and Protocol VLAN Identifier: %u (0x%04X)", tempShort, tempShort);
1290 case 0x03: /* VLAN Name */
1293 tempShort = tvb_get_ntohs(tvb, tempOffset);
1295 proto_tree_add_text(tree, tvb, tempOffset, 2, "VLAN Identifier: %u (0x%04X)", tempShort, tempShort);
1299 /* Get vlan name length */
1300 tempByte = tvb_get_guint8(tvb, tempOffset);
1302 proto_tree_add_text(tree, tvb, tempOffset, 1, "VLAN Name Length: %u", tempByte);
1309 proto_tree_add_text(tree, tvb, tempOffset, tempByte, "VLAN Name: %s",
1310 tvb_format_stringzpad(tvb, tempOffset, tempByte));
1315 case 0x04: /* Protocol ID */
1317 /* Get protocal id length */
1318 tempByte = tvb_get_guint8(tvb, tempOffset);
1320 proto_tree_add_text(tree, tvb, tempOffset, 1, "Protocol Identity Length: %u", tempByte);
1327 proto_tree_add_text(tree, tvb, tempOffset, tempByte, "Protocol Identity: %s",
1328 tvb_bytes_to_str(tvb, tempOffset, tempByte));
1338 /* Dissect IEEE 802.3 TLVs */
1340 dissect_ieee_802_3_tlv(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint32 offset)
1346 guint32 tempOffset = offset;
1348 proto_tree *mac_phy_flags = NULL;
1349 proto_tree *autoneg_advertised_subtree = NULL;
1351 proto_item *tf = NULL;
1354 subType = tvb_get_guint8(tvb, tempOffset);
1357 proto_tree_add_item(tree, hf_ieee_802_3_subtype, tvb, tempOffset, 1, FALSE);
1363 case 0x01: /* MAC/PHY Configuration/Status */
1365 /* Get auto-negotiation info */
1366 tempByte = tvb_get_guint8(tvb, tempOffset);
1369 tf = proto_tree_add_text(tree, tvb, tempOffset, 1, "Auto-Negotiation Support/Status: 0x%02x", tempByte);
1370 mac_phy_flags = proto_item_add_subtree(tf, ett_802_3_flags);
1372 /* Get supported flag */
1373 proto_tree_add_text(mac_phy_flags, tvb, tempOffset, 1, "%s",
1374 decode_boolean_bitfield(tempByte, 0x01, 8, "Auto-Negotiation: Supported",
1375 "Auto-Negotiation: Not Supported"));
1377 /* Get enabled flag */
1378 proto_tree_add_text(mac_phy_flags, tvb, tempOffset, 1, "%s",
1379 decode_boolean_bitfield(tempByte, 0x02, 8, "Auto-Negotiation: Enabled",
1380 "Auto-Negotiation: Not Enabled"));
1385 /* Get pmd auto-negotiation advertised capability */
1386 tempShort = tvb_get_ntohs(tvb, tempOffset);
1389 tf = proto_tree_add_text(tree, tvb, tempOffset, 2, "PMD Auto-Negotiation Advertised Capability: 0x%04X", tempShort);
1390 autoneg_advertised_subtree = proto_item_add_subtree(tf, ett_802_3_autoneg_advertised);
1392 if (tempShort & AUTONEG_1000BASE_TFD)
1393 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1394 decode_boolean_bitfield(tempShort, AUTONEG_1000BASE_TFD,
1395 16, "1000BASE-T (full duplex mode)", ""));
1397 if (tempShort & AUTONEG_1000BASE_T)
1398 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1399 decode_boolean_bitfield(tempShort, AUTONEG_1000BASE_T,
1400 16, "1000BASE-T (half duplex mode)", ""));
1402 if (tempShort & AUTONEG_1000BASE_XFD)
1403 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1404 decode_boolean_bitfield(tempShort, AUTONEG_1000BASE_XFD,
1405 16, "1000BASE-X (-LX, -SX, -CX full duplex mode)", ""));
1407 if (tempShort & AUTONEG_1000BASE_X)
1408 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1409 decode_boolean_bitfield(tempShort, AUTONEG_1000BASE_X,
1410 16, "1000BASE-X (-LX, -SX, -CX half duplex mode)", ""));
1412 if (tempShort & AUTONEG_FDX_BPAUSE)
1413 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1414 decode_boolean_bitfield(tempShort, AUTONEG_FDX_BPAUSE,
1415 16, "Asymmetric and Symmetric PAUSE (for full-duplex links)", ""));
1417 if (tempShort & AUTONEG_FDX_SPAUSE)
1418 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1419 decode_boolean_bitfield(tempShort, AUTONEG_FDX_SPAUSE,
1420 16, "Symmetric PAUSE (for full-duplex links)", ""));
1422 if (tempShort & AUTONEG_FDX_APAUSE)
1423 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1424 decode_boolean_bitfield(tempShort, AUTONEG_FDX_APAUSE,
1425 16, "Asymmetric PAUSE (for full-duplex links)", ""));
1427 if (tempShort & AUTONEG_FDX_PAUSE)
1428 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1429 decode_boolean_bitfield(tempShort, AUTONEG_FDX_PAUSE,
1430 16, "PAUSE (for full-duplex links)", ""));
1432 if (tempShort & AUTONEG_100BASE_T2FD)
1433 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1434 decode_boolean_bitfield(tempShort, AUTONEG_100BASE_T2FD,
1435 16, "100BASE-T2 (full duplex mode)", ""));
1437 if (tempShort & AUTONEG_100BASE_T2)
1438 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1439 decode_boolean_bitfield(tempShort, AUTONEG_100BASE_T2,
1440 16, "100BASE-T2 (half duplex mode)", ""));
1442 if (tempShort & AUTONEG_100BASE_TXFD)
1443 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1444 decode_boolean_bitfield(tempShort, AUTONEG_100BASE_TXFD,
1445 16, "100BASE-TX (full duplex mode)", ""));
1447 if (tempShort & AUTONEG_100BASE_TX)
1448 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1449 decode_boolean_bitfield(tempShort, AUTONEG_100BASE_TX,
1450 16, "100BASE-TX (half duplex mode)", ""));
1452 if (tempShort & AUTONEG_100BASE_T4)
1453 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1454 decode_boolean_bitfield(tempShort, AUTONEG_100BASE_T4,
1455 16, "100BASE-T4", ""));
1457 if (tempShort & AUTONEG_10BASET_FD)
1458 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1459 decode_boolean_bitfield(tempShort, AUTONEG_10BASET_FD,
1460 16, "10BASE-T (full duplex mode)", ""));
1462 if (tempShort & AUTONEG_10BASE_T)
1463 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1464 decode_boolean_bitfield(tempShort, AUTONEG_10BASE_T,
1465 16, "10BASE-T (half duplex mode)", ""));
1467 if (tempShort & AUTONEG_OTHER)
1468 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1469 decode_boolean_bitfield(tempShort, AUTONEG_OTHER,
1470 16, "other or unknown", ""));
1472 tf = proto_tree_add_text(tree, tvb, tempOffset, 2, "Same in inverse (wrong) bitorder");
1473 autoneg_advertised_subtree = proto_item_add_subtree(tf, ett_802_3_autoneg_advertised);
1475 if (tempShort & INV_AUTONEG_1000BASE_TFD)
1476 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1477 decode_boolean_bitfield(tempShort, INV_AUTONEG_1000BASE_TFD,
1478 16, "1000BASE-T (full duplex mode)", ""));
1480 if (tempShort & INV_AUTONEG_1000BASE_T)
1481 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1482 decode_boolean_bitfield(tempShort, INV_AUTONEG_1000BASE_T,
1483 16, "1000BASE-T (half duplex mode)", ""));
1485 if (tempShort & INV_AUTONEG_1000BASE_XFD)
1486 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1487 decode_boolean_bitfield(tempShort, INV_AUTONEG_1000BASE_XFD,
1488 16, "1000BASE-X (-LX, -SX, -CX full duplex mode)", ""));
1490 if (tempShort & INV_AUTONEG_1000BASE_X)
1491 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1492 decode_boolean_bitfield(tempShort, INV_AUTONEG_1000BASE_X,
1493 16, "1000BASE-X (-LX, -SX, -CX half duplex mode)", ""));
1495 if (tempShort & INV_AUTONEG_FDX_BPAUSE)
1496 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1497 decode_boolean_bitfield(tempShort, INV_AUTONEG_FDX_BPAUSE,
1498 16, "Asymmetric and Symmetric PAUSE (for full-duplex links)", ""));
1500 if (tempShort & INV_AUTONEG_FDX_SPAUSE)
1501 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1502 decode_boolean_bitfield(tempShort, INV_AUTONEG_FDX_SPAUSE,
1503 16, "Symmetric PAUSE (for full-duplex links)", ""));
1505 if (tempShort & INV_AUTONEG_FDX_APAUSE)
1506 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1507 decode_boolean_bitfield(tempShort, INV_AUTONEG_FDX_APAUSE,
1508 16, "Asymmetric PAUSE (for full-duplex links)", ""));
1510 if (tempShort & INV_AUTONEG_FDX_PAUSE)
1511 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1512 decode_boolean_bitfield(tempShort, INV_AUTONEG_FDX_PAUSE,
1513 16, "PAUSE (for full-duplex links)", ""));
1515 if (tempShort & INV_AUTONEG_100BASE_T2FD)
1516 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1517 decode_boolean_bitfield(tempShort, INV_AUTONEG_100BASE_T2FD,
1518 16, "100BASE-T2 (full duplex mode)", ""));
1520 if (tempShort & INV_AUTONEG_100BASE_T2)
1521 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1522 decode_boolean_bitfield(tempShort, INV_AUTONEG_100BASE_T2,
1523 16, "100BASE-T2 (half duplex mode)", ""));
1525 if (tempShort & INV_AUTONEG_100BASE_TXFD)
1526 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1527 decode_boolean_bitfield(tempShort, INV_AUTONEG_100BASE_TXFD,
1528 16, "100BASE-TX (full duplex mode)", ""));
1530 if (tempShort & INV_AUTONEG_100BASE_TX)
1531 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1532 decode_boolean_bitfield(tempShort, INV_AUTONEG_100BASE_TX,
1533 16, "100BASE-TX (half duplex mode)", ""));
1535 if (tempShort & INV_AUTONEG_100BASE_T4)
1536 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1537 decode_boolean_bitfield(tempShort, INV_AUTONEG_100BASE_T4,
1538 16, "100BASE-T4", ""));
1540 if (tempShort & INV_AUTONEG_10BASET_FD)
1541 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1542 decode_boolean_bitfield(tempShort, INV_AUTONEG_10BASET_FD,
1543 16, "10BASE-T (full duplex mode)", ""));
1545 if (tempShort & INV_AUTONEG_10BASE_T)
1546 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1547 decode_boolean_bitfield(tempShort, INV_AUTONEG_10BASE_T,
1548 16, "10BASE-T (half duplex mode)", ""));
1550 if (tempShort & INV_AUTONEG_OTHER)
1551 proto_tree_add_text(autoneg_advertised_subtree, tvb, (offset+2), 2, "%s",
1552 decode_boolean_bitfield(tempShort, INV_AUTONEG_OTHER,
1553 16, "other or unknown", ""));
1559 /* Get operational MAU type */
1560 tempShort = tvb_get_ntohs(tvb, tempOffset);
1562 proto_tree_add_text(tree, tvb, tempOffset, 2, "Operational MAU Type: %s (0x%04X)",
1563 val_to_str(tempShort,operational_mau_type_values,"Unknown"),
1570 case 0x02: /* MDI Power Support */
1574 /* Get MDI power support info */
1575 tempByte = tvb_get_guint8(tvb, tempOffset);
1578 tf = proto_tree_add_text(tree, tvb, tempOffset, 1, "MDI Power Support: 0x%02x", tempByte);
1579 mac_phy_flags = proto_item_add_subtree(tf, ett_802_3_power);
1581 /* Get port class */
1582 proto_tree_add_text(mac_phy_flags, tvb, tempOffset, 1, "%s",
1583 decode_boolean_bitfield(tempByte, 0x01, 8, "Port Class: PSE",
1586 /* Get PSE MDI power support */
1587 proto_tree_add_text(mac_phy_flags, tvb, tempOffset, 1, "%s",
1588 decode_boolean_bitfield(tempByte, 0x02, 8, "PSE MDI Power: Supported",
1589 "PSE MDI Power: Not Supported"));
1591 /* Get PSE MDI power state */
1592 proto_tree_add_text(mac_phy_flags, tvb, tempOffset, 1, "%s",
1593 decode_boolean_bitfield(tempByte, 0x04, 8, "PSE MDI Power Enabled: Yes",
1594 "PSE MDI Power Enabled: No"));
1596 /* Get PSE pairs control ability */
1597 proto_tree_add_text(mac_phy_flags, tvb, tempOffset, 1, "%s",
1598 decode_boolean_bitfield(tempByte, 0x08, 8, "PSE Pairs Control Ability: Yes",
1599 "PSE Pairs Control Ability: No"));
1604 /* Get PSE power pair */
1605 tempByte = tvb_get_guint8(tvb, tempOffset);
1607 proto_tree_add_text(tree, tvb, tempOffset, 1, "PSE Power Pair: %u", tempByte);
1611 /* Get power class */
1612 tempByte = tvb_get_guint8(tvb, tempOffset);
1614 proto_tree_add_text(tree, tvb, tempOffset, 1, "Power Class: %u", tempByte);
1618 /* Get first byte */
1619 tempByte = tvb_get_guint8(tvb, tempOffset);
1621 /* Determine power type */
1622 subType = ((tempByte & 0xC0) >> 6);
1624 proto_tree_add_text(tree, tvb, tempOffset, 1, "%s %s %s",
1625 decode_boolean_bitfield(tempByte, 0xC0, 8, "Power Type:", "Power Type:"),
1626 val_to_str(subType, power_type_802_3, "Unkown"),
1627 val_to_str(subType, media_power_type, "Unknown"));
1629 /* Determine power source */
1635 subType = ((tempByte & 0x30) >> 4);
1636 strPtr = val_to_str(subType, media_power_pse_device, "Reserved");
1643 subType = ((tempByte & 0x30) >> 4);
1644 strPtr = val_to_str(subType, media_power_pd_device, "Reserved");
1655 proto_tree_add_text(tree, tvb, tempOffset, 1, "%s %s",
1656 decode_boolean_bitfield(tempByte, 0x30, 8, "Power Source:", "Power Source:"),
1659 /* Determine power priority */
1660 subType = (tempByte & 0x0F);
1662 proto_tree_add_text(tree, tvb, tempOffset, 1, "%s %s",
1663 decode_boolean_bitfield(tempByte, 0x0F, 8, "Power Priority:", "Power Priority:"),
1664 val_to_str(subType, media_power_priority, "Reserved"));
1668 /* Power Value: 1 to 255 expected */
1669 tempShort = tvb_get_ntohs(tvb, tempOffset);
1671 proto_tree_add_text(tree, tvb, tempOffset, 2, "PD Requested Power Value: %u.%u Watt", tempShort/10, tempShort%10);
1675 /* Power Value: 1 to 255 expected */
1676 tempShort = tvb_get_ntohs(tvb, tempOffset);
1678 proto_tree_add_text(tree, tvb, tempOffset, 2, "PSE Allocated Power Value: %u.%u Watt", tempShort/10, tempShort%10);
1684 case 0x03: /* Link Aggregation */
1686 /* Get aggregation status */
1687 tempByte = tvb_get_guint8(tvb, tempOffset);
1690 tf = proto_tree_add_text(tree, tvb, tempOffset, 1, "Aggregation Status: 0x%02x", tempByte);
1691 mac_phy_flags = proto_item_add_subtree(tf, ett_802_3_aggregation);
1693 /* Get aggregation capability */
1694 proto_tree_add_text(mac_phy_flags, tvb, tempOffset, 1, "%s",
1695 decode_boolean_bitfield(tempByte, 0x01, 8, "Aggregation Capability: Yes",
1696 "Aggregation Capability: No"));
1698 /* Get aggregation status */
1699 proto_tree_add_text(mac_phy_flags, tvb, tempOffset, 1, "%s",
1700 decode_boolean_bitfield(tempByte, 0x02, 8, "Aggregation Status: Enabled",
1701 "Aggregation Status: Not Enabled"));
1706 /* Get aggregated port id */
1707 tempLong = tvb_get_ntohl(tvb, tempOffset);
1709 proto_tree_add_text(tree, tvb, tempOffset, 4, "Aggregated Port Id: %u", tempLong);
1715 case 0x04: /* Maximum Frame Size */
1717 /* Get maximum frame size */
1718 tempShort = tvb_get_ntohs(tvb, tempOffset);
1720 proto_tree_add_text(tree, tvb, tempOffset, 2, "Maximum Frame Size: %u", tempShort);
1731 /* Dissect Media TLVs */
1733 dissect_media_tlv(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint32 offset, guint16 tlvLen)
1735 guint32 tempOffset = offset;
1743 guint64 temp64bit = 0;
1745 proto_tree *media_flags = NULL;
1746 proto_item *tf = NULL;
1749 subType = tvb_get_guint8(tvb, tempOffset);
1751 proto_tree_add_item(tree, hf_media_tlv_subtype, tvb, tempOffset, 1, FALSE);
1757 case 1: /* LLDP-MED Capabilities */
1759 /* Get capabilities */
1762 proto_tree_add_text(tree, tvb, tempOffset, 0, "TLV too short");
1765 tempShort = tvb_get_ntohs(tvb, tempOffset);
1768 tf = proto_tree_add_text(tree, tvb, tempOffset, 2, "Capabilities: 0x%04x", tempShort);
1769 media_flags = proto_item_add_subtree(tf, ett_media_capabilities);
1770 if (tempShort & MEDIA_CAPABILITY_LLDP)
1771 proto_tree_add_text(media_flags, tvb, tempOffset, 2, "%s",
1772 decode_boolean_bitfield(tempShort, MEDIA_CAPABILITY_LLDP, 16,
1773 "LLDP-MED Capabilities", ""));
1774 if (tempShort & MEDIA_CAPABILITY_NETWORK_POLICY)
1775 proto_tree_add_text(media_flags, tvb, tempOffset, 2, "%s",
1776 decode_boolean_bitfield(tempShort, MEDIA_CAPABILITY_NETWORK_POLICY, 16,
1777 "Network Policy", ""));
1778 if (tempShort & MEDIA_CAPABILITY_LOCATION_ID)
1779 proto_tree_add_text(media_flags, tvb, tempOffset, 2, "%s",
1780 decode_boolean_bitfield(tempShort, MEDIA_CAPABILITY_LOCATION_ID, 16,
1781 "Location Identification", ""));
1782 if (tempShort & MEDIA_CAPABILITY_MDI_PSE)
1783 proto_tree_add_text(media_flags, tvb, tempOffset, 2, "%s",
1784 decode_boolean_bitfield(tempShort, MEDIA_CAPABILITY_MDI_PSE, 16,
1785 "Extended Power via MDI-PSE", ""));
1786 if (tempShort & MEDIA_CAPABILITY_MDI_PD)
1787 proto_tree_add_text(media_flags, tvb, tempOffset, 2, "%s",
1788 decode_boolean_bitfield(tempShort, MEDIA_CAPABILITY_MDI_PD, 16,
1789 "Extended Power via MDI-PD", ""));
1790 if (tempShort & MEDIA_CAPABILITY_INVENTORY)
1791 proto_tree_add_text(media_flags, tvb, tempOffset, 2, "%s",
1792 decode_boolean_bitfield(tempShort, MEDIA_CAPABILITY_INVENTORY, 16,
1798 /* Get Class type */
1801 proto_tree_add_text(tree, tvb, tempOffset, 0, "TLV too short");
1804 tempByte = tvb_get_guint8(tvb, tempOffset);
1806 proto_tree_add_text(tree, tvb, tempOffset, 1, "Class Type: %s", val_to_str(tempByte, media_class_values, "Unknown"));
1812 case 2: /* Network Policy */
1814 /* Get application type */
1817 proto_tree_add_text(tree, tvb, tempOffset, 0, "TLV too short");
1820 tempByte = tvb_get_guint8(tvb, tempOffset);
1822 proto_tree_add_text(tree, tvb, tempOffset, 1, "Application Type: %s (%u)",
1823 val_to_str(tempByte, media_application_type, "Unknown"), tempByte);
1830 proto_tree_add_text(tree, tvb, tempOffset, 0, "TLV too short");
1833 tempShort = tvb_get_ntohs(tvb, tempOffset);
1835 /* Unknown policy flag */
1837 proto_tree_add_text(tree, tvb, tempOffset, 2, "%s",
1838 decode_boolean_bitfield(tempShort, 0x8000, 16,"Policy: Unknown", "Policy: Defined"));
1842 proto_tree_add_text(tree, tvb, tempOffset, 2, "%s",
1843 decode_boolean_bitfield(tempShort, 0x4000, 16,"Tagged: Yes", "Tagged: No"));
1846 tempVLAN = (tempShort & 0x1FFE) >> 1;
1848 proto_tree_add_text(tree, tvb, tempOffset, 2, "%s %u",
1849 decode_boolean_bitfield(tempShort, 0x1FFE, 16, "VLAN Id:", "VLAN Id:"), tempVLAN);
1853 /* Get L2 priority */
1856 proto_tree_add_text(tree, tvb, tempOffset, 0, "TLV too short");
1859 tempShort = tvb_get_ntohs(tvb, tempOffset);
1861 proto_tree_add_text(tree, tvb, tempOffset, 2, "%s %u",
1862 decode_boolean_bitfield(tempShort, 0x01C0, 16, "L2 Priority:", "L2 Priority:"),
1863 ((tempShort & 0x01C0) >> 6));
1867 /* Get DSCP value */
1868 tempByte = tvb_get_guint8(tvb, tempOffset);
1870 proto_tree_add_text(tree, tvb, tempOffset, 1, "%s %u",
1871 decode_boolean_bitfield(tempByte, 0x3F, 8, "DSCP Value:", "DSCP Value:"),
1876 case 3: /* Location Identification */
1878 /* Get location data format */
1881 proto_tree_add_text(tree, tvb, tempOffset, 0, "TLV too short");
1884 tempByte = tvb_get_guint8(tvb, tempOffset);
1886 proto_tree_add_text(tree, tvb, tempOffset, 1, "Location Data Format: %s (%u)",
1887 val_to_str(tempByte, location_data_format, "Unknown"), tempByte);
1893 case 1: /* Coordinate-based LCI */
1897 * XXX - should this be handled by the BOOTP
1898 * dissector, and exported to us?
1902 proto_tree_add_text(tree, tvb, tempOffset, 0, "TLV too short");
1906 /* Get latitude resolution */
1907 tempByte = tvb_get_guint8(tvb, tempOffset);
1909 proto_tree_add_text(tree, tvb, tempOffset, 1, "%s %u",
1910 decode_boolean_bitfield(tempByte, 0xFC, 8, "Latitude Resolution:", "Latitude Resolution:"),
1911 ((tempByte & 0xFC) >> 2));
1914 temp64bit = tvb_get_ntoh64(tvb, tempOffset);
1915 temp64bit = (temp64bit & G_GINT64_CONSTANT(0x03FFFFFFFF000000)) >> 24;
1917 proto_tree_add_text(tree, tvb, tempOffset, 5, "Latitude: %s (0x%16" G_GINT64_MODIFIER "X)",
1918 get_latitude_or_longitude(0, temp64bit),
1923 /* Get longitude resolution */
1924 tempByte = tvb_get_guint8(tvb, tempOffset);
1926 proto_tree_add_text(tree, tvb, tempOffset, 1, "%s %u",
1927 decode_boolean_bitfield(tempByte, 0xFC, 8, "Longitude Resolution:", "Longitude Resolution:"),
1928 ((tempByte & 0xFC) >> 2));
1931 temp64bit = tvb_get_ntoh64(tvb, tempOffset);
1932 temp64bit = (temp64bit & G_GINT64_CONSTANT(0x03FFFFFFFF000000)) >> 24;
1935 proto_tree_add_text(tree, tvb, tempOffset, 5, "Longitude: %s (0x%16" G_GINT64_MODIFIER "X)",
1936 get_latitude_or_longitude(1,temp64bit),
1942 tempByte = tvb_get_guint8(tvb, tempOffset);
1945 tf = proto_tree_add_text(tree, tvb, tempOffset, 1, "%s",
1946 decode_boolean_bitfield(tempByte, 0xF0, 8, "Altitude Type: ", "Altitude Type: "));
1948 switch ((tempByte >> 4))
1951 proto_item_append_text(tf, "Meters (1)");
1954 proto_item_append_text(tf, "Floors (2)");
1957 proto_item_append_text(tf, " Unknown (%u)", (tempByte >> 4));
1962 /* Get Altitude Resolution */
1963 tempShort = tvb_get_ntohs(tvb, tempOffset);
1965 proto_tree_add_text(tree, tvb, tempOffset, 2, "%s %u",
1966 decode_boolean_bitfield(tempShort, 0x0FC0, 16, "Altitude Resolution: ", "Altitude Type: "),
1967 ((tempShort & 0x0FC0) >> 6));
1972 tempLong = (tvb_get_ntohl(tvb, tempOffset) & 0x03FFFFFFF);
1974 proto_tree_add_text(tree, tvb, tempOffset, 4, "Altitude: 0x%08X", tempLong);
1979 tempByte = tvb_get_guint8(tvb, tempOffset);
1981 proto_tree_add_text(tree, tvb, tempOffset, 1, "Datum: %u", tempByte);
1985 case 2: /* Civic Address LCI */
1988 * See draft-ietf-geopriv-dhcp-civil-07.
1989 * XXX - should this be handled by the BOOTP
1990 * dissector, and exported to us?
1994 proto_tree_add_text(tree, tvb, tempOffset, 0, "TLV too short");
1998 /* Get LCI length */
1999 tempByte = tvb_get_guint8(tvb, tempOffset);
2001 if (tempByte > tlvLen)
2004 proto_tree_add_text(tree, tvb, tempOffset, 1, "LCI Length: %u (greater than TLV length)", tempByte);
2010 proto_tree_add_text(tree, tvb, tempOffset, 1, "LCI Length: %u", tempByte);
2012 LCI_Length = (guint32)tempByte;
2016 /* Get what value */
2019 proto_tree_add_text(tree, tvb, tempOffset, 0, "LCI Length too short");
2022 tempByte = tvb_get_guint8(tvb, tempOffset);
2024 proto_tree_add_text(tree, tvb, tempOffset, 1, "What: %s (%u)",
2025 val_to_str(tempByte,civic_address_what_values,"Unknown"),
2030 /* Get country code */
2033 proto_tree_add_text(tree, tvb, tempOffset, 0, "LCI Length too short");
2037 proto_tree_add_text(tree, tvb, tempOffset, 2, "Country: %s",
2038 tvb_format_text(tvb, tempOffset, 2));
2043 while (LCI_Length > 0)
2048 proto_tree_add_text(tree, tvb, tempOffset, 0, "LCI Length too short");
2051 tempByte = tvb_get_guint8(tvb, tempOffset);
2053 proto_tree_add_text(tree, tvb, tempOffset, 1, "CA Type: %s (%u)",
2054 val_to_str(tempByte,civic_address_type_values,"Unknown"),
2063 proto_tree_add_text(tree, tvb, tempOffset, 0, "LCI Length too short");
2066 tempByte = tvb_get_guint8(tvb, tempOffset);
2068 proto_tree_add_text(tree, tvb, tempOffset, 1, "CA Length: %u", tempByte);
2073 /* Make sure the CA value is within the specified length */
2074 if (tempByte > LCI_Length)
2081 proto_tree_add_text(tree, tvb, tempOffset, tempByte, "CA Value: %s",
2082 tvb_format_stringzpad(tvb, tempOffset, tempByte));
2084 tempOffset += tempByte;
2085 LCI_Length -= tempByte;
2091 case 3: /* ECS ELIN */
2096 proto_tree_add_text(tree, tvb, tempOffset, tlvLen, "ELIN: %s",
2097 tvb_format_stringzpad(tvb, tempOffset, tlvLen));
2107 case 4: /* Extended Power-via-MDI */
2109 /* Get first byte */
2110 tempByte = tvb_get_guint8(tvb, tempOffset);
2112 /* Determine power type */
2113 subType = ((tempByte & 0xC0) >> 6);
2115 proto_tree_add_text(tree, tvb, tempOffset, 1, "%s %s",
2116 decode_boolean_bitfield(tempByte, 0xC0, 8, "Power Type:", "Power Type:"),
2117 val_to_str(subType, media_power_type, "Unknown"));
2119 /* Determine power source */
2124 subType = ((tempByte & 0x30) >> 4);
2125 strPtr = val_to_str(subType, media_power_pse_device, "Reserved");
2131 subType = ((tempByte & 0x30) >> 4);
2132 strPtr = val_to_str(subType, media_power_pd_device, "Reserved");
2143 proto_tree_add_text(tree, tvb, tempOffset, 1, "%s %s",
2144 decode_boolean_bitfield(tempByte, 0x30, 8, "Power Source:", "Power Source:"),
2147 /* Determine power priority */
2148 subType = (tempByte & 0x0F);
2150 proto_tree_add_text(tree, tvb, tempOffset, 1, "%s %s",
2151 decode_boolean_bitfield(tempByte, 0x0F, 8, "Power Priority:", "Power Priority:"),
2152 val_to_str(subType, media_power_priority, "Reserved"));
2156 /* Power Value: 0 to 102.3 Watts (0.1 W increments) */
2157 tempShort = tvb_get_ntohs(tvb, tempOffset) * 100;
2159 proto_tree_add_text(tree, tvb, tempOffset, 2, "Power Value: %u mW", tempShort);
2163 case 5: /* Hardware Revision */
2165 /* Figure out the length of the hardware revision field */
2169 proto_tree_add_text(tree, tvb, tempOffset, tlvLen, "Hardware Revision: %s",
2170 tvb_format_stringzpad(tvb, tempOffset, tlvLen));
2175 case 6: /* Firmware Revision */
2177 /* Figure out the length of the firmware revision field */
2181 proto_tree_add_text(tree, tvb, tempOffset, tlvLen, "Firmware Revision: %s",
2182 tvb_format_stringzpad(tvb, tempOffset, tlvLen));
2187 case 7: /* Software Revision */
2189 /* Figure out the length of the software revision field */
2193 proto_tree_add_text(tree, tvb, tempOffset, tlvLen, "Software Revision: %s",
2194 tvb_format_stringzpad(tvb, tempOffset, tlvLen));
2199 case 8: /* Serial Number */
2201 /* Figure out the length of the serial number field */
2205 proto_tree_add_text(tree, tvb, tempOffset, tlvLen, "Serial Number: %s",
2206 tvb_format_stringzpad(tvb, tempOffset, tlvLen));
2211 case 9: /* Manufacturer Name */
2213 /* Figure out the length of the manufacturer name field */
2217 proto_tree_add_text(tree, tvb, tempOffset, tlvLen, "Manufacturer Name: %s",
2218 tvb_format_stringzpad(tvb, tempOffset, tlvLen));
2223 case 10: /* Model Name */
2225 /* Figure out the length of the model name field */
2229 proto_tree_add_text(tree, tvb, tempOffset, tlvLen, "Model Name: %s",
2230 tvb_format_stringzpad(tvb, tempOffset, tlvLen));
2235 case 11: /* Asset ID */
2237 /* Figure out the length of the asset id field */
2241 proto_tree_add_text(tree, tvb, tempOffset, tlvLen, "Asset ID: %s",
2242 tvb_format_stringzpad(tvb, tempOffset, tlvLen));
2254 dissect_profinet_period(tvbuff_t *tvb, proto_tree *tree, guint32 offset, const gchar *name, int hf_valid, int hf_value)
2257 proto_tree *period_tree;
2258 proto_item *period_item;
2261 period = tvb_get_ntohl(tvb, offset);
2263 period_item = proto_tree_add_text(tree, tvb, offset, 4, "%s: %s, %uns",
2264 name, (period & 0x80000000) ? "Valid" : "Invalid", period & 0x7FFFFFFF);
2265 period_tree = proto_item_add_subtree(period_item, ett_profinet_period);
2267 proto_tree_add_uint(period_tree, hf_valid, tvb, offset, 4, period);
2268 proto_tree_add_uint(period_tree, hf_value, tvb, offset, 4, period);
2275 /* Dissect PROFINET TLVs */
2277 dissect_profinet_tlv(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint32 offset, guint16 tlvLen2)
2280 proto_item *tf = NULL;
2281 guint16 class2_PortStatus;
2282 guint16 class3_PortStatus;
2283 guint32 port_rx_delay_local;
2284 guint32 port_rx_delay_remote;
2285 guint32 port_tx_delay_local;
2286 guint32 port_tx_delay_remote;
2287 guint32 cable_delay_local;
2288 const guint8 *mac_addr = NULL;
2290 guint16 mrrt_PortStatus;
2294 subType = tvb_get_guint8(tvb, offset);
2296 proto_tree_add_uint(tree, hf_profinet_tlv_subtype, tvb, offset, 1, subType);
2301 case 1: /* LLDP_PNIO_DELAY */
2303 port_rx_delay_local = tvb_get_ntohl(tvb, offset);
2304 tf = proto_tree_add_uint(tree, hf_profinet_port_rx_delay_local, tvb, offset, 4, port_rx_delay_local);
2305 if(port_rx_delay_local) {
2306 proto_item_append_text(tf, "ns");
2308 proto_item_append_text(tf, " (unknown)");
2311 port_rx_delay_remote = tvb_get_ntohl(tvb, offset);
2312 tf = proto_tree_add_uint(tree, hf_profinet_port_rx_delay_remote, tvb, offset, 4, port_rx_delay_remote);
2313 if(port_rx_delay_remote) {
2314 proto_item_append_text(tf, "ns");
2316 proto_item_append_text(tf, " (unknown)");
2319 port_tx_delay_local = tvb_get_ntohl(tvb, offset);
2320 tf = proto_tree_add_uint(tree, hf_profinet_port_tx_delay_local, tvb, offset, 4, port_tx_delay_local);
2321 if(port_tx_delay_local) {
2322 proto_item_append_text(tf, "ns");
2324 proto_item_append_text(tf, " (unknown)");
2327 port_tx_delay_remote = tvb_get_ntohl(tvb, offset);
2328 tf = proto_tree_add_uint(tree, hf_profinet_port_tx_delay_remote, tvb, offset, 4, port_tx_delay_remote);
2329 if(port_tx_delay_remote) {
2330 proto_item_append_text(tf, "ns");
2332 proto_item_append_text(tf, " (unknown)");
2335 cable_delay_local = tvb_get_ntohl(tvb, offset);
2336 tf = proto_tree_add_uint(tree, hf_profinet_cable_delay_local, tvb, offset, 4, cable_delay_local);
2337 if(cable_delay_local) {
2338 proto_item_append_text(tf, "ns");
2340 proto_item_append_text(tf, " (unknown)");
2345 case 2: /* LLDP_PNIO_PORTSTATUS */
2347 class2_PortStatus = tvb_get_ntohs(tvb, offset);
2348 proto_tree_add_uint(tree, hf_profinet_class2_port_status, tvb, offset, 2, class2_PortStatus);
2350 class3_PortStatus = tvb_get_ntohs(tvb, offset);
2351 proto_tree_add_uint(tree, hf_profinet_class3_port_status, tvb, offset, 2, class3_PortStatus);
2355 /*case 3:*/ /* XXX - LLDP_PNIO_ALIAS */
2356 case 4: /* LLDP_PNIO_MRPPORTSTATUS */
2359 tvb_get_ntohguid (tvb, offset, (e_guid_t *) &uuid);
2360 proto_tree_add_guid(tree, hf_profinet_mrp_domain_uuid, tvb, offset, 16, (e_guid_t *) &uuid);
2363 /* MRRT PortStatus */
2364 mrrt_PortStatus = tvb_get_ntohs(tvb, offset);
2365 proto_tree_add_uint(tree, hf_profinet_mrrt_port_status, tvb, offset, 2, mrrt_PortStatus);
2369 case 5: /* LLDP_PNIO_CHASSIS_MAC */
2371 mac_addr=tvb_get_ptr(tvb, offset, 6);
2372 proto_tree_add_ether(tree, hf_profinet_cm_mac, tvb, offset, 6, mac_addr);
2376 case 6: /* LLDP_PNIO_PTCPSTATUS */
2378 /* MasterSourceAddress */
2379 mac_addr=tvb_get_ptr(tvb, offset, 6);
2380 proto_tree_add_ether(tree, hf_profinet_master_source_address, tvb, offset, 6, mac_addr);
2383 tvb_get_ntohguid (tvb, offset, (e_guid_t *) &uuid);
2384 proto_tree_add_guid(tree, hf_profinet_subdomain_uuid, tvb, offset, 16, (e_guid_t *) &uuid);
2387 tvb_get_ntohguid (tvb, offset, (e_guid_t *) &uuid);
2388 proto_tree_add_guid(tree, hf_profinet_ir_data_uuid, tvb, offset, 16, (e_guid_t *) &uuid);
2390 /* LengthOfPeriod */
2391 offset = dissect_profinet_period(tvb, tree, offset, "LengthOfPeriod",
2392 hf_profinet_length_of_period_valid, hf_profinet_length_of_period_length);
2393 /* RedPeriodBegin */
2394 offset = dissect_profinet_period(tvb, tree, offset, "RedPeriodBegin",
2395 hf_profinet_red_period_begin_valid, hf_profinet_red_period_begin_offset);
2396 /* OrangePeriodBegin */
2397 offset = dissect_profinet_period(tvb, tree, offset, "OrangePeriodBegin",
2398 hf_profinet_orange_period_begin_valid, hf_profinet_orange_period_begin_offset);
2399 /* GreenPeriodBegin */
2400 offset = dissect_profinet_period(tvb, tree, offset, "GreenPeriodBegin",
2401 hf_profinet_green_period_begin_valid, hf_profinet_green_period_begin_offset);
2405 proto_tree_add_item(tree, hf_unknown_subtype, tvb, offset, tlvLen2-1, FALSE);
2410 /* Dissect Organizational Specific TLV */
2412 dissect_organizational_specific_tlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
2419 const char *subTypeStr;
2421 proto_tree *org_tlv_tree = NULL;
2422 proto_item *tf = NULL;
2424 /* Get tlv type and length */
2425 tempShort = tvb_get_ntohs(tvb, offset);
2427 /* Get tlv length */
2428 tempLen = TLV_INFO_LEN(tempShort);
2431 oui = tvb_get_ntoh24(tvb, (offset+2));
2432 subType = tvb_get_guint8(tvb, (offset+5));
2434 ouiStr = val_to_str(oui, tlv_oui_subtype_vals, "Unknown");
2437 case OUI_IEEE_802_1:
2438 subTypeStr = val_to_str(subType, ieee_802_1_subtypes, "Unknown subtype 0x%x");
2440 case OUI_IEEE_802_3:
2441 subTypeStr = val_to_str(subType, ieee_802_3_subtypes, "Unknown subtype 0x%x");
2443 case OUI_MEDIA_ENDPOINT:
2444 subTypeStr = val_to_str(subType, media_subtypes, "Unknown subtype 0x%x");
2447 subTypeStr = val_to_str(subType, profinet_subtypes, "Reserved (0x%x)");
2450 subTypeStr = "Unknown";
2456 tf = proto_tree_add_text(tree, tvb, offset, (tempLen + 2), "%s - %s",
2457 ouiStr, subTypeStr);
2458 org_tlv_tree = proto_item_add_subtree(tf, ett_org_spc_tlv);
2460 proto_tree_add_item(org_tlv_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
2465 proto_tree_add_uint_format(org_tlv_tree, hf_lldp_tlv_len, tvb, offset, 2,
2466 tempShort, "TLV Length: %u (too short, must be >= 4)", tempLen);
2468 return (tempLen + 2);
2472 proto_tree_add_item(org_tlv_tree, hf_lldp_tlv_len, tvb, offset, 2, FALSE);
2474 /* Display organizational unique id */
2475 proto_tree_add_uint(org_tlv_tree, hf_org_spc_oui, tvb, (offset+2), 3, oui);
2480 case OUI_IEEE_802_1:
2481 dissect_ieee_802_1_tlv(tvb, pinfo, org_tlv_tree, (offset+5));
2483 case OUI_IEEE_802_3:
2484 dissect_ieee_802_3_tlv(tvb, pinfo, org_tlv_tree, (offset+5));
2486 case OUI_MEDIA_ENDPOINT:
2487 dissect_media_tlv(tvb, pinfo, org_tlv_tree, (offset+5), (guint16) (tempLen-3));
2490 dissect_profinet_tlv(tvb, pinfo, org_tlv_tree, (offset+5), (guint16) (tempLen-3));
2493 proto_tree_add_item(org_tlv_tree, hf_unknown_subtype, tvb, (offset+5), (guint16) (tempLen-3), FALSE);
2496 return (tempLen + 2);
2499 /* Dissect Unknown TLV */
2501 dissect_lldp_unknown_tlv(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint32 offset)
2506 proto_tree *unknown_tlv_tree = NULL;
2507 proto_item *tf = NULL;
2509 /* Get tlv type and length */
2510 tempShort = tvb_get_ntohs(tvb, offset);
2512 /* Get tlv length */
2513 tempLen = TLV_INFO_LEN(tempShort);
2517 tf = proto_tree_add_text(tree, tvb, offset, (tempLen + 2), "Unknown TLV");
2518 unknown_tlv_tree = proto_item_add_subtree(tf, ett_unknown_tlv);
2520 proto_tree_add_item(unknown_tlv_tree, hf_lldp_tlv_type, tvb, offset, 2, FALSE);
2521 proto_tree_add_item(unknown_tlv_tree, hf_lldp_tlv_len, tvb, offset, 2, FALSE);
2524 return (tempLen + 2);
2528 /* Dissect LLDP packets */
2530 dissect_lldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2533 proto_tree *lldp_tree = NULL;
2536 gint32 rtnValue = 0;
2539 gboolean reachedEnd = FALSE;
2541 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LLDP");
2543 /* Clear the information column on summary display */
2544 col_clear(pinfo->cinfo, COL_INFO);
2548 ti = proto_tree_add_item(tree, proto_lldp, tvb, offset, -1, FALSE);
2549 lldp_tree = proto_item_add_subtree(ti, ett_lldp);
2552 /* Get chassis id tlv */
2553 rtnValue = dissect_lldp_chassis_id(tvb, pinfo, lldp_tree, offset);
2556 col_set_str(pinfo->cinfo, COL_INFO, "Invalid Chassis ID TLV");
2563 /* Get port id tlv */
2564 rtnValue = dissect_lldp_port_id(tvb, pinfo, lldp_tree, offset);
2567 col_set_str(pinfo->cinfo, COL_INFO, "Invalid Port ID TLV");
2574 /* Get time to live tlv */
2575 rtnValue = dissect_lldp_time_to_live(tvb, pinfo, lldp_tree, offset);
2578 col_set_str(pinfo->cinfo, COL_INFO, "Invalid Time-to-Live TLV");
2585 /* Dissect optional tlv's until end-of-lldpdu is reached */
2588 tempShort = tvb_get_ntohs(tvb, offset);
2589 tempType = TLV_TYPE(tempShort);
2593 case CHASSIS_ID_TLV_TYPE:
2594 rtnValue = dissect_lldp_chassis_id(tvb, pinfo, lldp_tree, offset);
2595 rtnValue = -1; /* Duplicate chassis id tlv */
2596 col_set_str(pinfo->cinfo, COL_INFO, "Duplicate Chassis ID TLV");
2598 case PORT_ID_TLV_TYPE:
2599 rtnValue = dissect_lldp_port_id(tvb, pinfo, lldp_tree, offset);
2600 rtnValue = -1; /* Duplicate port id tlv */
2601 col_set_str(pinfo->cinfo, COL_INFO, "Duplicate Port ID TLV");
2603 case TIME_TO_LIVE_TLV_TYPE:
2604 rtnValue = dissect_lldp_time_to_live(tvb, pinfo, lldp_tree, offset);
2605 rtnValue = -1; /* Duplicate time-to-live tlv */
2606 col_set_str(pinfo->cinfo, COL_INFO, "Duplicate Time-To-Live TLV");
2608 case END_OF_LLDPDU_TLV_TYPE:
2609 rtnValue = dissect_lldp_end_of_lldpdu(tvb, pinfo, lldp_tree, offset);
2611 case PORT_DESCRIPTION_TLV_TYPE:
2612 rtnValue = dissect_lldp_port_desc(tvb, pinfo, lldp_tree, offset);
2614 case SYSTEM_NAME_TLV_TYPE:
2615 case SYSTEM_DESCRIPTION_TLV_TYPE:
2616 rtnValue = dissect_lldp_system_name(tvb, pinfo, lldp_tree, offset);
2618 case SYSTEM_CAPABILITIES_TLV_TYPE:
2619 rtnValue = dissect_lldp_system_capabilities(tvb, pinfo, lldp_tree, offset);
2621 case MANAGEMENT_ADDR_TLV_TYPE:
2622 rtnValue = dissect_lldp_management_address(tvb, pinfo, lldp_tree, offset);
2624 case ORGANIZATION_SPECIFIC_TLV_TYPE:
2625 rtnValue = dissect_organizational_specific_tlv(tvb, pinfo, lldp_tree, offset);
2628 rtnValue = dissect_lldp_unknown_tlv(tvb, pinfo, lldp_tree, offset);
2640 /* Register the protocol with Wireshark */
2642 proto_register_lldp(void)
2644 /* Setup list of header fields */
2645 static hf_register_info hf[] = {
2646 { &hf_lldp_tlv_type,
2647 { "TLV Type", "lldp.tlv.type", FT_UINT16, BASE_DEC,
2648 VALS(tlv_types), TLV_TYPE_MASK, NULL, HFILL }
2651 { "TLV Length", "lldp.tlv.len", FT_UINT16, BASE_DEC,
2652 NULL, TLV_INFO_LEN_MASK, NULL, HFILL }
2654 { &hf_chassis_id_subtype,
2655 { "Chassis Id Subtype", "lldp.chassis.subtype", FT_UINT8, BASE_DEC,
2656 VALS(chassis_id_subtypes), 0, NULL, HFILL }
2659 { "Chassis Id", "lldp.chassis.id", FT_BYTES, BASE_NONE,
2660 NULL, 0, NULL, HFILL }
2662 { &hf_chassis_id_mac,
2663 { "Chassis Id", "lldp.chassis.id.mac", FT_ETHER, BASE_NONE,
2664 NULL, 0, NULL, HFILL }
2666 { &hf_chassis_id_ip4,
2667 { "Chassis Id", "lldp.chassis.id.ip4", FT_IPv4, BASE_NONE,
2668 NULL, 0, NULL, HFILL }
2670 { &hf_chassis_id_ip6,
2671 { "Chassis Id", "lldp.chassis.id.ip6", FT_IPv6, BASE_NONE,
2672 NULL, 0, NULL, HFILL }
2674 { &hf_port_id_subtype,
2675 { "Port Id Subtype", "lldp.port.subtype", FT_UINT8, BASE_DEC,
2676 VALS(port_id_subtypes), 0, NULL, HFILL }
2679 { "Port Id", "lldp.port.id.mac", FT_ETHER, BASE_NONE,
2680 NULL, 0, NULL, HFILL }
2682 { &hf_lldp_network_address_family,
2683 { "Network Address family", "lldp.network_address.subtype", FT_UINT8, BASE_DEC,
2684 VALS(afn_vals), 0, NULL, HFILL }
2687 { "Port Id", "lldp.port.id.ip4", FT_IPv4, BASE_NONE,
2688 NULL, 0, NULL, HFILL }
2691 { "Port Id", "lldp.port.id.ip6", FT_IPv6, BASE_NONE,
2692 NULL, 0, NULL, HFILL }
2695 { "Seconds", "lldp.time_to_live", FT_UINT16, BASE_DEC,
2696 NULL, 0, NULL, HFILL }
2698 { &hf_mgn_addr_ipv4,
2699 { "Management Address", "lldp.mgn.addr.ip4", FT_IPv4, BASE_NONE,
2700 NULL, 0, NULL, HFILL }
2702 { &hf_mgn_addr_ipv6,
2703 { "Management Address", "lldp.mgn.addr.ip6", FT_IPv6, BASE_NONE,
2704 NULL, 0, NULL, HFILL }
2707 { "Management Address", "lldp.mgn.addr.hex", FT_BYTES, BASE_NONE,
2708 NULL, 0, NULL, HFILL }
2711 { "Object Identifier", "lldp.mgn.obj.id", FT_BYTES, BASE_NONE,
2712 NULL, 0, NULL, HFILL }
2715 { "Organization Unique Code", "lldp.orgtlv.oui", FT_UINT24, BASE_HEX,
2716 VALS(tlv_oui_subtype_vals), 0x0, NULL, HFILL }
2718 { &hf_ieee_802_1_subtype,
2719 { "IEEE 802.1 Subtype", "lldp.ieee.802_1.subtype", FT_UINT8, BASE_HEX,
2720 VALS(ieee_802_1_subtypes), 0x0, NULL, HFILL }
2722 { &hf_ieee_802_3_subtype,
2723 { "IEEE 802.3 Subtype", "lldp.ieee.802_3.subtype", FT_UINT8, BASE_HEX,
2724 VALS(ieee_802_3_subtypes), 0x0, NULL, HFILL }
2726 { &hf_media_tlv_subtype,
2727 { "Media Subtype", "lldp.media.subtype", FT_UINT8, BASE_HEX,
2728 VALS(media_subtypes), 0x0, NULL, HFILL }
2730 { &hf_profinet_tlv_subtype,
2731 { "Subtype", "lldp.profinet.subtype", FT_UINT8, BASE_HEX,
2732 VALS(profinet_subtypes), 0x0, "PROFINET Subtype", HFILL }
2734 { &hf_profinet_port_rx_delay_local,
2735 { "Port RX Delay Local", "lldp.profinet.port_rx_delay_local", FT_UINT32, BASE_DEC,
2736 NULL, 0x0, NULL, HFILL }
2738 { &hf_profinet_port_rx_delay_remote,
2739 { "Port RX Delay Remote", "lldp.profinet.port_rx_delay_remote", FT_UINT32, BASE_DEC,
2740 NULL, 0x0, NULL, HFILL }
2742 { &hf_profinet_port_tx_delay_local,
2743 { "Port TX Delay Local", "lldp.profinet.port_tx_delay_local", FT_UINT32, BASE_DEC,
2744 NULL, 0x0, NULL, HFILL }
2746 { &hf_profinet_port_tx_delay_remote,
2747 { "Port TX Delay Remote", "lldp.profinet.port_tx_delay_remote", FT_UINT32, BASE_DEC,
2748 NULL, 0x0, NULL, HFILL }
2750 { &hf_profinet_cable_delay_local,
2751 { "Port Cable Delay Local", "lldp.profinet.cable_delay_local", FT_UINT32, BASE_DEC,
2752 NULL, 0x0, NULL, HFILL }
2754 { &hf_profinet_class2_port_status,
2755 { "RTClass2 Port Status", "lldp.profinet.rtc2_port_status", FT_UINT16, BASE_HEX,
2756 VALS(profinet_port2_status_vals), 0x0, NULL, HFILL }
2758 { &hf_profinet_class3_port_status,
2759 { "RTClass3 Port Status", "lldp.profinet.rtc3_port_status", FT_UINT16, BASE_HEX,
2760 VALS(profinet_port3_status_vals), 0x0, NULL, HFILL }
2762 { &hf_profinet_mrp_domain_uuid,
2763 { "MRP DomainUUID", "lldp.profinet.mrp_domain_uuid", FT_GUID, BASE_NONE,
2764 NULL, 0x0, NULL, HFILL }
2766 { &hf_profinet_mrrt_port_status,
2767 { "MRRT PortStatus", "lldp.profinet.mrrt_port_status", FT_UINT16, BASE_HEX,
2768 VALS(profinet_mrrt_port_status_vals), 0x0, NULL, HFILL }
2770 { &hf_profinet_cm_mac,
2771 { "CMMacAdd", "lldp.profinet.cm_mac_add", FT_ETHER, BASE_NONE,
2772 NULL, 0x0, "CMResponderMacAdd or CMInitiatorMacAdd", HFILL }
2774 { &hf_profinet_master_source_address,
2775 { "MasterSourceAddress", "lldp.profinet.master_source_address", FT_ETHER, BASE_NONE,
2776 NULL, 0x0, NULL, HFILL }
2778 { &hf_profinet_subdomain_uuid,
2779 { "SubdomainUUID", "lldp.profinet.subdomain_uuid", FT_GUID, BASE_NONE,
2780 NULL, 0x0, NULL, HFILL }
2782 { &hf_profinet_ir_data_uuid,
2783 { "IRDataUUID", "lldp.profinet.ir_data_uuid", FT_GUID, BASE_NONE,
2784 NULL, 0x0, NULL, HFILL }
2786 { &hf_profinet_length_of_period_valid,
2787 { "LengthOfPeriod.Valid", "lldp.profinet.length_of_period_valid", FT_UINT32, BASE_DEC,
2788 NULL, 0x80000000, "Length field is valid/invalid", HFILL }
2790 { &hf_profinet_length_of_period_length,
2791 { "LengthOfPeriod.Length", "lldp.profinet.length_of_period_length", FT_UINT32, BASE_DEC,
2792 NULL, 0x7FFFFFFF, "Duration of a cycle in nanoseconds", HFILL }
2794 { &hf_profinet_red_period_begin_valid,
2795 { "RedPeriodBegin.Valid", "lldp.profinet.red_period_begin_valid", FT_UINT32, BASE_DEC,
2796 NULL, 0x80000000, "Offset field is valid/invalid", HFILL }
2798 { &hf_profinet_red_period_begin_offset,
2799 { "RedPeriodBegin.Offset", "lldp.profinet.red_period_begin_offset", FT_UINT32, BASE_DEC,
2800 NULL, 0x7FFFFFFF, "RT_CLASS_3 period, offset to cycle begin in nanoseconds", HFILL }
2802 { &hf_profinet_orange_period_begin_valid,
2803 { "OrangePeriodBegin.Valid", "lldp.profinet.orange_period_begin_valid", FT_UINT32, BASE_DEC,
2804 NULL, 0x80000000, "Offset field is valid/invalid", HFILL }
2806 { &hf_profinet_orange_period_begin_offset,
2807 { "OrangePeriodBegin.Offset","lldp.profinet.orange_period_begin_offset", FT_UINT32, BASE_DEC,
2808 NULL, 0x7FFFFFFF, "RT_CLASS_2 period, offset to cycle begin in nanoseconds", HFILL }
2810 { &hf_profinet_green_period_begin_valid,
2811 { "GreenPeriodBegin.Valid", "lldp.profinet.green_period_begin_valid", FT_UINT32, BASE_DEC,
2812 NULL, 0x80000000, "Offset field is valid/invalid", HFILL }
2814 { &hf_profinet_green_period_begin_offset,
2815 { "GreenPeriodBegin.Offset", "lldp.profinet.green_period_begin_offset", FT_UINT32, BASE_DEC,
2816 NULL, 0x7FFFFFFF, "Unrestricted period, offset to cycle begin in nanoseconds", HFILL }
2818 { &hf_unknown_subtype,
2819 { "Unknown Subtype Content","lldp.unknown_subtype", FT_BYTES, BASE_NONE,
2820 NULL, 0x0, NULL, HFILL }
2824 /* Setup protocol subtree array */
2825 static gint *ett[] = {
2831 &ett_port_description,
2834 &ett_system_cap_summary,
2835 &ett_system_cap_enabled,
2836 &ett_management_address,
2839 &ett_port_vlan_flags,
2841 &ett_802_3_autoneg_advertised,
2843 &ett_802_3_aggregation,
2844 &ett_media_capabilities,
2845 &ett_profinet_period
2848 /* Register the protocol name and description */
2849 proto_lldp = proto_register_protocol("Link Layer Discovery Protocol", "LLDP", "lldp");
2851 /* Required function calls to register the header fields and subtrees used */
2852 proto_register_field_array(proto_lldp, hf, array_length(hf));
2853 proto_register_subtree_array(ett, array_length(ett));
2857 proto_reg_handoff_lldp(void)
2859 dissector_handle_t lldp_handle;
2861 lldp_handle = create_dissector_handle(dissect_lldp,proto_lldp);
2862 dissector_add("ethertype", ETHERTYPE_LLDP, lldp_handle);