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
23 static 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 
60 static 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 
85 static 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 
107 static 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 
130 static 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 
154 static 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 
172 static 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 
183 static 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 
203 static 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 
221 static 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 
235 static 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 
245 static 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 
297 static 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 
345 static 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 
358 static 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 
373 static 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 
390 static 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 
406 static 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 
421 static 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 
432 static 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 
443 static 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 
454 static 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 
463 static 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 
494 static 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 
518 static 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 
529 static 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 
541 static 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 
553 static 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 
565 static 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 
582 static 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 
595 static 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 
print_ets_priority_assignment_table(const u_char * ptr)611 static 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 
print_tc_bandwidth_table(const u_char * ptr)620 static 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 
print_tsa_assignment_table(const u_char * ptr)628 static 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  */
639 static int
lldp_private_8021_print(const u_char * tptr,u_int tlv_len)640 lldp_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  */
842 static int
lldp_private_8023_print(const u_char * tptr,u_int tlv_len)843 lldp_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  */
906 static u_int64_t
lldp_extract_latlon(const u_char * tptr)907 lldp_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  */
920 static int
lldp_private_tia_print(const u_char * tptr,u_int tlv_len)921 lldp_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  */
1101 static int
lldp_private_dcbx_print(const u_char * pptr,u_int len)1102 lldp_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 
1261 static char *
lldp_network_addr_print(const u_char * tptr,u_int len)1262 lldp_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 
1306 static int
lldp_mgmt_addr_tlv_print(const u_char * pptr,u_int len)1307 lldp_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 
1367 void
lldp_print(register const u_char * pptr,register u_int len)1368 lldp_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