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