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
53static 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
78static 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
100static 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
123static 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
147static 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
165static 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
176static 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
196static 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
214static 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
228static 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
238static 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
290static 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
338static 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
351static 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
366static 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
383static 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
399static 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
414static 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
425static 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
436static 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
447static 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
456static 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
487static 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
511static 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
522static 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
534static 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
546static 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
558static 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
575static 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
588static 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
607static const struct tok lldp_iana_subtype_values[] =   {
608    { LLDP_IANA_SUBTYPE_MUDURL, "MUD-URL" },
609    { 0, NULL }
610};
611
612
613static void
614print_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
624static void
625print_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
634static void
635print_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 */
647static int
648lldp_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 */
850static int
851lldp_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 */
918static uint64_t
919lldp_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
934static int
935lldp_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 */
966static int
967lldp_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 */
1148static int
1149lldp_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
1312static char *
1313lldp_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
1357static int
1358lldp_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
1419void
1420lldp_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