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