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