xref: /netbsd-src/external/bsd/tcpdump/dist/print-lldp.c (revision c42dbd0ed2e61fe6eda8590caa852ccf34719964)
1 /*
2  * Copyright (c) 1998-2007 The TCPDUMP project
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that: (1) source code
6  * distributions retain the above copyright notice and this paragraph
7  * in its entirety, and (2) distributions including binary code include
8  * the above copyright notice and this paragraph in its entirety in
9  * the documentation or other materials provided with the distribution.
10  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
11  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
12  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13  * FOR A PARTICULAR PURPOSE.
14  *
15  * Original code by Hannes Gredler (hannes@gredler.at)
16  * IEEE and TIA extensions by Carles Kishimoto <carles.kishimoto@gmail.com>
17  * DCBX extensions by Kaladhar Musunuru <kaladharm@sourceforge.net>
18  */
19 
20 /* \summary: IEEE 802.1ab Link Layer Discovery Protocol (LLDP) printer */
21 
22 #include <sys/cdefs.h>
23 #ifndef lint
24 __RCSID("$NetBSD: print-lldp.c,v 1.10 2023/08/17 20:19:40 christos Exp $");
25 #endif
26 
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30 
31 #include "netdissect-stdinc.h"
32 
33 #include <stdio.h>
34 
35 #include "netdissect.h"
36 #include "extract.h"
37 #include "addrtoname.h"
38 #include "af.h"
39 #include "oui.h"
40 
41 #define	LLDP_EXTRACT_TYPE(x) (((x)&0xfe00)>>9)
42 #define	LLDP_EXTRACT_LEN(x) ((x)&0x01ff)
43 
44 /*
45  * TLV type codes
46  */
47 #define LLDP_END_TLV             0
48 #define LLDP_CHASSIS_ID_TLV      1
49 #define LLDP_PORT_ID_TLV         2
50 #define LLDP_TTL_TLV             3
51 #define LLDP_PORT_DESCR_TLV      4
52 #define LLDP_SYSTEM_NAME_TLV     5
53 #define LLDP_SYSTEM_DESCR_TLV    6
54 #define LLDP_SYSTEM_CAP_TLV      7
55 #define LLDP_MGMT_ADDR_TLV       8
56 #define LLDP_PRIVATE_TLV       127
57 
58 static const struct tok lldp_tlv_values[] = {
59     { LLDP_END_TLV, "End" },
60     { LLDP_CHASSIS_ID_TLV, "Chassis ID" },
61     { LLDP_PORT_ID_TLV, "Port ID" },
62     { LLDP_TTL_TLV, "Time to Live" },
63     { LLDP_PORT_DESCR_TLV, "Port Description" },
64     { LLDP_SYSTEM_NAME_TLV, "System Name" },
65     { LLDP_SYSTEM_DESCR_TLV, "System Description" },
66     { LLDP_SYSTEM_CAP_TLV, "System Capabilities" },
67     { LLDP_MGMT_ADDR_TLV, "Management Address" },
68     { LLDP_PRIVATE_TLV, "Organization specific" },
69     { 0, NULL}
70 };
71 
72 /*
73  * Chassis ID subtypes
74  */
75 #define LLDP_CHASSIS_CHASSIS_COMP_SUBTYPE  1
76 #define LLDP_CHASSIS_INTF_ALIAS_SUBTYPE    2
77 #define LLDP_CHASSIS_PORT_COMP_SUBTYPE     3
78 #define LLDP_CHASSIS_MAC_ADDR_SUBTYPE      4
79 #define LLDP_CHASSIS_NETWORK_ADDR_SUBTYPE  5
80 #define LLDP_CHASSIS_INTF_NAME_SUBTYPE     6
81 #define LLDP_CHASSIS_LOCAL_SUBTYPE         7
82 
83 static const struct tok lldp_chassis_subtype_values[] = {
84     { LLDP_CHASSIS_CHASSIS_COMP_SUBTYPE, "Chassis component"},
85     { LLDP_CHASSIS_INTF_ALIAS_SUBTYPE, "Interface alias"},
86     { LLDP_CHASSIS_PORT_COMP_SUBTYPE, "Port component"},
87     { LLDP_CHASSIS_MAC_ADDR_SUBTYPE, "MAC address"},
88     { LLDP_CHASSIS_NETWORK_ADDR_SUBTYPE, "Network address"},
89     { LLDP_CHASSIS_INTF_NAME_SUBTYPE, "Interface name"},
90     { LLDP_CHASSIS_LOCAL_SUBTYPE, "Local"},
91     { 0, NULL}
92 };
93 
94 /*
95  * Port ID subtypes
96  */
97 #define LLDP_PORT_INTF_ALIAS_SUBTYPE       1
98 #define LLDP_PORT_PORT_COMP_SUBTYPE        2
99 #define LLDP_PORT_MAC_ADDR_SUBTYPE         3
100 #define LLDP_PORT_NETWORK_ADDR_SUBTYPE     4
101 #define LLDP_PORT_INTF_NAME_SUBTYPE        5
102 #define LLDP_PORT_AGENT_CIRC_ID_SUBTYPE    6
103 #define LLDP_PORT_LOCAL_SUBTYPE            7
104 
105 static const struct tok lldp_port_subtype_values[] = {
106     { LLDP_PORT_INTF_ALIAS_SUBTYPE, "Interface alias"},
107     { LLDP_PORT_PORT_COMP_SUBTYPE, "Port component"},
108     { LLDP_PORT_MAC_ADDR_SUBTYPE, "MAC address"},
109     { LLDP_PORT_NETWORK_ADDR_SUBTYPE, "Network Address"},
110     { LLDP_PORT_INTF_NAME_SUBTYPE, "Interface Name"},
111     { LLDP_PORT_AGENT_CIRC_ID_SUBTYPE, "Agent circuit ID"},
112     { LLDP_PORT_LOCAL_SUBTYPE, "Local"},
113     { 0, NULL}
114 };
115 
116 /*
117  * System Capabilities
118  */
119 #define LLDP_CAP_OTHER              (1 <<  0)
120 #define LLDP_CAP_REPEATER           (1 <<  1)
121 #define LLDP_CAP_BRIDGE             (1 <<  2)
122 #define LLDP_CAP_WLAN_AP            (1 <<  3)
123 #define LLDP_CAP_ROUTER             (1 <<  4)
124 #define LLDP_CAP_PHONE              (1 <<  5)
125 #define LLDP_CAP_DOCSIS             (1 <<  6)
126 #define LLDP_CAP_STATION_ONLY       (1 <<  7)
127 
128 static const struct tok lldp_cap_values[] = {
129     { LLDP_CAP_OTHER, "Other"},
130     { LLDP_CAP_REPEATER, "Repeater"},
131     { LLDP_CAP_BRIDGE, "Bridge"},
132     { LLDP_CAP_WLAN_AP, "WLAN AP"},
133     { LLDP_CAP_ROUTER, "Router"},
134     { LLDP_CAP_PHONE, "Telephone"},
135     { LLDP_CAP_DOCSIS, "Docsis"},
136     { LLDP_CAP_STATION_ONLY, "Station Only"},
137     { 0, NULL}
138 };
139 
140 #define LLDP_PRIVATE_8021_SUBTYPE_PORT_VLAN_ID		1
141 #define LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_VLAN_ID	2
142 #define LLDP_PRIVATE_8021_SUBTYPE_VLAN_NAME		3
143 #define LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_IDENTITY	4
144 #define LLDP_PRIVATE_8021_SUBTYPE_LINKAGGR		7
145 #define LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION 8
146 #define LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION       9
147 #define LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION     10
148 #define LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION      11
149 #define LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY   12
150 #define LLDP_PRIVATE_8021_SUBTYPE_EVB                    13
151 #define LLDP_PRIVATE_8021_SUBTYPE_CDCP			 14
152 
153 static const struct tok lldp_8021_subtype_values[] = {
154     { LLDP_PRIVATE_8021_SUBTYPE_PORT_VLAN_ID, "Port VLAN Id"},
155     { LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_VLAN_ID, "Port and Protocol VLAN ID"},
156     { LLDP_PRIVATE_8021_SUBTYPE_VLAN_NAME, "VLAN name"},
157     { LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_IDENTITY, "Protocol Identity"},
158     { LLDP_PRIVATE_8021_SUBTYPE_LINKAGGR, "Link aggregation"},
159     { LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION, "Congestion Notification"},
160     { LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION, "ETS Configuration"},
161     { LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION, "ETS Recommendation"},
162     { LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION, "Priority Flow Control Configuration"},
163     { LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY, "Application Priority"},
164     { LLDP_PRIVATE_8021_SUBTYPE_EVB, "EVB"},
165     { LLDP_PRIVATE_8021_SUBTYPE_CDCP,"CDCP"},
166     { 0, NULL}
167 };
168 
169 #define LLDP_8021_PORT_PROTOCOL_VLAN_SUPPORT       (1 <<  1)
170 #define LLDP_8021_PORT_PROTOCOL_VLAN_STATUS        (1 <<  2)
171 
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_CAPABILITY     (1 <<  0)
551 #define LLDP_AGGREGATION_STATUS         (1 <<  1)
552 
553 static const struct tok lldp_aggregation_values[] = {
554     { LLDP_AGGREGATION_CAPABILITY, "supported"},
555     { LLDP_AGGREGATION_STATUS, "enabled"},
556     { 0, NULL}
557 };
558 
559 /*
560  * DCBX protocol subtypes.
561  */
562 #define LLDP_DCBX_SUBTYPE_1                1
563 #define LLDP_DCBX_SUBTYPE_2                2
564 
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 Station"},
599     { LLDP_EVB_MODE_RESERVED, "Reserved for future Standardization"},
600     { 0, NULL},
601 };
602 
603 #define NO_OF_BITS 8
604 #define LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION_LENGTH  6
605 #define LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION_LENGTH       25
606 #define LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION_LENGTH      25
607 #define LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION_LENGTH        6
608 #define LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY_MIN_LENGTH 5
609 #define LLDP_PRIVATE_8021_SUBTYPE_EVB_LENGTH                      9
610 #define LLDP_PRIVATE_8021_SUBTYPE_CDCP_MIN_LENGTH                 8
611 
612 #define LLDP_IANA_SUBTYPE_MUDURL 1
613 
614 static const struct tok lldp_iana_subtype_values[] =   {
615     { LLDP_IANA_SUBTYPE_MUDURL, "MUD-URL" },
616     { 0, NULL }
617 };
618 
619 
620 static void
621 print_ets_priority_assignment_table(netdissect_options *ndo,
622                                     const u_char *ptr)
623 {
624     ND_PRINT("\n\t    Priority Assignment Table");
625     ND_PRINT("\n\t     Priority : 0   1   2   3   4   5   6   7");
626     ND_PRINT("\n\t     Value    : %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d",
627               GET_U_1(ptr) >> 4, GET_U_1(ptr) & 0x0f,
628               GET_U_1(ptr + 1) >> 4, GET_U_1(ptr + 1) & 0x0f,
629               GET_U_1(ptr + 2) >> 4, GET_U_1(ptr + 2) & 0x0f,
630               GET_U_1(ptr + 3) >> 4, GET_U_1(ptr + 3) & 0x0f);
631 }
632 
633 static void
634 print_tc_bandwidth_table(netdissect_options *ndo,
635                          const u_char *ptr)
636 {
637     ND_PRINT("\n\t    TC Bandwidth Table");
638     ND_PRINT("\n\t     TC%%   : 0   1   2   3   4   5   6   7");
639     ND_PRINT("\n\t     Value : %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d",
640               GET_U_1(ptr), GET_U_1(ptr + 1), GET_U_1(ptr + 2),
641               GET_U_1(ptr + 3), GET_U_1(ptr + 4), GET_U_1(ptr + 5),
642               GET_U_1(ptr + 6), GET_U_1(ptr + 7));
643 }
644 
645 static void
646 print_tsa_assignment_table(netdissect_options *ndo,
647                            const u_char *ptr)
648 {
649     ND_PRINT("\n\t    TSA Assignment Table");
650     ND_PRINT("\n\t     Traffic Class: 0   1   2   3   4   5   6   7");
651     ND_PRINT("\n\t     Value        : %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d",
652               GET_U_1(ptr), GET_U_1(ptr + 1), GET_U_1(ptr + 2),
653               GET_U_1(ptr + 3), GET_U_1(ptr + 4), GET_U_1(ptr + 5),
654               GET_U_1(ptr + 6), GET_U_1(ptr + 7));
655 }
656 
657 /*
658  * Print IEEE 802.1 private extensions. (802.1AB annex E)
659  */
660 static int
661 lldp_private_8021_print(netdissect_options *ndo,
662                         const u_char *tptr, u_int tlv_len)
663 {
664     int hexdump = FALSE;
665     u_int subtype;
666     u_int sublen;
667     u_int tval;
668     u_int i;
669 
670     if (tlv_len < 4) {
671         return hexdump;
672     }
673     subtype = GET_U_1(tptr + 3);
674 
675     ND_PRINT("\n\t  %s Subtype (%u)",
676            tok2str(lldp_8021_subtype_values, "unknown", subtype),
677            subtype);
678 
679     switch (subtype) {
680     case LLDP_PRIVATE_8021_SUBTYPE_PORT_VLAN_ID:
681         if (tlv_len < 6) {
682             return hexdump;
683         }
684         ND_PRINT("\n\t    port vlan id (PVID): %u",
685                GET_BE_U_2(tptr + 4));
686         break;
687     case LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_VLAN_ID:
688         if (tlv_len < 7) {
689             return hexdump;
690         }
691         ND_PRINT("\n\t    port and protocol vlan id (PPVID): %u, flags [%s] (0x%02x)",
692                GET_BE_U_2(tptr + 5),
693                bittok2str(lldp_8021_port_protocol_id_values, "none", GET_U_1(tptr + 4)),
694                GET_U_1(tptr + 4));
695         break;
696     case LLDP_PRIVATE_8021_SUBTYPE_VLAN_NAME:
697         if (tlv_len < 6) {
698             return hexdump;
699         }
700         ND_PRINT("\n\t    vlan id (VID): %u", GET_BE_U_2(tptr + 4));
701         if (tlv_len < 7) {
702             return hexdump;
703         }
704         sublen = GET_U_1(tptr + 6);
705         if (tlv_len < 7+sublen) {
706             return hexdump;
707         }
708         ND_PRINT("\n\t    vlan name: ");
709         nd_printjnp(ndo, tptr + 7, sublen);
710         break;
711     case LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_IDENTITY:
712         if (tlv_len < 5) {
713             return hexdump;
714         }
715         sublen = GET_U_1(tptr + 4);
716         if (tlv_len < 5+sublen) {
717             return hexdump;
718         }
719         ND_PRINT("\n\t    protocol identity: ");
720         nd_printjnp(ndo, tptr + 5, sublen);
721         break;
722 
723     case LLDP_PRIVATE_8021_SUBTYPE_LINKAGGR:
724         if (tlv_len < 9) {
725             return hexdump;
726         }
727         ND_PRINT("\n\t    aggregation status [%s], aggregation port ID %u",
728                bittok2str(lldp_aggregation_values, "none", GET_U_1((tptr + 4))),
729                GET_BE_U_4(tptr + 5));
730         break;
731 
732     case LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION:
733         if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION_LENGTH){
734 		return hexdump;
735         }
736         tval=GET_U_1(tptr + 4);
737         ND_PRINT("\n\t    Pre-Priority CNPV Indicator");
738         ND_PRINT("\n\t     Priority : 0  1  2  3  4  5  6  7");
739         ND_PRINT("\n\t     Value    : ");
740         for(i=0;i<NO_OF_BITS;i++)
741             ND_PRINT("%-2d ", (tval >> i) & 0x01);
742         tval=GET_U_1(tptr + 5);
743         ND_PRINT("\n\t    Pre-Priority Ready Indicator");
744         ND_PRINT("\n\t     Priority : 0  1  2  3  4  5  6  7");
745         ND_PRINT("\n\t     Value    : ");
746         for(i=0;i<NO_OF_BITS;i++)
747             ND_PRINT("%-2d ", (tval >> i) & 0x01);
748         break;
749 
750     case LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION:
751         if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION_LENGTH) {
752             return hexdump;
753         }
754         tval=GET_U_1(tptr + 4);
755         ND_PRINT("\n\t    Willing:%u, CBS:%u, RES:%u, Max TCs:%u",
756 		tval >> 7, (tval >> 6) & 0x02, (tval >> 3) & 0x07, tval & 0x07);
757 
758         /*Print Priority Assignment Table*/
759         print_ets_priority_assignment_table(ndo, tptr + 5);
760 
761         /*Print TC Bandwidth Table*/
762         print_tc_bandwidth_table(ndo, tptr + 9);
763 
764         /* Print TSA Assignment Table */
765         print_tsa_assignment_table(ndo, tptr + 17);
766 
767         break;
768 
769     case LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION:
770         if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION_LENGTH) {
771 		return hexdump;
772         }
773         ND_PRINT("\n\t    RES: %u", GET_U_1(tptr + 4));
774         /*Print Priority Assignment Table */
775         print_ets_priority_assignment_table(ndo, tptr + 5);
776         /*Print TC Bandwidth Table */
777         print_tc_bandwidth_table(ndo, tptr + 9);
778         /* Print TSA Assignment Table */
779         print_tsa_assignment_table(ndo, tptr + 17);
780         break;
781 
782     case LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION:
783         if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION_LENGTH) {
784             return hexdump;
785         }
786         tval=GET_U_1(tptr + 4);
787         ND_PRINT("\n\t    Willing: %u, MBC: %u, RES: %u, PFC cap:%u ",
788 		tval >> 7, (tval >> 6) & 0x01, (tval >> 4) & 0x03, (tval & 0x0f));
789         ND_PRINT("\n\t    PFC Enable");
790         tval=GET_U_1(tptr + 5);
791         ND_PRINT("\n\t     Priority : 0  1  2  3  4  5  6  7");
792         ND_PRINT("\n\t     Value    : ");
793         for(i=0;i<NO_OF_BITS;i++)
794             ND_PRINT("%-2d ", (tval >> i) & 0x01);
795         break;
796 
797     case LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY:
798         if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY_MIN_LENGTH) {
799             return hexdump;
800         }
801         ND_PRINT("\n\t    RES: %u", GET_U_1(tptr + 4));
802         if(tlv_len<=LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY_MIN_LENGTH){
803 		return hexdump;
804         }
805         /*  Length of Application Priority Table */
806         sublen=tlv_len-5;
807         if(sublen%3!=0){
808 		return hexdump;
809         }
810         i=0;
811         ND_PRINT("\n\t    Application Priority Table");
812         while(i<sublen) {
813 		tval=GET_U_1(tptr + i + 5);
814 		ND_PRINT("\n\t      Priority: %u, RES: %u, Sel: %u, Protocol ID: %u",
815 			 tval >> 5, (tval >> 3) & 0x03, (tval & 0x07),
816 			 GET_BE_U_2(tptr + i + 6));
817 		i=i+3;
818         }
819         break;
820     case LLDP_PRIVATE_8021_SUBTYPE_EVB:
821         if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_EVB_LENGTH){
822 		return hexdump;
823         }
824         ND_PRINT("\n\t    EVB Bridge Status");
825         tval=GET_U_1(tptr + 4);
826         ND_PRINT("\n\t      RES: %u, BGID: %u, RRCAP: %u, RRCTR: %u",
827 		tval >> 3, (tval >> 2) & 0x01, (tval >> 1) & 0x01, tval & 0x01);
828         ND_PRINT("\n\t    EVB Station Status");
829         tval=GET_U_1(tptr + 5);
830         ND_PRINT("\n\t      RES: %u, SGID: %u, RRREQ: %u,RRSTAT: %u",
831 		tval >> 4, (tval >> 3) & 0x01, (tval >> 2) & 0x01, tval & 0x03);
832         tval=GET_U_1(tptr + 6);
833         ND_PRINT("\n\t    R: %u, RTE: %u, ",tval >> 5, tval & 0x1f);
834         tval=GET_U_1(tptr + 7);
835         ND_PRINT("EVB Mode: %s [%u]",
836 		tok2str(lldp_evb_mode_values, "unknown", tval >> 6), tval >> 6);
837         ND_PRINT("\n\t    ROL: %u, RWD: %u, ", (tval >> 5) & 0x01, tval & 0x1f);
838         tval=GET_U_1(tptr + 8);
839         ND_PRINT("RES: %u, ROL: %u, RKA: %u", tval >> 6, (tval >> 5) & 0x01, tval & 0x1f);
840         break;
841 
842     case LLDP_PRIVATE_8021_SUBTYPE_CDCP:
843         if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_CDCP_MIN_LENGTH){
844 		return hexdump;
845         }
846         tval=GET_U_1(tptr + 4);
847         ND_PRINT("\n\t    Role: %u, RES: %u, Scomp: %u ",
848 		tval >> 7, (tval >> 4) & 0x07, (tval >> 3) & 0x01);
849         ND_PRINT("ChnCap: %u", GET_BE_U_2(tptr + 6) & 0x0fff);
850         sublen=tlv_len-8;
851         if(sublen%3!=0) {
852 		return hexdump;
853         }
854         i=0;
855         while(i<sublen) {
856 		tval=GET_BE_U_3(tptr + i + 8);
857 		ND_PRINT("\n\t    SCID: %u, SVID: %u",
858 			tval >> 12, tval & 0x000fff);
859 		i=i+3;
860         }
861         break;
862 
863     default:
864         hexdump = TRUE;
865         break;
866     }
867 
868     return hexdump;
869 }
870 
871 /*
872  * Print IEEE 802.3 private extensions. (802.3bc)
873  */
874 static int
875 lldp_private_8023_print(netdissect_options *ndo,
876                         const u_char *tptr, u_int tlv_len)
877 {
878     int hexdump = FALSE;
879     u_int subtype;
880 
881     if (tlv_len < 4) {
882         return hexdump;
883     }
884     subtype = GET_U_1(tptr + 3);
885 
886     ND_PRINT("\n\t  %s Subtype (%u)",
887            tok2str(lldp_8023_subtype_values, "unknown", subtype),
888            subtype);
889 
890     switch (subtype) {
891     case LLDP_PRIVATE_8023_SUBTYPE_MACPHY:
892         if (tlv_len < 9) {
893             return hexdump;
894         }
895         ND_PRINT("\n\t    autonegotiation [%s] (0x%02x)",
896                bittok2str(lldp_8023_autonegotiation_values, "none", GET_U_1(tptr + 4)),
897                GET_U_1(tptr + 4));
898         ND_PRINT("\n\t    PMD autoneg capability [%s] (0x%04x)",
899                bittok2str(lldp_pmd_capability_values,"unknown", GET_BE_U_2(tptr + 5)),
900                GET_BE_U_2(tptr + 5));
901         ND_PRINT("\n\t    MAU type %s (0x%04x)",
902                tok2str(lldp_mau_types_values, "unknown", GET_BE_U_2(tptr + 7)),
903                GET_BE_U_2(tptr + 7));
904         break;
905 
906     case LLDP_PRIVATE_8023_SUBTYPE_MDIPOWER:
907         if (tlv_len < 7) {
908             return hexdump;
909         }
910         ND_PRINT("\n\t    MDI power support [%s], power pair %s, power class %s",
911                bittok2str(lldp_mdi_values, "none", GET_U_1((tptr + 4))),
912                tok2str(lldp_mdi_power_pairs_values, "unknown", GET_U_1((tptr + 5))),
913                tok2str(lldp_mdi_power_class_values, "unknown", GET_U_1((tptr + 6))));
914         break;
915 
916     case LLDP_PRIVATE_8023_SUBTYPE_LINKAGGR:
917         if (tlv_len < 9) {
918             return hexdump;
919         }
920         ND_PRINT("\n\t    aggregation status [%s], aggregation port ID %u",
921                bittok2str(lldp_aggregation_values, "none", GET_U_1((tptr + 4))),
922                GET_BE_U_4(tptr + 5));
923         break;
924 
925     case LLDP_PRIVATE_8023_SUBTYPE_MTU:
926         if (tlv_len < 6) {
927             return hexdump;
928         }
929         ND_PRINT("\n\t    MTU size %u", GET_BE_U_2(tptr + 4));
930         break;
931 
932     default:
933         hexdump = TRUE;
934         break;
935     }
936 
937     return hexdump;
938 }
939 
940 /*
941  * Extract 34bits of latitude/longitude coordinates.
942  */
943 static uint64_t
944 lldp_extract_latlon(netdissect_options *ndo, const u_char *tptr)
945 {
946     uint64_t latlon;
947 
948     latlon = GET_U_1(tptr) & 0x3;
949     latlon = (latlon << 32) | GET_BE_U_4(tptr + 1);
950 
951     return latlon;
952 }
953 
954 /* objects defined in IANA subtype 00 00 5e
955  * (right now there is only one)
956  */
957 
958 
959 static int
960 lldp_private_iana_print(netdissect_options *ndo,
961                         const u_char *tptr, u_int tlv_len)
962 {
963     int hexdump = FALSE;
964     u_int subtype;
965 
966     if (tlv_len < 8) {
967         return hexdump;
968     }
969     subtype = GET_U_1(tptr + 3);
970 
971     ND_PRINT("\n\t  %s Subtype (%u)",
972            tok2str(lldp_iana_subtype_values, "unknown", subtype),
973            subtype);
974 
975     switch (subtype) {
976     case LLDP_IANA_SUBTYPE_MUDURL:
977         ND_PRINT("\n\t  MUD-URL=");
978         (void)nd_printn(ndo, tptr+4, tlv_len-4, NULL);
979         break;
980     default:
981         hexdump=TRUE;
982     }
983 
984     return hexdump;
985 }
986 
987 
988 
989 /*
990  * Print private TIA extensions.
991  */
992 static int
993 lldp_private_tia_print(netdissect_options *ndo,
994                        const u_char *tptr, u_int tlv_len)
995 {
996     int hexdump = FALSE;
997     u_int subtype;
998     uint8_t location_format;
999     uint16_t power_val;
1000     u_int lci_len;
1001     uint8_t ca_type, ca_len;
1002 
1003     if (tlv_len < 4) {
1004         return hexdump;
1005     }
1006     subtype = GET_U_1(tptr + 3);
1007 
1008     ND_PRINT("\n\t  %s Subtype (%u)",
1009            tok2str(lldp_tia_subtype_values, "unknown", subtype),
1010            subtype);
1011 
1012     switch (subtype) {
1013     case LLDP_PRIVATE_TIA_SUBTYPE_CAPABILITIES:
1014         if (tlv_len < 7) {
1015             return hexdump;
1016         }
1017         ND_PRINT("\n\t    Media capabilities [%s] (0x%04x)",
1018                bittok2str(lldp_tia_capabilities_values, "none",
1019                           GET_BE_U_2(tptr + 4)), GET_BE_U_2(tptr + 4));
1020         ND_PRINT("\n\t    Device type [%s] (0x%02x)",
1021                tok2str(lldp_tia_device_type_values, "unknown", GET_U_1(tptr + 6)),
1022                GET_U_1(tptr + 6));
1023         break;
1024 
1025     case LLDP_PRIVATE_TIA_SUBTYPE_NETWORK_POLICY:
1026         if (tlv_len < 8) {
1027             return hexdump;
1028         }
1029         ND_PRINT("\n\t    Application type [%s] (0x%02x)",
1030                tok2str(lldp_tia_application_type_values, "none", GET_U_1(tptr + 4)),
1031                GET_U_1(tptr + 4));
1032         ND_PRINT(", Flags [%s]", bittok2str(
1033                    lldp_tia_network_policy_bits_values, "none", GET_U_1((tptr + 5))));
1034         ND_PRINT("\n\t    Vlan id %u",
1035                LLDP_EXTRACT_NETWORK_POLICY_VLAN(GET_BE_U_2(tptr + 5)));
1036         ND_PRINT(", L2 priority %u",
1037                LLDP_EXTRACT_NETWORK_POLICY_L2_PRIORITY(GET_BE_U_2(tptr + 6)));
1038         ND_PRINT(", DSCP value %u",
1039                LLDP_EXTRACT_NETWORK_POLICY_DSCP(GET_BE_U_2(tptr + 6)));
1040         break;
1041 
1042     case LLDP_PRIVATE_TIA_SUBTYPE_LOCAL_ID:
1043         if (tlv_len < 5) {
1044             return hexdump;
1045         }
1046         location_format = GET_U_1(tptr + 4);
1047         ND_PRINT("\n\t    Location data format %s (0x%02x)",
1048                tok2str(lldp_tia_location_data_format_values, "unknown", location_format),
1049                location_format);
1050 
1051         switch (location_format) {
1052         case LLDP_TIA_LOCATION_DATA_FORMAT_COORDINATE_BASED:
1053             if (tlv_len < 21) {
1054                 return hexdump;
1055             }
1056             ND_PRINT("\n\t    Latitude resolution %u, latitude value %" PRIu64,
1057                    (GET_U_1(tptr + 5) >> 2),
1058                    lldp_extract_latlon(ndo, tptr + 5));
1059             ND_PRINT("\n\t    Longitude resolution %u, longitude value %" PRIu64,
1060                    (GET_U_1(tptr + 10) >> 2),
1061                    lldp_extract_latlon(ndo, tptr + 10));
1062             ND_PRINT("\n\t    Altitude type %s (%u)",
1063                    tok2str(lldp_tia_location_altitude_type_values, "unknown",GET_U_1(tptr + 15) >> 4),
1064                    (GET_U_1(tptr + 15) >> 4));
1065             ND_PRINT("\n\t    Altitude resolution %u, altitude value 0x%x",
1066                    (GET_BE_U_2(tptr + 15)>>6)&0x3f,
1067                    (GET_BE_U_4(tptr + 16) & 0x3fffffff));
1068             ND_PRINT("\n\t    Datum %s (0x%02x)",
1069                    tok2str(lldp_tia_location_datum_type_values, "unknown", GET_U_1(tptr + 20)),
1070                    GET_U_1(tptr + 20));
1071             break;
1072 
1073         case LLDP_TIA_LOCATION_DATA_FORMAT_CIVIC_ADDRESS:
1074             if (tlv_len < 6) {
1075                 return hexdump;
1076             }
1077             lci_len = GET_U_1(tptr + 5);
1078             if (lci_len < 3) {
1079                 return hexdump;
1080             }
1081             if (tlv_len < 7+lci_len) {
1082                 return hexdump;
1083             }
1084             ND_PRINT("\n\t    LCI length %u, LCI what %s (0x%02x), Country-code ",
1085                    lci_len,
1086                    tok2str(lldp_tia_location_lci_what_values, "unknown", GET_U_1(tptr + 6)),
1087                    GET_U_1(tptr + 6));
1088 
1089             /* Country code */
1090             nd_printjnp(ndo, tptr + 7, 2);
1091 
1092             lci_len = lci_len-3;
1093             tptr = tptr + 9;
1094 
1095             /* Decode each civic address element */
1096             while (lci_len > 0) {
1097                 if (lci_len < 2) {
1098                     return hexdump;
1099                 }
1100 		ca_type = GET_U_1(tptr);
1101                 ca_len = GET_U_1(tptr + 1);
1102 
1103 		tptr += 2;
1104                 lci_len -= 2;
1105 
1106                 ND_PRINT("\n\t      CA type \'%s\' (%u), length %u: ",
1107                        tok2str(lldp_tia_location_lci_catype_values, "unknown", ca_type),
1108                        ca_type, ca_len);
1109 
1110 		/* basic sanity check */
1111 		if ( ca_type == 0 || ca_len == 0) {
1112                     return hexdump;
1113 		}
1114 		if (lci_len < ca_len) {
1115 		    return hexdump;
1116 		}
1117 
1118                 nd_printjnp(ndo, tptr, ca_len);
1119                 tptr += ca_len;
1120                 lci_len -= ca_len;
1121             }
1122             break;
1123 
1124         case LLDP_TIA_LOCATION_DATA_FORMAT_ECS_ELIN:
1125             ND_PRINT("\n\t    ECS ELIN id ");
1126             nd_printjnp(ndo, tptr + 5, tlv_len - 5);
1127             break;
1128 
1129         default:
1130             ND_PRINT("\n\t    Location ID ");
1131             print_unknown_data(ndo, tptr + 5, "\n\t      ", tlv_len - 5);
1132         }
1133         break;
1134 
1135     case LLDP_PRIVATE_TIA_SUBTYPE_EXTENDED_POWER_MDI:
1136         if (tlv_len < 7) {
1137             return hexdump;
1138         }
1139         ND_PRINT("\n\t    Power type [%s]",
1140                (GET_U_1(tptr + 4) & 0xC0 >> 6) ? "PD device" : "PSE device");
1141         ND_PRINT(", Power source [%s]",
1142                tok2str(lldp_tia_power_source_values, "none", (GET_U_1((tptr + 4)) & 0x30) >> 4));
1143         ND_PRINT("\n\t    Power priority [%s] (0x%02x)",
1144                tok2str(lldp_tia_power_priority_values, "none", GET_U_1(tptr + 4) & 0x0f),
1145                GET_U_1(tptr + 4) & 0x0f);
1146         power_val = GET_BE_U_2(tptr + 5);
1147         if (power_val < LLDP_TIA_POWER_VAL_MAX) {
1148             ND_PRINT(", Power %.1f Watts", ((float)power_val) / 10);
1149         } else {
1150             ND_PRINT(", Power %u (Reserved)", power_val);
1151         }
1152         break;
1153 
1154     case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV:
1155     case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV:
1156     case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV:
1157     case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER:
1158     case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME:
1159     case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME:
1160     case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID:
1161         ND_PRINT("\n\t  %s ",
1162                tok2str(lldp_tia_inventory_values, "unknown", subtype));
1163         nd_printjnp(ndo, tptr + 4, tlv_len - 4);
1164         break;
1165 
1166     default:
1167         hexdump = TRUE;
1168         break;
1169     }
1170 
1171     return hexdump;
1172 }
1173 
1174 /*
1175  * Print DCBX Protocol fields (V 1.01).
1176  */
1177 static int
1178 lldp_private_dcbx_print(netdissect_options *ndo,
1179                         const u_char *pptr, u_int len)
1180 {
1181     int hexdump = FALSE;
1182     u_int subtype;
1183     uint16_t tval;
1184     uint16_t tlv;
1185     uint32_t i, pgval, uval;
1186     u_int tlen, tlv_type;
1187     uint16_t tlv_len;
1188     const u_char *tptr, *mptr;
1189 
1190     if (len < 4) {
1191         return hexdump;
1192     }
1193     subtype = GET_U_1(pptr + 3);
1194 
1195     ND_PRINT("\n\t  %s Subtype (%u)",
1196            tok2str(lldp_dcbx_subtype_values, "unknown", subtype),
1197            subtype);
1198 
1199     /* by passing old version */
1200     if (subtype == LLDP_DCBX_SUBTYPE_1)
1201 	return TRUE;
1202 
1203     tptr = pptr + 4;
1204     tlen = len - 4;
1205 
1206     while (tlen >= sizeof(tlv)) {
1207 
1208         ND_TCHECK_LEN(tptr, sizeof(tlv));
1209 
1210         tlv = GET_BE_U_2(tptr);
1211 
1212         tlv_type = LLDP_EXTRACT_TYPE(tlv);
1213         tlv_len = LLDP_EXTRACT_LEN(tlv);
1214         hexdump = FALSE;
1215 
1216         tlen -= sizeof(tlv);
1217         tptr += sizeof(tlv);
1218 
1219         /* loop check */
1220         if (!tlv_type || !tlv_len) {
1221             break;
1222         }
1223 
1224         ND_TCHECK_LEN(tptr, tlv_len);
1225         if (tlen < tlv_len) {
1226             goto trunc;
1227         }
1228 
1229 	/* decode every tlv */
1230         switch (tlv_type) {
1231         case LLDP_DCBX_CONTROL_TLV:
1232             if (tlv_len < 10) {
1233                 goto trunc;
1234             }
1235 	    ND_PRINT("\n\t    Control - Protocol Control (type 0x%x, length %u)",
1236 		LLDP_DCBX_CONTROL_TLV, tlv_len);
1237 	    ND_PRINT("\n\t      Oper_Version: %u", GET_U_1(tptr));
1238 	    ND_PRINT("\n\t      Max_Version: %u", GET_U_1(tptr + 1));
1239 	    ND_PRINT("\n\t      Sequence Number: %u", GET_BE_U_4(tptr + 2));
1240 	    ND_PRINT("\n\t      Acknowledgement Number: %u",
1241 					GET_BE_U_4(tptr + 6));
1242 	    break;
1243         case LLDP_DCBX_PRIORITY_GROUPS_TLV:
1244             if (tlv_len < 17) {
1245                 goto trunc;
1246             }
1247 	    ND_PRINT("\n\t    Feature - Priority Group (type 0x%x, length %u)",
1248 		LLDP_DCBX_PRIORITY_GROUPS_TLV, tlv_len);
1249 	    ND_PRINT("\n\t      Oper_Version: %u", GET_U_1(tptr));
1250 	    ND_PRINT("\n\t      Max_Version: %u", GET_U_1(tptr + 1));
1251 	    ND_PRINT("\n\t      Info block(0x%02X): ", GET_U_1(tptr + 2));
1252 	    tval = GET_U_1(tptr + 2);
1253 	    ND_PRINT("Enable bit: %u, Willing bit: %u, Error Bit: %u",
1254 		(tval &  0x80) ? 1 : 0, (tval &  0x40) ? 1 : 0,
1255 		(tval &  0x20) ? 1 : 0);
1256 	    ND_PRINT("\n\t      SubType: %u", GET_U_1(tptr + 3));
1257 	    ND_PRINT("\n\t      Priority Allocation");
1258 
1259 	    /*
1260 	     * Array of 8 4-bit priority group ID values; we fetch all
1261 	     * 32 bits and extract each nibble.
1262 	     */
1263 	    pgval = GET_BE_U_4(tptr + 4);
1264 	    for (i = 0; i <= 7; i++) {
1265 		ND_PRINT("\n\t          PgId_%u: %u",
1266 			i, (pgval >> (28 - 4 * i)) & 0xF);
1267 	    }
1268 	    ND_PRINT("\n\t      Priority Group Allocation");
1269 	    for (i = 0; i <= 7; i++)
1270 		ND_PRINT("\n\t          Pg percentage[%u]: %u", i,
1271                          GET_U_1(tptr + 8 + i));
1272 	    ND_PRINT("\n\t      NumTCsSupported: %u", GET_U_1(tptr + 8 + 8));
1273 	    break;
1274         case LLDP_DCBX_PRIORITY_FLOW_CONTROL_TLV:
1275             if (tlv_len < 6) {
1276                 goto trunc;
1277             }
1278 	    ND_PRINT("\n\t    Feature - Priority Flow Control");
1279 	    ND_PRINT(" (type 0x%x, length %u)",
1280 		LLDP_DCBX_PRIORITY_FLOW_CONTROL_TLV, tlv_len);
1281 	    ND_PRINT("\n\t      Oper_Version: %u", GET_U_1(tptr));
1282 	    ND_PRINT("\n\t      Max_Version: %u", GET_U_1(tptr + 1));
1283 	    ND_PRINT("\n\t      Info block(0x%02X): ", GET_U_1(tptr + 2));
1284 	    tval = GET_U_1(tptr + 2);
1285 	    ND_PRINT("Enable bit: %u, Willing bit: %u, Error Bit: %u",
1286 		(tval &  0x80) ? 1 : 0, (tval &  0x40) ? 1 : 0,
1287 		(tval &  0x20) ? 1 : 0);
1288 	    ND_PRINT("\n\t      SubType: %u", GET_U_1(tptr + 3));
1289 	    tval = GET_U_1(tptr + 4);
1290 	    ND_PRINT("\n\t      PFC Config (0x%02X)", GET_U_1(tptr + 4));
1291 	    for (i = 0; i <= 7; i++)
1292 		ND_PRINT("\n\t          Priority Bit %u: %s",
1293 		    i, (tval & (1 << i)) ? "Enabled" : "Disabled");
1294 	    ND_PRINT("\n\t      NumTCPFCSupported: %u", GET_U_1(tptr + 5));
1295 	    break;
1296         case LLDP_DCBX_APPLICATION_TLV:
1297             if (tlv_len < 4) {
1298                 goto trunc;
1299             }
1300 	    ND_PRINT("\n\t    Feature - Application (type 0x%x, length %u)",
1301 		LLDP_DCBX_APPLICATION_TLV, tlv_len);
1302 	    ND_PRINT("\n\t      Oper_Version: %u", GET_U_1(tptr));
1303 	    ND_PRINT("\n\t      Max_Version: %u", GET_U_1(tptr + 1));
1304 	    ND_PRINT("\n\t      Info block(0x%02X): ", GET_U_1(tptr + 2));
1305 	    tval = GET_U_1(tptr + 2);
1306 	    ND_PRINT("Enable bit: %u, Willing bit: %u, Error Bit: %u",
1307 		(tval &  0x80) ? 1 : 0, (tval &  0x40) ? 1 : 0,
1308 		(tval &  0x20) ? 1 : 0);
1309 	    ND_PRINT("\n\t      SubType: %u", GET_U_1(tptr + 3));
1310 	    tval = tlv_len - 4;
1311 	    mptr = tptr + 4;
1312 	    while (tval >= 6) {
1313 		ND_PRINT("\n\t      Application Value");
1314 		ND_PRINT("\n\t          Application Protocol ID: 0x%04x",
1315 			GET_BE_U_2(mptr));
1316 		uval = GET_BE_U_3(mptr + 2);
1317 		ND_PRINT("\n\t          SF (0x%x) Application Protocol ID is %s",
1318 			(uval >> 22),
1319 			(uval >> 22) ? "Socket Number" : "L2 EtherType");
1320 		ND_PRINT("\n\t          OUI: 0x%06x", uval & 0x3fffff);
1321 		ND_PRINT("\n\t          User Priority Map: 0x%02x",
1322                          GET_U_1(mptr + 5));
1323 		tval = tval - 6;
1324 		mptr = mptr + 6;
1325 	    }
1326 	    break;
1327 	default:
1328 	    hexdump = TRUE;
1329 	    break;
1330 	}
1331 
1332         /* do we also want to see a hex dump ? */
1333         if (ndo->ndo_vflag > 1 || (ndo->ndo_vflag && hexdump)) {
1334 	    print_unknown_data(ndo, tptr, "\n\t    ", tlv_len);
1335         }
1336 
1337         tlen -= tlv_len;
1338         tptr += tlv_len;
1339     }
1340 
1341  trunc:
1342     return hexdump;
1343 }
1344 
1345 static char *
1346 lldp_network_addr_print(netdissect_options *ndo, const u_char *tptr, u_int len)
1347 {
1348     uint8_t af;
1349     static char buf[BUFSIZE];
1350     const char * (*pfunc)(netdissect_options *, const u_char *);
1351 
1352     if (len < 1)
1353       return NULL;
1354     len--;
1355     af = GET_U_1(tptr);
1356     switch (af) {
1357     case AFNUM_INET:
1358         if (len < sizeof(nd_ipv4))
1359           return NULL;
1360         pfunc = ipaddr_string;
1361         break;
1362     case AFNUM_INET6:
1363         if (len < sizeof(nd_ipv6))
1364           return NULL;
1365         pfunc = ip6addr_string;
1366         break;
1367     case AFNUM_802:
1368         if (len < MAC_ADDR_LEN)
1369           return NULL;
1370         pfunc = etheraddr_string;
1371         break;
1372     default:
1373         pfunc = NULL;
1374         break;
1375     }
1376 
1377     if (!pfunc) {
1378         snprintf(buf, sizeof(buf), "AFI %s (%u), no AF printer !",
1379                  tok2str(af_values, "Unknown", af), af);
1380     } else {
1381         snprintf(buf, sizeof(buf), "AFI %s (%u): %s",
1382                  tok2str(af_values, "Unknown", af), af, (*pfunc)(ndo, tptr+1));
1383     }
1384 
1385     return buf;
1386 }
1387 
1388 static int
1389 lldp_mgmt_addr_tlv_print(netdissect_options *ndo,
1390                          const u_char *pptr, u_int len)
1391 {
1392     uint8_t mgmt_addr_len, intf_num_subtype, oid_len;
1393     const u_char *tptr;
1394     u_int tlen;
1395     char *mgmt_addr;
1396 
1397     tlen = len;
1398     tptr = pptr;
1399 
1400     if (tlen < 1) {
1401         return 0;
1402     }
1403     mgmt_addr_len = GET_U_1(tptr);
1404     tptr++;
1405     tlen--;
1406 
1407     if (tlen < mgmt_addr_len) {
1408         return 0;
1409     }
1410 
1411     mgmt_addr = lldp_network_addr_print(ndo, tptr, mgmt_addr_len);
1412     if (mgmt_addr == NULL) {
1413         return 0;
1414     }
1415     ND_PRINT("\n\t  Management Address length %u, %s",
1416            mgmt_addr_len, mgmt_addr);
1417     tptr += mgmt_addr_len;
1418     tlen -= mgmt_addr_len;
1419 
1420     if (tlen < LLDP_INTF_NUM_LEN) {
1421         return 0;
1422     }
1423 
1424     intf_num_subtype = GET_U_1(tptr);
1425     ND_PRINT("\n\t  %s Interface Numbering (%u): %u",
1426            tok2str(lldp_intf_numb_subtype_values, "Unknown", intf_num_subtype),
1427            intf_num_subtype,
1428            GET_BE_U_4(tptr + 1));
1429 
1430     tptr += LLDP_INTF_NUM_LEN;
1431     tlen -= LLDP_INTF_NUM_LEN;
1432 
1433     /*
1434      * The OID is optional.
1435      */
1436     if (tlen) {
1437         oid_len = GET_U_1(tptr);
1438 
1439         if (tlen < 1U + oid_len) {
1440             return 0;
1441         }
1442         if (oid_len) {
1443             ND_PRINT("\n\t  OID length %u", oid_len);
1444             nd_printjnp(ndo, tptr + 1, oid_len);
1445         }
1446     }
1447 
1448     return 1;
1449 }
1450 
1451 void
1452 lldp_print(netdissect_options *ndo,
1453            const u_char *pptr, u_int len)
1454 {
1455     uint8_t subtype;
1456     uint16_t tlv, cap, ena_cap;
1457     u_int oui, tlen, hexdump, tlv_type, tlv_len;
1458     const u_char *tptr;
1459     char *network_addr;
1460 
1461     ndo->ndo_protocol = "lldp";
1462     tptr = pptr;
1463     tlen = len;
1464 
1465     ND_PRINT("LLDP, length %u", len);
1466 
1467     while (tlen >= sizeof(tlv)) {
1468 
1469         ND_TCHECK_LEN(tptr, sizeof(tlv));
1470 
1471         tlv = GET_BE_U_2(tptr);
1472 
1473         tlv_type = LLDP_EXTRACT_TYPE(tlv);
1474         tlv_len = LLDP_EXTRACT_LEN(tlv);
1475         hexdump = FALSE;
1476 
1477         tlen -= sizeof(tlv);
1478         tptr += sizeof(tlv);
1479 
1480         if (ndo->ndo_vflag) {
1481             ND_PRINT("\n\t%s TLV (%u), length %u",
1482                    tok2str(lldp_tlv_values, "Unknown", tlv_type),
1483                    tlv_type, tlv_len);
1484         }
1485 
1486         /* infinite loop check */
1487         if (!tlv_type || !tlv_len) {
1488             break;
1489         }
1490 
1491         ND_TCHECK_LEN(tptr, tlv_len);
1492         if (tlen < tlv_len) {
1493             goto trunc;
1494         }
1495 
1496         switch (tlv_type) {
1497 
1498         case LLDP_CHASSIS_ID_TLV:
1499             if (ndo->ndo_vflag) {
1500                 if (tlv_len < 2) {
1501                     goto trunc;
1502                 }
1503                 subtype = GET_U_1(tptr);
1504                 ND_PRINT("\n\t  Subtype %s (%u): ",
1505                        tok2str(lldp_chassis_subtype_values, "Unknown", subtype),
1506                        subtype);
1507 
1508                 switch (subtype) {
1509                 case LLDP_CHASSIS_MAC_ADDR_SUBTYPE:
1510                     if (tlv_len < 1+6) {
1511                         goto trunc;
1512                     }
1513                     ND_PRINT("%s", GET_ETHERADDR_STRING(tptr + 1));
1514                     break;
1515 
1516                 case LLDP_CHASSIS_INTF_NAME_SUBTYPE: /* fall through */
1517                 case LLDP_CHASSIS_LOCAL_SUBTYPE:
1518                 case LLDP_CHASSIS_CHASSIS_COMP_SUBTYPE:
1519                 case LLDP_CHASSIS_INTF_ALIAS_SUBTYPE:
1520                 case LLDP_CHASSIS_PORT_COMP_SUBTYPE:
1521                     nd_printjnp(ndo, tptr + 1, tlv_len - 1);
1522                     break;
1523 
1524                 case LLDP_CHASSIS_NETWORK_ADDR_SUBTYPE:
1525                     network_addr = lldp_network_addr_print(ndo, tptr+1, tlv_len-1);
1526                     if (network_addr == NULL) {
1527                         goto trunc;
1528                     }
1529                     ND_PRINT("%s", network_addr);
1530                     break;
1531 
1532                 default:
1533                     hexdump = TRUE;
1534                     break;
1535                 }
1536             }
1537             break;
1538 
1539         case LLDP_PORT_ID_TLV:
1540             if (ndo->ndo_vflag) {
1541                 if (tlv_len < 2) {
1542                     goto trunc;
1543                 }
1544                 subtype = GET_U_1(tptr);
1545                 ND_PRINT("\n\t  Subtype %s (%u): ",
1546                        tok2str(lldp_port_subtype_values, "Unknown", subtype),
1547                        subtype);
1548 
1549                 switch (subtype) {
1550                 case LLDP_PORT_MAC_ADDR_SUBTYPE:
1551                     if (tlv_len < 1+6) {
1552                         goto trunc;
1553                     }
1554                     ND_PRINT("%s", GET_ETHERADDR_STRING(tptr + 1));
1555                     break;
1556 
1557                 case LLDP_PORT_INTF_NAME_SUBTYPE: /* fall through */
1558                 case LLDP_PORT_LOCAL_SUBTYPE:
1559                 case LLDP_PORT_AGENT_CIRC_ID_SUBTYPE:
1560                 case LLDP_PORT_INTF_ALIAS_SUBTYPE:
1561                 case LLDP_PORT_PORT_COMP_SUBTYPE:
1562                     nd_printjnp(ndo, tptr + 1, tlv_len - 1);
1563                     break;
1564 
1565                 case LLDP_PORT_NETWORK_ADDR_SUBTYPE:
1566                     network_addr = lldp_network_addr_print(ndo, tptr+1, tlv_len-1);
1567                     if (network_addr == NULL) {
1568                         goto trunc;
1569                     }
1570                     ND_PRINT("%s", network_addr);
1571                     break;
1572 
1573                 default:
1574                     hexdump = TRUE;
1575                     break;
1576                 }
1577             }
1578             break;
1579 
1580         case LLDP_TTL_TLV:
1581             if (ndo->ndo_vflag) {
1582                 if (tlv_len < 2) {
1583                     goto trunc;
1584                 }
1585                 ND_PRINT(": TTL %us", GET_BE_U_2(tptr));
1586             }
1587             break;
1588 
1589         case LLDP_PORT_DESCR_TLV:
1590             if (ndo->ndo_vflag) {
1591                 ND_PRINT(": ");
1592                 nd_printjnp(ndo, tptr, tlv_len);
1593             }
1594             break;
1595 
1596         case LLDP_SYSTEM_NAME_TLV:
1597             /*
1598              * The system name is also print in non-verbose mode
1599              * similar to the CDP printer.
1600              */
1601             ND_PRINT(": ");
1602             nd_printjnp(ndo, tptr, tlv_len);
1603             break;
1604 
1605         case LLDP_SYSTEM_DESCR_TLV:
1606             if (ndo->ndo_vflag) {
1607                 ND_PRINT("\n\t  ");
1608                 nd_printjnp(ndo, tptr, tlv_len);
1609             }
1610             break;
1611 
1612         case LLDP_SYSTEM_CAP_TLV:
1613             if (ndo->ndo_vflag) {
1614                 /*
1615                  * XXX - IEEE Std 802.1AB-2009 says the first octet
1616                  * if a chassis ID subtype, with the system
1617                  * capabilities and enabled capabilities following
1618                  * it.
1619                  */
1620                 if (tlv_len < 4) {
1621                     goto trunc;
1622                 }
1623                 cap = GET_BE_U_2(tptr);
1624                 ena_cap = GET_BE_U_2(tptr + 2);
1625                 ND_PRINT("\n\t  System  Capabilities [%s] (0x%04x)",
1626                        bittok2str(lldp_cap_values, "none", cap), cap);
1627                 ND_PRINT("\n\t  Enabled Capabilities [%s] (0x%04x)",
1628                        bittok2str(lldp_cap_values, "none", ena_cap), ena_cap);
1629             }
1630             break;
1631 
1632         case LLDP_MGMT_ADDR_TLV:
1633             if (ndo->ndo_vflag) {
1634                 if (!lldp_mgmt_addr_tlv_print(ndo, tptr, tlv_len)) {
1635                     goto trunc;
1636                 }
1637             }
1638             break;
1639 
1640         case LLDP_PRIVATE_TLV:
1641             if (ndo->ndo_vflag) {
1642                 if (tlv_len < 3) {
1643                     goto trunc;
1644                 }
1645                 oui = GET_BE_U_3(tptr);
1646                 ND_PRINT(": OUI %s (0x%06x)", tok2str(oui_values, "Unknown", oui), oui);
1647 
1648                 switch (oui) {
1649                 case OUI_IEEE_8021_PRIVATE:
1650                     hexdump = lldp_private_8021_print(ndo, tptr, tlv_len);
1651                     break;
1652                 case OUI_IEEE_8023_PRIVATE:
1653                     hexdump = lldp_private_8023_print(ndo, tptr, tlv_len);
1654                     break;
1655 		case OUI_IANA:
1656                     hexdump = lldp_private_iana_print(ndo, tptr, tlv_len);
1657                     break;
1658                 case OUI_TIA:
1659                     hexdump = lldp_private_tia_print(ndo, tptr, tlv_len);
1660                     break;
1661                 case OUI_DCBX:
1662                     hexdump = lldp_private_dcbx_print(ndo, tptr, tlv_len);
1663                     break;
1664                 default:
1665                     hexdump = TRUE;
1666                     break;
1667                 }
1668             }
1669             break;
1670 
1671         default:
1672             hexdump = TRUE;
1673             break;
1674         }
1675 
1676         /* do we also want to see a hex dump ? */
1677         if (ndo->ndo_vflag > 1 || (ndo->ndo_vflag && hexdump)) {
1678             print_unknown_data(ndo, tptr, "\n\t  ", tlv_len);
1679         }
1680 
1681         tlen -= tlv_len;
1682         tptr += tlv_len;
1683     }
1684     return;
1685  trunc:
1686     nd_print_trunc(ndo);
1687 }
1688