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