github.com/gopacket/gopacket@v1.1.0/layers/lldp.go (about) 1 // Copyright 2012 Google, Inc. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style license 4 // that can be found in the LICENSE file in the root of the source 5 // tree. 6 7 package layers 8 9 import ( 10 "encoding/binary" 11 "errors" 12 "fmt" 13 14 "github.com/gopacket/gopacket" 15 ) 16 17 // LLDPTLVType is the type of each TLV value in a LinkLayerDiscovery packet. 18 type LLDPTLVType byte 19 20 const ( 21 LLDPTLVEnd LLDPTLVType = 0 22 LLDPTLVChassisID LLDPTLVType = 1 23 LLDPTLVPortID LLDPTLVType = 2 24 LLDPTLVTTL LLDPTLVType = 3 25 LLDPTLVPortDescription LLDPTLVType = 4 26 LLDPTLVSysName LLDPTLVType = 5 27 LLDPTLVSysDescription LLDPTLVType = 6 28 LLDPTLVSysCapabilities LLDPTLVType = 7 29 LLDPTLVMgmtAddress LLDPTLVType = 8 30 LLDPTLVOrgSpecific LLDPTLVType = 127 31 ) 32 33 // LinkLayerDiscoveryValue is a TLV value inside a LinkLayerDiscovery packet layer. 34 type LinkLayerDiscoveryValue struct { 35 Type LLDPTLVType 36 Length uint16 37 Value []byte 38 } 39 40 func (c *LinkLayerDiscoveryValue) len() int { 41 return 0 42 } 43 44 // LLDPChassisIDSubType specifies the value type for a single LLDPChassisID.ID 45 type LLDPChassisIDSubType byte 46 47 // LLDP Chassis Types 48 const ( 49 LLDPChassisIDSubTypeReserved LLDPChassisIDSubType = 0 50 LLDPChassisIDSubTypeChassisComp LLDPChassisIDSubType = 1 51 LLDPChassisIDSubtypeIfaceAlias LLDPChassisIDSubType = 2 52 LLDPChassisIDSubTypePortComp LLDPChassisIDSubType = 3 53 LLDPChassisIDSubTypeMACAddr LLDPChassisIDSubType = 4 54 LLDPChassisIDSubTypeNetworkAddr LLDPChassisIDSubType = 5 55 LLDPChassisIDSubtypeIfaceName LLDPChassisIDSubType = 6 56 LLDPChassisIDSubTypeLocal LLDPChassisIDSubType = 7 57 ) 58 59 type LLDPChassisID struct { 60 Subtype LLDPChassisIDSubType 61 ID []byte 62 } 63 64 func (c *LLDPChassisID) serialize() []byte { 65 66 var buf = make([]byte, c.serializedLen()) 67 idLen := uint16(LLDPTLVChassisID)<<9 | uint16(len(c.ID)+1) //id should take 7 bits, length should take 9 bits, +1 for subtype 68 binary.BigEndian.PutUint16(buf[0:2], idLen) 69 buf[2] = byte(c.Subtype) 70 copy(buf[3:], c.ID) 71 return buf 72 } 73 74 func (c *LLDPChassisID) serializedLen() int { 75 return len(c.ID) + 3 // +2 for id and length, +1 for subtype 76 } 77 78 // LLDPPortIDSubType specifies the value type for a single LLDPPortID.ID 79 type LLDPPortIDSubType byte 80 81 // LLDP PortID types 82 const ( 83 LLDPPortIDSubtypeReserved LLDPPortIDSubType = 0 84 LLDPPortIDSubtypeIfaceAlias LLDPPortIDSubType = 1 85 LLDPPortIDSubtypePortComp LLDPPortIDSubType = 2 86 LLDPPortIDSubtypeMACAddr LLDPPortIDSubType = 3 87 LLDPPortIDSubtypeNetworkAddr LLDPPortIDSubType = 4 88 LLDPPortIDSubtypeIfaceName LLDPPortIDSubType = 5 89 LLDPPortIDSubtypeAgentCircuitID LLDPPortIDSubType = 6 90 LLDPPortIDSubtypeLocal LLDPPortIDSubType = 7 91 ) 92 93 type LLDPPortID struct { 94 Subtype LLDPPortIDSubType 95 ID []byte 96 } 97 98 func (c *LLDPPortID) serialize() []byte { 99 100 var buf = make([]byte, c.serializedLen()) 101 idLen := uint16(LLDPTLVPortID)<<9 | uint16(len(c.ID)+1) //id should take 7 bits, length should take 9 bits, +1 for subtype 102 binary.BigEndian.PutUint16(buf[0:2], idLen) 103 buf[2] = byte(c.Subtype) 104 copy(buf[3:], c.ID) 105 return buf 106 } 107 108 func (c *LLDPPortID) serializedLen() int { 109 return len(c.ID) + 3 // +2 for id and length, +1 for subtype 110 } 111 112 // LinkLayerDiscovery is a packet layer containing the LinkLayer Discovery Protocol. 113 // See http:http://standards.ieee.org/getieee802/download/802.1AB-2009.pdf 114 // ChassisID, PortID and TTL are mandatory TLV's. Other values can be decoded 115 // with DecodeValues() 116 type LinkLayerDiscovery struct { 117 BaseLayer 118 ChassisID LLDPChassisID 119 PortID LLDPPortID 120 TTL uint16 121 Values []LinkLayerDiscoveryValue 122 } 123 124 type IEEEOUI uint32 125 126 // http://standards.ieee.org/develop/regauth/oui/oui.txt 127 const ( 128 IEEEOUI8021 IEEEOUI = 0x0080c2 129 IEEEOUI8023 IEEEOUI = 0x00120f 130 IEEEOUI80211 IEEEOUI = 0x000fac 131 IEEEOUI8021Qbg IEEEOUI = 0x0013BF 132 IEEEOUICisco2 IEEEOUI = 0x000142 133 IEEEOUIMedia IEEEOUI = 0x0012bb // TR-41 134 IEEEOUIProfinet IEEEOUI = 0x000ecf 135 IEEEOUIDCBX IEEEOUI = 0x001b21 136 ) 137 138 // LLDPOrgSpecificTLV is an Organisation-specific TLV 139 type LLDPOrgSpecificTLV struct { 140 OUI IEEEOUI 141 SubType uint8 142 Info []byte 143 } 144 145 // LLDPCapabilities Types 146 const ( 147 LLDPCapsOther uint16 = 1 << 0 148 LLDPCapsRepeater uint16 = 1 << 1 149 LLDPCapsBridge uint16 = 1 << 2 150 LLDPCapsWLANAP uint16 = 1 << 3 151 LLDPCapsRouter uint16 = 1 << 4 152 LLDPCapsPhone uint16 = 1 << 5 153 LLDPCapsDocSis uint16 = 1 << 6 154 LLDPCapsStationOnly uint16 = 1 << 7 155 LLDPCapsCVLAN uint16 = 1 << 8 156 LLDPCapsSVLAN uint16 = 1 << 9 157 LLDPCapsTmpr uint16 = 1 << 10 158 ) 159 160 // LLDPCapabilities represents the capabilities of a device 161 type LLDPCapabilities struct { 162 Other bool 163 Repeater bool 164 Bridge bool 165 WLANAP bool 166 Router bool 167 Phone bool 168 DocSis bool 169 StationOnly bool 170 CVLAN bool 171 SVLAN bool 172 TMPR bool 173 } 174 175 type LLDPSysCapabilities struct { 176 SystemCap LLDPCapabilities 177 EnabledCap LLDPCapabilities 178 } 179 180 type IANAAddressFamily byte 181 182 // LLDP Management Address Subtypes 183 // http://www.iana.org/assignments/address-family-numbers/address-family-numbers.xml 184 const ( 185 IANAAddressFamilyReserved IANAAddressFamily = 0 186 IANAAddressFamilyIPV4 IANAAddressFamily = 1 187 IANAAddressFamilyIPV6 IANAAddressFamily = 2 188 IANAAddressFamilyNSAP IANAAddressFamily = 3 189 IANAAddressFamilyHDLC IANAAddressFamily = 4 190 IANAAddressFamilyBBN1822 IANAAddressFamily = 5 191 IANAAddressFamily802 IANAAddressFamily = 6 192 IANAAddressFamilyE163 IANAAddressFamily = 7 193 IANAAddressFamilyE164 IANAAddressFamily = 8 194 IANAAddressFamilyF69 IANAAddressFamily = 9 195 IANAAddressFamilyX121 IANAAddressFamily = 10 196 IANAAddressFamilyIPX IANAAddressFamily = 11 197 IANAAddressFamilyAtalk IANAAddressFamily = 12 198 IANAAddressFamilyDecnet IANAAddressFamily = 13 199 IANAAddressFamilyBanyan IANAAddressFamily = 14 200 IANAAddressFamilyE164NSAP IANAAddressFamily = 15 201 IANAAddressFamilyDNS IANAAddressFamily = 16 202 IANAAddressFamilyDistname IANAAddressFamily = 17 203 IANAAddressFamilyASNumber IANAAddressFamily = 18 204 IANAAddressFamilyXTPIPV4 IANAAddressFamily = 19 205 IANAAddressFamilyXTPIPV6 IANAAddressFamily = 20 206 IANAAddressFamilyXTP IANAAddressFamily = 21 207 IANAAddressFamilyFcWWPN IANAAddressFamily = 22 208 IANAAddressFamilyFcWWNN IANAAddressFamily = 23 209 IANAAddressFamilyGWID IANAAddressFamily = 24 210 IANAAddressFamilyL2VPN IANAAddressFamily = 25 211 ) 212 213 type LLDPInterfaceSubtype byte 214 215 // LLDP Interface Subtypes 216 const ( 217 LLDPInterfaceSubtypeUnknown LLDPInterfaceSubtype = 1 218 LLDPInterfaceSubtypeifIndex LLDPInterfaceSubtype = 2 219 LLDPInterfaceSubtypeSysPort LLDPInterfaceSubtype = 3 220 ) 221 222 type LLDPMgmtAddress struct { 223 Subtype IANAAddressFamily 224 Address []byte 225 InterfaceSubtype LLDPInterfaceSubtype 226 InterfaceNumber uint32 227 OID string 228 } 229 230 // LinkLayerDiscoveryInfo represents the decoded details for a set of LinkLayerDiscoveryValues 231 // Organisation-specific TLV's can be decoded using the various Decode() methods 232 type LinkLayerDiscoveryInfo struct { 233 BaseLayer 234 PortDescription string 235 SysName string 236 SysDescription string 237 SysCapabilities LLDPSysCapabilities 238 MgmtAddress LLDPMgmtAddress 239 OrgTLVs []LLDPOrgSpecificTLV // Private TLVs 240 Unknown []LinkLayerDiscoveryValue // undecoded TLVs 241 } 242 243 // / IEEE 802.1 TLV Subtypes 244 const ( 245 LLDP8021SubtypePortVLANID uint8 = 1 246 LLDP8021SubtypeProtocolVLANID uint8 = 2 247 LLDP8021SubtypeVLANName uint8 = 3 248 LLDP8021SubtypeProtocolIdentity uint8 = 4 249 LLDP8021SubtypeVDIUsageDigest uint8 = 5 250 LLDP8021SubtypeManagementVID uint8 = 6 251 LLDP8021SubtypeLinkAggregation uint8 = 7 252 ) 253 254 // VLAN Port Protocol ID options 255 const ( 256 LLDPProtocolVLANIDCapability byte = 1 << 1 257 LLDPProtocolVLANIDStatus byte = 1 << 2 258 ) 259 260 type PortProtocolVLANID struct { 261 Supported bool 262 Enabled bool 263 ID uint16 264 } 265 266 type VLANName struct { 267 ID uint16 268 Name string 269 } 270 271 type ProtocolIdentity []byte 272 273 // LACP options 274 const ( 275 LLDPAggregationCapability byte = 1 << 0 276 LLDPAggregationStatus byte = 1 << 1 277 ) 278 279 // IEEE 802 Link Aggregation parameters 280 type LLDPLinkAggregation struct { 281 Supported bool 282 Enabled bool 283 PortID uint32 284 } 285 286 // LLDPInfo8021 represents the information carried in 802.1 Org-specific TLVs 287 type LLDPInfo8021 struct { 288 PVID uint16 289 PPVIDs []PortProtocolVLANID 290 VLANNames []VLANName 291 ProtocolIdentities []ProtocolIdentity 292 VIDUsageDigest uint32 293 ManagementVID uint16 294 LinkAggregation LLDPLinkAggregation 295 } 296 297 // IEEE 802.3 TLV Subtypes 298 const ( 299 LLDP8023SubtypeMACPHY uint8 = 1 300 LLDP8023SubtypeMDIPower uint8 = 2 301 LLDP8023SubtypeLinkAggregation uint8 = 3 302 LLDP8023SubtypeMTU uint8 = 4 303 ) 304 305 // MACPHY options 306 const ( 307 LLDPMACPHYCapability byte = 1 << 0 308 LLDPMACPHYStatus byte = 1 << 1 309 ) 310 311 // From IANA-MAU-MIB (introduced by RFC 4836) - dot3MauType 312 const ( 313 LLDPMAUTypeUnknown uint16 = 0 314 LLDPMAUTypeAUI uint16 = 1 315 LLDPMAUType10Base5 uint16 = 2 316 LLDPMAUTypeFOIRL uint16 = 3 317 LLDPMAUType10Base2 uint16 = 4 318 LLDPMAUType10BaseT uint16 = 5 319 LLDPMAUType10BaseFP uint16 = 6 320 LLDPMAUType10BaseFB uint16 = 7 321 LLDPMAUType10BaseFL uint16 = 8 322 LLDPMAUType10BROAD36 uint16 = 9 323 LLDPMAUType10BaseT_HD uint16 = 10 324 LLDPMAUType10BaseT_FD uint16 = 11 325 LLDPMAUType10BaseFL_HD uint16 = 12 326 LLDPMAUType10BaseFL_FD uint16 = 13 327 LLDPMAUType100BaseT4 uint16 = 14 328 LLDPMAUType100BaseTX_HD uint16 = 15 329 LLDPMAUType100BaseTX_FD uint16 = 16 330 LLDPMAUType100BaseFX_HD uint16 = 17 331 LLDPMAUType100BaseFX_FD uint16 = 18 332 LLDPMAUType100BaseT2_HD uint16 = 19 333 LLDPMAUType100BaseT2_FD uint16 = 20 334 LLDPMAUType1000BaseX_HD uint16 = 21 335 LLDPMAUType1000BaseX_FD uint16 = 22 336 LLDPMAUType1000BaseLX_HD uint16 = 23 337 LLDPMAUType1000BaseLX_FD uint16 = 24 338 LLDPMAUType1000BaseSX_HD uint16 = 25 339 LLDPMAUType1000BaseSX_FD uint16 = 26 340 LLDPMAUType1000BaseCX_HD uint16 = 27 341 LLDPMAUType1000BaseCX_FD uint16 = 28 342 LLDPMAUType1000BaseT_HD uint16 = 29 343 LLDPMAUType1000BaseT_FD uint16 = 30 344 LLDPMAUType10GBaseX uint16 = 31 345 LLDPMAUType10GBaseLX4 uint16 = 32 346 LLDPMAUType10GBaseR uint16 = 33 347 LLDPMAUType10GBaseER uint16 = 34 348 LLDPMAUType10GBaseLR uint16 = 35 349 LLDPMAUType10GBaseSR uint16 = 36 350 LLDPMAUType10GBaseW uint16 = 37 351 LLDPMAUType10GBaseEW uint16 = 38 352 LLDPMAUType10GBaseLW uint16 = 39 353 LLDPMAUType10GBaseSW uint16 = 40 354 LLDPMAUType10GBaseCX4 uint16 = 41 355 LLDPMAUType2BaseTL uint16 = 42 356 LLDPMAUType10PASS_TS uint16 = 43 357 LLDPMAUType100BaseBX10D uint16 = 44 358 LLDPMAUType100BaseBX10U uint16 = 45 359 LLDPMAUType100BaseLX10 uint16 = 46 360 LLDPMAUType1000BaseBX10D uint16 = 47 361 LLDPMAUType1000BaseBX10U uint16 = 48 362 LLDPMAUType1000BaseLX10 uint16 = 49 363 LLDPMAUType1000BasePX10D uint16 = 50 364 LLDPMAUType1000BasePX10U uint16 = 51 365 LLDPMAUType1000BasePX20D uint16 = 52 366 LLDPMAUType1000BasePX20U uint16 = 53 367 LLDPMAUType10GBaseT uint16 = 54 368 LLDPMAUType10GBaseLRM uint16 = 55 369 LLDPMAUType1000BaseKX uint16 = 56 370 LLDPMAUType10GBaseKX4 uint16 = 57 371 LLDPMAUType10GBaseKR uint16 = 58 372 LLDPMAUType10_1GBasePRX_D1 uint16 = 59 373 LLDPMAUType10_1GBasePRX_D2 uint16 = 60 374 LLDPMAUType10_1GBasePRX_D3 uint16 = 61 375 LLDPMAUType10_1GBasePRX_U1 uint16 = 62 376 LLDPMAUType10_1GBasePRX_U2 uint16 = 63 377 LLDPMAUType10_1GBasePRX_U3 uint16 = 64 378 LLDPMAUType10GBasePR_D1 uint16 = 65 379 LLDPMAUType10GBasePR_D2 uint16 = 66 380 LLDPMAUType10GBasePR_D3 uint16 = 67 381 LLDPMAUType10GBasePR_U1 uint16 = 68 382 LLDPMAUType10GBasePR_U3 uint16 = 69 383 ) 384 385 // From RFC 3636 - ifMauAutoNegCapAdvertisedBits 386 const ( 387 LLDPMAUPMDOther uint16 = 1 << 15 388 LLDPMAUPMD10BaseT uint16 = 1 << 14 389 LLDPMAUPMD10BaseT_FD uint16 = 1 << 13 390 LLDPMAUPMD100BaseT4 uint16 = 1 << 12 391 LLDPMAUPMD100BaseTX uint16 = 1 << 11 392 LLDPMAUPMD100BaseTX_FD uint16 = 1 << 10 393 LLDPMAUPMD100BaseT2 uint16 = 1 << 9 394 LLDPMAUPMD100BaseT2_FD uint16 = 1 << 8 395 LLDPMAUPMDFDXPAUSE uint16 = 1 << 7 396 LLDPMAUPMDFDXAPAUSE uint16 = 1 << 6 397 LLDPMAUPMDFDXSPAUSE uint16 = 1 << 5 398 LLDPMAUPMDFDXBPAUSE uint16 = 1 << 4 399 LLDPMAUPMD1000BaseX uint16 = 1 << 3 400 LLDPMAUPMD1000BaseX_FD uint16 = 1 << 2 401 LLDPMAUPMD1000BaseT uint16 = 1 << 1 402 LLDPMAUPMD1000BaseT_FD uint16 = 1 << 0 403 ) 404 405 // Inverted ifMauAutoNegCapAdvertisedBits if required 406 // (Some manufacturers misinterpreted the spec - 407 // see https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=1455) 408 const ( 409 LLDPMAUPMDOtherInv uint16 = 1 << 0 410 LLDPMAUPMD10BaseTInv uint16 = 1 << 1 411 LLDPMAUPMD10BaseT_FDInv uint16 = 1 << 2 412 LLDPMAUPMD100BaseT4Inv uint16 = 1 << 3 413 LLDPMAUPMD100BaseTXInv uint16 = 1 << 4 414 LLDPMAUPMD100BaseTX_FDInv uint16 = 1 << 5 415 LLDPMAUPMD100BaseT2Inv uint16 = 1 << 6 416 LLDPMAUPMD100BaseT2_FDInv uint16 = 1 << 7 417 LLDPMAUPMDFDXPAUSEInv uint16 = 1 << 8 418 LLDPMAUPMDFDXAPAUSEInv uint16 = 1 << 9 419 LLDPMAUPMDFDXSPAUSEInv uint16 = 1 << 10 420 LLDPMAUPMDFDXBPAUSEInv uint16 = 1 << 11 421 LLDPMAUPMD1000BaseXInv uint16 = 1 << 12 422 LLDPMAUPMD1000BaseX_FDInv uint16 = 1 << 13 423 LLDPMAUPMD1000BaseTInv uint16 = 1 << 14 424 LLDPMAUPMD1000BaseT_FDInv uint16 = 1 << 15 425 ) 426 427 type LLDPMACPHYConfigStatus struct { 428 AutoNegSupported bool 429 AutoNegEnabled bool 430 AutoNegCapability uint16 431 MAUType uint16 432 } 433 434 // MDI Power options 435 const ( 436 LLDPMDIPowerPortClass byte = 1 << 0 437 LLDPMDIPowerCapability byte = 1 << 1 438 LLDPMDIPowerStatus byte = 1 << 2 439 LLDPMDIPowerPairsAbility byte = 1 << 3 440 ) 441 442 type LLDPPowerType byte 443 444 type LLDPPowerSource byte 445 446 type LLDPPowerPriority byte 447 448 const ( 449 LLDPPowerPriorityUnknown LLDPPowerPriority = 0 450 LLDPPowerPriorityMedium LLDPPowerPriority = 1 451 LLDPPowerPriorityHigh LLDPPowerPriority = 2 452 LLDPPowerPriorityLow LLDPPowerPriority = 3 453 ) 454 455 type LLDPPowerViaMDI8023 struct { 456 PortClassPSE bool // false = PD 457 PSESupported bool 458 PSEEnabled bool 459 PSEPairsAbility bool 460 PSEPowerPair uint8 461 PSEClass uint8 462 Type LLDPPowerType 463 Source LLDPPowerSource 464 Priority LLDPPowerPriority 465 Requested uint16 // 1-510 Watts 466 Allocated uint16 // 1-510 Watts 467 } 468 469 // LLDPInfo8023 represents the information carried in 802.3 Org-specific TLVs 470 type LLDPInfo8023 struct { 471 MACPHYConfigStatus LLDPMACPHYConfigStatus 472 PowerViaMDI LLDPPowerViaMDI8023 473 LinkAggregation LLDPLinkAggregation 474 MTU uint16 475 } 476 477 // IEEE 802.1Qbg TLV Subtypes 478 const ( 479 LLDP8021QbgEVB uint8 = 0 480 LLDP8021QbgCDCP uint8 = 1 481 LLDP8021QbgVDP uint8 = 2 482 LLDP8021QbgEVB22 uint8 = 13 483 ) 484 485 // LLDPEVBCapabilities Types 486 const ( 487 LLDPEVBCapsSTD uint16 = 1 << 7 488 LLDPEVBCapsRR uint16 = 1 << 6 489 LLDPEVBCapsRTE uint16 = 1 << 2 490 LLDPEVBCapsECP uint16 = 1 << 1 491 LLDPEVBCapsVDP uint16 = 1 << 0 492 ) 493 494 // LLDPEVBCapabilities represents the EVB capabilities of a device 495 type LLDPEVBCapabilities struct { 496 StandardBridging bool 497 ReflectiveRelay bool 498 RetransmissionTimerExponent bool 499 EdgeControlProtocol bool 500 VSIDiscoveryProtocol bool 501 } 502 503 type LLDPEVBSettings struct { 504 Supported LLDPEVBCapabilities 505 Enabled LLDPEVBCapabilities 506 SupportedVSIs uint16 507 ConfiguredVSIs uint16 508 RTEExponent uint8 509 } 510 511 // LLDPInfo8021Qbg represents the information carried in 802.1Qbg Org-specific TLVs 512 type LLDPInfo8021Qbg struct { 513 EVBSettings LLDPEVBSettings 514 } 515 516 type LLDPMediaSubtype uint8 517 518 // Media TLV Subtypes 519 const ( 520 LLDPMediaTypeCapabilities LLDPMediaSubtype = 1 521 LLDPMediaTypeNetwork LLDPMediaSubtype = 2 522 LLDPMediaTypeLocation LLDPMediaSubtype = 3 523 LLDPMediaTypePower LLDPMediaSubtype = 4 524 LLDPMediaTypeHardware LLDPMediaSubtype = 5 525 LLDPMediaTypeFirmware LLDPMediaSubtype = 6 526 LLDPMediaTypeSoftware LLDPMediaSubtype = 7 527 LLDPMediaTypeSerial LLDPMediaSubtype = 8 528 LLDPMediaTypeManufacturer LLDPMediaSubtype = 9 529 LLDPMediaTypeModel LLDPMediaSubtype = 10 530 LLDPMediaTypeAssetID LLDPMediaSubtype = 11 531 ) 532 533 type LLDPMediaClass uint8 534 535 // Media Class Values 536 const ( 537 LLDPMediaClassUndefined LLDPMediaClass = 0 538 LLDPMediaClassEndpointI LLDPMediaClass = 1 539 LLDPMediaClassEndpointII LLDPMediaClass = 2 540 LLDPMediaClassEndpointIII LLDPMediaClass = 3 541 LLDPMediaClassNetwork LLDPMediaClass = 4 542 ) 543 544 // LLDPMediaCapabilities Types 545 const ( 546 LLDPMediaCapsLLDP uint16 = 1 << 0 547 LLDPMediaCapsNetwork uint16 = 1 << 1 548 LLDPMediaCapsLocation uint16 = 1 << 2 549 LLDPMediaCapsPowerPSE uint16 = 1 << 3 550 LLDPMediaCapsPowerPD uint16 = 1 << 4 551 LLDPMediaCapsInventory uint16 = 1 << 5 552 ) 553 554 // LLDPMediaCapabilities represents the LLDP Media capabilities of a device 555 type LLDPMediaCapabilities struct { 556 Capabilities bool 557 NetworkPolicy bool 558 Location bool 559 PowerPSE bool 560 PowerPD bool 561 Inventory bool 562 Class LLDPMediaClass 563 } 564 565 type LLDPApplicationType uint8 566 567 const ( 568 LLDPAppTypeReserved LLDPApplicationType = 0 569 LLDPAppTypeVoice LLDPApplicationType = 1 570 LLDPappTypeVoiceSignaling LLDPApplicationType = 2 571 LLDPappTypeGuestVoice LLDPApplicationType = 3 572 LLDPappTypeGuestVoiceSignaling LLDPApplicationType = 4 573 LLDPappTypeSoftphoneVoice LLDPApplicationType = 5 574 LLDPappTypeVideoConferencing LLDPApplicationType = 6 575 LLDPappTypeStreamingVideo LLDPApplicationType = 7 576 LLDPappTypeVideoSignaling LLDPApplicationType = 8 577 ) 578 579 type LLDPNetworkPolicy struct { 580 ApplicationType LLDPApplicationType 581 Defined bool 582 Tagged bool 583 VLANId uint16 584 L2Priority uint16 585 DSCPValue uint8 586 } 587 588 type LLDPLocationFormat uint8 589 590 const ( 591 LLDPLocationFormatInvalid LLDPLocationFormat = 0 592 LLDPLocationFormatCoordinate LLDPLocationFormat = 1 593 LLDPLocationFormatAddress LLDPLocationFormat = 2 594 LLDPLocationFormatECS LLDPLocationFormat = 3 595 ) 596 597 type LLDPLocationAddressWhat uint8 598 599 const ( 600 LLDPLocationAddressWhatDHCP LLDPLocationAddressWhat = 0 601 LLDPLocationAddressWhatNetwork LLDPLocationAddressWhat = 1 602 LLDPLocationAddressWhatClient LLDPLocationAddressWhat = 2 603 ) 604 605 type LLDPLocationAddressType uint8 606 607 const ( 608 LLDPLocationAddressTypeLanguage LLDPLocationAddressType = 0 609 LLDPLocationAddressTypeNational LLDPLocationAddressType = 1 610 LLDPLocationAddressTypeCounty LLDPLocationAddressType = 2 611 LLDPLocationAddressTypeCity LLDPLocationAddressType = 3 612 LLDPLocationAddressTypeCityDivision LLDPLocationAddressType = 4 613 LLDPLocationAddressTypeNeighborhood LLDPLocationAddressType = 5 614 LLDPLocationAddressTypeStreet LLDPLocationAddressType = 6 615 LLDPLocationAddressTypeLeadingStreet LLDPLocationAddressType = 16 616 LLDPLocationAddressTypeTrailingStreet LLDPLocationAddressType = 17 617 LLDPLocationAddressTypeStreetSuffix LLDPLocationAddressType = 18 618 LLDPLocationAddressTypeHouseNum LLDPLocationAddressType = 19 619 LLDPLocationAddressTypeHouseSuffix LLDPLocationAddressType = 20 620 LLDPLocationAddressTypeLandmark LLDPLocationAddressType = 21 621 LLDPLocationAddressTypeAdditional LLDPLocationAddressType = 22 622 LLDPLocationAddressTypeName LLDPLocationAddressType = 23 623 LLDPLocationAddressTypePostal LLDPLocationAddressType = 24 624 LLDPLocationAddressTypeBuilding LLDPLocationAddressType = 25 625 LLDPLocationAddressTypeUnit LLDPLocationAddressType = 26 626 LLDPLocationAddressTypeFloor LLDPLocationAddressType = 27 627 LLDPLocationAddressTypeRoom LLDPLocationAddressType = 28 628 LLDPLocationAddressTypePlace LLDPLocationAddressType = 29 629 LLDPLocationAddressTypeScript LLDPLocationAddressType = 128 630 ) 631 632 type LLDPLocationCoordinate struct { 633 LatitudeResolution uint8 634 Latitude uint64 635 LongitudeResolution uint8 636 Longitude uint64 637 AltitudeType uint8 638 AltitudeResolution uint16 639 Altitude uint32 640 Datum uint8 641 } 642 643 type LLDPLocationAddressLine struct { 644 Type LLDPLocationAddressType 645 Value string 646 } 647 648 type LLDPLocationAddress struct { 649 What LLDPLocationAddressWhat 650 CountryCode string 651 AddressLines []LLDPLocationAddressLine 652 } 653 654 type LLDPLocationECS struct { 655 ELIN string 656 } 657 658 // LLDP represents a physical location. 659 // Only one of the embedded types will contain values, depending on Format. 660 type LLDPLocation struct { 661 Format LLDPLocationFormat 662 Coordinate LLDPLocationCoordinate 663 Address LLDPLocationAddress 664 ECS LLDPLocationECS 665 } 666 667 type LLDPPowerViaMDI struct { 668 Type LLDPPowerType 669 Source LLDPPowerSource 670 Priority LLDPPowerPriority 671 Value uint16 672 } 673 674 // LLDPInfoMedia represents the information carried in TR-41 Org-specific TLVs 675 type LLDPInfoMedia struct { 676 MediaCapabilities LLDPMediaCapabilities 677 NetworkPolicy LLDPNetworkPolicy 678 Location LLDPLocation 679 PowerViaMDI LLDPPowerViaMDI 680 HardwareRevision string 681 FirmwareRevision string 682 SoftwareRevision string 683 SerialNumber string 684 Manufacturer string 685 Model string 686 AssetID string 687 } 688 689 type LLDPCisco2Subtype uint8 690 691 // Cisco2 TLV Subtypes 692 const ( 693 LLDPCisco2PowerViaMDI LLDPCisco2Subtype = 1 694 ) 695 696 const ( 697 LLDPCiscoPSESupport uint8 = 1 << 0 698 LLDPCiscoArchShared uint8 = 1 << 1 699 LLDPCiscoPDSparePair uint8 = 1 << 2 700 LLDPCiscoPSESparePair uint8 = 1 << 3 701 ) 702 703 // LLDPInfoCisco2 represents the information carried in Cisco Org-specific TLVs 704 type LLDPInfoCisco2 struct { 705 PSEFourWirePoESupported bool 706 PDSparePairArchitectureShared bool 707 PDRequestSparePairPoEOn bool 708 PSESparePairPoEOn bool 709 } 710 711 // Profinet Subtypes 712 type LLDPProfinetSubtype uint8 713 714 const ( 715 LLDPProfinetPNIODelay LLDPProfinetSubtype = 1 716 LLDPProfinetPNIOPortStatus LLDPProfinetSubtype = 2 717 LLDPProfinetPNIOMRPPortStatus LLDPProfinetSubtype = 4 718 LLDPProfinetPNIOChassisMAC LLDPProfinetSubtype = 5 719 LLDPProfinetPNIOPTCPStatus LLDPProfinetSubtype = 6 720 ) 721 722 type LLDPPNIODelay struct { 723 RXLocal uint32 724 RXRemote uint32 725 TXLocal uint32 726 TXRemote uint32 727 CableLocal uint32 728 } 729 730 type LLDPPNIOPortStatus struct { 731 Class2 uint16 732 Class3 uint16 733 } 734 735 type LLDPPNIOMRPPortStatus struct { 736 UUID []byte 737 Status uint16 738 } 739 740 type LLDPPNIOPTCPStatus struct { 741 MasterAddress []byte 742 SubdomainUUID []byte 743 IRDataUUID []byte 744 PeriodValid bool 745 PeriodLength uint32 746 RedPeriodValid bool 747 RedPeriodBegin uint32 748 OrangePeriodValid bool 749 OrangePeriodBegin uint32 750 GreenPeriodValid bool 751 GreenPeriodBegin uint32 752 } 753 754 // LLDPInfoProfinet represents the information carried in Profinet Org-specific TLVs 755 type LLDPInfoProfinet struct { 756 PNIODelay LLDPPNIODelay 757 PNIOPortStatus LLDPPNIOPortStatus 758 PNIOMRPPortStatus LLDPPNIOMRPPortStatus 759 ChassisMAC []byte 760 PNIOPTCPStatus LLDPPNIOPTCPStatus 761 } 762 763 // LayerType returns gopacket.LayerTypeLinkLayerDiscovery. 764 func (c *LinkLayerDiscovery) LayerType() gopacket.LayerType { 765 return LayerTypeLinkLayerDiscovery 766 } 767 768 // SerializeTo serializes LLDP packet to bytes and writes on SerializeBuffer. 769 func (c *LinkLayerDiscovery) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 770 chassIDLen := c.ChassisID.serializedLen() 771 portIDLen := c.PortID.serializedLen() 772 vb, err := b.AppendBytes(chassIDLen + portIDLen + 4) // +4 for TTL 773 if err != nil { 774 return err 775 } 776 copy(vb[:chassIDLen], c.ChassisID.serialize()) 777 copy(vb[chassIDLen:], c.PortID.serialize()) 778 ttlIDLen := uint16(LLDPTLVTTL)<<9 | uint16(2) 779 binary.BigEndian.PutUint16(vb[chassIDLen+portIDLen:], ttlIDLen) 780 binary.BigEndian.PutUint16(vb[chassIDLen+portIDLen+2:], c.TTL) 781 782 for _, v := range c.Values { 783 vb, err := b.AppendBytes(int(v.Length) + 2) // +2 for TLV type and length; 1 byte for subtype is included in v.Value 784 if err != nil { 785 return err 786 } 787 idLen := ((uint16(v.Type) << 9) | v.Length) 788 binary.BigEndian.PutUint16(vb[0:2], idLen) 789 copy(vb[2:], v.Value) 790 } 791 792 vb, err = b.AppendBytes(2) // End Tlv, 2 bytes 793 if err != nil { 794 return err 795 } 796 binary.BigEndian.PutUint16(vb[len(vb)-2:], uint16(0)) //End tlv, 2 bytes, all zero 797 return nil 798 799 } 800 801 func decodeLinkLayerDiscovery(data []byte, p gopacket.PacketBuilder) error { 802 var vals []LinkLayerDiscoveryValue 803 vData := data[0:] 804 for len(vData) > 0 { 805 if len(vData) < 2 { 806 p.SetTruncated() 807 return errors.New("LLDP vdata < 2 bytes") 808 } 809 nbit := vData[0] & 0x01 810 t := LLDPTLVType(vData[0] >> 1) 811 val := LinkLayerDiscoveryValue{Type: t, Length: uint16(nbit)<<8 + uint16(vData[1])} 812 if val.Length > 0 { 813 if len(vData) < int(val.Length+2) { 814 p.SetTruncated() 815 return fmt.Errorf("LLDP VData < %d bytes", val.Length+2) 816 } 817 val.Value = vData[2 : val.Length+2] 818 } 819 vals = append(vals, val) 820 if t == LLDPTLVEnd { 821 break 822 } 823 if len(vData) < int(2+val.Length) { 824 return errors.New("Malformed LinkLayerDiscovery Header") 825 } 826 vData = vData[2+val.Length:] 827 } 828 if len(vals) < 4 { 829 return errors.New("Missing mandatory LinkLayerDiscovery TLV") 830 } 831 c := &LinkLayerDiscovery{} 832 gotEnd := false 833 for _, v := range vals { 834 switch v.Type { 835 case LLDPTLVEnd: 836 gotEnd = true 837 case LLDPTLVChassisID: 838 if len(v.Value) < 2 { 839 return errors.New("Malformed LinkLayerDiscovery ChassisID TLV") 840 } 841 c.ChassisID.Subtype = LLDPChassisIDSubType(v.Value[0]) 842 c.ChassisID.ID = v.Value[1:] 843 case LLDPTLVPortID: 844 if len(v.Value) < 2 { 845 return errors.New("Malformed LinkLayerDiscovery PortID TLV") 846 } 847 c.PortID.Subtype = LLDPPortIDSubType(v.Value[0]) 848 c.PortID.ID = v.Value[1:] 849 case LLDPTLVTTL: 850 if len(v.Value) < 2 { 851 return errors.New("Malformed LinkLayerDiscovery TTL TLV") 852 } 853 c.TTL = binary.BigEndian.Uint16(v.Value[0:2]) 854 default: 855 c.Values = append(c.Values, v) 856 } 857 } 858 if c.ChassisID.Subtype == 0 || c.PortID.Subtype == 0 || !gotEnd { 859 return errors.New("Missing mandatory LinkLayerDiscovery TLV") 860 } 861 c.Contents = data 862 p.AddLayer(c) 863 864 info := &LinkLayerDiscoveryInfo{} 865 p.AddLayer(info) 866 for _, v := range c.Values { 867 switch v.Type { 868 case LLDPTLVPortDescription: 869 info.PortDescription = string(v.Value) 870 case LLDPTLVSysName: 871 info.SysName = string(v.Value) 872 case LLDPTLVSysDescription: 873 info.SysDescription = string(v.Value) 874 case LLDPTLVSysCapabilities: 875 if err := checkLLDPTLVLen(v, 4); err != nil { 876 return err 877 } 878 info.SysCapabilities.SystemCap = getCapabilities(binary.BigEndian.Uint16(v.Value[0:2])) 879 info.SysCapabilities.EnabledCap = getCapabilities(binary.BigEndian.Uint16(v.Value[2:4])) 880 case LLDPTLVMgmtAddress: 881 if err := checkLLDPTLVLen(v, 9); err != nil { 882 return err 883 } 884 mlen := v.Value[0] 885 if err := checkLLDPTLVLen(v, int(mlen+7)); err != nil { 886 return err 887 } 888 info.MgmtAddress.Subtype = IANAAddressFamily(v.Value[1]) 889 info.MgmtAddress.Address = v.Value[2 : mlen+1] 890 info.MgmtAddress.InterfaceSubtype = LLDPInterfaceSubtype(v.Value[mlen+1]) 891 info.MgmtAddress.InterfaceNumber = binary.BigEndian.Uint32(v.Value[mlen+2 : mlen+6]) 892 olen := v.Value[mlen+6] 893 if err := checkLLDPTLVLen(v, int(mlen+7+olen)); err != nil { 894 return err 895 } 896 info.MgmtAddress.OID = string(v.Value[mlen+7 : mlen+7+olen]) 897 case LLDPTLVOrgSpecific: 898 if err := checkLLDPTLVLen(v, 4); err != nil { 899 return err 900 } 901 info.OrgTLVs = append(info.OrgTLVs, LLDPOrgSpecificTLV{IEEEOUI(binary.BigEndian.Uint32(append([]byte{byte(0)}, v.Value[0:3]...))), uint8(v.Value[3]), v.Value[4:]}) 902 } 903 } 904 return nil 905 } 906 907 func (l *LinkLayerDiscoveryInfo) Decode8021() (info LLDPInfo8021, err error) { 908 for _, o := range l.OrgTLVs { 909 if o.OUI != IEEEOUI8021 { 910 continue 911 } 912 switch o.SubType { 913 case LLDP8021SubtypePortVLANID: 914 if err = checkLLDPOrgSpecificLen(o, 2); err != nil { 915 return 916 } 917 info.PVID = binary.BigEndian.Uint16(o.Info[0:2]) 918 case LLDP8021SubtypeProtocolVLANID: 919 if err = checkLLDPOrgSpecificLen(o, 3); err != nil { 920 return 921 } 922 sup := (o.Info[0]&LLDPProtocolVLANIDCapability > 0) 923 en := (o.Info[0]&LLDPProtocolVLANIDStatus > 0) 924 id := binary.BigEndian.Uint16(o.Info[1:3]) 925 info.PPVIDs = append(info.PPVIDs, PortProtocolVLANID{sup, en, id}) 926 case LLDP8021SubtypeVLANName: 927 if err = checkLLDPOrgSpecificLen(o, 2); err != nil { 928 return 929 } 930 id := binary.BigEndian.Uint16(o.Info[0:2]) 931 info.VLANNames = append(info.VLANNames, VLANName{id, string(o.Info[3:])}) 932 case LLDP8021SubtypeProtocolIdentity: 933 if err = checkLLDPOrgSpecificLen(o, 1); err != nil { 934 return 935 } 936 l := int(o.Info[0]) 937 if l > 0 { 938 info.ProtocolIdentities = append(info.ProtocolIdentities, o.Info[1:1+l]) 939 } 940 case LLDP8021SubtypeVDIUsageDigest: 941 if err = checkLLDPOrgSpecificLen(o, 4); err != nil { 942 return 943 } 944 info.VIDUsageDigest = binary.BigEndian.Uint32(o.Info[0:4]) 945 case LLDP8021SubtypeManagementVID: 946 if err = checkLLDPOrgSpecificLen(o, 2); err != nil { 947 return 948 } 949 info.ManagementVID = binary.BigEndian.Uint16(o.Info[0:2]) 950 case LLDP8021SubtypeLinkAggregation: 951 if err = checkLLDPOrgSpecificLen(o, 5); err != nil { 952 return 953 } 954 sup := (o.Info[0]&LLDPAggregationCapability > 0) 955 en := (o.Info[0]&LLDPAggregationStatus > 0) 956 info.LinkAggregation = LLDPLinkAggregation{sup, en, binary.BigEndian.Uint32(o.Info[1:5])} 957 } 958 } 959 return 960 } 961 962 func (l *LinkLayerDiscoveryInfo) Decode8023() (info LLDPInfo8023, err error) { 963 for _, o := range l.OrgTLVs { 964 if o.OUI != IEEEOUI8023 { 965 continue 966 } 967 switch o.SubType { 968 case LLDP8023SubtypeMACPHY: 969 if err = checkLLDPOrgSpecificLen(o, 5); err != nil { 970 return 971 } 972 sup := (o.Info[0]&LLDPMACPHYCapability > 0) 973 en := (o.Info[0]&LLDPMACPHYStatus > 0) 974 ca := binary.BigEndian.Uint16(o.Info[1:3]) 975 mau := binary.BigEndian.Uint16(o.Info[3:5]) 976 info.MACPHYConfigStatus = LLDPMACPHYConfigStatus{sup, en, ca, mau} 977 case LLDP8023SubtypeMDIPower: 978 if err = checkLLDPOrgSpecificLen(o, 3); err != nil { 979 return 980 } 981 info.PowerViaMDI.PortClassPSE = (o.Info[0]&LLDPMDIPowerPortClass > 0) 982 info.PowerViaMDI.PSESupported = (o.Info[0]&LLDPMDIPowerCapability > 0) 983 info.PowerViaMDI.PSEEnabled = (o.Info[0]&LLDPMDIPowerStatus > 0) 984 info.PowerViaMDI.PSEPairsAbility = (o.Info[0]&LLDPMDIPowerPairsAbility > 0) 985 info.PowerViaMDI.PSEPowerPair = uint8(o.Info[1]) 986 info.PowerViaMDI.PSEClass = uint8(o.Info[2]) 987 if len(o.Info) >= 7 { 988 info.PowerViaMDI.Type = LLDPPowerType((o.Info[3] & 0xc0) >> 6) 989 info.PowerViaMDI.Source = LLDPPowerSource((o.Info[3] & 0x30) >> 4) 990 if info.PowerViaMDI.Type == 1 || info.PowerViaMDI.Type == 3 { 991 info.PowerViaMDI.Source += 128 // For Stringify purposes 992 } 993 info.PowerViaMDI.Priority = LLDPPowerPriority(o.Info[3] & 0x0f) 994 info.PowerViaMDI.Requested = binary.BigEndian.Uint16(o.Info[4:6]) 995 info.PowerViaMDI.Allocated = binary.BigEndian.Uint16(o.Info[6:8]) 996 } 997 case LLDP8023SubtypeLinkAggregation: 998 if err = checkLLDPOrgSpecificLen(o, 5); err != nil { 999 return 1000 } 1001 sup := (o.Info[0]&LLDPAggregationCapability > 0) 1002 en := (o.Info[0]&LLDPAggregationStatus > 0) 1003 info.LinkAggregation = LLDPLinkAggregation{sup, en, binary.BigEndian.Uint32(o.Info[1:5])} 1004 case LLDP8023SubtypeMTU: 1005 if err = checkLLDPOrgSpecificLen(o, 2); err != nil { 1006 return 1007 } 1008 info.MTU = binary.BigEndian.Uint16(o.Info[0:2]) 1009 } 1010 } 1011 return 1012 } 1013 1014 func (l *LinkLayerDiscoveryInfo) Decode8021Qbg() (info LLDPInfo8021Qbg, err error) { 1015 for _, o := range l.OrgTLVs { 1016 if o.OUI != IEEEOUI8021Qbg { 1017 continue 1018 } 1019 switch o.SubType { 1020 case LLDP8021QbgEVB: 1021 if err = checkLLDPOrgSpecificLen(o, 9); err != nil { 1022 return 1023 } 1024 info.EVBSettings.Supported = getEVBCapabilities(binary.BigEndian.Uint16(o.Info[0:2])) 1025 info.EVBSettings.Enabled = getEVBCapabilities(binary.BigEndian.Uint16(o.Info[2:4])) 1026 info.EVBSettings.SupportedVSIs = binary.BigEndian.Uint16(o.Info[4:6]) 1027 info.EVBSettings.ConfiguredVSIs = binary.BigEndian.Uint16(o.Info[6:8]) 1028 info.EVBSettings.RTEExponent = uint8(o.Info[8]) 1029 } 1030 } 1031 return 1032 } 1033 1034 func (l *LinkLayerDiscoveryInfo) DecodeMedia() (info LLDPInfoMedia, err error) { 1035 for _, o := range l.OrgTLVs { 1036 if o.OUI != IEEEOUIMedia { 1037 continue 1038 } 1039 switch LLDPMediaSubtype(o.SubType) { 1040 case LLDPMediaTypeCapabilities: 1041 if err = checkLLDPOrgSpecificLen(o, 3); err != nil { 1042 return 1043 } 1044 b := binary.BigEndian.Uint16(o.Info[0:2]) 1045 info.MediaCapabilities.Capabilities = (b & LLDPMediaCapsLLDP) > 0 1046 info.MediaCapabilities.NetworkPolicy = (b & LLDPMediaCapsNetwork) > 0 1047 info.MediaCapabilities.Location = (b & LLDPMediaCapsLocation) > 0 1048 info.MediaCapabilities.PowerPSE = (b & LLDPMediaCapsPowerPSE) > 0 1049 info.MediaCapabilities.PowerPD = (b & LLDPMediaCapsPowerPD) > 0 1050 info.MediaCapabilities.Inventory = (b & LLDPMediaCapsInventory) > 0 1051 info.MediaCapabilities.Class = LLDPMediaClass(o.Info[2]) 1052 case LLDPMediaTypeNetwork: 1053 if err = checkLLDPOrgSpecificLen(o, 4); err != nil { 1054 return 1055 } 1056 info.NetworkPolicy.ApplicationType = LLDPApplicationType(o.Info[0]) 1057 b := binary.BigEndian.Uint16(o.Info[1:3]) 1058 info.NetworkPolicy.Defined = (b & 0x8000) == 0 1059 info.NetworkPolicy.Tagged = (b & 0x4000) > 0 1060 info.NetworkPolicy.VLANId = (b & 0x1ffe) >> 1 1061 b = binary.BigEndian.Uint16(o.Info[2:4]) 1062 info.NetworkPolicy.L2Priority = (b & 0x01c0) >> 6 1063 info.NetworkPolicy.DSCPValue = uint8(o.Info[3] & 0x3f) 1064 case LLDPMediaTypeLocation: 1065 if err = checkLLDPOrgSpecificLen(o, 1); err != nil { 1066 return 1067 } 1068 info.Location.Format = LLDPLocationFormat(o.Info[0]) 1069 o.Info = o.Info[1:] 1070 switch info.Location.Format { 1071 case LLDPLocationFormatCoordinate: 1072 if err = checkLLDPOrgSpecificLen(o, 16); err != nil { 1073 return 1074 } 1075 info.Location.Coordinate.LatitudeResolution = uint8(o.Info[0]&0xfc) >> 2 1076 b := binary.BigEndian.Uint64(o.Info[0:8]) 1077 info.Location.Coordinate.Latitude = (b & 0x03ffffffff000000) >> 24 1078 info.Location.Coordinate.LongitudeResolution = uint8(o.Info[5]&0xfc) >> 2 1079 b = binary.BigEndian.Uint64(o.Info[5:13]) 1080 info.Location.Coordinate.Longitude = (b & 0x03ffffffff000000) >> 24 1081 info.Location.Coordinate.AltitudeType = uint8((o.Info[10] & 0x30) >> 4) 1082 b1 := binary.BigEndian.Uint16(o.Info[10:12]) 1083 info.Location.Coordinate.AltitudeResolution = (b1 & 0xfc0) >> 6 1084 b2 := binary.BigEndian.Uint32(o.Info[11:15]) 1085 info.Location.Coordinate.Altitude = b2 & 0x3fffffff 1086 info.Location.Coordinate.Datum = uint8(o.Info[15]) 1087 case LLDPLocationFormatAddress: 1088 if err = checkLLDPOrgSpecificLen(o, 3); err != nil { 1089 return 1090 } 1091 //ll := uint8(o.Info[0]) 1092 info.Location.Address.What = LLDPLocationAddressWhat(o.Info[1]) 1093 info.Location.Address.CountryCode = string(o.Info[2:4]) 1094 data := o.Info[4:] 1095 for len(data) > 1 { 1096 aType := LLDPLocationAddressType(data[0]) 1097 aLen := int(data[1]) 1098 if len(data) >= aLen+2 { 1099 info.Location.Address.AddressLines = append(info.Location.Address.AddressLines, LLDPLocationAddressLine{aType, string(data[2 : aLen+2])}) 1100 data = data[aLen+2:] 1101 } else { 1102 break 1103 } 1104 } 1105 case LLDPLocationFormatECS: 1106 info.Location.ECS.ELIN = string(o.Info) 1107 } 1108 case LLDPMediaTypePower: 1109 if err = checkLLDPOrgSpecificLen(o, 3); err != nil { 1110 return 1111 } 1112 info.PowerViaMDI.Type = LLDPPowerType((o.Info[0] & 0xc0) >> 6) 1113 info.PowerViaMDI.Source = LLDPPowerSource((o.Info[0] & 0x30) >> 4) 1114 if info.PowerViaMDI.Type == 1 || info.PowerViaMDI.Type == 3 { 1115 info.PowerViaMDI.Source += 128 // For Stringify purposes 1116 } 1117 info.PowerViaMDI.Priority = LLDPPowerPriority(o.Info[0] & 0x0f) 1118 info.PowerViaMDI.Value = binary.BigEndian.Uint16(o.Info[1:3]) * 100 // 0 to 102.3 w, 0.1W increments 1119 case LLDPMediaTypeHardware: 1120 info.HardwareRevision = string(o.Info) 1121 case LLDPMediaTypeFirmware: 1122 info.FirmwareRevision = string(o.Info) 1123 case LLDPMediaTypeSoftware: 1124 info.SoftwareRevision = string(o.Info) 1125 case LLDPMediaTypeSerial: 1126 info.SerialNumber = string(o.Info) 1127 case LLDPMediaTypeManufacturer: 1128 info.Manufacturer = string(o.Info) 1129 case LLDPMediaTypeModel: 1130 info.Model = string(o.Info) 1131 case LLDPMediaTypeAssetID: 1132 info.AssetID = string(o.Info) 1133 } 1134 } 1135 return 1136 } 1137 1138 func (l *LinkLayerDiscoveryInfo) DecodeCisco2() (info LLDPInfoCisco2, err error) { 1139 for _, o := range l.OrgTLVs { 1140 if o.OUI != IEEEOUICisco2 { 1141 continue 1142 } 1143 switch LLDPCisco2Subtype(o.SubType) { 1144 case LLDPCisco2PowerViaMDI: 1145 if err = checkLLDPOrgSpecificLen(o, 1); err != nil { 1146 return 1147 } 1148 info.PSEFourWirePoESupported = (o.Info[0] & LLDPCiscoPSESupport) > 0 1149 info.PDSparePairArchitectureShared = (o.Info[0] & LLDPCiscoArchShared) > 0 1150 info.PDRequestSparePairPoEOn = (o.Info[0] & LLDPCiscoPDSparePair) > 0 1151 info.PSESparePairPoEOn = (o.Info[0] & LLDPCiscoPSESparePair) > 0 1152 } 1153 } 1154 return 1155 } 1156 1157 func (l *LinkLayerDiscoveryInfo) DecodeProfinet() (info LLDPInfoProfinet, err error) { 1158 for _, o := range l.OrgTLVs { 1159 if o.OUI != IEEEOUIProfinet { 1160 continue 1161 } 1162 switch LLDPProfinetSubtype(o.SubType) { 1163 case LLDPProfinetPNIODelay: 1164 if err = checkLLDPOrgSpecificLen(o, 20); err != nil { 1165 return 1166 } 1167 info.PNIODelay.RXLocal = binary.BigEndian.Uint32(o.Info[0:4]) 1168 info.PNIODelay.RXRemote = binary.BigEndian.Uint32(o.Info[4:8]) 1169 info.PNIODelay.TXLocal = binary.BigEndian.Uint32(o.Info[8:12]) 1170 info.PNIODelay.TXRemote = binary.BigEndian.Uint32(o.Info[12:16]) 1171 info.PNIODelay.CableLocal = binary.BigEndian.Uint32(o.Info[16:20]) 1172 case LLDPProfinetPNIOPortStatus: 1173 if err = checkLLDPOrgSpecificLen(o, 4); err != nil { 1174 return 1175 } 1176 info.PNIOPortStatus.Class2 = binary.BigEndian.Uint16(o.Info[0:2]) 1177 info.PNIOPortStatus.Class3 = binary.BigEndian.Uint16(o.Info[2:4]) 1178 case LLDPProfinetPNIOMRPPortStatus: 1179 if err = checkLLDPOrgSpecificLen(o, 18); err != nil { 1180 return 1181 } 1182 info.PNIOMRPPortStatus.UUID = o.Info[0:16] 1183 info.PNIOMRPPortStatus.Status = binary.BigEndian.Uint16(o.Info[16:18]) 1184 case LLDPProfinetPNIOChassisMAC: 1185 if err = checkLLDPOrgSpecificLen(o, 6); err != nil { 1186 return 1187 } 1188 info.ChassisMAC = o.Info[0:6] 1189 case LLDPProfinetPNIOPTCPStatus: 1190 if err = checkLLDPOrgSpecificLen(o, 54); err != nil { 1191 return 1192 } 1193 info.PNIOPTCPStatus.MasterAddress = o.Info[0:6] 1194 info.PNIOPTCPStatus.SubdomainUUID = o.Info[6:22] 1195 info.PNIOPTCPStatus.IRDataUUID = o.Info[22:38] 1196 b := binary.BigEndian.Uint32(o.Info[38:42]) 1197 info.PNIOPTCPStatus.PeriodValid = (b & 0x80000000) > 0 1198 info.PNIOPTCPStatus.PeriodLength = b & 0x7fffffff 1199 b = binary.BigEndian.Uint32(o.Info[42:46]) 1200 info.PNIOPTCPStatus.RedPeriodValid = (b & 0x80000000) > 0 1201 info.PNIOPTCPStatus.RedPeriodBegin = b & 0x7fffffff 1202 b = binary.BigEndian.Uint32(o.Info[46:50]) 1203 info.PNIOPTCPStatus.OrangePeriodValid = (b & 0x80000000) > 0 1204 info.PNIOPTCPStatus.OrangePeriodBegin = b & 0x7fffffff 1205 b = binary.BigEndian.Uint32(o.Info[50:54]) 1206 info.PNIOPTCPStatus.GreenPeriodValid = (b & 0x80000000) > 0 1207 info.PNIOPTCPStatus.GreenPeriodBegin = b & 0x7fffffff 1208 } 1209 } 1210 return 1211 } 1212 1213 // LayerType returns gopacket.LayerTypeLinkLayerDiscoveryInfo. 1214 func (c *LinkLayerDiscoveryInfo) LayerType() gopacket.LayerType { 1215 return LayerTypeLinkLayerDiscoveryInfo 1216 } 1217 1218 func getCapabilities(v uint16) (c LLDPCapabilities) { 1219 c.Other = (v&LLDPCapsOther > 0) 1220 c.Repeater = (v&LLDPCapsRepeater > 0) 1221 c.Bridge = (v&LLDPCapsBridge > 0) 1222 c.WLANAP = (v&LLDPCapsWLANAP > 0) 1223 c.Router = (v&LLDPCapsRouter > 0) 1224 c.Phone = (v&LLDPCapsPhone > 0) 1225 c.DocSis = (v&LLDPCapsDocSis > 0) 1226 c.StationOnly = (v&LLDPCapsStationOnly > 0) 1227 c.CVLAN = (v&LLDPCapsCVLAN > 0) 1228 c.SVLAN = (v&LLDPCapsSVLAN > 0) 1229 c.TMPR = (v&LLDPCapsTmpr > 0) 1230 return 1231 } 1232 1233 func getEVBCapabilities(v uint16) (c LLDPEVBCapabilities) { 1234 c.StandardBridging = (v & LLDPEVBCapsSTD) > 0 1235 c.StandardBridging = (v & LLDPEVBCapsSTD) > 0 1236 c.ReflectiveRelay = (v & LLDPEVBCapsRR) > 0 1237 c.RetransmissionTimerExponent = (v & LLDPEVBCapsRTE) > 0 1238 c.EdgeControlProtocol = (v & LLDPEVBCapsECP) > 0 1239 c.VSIDiscoveryProtocol = (v & LLDPEVBCapsVDP) > 0 1240 return 1241 } 1242 1243 func (t LLDPTLVType) String() (s string) { 1244 switch t { 1245 case LLDPTLVEnd: 1246 s = "TLV End" 1247 case LLDPTLVChassisID: 1248 s = "Chassis ID" 1249 case LLDPTLVPortID: 1250 s = "Port ID" 1251 case LLDPTLVTTL: 1252 s = "TTL" 1253 case LLDPTLVPortDescription: 1254 s = "Port Description" 1255 case LLDPTLVSysName: 1256 s = "System Name" 1257 case LLDPTLVSysDescription: 1258 s = "System Description" 1259 case LLDPTLVSysCapabilities: 1260 s = "System Capabilities" 1261 case LLDPTLVMgmtAddress: 1262 s = "Management Address" 1263 case LLDPTLVOrgSpecific: 1264 s = "Organisation Specific" 1265 default: 1266 s = "Unknown" 1267 } 1268 return 1269 } 1270 1271 func (t LLDPChassisIDSubType) String() (s string) { 1272 switch t { 1273 case LLDPChassisIDSubTypeReserved: 1274 s = "Reserved" 1275 case LLDPChassisIDSubTypeChassisComp: 1276 s = "Chassis Component" 1277 case LLDPChassisIDSubtypeIfaceAlias: 1278 s = "Interface Alias" 1279 case LLDPChassisIDSubTypePortComp: 1280 s = "Port Component" 1281 case LLDPChassisIDSubTypeMACAddr: 1282 s = "MAC Address" 1283 case LLDPChassisIDSubTypeNetworkAddr: 1284 s = "Network Address" 1285 case LLDPChassisIDSubtypeIfaceName: 1286 s = "Interface Name" 1287 case LLDPChassisIDSubTypeLocal: 1288 s = "Local" 1289 default: 1290 s = "Unknown" 1291 } 1292 return 1293 } 1294 1295 func (t LLDPPortIDSubType) String() (s string) { 1296 switch t { 1297 case LLDPPortIDSubtypeReserved: 1298 s = "Reserved" 1299 case LLDPPortIDSubtypeIfaceAlias: 1300 s = "Interface Alias" 1301 case LLDPPortIDSubtypePortComp: 1302 s = "Port Component" 1303 case LLDPPortIDSubtypeMACAddr: 1304 s = "MAC Address" 1305 case LLDPPortIDSubtypeNetworkAddr: 1306 s = "Network Address" 1307 case LLDPPortIDSubtypeIfaceName: 1308 s = "Interface Name" 1309 case LLDPPortIDSubtypeAgentCircuitID: 1310 s = "Agent Circuit ID" 1311 case LLDPPortIDSubtypeLocal: 1312 s = "Local" 1313 default: 1314 s = "Unknown" 1315 } 1316 return 1317 } 1318 1319 func (t IANAAddressFamily) String() (s string) { 1320 switch t { 1321 case IANAAddressFamilyReserved: 1322 s = "Reserved" 1323 case IANAAddressFamilyIPV4: 1324 s = "IPv4" 1325 case IANAAddressFamilyIPV6: 1326 s = "IPv6" 1327 case IANAAddressFamilyNSAP: 1328 s = "NSAP" 1329 case IANAAddressFamilyHDLC: 1330 s = "HDLC" 1331 case IANAAddressFamilyBBN1822: 1332 s = "BBN 1822" 1333 case IANAAddressFamily802: 1334 s = "802 media plus Ethernet 'canonical format'" 1335 case IANAAddressFamilyE163: 1336 s = "E.163" 1337 case IANAAddressFamilyE164: 1338 s = "E.164 (SMDS, Frame Relay, ATM)" 1339 case IANAAddressFamilyF69: 1340 s = "F.69 (Telex)" 1341 case IANAAddressFamilyX121: 1342 s = "X.121, X.25, Frame Relay" 1343 case IANAAddressFamilyIPX: 1344 s = "IPX" 1345 case IANAAddressFamilyAtalk: 1346 s = "Appletalk" 1347 case IANAAddressFamilyDecnet: 1348 s = "Decnet IV" 1349 case IANAAddressFamilyBanyan: 1350 s = "Banyan Vines" 1351 case IANAAddressFamilyE164NSAP: 1352 s = "E.164 with NSAP format subaddress" 1353 case IANAAddressFamilyDNS: 1354 s = "DNS" 1355 case IANAAddressFamilyDistname: 1356 s = "Distinguished Name" 1357 case IANAAddressFamilyASNumber: 1358 s = "AS Number" 1359 case IANAAddressFamilyXTPIPV4: 1360 s = "XTP over IP version 4" 1361 case IANAAddressFamilyXTPIPV6: 1362 s = "XTP over IP version 6" 1363 case IANAAddressFamilyXTP: 1364 s = "XTP native mode XTP" 1365 case IANAAddressFamilyFcWWPN: 1366 s = "Fibre Channel World-Wide Port Name" 1367 case IANAAddressFamilyFcWWNN: 1368 s = "Fibre Channel World-Wide Node Name" 1369 case IANAAddressFamilyGWID: 1370 s = "GWID" 1371 case IANAAddressFamilyL2VPN: 1372 s = "AFI for Layer 2 VPN" 1373 default: 1374 s = "Unknown" 1375 } 1376 return 1377 } 1378 1379 func (t LLDPInterfaceSubtype) String() (s string) { 1380 switch t { 1381 case LLDPInterfaceSubtypeUnknown: 1382 s = "Unknown" 1383 case LLDPInterfaceSubtypeifIndex: 1384 s = "IfIndex" 1385 case LLDPInterfaceSubtypeSysPort: 1386 s = "System Port Number" 1387 default: 1388 s = "Unknown" 1389 } 1390 return 1391 } 1392 1393 func (t LLDPPowerType) String() (s string) { 1394 switch t { 1395 case 0: 1396 s = "Type 2 PSE Device" 1397 case 1: 1398 s = "Type 2 PD Device" 1399 case 2: 1400 s = "Type 1 PSE Device" 1401 case 3: 1402 s = "Type 1 PD Device" 1403 default: 1404 s = "Unknown" 1405 } 1406 return 1407 } 1408 1409 func (t LLDPPowerSource) String() (s string) { 1410 switch t { 1411 // PD Device 1412 case 0: 1413 s = "Unknown" 1414 case 1: 1415 s = "PSE" 1416 case 2: 1417 s = "Local" 1418 case 3: 1419 s = "PSE and Local" 1420 // PSE Device (Actual value + 128) 1421 case 128: 1422 s = "Unknown" 1423 case 129: 1424 s = "Primary Power Source" 1425 case 130: 1426 s = "Backup Power Source" 1427 default: 1428 s = "Unknown" 1429 } 1430 return 1431 } 1432 1433 func (t LLDPPowerPriority) String() (s string) { 1434 switch t { 1435 case 0: 1436 s = "Unknown" 1437 case 1: 1438 s = "Critical" 1439 case 2: 1440 s = "High" 1441 case 3: 1442 s = "Low" 1443 default: 1444 s = "Unknown" 1445 } 1446 return 1447 } 1448 1449 func (t LLDPMediaSubtype) String() (s string) { 1450 switch t { 1451 case LLDPMediaTypeCapabilities: 1452 s = "Media Capabilities" 1453 case LLDPMediaTypeNetwork: 1454 s = "Network Policy" 1455 case LLDPMediaTypeLocation: 1456 s = "Location Identification" 1457 case LLDPMediaTypePower: 1458 s = "Extended Power-via-MDI" 1459 case LLDPMediaTypeHardware: 1460 s = "Hardware Revision" 1461 case LLDPMediaTypeFirmware: 1462 s = "Firmware Revision" 1463 case LLDPMediaTypeSoftware: 1464 s = "Software Revision" 1465 case LLDPMediaTypeSerial: 1466 s = "Serial Number" 1467 case LLDPMediaTypeManufacturer: 1468 s = "Manufacturer" 1469 case LLDPMediaTypeModel: 1470 s = "Model" 1471 case LLDPMediaTypeAssetID: 1472 s = "Asset ID" 1473 default: 1474 s = "Unknown" 1475 } 1476 return 1477 } 1478 1479 func (t LLDPMediaClass) String() (s string) { 1480 switch t { 1481 case LLDPMediaClassUndefined: 1482 s = "Undefined" 1483 case LLDPMediaClassEndpointI: 1484 s = "Endpoint Class I" 1485 case LLDPMediaClassEndpointII: 1486 s = "Endpoint Class II" 1487 case LLDPMediaClassEndpointIII: 1488 s = "Endpoint Class III" 1489 case LLDPMediaClassNetwork: 1490 s = "Network Connectivity" 1491 default: 1492 s = "Unknown" 1493 } 1494 return 1495 } 1496 1497 func (t LLDPApplicationType) String() (s string) { 1498 switch t { 1499 case LLDPAppTypeReserved: 1500 s = "Reserved" 1501 case LLDPAppTypeVoice: 1502 s = "Voice" 1503 case LLDPappTypeVoiceSignaling: 1504 s = "Voice Signaling" 1505 case LLDPappTypeGuestVoice: 1506 s = "Guest Voice" 1507 case LLDPappTypeGuestVoiceSignaling: 1508 s = "Guest Voice Signaling" 1509 case LLDPappTypeSoftphoneVoice: 1510 s = "Softphone Voice" 1511 case LLDPappTypeVideoConferencing: 1512 s = "Video Conferencing" 1513 case LLDPappTypeStreamingVideo: 1514 s = "Streaming Video" 1515 case LLDPappTypeVideoSignaling: 1516 s = "Video Signaling" 1517 default: 1518 s = "Unknown" 1519 } 1520 return 1521 } 1522 1523 func (t LLDPLocationFormat) String() (s string) { 1524 switch t { 1525 case LLDPLocationFormatInvalid: 1526 s = "Invalid" 1527 case LLDPLocationFormatCoordinate: 1528 s = "Coordinate-based LCI" 1529 case LLDPLocationFormatAddress: 1530 s = "Address-based LCO" 1531 case LLDPLocationFormatECS: 1532 s = "ECS ELIN" 1533 default: 1534 s = "Unknown" 1535 } 1536 return 1537 } 1538 1539 func (t LLDPLocationAddressType) String() (s string) { 1540 switch t { 1541 case LLDPLocationAddressTypeLanguage: 1542 s = "Language" 1543 case LLDPLocationAddressTypeNational: 1544 s = "National subdivisions (province, state, etc)" 1545 case LLDPLocationAddressTypeCounty: 1546 s = "County, parish, district" 1547 case LLDPLocationAddressTypeCity: 1548 s = "City, township" 1549 case LLDPLocationAddressTypeCityDivision: 1550 s = "City division, borough, ward" 1551 case LLDPLocationAddressTypeNeighborhood: 1552 s = "Neighborhood, block" 1553 case LLDPLocationAddressTypeStreet: 1554 s = "Street" 1555 case LLDPLocationAddressTypeLeadingStreet: 1556 s = "Leading street direction" 1557 case LLDPLocationAddressTypeTrailingStreet: 1558 s = "Trailing street suffix" 1559 case LLDPLocationAddressTypeStreetSuffix: 1560 s = "Street suffix" 1561 case LLDPLocationAddressTypeHouseNum: 1562 s = "House number" 1563 case LLDPLocationAddressTypeHouseSuffix: 1564 s = "House number suffix" 1565 case LLDPLocationAddressTypeLandmark: 1566 s = "Landmark or vanity address" 1567 case LLDPLocationAddressTypeAdditional: 1568 s = "Additional location information" 1569 case LLDPLocationAddressTypeName: 1570 s = "Name" 1571 case LLDPLocationAddressTypePostal: 1572 s = "Postal/ZIP code" 1573 case LLDPLocationAddressTypeBuilding: 1574 s = "Building" 1575 case LLDPLocationAddressTypeUnit: 1576 s = "Unit" 1577 case LLDPLocationAddressTypeFloor: 1578 s = "Floor" 1579 case LLDPLocationAddressTypeRoom: 1580 s = "Room number" 1581 case LLDPLocationAddressTypePlace: 1582 s = "Place type" 1583 case LLDPLocationAddressTypeScript: 1584 s = "Script" 1585 default: 1586 s = "Unknown" 1587 } 1588 return 1589 } 1590 1591 func checkLLDPTLVLen(v LinkLayerDiscoveryValue, l int) (err error) { 1592 if len(v.Value) < l { 1593 err = fmt.Errorf("Invalid TLV %v length %d (wanted mimimum %v", v.Type, len(v.Value), l) 1594 } 1595 return 1596 } 1597 1598 func checkLLDPOrgSpecificLen(o LLDPOrgSpecificTLV, l int) (err error) { 1599 if len(o.Info) < l { 1600 err = fmt.Errorf("Invalid Org Specific TLV %v length %d (wanted minimum %v)", o.SubType, len(o.Info), l) 1601 } 1602 return 1603 }