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