xref: /netbsd-src/external/bsd/tcpdump/dist/print-lldp.c (revision 26ba0b503b498a5194a71ac319838b7f5497f3fe)
10f74e101Schristos /*
20f74e101Schristos  * Copyright (c) 1998-2007 The TCPDUMP project
30f74e101Schristos  *
40f74e101Schristos  * Redistribution and use in source and binary forms, with or without
50f74e101Schristos  * modification, are permitted provided that: (1) source code
60f74e101Schristos  * distributions retain the above copyright notice and this paragraph
70f74e101Schristos  * in its entirety, and (2) distributions including binary code include
80f74e101Schristos  * the above copyright notice and this paragraph in its entirety in
90f74e101Schristos  * the documentation or other materials provided with the distribution.
100f74e101Schristos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
110f74e101Schristos  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
120f74e101Schristos  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
130f74e101Schristos  * FOR A PARTICULAR PURPOSE.
140f74e101Schristos  *
1572c96ff3Schristos  * Original code by Hannes Gredler (hannes@gredler.at)
160f74e101Schristos  * IEEE and TIA extensions by Carles Kishimoto <carles.kishimoto@gmail.com>
170e9868baSchristos  * DCBX extensions by Kaladhar Musunuru <kaladharm@sourceforge.net>
180f74e101Schristos  */
190f74e101Schristos 
20dc860a36Sspz /* \summary: IEEE 802.1ab Link Layer Discovery Protocol (LLDP) printer */
21dc860a36Sspz 
2211b3aaa1Schristos #include <sys/cdefs.h>
230f74e101Schristos #ifndef lint
24*26ba0b50Schristos __RCSID("$NetBSD: print-lldp.c,v 1.11 2024/09/02 16:15:31 christos Exp $");
250f74e101Schristos #endif
260f74e101Schristos 
27c74ad251Schristos #include <config.h>
280f74e101Schristos 
29c74ad251Schristos #include "netdissect-stdinc.h"
300f74e101Schristos 
310f74e101Schristos #include <stdio.h>
320f74e101Schristos 
33fdccd7e4Schristos #include "netdissect.h"
340f74e101Schristos #include "extract.h"
350f74e101Schristos #include "addrtoname.h"
360f74e101Schristos #include "af.h"
370f74e101Schristos #include "oui.h"
380f74e101Schristos 
390f74e101Schristos #define	LLDP_EXTRACT_TYPE(x) (((x)&0xfe00)>>9)
400f74e101Schristos #define	LLDP_EXTRACT_LEN(x) ((x)&0x01ff)
410f74e101Schristos 
420f74e101Schristos /*
430f74e101Schristos  * TLV type codes
440f74e101Schristos  */
450f74e101Schristos #define LLDP_END_TLV             0
460f74e101Schristos #define LLDP_CHASSIS_ID_TLV      1
470f74e101Schristos #define LLDP_PORT_ID_TLV         2
480f74e101Schristos #define LLDP_TTL_TLV             3
490f74e101Schristos #define LLDP_PORT_DESCR_TLV      4
500f74e101Schristos #define LLDP_SYSTEM_NAME_TLV     5
510f74e101Schristos #define LLDP_SYSTEM_DESCR_TLV    6
520f74e101Schristos #define LLDP_SYSTEM_CAP_TLV      7
530f74e101Schristos #define LLDP_MGMT_ADDR_TLV       8
540f74e101Schristos #define LLDP_PRIVATE_TLV       127
550f74e101Schristos 
560f74e101Schristos static const struct tok lldp_tlv_values[] = {
570f74e101Schristos     { LLDP_END_TLV, "End" },
580f74e101Schristos     { LLDP_CHASSIS_ID_TLV, "Chassis ID" },
590f74e101Schristos     { LLDP_PORT_ID_TLV, "Port ID" },
600f74e101Schristos     { LLDP_TTL_TLV, "Time to Live" },
610f74e101Schristos     { LLDP_PORT_DESCR_TLV, "Port Description" },
620f74e101Schristos     { LLDP_SYSTEM_NAME_TLV, "System Name" },
630f74e101Schristos     { LLDP_SYSTEM_DESCR_TLV, "System Description" },
640f74e101Schristos     { LLDP_SYSTEM_CAP_TLV, "System Capabilities" },
650f74e101Schristos     { LLDP_MGMT_ADDR_TLV, "Management Address" },
660f74e101Schristos     { LLDP_PRIVATE_TLV, "Organization specific" },
670f74e101Schristos     { 0, NULL}
680f74e101Schristos };
690f74e101Schristos 
700f74e101Schristos /*
710f74e101Schristos  * Chassis ID subtypes
720f74e101Schristos  */
730f74e101Schristos #define LLDP_CHASSIS_CHASSIS_COMP_SUBTYPE  1
740f74e101Schristos #define LLDP_CHASSIS_INTF_ALIAS_SUBTYPE    2
750f74e101Schristos #define LLDP_CHASSIS_PORT_COMP_SUBTYPE     3
760f74e101Schristos #define LLDP_CHASSIS_MAC_ADDR_SUBTYPE      4
770f74e101Schristos #define LLDP_CHASSIS_NETWORK_ADDR_SUBTYPE  5
780f74e101Schristos #define LLDP_CHASSIS_INTF_NAME_SUBTYPE     6
790f74e101Schristos #define LLDP_CHASSIS_LOCAL_SUBTYPE         7
800f74e101Schristos 
810f74e101Schristos static const struct tok lldp_chassis_subtype_values[] = {
820f74e101Schristos     { LLDP_CHASSIS_CHASSIS_COMP_SUBTYPE, "Chassis component"},
830f74e101Schristos     { LLDP_CHASSIS_INTF_ALIAS_SUBTYPE, "Interface alias"},
840f74e101Schristos     { LLDP_CHASSIS_PORT_COMP_SUBTYPE, "Port component"},
850f74e101Schristos     { LLDP_CHASSIS_MAC_ADDR_SUBTYPE, "MAC address"},
860f74e101Schristos     { LLDP_CHASSIS_NETWORK_ADDR_SUBTYPE, "Network address"},
870f74e101Schristos     { LLDP_CHASSIS_INTF_NAME_SUBTYPE, "Interface name"},
880f74e101Schristos     { LLDP_CHASSIS_LOCAL_SUBTYPE, "Local"},
890f74e101Schristos     { 0, NULL}
900f74e101Schristos };
910f74e101Schristos 
920f74e101Schristos /*
930f74e101Schristos  * Port ID subtypes
940f74e101Schristos  */
950f74e101Schristos #define LLDP_PORT_INTF_ALIAS_SUBTYPE       1
960f74e101Schristos #define LLDP_PORT_PORT_COMP_SUBTYPE        2
970f74e101Schristos #define LLDP_PORT_MAC_ADDR_SUBTYPE         3
980f74e101Schristos #define LLDP_PORT_NETWORK_ADDR_SUBTYPE     4
990f74e101Schristos #define LLDP_PORT_INTF_NAME_SUBTYPE        5
1000f74e101Schristos #define LLDP_PORT_AGENT_CIRC_ID_SUBTYPE    6
1010f74e101Schristos #define LLDP_PORT_LOCAL_SUBTYPE            7
1020f74e101Schristos 
1030f74e101Schristos static const struct tok lldp_port_subtype_values[] = {
1040f74e101Schristos     { LLDP_PORT_INTF_ALIAS_SUBTYPE, "Interface alias"},
1050f74e101Schristos     { LLDP_PORT_PORT_COMP_SUBTYPE, "Port component"},
1060f74e101Schristos     { LLDP_PORT_MAC_ADDR_SUBTYPE, "MAC address"},
1070f74e101Schristos     { LLDP_PORT_NETWORK_ADDR_SUBTYPE, "Network Address"},
1080f74e101Schristos     { LLDP_PORT_INTF_NAME_SUBTYPE, "Interface Name"},
1090f74e101Schristos     { LLDP_PORT_AGENT_CIRC_ID_SUBTYPE, "Agent circuit ID"},
1100f74e101Schristos     { LLDP_PORT_LOCAL_SUBTYPE, "Local"},
1110f74e101Schristos     { 0, NULL}
1120f74e101Schristos };
1130f74e101Schristos 
1140f74e101Schristos /*
1150f74e101Schristos  * System Capabilities
1160f74e101Schristos  */
1170f74e101Schristos #define LLDP_CAP_OTHER              (1 <<  0)
1180f74e101Schristos #define LLDP_CAP_REPEATER           (1 <<  1)
1190f74e101Schristos #define LLDP_CAP_BRIDGE             (1 <<  2)
1200f74e101Schristos #define LLDP_CAP_WLAN_AP            (1 <<  3)
1210f74e101Schristos #define LLDP_CAP_ROUTER             (1 <<  4)
1220f74e101Schristos #define LLDP_CAP_PHONE              (1 <<  5)
1230f74e101Schristos #define LLDP_CAP_DOCSIS             (1 <<  6)
1240f74e101Schristos #define LLDP_CAP_STATION_ONLY       (1 <<  7)
1250f74e101Schristos 
1260f74e101Schristos static const struct tok lldp_cap_values[] = {
1270f74e101Schristos     { LLDP_CAP_OTHER, "Other"},
1280f74e101Schristos     { LLDP_CAP_REPEATER, "Repeater"},
1290f74e101Schristos     { LLDP_CAP_BRIDGE, "Bridge"},
1300f74e101Schristos     { LLDP_CAP_WLAN_AP, "WLAN AP"},
1310f74e101Schristos     { LLDP_CAP_ROUTER, "Router"},
1320f74e101Schristos     { LLDP_CAP_PHONE, "Telephone"},
1330f74e101Schristos     { LLDP_CAP_DOCSIS, "Docsis"},
1340f74e101Schristos     { LLDP_CAP_STATION_ONLY, "Station Only"},
1350f74e101Schristos     { 0, NULL}
1360f74e101Schristos };
1370f74e101Schristos 
1380f74e101Schristos #define LLDP_PRIVATE_8021_SUBTYPE_PORT_VLAN_ID		1
1390f74e101Schristos #define LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_VLAN_ID	2
1400f74e101Schristos #define LLDP_PRIVATE_8021_SUBTYPE_VLAN_NAME		3
1410f74e101Schristos #define LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_IDENTITY	4
142c74ad251Schristos #define LLDP_PRIVATE_8021_SUBTYPE_LINKAGGR		7
143870189d2Schristos #define LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION 8
144870189d2Schristos #define LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION       9
145870189d2Schristos #define LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION     10
146870189d2Schristos #define LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION      11
147870189d2Schristos #define LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY   12
148870189d2Schristos #define LLDP_PRIVATE_8021_SUBTYPE_EVB                    13
149870189d2Schristos #define LLDP_PRIVATE_8021_SUBTYPE_CDCP			 14
1500f74e101Schristos 
1510f74e101Schristos static const struct tok lldp_8021_subtype_values[] = {
1520f74e101Schristos     { LLDP_PRIVATE_8021_SUBTYPE_PORT_VLAN_ID, "Port VLAN Id"},
1530f74e101Schristos     { LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_VLAN_ID, "Port and Protocol VLAN ID"},
1540f74e101Schristos     { LLDP_PRIVATE_8021_SUBTYPE_VLAN_NAME, "VLAN name"},
1550f74e101Schristos     { LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_IDENTITY, "Protocol Identity"},
156c74ad251Schristos     { LLDP_PRIVATE_8021_SUBTYPE_LINKAGGR, "Link aggregation"},
157870189d2Schristos     { LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION, "Congestion Notification"},
158870189d2Schristos     { LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION, "ETS Configuration"},
159870189d2Schristos     { LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION, "ETS Recommendation"},
160870189d2Schristos     { LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION, "Priority Flow Control Configuration"},
161870189d2Schristos     { LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY, "Application Priority"},
162870189d2Schristos     { LLDP_PRIVATE_8021_SUBTYPE_EVB, "EVB"},
163870189d2Schristos     { LLDP_PRIVATE_8021_SUBTYPE_CDCP,"CDCP"},
1640f74e101Schristos     { 0, NULL}
1650f74e101Schristos };
1660f74e101Schristos 
1670f74e101Schristos #define LLDP_8021_PORT_PROTOCOL_VLAN_SUPPORT       (1 <<  1)
1680f74e101Schristos #define LLDP_8021_PORT_PROTOCOL_VLAN_STATUS        (1 <<  2)
1690f74e101Schristos 
1700f74e101Schristos static const struct tok lldp_8021_port_protocol_id_values[] = {
1710f74e101Schristos     { LLDP_8021_PORT_PROTOCOL_VLAN_SUPPORT, "supported"},
1720f74e101Schristos     { LLDP_8021_PORT_PROTOCOL_VLAN_STATUS, "enabled"},
1730f74e101Schristos     { 0, NULL}
1740f74e101Schristos };
1750f74e101Schristos 
1760f74e101Schristos #define LLDP_PRIVATE_8023_SUBTYPE_MACPHY        1
1770f74e101Schristos #define LLDP_PRIVATE_8023_SUBTYPE_MDIPOWER      2
1780f74e101Schristos #define LLDP_PRIVATE_8023_SUBTYPE_LINKAGGR      3
1790f74e101Schristos #define LLDP_PRIVATE_8023_SUBTYPE_MTU           4
1800f74e101Schristos 
1810f74e101Schristos static const struct tok lldp_8023_subtype_values[] = {
1820f74e101Schristos     { LLDP_PRIVATE_8023_SUBTYPE_MACPHY,	"MAC/PHY configuration/status"},
1830f74e101Schristos     { LLDP_PRIVATE_8023_SUBTYPE_MDIPOWER, "Power via MDI"},
1840f74e101Schristos     { LLDP_PRIVATE_8023_SUBTYPE_LINKAGGR, "Link aggregation"},
1850f74e101Schristos     { LLDP_PRIVATE_8023_SUBTYPE_MTU, "Max frame size"},
1860f74e101Schristos     { 0, NULL}
1870f74e101Schristos };
1880f74e101Schristos 
1890f74e101Schristos #define LLDP_PRIVATE_TIA_SUBTYPE_CAPABILITIES                   1
1900f74e101Schristos #define LLDP_PRIVATE_TIA_SUBTYPE_NETWORK_POLICY                 2
1910f74e101Schristos #define LLDP_PRIVATE_TIA_SUBTYPE_LOCAL_ID                       3
1920f74e101Schristos #define LLDP_PRIVATE_TIA_SUBTYPE_EXTENDED_POWER_MDI             4
1930f74e101Schristos #define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV         5
1940f74e101Schristos #define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV         6
1950f74e101Schristos #define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV         7
1960f74e101Schristos #define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER        8
1970f74e101Schristos #define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME    9
1980f74e101Schristos #define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME           10
1990f74e101Schristos #define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID             11
2000f74e101Schristos 
2010f74e101Schristos static const struct tok lldp_tia_subtype_values[] = {
2020f74e101Schristos     { LLDP_PRIVATE_TIA_SUBTYPE_CAPABILITIES, "LLDP-MED Capabilities" },
2030f74e101Schristos     { LLDP_PRIVATE_TIA_SUBTYPE_NETWORK_POLICY, "Network policy" },
2040f74e101Schristos     { LLDP_PRIVATE_TIA_SUBTYPE_LOCAL_ID, "Location identification" },
2050f74e101Schristos     { LLDP_PRIVATE_TIA_SUBTYPE_EXTENDED_POWER_MDI, "Extended power-via-MDI" },
2060f74e101Schristos     { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV, "Inventory - hardware revision" },
2070f74e101Schristos     { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV, "Inventory - firmware revision" },
2080f74e101Schristos     { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV, "Inventory - software revision" },
2090f74e101Schristos     { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER, "Inventory - serial number" },
2100f74e101Schristos     { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME, "Inventory - manufacturer name" },
2110f74e101Schristos     { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME, "Inventory - model name" },
2120f74e101Schristos     { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID, "Inventory - asset ID" },
2130f74e101Schristos     { 0, NULL}
2140f74e101Schristos };
2150f74e101Schristos 
2160f74e101Schristos #define LLDP_PRIVATE_TIA_LOCATION_ALTITUDE_METERS       1
2170f74e101Schristos #define LLDP_PRIVATE_TIA_LOCATION_ALTITUDE_FLOORS       2
2180f74e101Schristos 
2190f74e101Schristos static const struct tok lldp_tia_location_altitude_type_values[] = {
2200f74e101Schristos     { LLDP_PRIVATE_TIA_LOCATION_ALTITUDE_METERS, "meters"},
2210f74e101Schristos     { LLDP_PRIVATE_TIA_LOCATION_ALTITUDE_FLOORS, "floors"},
2220f74e101Schristos     { 0, NULL}
2230f74e101Schristos };
2240f74e101Schristos 
2250f74e101Schristos /* ANSI/TIA-1057 - Annex B */
2260f74e101Schristos #define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A1		1
2270f74e101Schristos #define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A2		2
2280f74e101Schristos #define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A3		3
2290f74e101Schristos #define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A4		4
2300f74e101Schristos #define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A5		5
2310f74e101Schristos #define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A6		6
2320f74e101Schristos 
2330f74e101Schristos static const struct tok lldp_tia_location_lci_catype_values[] = {
2340f74e101Schristos     { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A1, "national subdivisions (state,canton,region,province,prefecture)"},
2350f74e101Schristos     { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A2, "county, parish, gun, district"},
2360f74e101Schristos     { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A3, "city, township, shi"},
2370f74e101Schristos     { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A4, "city division, borough, city district, ward chou"},
2380f74e101Schristos     { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A5, "neighborhood, block"},
2390f74e101Schristos     { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A6, "street"},
2400f74e101Schristos     { 0, NULL}
2410f74e101Schristos };
2420f74e101Schristos 
2430f74e101Schristos static const struct tok lldp_tia_location_lci_what_values[] = {
2440f74e101Schristos     { 0, "location of DHCP server"},
2450f74e101Schristos     { 1, "location of the network element believed to be closest to the client"},
2460f74e101Schristos     { 2, "location of the client"},
2470f74e101Schristos     { 0, NULL}
2480f74e101Schristos };
2490f74e101Schristos 
2500f74e101Schristos /*
2510f74e101Schristos  * From RFC 3636 - dot3MauType
2520f74e101Schristos  */
2530f74e101Schristos #define		LLDP_MAU_TYPE_UNKNOWN		0
2540f74e101Schristos #define		LLDP_MAU_TYPE_AUI		1
2550f74e101Schristos #define		LLDP_MAU_TYPE_10BASE_5		2
2560f74e101Schristos #define		LLDP_MAU_TYPE_FOIRL		3
2570f74e101Schristos #define		LLDP_MAU_TYPE_10BASE_2		4
2580f74e101Schristos #define		LLDP_MAU_TYPE_10BASE_T		5
2590f74e101Schristos #define		LLDP_MAU_TYPE_10BASE_FP		6
2600f74e101Schristos #define		LLDP_MAU_TYPE_10BASE_FB		7
2610f74e101Schristos #define		LLDP_MAU_TYPE_10BASE_FL		8
2620f74e101Schristos #define		LLDP_MAU_TYPE_10BROAD36		9
2630f74e101Schristos #define		LLDP_MAU_TYPE_10BASE_T_HD	10
2640f74e101Schristos #define		LLDP_MAU_TYPE_10BASE_T_FD	11
2650f74e101Schristos #define		LLDP_MAU_TYPE_10BASE_FL_HD	12
2660f74e101Schristos #define		LLDP_MAU_TYPE_10BASE_FL_FD	13
2670f74e101Schristos #define		LLDP_MAU_TYPE_100BASE_T4	14
2680f74e101Schristos #define		LLDP_MAU_TYPE_100BASE_TX_HD	15
2690f74e101Schristos #define		LLDP_MAU_TYPE_100BASE_TX_FD	16
2700f74e101Schristos #define		LLDP_MAU_TYPE_100BASE_FX_HD	17
2710f74e101Schristos #define		LLDP_MAU_TYPE_100BASE_FX_FD	18
2720f74e101Schristos #define		LLDP_MAU_TYPE_100BASE_T2_HD	19
2730f74e101Schristos #define		LLDP_MAU_TYPE_100BASE_T2_FD	20
2740f74e101Schristos #define		LLDP_MAU_TYPE_1000BASE_X_HD	21
2750f74e101Schristos #define		LLDP_MAU_TYPE_1000BASE_X_FD	22
2760f74e101Schristos #define		LLDP_MAU_TYPE_1000BASE_LX_HD	23
2770f74e101Schristos #define		LLDP_MAU_TYPE_1000BASE_LX_FD	24
2780f74e101Schristos #define		LLDP_MAU_TYPE_1000BASE_SX_HD	25
2790f74e101Schristos #define		LLDP_MAU_TYPE_1000BASE_SX_FD	26
2800f74e101Schristos #define		LLDP_MAU_TYPE_1000BASE_CX_HD	27
2810f74e101Schristos #define		LLDP_MAU_TYPE_1000BASE_CX_FD	28
2820f74e101Schristos #define		LLDP_MAU_TYPE_1000BASE_T_HD	29
2830f74e101Schristos #define		LLDP_MAU_TYPE_1000BASE_T_FD	30
2840f74e101Schristos #define		LLDP_MAU_TYPE_10GBASE_X		31
2850f74e101Schristos #define		LLDP_MAU_TYPE_10GBASE_LX4	32
2860f74e101Schristos #define		LLDP_MAU_TYPE_10GBASE_R		33
2870f74e101Schristos #define		LLDP_MAU_TYPE_10GBASE_ER	34
2880f74e101Schristos #define		LLDP_MAU_TYPE_10GBASE_LR	35
2890f74e101Schristos #define		LLDP_MAU_TYPE_10GBASE_SR	36
2900f74e101Schristos #define		LLDP_MAU_TYPE_10GBASE_W		37
2910f74e101Schristos #define		LLDP_MAU_TYPE_10GBASE_EW	38
2920f74e101Schristos #define		LLDP_MAU_TYPE_10GBASE_LW	39
2930f74e101Schristos #define		LLDP_MAU_TYPE_10GBASE_SW	40
2940f74e101Schristos 
2950f74e101Schristos static const struct tok lldp_mau_types_values[] = {
2960f74e101Schristos     { LLDP_MAU_TYPE_UNKNOWN,            "Unknown"},
2970f74e101Schristos     { LLDP_MAU_TYPE_AUI,                "AUI"},
2980f74e101Schristos     { LLDP_MAU_TYPE_10BASE_5,           "10BASE_5"},
2990f74e101Schristos     { LLDP_MAU_TYPE_FOIRL,              "FOIRL"},
3000f74e101Schristos     { LLDP_MAU_TYPE_10BASE_2,           "10BASE2"},
3010f74e101Schristos     { LLDP_MAU_TYPE_10BASE_T,           "10BASET duplex mode unknown"},
3020f74e101Schristos     { LLDP_MAU_TYPE_10BASE_FP,          "10BASEFP"},
3030f74e101Schristos     { LLDP_MAU_TYPE_10BASE_FB,          "10BASEFB"},
3040f74e101Schristos     { LLDP_MAU_TYPE_10BASE_FL,          "10BASEFL duplex mode unknown"},
3050f74e101Schristos     { LLDP_MAU_TYPE_10BROAD36,          "10BROAD36"},
3060f74e101Schristos     { LLDP_MAU_TYPE_10BASE_T_HD,        "10BASET hdx"},
3070f74e101Schristos     { LLDP_MAU_TYPE_10BASE_T_FD,        "10BASET fdx"},
3080f74e101Schristos     { LLDP_MAU_TYPE_10BASE_FL_HD,       "10BASEFL hdx"},
3090f74e101Schristos     { LLDP_MAU_TYPE_10BASE_FL_FD,       "10BASEFL fdx"},
3100f74e101Schristos     { LLDP_MAU_TYPE_100BASE_T4,         "100BASET4"},
3110f74e101Schristos     { LLDP_MAU_TYPE_100BASE_TX_HD,      "100BASETX hdx"},
3120f74e101Schristos     { LLDP_MAU_TYPE_100BASE_TX_FD,      "100BASETX fdx"},
3130f74e101Schristos     { LLDP_MAU_TYPE_100BASE_FX_HD,      "100BASEFX hdx"},
3140f74e101Schristos     { LLDP_MAU_TYPE_100BASE_FX_FD,      "100BASEFX fdx"},
3150f74e101Schristos     { LLDP_MAU_TYPE_100BASE_T2_HD,      "100BASET2 hdx"},
3160f74e101Schristos     { LLDP_MAU_TYPE_100BASE_T2_FD,      "100BASET2 fdx"},
3170f74e101Schristos     { LLDP_MAU_TYPE_1000BASE_X_HD,      "1000BASEX hdx"},
3180f74e101Schristos     { LLDP_MAU_TYPE_1000BASE_X_FD,      "1000BASEX fdx"},
3190f74e101Schristos     { LLDP_MAU_TYPE_1000BASE_LX_HD,     "1000BASELX hdx"},
3200f74e101Schristos     { LLDP_MAU_TYPE_1000BASE_LX_FD,     "1000BASELX fdx"},
3210f74e101Schristos     { LLDP_MAU_TYPE_1000BASE_SX_HD,     "1000BASESX hdx"},
3220f74e101Schristos     { LLDP_MAU_TYPE_1000BASE_SX_FD,     "1000BASESX fdx"},
3230f74e101Schristos     { LLDP_MAU_TYPE_1000BASE_CX_HD,     "1000BASECX hdx"},
3240f74e101Schristos     { LLDP_MAU_TYPE_1000BASE_CX_FD,     "1000BASECX fdx"},
3250f74e101Schristos     { LLDP_MAU_TYPE_1000BASE_T_HD,      "1000BASET hdx"},
3260f74e101Schristos     { LLDP_MAU_TYPE_1000BASE_T_FD,      "1000BASET fdx"},
3270f74e101Schristos     { LLDP_MAU_TYPE_10GBASE_X,          "10GBASEX"},
3280f74e101Schristos     { LLDP_MAU_TYPE_10GBASE_LX4,        "10GBASELX4"},
3290f74e101Schristos     { LLDP_MAU_TYPE_10GBASE_R,          "10GBASER"},
3300f74e101Schristos     { LLDP_MAU_TYPE_10GBASE_ER,         "10GBASEER"},
3310f74e101Schristos     { LLDP_MAU_TYPE_10GBASE_LR,         "10GBASELR"},
3320f74e101Schristos     { LLDP_MAU_TYPE_10GBASE_SR,         "10GBASESR"},
3330f74e101Schristos     { LLDP_MAU_TYPE_10GBASE_W,          "10GBASEW"},
3340f74e101Schristos     { LLDP_MAU_TYPE_10GBASE_EW,         "10GBASEEW"},
3350f74e101Schristos     { LLDP_MAU_TYPE_10GBASE_LW,         "10GBASELW"},
3360f74e101Schristos     { LLDP_MAU_TYPE_10GBASE_SW,         "10GBASESW"},
3370f74e101Schristos     { 0, NULL}
3380f74e101Schristos };
3390f74e101Schristos 
3400f74e101Schristos #define LLDP_8023_AUTONEGOTIATION_SUPPORT       (1 <<  0)
3410f74e101Schristos #define LLDP_8023_AUTONEGOTIATION_STATUS        (1 <<  1)
3420f74e101Schristos 
3430f74e101Schristos static const struct tok lldp_8023_autonegotiation_values[] = {
3440f74e101Schristos     { LLDP_8023_AUTONEGOTIATION_SUPPORT, "supported"},
3450f74e101Schristos     { LLDP_8023_AUTONEGOTIATION_STATUS, "enabled"},
3460f74e101Schristos     { 0, NULL}
3470f74e101Schristos };
3480f74e101Schristos 
3490f74e101Schristos #define LLDP_TIA_CAPABILITY_MED                         (1 <<  0)
3500f74e101Schristos #define LLDP_TIA_CAPABILITY_NETWORK_POLICY              (1 <<  1)
3510f74e101Schristos #define LLDP_TIA_CAPABILITY_LOCATION_IDENTIFICATION     (1 <<  2)
3520f74e101Schristos #define LLDP_TIA_CAPABILITY_EXTENDED_POWER_MDI_PSE      (1 <<  3)
3530f74e101Schristos #define LLDP_TIA_CAPABILITY_EXTENDED_POWER_MDI_PD       (1 <<  4)
3540f74e101Schristos #define LLDP_TIA_CAPABILITY_INVENTORY                   (1 <<  5)
3550f74e101Schristos 
3560f74e101Schristos static const struct tok lldp_tia_capabilities_values[] = {
3570f74e101Schristos     { LLDP_TIA_CAPABILITY_MED, "LLDP-MED capabilities"},
3580f74e101Schristos     { LLDP_TIA_CAPABILITY_NETWORK_POLICY, "network policy"},
3590f74e101Schristos     { LLDP_TIA_CAPABILITY_LOCATION_IDENTIFICATION, "location identification"},
3600f74e101Schristos     { LLDP_TIA_CAPABILITY_EXTENDED_POWER_MDI_PSE, "extended power via MDI-PSE"},
3610f74e101Schristos     { LLDP_TIA_CAPABILITY_EXTENDED_POWER_MDI_PD, "extended power via MDI-PD"},
3620f74e101Schristos     { LLDP_TIA_CAPABILITY_INVENTORY, "Inventory"},
3630f74e101Schristos     { 0, NULL}
3640f74e101Schristos };
3650f74e101Schristos 
3660f74e101Schristos #define LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_1           1
3670f74e101Schristos #define LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_2           2
3680f74e101Schristos #define LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_3           3
3690f74e101Schristos #define LLDP_TIA_DEVICE_TYPE_NETWORK_CONNECTIVITY       4
3700f74e101Schristos 
3710f74e101Schristos static const struct tok lldp_tia_device_type_values[] = {
3720f74e101Schristos     { LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_1, "endpoint class 1"},
3730f74e101Schristos     { LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_2, "endpoint class 2"},
3740f74e101Schristos     { LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_3, "endpoint class 3"},
3750f74e101Schristos     { LLDP_TIA_DEVICE_TYPE_NETWORK_CONNECTIVITY, "network connectivity"},
3760f74e101Schristos     { 0, NULL}
3770f74e101Schristos };
3780f74e101Schristos 
3790f74e101Schristos #define LLDP_TIA_APPLICATION_TYPE_VOICE                 1
3800f74e101Schristos #define LLDP_TIA_APPLICATION_TYPE_VOICE_SIGNALING       2
3810f74e101Schristos #define LLDP_TIA_APPLICATION_TYPE_GUEST_VOICE           3
3820f74e101Schristos #define LLDP_TIA_APPLICATION_TYPE_GUEST_VOICE_SIGNALING 4
3830f74e101Schristos #define LLDP_TIA_APPLICATION_TYPE_SOFTPHONE_VOICE       5
3840f74e101Schristos #define LLDP_TIA_APPLICATION_TYPE_VIDEO_CONFERENCING    6
3850f74e101Schristos #define LLDP_TIA_APPLICATION_TYPE_STREAMING_VIDEO       7
3860f74e101Schristos #define LLDP_TIA_APPLICATION_TYPE_VIDEO_SIGNALING       8
3870f74e101Schristos 
3880f74e101Schristos static const struct tok lldp_tia_application_type_values[] = {
3890f74e101Schristos     { LLDP_TIA_APPLICATION_TYPE_VOICE, "voice"},
3900f74e101Schristos     { LLDP_TIA_APPLICATION_TYPE_VOICE_SIGNALING, "voice signaling"},
3910f74e101Schristos     { LLDP_TIA_APPLICATION_TYPE_GUEST_VOICE, "guest voice"},
3920f74e101Schristos     { LLDP_TIA_APPLICATION_TYPE_GUEST_VOICE_SIGNALING, "guest voice signaling"},
3930f74e101Schristos     { LLDP_TIA_APPLICATION_TYPE_SOFTPHONE_VOICE, "softphone voice"},
3940f74e101Schristos     { LLDP_TIA_APPLICATION_TYPE_VIDEO_CONFERENCING, "video conferencing"},
3950f74e101Schristos     { LLDP_TIA_APPLICATION_TYPE_STREAMING_VIDEO, "streaming video"},
3960f74e101Schristos     { LLDP_TIA_APPLICATION_TYPE_VIDEO_SIGNALING, "video signaling"},
3970f74e101Schristos     { 0, NULL}
3980f74e101Schristos };
3990f74e101Schristos 
4000e9868baSchristos #define LLDP_TIA_NETWORK_POLICY_X_BIT           (1 << 5)
4010f74e101Schristos #define LLDP_TIA_NETWORK_POLICY_T_BIT           (1 << 6)
4020e9868baSchristos #define LLDP_TIA_NETWORK_POLICY_U_BIT           (1 << 7)
4030f74e101Schristos 
4040f74e101Schristos static const struct tok lldp_tia_network_policy_bits_values[] = {
4050f74e101Schristos     { LLDP_TIA_NETWORK_POLICY_U_BIT, "Unknown"},
4060f74e101Schristos     { LLDP_TIA_NETWORK_POLICY_T_BIT, "Tagged"},
4070f74e101Schristos     { LLDP_TIA_NETWORK_POLICY_X_BIT, "reserved"},
4080f74e101Schristos     { 0, NULL}
4090f74e101Schristos };
4100f74e101Schristos 
4110f74e101Schristos #define LLDP_EXTRACT_NETWORK_POLICY_VLAN(x)           (((x)&0x1ffe)>>1)
4120f74e101Schristos #define LLDP_EXTRACT_NETWORK_POLICY_L2_PRIORITY(x)    (((x)&0x01ff)>>6)
4130f74e101Schristos #define LLDP_EXTRACT_NETWORK_POLICY_DSCP(x)           ((x)&0x003f)
4140f74e101Schristos 
4150f74e101Schristos #define LLDP_TIA_LOCATION_DATA_FORMAT_COORDINATE_BASED  1
4160f74e101Schristos #define LLDP_TIA_LOCATION_DATA_FORMAT_CIVIC_ADDRESS     2
4170f74e101Schristos #define LLDP_TIA_LOCATION_DATA_FORMAT_ECS_ELIN          3
4180f74e101Schristos 
4190f74e101Schristos static const struct tok lldp_tia_location_data_format_values[] = {
4200f74e101Schristos     { LLDP_TIA_LOCATION_DATA_FORMAT_COORDINATE_BASED, "coordinate-based LCI"},
4210f74e101Schristos     { LLDP_TIA_LOCATION_DATA_FORMAT_CIVIC_ADDRESS, "civic address LCI"},
4220f74e101Schristos     { LLDP_TIA_LOCATION_DATA_FORMAT_ECS_ELIN, "ECS ELIN"},
4230f74e101Schristos     { 0, NULL}
4240f74e101Schristos };
4250f74e101Schristos 
4260f74e101Schristos #define LLDP_TIA_LOCATION_DATUM_WGS_84          1
4270f74e101Schristos #define LLDP_TIA_LOCATION_DATUM_NAD_83_NAVD_88  2
4280f74e101Schristos #define LLDP_TIA_LOCATION_DATUM_NAD_83_MLLW     3
4290f74e101Schristos 
4300f74e101Schristos static const struct tok lldp_tia_location_datum_type_values[] = {
4310f74e101Schristos     { LLDP_TIA_LOCATION_DATUM_WGS_84, "World Geodesic System 1984"},
4320f74e101Schristos     { LLDP_TIA_LOCATION_DATUM_NAD_83_NAVD_88, "North American Datum 1983 (NAVD88)"},
4330f74e101Schristos     { LLDP_TIA_LOCATION_DATUM_NAD_83_MLLW, "North American Datum 1983 (MLLW)"},
4340f74e101Schristos     { 0, NULL}
4350f74e101Schristos };
4360f74e101Schristos 
4370f74e101Schristos #define LLDP_TIA_POWER_SOURCE_PSE               1
4380f74e101Schristos #define LLDP_TIA_POWER_SOURCE_LOCAL             2
4390f74e101Schristos #define LLDP_TIA_POWER_SOURCE_PSE_AND_LOCAL     3
4400f74e101Schristos 
4410f74e101Schristos static const struct tok lldp_tia_power_source_values[] = {
4420f74e101Schristos     { LLDP_TIA_POWER_SOURCE_PSE, "PSE - primary power source"},
4430f74e101Schristos     { LLDP_TIA_POWER_SOURCE_LOCAL, "local - backup power source"},
4440f74e101Schristos     { LLDP_TIA_POWER_SOURCE_PSE_AND_LOCAL, "PSE+local - reserved"},
4450f74e101Schristos     { 0, NULL}
4460f74e101Schristos };
4470f74e101Schristos 
4480f74e101Schristos #define LLDP_TIA_POWER_PRIORITY_CRITICAL        1
4490f74e101Schristos #define LLDP_TIA_POWER_PRIORITY_HIGH            2
4500f74e101Schristos #define LLDP_TIA_POWER_PRIORITY_LOW             3
4510f74e101Schristos 
4520f74e101Schristos static const struct tok lldp_tia_power_priority_values[] = {
4530f74e101Schristos     { LLDP_TIA_POWER_PRIORITY_CRITICAL, "critical"},
4540f74e101Schristos     { LLDP_TIA_POWER_PRIORITY_HIGH, "high"},
4550f74e101Schristos     { LLDP_TIA_POWER_PRIORITY_LOW, "low"},
4560f74e101Schristos     { 0, NULL}
4570f74e101Schristos };
4580f74e101Schristos 
4590f74e101Schristos #define LLDP_TIA_POWER_VAL_MAX               1024
4600f74e101Schristos 
4610f74e101Schristos static const struct tok lldp_tia_inventory_values[] = {
4620f74e101Schristos     { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV, "Hardware revision" },
4630f74e101Schristos     { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV, "Firmware revision" },
4640f74e101Schristos     { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV, "Software revision" },
4650f74e101Schristos     { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER, "Serial number" },
4660f74e101Schristos     { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME, "Manufacturer name" },
4670f74e101Schristos     { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME, "Model name" },
4680f74e101Schristos     { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID, "Asset ID" },
4690f74e101Schristos     { 0, NULL}
4700f74e101Schristos };
4710f74e101Schristos 
4720f74e101Schristos /*
4730f74e101Schristos  * From RFC 3636 - ifMauAutoNegCapAdvertisedBits
4740f74e101Schristos  */
4750f74e101Schristos #define	 LLDP_MAU_PMD_OTHER			(1 <<  15)
4760f74e101Schristos #define	 LLDP_MAU_PMD_10BASE_T			(1 <<  14)
4770f74e101Schristos #define	 LLDP_MAU_PMD_10BASE_T_FD		(1 <<  13)
4780f74e101Schristos #define	 LLDP_MAU_PMD_100BASE_T4		(1 <<  12)
4790f74e101Schristos #define	 LLDP_MAU_PMD_100BASE_TX		(1 <<  11)
4800f74e101Schristos #define	 LLDP_MAU_PMD_100BASE_TX_FD		(1 <<  10)
4810f74e101Schristos #define	 LLDP_MAU_PMD_100BASE_T2		(1 <<  9)
4820f74e101Schristos #define	 LLDP_MAU_PMD_100BASE_T2_FD		(1 <<  8)
4830f74e101Schristos #define	 LLDP_MAU_PMD_FDXPAUSE			(1 <<  7)
4840f74e101Schristos #define	 LLDP_MAU_PMD_FDXAPAUSE			(1 <<  6)
4850f74e101Schristos #define	 LLDP_MAU_PMD_FDXSPAUSE			(1 <<  5)
4860f74e101Schristos #define	 LLDP_MAU_PMD_FDXBPAUSE			(1 <<  4)
4870f74e101Schristos #define	 LLDP_MAU_PMD_1000BASE_X		(1 <<  3)
4880f74e101Schristos #define	 LLDP_MAU_PMD_1000BASE_X_FD		(1 <<  2)
4890f74e101Schristos #define	 LLDP_MAU_PMD_1000BASE_T		(1 <<  1)
4900f74e101Schristos #define	 LLDP_MAU_PMD_1000BASE_T_FD		(1 <<  0)
4910f74e101Schristos 
4920f74e101Schristos static const struct tok lldp_pmd_capability_values[] = {
4930f74e101Schristos     { LLDP_MAU_PMD_10BASE_T,		"10BASE-T hdx"},
4940f74e101Schristos     { LLDP_MAU_PMD_10BASE_T_FD,	        "10BASE-T fdx"},
4950f74e101Schristos     { LLDP_MAU_PMD_100BASE_T4,		"100BASE-T4"},
4960f74e101Schristos     { LLDP_MAU_PMD_100BASE_TX,		"100BASE-TX hdx"},
4970f74e101Schristos     { LLDP_MAU_PMD_100BASE_TX_FD,	"100BASE-TX fdx"},
4980f74e101Schristos     { LLDP_MAU_PMD_100BASE_T2,		"100BASE-T2 hdx"},
4990f74e101Schristos     { LLDP_MAU_PMD_100BASE_T2_FD,	"100BASE-T2 fdx"},
5000f74e101Schristos     { LLDP_MAU_PMD_FDXPAUSE,		"Pause for fdx links"},
5010f74e101Schristos     { LLDP_MAU_PMD_FDXAPAUSE,		"Asym PAUSE for fdx"},
5020f74e101Schristos     { LLDP_MAU_PMD_FDXSPAUSE,		"Sym PAUSE for fdx"},
5030f74e101Schristos     { LLDP_MAU_PMD_FDXBPAUSE,		"Asym and Sym PAUSE for fdx"},
5040f74e101Schristos     { LLDP_MAU_PMD_1000BASE_X,		"1000BASE-{X LX SX CX} hdx"},
5050f74e101Schristos     { LLDP_MAU_PMD_1000BASE_X_FD,	"1000BASE-{X LX SX CX} fdx"},
5060f74e101Schristos     { LLDP_MAU_PMD_1000BASE_T,		"1000BASE-T hdx"},
5070f74e101Schristos     { LLDP_MAU_PMD_1000BASE_T_FD,	"1000BASE-T fdx"},
5080f74e101Schristos     { 0, NULL}
5090f74e101Schristos };
5100f74e101Schristos 
5110f74e101Schristos #define	LLDP_MDI_PORT_CLASS			(1 <<  0)
5120f74e101Schristos #define	LLDP_MDI_POWER_SUPPORT			(1 <<  1)
5130f74e101Schristos #define LLDP_MDI_POWER_STATE			(1 <<  2)
5140f74e101Schristos #define LLDP_MDI_PAIR_CONTROL_ABILITY		(1 <<  3)
5150f74e101Schristos 
5160f74e101Schristos static const struct tok lldp_mdi_values[] = {
5170f74e101Schristos     { LLDP_MDI_PORT_CLASS,		"PSE"},
5180f74e101Schristos     { LLDP_MDI_POWER_SUPPORT,		"supported"},
5190f74e101Schristos     { LLDP_MDI_POWER_STATE,		"enabled"},
5200f74e101Schristos     { LLDP_MDI_PAIR_CONTROL_ABILITY,	"can be controlled"},
5210f74e101Schristos     { 0, NULL}
5220f74e101Schristos };
5230f74e101Schristos 
5240f74e101Schristos #define LLDP_MDI_PSE_PORT_POWER_PAIRS_SIGNAL	1
5250f74e101Schristos #define LLDP_MDI_PSE_PORT_POWER_PAIRS_SPARE	2
5260f74e101Schristos 
5270f74e101Schristos static const struct tok lldp_mdi_power_pairs_values[] = {
5280f74e101Schristos     { LLDP_MDI_PSE_PORT_POWER_PAIRS_SIGNAL,	"signal"},
5290f74e101Schristos     { LLDP_MDI_PSE_PORT_POWER_PAIRS_SPARE,	"spare"},
5300f74e101Schristos     { 0, NULL}
5310f74e101Schristos };
5320f74e101Schristos 
5330f74e101Schristos #define LLDP_MDI_POWER_CLASS0		1
5340f74e101Schristos #define LLDP_MDI_POWER_CLASS1		2
5350f74e101Schristos #define LLDP_MDI_POWER_CLASS2		3
5360f74e101Schristos #define LLDP_MDI_POWER_CLASS3		4
5370f74e101Schristos #define LLDP_MDI_POWER_CLASS4		5
5380f74e101Schristos 
5390f74e101Schristos static const struct tok lldp_mdi_power_class_values[] = {
5400f74e101Schristos     { LLDP_MDI_POWER_CLASS0,     "class0"},
5410f74e101Schristos     { LLDP_MDI_POWER_CLASS1,     "class1"},
5420f74e101Schristos     { LLDP_MDI_POWER_CLASS2,     "class2"},
5430f74e101Schristos     { LLDP_MDI_POWER_CLASS3,     "class3"},
5440f74e101Schristos     { LLDP_MDI_POWER_CLASS4,     "class4"},
5450f74e101Schristos     { 0, NULL}
5460f74e101Schristos };
5470f74e101Schristos 
548c74ad251Schristos #define LLDP_AGGREGATION_CAPABILITY     (1 <<  0)
5490f74e101Schristos #define LLDP_AGGREGATION_STATUS         (1 <<  1)
5500f74e101Schristos 
5510f74e101Schristos static const struct tok lldp_aggregation_values[] = {
552c74ad251Schristos     { LLDP_AGGREGATION_CAPABILITY, "supported"},
5530f74e101Schristos     { LLDP_AGGREGATION_STATUS, "enabled"},
5540f74e101Schristos     { 0, NULL}
5550f74e101Schristos };
5560f74e101Schristos 
5570f74e101Schristos /*
5580e9868baSchristos  * DCBX protocol subtypes.
5590e9868baSchristos  */
5600e9868baSchristos #define LLDP_DCBX_SUBTYPE_1                1
5610e9868baSchristos #define LLDP_DCBX_SUBTYPE_2                2
5620e9868baSchristos 
5630e9868baSchristos static const struct tok lldp_dcbx_subtype_values[] = {
5640e9868baSchristos     { LLDP_DCBX_SUBTYPE_1, "DCB Capability Exchange Protocol Rev 1" },
5650e9868baSchristos     { LLDP_DCBX_SUBTYPE_2, "DCB Capability Exchange Protocol Rev 1.01" },
5660e9868baSchristos     { 0, NULL}
5670e9868baSchristos };
5680e9868baSchristos 
5690e9868baSchristos #define LLDP_DCBX_CONTROL_TLV                1
5700e9868baSchristos #define LLDP_DCBX_PRIORITY_GROUPS_TLV        2
5710e9868baSchristos #define LLDP_DCBX_PRIORITY_FLOW_CONTROL_TLV  3
5720e9868baSchristos #define LLDP_DCBX_APPLICATION_TLV            4
5730e9868baSchristos 
5740e9868baSchristos /*
5750f74e101Schristos  * Interface numbering subtypes.
5760f74e101Schristos  */
5770f74e101Schristos #define LLDP_INTF_NUMB_IFX_SUBTYPE         2
5780f74e101Schristos #define LLDP_INTF_NUMB_SYSPORT_SUBTYPE     3
5790f74e101Schristos 
5800f74e101Schristos static const struct tok lldp_intf_numb_subtype_values[] = {
5810f74e101Schristos     { LLDP_INTF_NUMB_IFX_SUBTYPE, "Interface Index" },
5820f74e101Schristos     { LLDP_INTF_NUMB_SYSPORT_SUBTYPE, "System Port Number" },
5830f74e101Schristos     { 0, NULL}
5840f74e101Schristos };
5850f74e101Schristos 
5860f74e101Schristos #define LLDP_INTF_NUM_LEN                  5
5870f74e101Schristos 
588870189d2Schristos #define LLDP_EVB_MODE_NOT_SUPPORTED	0
589870189d2Schristos #define LLDP_EVB_MODE_EVB_BRIDGE	1
590870189d2Schristos #define LLDP_EVB_MODE_EVB_STATION	2
591870189d2Schristos #define LLDP_EVB_MODE_RESERVED		3
592870189d2Schristos 
593870189d2Schristos static const struct tok lldp_evb_mode_values[]={
594870189d2Schristos     { LLDP_EVB_MODE_NOT_SUPPORTED, "Not Supported"},
595870189d2Schristos     { LLDP_EVB_MODE_EVB_BRIDGE, "EVB Bridge"},
596c74ad251Schristos     { LLDP_EVB_MODE_EVB_STATION, "EVB Station"},
597870189d2Schristos     { LLDP_EVB_MODE_RESERVED, "Reserved for future Standardization"},
59872c96ff3Schristos     { 0, NULL},
599870189d2Schristos };
600870189d2Schristos 
601870189d2Schristos #define NO_OF_BITS 8
602870189d2Schristos #define LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION_LENGTH  6
603870189d2Schristos #define LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION_LENGTH       25
604870189d2Schristos #define LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION_LENGTH      25
605870189d2Schristos #define LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION_LENGTH        6
606870189d2Schristos #define LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY_MIN_LENGTH 5
607870189d2Schristos #define LLDP_PRIVATE_8021_SUBTYPE_EVB_LENGTH                      9
608870189d2Schristos #define LLDP_PRIVATE_8021_SUBTYPE_CDCP_MIN_LENGTH                 8
609870189d2Schristos 
610dc860a36Sspz #define LLDP_IANA_SUBTYPE_MUDURL 1
611dc860a36Sspz 
612dc860a36Sspz static const struct tok lldp_iana_subtype_values[] =   {
613dc860a36Sspz     { LLDP_IANA_SUBTYPE_MUDURL, "MUD-URL" },
614dc860a36Sspz     { 0, NULL }
615dc860a36Sspz };
616dc860a36Sspz 
617dc860a36Sspz 
618b3a00663Schristos static void
619b3a00663Schristos print_ets_priority_assignment_table(netdissect_options *ndo,
620b3a00663Schristos                                     const u_char *ptr)
621870189d2Schristos {
622c74ad251Schristos     ND_PRINT("\n\t    Priority Assignment Table");
623c74ad251Schristos     ND_PRINT("\n\t     Priority : 0   1   2   3   4   5   6   7");
624c74ad251Schristos     ND_PRINT("\n\t     Value    : %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d",
625c74ad251Schristos               GET_U_1(ptr) >> 4, GET_U_1(ptr) & 0x0f,
626c74ad251Schristos               GET_U_1(ptr + 1) >> 4, GET_U_1(ptr + 1) & 0x0f,
627c74ad251Schristos               GET_U_1(ptr + 2) >> 4, GET_U_1(ptr + 2) & 0x0f,
628c74ad251Schristos               GET_U_1(ptr + 3) >> 4, GET_U_1(ptr + 3) & 0x0f);
629870189d2Schristos }
630870189d2Schristos 
631b3a00663Schristos static void
632b3a00663Schristos print_tc_bandwidth_table(netdissect_options *ndo,
633b3a00663Schristos                          const u_char *ptr)
634870189d2Schristos {
635c74ad251Schristos     ND_PRINT("\n\t    TC Bandwidth Table");
636c74ad251Schristos     ND_PRINT("\n\t     TC%%   : 0   1   2   3   4   5   6   7");
637c74ad251Schristos     ND_PRINT("\n\t     Value : %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d",
638c74ad251Schristos               GET_U_1(ptr), GET_U_1(ptr + 1), GET_U_1(ptr + 2),
639c74ad251Schristos               GET_U_1(ptr + 3), GET_U_1(ptr + 4), GET_U_1(ptr + 5),
640c74ad251Schristos               GET_U_1(ptr + 6), GET_U_1(ptr + 7));
641870189d2Schristos }
642870189d2Schristos 
643b3a00663Schristos static void
644b3a00663Schristos print_tsa_assignment_table(netdissect_options *ndo,
645b3a00663Schristos                            const u_char *ptr)
646870189d2Schristos {
647c74ad251Schristos     ND_PRINT("\n\t    TSA Assignment Table");
648c74ad251Schristos     ND_PRINT("\n\t     Traffic Class: 0   1   2   3   4   5   6   7");
649c74ad251Schristos     ND_PRINT("\n\t     Value        : %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d",
650c74ad251Schristos               GET_U_1(ptr), GET_U_1(ptr + 1), GET_U_1(ptr + 2),
651c74ad251Schristos               GET_U_1(ptr + 3), GET_U_1(ptr + 4), GET_U_1(ptr + 5),
652c74ad251Schristos               GET_U_1(ptr + 6), GET_U_1(ptr + 7));
653870189d2Schristos }
654870189d2Schristos 
6550f74e101Schristos /*
6560e9868baSchristos  * Print IEEE 802.1 private extensions. (802.1AB annex E)
6570f74e101Schristos  */
6580f74e101Schristos static int
659b3a00663Schristos lldp_private_8021_print(netdissect_options *ndo,
660b3a00663Schristos                         const u_char *tptr, u_int tlv_len)
6610f74e101Schristos {
662c74ad251Schristos     int hexdump = FALSE;
663c74ad251Schristos     u_int subtype;
6640e9868baSchristos     u_int sublen;
665870189d2Schristos     u_int tval;
66672c96ff3Schristos     u_int i;
6670f74e101Schristos 
6680e9868baSchristos     if (tlv_len < 4) {
6690e9868baSchristos         return hexdump;
6700e9868baSchristos     }
671c74ad251Schristos     subtype = GET_U_1(tptr + 3);
6720f74e101Schristos 
673c74ad251Schristos     ND_PRINT("\n\t  %s Subtype (%u)",
6740f74e101Schristos            tok2str(lldp_8021_subtype_values, "unknown", subtype),
675c74ad251Schristos            subtype);
6760f74e101Schristos 
6770f74e101Schristos     switch (subtype) {
6780f74e101Schristos     case LLDP_PRIVATE_8021_SUBTYPE_PORT_VLAN_ID:
6790e9868baSchristos         if (tlv_len < 6) {
6800e9868baSchristos             return hexdump;
6810e9868baSchristos         }
682c74ad251Schristos         ND_PRINT("\n\t    port vlan id (PVID): %u",
683c74ad251Schristos                GET_BE_U_2(tptr + 4));
6840f74e101Schristos         break;
6850f74e101Schristos     case LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_VLAN_ID:
6860e9868baSchristos         if (tlv_len < 7) {
6870e9868baSchristos             return hexdump;
6880e9868baSchristos         }
689c74ad251Schristos         ND_PRINT("\n\t    port and protocol vlan id (PPVID): %u, flags [%s] (0x%02x)",
690c74ad251Schristos                GET_BE_U_2(tptr + 5),
691c74ad251Schristos                bittok2str(lldp_8021_port_protocol_id_values, "none", GET_U_1(tptr + 4)),
692c74ad251Schristos                GET_U_1(tptr + 4));
6930f74e101Schristos         break;
6940f74e101Schristos     case LLDP_PRIVATE_8021_SUBTYPE_VLAN_NAME:
6950e9868baSchristos         if (tlv_len < 6) {
6960e9868baSchristos             return hexdump;
6970e9868baSchristos         }
698c74ad251Schristos         ND_PRINT("\n\t    vlan id (VID): %u", GET_BE_U_2(tptr + 4));
6990e9868baSchristos         if (tlv_len < 7) {
7000e9868baSchristos             return hexdump;
7010e9868baSchristos         }
702c74ad251Schristos         sublen = GET_U_1(tptr + 6);
7030e9868baSchristos         if (tlv_len < 7+sublen) {
7040e9868baSchristos             return hexdump;
7050e9868baSchristos         }
706c74ad251Schristos         ND_PRINT("\n\t    vlan name: ");
707c74ad251Schristos         nd_printjnp(ndo, tptr + 7, sublen);
7080f74e101Schristos         break;
7090f74e101Schristos     case LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_IDENTITY:
7100e9868baSchristos         if (tlv_len < 5) {
7110e9868baSchristos             return hexdump;
7120e9868baSchristos         }
713c74ad251Schristos         sublen = GET_U_1(tptr + 4);
7140e9868baSchristos         if (tlv_len < 5+sublen) {
7150e9868baSchristos             return hexdump;
7160e9868baSchristos         }
717c74ad251Schristos         ND_PRINT("\n\t    protocol identity: ");
718c74ad251Schristos         nd_printjnp(ndo, tptr + 5, sublen);
7190f74e101Schristos         break;
720c74ad251Schristos 
721c74ad251Schristos     case LLDP_PRIVATE_8021_SUBTYPE_LINKAGGR:
722c74ad251Schristos         if (tlv_len < 9) {
723c74ad251Schristos             return hexdump;
724c74ad251Schristos         }
725c74ad251Schristos         ND_PRINT("\n\t    aggregation status [%s], aggregation port ID %u",
726c74ad251Schristos                bittok2str(lldp_aggregation_values, "none", GET_U_1((tptr + 4))),
727c74ad251Schristos                GET_BE_U_4(tptr + 5));
728c74ad251Schristos         break;
729c74ad251Schristos 
730870189d2Schristos     case LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION:
731870189d2Schristos         if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION_LENGTH){
732870189d2Schristos 		return hexdump;
733870189d2Schristos         }
734c74ad251Schristos         tval=GET_U_1(tptr + 4);
735c74ad251Schristos         ND_PRINT("\n\t    Pre-Priority CNPV Indicator");
736c74ad251Schristos         ND_PRINT("\n\t     Priority : 0  1  2  3  4  5  6  7");
737c74ad251Schristos         ND_PRINT("\n\t     Value    : ");
738870189d2Schristos         for(i=0;i<NO_OF_BITS;i++)
739c74ad251Schristos             ND_PRINT("%-2d ", (tval >> i) & 0x01);
740c74ad251Schristos         tval=GET_U_1(tptr + 5);
741c74ad251Schristos         ND_PRINT("\n\t    Pre-Priority Ready Indicator");
742c74ad251Schristos         ND_PRINT("\n\t     Priority : 0  1  2  3  4  5  6  7");
743c74ad251Schristos         ND_PRINT("\n\t     Value    : ");
744870189d2Schristos         for(i=0;i<NO_OF_BITS;i++)
745c74ad251Schristos             ND_PRINT("%-2d ", (tval >> i) & 0x01);
746870189d2Schristos         break;
747870189d2Schristos 
748870189d2Schristos     case LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION:
749870189d2Schristos         if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION_LENGTH) {
750870189d2Schristos             return hexdump;
751870189d2Schristos         }
752c74ad251Schristos         tval=GET_U_1(tptr + 4);
753c74ad251Schristos         ND_PRINT("\n\t    Willing:%u, CBS:%u, RES:%u, Max TCs:%u",
754c74ad251Schristos 		tval >> 7, (tval >> 6) & 0x02, (tval >> 3) & 0x07, tval & 0x07);
755870189d2Schristos 
756870189d2Schristos         /*Print Priority Assignment Table*/
757b3a00663Schristos         print_ets_priority_assignment_table(ndo, tptr + 5);
758870189d2Schristos 
759870189d2Schristos         /*Print TC Bandwidth Table*/
760b3a00663Schristos         print_tc_bandwidth_table(ndo, tptr + 9);
761870189d2Schristos 
762870189d2Schristos         /* Print TSA Assignment Table */
763b3a00663Schristos         print_tsa_assignment_table(ndo, tptr + 17);
764870189d2Schristos 
765870189d2Schristos         break;
766870189d2Schristos 
767870189d2Schristos     case LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION:
768870189d2Schristos         if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION_LENGTH) {
769870189d2Schristos 		return hexdump;
770870189d2Schristos         }
771c74ad251Schristos         ND_PRINT("\n\t    RES: %u", GET_U_1(tptr + 4));
772870189d2Schristos         /*Print Priority Assignment Table */
773b3a00663Schristos         print_ets_priority_assignment_table(ndo, tptr + 5);
774870189d2Schristos         /*Print TC Bandwidth Table */
775b3a00663Schristos         print_tc_bandwidth_table(ndo, tptr + 9);
776870189d2Schristos         /* Print TSA Assignment Table */
777b3a00663Schristos         print_tsa_assignment_table(ndo, tptr + 17);
778870189d2Schristos         break;
779870189d2Schristos 
780870189d2Schristos     case LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION:
781870189d2Schristos         if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION_LENGTH) {
782870189d2Schristos             return hexdump;
783870189d2Schristos         }
784c74ad251Schristos         tval=GET_U_1(tptr + 4);
785c74ad251Schristos         ND_PRINT("\n\t    Willing: %u, MBC: %u, RES: %u, PFC cap:%u ",
786c74ad251Schristos 		tval >> 7, (tval >> 6) & 0x01, (tval >> 4) & 0x03, (tval & 0x0f));
787c74ad251Schristos         ND_PRINT("\n\t    PFC Enable");
788c74ad251Schristos         tval=GET_U_1(tptr + 5);
789c74ad251Schristos         ND_PRINT("\n\t     Priority : 0  1  2  3  4  5  6  7");
790c74ad251Schristos         ND_PRINT("\n\t     Value    : ");
791870189d2Schristos         for(i=0;i<NO_OF_BITS;i++)
792c74ad251Schristos             ND_PRINT("%-2d ", (tval >> i) & 0x01);
793870189d2Schristos         break;
794870189d2Schristos 
795870189d2Schristos     case LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY:
796870189d2Schristos         if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY_MIN_LENGTH) {
797870189d2Schristos             return hexdump;
798870189d2Schristos         }
799c74ad251Schristos         ND_PRINT("\n\t    RES: %u", GET_U_1(tptr + 4));
800870189d2Schristos         if(tlv_len<=LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY_MIN_LENGTH){
801870189d2Schristos 		return hexdump;
802870189d2Schristos         }
803870189d2Schristos         /*  Length of Application Priority Table */
804870189d2Schristos         sublen=tlv_len-5;
805870189d2Schristos         if(sublen%3!=0){
806870189d2Schristos 		return hexdump;
807870189d2Schristos         }
808870189d2Schristos         i=0;
809c74ad251Schristos         ND_PRINT("\n\t    Application Priority Table");
810870189d2Schristos         while(i<sublen) {
811c74ad251Schristos 		tval=GET_U_1(tptr + i + 5);
812c74ad251Schristos 		ND_PRINT("\n\t      Priority: %u, RES: %u, Sel: %u, Protocol ID: %u",
81372c96ff3Schristos 			 tval >> 5, (tval >> 3) & 0x03, (tval & 0x07),
814c74ad251Schristos 			 GET_BE_U_2(tptr + i + 6));
815870189d2Schristos 		i=i+3;
816870189d2Schristos         }
817870189d2Schristos         break;
818870189d2Schristos     case LLDP_PRIVATE_8021_SUBTYPE_EVB:
819870189d2Schristos         if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_EVB_LENGTH){
820870189d2Schristos 		return hexdump;
821870189d2Schristos         }
822c74ad251Schristos         ND_PRINT("\n\t    EVB Bridge Status");
823c74ad251Schristos         tval=GET_U_1(tptr + 4);
824c74ad251Schristos         ND_PRINT("\n\t      RES: %u, BGID: %u, RRCAP: %u, RRCTR: %u",
825c74ad251Schristos 		tval >> 3, (tval >> 2) & 0x01, (tval >> 1) & 0x01, tval & 0x01);
826c74ad251Schristos         ND_PRINT("\n\t    EVB Station Status");
827c74ad251Schristos         tval=GET_U_1(tptr + 5);
828c74ad251Schristos         ND_PRINT("\n\t      RES: %u, SGID: %u, RRREQ: %u,RRSTAT: %u",
829c74ad251Schristos 		tval >> 4, (tval >> 3) & 0x01, (tval >> 2) & 0x01, tval & 0x03);
830c74ad251Schristos         tval=GET_U_1(tptr + 6);
831c74ad251Schristos         ND_PRINT("\n\t    R: %u, RTE: %u, ",tval >> 5, tval & 0x1f);
832c74ad251Schristos         tval=GET_U_1(tptr + 7);
833c74ad251Schristos         ND_PRINT("EVB Mode: %s [%u]",
834c74ad251Schristos 		tok2str(lldp_evb_mode_values, "unknown", tval >> 6), tval >> 6);
835c74ad251Schristos         ND_PRINT("\n\t    ROL: %u, RWD: %u, ", (tval >> 5) & 0x01, tval & 0x1f);
836c74ad251Schristos         tval=GET_U_1(tptr + 8);
837c74ad251Schristos         ND_PRINT("RES: %u, ROL: %u, RKA: %u", tval >> 6, (tval >> 5) & 0x01, tval & 0x1f);
838870189d2Schristos         break;
839870189d2Schristos 
840870189d2Schristos     case LLDP_PRIVATE_8021_SUBTYPE_CDCP:
841870189d2Schristos         if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_CDCP_MIN_LENGTH){
842870189d2Schristos 		return hexdump;
843870189d2Schristos         }
844c74ad251Schristos         tval=GET_U_1(tptr + 4);
845c74ad251Schristos         ND_PRINT("\n\t    Role: %u, RES: %u, Scomp: %u ",
846c74ad251Schristos 		tval >> 7, (tval >> 4) & 0x07, (tval >> 3) & 0x01);
847c74ad251Schristos         ND_PRINT("ChnCap: %u", GET_BE_U_2(tptr + 6) & 0x0fff);
848870189d2Schristos         sublen=tlv_len-8;
849870189d2Schristos         if(sublen%3!=0) {
850870189d2Schristos 		return hexdump;
851870189d2Schristos         }
852870189d2Schristos         i=0;
853870189d2Schristos         while(i<sublen) {
854c74ad251Schristos 		tval=GET_BE_U_3(tptr + i + 8);
855c74ad251Schristos 		ND_PRINT("\n\t    SCID: %u, SVID: %u",
856c74ad251Schristos 			tval >> 12, tval & 0x000fff);
857870189d2Schristos 		i=i+3;
858870189d2Schristos         }
859870189d2Schristos         break;
8600f74e101Schristos 
8610f74e101Schristos     default:
8620f74e101Schristos         hexdump = TRUE;
8630f74e101Schristos         break;
8640f74e101Schristos     }
8650f74e101Schristos 
8660f74e101Schristos     return hexdump;
8670f74e101Schristos }
8680f74e101Schristos 
8690f74e101Schristos /*
8700e9868baSchristos  * Print IEEE 802.3 private extensions. (802.3bc)
8710f74e101Schristos  */
8720f74e101Schristos static int
873b3a00663Schristos lldp_private_8023_print(netdissect_options *ndo,
874b3a00663Schristos                         const u_char *tptr, u_int tlv_len)
8750f74e101Schristos {
876c74ad251Schristos     int hexdump = FALSE;
877c74ad251Schristos     u_int subtype;
8780f74e101Schristos 
8790e9868baSchristos     if (tlv_len < 4) {
8800e9868baSchristos         return hexdump;
8810e9868baSchristos     }
882c74ad251Schristos     subtype = GET_U_1(tptr + 3);
8830f74e101Schristos 
884c74ad251Schristos     ND_PRINT("\n\t  %s Subtype (%u)",
8850f74e101Schristos            tok2str(lldp_8023_subtype_values, "unknown", subtype),
886c74ad251Schristos            subtype);
8870f74e101Schristos 
8880f74e101Schristos     switch (subtype) {
8890f74e101Schristos     case LLDP_PRIVATE_8023_SUBTYPE_MACPHY:
8900e9868baSchristos         if (tlv_len < 9) {
8910e9868baSchristos             return hexdump;
8920e9868baSchristos         }
893c74ad251Schristos         ND_PRINT("\n\t    autonegotiation [%s] (0x%02x)",
894c74ad251Schristos                bittok2str(lldp_8023_autonegotiation_values, "none", GET_U_1(tptr + 4)),
895c74ad251Schristos                GET_U_1(tptr + 4));
896c74ad251Schristos         ND_PRINT("\n\t    PMD autoneg capability [%s] (0x%04x)",
897c74ad251Schristos                bittok2str(lldp_pmd_capability_values,"unknown", GET_BE_U_2(tptr + 5)),
898c74ad251Schristos                GET_BE_U_2(tptr + 5));
899c74ad251Schristos         ND_PRINT("\n\t    MAU type %s (0x%04x)",
900c74ad251Schristos                tok2str(lldp_mau_types_values, "unknown", GET_BE_U_2(tptr + 7)),
901c74ad251Schristos                GET_BE_U_2(tptr + 7));
9020f74e101Schristos         break;
9030f74e101Schristos 
9040f74e101Schristos     case LLDP_PRIVATE_8023_SUBTYPE_MDIPOWER:
9050e9868baSchristos         if (tlv_len < 7) {
9060e9868baSchristos             return hexdump;
9070e9868baSchristos         }
908c74ad251Schristos         ND_PRINT("\n\t    MDI power support [%s], power pair %s, power class %s",
909c74ad251Schristos                bittok2str(lldp_mdi_values, "none", GET_U_1((tptr + 4))),
910c74ad251Schristos                tok2str(lldp_mdi_power_pairs_values, "unknown", GET_U_1((tptr + 5))),
911c74ad251Schristos                tok2str(lldp_mdi_power_class_values, "unknown", GET_U_1((tptr + 6))));
9120f74e101Schristos         break;
9130f74e101Schristos 
9140f74e101Schristos     case LLDP_PRIVATE_8023_SUBTYPE_LINKAGGR:
9150e9868baSchristos         if (tlv_len < 9) {
9160e9868baSchristos             return hexdump;
9170e9868baSchristos         }
918c74ad251Schristos         ND_PRINT("\n\t    aggregation status [%s], aggregation port ID %u",
919c74ad251Schristos                bittok2str(lldp_aggregation_values, "none", GET_U_1((tptr + 4))),
920c74ad251Schristos                GET_BE_U_4(tptr + 5));
9210f74e101Schristos         break;
9220f74e101Schristos 
9230f74e101Schristos     case LLDP_PRIVATE_8023_SUBTYPE_MTU:
92472c96ff3Schristos         if (tlv_len < 6) {
92572c96ff3Schristos             return hexdump;
92672c96ff3Schristos         }
927c74ad251Schristos         ND_PRINT("\n\t    MTU size %u", GET_BE_U_2(tptr + 4));
9280f74e101Schristos         break;
9290f74e101Schristos 
9300f74e101Schristos     default:
9310f74e101Schristos         hexdump = TRUE;
9320f74e101Schristos         break;
9330f74e101Schristos     }
9340f74e101Schristos 
9350f74e101Schristos     return hexdump;
9360f74e101Schristos }
9370f74e101Schristos 
9380f74e101Schristos /*
9390f74e101Schristos  * Extract 34bits of latitude/longitude coordinates.
9400f74e101Schristos  */
941b3a00663Schristos static uint64_t
942c74ad251Schristos lldp_extract_latlon(netdissect_options *ndo, const u_char *tptr)
9430f74e101Schristos {
944b3a00663Schristos     uint64_t latlon;
9450f74e101Schristos 
946c74ad251Schristos     latlon = GET_U_1(tptr) & 0x3;
947c74ad251Schristos     latlon = (latlon << 32) | GET_BE_U_4(tptr + 1);
9480f74e101Schristos 
9490f74e101Schristos     return latlon;
9500f74e101Schristos }
9510f74e101Schristos 
952dc860a36Sspz /* objects defined in IANA subtype 00 00 5e
953dc860a36Sspz  * (right now there is only one)
954dc860a36Sspz  */
955dc860a36Sspz 
956dc860a36Sspz 
957dc860a36Sspz static int
958dc860a36Sspz lldp_private_iana_print(netdissect_options *ndo,
959dc860a36Sspz                         const u_char *tptr, u_int tlv_len)
960dc860a36Sspz {
961c74ad251Schristos     int hexdump = FALSE;
962c74ad251Schristos     u_int subtype;
963dc860a36Sspz 
964dc860a36Sspz     if (tlv_len < 8) {
965dc860a36Sspz         return hexdump;
966dc860a36Sspz     }
967c74ad251Schristos     subtype = GET_U_1(tptr + 3);
968dc860a36Sspz 
969c74ad251Schristos     ND_PRINT("\n\t  %s Subtype (%u)",
970dc860a36Sspz            tok2str(lldp_iana_subtype_values, "unknown", subtype),
971c74ad251Schristos            subtype);
972dc860a36Sspz 
973dc860a36Sspz     switch (subtype) {
974dc860a36Sspz     case LLDP_IANA_SUBTYPE_MUDURL:
975c74ad251Schristos         ND_PRINT("\n\t  MUD-URL=");
976c74ad251Schristos         (void)nd_printn(ndo, tptr+4, tlv_len-4, NULL);
977dc860a36Sspz         break;
978dc860a36Sspz     default:
979dc860a36Sspz         hexdump=TRUE;
980dc860a36Sspz     }
981dc860a36Sspz 
982dc860a36Sspz     return hexdump;
983dc860a36Sspz }
984dc860a36Sspz 
985dc860a36Sspz 
986dc860a36Sspz 
9870f74e101Schristos /*
9880f74e101Schristos  * Print private TIA extensions.
9890f74e101Schristos  */
9900f74e101Schristos static int
991b3a00663Schristos lldp_private_tia_print(netdissect_options *ndo,
992b3a00663Schristos                        const u_char *tptr, u_int tlv_len)
9930f74e101Schristos {
994c74ad251Schristos     int hexdump = FALSE;
995c74ad251Schristos     u_int subtype;
996b3a00663Schristos     uint8_t location_format;
997b3a00663Schristos     uint16_t power_val;
9980e9868baSchristos     u_int lci_len;
999b3a00663Schristos     uint8_t ca_type, ca_len;
10000f74e101Schristos 
10010e9868baSchristos     if (tlv_len < 4) {
10020e9868baSchristos         return hexdump;
10030e9868baSchristos     }
1004c74ad251Schristos     subtype = GET_U_1(tptr + 3);
10050f74e101Schristos 
1006c74ad251Schristos     ND_PRINT("\n\t  %s Subtype (%u)",
10070f74e101Schristos            tok2str(lldp_tia_subtype_values, "unknown", subtype),
1008c74ad251Schristos            subtype);
10090f74e101Schristos 
10100f74e101Schristos     switch (subtype) {
10110f74e101Schristos     case LLDP_PRIVATE_TIA_SUBTYPE_CAPABILITIES:
10120e9868baSchristos         if (tlv_len < 7) {
10130e9868baSchristos             return hexdump;
10140e9868baSchristos         }
1015c74ad251Schristos         ND_PRINT("\n\t    Media capabilities [%s] (0x%04x)",
10160f74e101Schristos                bittok2str(lldp_tia_capabilities_values, "none",
1017c74ad251Schristos                           GET_BE_U_2(tptr + 4)), GET_BE_U_2(tptr + 4));
1018c74ad251Schristos         ND_PRINT("\n\t    Device type [%s] (0x%02x)",
1019c74ad251Schristos                tok2str(lldp_tia_device_type_values, "unknown", GET_U_1(tptr + 6)),
1020c74ad251Schristos                GET_U_1(tptr + 6));
10210f74e101Schristos         break;
10220f74e101Schristos 
10230f74e101Schristos     case LLDP_PRIVATE_TIA_SUBTYPE_NETWORK_POLICY:
10240e9868baSchristos         if (tlv_len < 8) {
10250e9868baSchristos             return hexdump;
10260e9868baSchristos         }
1027c74ad251Schristos         ND_PRINT("\n\t    Application type [%s] (0x%02x)",
1028c74ad251Schristos                tok2str(lldp_tia_application_type_values, "none", GET_U_1(tptr + 4)),
1029c74ad251Schristos                GET_U_1(tptr + 4));
1030c74ad251Schristos         ND_PRINT(", Flags [%s]", bittok2str(
1031c74ad251Schristos                    lldp_tia_network_policy_bits_values, "none", GET_U_1((tptr + 5))));
1032c74ad251Schristos         ND_PRINT("\n\t    Vlan id %u",
1033c74ad251Schristos                LLDP_EXTRACT_NETWORK_POLICY_VLAN(GET_BE_U_2(tptr + 5)));
1034c74ad251Schristos         ND_PRINT(", L2 priority %u",
1035c74ad251Schristos                LLDP_EXTRACT_NETWORK_POLICY_L2_PRIORITY(GET_BE_U_2(tptr + 6)));
1036c74ad251Schristos         ND_PRINT(", DSCP value %u",
1037c74ad251Schristos                LLDP_EXTRACT_NETWORK_POLICY_DSCP(GET_BE_U_2(tptr + 6)));
10380f74e101Schristos         break;
10390f74e101Schristos 
10400f74e101Schristos     case LLDP_PRIVATE_TIA_SUBTYPE_LOCAL_ID:
10410e9868baSchristos         if (tlv_len < 5) {
10420e9868baSchristos             return hexdump;
10430e9868baSchristos         }
1044c74ad251Schristos         location_format = GET_U_1(tptr + 4);
1045c74ad251Schristos         ND_PRINT("\n\t    Location data format %s (0x%02x)",
10460f74e101Schristos                tok2str(lldp_tia_location_data_format_values, "unknown", location_format),
1047c74ad251Schristos                location_format);
10480f74e101Schristos 
10490f74e101Schristos         switch (location_format) {
10500f74e101Schristos         case LLDP_TIA_LOCATION_DATA_FORMAT_COORDINATE_BASED:
10510e9868baSchristos             if (tlv_len < 21) {
10520e9868baSchristos                 return hexdump;
10530e9868baSchristos             }
1054c74ad251Schristos             ND_PRINT("\n\t    Latitude resolution %u, latitude value %" PRIu64,
1055c74ad251Schristos                    (GET_U_1(tptr + 5) >> 2),
1056c74ad251Schristos                    lldp_extract_latlon(ndo, tptr + 5));
1057c74ad251Schristos             ND_PRINT("\n\t    Longitude resolution %u, longitude value %" PRIu64,
1058c74ad251Schristos                    (GET_U_1(tptr + 10) >> 2),
1059c74ad251Schristos                    lldp_extract_latlon(ndo, tptr + 10));
1060c74ad251Schristos             ND_PRINT("\n\t    Altitude type %s (%u)",
1061c74ad251Schristos                    tok2str(lldp_tia_location_altitude_type_values, "unknown",GET_U_1(tptr + 15) >> 4),
1062c74ad251Schristos                    (GET_U_1(tptr + 15) >> 4));
1063c74ad251Schristos             ND_PRINT("\n\t    Altitude resolution %u, altitude value 0x%x",
1064c74ad251Schristos                    (GET_BE_U_2(tptr + 15)>>6)&0x3f,
1065c74ad251Schristos                    (GET_BE_U_4(tptr + 16) & 0x3fffffff));
1066c74ad251Schristos             ND_PRINT("\n\t    Datum %s (0x%02x)",
1067c74ad251Schristos                    tok2str(lldp_tia_location_datum_type_values, "unknown", GET_U_1(tptr + 20)),
1068c74ad251Schristos                    GET_U_1(tptr + 20));
10690f74e101Schristos             break;
10700f74e101Schristos 
10710f74e101Schristos         case LLDP_TIA_LOCATION_DATA_FORMAT_CIVIC_ADDRESS:
10720e9868baSchristos             if (tlv_len < 6) {
10730e9868baSchristos                 return hexdump;
10740e9868baSchristos             }
1075c74ad251Schristos             lci_len = GET_U_1(tptr + 5);
10760e9868baSchristos             if (lci_len < 3) {
10770e9868baSchristos                 return hexdump;
10780e9868baSchristos             }
10790e9868baSchristos             if (tlv_len < 7+lci_len) {
10800e9868baSchristos                 return hexdump;
10810e9868baSchristos             }
1082c74ad251Schristos             ND_PRINT("\n\t    LCI length %u, LCI what %s (0x%02x), Country-code ",
10830f74e101Schristos                    lci_len,
1084c74ad251Schristos                    tok2str(lldp_tia_location_lci_what_values, "unknown", GET_U_1(tptr + 6)),
1085c74ad251Schristos                    GET_U_1(tptr + 6));
10860f74e101Schristos 
10870f74e101Schristos             /* Country code */
1088c74ad251Schristos             nd_printjnp(ndo, tptr + 7, 2);
10890f74e101Schristos 
10900f74e101Schristos             lci_len = lci_len-3;
10910f74e101Schristos             tptr = tptr + 9;
10920f74e101Schristos 
10930f74e101Schristos             /* Decode each civic address element */
10940f74e101Schristos             while (lci_len > 0) {
10950e9868baSchristos                 if (lci_len < 2) {
10960e9868baSchristos                     return hexdump;
10970e9868baSchristos                 }
1098c74ad251Schristos 		ca_type = GET_U_1(tptr);
1099c74ad251Schristos                 ca_len = GET_U_1(tptr + 1);
11000f74e101Schristos 
11010f74e101Schristos 		tptr += 2;
11020f74e101Schristos                 lci_len -= 2;
11030f74e101Schristos 
1104*26ba0b50Schristos                 ND_PRINT("\n\t      CA type '%s' (%u), length %u: ",
11050f74e101Schristos                        tok2str(lldp_tia_location_lci_catype_values, "unknown", ca_type),
1106c74ad251Schristos                        ca_type, ca_len);
11070f74e101Schristos 
11080f74e101Schristos 		/* basic sanity check */
11090f74e101Schristos 		if ( ca_type == 0 || ca_len == 0) {
11100f74e101Schristos                     return hexdump;
11110f74e101Schristos 		}
11120e9868baSchristos 		if (lci_len < ca_len) {
11130e9868baSchristos 		    return hexdump;
11140e9868baSchristos 		}
11150f74e101Schristos 
1116c74ad251Schristos                 nd_printjnp(ndo, tptr, ca_len);
11170f74e101Schristos                 tptr += ca_len;
11180f74e101Schristos                 lci_len -= ca_len;
11190f74e101Schristos             }
11200f74e101Schristos             break;
11210f74e101Schristos 
11220f74e101Schristos         case LLDP_TIA_LOCATION_DATA_FORMAT_ECS_ELIN:
1123c74ad251Schristos             ND_PRINT("\n\t    ECS ELIN id ");
1124c74ad251Schristos             nd_printjnp(ndo, tptr + 5, tlv_len - 5);
11250f74e101Schristos             break;
11260f74e101Schristos 
11270f74e101Schristos         default:
1128c74ad251Schristos             ND_PRINT("\n\t    Location ID ");
1129b3a00663Schristos             print_unknown_data(ndo, tptr + 5, "\n\t      ", tlv_len - 5);
11300f74e101Schristos         }
11310f74e101Schristos         break;
11320f74e101Schristos 
11330f74e101Schristos     case LLDP_PRIVATE_TIA_SUBTYPE_EXTENDED_POWER_MDI:
11340e9868baSchristos         if (tlv_len < 7) {
11350e9868baSchristos             return hexdump;
11360e9868baSchristos         }
1137c74ad251Schristos         ND_PRINT("\n\t    Power type [%s]",
1138c74ad251Schristos                (GET_U_1(tptr + 4) & 0xC0 >> 6) ? "PD device" : "PSE device");
1139c74ad251Schristos         ND_PRINT(", Power source [%s]",
1140c74ad251Schristos                tok2str(lldp_tia_power_source_values, "none", (GET_U_1((tptr + 4)) & 0x30) >> 4));
1141c74ad251Schristos         ND_PRINT("\n\t    Power priority [%s] (0x%02x)",
1142c74ad251Schristos                tok2str(lldp_tia_power_priority_values, "none", GET_U_1(tptr + 4) & 0x0f),
1143c74ad251Schristos                GET_U_1(tptr + 4) & 0x0f);
1144c74ad251Schristos         power_val = GET_BE_U_2(tptr + 5);
11450f74e101Schristos         if (power_val < LLDP_TIA_POWER_VAL_MAX) {
1146c74ad251Schristos             ND_PRINT(", Power %.1f Watts", ((float)power_val) / 10);
11470f74e101Schristos         } else {
1148c74ad251Schristos             ND_PRINT(", Power %u (Reserved)", power_val);
11490f74e101Schristos         }
11500f74e101Schristos         break;
11510f74e101Schristos 
11520f74e101Schristos     case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV:
11530f74e101Schristos     case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV:
11540f74e101Schristos     case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV:
11550f74e101Schristos     case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER:
11560f74e101Schristos     case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME:
11570f74e101Schristos     case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME:
11580f74e101Schristos     case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID:
1159c74ad251Schristos         ND_PRINT("\n\t  %s ",
1160c74ad251Schristos                tok2str(lldp_tia_inventory_values, "unknown", subtype));
1161c74ad251Schristos         nd_printjnp(ndo, tptr + 4, tlv_len - 4);
11620f74e101Schristos         break;
11630f74e101Schristos 
11640f74e101Schristos     default:
11650f74e101Schristos         hexdump = TRUE;
11660f74e101Schristos         break;
11670f74e101Schristos     }
11680f74e101Schristos 
11690f74e101Schristos     return hexdump;
11700f74e101Schristos }
11710f74e101Schristos 
11720e9868baSchristos /*
11730e9868baSchristos  * Print DCBX Protocol fields (V 1.01).
11740e9868baSchristos  */
11750e9868baSchristos static int
1176b3a00663Schristos lldp_private_dcbx_print(netdissect_options *ndo,
1177b3a00663Schristos                         const u_char *pptr, u_int len)
11780e9868baSchristos {
1179c74ad251Schristos     int hexdump = FALSE;
1180c74ad251Schristos     u_int subtype;
1181c74ad251Schristos     uint16_t tval;
1182b3a00663Schristos     uint16_t tlv;
1183b3a00663Schristos     uint32_t i, pgval, uval;
1184c74ad251Schristos     u_int tlen, tlv_type;
1185c74ad251Schristos     uint16_t tlv_len;
11860e9868baSchristos     const u_char *tptr, *mptr;
11870e9868baSchristos 
11880e9868baSchristos     if (len < 4) {
11890e9868baSchristos         return hexdump;
11900e9868baSchristos     }
1191c74ad251Schristos     subtype = GET_U_1(pptr + 3);
11920e9868baSchristos 
1193c74ad251Schristos     ND_PRINT("\n\t  %s Subtype (%u)",
11940e9868baSchristos            tok2str(lldp_dcbx_subtype_values, "unknown", subtype),
1195c74ad251Schristos            subtype);
11960e9868baSchristos 
11970e9868baSchristos     /* by passing old version */
11980e9868baSchristos     if (subtype == LLDP_DCBX_SUBTYPE_1)
11990e9868baSchristos 	return TRUE;
12000e9868baSchristos 
12010e9868baSchristos     tptr = pptr + 4;
12020e9868baSchristos     tlen = len - 4;
12030e9868baSchristos 
12040e9868baSchristos     while (tlen >= sizeof(tlv)) {
12050e9868baSchristos 
1206c74ad251Schristos         ND_TCHECK_LEN(tptr, sizeof(tlv));
12070e9868baSchristos 
1208c74ad251Schristos         tlv = GET_BE_U_2(tptr);
12090e9868baSchristos 
12100e9868baSchristos         tlv_type = LLDP_EXTRACT_TYPE(tlv);
12110e9868baSchristos         tlv_len = LLDP_EXTRACT_LEN(tlv);
12120e9868baSchristos         hexdump = FALSE;
12130e9868baSchristos 
12140e9868baSchristos         tlen -= sizeof(tlv);
12150e9868baSchristos         tptr += sizeof(tlv);
12160e9868baSchristos 
12170e9868baSchristos         /* loop check */
12180e9868baSchristos         if (!tlv_type || !tlv_len) {
12190e9868baSchristos             break;
12200e9868baSchristos         }
12210e9868baSchristos 
1222c74ad251Schristos         ND_TCHECK_LEN(tptr, tlv_len);
12230e9868baSchristos         if (tlen < tlv_len) {
12240e9868baSchristos             goto trunc;
12250e9868baSchristos         }
12260e9868baSchristos 
12270e9868baSchristos 	/* decode every tlv */
12280e9868baSchristos         switch (tlv_type) {
12290e9868baSchristos         case LLDP_DCBX_CONTROL_TLV:
12300e9868baSchristos             if (tlv_len < 10) {
12310e9868baSchristos                 goto trunc;
12320e9868baSchristos             }
1233c74ad251Schristos 	    ND_PRINT("\n\t    Control - Protocol Control (type 0x%x, length %u)",
1234c74ad251Schristos 		LLDP_DCBX_CONTROL_TLV, tlv_len);
1235c74ad251Schristos 	    ND_PRINT("\n\t      Oper_Version: %u", GET_U_1(tptr));
1236c74ad251Schristos 	    ND_PRINT("\n\t      Max_Version: %u", GET_U_1(tptr + 1));
1237c74ad251Schristos 	    ND_PRINT("\n\t      Sequence Number: %u", GET_BE_U_4(tptr + 2));
1238c74ad251Schristos 	    ND_PRINT("\n\t      Acknowledgement Number: %u",
1239c74ad251Schristos 					GET_BE_U_4(tptr + 6));
12400e9868baSchristos 	    break;
12410e9868baSchristos         case LLDP_DCBX_PRIORITY_GROUPS_TLV:
12420e9868baSchristos             if (tlv_len < 17) {
12430e9868baSchristos                 goto trunc;
12440e9868baSchristos             }
1245c74ad251Schristos 	    ND_PRINT("\n\t    Feature - Priority Group (type 0x%x, length %u)",
1246c74ad251Schristos 		LLDP_DCBX_PRIORITY_GROUPS_TLV, tlv_len);
1247c74ad251Schristos 	    ND_PRINT("\n\t      Oper_Version: %u", GET_U_1(tptr));
1248c74ad251Schristos 	    ND_PRINT("\n\t      Max_Version: %u", GET_U_1(tptr + 1));
1249c74ad251Schristos 	    ND_PRINT("\n\t      Info block(0x%02X): ", GET_U_1(tptr + 2));
1250c74ad251Schristos 	    tval = GET_U_1(tptr + 2);
1251c74ad251Schristos 	    ND_PRINT("Enable bit: %u, Willing bit: %u, Error Bit: %u",
12520e9868baSchristos 		(tval &  0x80) ? 1 : 0, (tval &  0x40) ? 1 : 0,
1253c74ad251Schristos 		(tval &  0x20) ? 1 : 0);
1254c74ad251Schristos 	    ND_PRINT("\n\t      SubType: %u", GET_U_1(tptr + 3));
1255c74ad251Schristos 	    ND_PRINT("\n\t      Priority Allocation");
12560e9868baSchristos 
1257b3a00663Schristos 	    /*
1258b3a00663Schristos 	     * Array of 8 4-bit priority group ID values; we fetch all
1259b3a00663Schristos 	     * 32 bits and extract each nibble.
1260b3a00663Schristos 	     */
1261c74ad251Schristos 	    pgval = GET_BE_U_4(tptr + 4);
12620e9868baSchristos 	    for (i = 0; i <= 7; i++) {
1263c74ad251Schristos 		ND_PRINT("\n\t          PgId_%u: %u",
1264c74ad251Schristos 			i, (pgval >> (28 - 4 * i)) & 0xF);
12650e9868baSchristos 	    }
1266c74ad251Schristos 	    ND_PRINT("\n\t      Priority Group Allocation");
12670e9868baSchristos 	    for (i = 0; i <= 7; i++)
1268c74ad251Schristos 		ND_PRINT("\n\t          Pg percentage[%u]: %u", i,
1269c74ad251Schristos                          GET_U_1(tptr + 8 + i));
1270c74ad251Schristos 	    ND_PRINT("\n\t      NumTCsSupported: %u", GET_U_1(tptr + 8 + 8));
12710e9868baSchristos 	    break;
12720e9868baSchristos         case LLDP_DCBX_PRIORITY_FLOW_CONTROL_TLV:
12730e9868baSchristos             if (tlv_len < 6) {
12740e9868baSchristos                 goto trunc;
12750e9868baSchristos             }
1276c74ad251Schristos 	    ND_PRINT("\n\t    Feature - Priority Flow Control");
1277c74ad251Schristos 	    ND_PRINT(" (type 0x%x, length %u)",
1278c74ad251Schristos 		LLDP_DCBX_PRIORITY_FLOW_CONTROL_TLV, tlv_len);
1279c74ad251Schristos 	    ND_PRINT("\n\t      Oper_Version: %u", GET_U_1(tptr));
1280c74ad251Schristos 	    ND_PRINT("\n\t      Max_Version: %u", GET_U_1(tptr + 1));
1281c74ad251Schristos 	    ND_PRINT("\n\t      Info block(0x%02X): ", GET_U_1(tptr + 2));
1282c74ad251Schristos 	    tval = GET_U_1(tptr + 2);
1283c74ad251Schristos 	    ND_PRINT("Enable bit: %u, Willing bit: %u, Error Bit: %u",
12840e9868baSchristos 		(tval &  0x80) ? 1 : 0, (tval &  0x40) ? 1 : 0,
1285c74ad251Schristos 		(tval &  0x20) ? 1 : 0);
1286c74ad251Schristos 	    ND_PRINT("\n\t      SubType: %u", GET_U_1(tptr + 3));
1287c74ad251Schristos 	    tval = GET_U_1(tptr + 4);
1288c74ad251Schristos 	    ND_PRINT("\n\t      PFC Config (0x%02X)", GET_U_1(tptr + 4));
12890e9868baSchristos 	    for (i = 0; i <= 7; i++)
1290c74ad251Schristos 		ND_PRINT("\n\t          Priority Bit %u: %s",
1291c74ad251Schristos 		    i, (tval & (1 << i)) ? "Enabled" : "Disabled");
1292c74ad251Schristos 	    ND_PRINT("\n\t      NumTCPFCSupported: %u", GET_U_1(tptr + 5));
12930e9868baSchristos 	    break;
12940e9868baSchristos         case LLDP_DCBX_APPLICATION_TLV:
12950e9868baSchristos             if (tlv_len < 4) {
12960e9868baSchristos                 goto trunc;
12970e9868baSchristos             }
1298c74ad251Schristos 	    ND_PRINT("\n\t    Feature - Application (type 0x%x, length %u)",
1299c74ad251Schristos 		LLDP_DCBX_APPLICATION_TLV, tlv_len);
1300c74ad251Schristos 	    ND_PRINT("\n\t      Oper_Version: %u", GET_U_1(tptr));
1301c74ad251Schristos 	    ND_PRINT("\n\t      Max_Version: %u", GET_U_1(tptr + 1));
1302c74ad251Schristos 	    ND_PRINT("\n\t      Info block(0x%02X): ", GET_U_1(tptr + 2));
1303c74ad251Schristos 	    tval = GET_U_1(tptr + 2);
1304c74ad251Schristos 	    ND_PRINT("Enable bit: %u, Willing bit: %u, Error Bit: %u",
13050e9868baSchristos 		(tval &  0x80) ? 1 : 0, (tval &  0x40) ? 1 : 0,
1306c74ad251Schristos 		(tval &  0x20) ? 1 : 0);
1307c74ad251Schristos 	    ND_PRINT("\n\t      SubType: %u", GET_U_1(tptr + 3));
13080e9868baSchristos 	    tval = tlv_len - 4;
13090e9868baSchristos 	    mptr = tptr + 4;
13100e9868baSchristos 	    while (tval >= 6) {
1311c74ad251Schristos 		ND_PRINT("\n\t      Application Value");
1312c74ad251Schristos 		ND_PRINT("\n\t          Application Protocol ID: 0x%04x",
1313c74ad251Schristos 			GET_BE_U_2(mptr));
1314c74ad251Schristos 		uval = GET_BE_U_3(mptr + 2);
1315c74ad251Schristos 		ND_PRINT("\n\t          SF (0x%x) Application Protocol ID is %s",
13160e9868baSchristos 			(uval >> 22),
1317c74ad251Schristos 			(uval >> 22) ? "Socket Number" : "L2 EtherType");
1318c74ad251Schristos 		ND_PRINT("\n\t          OUI: 0x%06x", uval & 0x3fffff);
1319c74ad251Schristos 		ND_PRINT("\n\t          User Priority Map: 0x%02x",
1320c74ad251Schristos                          GET_U_1(mptr + 5));
13210e9868baSchristos 		tval = tval - 6;
13220e9868baSchristos 		mptr = mptr + 6;
13230e9868baSchristos 	    }
13240e9868baSchristos 	    break;
13250e9868baSchristos 	default:
13260e9868baSchristos 	    hexdump = TRUE;
13270e9868baSchristos 	    break;
13280e9868baSchristos 	}
13290e9868baSchristos 
13300e9868baSchristos         /* do we also want to see a hex dump ? */
1331b3a00663Schristos         if (ndo->ndo_vflag > 1 || (ndo->ndo_vflag && hexdump)) {
1332b3a00663Schristos 	    print_unknown_data(ndo, tptr, "\n\t    ", tlv_len);
13330e9868baSchristos         }
13340e9868baSchristos 
13350e9868baSchristos         tlen -= tlv_len;
13360e9868baSchristos         tptr += tlv_len;
13370e9868baSchristos     }
13380e9868baSchristos 
13390e9868baSchristos  trunc:
13400e9868baSchristos     return hexdump;
13410e9868baSchristos }
13420e9868baSchristos 
13430f74e101Schristos static char *
1344ba2ff121Schristos lldp_network_addr_print(netdissect_options *ndo, const u_char *tptr, u_int len)
1345ba2ff121Schristos {
1346b3a00663Schristos     uint8_t af;
13470f74e101Schristos     static char buf[BUFSIZE];
1348b3a00663Schristos     const char * (*pfunc)(netdissect_options *, const u_char *);
13490f74e101Schristos 
13500e9868baSchristos     if (len < 1)
13510e9868baSchristos       return NULL;
13520e9868baSchristos     len--;
1353c74ad251Schristos     af = GET_U_1(tptr);
13540f74e101Schristos     switch (af) {
13550f74e101Schristos     case AFNUM_INET:
1356c74ad251Schristos         if (len < sizeof(nd_ipv4))
13570e9868baSchristos           return NULL;
1358c74ad251Schristos         pfunc = ipaddr_string;
13590f74e101Schristos         break;
13600f74e101Schristos     case AFNUM_INET6:
1361c74ad251Schristos         if (len < sizeof(nd_ipv6))
13620e9868baSchristos           return NULL;
1363c74ad251Schristos         pfunc = ip6addr_string;
13640f74e101Schristos         break;
13650f74e101Schristos     case AFNUM_802:
1366c74ad251Schristos         if (len < MAC_ADDR_LEN)
13670e9868baSchristos           return NULL;
13680f74e101Schristos         pfunc = etheraddr_string;
13690f74e101Schristos         break;
13700f74e101Schristos     default:
13710f74e101Schristos         pfunc = NULL;
13720f74e101Schristos         break;
13730f74e101Schristos     }
13740f74e101Schristos 
13750f74e101Schristos     if (!pfunc) {
13760f74e101Schristos         snprintf(buf, sizeof(buf), "AFI %s (%u), no AF printer !",
13770f74e101Schristos                  tok2str(af_values, "Unknown", af), af);
13780f74e101Schristos     } else {
13790f74e101Schristos         snprintf(buf, sizeof(buf), "AFI %s (%u): %s",
1380b3a00663Schristos                  tok2str(af_values, "Unknown", af), af, (*pfunc)(ndo, tptr+1));
13810f74e101Schristos     }
13820f74e101Schristos 
13830f74e101Schristos     return buf;
13840f74e101Schristos }
13850f74e101Schristos 
13860f74e101Schristos static int
1387b3a00663Schristos lldp_mgmt_addr_tlv_print(netdissect_options *ndo,
1388ba2ff121Schristos                          const u_char *pptr, u_int len)
1389ba2ff121Schristos {
1390b3a00663Schristos     uint8_t mgmt_addr_len, intf_num_subtype, oid_len;
13910f74e101Schristos     const u_char *tptr;
13920f74e101Schristos     u_int tlen;
13930e9868baSchristos     char *mgmt_addr;
13940f74e101Schristos 
13950f74e101Schristos     tlen = len;
13960f74e101Schristos     tptr = pptr;
13970f74e101Schristos 
13980e9868baSchristos     if (tlen < 1) {
13990e9868baSchristos         return 0;
14000e9868baSchristos     }
1401c74ad251Schristos     mgmt_addr_len = GET_U_1(tptr);
1402c74ad251Schristos     tptr++;
14030f74e101Schristos     tlen--;
14040f74e101Schristos 
14050f74e101Schristos     if (tlen < mgmt_addr_len) {
14060f74e101Schristos         return 0;
14070f74e101Schristos     }
14080f74e101Schristos 
1409b3a00663Schristos     mgmt_addr = lldp_network_addr_print(ndo, tptr, mgmt_addr_len);
14100e9868baSchristos     if (mgmt_addr == NULL) {
14110e9868baSchristos         return 0;
14120e9868baSchristos     }
1413c74ad251Schristos     ND_PRINT("\n\t  Management Address length %u, %s",
1414c74ad251Schristos            mgmt_addr_len, mgmt_addr);
14150f74e101Schristos     tptr += mgmt_addr_len;
14160f74e101Schristos     tlen -= mgmt_addr_len;
14170f74e101Schristos 
14180f74e101Schristos     if (tlen < LLDP_INTF_NUM_LEN) {
14190f74e101Schristos         return 0;
14200f74e101Schristos     }
14210f74e101Schristos 
1422c74ad251Schristos     intf_num_subtype = GET_U_1(tptr);
1423c74ad251Schristos     ND_PRINT("\n\t  %s Interface Numbering (%u): %u",
14240f74e101Schristos            tok2str(lldp_intf_numb_subtype_values, "Unknown", intf_num_subtype),
14250f74e101Schristos            intf_num_subtype,
1426c74ad251Schristos            GET_BE_U_4(tptr + 1));
14270f74e101Schristos 
14280f74e101Schristos     tptr += LLDP_INTF_NUM_LEN;
14290f74e101Schristos     tlen -= LLDP_INTF_NUM_LEN;
14300f74e101Schristos 
14310f74e101Schristos     /*
14320f74e101Schristos      * The OID is optional.
14330f74e101Schristos      */
14340f74e101Schristos     if (tlen) {
1435c74ad251Schristos         oid_len = GET_U_1(tptr);
14360f74e101Schristos 
143772c96ff3Schristos         if (tlen < 1U + oid_len) {
14380e9868baSchristos             return 0;
14390e9868baSchristos         }
14400f74e101Schristos         if (oid_len) {
1441c74ad251Schristos             ND_PRINT("\n\t  OID length %u", oid_len);
1442c74ad251Schristos             nd_printjnp(ndo, tptr + 1, oid_len);
14430f74e101Schristos         }
14440f74e101Schristos     }
14450f74e101Schristos 
14460f74e101Schristos     return 1;
14470f74e101Schristos }
14480f74e101Schristos 
14490f74e101Schristos void
1450b3a00663Schristos lldp_print(netdissect_options *ndo,
1451c74ad251Schristos            const u_char *pptr, u_int len)
1452ba2ff121Schristos {
1453b3a00663Schristos     uint8_t subtype;
1454b3a00663Schristos     uint16_t tlv, cap, ena_cap;
14550f74e101Schristos     u_int oui, tlen, hexdump, tlv_type, tlv_len;
14560f74e101Schristos     const u_char *tptr;
14570e9868baSchristos     char *network_addr;
14580f74e101Schristos 
1459c74ad251Schristos     ndo->ndo_protocol = "lldp";
14600f74e101Schristos     tptr = pptr;
14610f74e101Schristos     tlen = len;
14620f74e101Schristos 
1463c74ad251Schristos     ND_PRINT("LLDP, length %u", len);
14640f74e101Schristos 
14650f74e101Schristos     while (tlen >= sizeof(tlv)) {
14660f74e101Schristos 
1467c74ad251Schristos         ND_TCHECK_LEN(tptr, sizeof(tlv));
14680f74e101Schristos 
1469c74ad251Schristos         tlv = GET_BE_U_2(tptr);
14700f74e101Schristos 
14710f74e101Schristos         tlv_type = LLDP_EXTRACT_TYPE(tlv);
14720f74e101Schristos         tlv_len = LLDP_EXTRACT_LEN(tlv);
14730f74e101Schristos         hexdump = FALSE;
14740f74e101Schristos 
14750f74e101Schristos         tlen -= sizeof(tlv);
14760f74e101Schristos         tptr += sizeof(tlv);
14770f74e101Schristos 
1478b3a00663Schristos         if (ndo->ndo_vflag) {
1479c74ad251Schristos             ND_PRINT("\n\t%s TLV (%u), length %u",
14800f74e101Schristos                    tok2str(lldp_tlv_values, "Unknown", tlv_type),
1481c74ad251Schristos                    tlv_type, tlv_len);
14820f74e101Schristos         }
14830f74e101Schristos 
14840f74e101Schristos         /* infinite loop check */
14850f74e101Schristos         if (!tlv_type || !tlv_len) {
14860f74e101Schristos             break;
14870f74e101Schristos         }
14880f74e101Schristos 
1489c74ad251Schristos         ND_TCHECK_LEN(tptr, tlv_len);
14900e9868baSchristos         if (tlen < tlv_len) {
14910e9868baSchristos             goto trunc;
14920e9868baSchristos         }
14930f74e101Schristos 
14940f74e101Schristos         switch (tlv_type) {
14950e9868baSchristos 
14960e9868baSchristos         case LLDP_CHASSIS_ID_TLV:
1497b3a00663Schristos             if (ndo->ndo_vflag) {
14980e9868baSchristos                 if (tlv_len < 2) {
14990e9868baSchristos                     goto trunc;
15000e9868baSchristos                 }
1501c74ad251Schristos                 subtype = GET_U_1(tptr);
1502c74ad251Schristos                 ND_PRINT("\n\t  Subtype %s (%u): ",
15030e9868baSchristos                        tok2str(lldp_chassis_subtype_values, "Unknown", subtype),
1504c74ad251Schristos                        subtype);
15050e9868baSchristos 
15060e9868baSchristos                 switch (subtype) {
15070e9868baSchristos                 case LLDP_CHASSIS_MAC_ADDR_SUBTYPE:
15080e9868baSchristos                     if (tlv_len < 1+6) {
15090e9868baSchristos                         goto trunc;
15100e9868baSchristos                     }
1511c74ad251Schristos                     ND_PRINT("%s", GET_ETHERADDR_STRING(tptr + 1));
15120e9868baSchristos                     break;
15130e9868baSchristos 
15140e9868baSchristos                 case LLDP_CHASSIS_INTF_NAME_SUBTYPE: /* fall through */
15150e9868baSchristos                 case LLDP_CHASSIS_LOCAL_SUBTYPE:
15160e9868baSchristos                 case LLDP_CHASSIS_CHASSIS_COMP_SUBTYPE:
15170e9868baSchristos                 case LLDP_CHASSIS_INTF_ALIAS_SUBTYPE:
15180e9868baSchristos                 case LLDP_CHASSIS_PORT_COMP_SUBTYPE:
1519c74ad251Schristos                     nd_printjnp(ndo, tptr + 1, tlv_len - 1);
15200e9868baSchristos                     break;
15210e9868baSchristos 
15220e9868baSchristos                 case LLDP_CHASSIS_NETWORK_ADDR_SUBTYPE:
1523b3a00663Schristos                     network_addr = lldp_network_addr_print(ndo, tptr+1, tlv_len-1);
15240e9868baSchristos                     if (network_addr == NULL) {
15250e9868baSchristos                         goto trunc;
15260e9868baSchristos                     }
1527c74ad251Schristos                     ND_PRINT("%s", network_addr);
15280e9868baSchristos                     break;
15290e9868baSchristos 
15300e9868baSchristos                 default:
15310e9868baSchristos                     hexdump = TRUE;
15320e9868baSchristos                     break;
15330e9868baSchristos                 }
15340e9868baSchristos             }
15350e9868baSchristos             break;
15360e9868baSchristos 
15370e9868baSchristos         case LLDP_PORT_ID_TLV:
1538b3a00663Schristos             if (ndo->ndo_vflag) {
15390e9868baSchristos                 if (tlv_len < 2) {
15400e9868baSchristos                     goto trunc;
15410e9868baSchristos                 }
1542c74ad251Schristos                 subtype = GET_U_1(tptr);
1543c74ad251Schristos                 ND_PRINT("\n\t  Subtype %s (%u): ",
15440e9868baSchristos                        tok2str(lldp_port_subtype_values, "Unknown", subtype),
1545c74ad251Schristos                        subtype);
15460e9868baSchristos 
15470e9868baSchristos                 switch (subtype) {
15480e9868baSchristos                 case LLDP_PORT_MAC_ADDR_SUBTYPE:
15490e9868baSchristos                     if (tlv_len < 1+6) {
15500e9868baSchristos                         goto trunc;
15510e9868baSchristos                     }
1552c74ad251Schristos                     ND_PRINT("%s", GET_ETHERADDR_STRING(tptr + 1));
15530e9868baSchristos                     break;
15540e9868baSchristos 
15550e9868baSchristos                 case LLDP_PORT_INTF_NAME_SUBTYPE: /* fall through */
15560e9868baSchristos                 case LLDP_PORT_LOCAL_SUBTYPE:
15570e9868baSchristos                 case LLDP_PORT_AGENT_CIRC_ID_SUBTYPE:
15580e9868baSchristos                 case LLDP_PORT_INTF_ALIAS_SUBTYPE:
15590e9868baSchristos                 case LLDP_PORT_PORT_COMP_SUBTYPE:
1560c74ad251Schristos                     nd_printjnp(ndo, tptr + 1, tlv_len - 1);
15610e9868baSchristos                     break;
15620e9868baSchristos 
15630e9868baSchristos                 case LLDP_PORT_NETWORK_ADDR_SUBTYPE:
1564b3a00663Schristos                     network_addr = lldp_network_addr_print(ndo, tptr+1, tlv_len-1);
15650e9868baSchristos                     if (network_addr == NULL) {
15660e9868baSchristos                         goto trunc;
15670e9868baSchristos                     }
1568c74ad251Schristos                     ND_PRINT("%s", network_addr);
15690e9868baSchristos                     break;
15700e9868baSchristos 
15710e9868baSchristos                 default:
15720e9868baSchristos                     hexdump = TRUE;
15730e9868baSchristos                     break;
15740e9868baSchristos                 }
15750e9868baSchristos             }
15760e9868baSchristos             break;
15770e9868baSchristos 
15780f74e101Schristos         case LLDP_TTL_TLV:
1579b3a00663Schristos             if (ndo->ndo_vflag) {
15800e9868baSchristos                 if (tlv_len < 2) {
15810e9868baSchristos                     goto trunc;
15820e9868baSchristos                 }
1583c74ad251Schristos                 ND_PRINT(": TTL %us", GET_BE_U_2(tptr));
15840f74e101Schristos             }
15850f74e101Schristos             break;
15860f74e101Schristos 
15870e9868baSchristos         case LLDP_PORT_DESCR_TLV:
1588b3a00663Schristos             if (ndo->ndo_vflag) {
1589c74ad251Schristos                 ND_PRINT(": ");
1590c74ad251Schristos                 nd_printjnp(ndo, tptr, tlv_len);
15910e9868baSchristos             }
15920e9868baSchristos             break;
15930f74e101Schristos 
15940e9868baSchristos         case LLDP_SYSTEM_NAME_TLV:
15950f74e101Schristos             /*
15960f74e101Schristos              * The system name is also print in non-verbose mode
15970f74e101Schristos              * similar to the CDP printer.
15980f74e101Schristos              */
1599c74ad251Schristos             ND_PRINT(": ");
1600c74ad251Schristos             nd_printjnp(ndo, tptr, tlv_len);
16010f74e101Schristos             break;
16020f74e101Schristos 
16030f74e101Schristos         case LLDP_SYSTEM_DESCR_TLV:
1604b3a00663Schristos             if (ndo->ndo_vflag) {
1605c74ad251Schristos                 ND_PRINT("\n\t  ");
1606c74ad251Schristos                 nd_printjnp(ndo, tptr, tlv_len);
16070f74e101Schristos             }
16080f74e101Schristos             break;
16090f74e101Schristos 
16100f74e101Schristos         case LLDP_SYSTEM_CAP_TLV:
1611b3a00663Schristos             if (ndo->ndo_vflag) {
16120e9868baSchristos                 /*
16130e9868baSchristos                  * XXX - IEEE Std 802.1AB-2009 says the first octet
16140e9868baSchristos                  * if a chassis ID subtype, with the system
16150e9868baSchristos                  * capabilities and enabled capabilities following
16160e9868baSchristos                  * it.
16170e9868baSchristos                  */
16180e9868baSchristos                 if (tlv_len < 4) {
16190e9868baSchristos                     goto trunc;
16200e9868baSchristos                 }
1621c74ad251Schristos                 cap = GET_BE_U_2(tptr);
1622c74ad251Schristos                 ena_cap = GET_BE_U_2(tptr + 2);
1623c74ad251Schristos                 ND_PRINT("\n\t  System  Capabilities [%s] (0x%04x)",
1624c74ad251Schristos                        bittok2str(lldp_cap_values, "none", cap), cap);
1625c74ad251Schristos                 ND_PRINT("\n\t  Enabled Capabilities [%s] (0x%04x)",
1626c74ad251Schristos                        bittok2str(lldp_cap_values, "none", ena_cap), ena_cap);
16270f74e101Schristos             }
16280f74e101Schristos             break;
16290f74e101Schristos 
16300f74e101Schristos         case LLDP_MGMT_ADDR_TLV:
1631b3a00663Schristos             if (ndo->ndo_vflag) {
1632b3a00663Schristos                 if (!lldp_mgmt_addr_tlv_print(ndo, tptr, tlv_len)) {
16330f74e101Schristos                     goto trunc;
16340f74e101Schristos                 }
16350f74e101Schristos             }
16360f74e101Schristos             break;
16370f74e101Schristos 
16380e9868baSchristos         case LLDP_PRIVATE_TLV:
1639b3a00663Schristos             if (ndo->ndo_vflag) {
16400e9868baSchristos                 if (tlv_len < 3) {
16410e9868baSchristos                     goto trunc;
16420e9868baSchristos                 }
1643c74ad251Schristos                 oui = GET_BE_U_3(tptr);
1644c74ad251Schristos                 ND_PRINT(": OUI %s (0x%06x)", tok2str(oui_values, "Unknown", oui), oui);
16450e9868baSchristos 
16460e9868baSchristos                 switch (oui) {
16470e9868baSchristos                 case OUI_IEEE_8021_PRIVATE:
1648b3a00663Schristos                     hexdump = lldp_private_8021_print(ndo, tptr, tlv_len);
16490e9868baSchristos                     break;
16500e9868baSchristos                 case OUI_IEEE_8023_PRIVATE:
1651b3a00663Schristos                     hexdump = lldp_private_8023_print(ndo, tptr, tlv_len);
16520e9868baSchristos                     break;
1653dc860a36Sspz 		case OUI_IANA:
1654dc860a36Sspz                     hexdump = lldp_private_iana_print(ndo, tptr, tlv_len);
1655dc860a36Sspz                     break;
16560e9868baSchristos                 case OUI_TIA:
1657b3a00663Schristos                     hexdump = lldp_private_tia_print(ndo, tptr, tlv_len);
16580e9868baSchristos                     break;
16590e9868baSchristos                 case OUI_DCBX:
1660b3a00663Schristos                     hexdump = lldp_private_dcbx_print(ndo, tptr, tlv_len);
16610e9868baSchristos                     break;
16620e9868baSchristos                 default:
16630e9868baSchristos                     hexdump = TRUE;
16640e9868baSchristos                     break;
16650e9868baSchristos                 }
16660e9868baSchristos             }
16670e9868baSchristos             break;
16680e9868baSchristos 
16690f74e101Schristos         default:
16700f74e101Schristos             hexdump = TRUE;
16710f74e101Schristos             break;
16720f74e101Schristos         }
16730f74e101Schristos 
16740f74e101Schristos         /* do we also want to see a hex dump ? */
1675b3a00663Schristos         if (ndo->ndo_vflag > 1 || (ndo->ndo_vflag && hexdump)) {
1676b3a00663Schristos             print_unknown_data(ndo, tptr, "\n\t  ", tlv_len);
16770f74e101Schristos         }
16780f74e101Schristos 
16790f74e101Schristos         tlen -= tlv_len;
16800f74e101Schristos         tptr += tlv_len;
16810f74e101Schristos     }
16820f74e101Schristos     return;
16830f74e101Schristos  trunc:
1684c74ad251Schristos     nd_print_trunc(ndo);
16850f74e101Schristos }
1686