1/*
2 * Copyright (c) 1998-2007 The TCPDUMP project
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that: (1) source code
6 * distributions retain the above copyright notice and this paragraph
7 * in its entirety, and (2) distributions including binary code include
8 * the above copyright notice and this paragraph in its entirety in
9 * the documentation or other materials provided with the distribution.
10 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
11 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
12 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13 * FOR A PARTICULAR PURPOSE.
14 *
15 * Original code by Hannes Gredler (hannes@gredler.at)
16 * IEEE and TIA extensions by Carles Kishimoto <carles.kishimoto@gmail.com>
17 * DCBX extensions by Kaladhar Musunuru <kaladharm@sourceforge.net>
18 */
19
20/* \summary: IEEE 802.1ab Link Layer Discovery Protocol (LLDP) printer */
21
22#include <sys/cdefs.h>
23#ifndef lint
24__RCSID("$NetBSD: print-lldp.c,v 1.10 2023/08/17 20:19:40 christos Exp $");
25#endif
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30
31#include "netdissect-stdinc.h"
32
33#include <stdio.h>
34
35#include "netdissect.h"
36#include "extract.h"
37#include "addrtoname.h"
38#include "af.h"
39#include "oui.h"
40
41#define	LLDP_EXTRACT_TYPE(x) (((x)&0xfe00)>>9)
42#define	LLDP_EXTRACT_LEN(x) ((x)&0x01ff)
43
44/*
45 * TLV type codes
46 */
47#define LLDP_END_TLV             0
48#define LLDP_CHASSIS_ID_TLV      1
49#define LLDP_PORT_ID_TLV         2
50#define LLDP_TTL_TLV             3
51#define LLDP_PORT_DESCR_TLV      4
52#define LLDP_SYSTEM_NAME_TLV     5
53#define LLDP_SYSTEM_DESCR_TLV    6
54#define LLDP_SYSTEM_CAP_TLV      7
55#define LLDP_MGMT_ADDR_TLV       8
56#define LLDP_PRIVATE_TLV       127
57
58static const struct tok lldp_tlv_values[] = {
59    { LLDP_END_TLV, "End" },
60    { LLDP_CHASSIS_ID_TLV, "Chassis ID" },
61    { LLDP_PORT_ID_TLV, "Port ID" },
62    { LLDP_TTL_TLV, "Time to Live" },
63    { LLDP_PORT_DESCR_TLV, "Port Description" },
64    { LLDP_SYSTEM_NAME_TLV, "System Name" },
65    { LLDP_SYSTEM_DESCR_TLV, "System Description" },
66    { LLDP_SYSTEM_CAP_TLV, "System Capabilities" },
67    { LLDP_MGMT_ADDR_TLV, "Management Address" },
68    { LLDP_PRIVATE_TLV, "Organization specific" },
69    { 0, NULL}
70};
71
72/*
73 * Chassis ID subtypes
74 */
75#define LLDP_CHASSIS_CHASSIS_COMP_SUBTYPE  1
76#define LLDP_CHASSIS_INTF_ALIAS_SUBTYPE    2
77#define LLDP_CHASSIS_PORT_COMP_SUBTYPE     3
78#define LLDP_CHASSIS_MAC_ADDR_SUBTYPE      4
79#define LLDP_CHASSIS_NETWORK_ADDR_SUBTYPE  5
80#define LLDP_CHASSIS_INTF_NAME_SUBTYPE     6
81#define LLDP_CHASSIS_LOCAL_SUBTYPE         7
82
83static const struct tok lldp_chassis_subtype_values[] = {
84    { LLDP_CHASSIS_CHASSIS_COMP_SUBTYPE, "Chassis component"},
85    { LLDP_CHASSIS_INTF_ALIAS_SUBTYPE, "Interface alias"},
86    { LLDP_CHASSIS_PORT_COMP_SUBTYPE, "Port component"},
87    { LLDP_CHASSIS_MAC_ADDR_SUBTYPE, "MAC address"},
88    { LLDP_CHASSIS_NETWORK_ADDR_SUBTYPE, "Network address"},
89    { LLDP_CHASSIS_INTF_NAME_SUBTYPE, "Interface name"},
90    { LLDP_CHASSIS_LOCAL_SUBTYPE, "Local"},
91    { 0, NULL}
92};
93
94/*
95 * Port ID subtypes
96 */
97#define LLDP_PORT_INTF_ALIAS_SUBTYPE       1
98#define LLDP_PORT_PORT_COMP_SUBTYPE        2
99#define LLDP_PORT_MAC_ADDR_SUBTYPE         3
100#define LLDP_PORT_NETWORK_ADDR_SUBTYPE     4
101#define LLDP_PORT_INTF_NAME_SUBTYPE        5
102#define LLDP_PORT_AGENT_CIRC_ID_SUBTYPE    6
103#define LLDP_PORT_LOCAL_SUBTYPE            7
104
105static const struct tok lldp_port_subtype_values[] = {
106    { LLDP_PORT_INTF_ALIAS_SUBTYPE, "Interface alias"},
107    { LLDP_PORT_PORT_COMP_SUBTYPE, "Port component"},
108    { LLDP_PORT_MAC_ADDR_SUBTYPE, "MAC address"},
109    { LLDP_PORT_NETWORK_ADDR_SUBTYPE, "Network Address"},
110    { LLDP_PORT_INTF_NAME_SUBTYPE, "Interface Name"},
111    { LLDP_PORT_AGENT_CIRC_ID_SUBTYPE, "Agent circuit ID"},
112    { LLDP_PORT_LOCAL_SUBTYPE, "Local"},
113    { 0, NULL}
114};
115
116/*
117 * System Capabilities
118 */
119#define LLDP_CAP_OTHER              (1 <<  0)
120#define LLDP_CAP_REPEATER           (1 <<  1)
121#define LLDP_CAP_BRIDGE             (1 <<  2)
122#define LLDP_CAP_WLAN_AP            (1 <<  3)
123#define LLDP_CAP_ROUTER             (1 <<  4)
124#define LLDP_CAP_PHONE              (1 <<  5)
125#define LLDP_CAP_DOCSIS             (1 <<  6)
126#define LLDP_CAP_STATION_ONLY       (1 <<  7)
127
128static const struct tok lldp_cap_values[] = {
129    { LLDP_CAP_OTHER, "Other"},
130    { LLDP_CAP_REPEATER, "Repeater"},
131    { LLDP_CAP_BRIDGE, "Bridge"},
132    { LLDP_CAP_WLAN_AP, "WLAN AP"},
133    { LLDP_CAP_ROUTER, "Router"},
134    { LLDP_CAP_PHONE, "Telephone"},
135    { LLDP_CAP_DOCSIS, "Docsis"},
136    { LLDP_CAP_STATION_ONLY, "Station Only"},
137    { 0, NULL}
138};
139
140#define LLDP_PRIVATE_8021_SUBTYPE_PORT_VLAN_ID		1
141#define LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_VLAN_ID	2
142#define LLDP_PRIVATE_8021_SUBTYPE_VLAN_NAME		3
143#define LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_IDENTITY	4
144#define LLDP_PRIVATE_8021_SUBTYPE_LINKAGGR		7
145#define LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION 8
146#define LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION       9
147#define LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION     10
148#define LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION      11
149#define LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY   12
150#define LLDP_PRIVATE_8021_SUBTYPE_EVB                    13
151#define LLDP_PRIVATE_8021_SUBTYPE_CDCP			 14
152
153static const struct tok lldp_8021_subtype_values[] = {
154    { LLDP_PRIVATE_8021_SUBTYPE_PORT_VLAN_ID, "Port VLAN Id"},
155    { LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_VLAN_ID, "Port and Protocol VLAN ID"},
156    { LLDP_PRIVATE_8021_SUBTYPE_VLAN_NAME, "VLAN name"},
157    { LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_IDENTITY, "Protocol Identity"},
158    { LLDP_PRIVATE_8021_SUBTYPE_LINKAGGR, "Link aggregation"},
159    { LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION, "Congestion Notification"},
160    { LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION, "ETS Configuration"},
161    { LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION, "ETS Recommendation"},
162    { LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION, "Priority Flow Control Configuration"},
163    { LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY, "Application Priority"},
164    { LLDP_PRIVATE_8021_SUBTYPE_EVB, "EVB"},
165    { LLDP_PRIVATE_8021_SUBTYPE_CDCP,"CDCP"},
166    { 0, NULL}
167};
168
169#define LLDP_8021_PORT_PROTOCOL_VLAN_SUPPORT       (1 <<  1)
170#define LLDP_8021_PORT_PROTOCOL_VLAN_STATUS        (1 <<  2)
171
172static const struct tok lldp_8021_port_protocol_id_values[] = {
173    { LLDP_8021_PORT_PROTOCOL_VLAN_SUPPORT, "supported"},
174    { LLDP_8021_PORT_PROTOCOL_VLAN_STATUS, "enabled"},
175    { 0, NULL}
176};
177
178#define LLDP_PRIVATE_8023_SUBTYPE_MACPHY        1
179#define LLDP_PRIVATE_8023_SUBTYPE_MDIPOWER      2
180#define LLDP_PRIVATE_8023_SUBTYPE_LINKAGGR      3
181#define LLDP_PRIVATE_8023_SUBTYPE_MTU           4
182
183static const struct tok lldp_8023_subtype_values[] = {
184    { LLDP_PRIVATE_8023_SUBTYPE_MACPHY,	"MAC/PHY configuration/status"},
185    { LLDP_PRIVATE_8023_SUBTYPE_MDIPOWER, "Power via MDI"},
186    { LLDP_PRIVATE_8023_SUBTYPE_LINKAGGR, "Link aggregation"},
187    { LLDP_PRIVATE_8023_SUBTYPE_MTU, "Max frame size"},
188    { 0, NULL}
189};
190
191#define LLDP_PRIVATE_TIA_SUBTYPE_CAPABILITIES                   1
192#define LLDP_PRIVATE_TIA_SUBTYPE_NETWORK_POLICY                 2
193#define LLDP_PRIVATE_TIA_SUBTYPE_LOCAL_ID                       3
194#define LLDP_PRIVATE_TIA_SUBTYPE_EXTENDED_POWER_MDI             4
195#define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV         5
196#define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV         6
197#define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV         7
198#define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER        8
199#define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME    9
200#define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME           10
201#define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID             11
202
203static const struct tok lldp_tia_subtype_values[] = {
204    { LLDP_PRIVATE_TIA_SUBTYPE_CAPABILITIES, "LLDP-MED Capabilities" },
205    { LLDP_PRIVATE_TIA_SUBTYPE_NETWORK_POLICY, "Network policy" },
206    { LLDP_PRIVATE_TIA_SUBTYPE_LOCAL_ID, "Location identification" },
207    { LLDP_PRIVATE_TIA_SUBTYPE_EXTENDED_POWER_MDI, "Extended power-via-MDI" },
208    { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV, "Inventory - hardware revision" },
209    { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV, "Inventory - firmware revision" },
210    { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV, "Inventory - software revision" },
211    { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER, "Inventory - serial number" },
212    { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME, "Inventory - manufacturer name" },
213    { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME, "Inventory - model name" },
214    { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID, "Inventory - asset ID" },
215    { 0, NULL}
216};
217
218#define LLDP_PRIVATE_TIA_LOCATION_ALTITUDE_METERS       1
219#define LLDP_PRIVATE_TIA_LOCATION_ALTITUDE_FLOORS       2
220
221static const struct tok lldp_tia_location_altitude_type_values[] = {
222    { LLDP_PRIVATE_TIA_LOCATION_ALTITUDE_METERS, "meters"},
223    { LLDP_PRIVATE_TIA_LOCATION_ALTITUDE_FLOORS, "floors"},
224    { 0, NULL}
225};
226
227/* ANSI/TIA-1057 - Annex B */
228#define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A1		1
229#define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A2		2
230#define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A3		3
231#define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A4		4
232#define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A5		5
233#define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A6		6
234
235static const struct tok lldp_tia_location_lci_catype_values[] = {
236    { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A1, "national subdivisions (state,canton,region,province,prefecture)"},
237    { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A2, "county, parish, gun, district"},
238    { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A3, "city, township, shi"},
239    { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A4, "city division, borough, city district, ward chou"},
240    { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A5, "neighborhood, block"},
241    { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A6, "street"},
242    { 0, NULL}
243};
244
245static const struct tok lldp_tia_location_lci_what_values[] = {
246    { 0, "location of DHCP server"},
247    { 1, "location of the network element believed to be closest to the client"},
248    { 2, "location of the client"},
249    { 0, NULL}
250};
251
252/*
253 * From RFC 3636 - dot3MauType
254 */
255#define		LLDP_MAU_TYPE_UNKNOWN		0
256#define		LLDP_MAU_TYPE_AUI		1
257#define		LLDP_MAU_TYPE_10BASE_5		2
258#define		LLDP_MAU_TYPE_FOIRL		3
259#define		LLDP_MAU_TYPE_10BASE_2		4
260#define		LLDP_MAU_TYPE_10BASE_T		5
261#define		LLDP_MAU_TYPE_10BASE_FP		6
262#define		LLDP_MAU_TYPE_10BASE_FB		7
263#define		LLDP_MAU_TYPE_10BASE_FL		8
264#define		LLDP_MAU_TYPE_10BROAD36		9
265#define		LLDP_MAU_TYPE_10BASE_T_HD	10
266#define		LLDP_MAU_TYPE_10BASE_T_FD	11
267#define		LLDP_MAU_TYPE_10BASE_FL_HD	12
268#define		LLDP_MAU_TYPE_10BASE_FL_FD	13
269#define		LLDP_MAU_TYPE_100BASE_T4	14
270#define		LLDP_MAU_TYPE_100BASE_TX_HD	15
271#define		LLDP_MAU_TYPE_100BASE_TX_FD	16
272#define		LLDP_MAU_TYPE_100BASE_FX_HD	17
273#define		LLDP_MAU_TYPE_100BASE_FX_FD	18
274#define		LLDP_MAU_TYPE_100BASE_T2_HD	19
275#define		LLDP_MAU_TYPE_100BASE_T2_FD	20
276#define		LLDP_MAU_TYPE_1000BASE_X_HD	21
277#define		LLDP_MAU_TYPE_1000BASE_X_FD	22
278#define		LLDP_MAU_TYPE_1000BASE_LX_HD	23
279#define		LLDP_MAU_TYPE_1000BASE_LX_FD	24
280#define		LLDP_MAU_TYPE_1000BASE_SX_HD	25
281#define		LLDP_MAU_TYPE_1000BASE_SX_FD	26
282#define		LLDP_MAU_TYPE_1000BASE_CX_HD	27
283#define		LLDP_MAU_TYPE_1000BASE_CX_FD	28
284#define		LLDP_MAU_TYPE_1000BASE_T_HD	29
285#define		LLDP_MAU_TYPE_1000BASE_T_FD	30
286#define		LLDP_MAU_TYPE_10GBASE_X		31
287#define		LLDP_MAU_TYPE_10GBASE_LX4	32
288#define		LLDP_MAU_TYPE_10GBASE_R		33
289#define		LLDP_MAU_TYPE_10GBASE_ER	34
290#define		LLDP_MAU_TYPE_10GBASE_LR	35
291#define		LLDP_MAU_TYPE_10GBASE_SR	36
292#define		LLDP_MAU_TYPE_10GBASE_W		37
293#define		LLDP_MAU_TYPE_10GBASE_EW	38
294#define		LLDP_MAU_TYPE_10GBASE_LW	39
295#define		LLDP_MAU_TYPE_10GBASE_SW	40
296
297static const struct tok lldp_mau_types_values[] = {
298    { LLDP_MAU_TYPE_UNKNOWN,            "Unknown"},
299    { LLDP_MAU_TYPE_AUI,                "AUI"},
300    { LLDP_MAU_TYPE_10BASE_5,           "10BASE_5"},
301    { LLDP_MAU_TYPE_FOIRL,              "FOIRL"},
302    { LLDP_MAU_TYPE_10BASE_2,           "10BASE2"},
303    { LLDP_MAU_TYPE_10BASE_T,           "10BASET duplex mode unknown"},
304    { LLDP_MAU_TYPE_10BASE_FP,          "10BASEFP"},
305    { LLDP_MAU_TYPE_10BASE_FB,          "10BASEFB"},
306    { LLDP_MAU_TYPE_10BASE_FL,          "10BASEFL duplex mode unknown"},
307    { LLDP_MAU_TYPE_10BROAD36,          "10BROAD36"},
308    { LLDP_MAU_TYPE_10BASE_T_HD,        "10BASET hdx"},
309    { LLDP_MAU_TYPE_10BASE_T_FD,        "10BASET fdx"},
310    { LLDP_MAU_TYPE_10BASE_FL_HD,       "10BASEFL hdx"},
311    { LLDP_MAU_TYPE_10BASE_FL_FD,       "10BASEFL fdx"},
312    { LLDP_MAU_TYPE_100BASE_T4,         "100BASET4"},
313    { LLDP_MAU_TYPE_100BASE_TX_HD,      "100BASETX hdx"},
314    { LLDP_MAU_TYPE_100BASE_TX_FD,      "100BASETX fdx"},
315    { LLDP_MAU_TYPE_100BASE_FX_HD,      "100BASEFX hdx"},
316    { LLDP_MAU_TYPE_100BASE_FX_FD,      "100BASEFX fdx"},
317    { LLDP_MAU_TYPE_100BASE_T2_HD,      "100BASET2 hdx"},
318    { LLDP_MAU_TYPE_100BASE_T2_FD,      "100BASET2 fdx"},
319    { LLDP_MAU_TYPE_1000BASE_X_HD,      "1000BASEX hdx"},
320    { LLDP_MAU_TYPE_1000BASE_X_FD,      "1000BASEX fdx"},
321    { LLDP_MAU_TYPE_1000BASE_LX_HD,     "1000BASELX hdx"},
322    { LLDP_MAU_TYPE_1000BASE_LX_FD,     "1000BASELX fdx"},
323    { LLDP_MAU_TYPE_1000BASE_SX_HD,     "1000BASESX hdx"},
324    { LLDP_MAU_TYPE_1000BASE_SX_FD,     "1000BASESX fdx"},
325    { LLDP_MAU_TYPE_1000BASE_CX_HD,     "1000BASECX hdx"},
326    { LLDP_MAU_TYPE_1000BASE_CX_FD,     "1000BASECX fdx"},
327    { LLDP_MAU_TYPE_1000BASE_T_HD,      "1000BASET hdx"},
328    { LLDP_MAU_TYPE_1000BASE_T_FD,      "1000BASET fdx"},
329    { LLDP_MAU_TYPE_10GBASE_X,          "10GBASEX"},
330    { LLDP_MAU_TYPE_10GBASE_LX4,        "10GBASELX4"},
331    { LLDP_MAU_TYPE_10GBASE_R,          "10GBASER"},
332    { LLDP_MAU_TYPE_10GBASE_ER,         "10GBASEER"},
333    { LLDP_MAU_TYPE_10GBASE_LR,         "10GBASELR"},
334    { LLDP_MAU_TYPE_10GBASE_SR,         "10GBASESR"},
335    { LLDP_MAU_TYPE_10GBASE_W,          "10GBASEW"},
336    { LLDP_MAU_TYPE_10GBASE_EW,         "10GBASEEW"},
337    { LLDP_MAU_TYPE_10GBASE_LW,         "10GBASELW"},
338    { LLDP_MAU_TYPE_10GBASE_SW,         "10GBASESW"},
339    { 0, NULL}
340};
341
342#define LLDP_8023_AUTONEGOTIATION_SUPPORT       (1 <<  0)
343#define LLDP_8023_AUTONEGOTIATION_STATUS        (1 <<  1)
344
345static const struct tok lldp_8023_autonegotiation_values[] = {
346    { LLDP_8023_AUTONEGOTIATION_SUPPORT, "supported"},
347    { LLDP_8023_AUTONEGOTIATION_STATUS, "enabled"},
348    { 0, NULL}
349};
350
351#define LLDP_TIA_CAPABILITY_MED                         (1 <<  0)
352#define LLDP_TIA_CAPABILITY_NETWORK_POLICY              (1 <<  1)
353#define LLDP_TIA_CAPABILITY_LOCATION_IDENTIFICATION     (1 <<  2)
354#define LLDP_TIA_CAPABILITY_EXTENDED_POWER_MDI_PSE      (1 <<  3)
355#define LLDP_TIA_CAPABILITY_EXTENDED_POWER_MDI_PD       (1 <<  4)
356#define LLDP_TIA_CAPABILITY_INVENTORY                   (1 <<  5)
357
358static const struct tok lldp_tia_capabilities_values[] = {
359    { LLDP_TIA_CAPABILITY_MED, "LLDP-MED capabilities"},
360    { LLDP_TIA_CAPABILITY_NETWORK_POLICY, "network policy"},
361    { LLDP_TIA_CAPABILITY_LOCATION_IDENTIFICATION, "location identification"},
362    { LLDP_TIA_CAPABILITY_EXTENDED_POWER_MDI_PSE, "extended power via MDI-PSE"},
363    { LLDP_TIA_CAPABILITY_EXTENDED_POWER_MDI_PD, "extended power via MDI-PD"},
364    { LLDP_TIA_CAPABILITY_INVENTORY, "Inventory"},
365    { 0, NULL}
366};
367
368#define LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_1           1
369#define LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_2           2
370#define LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_3           3
371#define LLDP_TIA_DEVICE_TYPE_NETWORK_CONNECTIVITY       4
372
373static const struct tok lldp_tia_device_type_values[] = {
374    { LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_1, "endpoint class 1"},
375    { LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_2, "endpoint class 2"},
376    { LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_3, "endpoint class 3"},
377    { LLDP_TIA_DEVICE_TYPE_NETWORK_CONNECTIVITY, "network connectivity"},
378    { 0, NULL}
379};
380
381#define LLDP_TIA_APPLICATION_TYPE_VOICE                 1
382#define LLDP_TIA_APPLICATION_TYPE_VOICE_SIGNALING       2
383#define LLDP_TIA_APPLICATION_TYPE_GUEST_VOICE           3
384#define LLDP_TIA_APPLICATION_TYPE_GUEST_VOICE_SIGNALING 4
385#define LLDP_TIA_APPLICATION_TYPE_SOFTPHONE_VOICE       5
386#define LLDP_TIA_APPLICATION_TYPE_VIDEO_CONFERENCING    6
387#define LLDP_TIA_APPLICATION_TYPE_STREAMING_VIDEO       7
388#define LLDP_TIA_APPLICATION_TYPE_VIDEO_SIGNALING       8
389
390static const struct tok lldp_tia_application_type_values[] = {
391    { LLDP_TIA_APPLICATION_TYPE_VOICE, "voice"},
392    { LLDP_TIA_APPLICATION_TYPE_VOICE_SIGNALING, "voice signaling"},
393    { LLDP_TIA_APPLICATION_TYPE_GUEST_VOICE, "guest voice"},
394    { LLDP_TIA_APPLICATION_TYPE_GUEST_VOICE_SIGNALING, "guest voice signaling"},
395    { LLDP_TIA_APPLICATION_TYPE_SOFTPHONE_VOICE, "softphone voice"},
396    { LLDP_TIA_APPLICATION_TYPE_VIDEO_CONFERENCING, "video conferencing"},
397    { LLDP_TIA_APPLICATION_TYPE_STREAMING_VIDEO, "streaming video"},
398    { LLDP_TIA_APPLICATION_TYPE_VIDEO_SIGNALING, "video signaling"},
399    { 0, NULL}
400};
401
402#define LLDP_TIA_NETWORK_POLICY_X_BIT           (1 << 5)
403#define LLDP_TIA_NETWORK_POLICY_T_BIT           (1 << 6)
404#define LLDP_TIA_NETWORK_POLICY_U_BIT           (1 << 7)
405
406static const struct tok lldp_tia_network_policy_bits_values[] = {
407    { LLDP_TIA_NETWORK_POLICY_U_BIT, "Unknown"},
408    { LLDP_TIA_NETWORK_POLICY_T_BIT, "Tagged"},
409    { LLDP_TIA_NETWORK_POLICY_X_BIT, "reserved"},
410    { 0, NULL}
411};
412
413#define LLDP_EXTRACT_NETWORK_POLICY_VLAN(x)           (((x)&0x1ffe)>>1)
414#define LLDP_EXTRACT_NETWORK_POLICY_L2_PRIORITY(x)    (((x)&0x01ff)>>6)
415#define LLDP_EXTRACT_NETWORK_POLICY_DSCP(x)           ((x)&0x003f)
416
417#define LLDP_TIA_LOCATION_DATA_FORMAT_COORDINATE_BASED  1
418#define LLDP_TIA_LOCATION_DATA_FORMAT_CIVIC_ADDRESS     2
419#define LLDP_TIA_LOCATION_DATA_FORMAT_ECS_ELIN          3
420
421static const struct tok lldp_tia_location_data_format_values[] = {
422    { LLDP_TIA_LOCATION_DATA_FORMAT_COORDINATE_BASED, "coordinate-based LCI"},
423    { LLDP_TIA_LOCATION_DATA_FORMAT_CIVIC_ADDRESS, "civic address LCI"},
424    { LLDP_TIA_LOCATION_DATA_FORMAT_ECS_ELIN, "ECS ELIN"},
425    { 0, NULL}
426};
427
428#define LLDP_TIA_LOCATION_DATUM_WGS_84          1
429#define LLDP_TIA_LOCATION_DATUM_NAD_83_NAVD_88  2
430#define LLDP_TIA_LOCATION_DATUM_NAD_83_MLLW     3
431
432static const struct tok lldp_tia_location_datum_type_values[] = {
433    { LLDP_TIA_LOCATION_DATUM_WGS_84, "World Geodesic System 1984"},
434    { LLDP_TIA_LOCATION_DATUM_NAD_83_NAVD_88, "North American Datum 1983 (NAVD88)"},
435    { LLDP_TIA_LOCATION_DATUM_NAD_83_MLLW, "North American Datum 1983 (MLLW)"},
436    { 0, NULL}
437};
438
439#define LLDP_TIA_POWER_SOURCE_PSE               1
440#define LLDP_TIA_POWER_SOURCE_LOCAL             2
441#define LLDP_TIA_POWER_SOURCE_PSE_AND_LOCAL     3
442
443static const struct tok lldp_tia_power_source_values[] = {
444    { LLDP_TIA_POWER_SOURCE_PSE, "PSE - primary power source"},
445    { LLDP_TIA_POWER_SOURCE_LOCAL, "local - backup power source"},
446    { LLDP_TIA_POWER_SOURCE_PSE_AND_LOCAL, "PSE+local - reserved"},
447    { 0, NULL}
448};
449
450#define LLDP_TIA_POWER_PRIORITY_CRITICAL        1
451#define LLDP_TIA_POWER_PRIORITY_HIGH            2
452#define LLDP_TIA_POWER_PRIORITY_LOW             3
453
454static const struct tok lldp_tia_power_priority_values[] = {
455    { LLDP_TIA_POWER_PRIORITY_CRITICAL, "critical"},
456    { LLDP_TIA_POWER_PRIORITY_HIGH, "high"},
457    { LLDP_TIA_POWER_PRIORITY_LOW, "low"},
458    { 0, NULL}
459};
460
461#define LLDP_TIA_POWER_VAL_MAX               1024
462
463static const struct tok lldp_tia_inventory_values[] = {
464    { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV, "Hardware revision" },
465    { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV, "Firmware revision" },
466    { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV, "Software revision" },
467    { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER, "Serial number" },
468    { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME, "Manufacturer name" },
469    { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME, "Model name" },
470    { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID, "Asset ID" },
471    { 0, NULL}
472};
473
474/*
475 * From RFC 3636 - ifMauAutoNegCapAdvertisedBits
476 */
477#define	 LLDP_MAU_PMD_OTHER			(1 <<  15)
478#define	 LLDP_MAU_PMD_10BASE_T			(1 <<  14)
479#define	 LLDP_MAU_PMD_10BASE_T_FD		(1 <<  13)
480#define	 LLDP_MAU_PMD_100BASE_T4		(1 <<  12)
481#define	 LLDP_MAU_PMD_100BASE_TX		(1 <<  11)
482#define	 LLDP_MAU_PMD_100BASE_TX_FD		(1 <<  10)
483#define	 LLDP_MAU_PMD_100BASE_T2		(1 <<  9)
484#define	 LLDP_MAU_PMD_100BASE_T2_FD		(1 <<  8)
485#define	 LLDP_MAU_PMD_FDXPAUSE			(1 <<  7)
486#define	 LLDP_MAU_PMD_FDXAPAUSE			(1 <<  6)
487#define	 LLDP_MAU_PMD_FDXSPAUSE			(1 <<  5)
488#define	 LLDP_MAU_PMD_FDXBPAUSE			(1 <<  4)
489#define	 LLDP_MAU_PMD_1000BASE_X		(1 <<  3)
490#define	 LLDP_MAU_PMD_1000BASE_X_FD		(1 <<  2)
491#define	 LLDP_MAU_PMD_1000BASE_T		(1 <<  1)
492#define	 LLDP_MAU_PMD_1000BASE_T_FD		(1 <<  0)
493
494static const struct tok lldp_pmd_capability_values[] = {
495    { LLDP_MAU_PMD_10BASE_T,		"10BASE-T hdx"},
496    { LLDP_MAU_PMD_10BASE_T_FD,	        "10BASE-T fdx"},
497    { LLDP_MAU_PMD_100BASE_T4,		"100BASE-T4"},
498    { LLDP_MAU_PMD_100BASE_TX,		"100BASE-TX hdx"},
499    { LLDP_MAU_PMD_100BASE_TX_FD,	"100BASE-TX fdx"},
500    { LLDP_MAU_PMD_100BASE_T2,		"100BASE-T2 hdx"},
501    { LLDP_MAU_PMD_100BASE_T2_FD,	"100BASE-T2 fdx"},
502    { LLDP_MAU_PMD_FDXPAUSE,		"Pause for fdx links"},
503    { LLDP_MAU_PMD_FDXAPAUSE,		"Asym PAUSE for fdx"},
504    { LLDP_MAU_PMD_FDXSPAUSE,		"Sym PAUSE for fdx"},
505    { LLDP_MAU_PMD_FDXBPAUSE,		"Asym and Sym PAUSE for fdx"},
506    { LLDP_MAU_PMD_1000BASE_X,		"1000BASE-{X LX SX CX} hdx"},
507    { LLDP_MAU_PMD_1000BASE_X_FD,	"1000BASE-{X LX SX CX} fdx"},
508    { LLDP_MAU_PMD_1000BASE_T,		"1000BASE-T hdx"},
509    { LLDP_MAU_PMD_1000BASE_T_FD,	"1000BASE-T fdx"},
510    { 0, NULL}
511};
512
513#define	LLDP_MDI_PORT_CLASS			(1 <<  0)
514#define	LLDP_MDI_POWER_SUPPORT			(1 <<  1)
515#define LLDP_MDI_POWER_STATE			(1 <<  2)
516#define LLDP_MDI_PAIR_CONTROL_ABILITY		(1 <<  3)
517
518static const struct tok lldp_mdi_values[] = {
519    { LLDP_MDI_PORT_CLASS,		"PSE"},
520    { LLDP_MDI_POWER_SUPPORT,		"supported"},
521    { LLDP_MDI_POWER_STATE,		"enabled"},
522    { LLDP_MDI_PAIR_CONTROL_ABILITY,	"can be controlled"},
523    { 0, NULL}
524};
525
526#define LLDP_MDI_PSE_PORT_POWER_PAIRS_SIGNAL	1
527#define LLDP_MDI_PSE_PORT_POWER_PAIRS_SPARE	2
528
529static const struct tok lldp_mdi_power_pairs_values[] = {
530    { LLDP_MDI_PSE_PORT_POWER_PAIRS_SIGNAL,	"signal"},
531    { LLDP_MDI_PSE_PORT_POWER_PAIRS_SPARE,	"spare"},
532    { 0, NULL}
533};
534
535#define LLDP_MDI_POWER_CLASS0		1
536#define LLDP_MDI_POWER_CLASS1		2
537#define LLDP_MDI_POWER_CLASS2		3
538#define LLDP_MDI_POWER_CLASS3		4
539#define LLDP_MDI_POWER_CLASS4		5
540
541static const struct tok lldp_mdi_power_class_values[] = {
542    { LLDP_MDI_POWER_CLASS0,     "class0"},
543    { LLDP_MDI_POWER_CLASS1,     "class1"},
544    { LLDP_MDI_POWER_CLASS2,     "class2"},
545    { LLDP_MDI_POWER_CLASS3,     "class3"},
546    { LLDP_MDI_POWER_CLASS4,     "class4"},
547    { 0, NULL}
548};
549
550#define LLDP_AGGREGATION_CAPABILITY     (1 <<  0)
551#define LLDP_AGGREGATION_STATUS         (1 <<  1)
552
553static const struct tok lldp_aggregation_values[] = {
554    { LLDP_AGGREGATION_CAPABILITY, "supported"},
555    { LLDP_AGGREGATION_STATUS, "enabled"},
556    { 0, NULL}
557};
558
559/*
560 * DCBX protocol subtypes.
561 */
562#define LLDP_DCBX_SUBTYPE_1                1
563#define LLDP_DCBX_SUBTYPE_2                2
564
565static const struct tok lldp_dcbx_subtype_values[] = {
566    { LLDP_DCBX_SUBTYPE_1, "DCB Capability Exchange Protocol Rev 1" },
567    { LLDP_DCBX_SUBTYPE_2, "DCB Capability Exchange Protocol Rev 1.01" },
568    { 0, NULL}
569};
570
571#define LLDP_DCBX_CONTROL_TLV                1
572#define LLDP_DCBX_PRIORITY_GROUPS_TLV        2
573#define LLDP_DCBX_PRIORITY_FLOW_CONTROL_TLV  3
574#define LLDP_DCBX_APPLICATION_TLV            4
575
576/*
577 * Interface numbering subtypes.
578 */
579#define LLDP_INTF_NUMB_IFX_SUBTYPE         2
580#define LLDP_INTF_NUMB_SYSPORT_SUBTYPE     3
581
582static const struct tok lldp_intf_numb_subtype_values[] = {
583    { LLDP_INTF_NUMB_IFX_SUBTYPE, "Interface Index" },
584    { LLDP_INTF_NUMB_SYSPORT_SUBTYPE, "System Port Number" },
585    { 0, NULL}
586};
587
588#define LLDP_INTF_NUM_LEN                  5
589
590#define LLDP_EVB_MODE_NOT_SUPPORTED	0
591#define LLDP_EVB_MODE_EVB_BRIDGE	1
592#define LLDP_EVB_MODE_EVB_STATION	2
593#define LLDP_EVB_MODE_RESERVED		3
594
595static const struct tok lldp_evb_mode_values[]={
596    { LLDP_EVB_MODE_NOT_SUPPORTED, "Not Supported"},
597    { LLDP_EVB_MODE_EVB_BRIDGE, "EVB Bridge"},
598    { LLDP_EVB_MODE_EVB_STATION, "EVB Station"},
599    { LLDP_EVB_MODE_RESERVED, "Reserved for future Standardization"},
600    { 0, NULL},
601};
602
603#define NO_OF_BITS 8
604#define LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION_LENGTH  6
605#define LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION_LENGTH       25
606#define LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION_LENGTH      25
607#define LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION_LENGTH        6
608#define LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY_MIN_LENGTH 5
609#define LLDP_PRIVATE_8021_SUBTYPE_EVB_LENGTH                      9
610#define LLDP_PRIVATE_8021_SUBTYPE_CDCP_MIN_LENGTH                 8
611
612#define LLDP_IANA_SUBTYPE_MUDURL 1
613
614static const struct tok lldp_iana_subtype_values[] =   {
615    { LLDP_IANA_SUBTYPE_MUDURL, "MUD-URL" },
616    { 0, NULL }
617};
618
619
620static void
621print_ets_priority_assignment_table(netdissect_options *ndo,
622                                    const u_char *ptr)
623{
624    ND_PRINT("\n\t    Priority Assignment Table");
625    ND_PRINT("\n\t     Priority : 0   1   2   3   4   5   6   7");
626    ND_PRINT("\n\t     Value    : %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d",
627              GET_U_1(ptr) >> 4, GET_U_1(ptr) & 0x0f,
628              GET_U_1(ptr + 1) >> 4, GET_U_1(ptr + 1) & 0x0f,
629              GET_U_1(ptr + 2) >> 4, GET_U_1(ptr + 2) & 0x0f,
630              GET_U_1(ptr + 3) >> 4, GET_U_1(ptr + 3) & 0x0f);
631}
632
633static void
634print_tc_bandwidth_table(netdissect_options *ndo,
635                         const u_char *ptr)
636{
637    ND_PRINT("\n\t    TC Bandwidth Table");
638    ND_PRINT("\n\t     TC%%   : 0   1   2   3   4   5   6   7");
639    ND_PRINT("\n\t     Value : %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d",
640              GET_U_1(ptr), GET_U_1(ptr + 1), GET_U_1(ptr + 2),
641              GET_U_1(ptr + 3), GET_U_1(ptr + 4), GET_U_1(ptr + 5),
642              GET_U_1(ptr + 6), GET_U_1(ptr + 7));
643}
644
645static void
646print_tsa_assignment_table(netdissect_options *ndo,
647                           const u_char *ptr)
648{
649    ND_PRINT("\n\t    TSA Assignment Table");
650    ND_PRINT("\n\t     Traffic Class: 0   1   2   3   4   5   6   7");
651    ND_PRINT("\n\t     Value        : %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d",
652              GET_U_1(ptr), GET_U_1(ptr + 1), GET_U_1(ptr + 2),
653              GET_U_1(ptr + 3), GET_U_1(ptr + 4), GET_U_1(ptr + 5),
654              GET_U_1(ptr + 6), GET_U_1(ptr + 7));
655}
656
657/*
658 * Print IEEE 802.1 private extensions. (802.1AB annex E)
659 */
660static int
661lldp_private_8021_print(netdissect_options *ndo,
662                        const u_char *tptr, u_int tlv_len)
663{
664    int hexdump = FALSE;
665    u_int subtype;
666    u_int sublen;
667    u_int tval;
668    u_int i;
669
670    if (tlv_len < 4) {
671        return hexdump;
672    }
673    subtype = GET_U_1(tptr + 3);
674
675    ND_PRINT("\n\t  %s Subtype (%u)",
676           tok2str(lldp_8021_subtype_values, "unknown", subtype),
677           subtype);
678
679    switch (subtype) {
680    case LLDP_PRIVATE_8021_SUBTYPE_PORT_VLAN_ID:
681        if (tlv_len < 6) {
682            return hexdump;
683        }
684        ND_PRINT("\n\t    port vlan id (PVID): %u",
685               GET_BE_U_2(tptr + 4));
686        break;
687    case LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_VLAN_ID:
688        if (tlv_len < 7) {
689            return hexdump;
690        }
691        ND_PRINT("\n\t    port and protocol vlan id (PPVID): %u, flags [%s] (0x%02x)",
692               GET_BE_U_2(tptr + 5),
693               bittok2str(lldp_8021_port_protocol_id_values, "none", GET_U_1(tptr + 4)),
694               GET_U_1(tptr + 4));
695        break;
696    case LLDP_PRIVATE_8021_SUBTYPE_VLAN_NAME:
697        if (tlv_len < 6) {
698            return hexdump;
699        }
700        ND_PRINT("\n\t    vlan id (VID): %u", GET_BE_U_2(tptr + 4));
701        if (tlv_len < 7) {
702            return hexdump;
703        }
704        sublen = GET_U_1(tptr + 6);
705        if (tlv_len < 7+sublen) {
706            return hexdump;
707        }
708        ND_PRINT("\n\t    vlan name: ");
709        nd_printjnp(ndo, tptr + 7, sublen);
710        break;
711    case LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_IDENTITY:
712        if (tlv_len < 5) {
713            return hexdump;
714        }
715        sublen = GET_U_1(tptr + 4);
716        if (tlv_len < 5+sublen) {
717            return hexdump;
718        }
719        ND_PRINT("\n\t    protocol identity: ");
720        nd_printjnp(ndo, tptr + 5, sublen);
721        break;
722
723    case LLDP_PRIVATE_8021_SUBTYPE_LINKAGGR:
724        if (tlv_len < 9) {
725            return hexdump;
726        }
727        ND_PRINT("\n\t    aggregation status [%s], aggregation port ID %u",
728               bittok2str(lldp_aggregation_values, "none", GET_U_1((tptr + 4))),
729               GET_BE_U_4(tptr + 5));
730        break;
731
732    case LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION:
733        if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION_LENGTH){
734		return hexdump;
735        }
736        tval=GET_U_1(tptr + 4);
737        ND_PRINT("\n\t    Pre-Priority CNPV Indicator");
738        ND_PRINT("\n\t     Priority : 0  1  2  3  4  5  6  7");
739        ND_PRINT("\n\t     Value    : ");
740        for(i=0;i<NO_OF_BITS;i++)
741            ND_PRINT("%-2d ", (tval >> i) & 0x01);
742        tval=GET_U_1(tptr + 5);
743        ND_PRINT("\n\t    Pre-Priority Ready Indicator");
744        ND_PRINT("\n\t     Priority : 0  1  2  3  4  5  6  7");
745        ND_PRINT("\n\t     Value    : ");
746        for(i=0;i<NO_OF_BITS;i++)
747            ND_PRINT("%-2d ", (tval >> i) & 0x01);
748        break;
749
750    case LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION:
751        if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION_LENGTH) {
752            return hexdump;
753        }
754        tval=GET_U_1(tptr + 4);
755        ND_PRINT("\n\t    Willing:%u, CBS:%u, RES:%u, Max TCs:%u",
756		tval >> 7, (tval >> 6) & 0x02, (tval >> 3) & 0x07, tval & 0x07);
757
758        /*Print Priority Assignment Table*/
759        print_ets_priority_assignment_table(ndo, tptr + 5);
760
761        /*Print TC Bandwidth Table*/
762        print_tc_bandwidth_table(ndo, tptr + 9);
763
764        /* Print TSA Assignment Table */
765        print_tsa_assignment_table(ndo, tptr + 17);
766
767        break;
768
769    case LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION:
770        if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION_LENGTH) {
771		return hexdump;
772        }
773        ND_PRINT("\n\t    RES: %u", GET_U_1(tptr + 4));
774        /*Print Priority Assignment Table */
775        print_ets_priority_assignment_table(ndo, tptr + 5);
776        /*Print TC Bandwidth Table */
777        print_tc_bandwidth_table(ndo, tptr + 9);
778        /* Print TSA Assignment Table */
779        print_tsa_assignment_table(ndo, tptr + 17);
780        break;
781
782    case LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION:
783        if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION_LENGTH) {
784            return hexdump;
785        }
786        tval=GET_U_1(tptr + 4);
787        ND_PRINT("\n\t    Willing: %u, MBC: %u, RES: %u, PFC cap:%u ",
788		tval >> 7, (tval >> 6) & 0x01, (tval >> 4) & 0x03, (tval & 0x0f));
789        ND_PRINT("\n\t    PFC Enable");
790        tval=GET_U_1(tptr + 5);
791        ND_PRINT("\n\t     Priority : 0  1  2  3  4  5  6  7");
792        ND_PRINT("\n\t     Value    : ");
793        for(i=0;i<NO_OF_BITS;i++)
794            ND_PRINT("%-2d ", (tval >> i) & 0x01);
795        break;
796
797    case LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY:
798        if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY_MIN_LENGTH) {
799            return hexdump;
800        }
801        ND_PRINT("\n\t    RES: %u", GET_U_1(tptr + 4));
802        if(tlv_len<=LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY_MIN_LENGTH){
803		return hexdump;
804        }
805        /*  Length of Application Priority Table */
806        sublen=tlv_len-5;
807        if(sublen%3!=0){
808		return hexdump;
809        }
810        i=0;
811        ND_PRINT("\n\t    Application Priority Table");
812        while(i<sublen) {
813		tval=GET_U_1(tptr + i + 5);
814		ND_PRINT("\n\t      Priority: %u, RES: %u, Sel: %u, Protocol ID: %u",
815			 tval >> 5, (tval >> 3) & 0x03, (tval & 0x07),
816			 GET_BE_U_2(tptr + i + 6));
817		i=i+3;
818        }
819        break;
820    case LLDP_PRIVATE_8021_SUBTYPE_EVB:
821        if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_EVB_LENGTH){
822		return hexdump;
823        }
824        ND_PRINT("\n\t    EVB Bridge Status");
825        tval=GET_U_1(tptr + 4);
826        ND_PRINT("\n\t      RES: %u, BGID: %u, RRCAP: %u, RRCTR: %u",
827		tval >> 3, (tval >> 2) & 0x01, (tval >> 1) & 0x01, tval & 0x01);
828        ND_PRINT("\n\t    EVB Station Status");
829        tval=GET_U_1(tptr + 5);
830        ND_PRINT("\n\t      RES: %u, SGID: %u, RRREQ: %u,RRSTAT: %u",
831		tval >> 4, (tval >> 3) & 0x01, (tval >> 2) & 0x01, tval & 0x03);
832        tval=GET_U_1(tptr + 6);
833        ND_PRINT("\n\t    R: %u, RTE: %u, ",tval >> 5, tval & 0x1f);
834        tval=GET_U_1(tptr + 7);
835        ND_PRINT("EVB Mode: %s [%u]",
836		tok2str(lldp_evb_mode_values, "unknown", tval >> 6), tval >> 6);
837        ND_PRINT("\n\t    ROL: %u, RWD: %u, ", (tval >> 5) & 0x01, tval & 0x1f);
838        tval=GET_U_1(tptr + 8);
839        ND_PRINT("RES: %u, ROL: %u, RKA: %u", tval >> 6, (tval >> 5) & 0x01, tval & 0x1f);
840        break;
841
842    case LLDP_PRIVATE_8021_SUBTYPE_CDCP:
843        if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_CDCP_MIN_LENGTH){
844		return hexdump;
845        }
846        tval=GET_U_1(tptr + 4);
847        ND_PRINT("\n\t    Role: %u, RES: %u, Scomp: %u ",
848		tval >> 7, (tval >> 4) & 0x07, (tval >> 3) & 0x01);
849        ND_PRINT("ChnCap: %u", GET_BE_U_2(tptr + 6) & 0x0fff);
850        sublen=tlv_len-8;
851        if(sublen%3!=0) {
852		return hexdump;
853        }
854        i=0;
855        while(i<sublen) {
856		tval=GET_BE_U_3(tptr + i + 8);
857		ND_PRINT("\n\t    SCID: %u, SVID: %u",
858			tval >> 12, tval & 0x000fff);
859		i=i+3;
860        }
861        break;
862
863    default:
864        hexdump = TRUE;
865        break;
866    }
867
868    return hexdump;
869}
870
871/*
872 * Print IEEE 802.3 private extensions. (802.3bc)
873 */
874static int
875lldp_private_8023_print(netdissect_options *ndo,
876                        const u_char *tptr, u_int tlv_len)
877{
878    int hexdump = FALSE;
879    u_int subtype;
880
881    if (tlv_len < 4) {
882        return hexdump;
883    }
884    subtype = GET_U_1(tptr + 3);
885
886    ND_PRINT("\n\t  %s Subtype (%u)",
887           tok2str(lldp_8023_subtype_values, "unknown", subtype),
888           subtype);
889
890    switch (subtype) {
891    case LLDP_PRIVATE_8023_SUBTYPE_MACPHY:
892        if (tlv_len < 9) {
893            return hexdump;
894        }
895        ND_PRINT("\n\t    autonegotiation [%s] (0x%02x)",
896               bittok2str(lldp_8023_autonegotiation_values, "none", GET_U_1(tptr + 4)),
897               GET_U_1(tptr + 4));
898        ND_PRINT("\n\t    PMD autoneg capability [%s] (0x%04x)",
899               bittok2str(lldp_pmd_capability_values,"unknown", GET_BE_U_2(tptr + 5)),
900               GET_BE_U_2(tptr + 5));
901        ND_PRINT("\n\t    MAU type %s (0x%04x)",
902               tok2str(lldp_mau_types_values, "unknown", GET_BE_U_2(tptr + 7)),
903               GET_BE_U_2(tptr + 7));
904        break;
905
906    case LLDP_PRIVATE_8023_SUBTYPE_MDIPOWER:
907        if (tlv_len < 7) {
908            return hexdump;
909        }
910        ND_PRINT("\n\t    MDI power support [%s], power pair %s, power class %s",
911               bittok2str(lldp_mdi_values, "none", GET_U_1((tptr + 4))),
912               tok2str(lldp_mdi_power_pairs_values, "unknown", GET_U_1((tptr + 5))),
913               tok2str(lldp_mdi_power_class_values, "unknown", GET_U_1((tptr + 6))));
914        break;
915
916    case LLDP_PRIVATE_8023_SUBTYPE_LINKAGGR:
917        if (tlv_len < 9) {
918            return hexdump;
919        }
920        ND_PRINT("\n\t    aggregation status [%s], aggregation port ID %u",
921               bittok2str(lldp_aggregation_values, "none", GET_U_1((tptr + 4))),
922               GET_BE_U_4(tptr + 5));
923        break;
924
925    case LLDP_PRIVATE_8023_SUBTYPE_MTU:
926        if (tlv_len < 6) {
927            return hexdump;
928        }
929        ND_PRINT("\n\t    MTU size %u", GET_BE_U_2(tptr + 4));
930        break;
931
932    default:
933        hexdump = TRUE;
934        break;
935    }
936
937    return hexdump;
938}
939
940/*
941 * Extract 34bits of latitude/longitude coordinates.
942 */
943static uint64_t
944lldp_extract_latlon(netdissect_options *ndo, const u_char *tptr)
945{
946    uint64_t latlon;
947
948    latlon = GET_U_1(tptr) & 0x3;
949    latlon = (latlon << 32) | GET_BE_U_4(tptr + 1);
950
951    return latlon;
952}
953
954/* objects defined in IANA subtype 00 00 5e
955 * (right now there is only one)
956 */
957
958
959static int
960lldp_private_iana_print(netdissect_options *ndo,
961                        const u_char *tptr, u_int tlv_len)
962{
963    int hexdump = FALSE;
964    u_int subtype;
965
966    if (tlv_len < 8) {
967        return hexdump;
968    }
969    subtype = GET_U_1(tptr + 3);
970
971    ND_PRINT("\n\t  %s Subtype (%u)",
972           tok2str(lldp_iana_subtype_values, "unknown", subtype),
973           subtype);
974
975    switch (subtype) {
976    case LLDP_IANA_SUBTYPE_MUDURL:
977        ND_PRINT("\n\t  MUD-URL=");
978        (void)nd_printn(ndo, tptr+4, tlv_len-4, NULL);
979        break;
980    default:
981        hexdump=TRUE;
982    }
983
984    return hexdump;
985}
986
987
988
989/*
990 * Print private TIA extensions.
991 */
992static int
993lldp_private_tia_print(netdissect_options *ndo,
994                       const u_char *tptr, u_int tlv_len)
995{
996    int hexdump = FALSE;
997    u_int subtype;
998    uint8_t location_format;
999    uint16_t power_val;
1000    u_int lci_len;
1001    uint8_t ca_type, ca_len;
1002
1003    if (tlv_len < 4) {
1004        return hexdump;
1005    }
1006    subtype = GET_U_1(tptr + 3);
1007
1008    ND_PRINT("\n\t  %s Subtype (%u)",
1009           tok2str(lldp_tia_subtype_values, "unknown", subtype),
1010           subtype);
1011
1012    switch (subtype) {
1013    case LLDP_PRIVATE_TIA_SUBTYPE_CAPABILITIES:
1014        if (tlv_len < 7) {
1015            return hexdump;
1016        }
1017        ND_PRINT("\n\t    Media capabilities [%s] (0x%04x)",
1018               bittok2str(lldp_tia_capabilities_values, "none",
1019                          GET_BE_U_2(tptr + 4)), GET_BE_U_2(tptr + 4));
1020        ND_PRINT("\n\t    Device type [%s] (0x%02x)",
1021               tok2str(lldp_tia_device_type_values, "unknown", GET_U_1(tptr + 6)),
1022               GET_U_1(tptr + 6));
1023        break;
1024
1025    case LLDP_PRIVATE_TIA_SUBTYPE_NETWORK_POLICY:
1026        if (tlv_len < 8) {
1027            return hexdump;
1028        }
1029        ND_PRINT("\n\t    Application type [%s] (0x%02x)",
1030               tok2str(lldp_tia_application_type_values, "none", GET_U_1(tptr + 4)),
1031               GET_U_1(tptr + 4));
1032        ND_PRINT(", Flags [%s]", bittok2str(
1033                   lldp_tia_network_policy_bits_values, "none", GET_U_1((tptr + 5))));
1034        ND_PRINT("\n\t    Vlan id %u",
1035               LLDP_EXTRACT_NETWORK_POLICY_VLAN(GET_BE_U_2(tptr + 5)));
1036        ND_PRINT(", L2 priority %u",
1037               LLDP_EXTRACT_NETWORK_POLICY_L2_PRIORITY(GET_BE_U_2(tptr + 6)));
1038        ND_PRINT(", DSCP value %u",
1039               LLDP_EXTRACT_NETWORK_POLICY_DSCP(GET_BE_U_2(tptr + 6)));
1040        break;
1041
1042    case LLDP_PRIVATE_TIA_SUBTYPE_LOCAL_ID:
1043        if (tlv_len < 5) {
1044            return hexdump;
1045        }
1046        location_format = GET_U_1(tptr + 4);
1047        ND_PRINT("\n\t    Location data format %s (0x%02x)",
1048               tok2str(lldp_tia_location_data_format_values, "unknown", location_format),
1049               location_format);
1050
1051        switch (location_format) {
1052        case LLDP_TIA_LOCATION_DATA_FORMAT_COORDINATE_BASED:
1053            if (tlv_len < 21) {
1054                return hexdump;
1055            }
1056            ND_PRINT("\n\t    Latitude resolution %u, latitude value %" PRIu64,
1057                   (GET_U_1(tptr + 5) >> 2),
1058                   lldp_extract_latlon(ndo, tptr + 5));
1059            ND_PRINT("\n\t    Longitude resolution %u, longitude value %" PRIu64,
1060                   (GET_U_1(tptr + 10) >> 2),
1061                   lldp_extract_latlon(ndo, tptr + 10));
1062            ND_PRINT("\n\t    Altitude type %s (%u)",
1063                   tok2str(lldp_tia_location_altitude_type_values, "unknown",GET_U_1(tptr + 15) >> 4),
1064                   (GET_U_1(tptr + 15) >> 4));
1065            ND_PRINT("\n\t    Altitude resolution %u, altitude value 0x%x",
1066                   (GET_BE_U_2(tptr + 15)>>6)&0x3f,
1067                   (GET_BE_U_4(tptr + 16) & 0x3fffffff));
1068            ND_PRINT("\n\t    Datum %s (0x%02x)",
1069                   tok2str(lldp_tia_location_datum_type_values, "unknown", GET_U_1(tptr + 20)),
1070                   GET_U_1(tptr + 20));
1071            break;
1072
1073        case LLDP_TIA_LOCATION_DATA_FORMAT_CIVIC_ADDRESS:
1074            if (tlv_len < 6) {
1075                return hexdump;
1076            }
1077            lci_len = GET_U_1(tptr + 5);
1078            if (lci_len < 3) {
1079                return hexdump;
1080            }
1081            if (tlv_len < 7+lci_len) {
1082                return hexdump;
1083            }
1084            ND_PRINT("\n\t    LCI length %u, LCI what %s (0x%02x), Country-code ",
1085                   lci_len,
1086                   tok2str(lldp_tia_location_lci_what_values, "unknown", GET_U_1(tptr + 6)),
1087                   GET_U_1(tptr + 6));
1088
1089            /* Country code */
1090            nd_printjnp(ndo, tptr + 7, 2);
1091
1092            lci_len = lci_len-3;
1093            tptr = tptr + 9;
1094
1095            /* Decode each civic address element */
1096            while (lci_len > 0) {
1097                if (lci_len < 2) {
1098                    return hexdump;
1099                }
1100		ca_type = GET_U_1(tptr);
1101                ca_len = GET_U_1(tptr + 1);
1102
1103		tptr += 2;
1104                lci_len -= 2;
1105
1106                ND_PRINT("\n\t      CA type \'%s\' (%u), length %u: ",
1107                       tok2str(lldp_tia_location_lci_catype_values, "unknown", ca_type),
1108                       ca_type, ca_len);
1109
1110		/* basic sanity check */
1111		if ( ca_type == 0 || ca_len == 0) {
1112                    return hexdump;
1113		}
1114		if (lci_len < ca_len) {
1115		    return hexdump;
1116		}
1117
1118                nd_printjnp(ndo, tptr, ca_len);
1119                tptr += ca_len;
1120                lci_len -= ca_len;
1121            }
1122            break;
1123
1124        case LLDP_TIA_LOCATION_DATA_FORMAT_ECS_ELIN:
1125            ND_PRINT("\n\t    ECS ELIN id ");
1126            nd_printjnp(ndo, tptr + 5, tlv_len - 5);
1127            break;
1128
1129        default:
1130            ND_PRINT("\n\t    Location ID ");
1131            print_unknown_data(ndo, tptr + 5, "\n\t      ", tlv_len - 5);
1132        }
1133        break;
1134
1135    case LLDP_PRIVATE_TIA_SUBTYPE_EXTENDED_POWER_MDI:
1136        if (tlv_len < 7) {
1137            return hexdump;
1138        }
1139        ND_PRINT("\n\t    Power type [%s]",
1140               (GET_U_1(tptr + 4) & 0xC0 >> 6) ? "PD device" : "PSE device");
1141        ND_PRINT(", Power source [%s]",
1142               tok2str(lldp_tia_power_source_values, "none", (GET_U_1((tptr + 4)) & 0x30) >> 4));
1143        ND_PRINT("\n\t    Power priority [%s] (0x%02x)",
1144               tok2str(lldp_tia_power_priority_values, "none", GET_U_1(tptr + 4) & 0x0f),
1145               GET_U_1(tptr + 4) & 0x0f);
1146        power_val = GET_BE_U_2(tptr + 5);
1147        if (power_val < LLDP_TIA_POWER_VAL_MAX) {
1148            ND_PRINT(", Power %.1f Watts", ((float)power_val) / 10);
1149        } else {
1150            ND_PRINT(", Power %u (Reserved)", power_val);
1151        }
1152        break;
1153
1154    case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV:
1155    case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV:
1156    case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV:
1157    case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER:
1158    case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME:
1159    case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME:
1160    case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID:
1161        ND_PRINT("\n\t  %s ",
1162               tok2str(lldp_tia_inventory_values, "unknown", subtype));
1163        nd_printjnp(ndo, tptr + 4, tlv_len - 4);
1164        break;
1165
1166    default:
1167        hexdump = TRUE;
1168        break;
1169    }
1170
1171    return hexdump;
1172}
1173
1174/*
1175 * Print DCBX Protocol fields (V 1.01).
1176 */
1177static int
1178lldp_private_dcbx_print(netdissect_options *ndo,
1179                        const u_char *pptr, u_int len)
1180{
1181    int hexdump = FALSE;
1182    u_int subtype;
1183    uint16_t tval;
1184    uint16_t tlv;
1185    uint32_t i, pgval, uval;
1186    u_int tlen, tlv_type;
1187    uint16_t tlv_len;
1188    const u_char *tptr, *mptr;
1189
1190    if (len < 4) {
1191        return hexdump;
1192    }
1193    subtype = GET_U_1(pptr + 3);
1194
1195    ND_PRINT("\n\t  %s Subtype (%u)",
1196           tok2str(lldp_dcbx_subtype_values, "unknown", subtype),
1197           subtype);
1198
1199    /* by passing old version */
1200    if (subtype == LLDP_DCBX_SUBTYPE_1)
1201	return TRUE;
1202
1203    tptr = pptr + 4;
1204    tlen = len - 4;
1205
1206    while (tlen >= sizeof(tlv)) {
1207
1208        ND_TCHECK_LEN(tptr, sizeof(tlv));
1209
1210        tlv = GET_BE_U_2(tptr);
1211
1212        tlv_type = LLDP_EXTRACT_TYPE(tlv);
1213        tlv_len = LLDP_EXTRACT_LEN(tlv);
1214        hexdump = FALSE;
1215
1216        tlen -= sizeof(tlv);
1217        tptr += sizeof(tlv);
1218
1219        /* loop check */
1220        if (!tlv_type || !tlv_len) {
1221            break;
1222        }
1223
1224        ND_TCHECK_LEN(tptr, tlv_len);
1225        if (tlen < tlv_len) {
1226            goto trunc;
1227        }
1228
1229	/* decode every tlv */
1230        switch (tlv_type) {
1231        case LLDP_DCBX_CONTROL_TLV:
1232            if (tlv_len < 10) {
1233                goto trunc;
1234            }
1235	    ND_PRINT("\n\t    Control - Protocol Control (type 0x%x, length %u)",
1236		LLDP_DCBX_CONTROL_TLV, tlv_len);
1237	    ND_PRINT("\n\t      Oper_Version: %u", GET_U_1(tptr));
1238	    ND_PRINT("\n\t      Max_Version: %u", GET_U_1(tptr + 1));
1239	    ND_PRINT("\n\t      Sequence Number: %u", GET_BE_U_4(tptr + 2));
1240	    ND_PRINT("\n\t      Acknowledgement Number: %u",
1241					GET_BE_U_4(tptr + 6));
1242	    break;
1243        case LLDP_DCBX_PRIORITY_GROUPS_TLV:
1244            if (tlv_len < 17) {
1245                goto trunc;
1246            }
1247	    ND_PRINT("\n\t    Feature - Priority Group (type 0x%x, length %u)",
1248		LLDP_DCBX_PRIORITY_GROUPS_TLV, tlv_len);
1249	    ND_PRINT("\n\t      Oper_Version: %u", GET_U_1(tptr));
1250	    ND_PRINT("\n\t      Max_Version: %u", GET_U_1(tptr + 1));
1251	    ND_PRINT("\n\t      Info block(0x%02X): ", GET_U_1(tptr + 2));
1252	    tval = GET_U_1(tptr + 2);
1253	    ND_PRINT("Enable bit: %u, Willing bit: %u, Error Bit: %u",
1254		(tval &  0x80) ? 1 : 0, (tval &  0x40) ? 1 : 0,
1255		(tval &  0x20) ? 1 : 0);
1256	    ND_PRINT("\n\t      SubType: %u", GET_U_1(tptr + 3));
1257	    ND_PRINT("\n\t      Priority Allocation");
1258
1259	    /*
1260	     * Array of 8 4-bit priority group ID values; we fetch all
1261	     * 32 bits and extract each nibble.
1262	     */
1263	    pgval = GET_BE_U_4(tptr + 4);
1264	    for (i = 0; i <= 7; i++) {
1265		ND_PRINT("\n\t          PgId_%u: %u",
1266			i, (pgval >> (28 - 4 * i)) & 0xF);
1267	    }
1268	    ND_PRINT("\n\t      Priority Group Allocation");
1269	    for (i = 0; i <= 7; i++)
1270		ND_PRINT("\n\t          Pg percentage[%u]: %u", i,
1271                         GET_U_1(tptr + 8 + i));
1272	    ND_PRINT("\n\t      NumTCsSupported: %u", GET_U_1(tptr + 8 + 8));
1273	    break;
1274        case LLDP_DCBX_PRIORITY_FLOW_CONTROL_TLV:
1275            if (tlv_len < 6) {
1276                goto trunc;
1277            }
1278	    ND_PRINT("\n\t    Feature - Priority Flow Control");
1279	    ND_PRINT(" (type 0x%x, length %u)",
1280		LLDP_DCBX_PRIORITY_FLOW_CONTROL_TLV, tlv_len);
1281	    ND_PRINT("\n\t      Oper_Version: %u", GET_U_1(tptr));
1282	    ND_PRINT("\n\t      Max_Version: %u", GET_U_1(tptr + 1));
1283	    ND_PRINT("\n\t      Info block(0x%02X): ", GET_U_1(tptr + 2));
1284	    tval = GET_U_1(tptr + 2);
1285	    ND_PRINT("Enable bit: %u, Willing bit: %u, Error Bit: %u",
1286		(tval &  0x80) ? 1 : 0, (tval &  0x40) ? 1 : 0,
1287		(tval &  0x20) ? 1 : 0);
1288	    ND_PRINT("\n\t      SubType: %u", GET_U_1(tptr + 3));
1289	    tval = GET_U_1(tptr + 4);
1290	    ND_PRINT("\n\t      PFC Config (0x%02X)", GET_U_1(tptr + 4));
1291	    for (i = 0; i <= 7; i++)
1292		ND_PRINT("\n\t          Priority Bit %u: %s",
1293		    i, (tval & (1 << i)) ? "Enabled" : "Disabled");
1294	    ND_PRINT("\n\t      NumTCPFCSupported: %u", GET_U_1(tptr + 5));
1295	    break;
1296        case LLDP_DCBX_APPLICATION_TLV:
1297            if (tlv_len < 4) {
1298                goto trunc;
1299            }
1300	    ND_PRINT("\n\t    Feature - Application (type 0x%x, length %u)",
1301		LLDP_DCBX_APPLICATION_TLV, tlv_len);
1302	    ND_PRINT("\n\t      Oper_Version: %u", GET_U_1(tptr));
1303	    ND_PRINT("\n\t      Max_Version: %u", GET_U_1(tptr + 1));
1304	    ND_PRINT("\n\t      Info block(0x%02X): ", GET_U_1(tptr + 2));
1305	    tval = GET_U_1(tptr + 2);
1306	    ND_PRINT("Enable bit: %u, Willing bit: %u, Error Bit: %u",
1307		(tval &  0x80) ? 1 : 0, (tval &  0x40) ? 1 : 0,
1308		(tval &  0x20) ? 1 : 0);
1309	    ND_PRINT("\n\t      SubType: %u", GET_U_1(tptr + 3));
1310	    tval = tlv_len - 4;
1311	    mptr = tptr + 4;
1312	    while (tval >= 6) {
1313		ND_PRINT("\n\t      Application Value");
1314		ND_PRINT("\n\t          Application Protocol ID: 0x%04x",
1315			GET_BE_U_2(mptr));
1316		uval = GET_BE_U_3(mptr + 2);
1317		ND_PRINT("\n\t          SF (0x%x) Application Protocol ID is %s",
1318			(uval >> 22),
1319			(uval >> 22) ? "Socket Number" : "L2 EtherType");
1320		ND_PRINT("\n\t          OUI: 0x%06x", uval & 0x3fffff);
1321		ND_PRINT("\n\t          User Priority Map: 0x%02x",
1322                         GET_U_1(mptr + 5));
1323		tval = tval - 6;
1324		mptr = mptr + 6;
1325	    }
1326	    break;
1327	default:
1328	    hexdump = TRUE;
1329	    break;
1330	}
1331
1332        /* do we also want to see a hex dump ? */
1333        if (ndo->ndo_vflag > 1 || (ndo->ndo_vflag && hexdump)) {
1334	    print_unknown_data(ndo, tptr, "\n\t    ", tlv_len);
1335        }
1336
1337        tlen -= tlv_len;
1338        tptr += tlv_len;
1339    }
1340
1341 trunc:
1342    return hexdump;
1343}
1344
1345static char *
1346lldp_network_addr_print(netdissect_options *ndo, const u_char *tptr, u_int len)
1347{
1348    uint8_t af;
1349    static char buf[BUFSIZE];
1350    const char * (*pfunc)(netdissect_options *, const u_char *);
1351
1352    if (len < 1)
1353      return NULL;
1354    len--;
1355    af = GET_U_1(tptr);
1356    switch (af) {
1357    case AFNUM_INET:
1358        if (len < sizeof(nd_ipv4))
1359          return NULL;
1360        pfunc = ipaddr_string;
1361        break;
1362    case AFNUM_INET6:
1363        if (len < sizeof(nd_ipv6))
1364          return NULL;
1365        pfunc = ip6addr_string;
1366        break;
1367    case AFNUM_802:
1368        if (len < MAC_ADDR_LEN)
1369          return NULL;
1370        pfunc = etheraddr_string;
1371        break;
1372    default:
1373        pfunc = NULL;
1374        break;
1375    }
1376
1377    if (!pfunc) {
1378        snprintf(buf, sizeof(buf), "AFI %s (%u), no AF printer !",
1379                 tok2str(af_values, "Unknown", af), af);
1380    } else {
1381        snprintf(buf, sizeof(buf), "AFI %s (%u): %s",
1382                 tok2str(af_values, "Unknown", af), af, (*pfunc)(ndo, tptr+1));
1383    }
1384
1385    return buf;
1386}
1387
1388static int
1389lldp_mgmt_addr_tlv_print(netdissect_options *ndo,
1390                         const u_char *pptr, u_int len)
1391{
1392    uint8_t mgmt_addr_len, intf_num_subtype, oid_len;
1393    const u_char *tptr;
1394    u_int tlen;
1395    char *mgmt_addr;
1396
1397    tlen = len;
1398    tptr = pptr;
1399
1400    if (tlen < 1) {
1401        return 0;
1402    }
1403    mgmt_addr_len = GET_U_1(tptr);
1404    tptr++;
1405    tlen--;
1406
1407    if (tlen < mgmt_addr_len) {
1408        return 0;
1409    }
1410
1411    mgmt_addr = lldp_network_addr_print(ndo, tptr, mgmt_addr_len);
1412    if (mgmt_addr == NULL) {
1413        return 0;
1414    }
1415    ND_PRINT("\n\t  Management Address length %u, %s",
1416           mgmt_addr_len, mgmt_addr);
1417    tptr += mgmt_addr_len;
1418    tlen -= mgmt_addr_len;
1419
1420    if (tlen < LLDP_INTF_NUM_LEN) {
1421        return 0;
1422    }
1423
1424    intf_num_subtype = GET_U_1(tptr);
1425    ND_PRINT("\n\t  %s Interface Numbering (%u): %u",
1426           tok2str(lldp_intf_numb_subtype_values, "Unknown", intf_num_subtype),
1427           intf_num_subtype,
1428           GET_BE_U_4(tptr + 1));
1429
1430    tptr += LLDP_INTF_NUM_LEN;
1431    tlen -= LLDP_INTF_NUM_LEN;
1432
1433    /*
1434     * The OID is optional.
1435     */
1436    if (tlen) {
1437        oid_len = GET_U_1(tptr);
1438
1439        if (tlen < 1U + oid_len) {
1440            return 0;
1441        }
1442        if (oid_len) {
1443            ND_PRINT("\n\t  OID length %u", oid_len);
1444            nd_printjnp(ndo, tptr + 1, oid_len);
1445        }
1446    }
1447
1448    return 1;
1449}
1450
1451void
1452lldp_print(netdissect_options *ndo,
1453           const u_char *pptr, u_int len)
1454{
1455    uint8_t subtype;
1456    uint16_t tlv, cap, ena_cap;
1457    u_int oui, tlen, hexdump, tlv_type, tlv_len;
1458    const u_char *tptr;
1459    char *network_addr;
1460
1461    ndo->ndo_protocol = "lldp";
1462    tptr = pptr;
1463    tlen = len;
1464
1465    ND_PRINT("LLDP, length %u", len);
1466
1467    while (tlen >= sizeof(tlv)) {
1468
1469        ND_TCHECK_LEN(tptr, sizeof(tlv));
1470
1471        tlv = GET_BE_U_2(tptr);
1472
1473        tlv_type = LLDP_EXTRACT_TYPE(tlv);
1474        tlv_len = LLDP_EXTRACT_LEN(tlv);
1475        hexdump = FALSE;
1476
1477        tlen -= sizeof(tlv);
1478        tptr += sizeof(tlv);
1479
1480        if (ndo->ndo_vflag) {
1481            ND_PRINT("\n\t%s TLV (%u), length %u",
1482                   tok2str(lldp_tlv_values, "Unknown", tlv_type),
1483                   tlv_type, tlv_len);
1484        }
1485
1486        /* infinite loop check */
1487        if (!tlv_type || !tlv_len) {
1488            break;
1489        }
1490
1491        ND_TCHECK_LEN(tptr, tlv_len);
1492        if (tlen < tlv_len) {
1493            goto trunc;
1494        }
1495
1496        switch (tlv_type) {
1497
1498        case LLDP_CHASSIS_ID_TLV:
1499            if (ndo->ndo_vflag) {
1500                if (tlv_len < 2) {
1501                    goto trunc;
1502                }
1503                subtype = GET_U_1(tptr);
1504                ND_PRINT("\n\t  Subtype %s (%u): ",
1505                       tok2str(lldp_chassis_subtype_values, "Unknown", subtype),
1506                       subtype);
1507
1508                switch (subtype) {
1509                case LLDP_CHASSIS_MAC_ADDR_SUBTYPE:
1510                    if (tlv_len < 1+6) {
1511                        goto trunc;
1512                    }
1513                    ND_PRINT("%s", GET_ETHERADDR_STRING(tptr + 1));
1514                    break;
1515
1516                case LLDP_CHASSIS_INTF_NAME_SUBTYPE: /* fall through */
1517                case LLDP_CHASSIS_LOCAL_SUBTYPE:
1518                case LLDP_CHASSIS_CHASSIS_COMP_SUBTYPE:
1519                case LLDP_CHASSIS_INTF_ALIAS_SUBTYPE:
1520                case LLDP_CHASSIS_PORT_COMP_SUBTYPE:
1521                    nd_printjnp(ndo, tptr + 1, tlv_len - 1);
1522                    break;
1523
1524                case LLDP_CHASSIS_NETWORK_ADDR_SUBTYPE:
1525                    network_addr = lldp_network_addr_print(ndo, tptr+1, tlv_len-1);
1526                    if (network_addr == NULL) {
1527                        goto trunc;
1528                    }
1529                    ND_PRINT("%s", network_addr);
1530                    break;
1531
1532                default:
1533                    hexdump = TRUE;
1534                    break;
1535                }
1536            }
1537            break;
1538
1539        case LLDP_PORT_ID_TLV:
1540            if (ndo->ndo_vflag) {
1541                if (tlv_len < 2) {
1542                    goto trunc;
1543                }
1544                subtype = GET_U_1(tptr);
1545                ND_PRINT("\n\t  Subtype %s (%u): ",
1546                       tok2str(lldp_port_subtype_values, "Unknown", subtype),
1547                       subtype);
1548
1549                switch (subtype) {
1550                case LLDP_PORT_MAC_ADDR_SUBTYPE:
1551                    if (tlv_len < 1+6) {
1552                        goto trunc;
1553                    }
1554                    ND_PRINT("%s", GET_ETHERADDR_STRING(tptr + 1));
1555                    break;
1556
1557                case LLDP_PORT_INTF_NAME_SUBTYPE: /* fall through */
1558                case LLDP_PORT_LOCAL_SUBTYPE:
1559                case LLDP_PORT_AGENT_CIRC_ID_SUBTYPE:
1560                case LLDP_PORT_INTF_ALIAS_SUBTYPE:
1561                case LLDP_PORT_PORT_COMP_SUBTYPE:
1562                    nd_printjnp(ndo, tptr + 1, tlv_len - 1);
1563                    break;
1564
1565                case LLDP_PORT_NETWORK_ADDR_SUBTYPE:
1566                    network_addr = lldp_network_addr_print(ndo, tptr+1, tlv_len-1);
1567                    if (network_addr == NULL) {
1568                        goto trunc;
1569                    }
1570                    ND_PRINT("%s", network_addr);
1571                    break;
1572
1573                default:
1574                    hexdump = TRUE;
1575                    break;
1576                }
1577            }
1578            break;
1579
1580        case LLDP_TTL_TLV:
1581            if (ndo->ndo_vflag) {
1582                if (tlv_len < 2) {
1583                    goto trunc;
1584                }
1585                ND_PRINT(": TTL %us", GET_BE_U_2(tptr));
1586            }
1587            break;
1588
1589        case LLDP_PORT_DESCR_TLV:
1590            if (ndo->ndo_vflag) {
1591                ND_PRINT(": ");
1592                nd_printjnp(ndo, tptr, tlv_len);
1593            }
1594            break;
1595
1596        case LLDP_SYSTEM_NAME_TLV:
1597            /*
1598             * The system name is also print in non-verbose mode
1599             * similar to the CDP printer.
1600             */
1601            ND_PRINT(": ");
1602            nd_printjnp(ndo, tptr, tlv_len);
1603            break;
1604
1605        case LLDP_SYSTEM_DESCR_TLV:
1606            if (ndo->ndo_vflag) {
1607                ND_PRINT("\n\t  ");
1608                nd_printjnp(ndo, tptr, tlv_len);
1609            }
1610            break;
1611
1612        case LLDP_SYSTEM_CAP_TLV:
1613            if (ndo->ndo_vflag) {
1614                /*
1615                 * XXX - IEEE Std 802.1AB-2009 says the first octet
1616                 * if a chassis ID subtype, with the system
1617                 * capabilities and enabled capabilities following
1618                 * it.
1619                 */
1620                if (tlv_len < 4) {
1621                    goto trunc;
1622                }
1623                cap = GET_BE_U_2(tptr);
1624                ena_cap = GET_BE_U_2(tptr + 2);
1625                ND_PRINT("\n\t  System  Capabilities [%s] (0x%04x)",
1626                       bittok2str(lldp_cap_values, "none", cap), cap);
1627                ND_PRINT("\n\t  Enabled Capabilities [%s] (0x%04x)",
1628                       bittok2str(lldp_cap_values, "none", ena_cap), ena_cap);
1629            }
1630            break;
1631
1632        case LLDP_MGMT_ADDR_TLV:
1633            if (ndo->ndo_vflag) {
1634                if (!lldp_mgmt_addr_tlv_print(ndo, tptr, tlv_len)) {
1635                    goto trunc;
1636                }
1637            }
1638            break;
1639
1640        case LLDP_PRIVATE_TLV:
1641            if (ndo->ndo_vflag) {
1642                if (tlv_len < 3) {
1643                    goto trunc;
1644                }
1645                oui = GET_BE_U_3(tptr);
1646                ND_PRINT(": OUI %s (0x%06x)", tok2str(oui_values, "Unknown", oui), oui);
1647
1648                switch (oui) {
1649                case OUI_IEEE_8021_PRIVATE:
1650                    hexdump = lldp_private_8021_print(ndo, tptr, tlv_len);
1651                    break;
1652                case OUI_IEEE_8023_PRIVATE:
1653                    hexdump = lldp_private_8023_print(ndo, tptr, tlv_len);
1654                    break;
1655		case OUI_IANA:
1656                    hexdump = lldp_private_iana_print(ndo, tptr, tlv_len);
1657                    break;
1658                case OUI_TIA:
1659                    hexdump = lldp_private_tia_print(ndo, tptr, tlv_len);
1660                    break;
1661                case OUI_DCBX:
1662                    hexdump = lldp_private_dcbx_print(ndo, tptr, tlv_len);
1663                    break;
1664                default:
1665                    hexdump = TRUE;
1666                    break;
1667                }
1668            }
1669            break;
1670
1671        default:
1672            hexdump = TRUE;
1673            break;
1674        }
1675
1676        /* do we also want to see a hex dump ? */
1677        if (ndo->ndo_vflag > 1 || (ndo->ndo_vflag && hexdump)) {
1678            print_unknown_data(ndo, tptr, "\n\t  ", tlv_len);
1679        }
1680
1681        tlen -= tlv_len;
1682        tptr += tlv_len;
1683    }
1684    return;
1685 trunc:
1686    nd_print_trunc(ndo);
1687}
1688