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