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