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