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