// Copyright 2012 Google, Inc. All rights reserved. // // Use of this source code is governed by a BSD-style license // that can be found in the LICENSE file in the root of the source // tree. package layers import ( "encoding/binary" "errors" "fmt" "github.com/google/gopacket" ) // LLDPTLVType is the type of each TLV value in a LinkLayerDiscovery packet. type LLDPTLVType byte const ( LLDPTLVEnd LLDPTLVType = 0 LLDPTLVChassisID LLDPTLVType = 1 LLDPTLVPortID LLDPTLVType = 2 LLDPTLVTTL LLDPTLVType = 3 LLDPTLVPortDescription LLDPTLVType = 4 LLDPTLVSysName LLDPTLVType = 5 LLDPTLVSysDescription LLDPTLVType = 6 LLDPTLVSysCapabilities LLDPTLVType = 7 LLDPTLVMgmtAddress LLDPTLVType = 8 LLDPTLVOrgSpecific LLDPTLVType = 127 ) // LinkLayerDiscoveryValue is a TLV value inside a LinkLayerDiscovery packet layer. type LinkLayerDiscoveryValue struct { Type LLDPTLVType Length uint16 Value []byte } // LLDPChassisIDSubType specifies the value type for a single LLDPChassisID.ID type LLDPChassisIDSubType byte // LLDP Chassis Types const ( LLDPChassisIDSubTypeReserved LLDPChassisIDSubType = 0 LLDPChassisIDSubTypeChassisComp LLDPChassisIDSubType = 1 LLDPChassisIDSubtypeIfaceAlias LLDPChassisIDSubType = 2 LLDPChassisIDSubTypePortComp LLDPChassisIDSubType = 3 LLDPChassisIDSubTypeMACAddr LLDPChassisIDSubType = 4 LLDPChassisIDSubTypeNetworkAddr LLDPChassisIDSubType = 5 LLDPChassisIDSubtypeIfaceName LLDPChassisIDSubType = 6 LLDPChassisIDSubTypeLocal LLDPChassisIDSubType = 7 ) type LLDPChassisID struct { Subtype LLDPChassisIDSubType ID []byte } // LLDPPortIDSubType specifies the value type for a single LLDPPortID.ID type LLDPPortIDSubType byte // LLDP PortID types const ( LLDPPortIDSubtypeReserved LLDPPortIDSubType = 0 LLDPPortIDSubtypeIfaceAlias LLDPPortIDSubType = 1 LLDPPortIDSubtypePortComp LLDPPortIDSubType = 2 LLDPPortIDSubtypeMACAddr LLDPPortIDSubType = 3 LLDPPortIDSubtypeNetworkAddr LLDPPortIDSubType = 4 LLDPPortIDSubtypeIfaceName LLDPPortIDSubType = 5 LLDPPortIDSubtypeAgentCircuitID LLDPPortIDSubType = 6 LLDPPortIDSubtypeLocal LLDPPortIDSubType = 7 ) type LLDPPortID struct { Subtype LLDPPortIDSubType ID []byte } // LinkLayerDiscovery is a packet layer containing the LinkLayer Discovery Protocol. // See http:http://standards.ieee.org/getieee802/download/802.1AB-2009.pdf // ChassisID, PortID and TTL are mandatory TLV's. Other values can be decoded // with DecodeValues() type LinkLayerDiscovery struct { BaseLayer ChassisID LLDPChassisID PortID LLDPPortID TTL uint16 Values []LinkLayerDiscoveryValue } type IEEEOUI uint32 // http://standards.ieee.org/develop/regauth/oui/oui.txt const ( IEEEOUI8021 IEEEOUI = 0x0080c2 IEEEOUI8023 IEEEOUI = 0x00120f IEEEOUI80211 IEEEOUI = 0x000fac IEEEOUI8021Qbg IEEEOUI = 0x0013BF IEEEOUICisco2 IEEEOUI = 0x000142 IEEEOUIMedia IEEEOUI = 0x0012bb // TR-41 IEEEOUIProfinet IEEEOUI = 0x000ecf IEEEOUIDCBX IEEEOUI = 0x001b21 ) // LLDPOrgSpecificTLV is an Organisation-specific TLV type LLDPOrgSpecificTLV struct { OUI IEEEOUI SubType uint8 Info []byte } // LLDPCapabilities Types const ( LLDPCapsOther uint16 = 1 << 0 LLDPCapsRepeater uint16 = 1 << 1 LLDPCapsBridge uint16 = 1 << 2 LLDPCapsWLANAP uint16 = 1 << 3 LLDPCapsRouter uint16 = 1 << 4 LLDPCapsPhone uint16 = 1 << 5 LLDPCapsDocSis uint16 = 1 << 6 LLDPCapsStationOnly uint16 = 1 << 7 LLDPCapsCVLAN uint16 = 1 << 8 LLDPCapsSVLAN uint16 = 1 << 9 LLDPCapsTmpr uint16 = 1 << 10 ) // LLDPCapabilities represents the capabilities of a device type LLDPCapabilities struct { Other bool Repeater bool Bridge bool WLANAP bool Router bool Phone bool DocSis bool StationOnly bool CVLAN bool SVLAN bool TMPR bool } type LLDPSysCapabilities struct { SystemCap LLDPCapabilities EnabledCap LLDPCapabilities } type IANAAddressFamily byte // LLDP Management Address Subtypes // http://www.iana.org/assignments/address-family-numbers/address-family-numbers.xml const ( IANAAddressFamilyReserved IANAAddressFamily = 0 IANAAddressFamilyIPV4 IANAAddressFamily = 1 IANAAddressFamilyIPV6 IANAAddressFamily = 2 IANAAddressFamilyNSAP IANAAddressFamily = 3 IANAAddressFamilyHDLC IANAAddressFamily = 4 IANAAddressFamilyBBN1822 IANAAddressFamily = 5 IANAAddressFamily802 IANAAddressFamily = 6 IANAAddressFamilyE163 IANAAddressFamily = 7 IANAAddressFamilyE164 IANAAddressFamily = 8 IANAAddressFamilyF69 IANAAddressFamily = 9 IANAAddressFamilyX121 IANAAddressFamily = 10 IANAAddressFamilyIPX IANAAddressFamily = 11 IANAAddressFamilyAtalk IANAAddressFamily = 12 IANAAddressFamilyDecnet IANAAddressFamily = 13 IANAAddressFamilyBanyan IANAAddressFamily = 14 IANAAddressFamilyE164NSAP IANAAddressFamily = 15 IANAAddressFamilyDNS IANAAddressFamily = 16 IANAAddressFamilyDistname IANAAddressFamily = 17 IANAAddressFamilyASNumber IANAAddressFamily = 18 IANAAddressFamilyXTPIPV4 IANAAddressFamily = 19 IANAAddressFamilyXTPIPV6 IANAAddressFamily = 20 IANAAddressFamilyXTP IANAAddressFamily = 21 IANAAddressFamilyFcWWPN IANAAddressFamily = 22 IANAAddressFamilyFcWWNN IANAAddressFamily = 23 IANAAddressFamilyGWID IANAAddressFamily = 24 IANAAddressFamilyL2VPN IANAAddressFamily = 25 ) type LLDPInterfaceSubtype byte // LLDP Interface Subtypes const ( LLDPInterfaceSubtypeUnknown LLDPInterfaceSubtype = 1 LLDPInterfaceSubtypeifIndex LLDPInterfaceSubtype = 2 LLDPInterfaceSubtypeSysPort LLDPInterfaceSubtype = 3 ) type LLDPMgmtAddress struct { Subtype IANAAddressFamily Address []byte InterfaceSubtype LLDPInterfaceSubtype InterfaceNumber uint32 OID string } // LinkLayerDiscoveryInfo represents the decoded details for a set of LinkLayerDiscoveryValues // Organisation-specific TLV's can be decoded using the various Decode() methods type LinkLayerDiscoveryInfo struct { BaseLayer PortDescription string SysName string SysDescription string SysCapabilities LLDPSysCapabilities MgmtAddress LLDPMgmtAddress OrgTLVs []LLDPOrgSpecificTLV // Private TLVs Unknown []LinkLayerDiscoveryValue // undecoded TLVs } /// IEEE 802.1 TLV Subtypes const ( LLDP8021SubtypePortVLANID uint8 = 1 LLDP8021SubtypeProtocolVLANID uint8 = 2 LLDP8021SubtypeVLANName uint8 = 3 LLDP8021SubtypeProtocolIdentity uint8 = 4 LLDP8021SubtypeVDIUsageDigest uint8 = 5 LLDP8021SubtypeManagementVID uint8 = 6 LLDP8021SubtypeLinkAggregation uint8 = 7 ) // VLAN Port Protocol ID options const ( LLDPProtocolVLANIDCapability byte = 1 << 1 LLDPProtocolVLANIDStatus byte = 1 << 2 ) type PortProtocolVLANID struct { Supported bool Enabled bool ID uint16 } type VLANName struct { ID uint16 Name string } type ProtocolIdentity []byte // LACP options const ( LLDPAggregationCapability byte = 1 << 0 LLDPAggregationStatus byte = 1 << 1 ) // IEEE 802 Link Aggregation parameters type LLDPLinkAggregation struct { Supported bool Enabled bool PortID uint32 } // LLDPInfo8021 represents the information carried in 802.1 Org-specific TLVs type LLDPInfo8021 struct { PVID uint16 PPVIDs []PortProtocolVLANID VLANNames []VLANName ProtocolIdentities []ProtocolIdentity VIDUsageDigest uint32 ManagementVID uint16 LinkAggregation LLDPLinkAggregation } // IEEE 802.3 TLV Subtypes const ( LLDP8023SubtypeMACPHY uint8 = 1 LLDP8023SubtypeMDIPower uint8 = 2 LLDP8023SubtypeLinkAggregation uint8 = 3 LLDP8023SubtypeMTU uint8 = 4 ) // MACPHY options const ( LLDPMACPHYCapability byte = 1 << 0 LLDPMACPHYStatus byte = 1 << 1 ) // From IANA-MAU-MIB (introduced by RFC 4836) - dot3MauType const ( LLDPMAUTypeUnknown uint16 = 0 LLDPMAUTypeAUI uint16 = 1 LLDPMAUType10Base5 uint16 = 2 LLDPMAUTypeFOIRL uint16 = 3 LLDPMAUType10Base2 uint16 = 4 LLDPMAUType10BaseT uint16 = 5 LLDPMAUType10BaseFP uint16 = 6 LLDPMAUType10BaseFB uint16 = 7 LLDPMAUType10BaseFL uint16 = 8 LLDPMAUType10BROAD36 uint16 = 9 LLDPMAUType10BaseT_HD uint16 = 10 LLDPMAUType10BaseT_FD uint16 = 11 LLDPMAUType10BaseFL_HD uint16 = 12 LLDPMAUType10BaseFL_FD uint16 = 13 LLDPMAUType100BaseT4 uint16 = 14 LLDPMAUType100BaseTX_HD uint16 = 15 LLDPMAUType100BaseTX_FD uint16 = 16 LLDPMAUType100BaseFX_HD uint16 = 17 LLDPMAUType100BaseFX_FD uint16 = 18 LLDPMAUType100BaseT2_HD uint16 = 19 LLDPMAUType100BaseT2_FD uint16 = 20 LLDPMAUType1000BaseX_HD uint16 = 21 LLDPMAUType1000BaseX_FD uint16 = 22 LLDPMAUType1000BaseLX_HD uint16 = 23 LLDPMAUType1000BaseLX_FD uint16 = 24 LLDPMAUType1000BaseSX_HD uint16 = 25 LLDPMAUType1000BaseSX_FD uint16 = 26 LLDPMAUType1000BaseCX_HD uint16 = 27 LLDPMAUType1000BaseCX_FD uint16 = 28 LLDPMAUType1000BaseT_HD uint16 = 29 LLDPMAUType1000BaseT_FD uint16 = 30 LLDPMAUType10GBaseX uint16 = 31 LLDPMAUType10GBaseLX4 uint16 = 32 LLDPMAUType10GBaseR uint16 = 33 LLDPMAUType10GBaseER uint16 = 34 LLDPMAUType10GBaseLR uint16 = 35 LLDPMAUType10GBaseSR uint16 = 36 LLDPMAUType10GBaseW uint16 = 37 LLDPMAUType10GBaseEW uint16 = 38 LLDPMAUType10GBaseLW uint16 = 39 LLDPMAUType10GBaseSW uint16 = 40 LLDPMAUType10GBaseCX4 uint16 = 41 LLDPMAUType2BaseTL uint16 = 42 LLDPMAUType10PASS_TS uint16 = 43 LLDPMAUType100BaseBX10D uint16 = 44 LLDPMAUType100BaseBX10U uint16 = 45 LLDPMAUType100BaseLX10 uint16 = 46 LLDPMAUType1000BaseBX10D uint16 = 47 LLDPMAUType1000BaseBX10U uint16 = 48 LLDPMAUType1000BaseLX10 uint16 = 49 LLDPMAUType1000BasePX10D uint16 = 50 LLDPMAUType1000BasePX10U uint16 = 51 LLDPMAUType1000BasePX20D uint16 = 52 LLDPMAUType1000BasePX20U uint16 = 53 LLDPMAUType10GBaseT uint16 = 54 LLDPMAUType10GBaseLRM uint16 = 55 LLDPMAUType1000BaseKX uint16 = 56 LLDPMAUType10GBaseKX4 uint16 = 57 LLDPMAUType10GBaseKR uint16 = 58 LLDPMAUType10_1GBasePRX_D1 uint16 = 59 LLDPMAUType10_1GBasePRX_D2 uint16 = 60 LLDPMAUType10_1GBasePRX_D3 uint16 = 61 LLDPMAUType10_1GBasePRX_U1 uint16 = 62 LLDPMAUType10_1GBasePRX_U2 uint16 = 63 LLDPMAUType10_1GBasePRX_U3 uint16 = 64 LLDPMAUType10GBasePR_D1 uint16 = 65 LLDPMAUType10GBasePR_D2 uint16 = 66 LLDPMAUType10GBasePR_D3 uint16 = 67 LLDPMAUType10GBasePR_U1 uint16 = 68 LLDPMAUType10GBasePR_U3 uint16 = 69 ) // From RFC 3636 - ifMauAutoNegCapAdvertisedBits const ( LLDPMAUPMDOther uint16 = 1 << 15 LLDPMAUPMD10BaseT uint16 = 1 << 14 LLDPMAUPMD10BaseT_FD uint16 = 1 << 13 LLDPMAUPMD100BaseT4 uint16 = 1 << 12 LLDPMAUPMD100BaseTX uint16 = 1 << 11 LLDPMAUPMD100BaseTX_FD uint16 = 1 << 10 LLDPMAUPMD100BaseT2 uint16 = 1 << 9 LLDPMAUPMD100BaseT2_FD uint16 = 1 << 8 LLDPMAUPMDFDXPAUSE uint16 = 1 << 7 LLDPMAUPMDFDXAPAUSE uint16 = 1 << 6 LLDPMAUPMDFDXSPAUSE uint16 = 1 << 5 LLDPMAUPMDFDXBPAUSE uint16 = 1 << 4 LLDPMAUPMD1000BaseX uint16 = 1 << 3 LLDPMAUPMD1000BaseX_FD uint16 = 1 << 2 LLDPMAUPMD1000BaseT uint16 = 1 << 1 LLDPMAUPMD1000BaseT_FD uint16 = 1 << 0 ) // Inverted ifMauAutoNegCapAdvertisedBits if required // (Some manufacturers misinterpreted the spec - // see https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=1455) const ( LLDPMAUPMDOtherInv uint16 = 1 << 0 LLDPMAUPMD10BaseTInv uint16 = 1 << 1 LLDPMAUPMD10BaseT_FDInv uint16 = 1 << 2 LLDPMAUPMD100BaseT4Inv uint16 = 1 << 3 LLDPMAUPMD100BaseTXInv uint16 = 1 << 4 LLDPMAUPMD100BaseTX_FDInv uint16 = 1 << 5 LLDPMAUPMD100BaseT2Inv uint16 = 1 << 6 LLDPMAUPMD100BaseT2_FDInv uint16 = 1 << 7 LLDPMAUPMDFDXPAUSEInv uint16 = 1 << 8 LLDPMAUPMDFDXAPAUSEInv uint16 = 1 << 9 LLDPMAUPMDFDXSPAUSEInv uint16 = 1 << 10 LLDPMAUPMDFDXBPAUSEInv uint16 = 1 << 11 LLDPMAUPMD1000BaseXInv uint16 = 1 << 12 LLDPMAUPMD1000BaseX_FDInv uint16 = 1 << 13 LLDPMAUPMD1000BaseTInv uint16 = 1 << 14 LLDPMAUPMD1000BaseT_FDInv uint16 = 1 << 15 ) type LLDPMACPHYConfigStatus struct { AutoNegSupported bool AutoNegEnabled bool AutoNegCapability uint16 MAUType uint16 } // MDI Power options const ( LLDPMDIPowerPortClass byte = 1 << 0 LLDPMDIPowerCapability byte = 1 << 1 LLDPMDIPowerStatus byte = 1 << 2 LLDPMDIPowerPairsAbility byte = 1 << 3 ) type LLDPPowerType byte type LLDPPowerSource byte type LLDPPowerPriority byte const ( LLDPPowerPriorityUnknown LLDPPowerPriority = 0 LLDPPowerPriorityMedium LLDPPowerPriority = 1 LLDPPowerPriorityHigh LLDPPowerPriority = 2 LLDPPowerPriorityLow LLDPPowerPriority = 3 ) type LLDPPowerViaMDI8023 struct { PortClassPSE bool // false = PD PSESupported bool PSEEnabled bool PSEPairsAbility bool PSEPowerPair uint8 PSEClass uint8 Type LLDPPowerType Source LLDPPowerSource Priority LLDPPowerPriority Requested uint16 // 1-510 Watts Allocated uint16 // 1-510 Watts } // LLDPInfo8023 represents the information carried in 802.3 Org-specific TLVs type LLDPInfo8023 struct { MACPHYConfigStatus LLDPMACPHYConfigStatus PowerViaMDI LLDPPowerViaMDI8023 LinkAggregation LLDPLinkAggregation MTU uint16 } // IEEE 802.1Qbg TLV Subtypes const ( LLDP8021QbgEVB uint8 = 0 LLDP8021QbgCDCP uint8 = 1 LLDP8021QbgVDP uint8 = 2 LLDP8021QbgEVB22 uint8 = 13 ) // LLDPEVBCapabilities Types const ( LLDPEVBCapsSTD uint16 = 1 << 7 LLDPEVBCapsRR uint16 = 1 << 6 LLDPEVBCapsRTE uint16 = 1 << 2 LLDPEVBCapsECP uint16 = 1 << 1 LLDPEVBCapsVDP uint16 = 1 << 0 ) // LLDPEVBCapabilities represents the EVB capabilities of a device type LLDPEVBCapabilities struct { StandardBridging bool ReflectiveRelay bool RetransmissionTimerExponent bool EdgeControlProtocol bool VSIDiscoveryProtocol bool } type LLDPEVBSettings struct { Supported LLDPEVBCapabilities Enabled LLDPEVBCapabilities SupportedVSIs uint16 ConfiguredVSIs uint16 RTEExponent uint8 } // LLDPInfo8021Qbg represents the information carried in 802.1Qbg Org-specific TLVs type LLDPInfo8021Qbg struct { EVBSettings LLDPEVBSettings } type LLDPMediaSubtype uint8 // Media TLV Subtypes const ( LLDPMediaTypeCapabilities LLDPMediaSubtype = 1 LLDPMediaTypeNetwork LLDPMediaSubtype = 2 LLDPMediaTypeLocation LLDPMediaSubtype = 3 LLDPMediaTypePower LLDPMediaSubtype = 4 LLDPMediaTypeHardware LLDPMediaSubtype = 5 LLDPMediaTypeFirmware LLDPMediaSubtype = 6 LLDPMediaTypeSoftware LLDPMediaSubtype = 7 LLDPMediaTypeSerial LLDPMediaSubtype = 8 LLDPMediaTypeManufacturer LLDPMediaSubtype = 9 LLDPMediaTypeModel LLDPMediaSubtype = 10 LLDPMediaTypeAssetID LLDPMediaSubtype = 11 ) type LLDPMediaClass uint8 // Media Class Values const ( LLDPMediaClassUndefined LLDPMediaClass = 0 LLDPMediaClassEndpointI LLDPMediaClass = 1 LLDPMediaClassEndpointII LLDPMediaClass = 2 LLDPMediaClassEndpointIII LLDPMediaClass = 3 LLDPMediaClassNetwork LLDPMediaClass = 4 ) // LLDPMediaCapabilities Types const ( LLDPMediaCapsLLDP uint16 = 1 << 0 LLDPMediaCapsNetwork uint16 = 1 << 1 LLDPMediaCapsLocation uint16 = 1 << 2 LLDPMediaCapsPowerPSE uint16 = 1 << 3 LLDPMediaCapsPowerPD uint16 = 1 << 4 LLDPMediaCapsInventory uint16 = 1 << 5 ) // LLDPMediaCapabilities represents the LLDP Media capabilities of a device type LLDPMediaCapabilities struct { Capabilities bool NetworkPolicy bool Location bool PowerPSE bool PowerPD bool Inventory bool Class LLDPMediaClass } type LLDPApplicationType uint8 const ( LLDPAppTypeReserved LLDPApplicationType = 0 LLDPAppTypeVoice LLDPApplicationType = 1 LLDPappTypeVoiceSignaling LLDPApplicationType = 2 LLDPappTypeGuestVoice LLDPApplicationType = 3 LLDPappTypeGuestVoiceSignaling LLDPApplicationType = 4 LLDPappTypeSoftphoneVoice LLDPApplicationType = 5 LLDPappTypeVideoConferencing LLDPApplicationType = 6 LLDPappTypeStreamingVideo LLDPApplicationType = 7 LLDPappTypeVideoSignaling LLDPApplicationType = 8 ) type LLDPNetworkPolicy struct { ApplicationType LLDPApplicationType Defined bool Tagged bool VLANId uint16 L2Priority uint16 DSCPValue uint8 } type LLDPLocationFormat uint8 const ( LLDPLocationFormatInvalid LLDPLocationFormat = 0 LLDPLocationFormatCoordinate LLDPLocationFormat = 1 LLDPLocationFormatAddress LLDPLocationFormat = 2 LLDPLocationFormatECS LLDPLocationFormat = 3 ) type LLDPLocationAddressWhat uint8 const ( LLDPLocationAddressWhatDHCP LLDPLocationAddressWhat = 0 LLDPLocationAddressWhatNetwork LLDPLocationAddressWhat = 1 LLDPLocationAddressWhatClient LLDPLocationAddressWhat = 2 ) type LLDPLocationAddressType uint8 const ( LLDPLocationAddressTypeLanguage LLDPLocationAddressType = 0 LLDPLocationAddressTypeNational LLDPLocationAddressType = 1 LLDPLocationAddressTypeCounty LLDPLocationAddressType = 2 LLDPLocationAddressTypeCity LLDPLocationAddressType = 3 LLDPLocationAddressTypeCityDivision LLDPLocationAddressType = 4 LLDPLocationAddressTypeNeighborhood LLDPLocationAddressType = 5 LLDPLocationAddressTypeStreet LLDPLocationAddressType = 6 LLDPLocationAddressTypeLeadingStreet LLDPLocationAddressType = 16 LLDPLocationAddressTypeTrailingStreet LLDPLocationAddressType = 17 LLDPLocationAddressTypeStreetSuffix LLDPLocationAddressType = 18 LLDPLocationAddressTypeHouseNum LLDPLocationAddressType = 19 LLDPLocationAddressTypeHouseSuffix LLDPLocationAddressType = 20 LLDPLocationAddressTypeLandmark LLDPLocationAddressType = 21 LLDPLocationAddressTypeAdditional LLDPLocationAddressType = 22 LLDPLocationAddressTypeName LLDPLocationAddressType = 23 LLDPLocationAddressTypePostal LLDPLocationAddressType = 24 LLDPLocationAddressTypeBuilding LLDPLocationAddressType = 25 LLDPLocationAddressTypeUnit LLDPLocationAddressType = 26 LLDPLocationAddressTypeFloor LLDPLocationAddressType = 27 LLDPLocationAddressTypeRoom LLDPLocationAddressType = 28 LLDPLocationAddressTypePlace LLDPLocationAddressType = 29 LLDPLocationAddressTypeScript LLDPLocationAddressType = 128 ) type LLDPLocationCoordinate struct { LatitudeResolution uint8 Latitude uint64 LongitudeResolution uint8 Longitude uint64 AltitudeType uint8 AltitudeResolution uint16 Altitude uint32 Datum uint8 } type LLDPLocationAddressLine struct { Type LLDPLocationAddressType Value string } type LLDPLocationAddress struct { What LLDPLocationAddressWhat CountryCode string AddressLines []LLDPLocationAddressLine } type LLDPLocationECS struct { ELIN string } // LLDP represents a physical location. // Only one of the embedded types will contain values, depending on Format. type LLDPLocation struct { Format LLDPLocationFormat Coordinate LLDPLocationCoordinate Address LLDPLocationAddress ECS LLDPLocationECS } type LLDPPowerViaMDI struct { Type LLDPPowerType Source LLDPPowerSource Priority LLDPPowerPriority Value uint16 } // LLDPInfoMedia represents the information carried in TR-41 Org-specific TLVs type LLDPInfoMedia struct { MediaCapabilities LLDPMediaCapabilities NetworkPolicy LLDPNetworkPolicy Location LLDPLocation PowerViaMDI LLDPPowerViaMDI HardwareRevision string FirmwareRevision string SoftwareRevision string SerialNumber string Manufacturer string Model string AssetID string } type LLDPCisco2Subtype uint8 // Cisco2 TLV Subtypes const ( LLDPCisco2PowerViaMDI LLDPCisco2Subtype = 1 ) const ( LLDPCiscoPSESupport uint8 = 1 << 0 LLDPCiscoArchShared uint8 = 1 << 1 LLDPCiscoPDSparePair uint8 = 1 << 2 LLDPCiscoPSESparePair uint8 = 1 << 3 ) // LLDPInfoCisco2 represents the information carried in Cisco Org-specific TLVs type LLDPInfoCisco2 struct { PSEFourWirePoESupported bool PDSparePairArchitectureShared bool PDRequestSparePairPoEOn bool PSESparePairPoEOn bool } // Profinet Subtypes type LLDPProfinetSubtype uint8 const ( LLDPProfinetPNIODelay LLDPProfinetSubtype = 1 LLDPProfinetPNIOPortStatus LLDPProfinetSubtype = 2 LLDPProfinetPNIOMRPPortStatus LLDPProfinetSubtype = 4 LLDPProfinetPNIOChassisMAC LLDPProfinetSubtype = 5 LLDPProfinetPNIOPTCPStatus LLDPProfinetSubtype = 6 ) type LLDPPNIODelay struct { RXLocal uint32 RXRemote uint32 TXLocal uint32 TXRemote uint32 CableLocal uint32 } type LLDPPNIOPortStatus struct { Class2 uint16 Class3 uint16 } type LLDPPNIOMRPPortStatus struct { UUID []byte Status uint16 } type LLDPPNIOPTCPStatus struct { MasterAddress []byte SubdomainUUID []byte IRDataUUID []byte PeriodValid bool PeriodLength uint32 RedPeriodValid bool RedPeriodBegin uint32 OrangePeriodValid bool OrangePeriodBegin uint32 GreenPeriodValid bool GreenPeriodBegin uint32 } // LLDPInfoProfinet represents the information carried in Profinet Org-specific TLVs type LLDPInfoProfinet struct { PNIODelay LLDPPNIODelay PNIOPortStatus LLDPPNIOPortStatus PNIOMRPPortStatus LLDPPNIOMRPPortStatus ChassisMAC []byte PNIOPTCPStatus LLDPPNIOPTCPStatus } // LayerType returns gopacket.LayerTypeLinkLayerDiscovery. func (c *LinkLayerDiscovery) LayerType() gopacket.LayerType { return LayerTypeLinkLayerDiscovery } func decodeLinkLayerDiscovery(data []byte, p gopacket.PacketBuilder) error { var vals []LinkLayerDiscoveryValue vData := data[0:] for len(vData) > 0 { nbit := vData[0] & 0x01 t := LLDPTLVType(vData[0] >> 1) val := LinkLayerDiscoveryValue{Type: t, Length: uint16(nbit)<<8 + uint16(vData[1])} if val.Length > 0 { val.Value = vData[2 : val.Length+2] } vals = append(vals, val) if t == LLDPTLVEnd { break } if len(vData) < int(2+val.Length) { return errors.New("Malformed LinkLayerDiscovery Header") } vData = vData[2+val.Length:] } if len(vals) < 4 { return errors.New("Missing mandatory LinkLayerDiscovery TLV") } c := &LinkLayerDiscovery{} gotEnd := false for _, v := range vals { switch v.Type { case LLDPTLVEnd: gotEnd = true case LLDPTLVChassisID: if len(v.Value) < 2 { return errors.New("Malformed LinkLayerDiscovery ChassisID TLV") } c.ChassisID.Subtype = LLDPChassisIDSubType(v.Value[0]) c.ChassisID.ID = v.Value[1:] case LLDPTLVPortID: if len(v.Value) < 2 { return errors.New("Malformed LinkLayerDiscovery PortID TLV") } c.PortID.Subtype = LLDPPortIDSubType(v.Value[0]) c.PortID.ID = v.Value[1:] case LLDPTLVTTL: if len(v.Value) < 2 { return errors.New("Malformed LinkLayerDiscovery TTL TLV") } c.TTL = binary.BigEndian.Uint16(v.Value[0:2]) default: c.Values = append(c.Values, v) } } if c.ChassisID.Subtype == 0 || c.PortID.Subtype == 0 || !gotEnd { return errors.New("Missing mandatory LinkLayerDiscovery TLV") } c.Contents = data p.AddLayer(c) info := &LinkLayerDiscoveryInfo{} p.AddLayer(info) for _, v := range c.Values { switch v.Type { case LLDPTLVPortDescription: info.PortDescription = string(v.Value) case LLDPTLVSysName: info.SysName = string(v.Value) case LLDPTLVSysDescription: info.SysDescription = string(v.Value) case LLDPTLVSysCapabilities: if err := checkLLDPTLVLen(v, 4); err != nil { return err } info.SysCapabilities.SystemCap = getCapabilities(binary.BigEndian.Uint16(v.Value[0:2])) info.SysCapabilities.EnabledCap = getCapabilities(binary.BigEndian.Uint16(v.Value[2:4])) case LLDPTLVMgmtAddress: if err := checkLLDPTLVLen(v, 9); err != nil { return err } mlen := v.Value[0] if err := checkLLDPTLVLen(v, int(mlen+7)); err != nil { return err } info.MgmtAddress.Subtype = IANAAddressFamily(v.Value[1]) info.MgmtAddress.Address = v.Value[2 : mlen+1] info.MgmtAddress.InterfaceSubtype = LLDPInterfaceSubtype(v.Value[mlen+1]) info.MgmtAddress.InterfaceNumber = binary.BigEndian.Uint32(v.Value[mlen+2 : mlen+6]) olen := v.Value[mlen+6] if err := checkLLDPTLVLen(v, int(mlen+6+olen)); err != nil { return err } info.MgmtAddress.OID = string(v.Value[mlen+9 : mlen+9+olen]) case LLDPTLVOrgSpecific: if err := checkLLDPTLVLen(v, 4); err != nil { return err } 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:]}) } } return nil } func (l *LinkLayerDiscoveryInfo) Decode8021() (info LLDPInfo8021, err error) { for _, o := range l.OrgTLVs { if o.OUI != IEEEOUI8021 { continue } switch o.SubType { case LLDP8021SubtypePortVLANID: if err = checkLLDPOrgSpecificLen(o, 2); err != nil { return } info.PVID = binary.BigEndian.Uint16(o.Info[0:2]) case LLDP8021SubtypeProtocolVLANID: if err = checkLLDPOrgSpecificLen(o, 3); err != nil { return } sup := (o.Info[0]&LLDPProtocolVLANIDCapability > 0) en := (o.Info[0]&LLDPProtocolVLANIDStatus > 0) id := binary.BigEndian.Uint16(o.Info[1:3]) info.PPVIDs = append(info.PPVIDs, PortProtocolVLANID{sup, en, id}) case LLDP8021SubtypeVLANName: if err = checkLLDPOrgSpecificLen(o, 2); err != nil { return } id := binary.BigEndian.Uint16(o.Info[0:2]) info.VLANNames = append(info.VLANNames, VLANName{id, string(o.Info[3:])}) case LLDP8021SubtypeProtocolIdentity: if err = checkLLDPOrgSpecificLen(o, 1); err != nil { return } l := int(o.Info[0]) if l > 0 { info.ProtocolIdentities = append(info.ProtocolIdentities, o.Info[1:1+l]) } case LLDP8021SubtypeVDIUsageDigest: if err = checkLLDPOrgSpecificLen(o, 4); err != nil { return } info.VIDUsageDigest = binary.BigEndian.Uint32(o.Info[0:4]) case LLDP8021SubtypeManagementVID: if err = checkLLDPOrgSpecificLen(o, 2); err != nil { return } info.ManagementVID = binary.BigEndian.Uint16(o.Info[0:2]) case LLDP8021SubtypeLinkAggregation: if err = checkLLDPOrgSpecificLen(o, 5); err != nil { return } sup := (o.Info[0]&LLDPAggregationCapability > 0) en := (o.Info[0]&LLDPAggregationStatus > 0) info.LinkAggregation = LLDPLinkAggregation{sup, en, binary.BigEndian.Uint32(o.Info[1:5])} } } return } func (l *LinkLayerDiscoveryInfo) Decode8023() (info LLDPInfo8023, err error) { for _, o := range l.OrgTLVs { if o.OUI != IEEEOUI8023 { continue } switch o.SubType { case LLDP8023SubtypeMACPHY: if err = checkLLDPOrgSpecificLen(o, 5); err != nil { return } sup := (o.Info[0]&LLDPMACPHYCapability > 0) en := (o.Info[0]&LLDPMACPHYStatus > 0) ca := binary.BigEndian.Uint16(o.Info[1:3]) mau := binary.BigEndian.Uint16(o.Info[3:5]) info.MACPHYConfigStatus = LLDPMACPHYConfigStatus{sup, en, ca, mau} case LLDP8023SubtypeMDIPower: if err = checkLLDPOrgSpecificLen(o, 3); err != nil { return } info.PowerViaMDI.PortClassPSE = (o.Info[0]&LLDPMDIPowerPortClass > 0) info.PowerViaMDI.PSESupported = (o.Info[0]&LLDPMDIPowerCapability > 0) info.PowerViaMDI.PSEEnabled = (o.Info[0]&LLDPMDIPowerStatus > 0) info.PowerViaMDI.PSEPairsAbility = (o.Info[0]&LLDPMDIPowerPairsAbility > 0) info.PowerViaMDI.PSEPowerPair = uint8(o.Info[1]) info.PowerViaMDI.PSEClass = uint8(o.Info[2]) if len(o.Info) >= 7 { info.PowerViaMDI.Type = LLDPPowerType((o.Info[3] & 0xc0) >> 6) info.PowerViaMDI.Source = LLDPPowerSource((o.Info[3] & 0x30) >> 4) if info.PowerViaMDI.Type == 1 || info.PowerViaMDI.Type == 3 { info.PowerViaMDI.Source += 128 // For Stringify purposes } info.PowerViaMDI.Priority = LLDPPowerPriority(o.Info[3] & 0x0f) info.PowerViaMDI.Requested = binary.BigEndian.Uint16(o.Info[4:6]) info.PowerViaMDI.Allocated = binary.BigEndian.Uint16(o.Info[6:8]) } case LLDP8023SubtypeLinkAggregation: if err = checkLLDPOrgSpecificLen(o, 5); err != nil { return } sup := (o.Info[0]&LLDPAggregationCapability > 0) en := (o.Info[0]&LLDPAggregationStatus > 0) info.LinkAggregation = LLDPLinkAggregation{sup, en, binary.BigEndian.Uint32(o.Info[1:5])} case LLDP8023SubtypeMTU: if err = checkLLDPOrgSpecificLen(o, 2); err != nil { return } info.MTU = binary.BigEndian.Uint16(o.Info[0:2]) } } return } func (l *LinkLayerDiscoveryInfo) Decode8021Qbg() (info LLDPInfo8021Qbg, err error) { for _, o := range l.OrgTLVs { if o.OUI != IEEEOUI8021Qbg { continue } switch o.SubType { case LLDP8021QbgEVB: if err = checkLLDPOrgSpecificLen(o, 9); err != nil { return } info.EVBSettings.Supported = getEVBCapabilities(binary.BigEndian.Uint16(o.Info[0:2])) info.EVBSettings.Enabled = getEVBCapabilities(binary.BigEndian.Uint16(o.Info[2:4])) info.EVBSettings.SupportedVSIs = binary.BigEndian.Uint16(o.Info[4:6]) info.EVBSettings.ConfiguredVSIs = binary.BigEndian.Uint16(o.Info[6:8]) info.EVBSettings.RTEExponent = uint8(o.Info[8]) } } return } func (l *LinkLayerDiscoveryInfo) DecodeMedia() (info LLDPInfoMedia, err error) { for _, o := range l.OrgTLVs { if o.OUI != IEEEOUIMedia { continue } switch LLDPMediaSubtype(o.SubType) { case LLDPMediaTypeCapabilities: if err = checkLLDPOrgSpecificLen(o, 3); err != nil { return } b := binary.BigEndian.Uint16(o.Info[0:2]) info.MediaCapabilities.Capabilities = (b & LLDPMediaCapsLLDP) > 0 info.MediaCapabilities.NetworkPolicy = (b & LLDPMediaCapsNetwork) > 0 info.MediaCapabilities.Location = (b & LLDPMediaCapsLocation) > 0 info.MediaCapabilities.PowerPSE = (b & LLDPMediaCapsPowerPSE) > 0 info.MediaCapabilities.PowerPD = (b & LLDPMediaCapsPowerPD) > 0 info.MediaCapabilities.Inventory = (b & LLDPMediaCapsInventory) > 0 info.MediaCapabilities.Class = LLDPMediaClass(o.Info[2]) case LLDPMediaTypeNetwork: if err = checkLLDPOrgSpecificLen(o, 4); err != nil { return } info.NetworkPolicy.ApplicationType = LLDPApplicationType(o.Info[0]) b := binary.BigEndian.Uint16(o.Info[1:3]) info.NetworkPolicy.Defined = (b & 0x8000) == 0 info.NetworkPolicy.Tagged = (b & 0x4000) > 0 info.NetworkPolicy.VLANId = (b & 0x1ffe) >> 1 b = binary.BigEndian.Uint16(o.Info[2:4]) info.NetworkPolicy.L2Priority = (b & 0x01c0) >> 6 info.NetworkPolicy.DSCPValue = uint8(o.Info[3] & 0x3f) case LLDPMediaTypeLocation: if err = checkLLDPOrgSpecificLen(o, 1); err != nil { return } info.Location.Format = LLDPLocationFormat(o.Info[0]) o.Info = o.Info[1:] switch info.Location.Format { case LLDPLocationFormatCoordinate: if err = checkLLDPOrgSpecificLen(o, 16); err != nil { return } info.Location.Coordinate.LatitudeResolution = uint8(o.Info[0]&0xfc) >> 2 b := binary.BigEndian.Uint64(o.Info[0:8]) info.Location.Coordinate.Latitude = (b & 0x03ffffffff000000) >> 24 info.Location.Coordinate.LongitudeResolution = uint8(o.Info[5]&0xfc) >> 2 b = binary.BigEndian.Uint64(o.Info[5:13]) info.Location.Coordinate.Longitude = (b & 0x03ffffffff000000) >> 24 info.Location.Coordinate.AltitudeType = uint8((o.Info[10] & 0x30) >> 4) b1 := binary.BigEndian.Uint16(o.Info[10:12]) info.Location.Coordinate.AltitudeResolution = (b1 & 0xfc0) >> 6 b2 := binary.BigEndian.Uint32(o.Info[11:15]) info.Location.Coordinate.Altitude = b2 & 0x3fffffff info.Location.Coordinate.Datum = uint8(o.Info[15]) case LLDPLocationFormatAddress: if err = checkLLDPOrgSpecificLen(o, 3); err != nil { return } //ll := uint8(o.Info[0]) info.Location.Address.What = LLDPLocationAddressWhat(o.Info[1]) info.Location.Address.CountryCode = string(o.Info[2:4]) data := o.Info[4:] for len(data) > 1 { aType := LLDPLocationAddressType(data[0]) aLen := int(data[1]) if len(data) >= aLen+2 { info.Location.Address.AddressLines = append(info.Location.Address.AddressLines, LLDPLocationAddressLine{aType, string(data[2 : aLen+2])}) data = data[aLen+2:] } else { break } } case LLDPLocationFormatECS: info.Location.ECS.ELIN = string(o.Info) } case LLDPMediaTypePower: if err = checkLLDPOrgSpecificLen(o, 3); err != nil { return } info.PowerViaMDI.Type = LLDPPowerType((o.Info[0] & 0xc0) >> 6) info.PowerViaMDI.Source = LLDPPowerSource((o.Info[0] & 0x30) >> 4) if info.PowerViaMDI.Type == 1 || info.PowerViaMDI.Type == 3 { info.PowerViaMDI.Source += 128 // For Stringify purposes } info.PowerViaMDI.Priority = LLDPPowerPriority(o.Info[0] & 0x0f) info.PowerViaMDI.Value = binary.BigEndian.Uint16(o.Info[1:3]) * 100 // 0 to 102.3 w, 0.1W increments case LLDPMediaTypeHardware: info.HardwareRevision = string(o.Info) case LLDPMediaTypeFirmware: info.FirmwareRevision = string(o.Info) case LLDPMediaTypeSoftware: info.SoftwareRevision = string(o.Info) case LLDPMediaTypeSerial: info.SerialNumber = string(o.Info) case LLDPMediaTypeManufacturer: info.Manufacturer = string(o.Info) case LLDPMediaTypeModel: info.Model = string(o.Info) case LLDPMediaTypeAssetID: info.AssetID = string(o.Info) } } return } func (l *LinkLayerDiscoveryInfo) DecodeCisco2() (info LLDPInfoCisco2, err error) { for _, o := range l.OrgTLVs { if o.OUI != IEEEOUICisco2 { continue } switch LLDPCisco2Subtype(o.SubType) { case LLDPCisco2PowerViaMDI: if err = checkLLDPOrgSpecificLen(o, 1); err != nil { return } info.PSEFourWirePoESupported = (o.Info[0] & LLDPCiscoPSESupport) > 0 info.PDSparePairArchitectureShared = (o.Info[0] & LLDPCiscoArchShared) > 0 info.PDRequestSparePairPoEOn = (o.Info[0] & LLDPCiscoPDSparePair) > 0 info.PSESparePairPoEOn = (o.Info[0] & LLDPCiscoPSESparePair) > 0 } } return } func (l *LinkLayerDiscoveryInfo) DecodeProfinet() (info LLDPInfoProfinet, err error) { for _, o := range l.OrgTLVs { if o.OUI != IEEEOUIProfinet { continue } switch LLDPProfinetSubtype(o.SubType) { case LLDPProfinetPNIODelay: if err = checkLLDPOrgSpecificLen(o, 20); err != nil { return } info.PNIODelay.RXLocal = binary.BigEndian.Uint32(o.Info[0:4]) info.PNIODelay.RXRemote = binary.BigEndian.Uint32(o.Info[4:8]) info.PNIODelay.TXLocal = binary.BigEndian.Uint32(o.Info[8:12]) info.PNIODelay.TXRemote = binary.BigEndian.Uint32(o.Info[12:16]) info.PNIODelay.CableLocal = binary.BigEndian.Uint32(o.Info[16:20]) case LLDPProfinetPNIOPortStatus: if err = checkLLDPOrgSpecificLen(o, 4); err != nil { return } info.PNIOPortStatus.Class2 = binary.BigEndian.Uint16(o.Info[0:2]) info.PNIOPortStatus.Class3 = binary.BigEndian.Uint16(o.Info[2:4]) case LLDPProfinetPNIOMRPPortStatus: if err = checkLLDPOrgSpecificLen(o, 18); err != nil { return } info.PNIOMRPPortStatus.UUID = o.Info[0:16] info.PNIOMRPPortStatus.Status = binary.BigEndian.Uint16(o.Info[16:18]) case LLDPProfinetPNIOChassisMAC: if err = checkLLDPOrgSpecificLen(o, 6); err != nil { return } info.ChassisMAC = o.Info[0:6] case LLDPProfinetPNIOPTCPStatus: if err = checkLLDPOrgSpecificLen(o, 54); err != nil { return } info.PNIOPTCPStatus.MasterAddress = o.Info[0:6] info.PNIOPTCPStatus.SubdomainUUID = o.Info[6:22] info.PNIOPTCPStatus.IRDataUUID = o.Info[22:38] b := binary.BigEndian.Uint32(o.Info[38:42]) info.PNIOPTCPStatus.PeriodValid = (b & 0x80000000) > 0 info.PNIOPTCPStatus.PeriodLength = b & 0x7fffffff b = binary.BigEndian.Uint32(o.Info[42:46]) info.PNIOPTCPStatus.RedPeriodValid = (b & 0x80000000) > 0 info.PNIOPTCPStatus.RedPeriodBegin = b & 0x7fffffff b = binary.BigEndian.Uint32(o.Info[46:50]) info.PNIOPTCPStatus.OrangePeriodValid = (b & 0x80000000) > 0 info.PNIOPTCPStatus.OrangePeriodBegin = b & 0x7fffffff b = binary.BigEndian.Uint32(o.Info[50:54]) info.PNIOPTCPStatus.GreenPeriodValid = (b & 0x80000000) > 0 info.PNIOPTCPStatus.GreenPeriodBegin = b & 0x7fffffff } } return } // LayerType returns gopacket.LayerTypeLinkLayerDiscoveryInfo. func (c *LinkLayerDiscoveryInfo) LayerType() gopacket.LayerType { return LayerTypeLinkLayerDiscoveryInfo } func getCapabilities(v uint16) (c LLDPCapabilities) { c.Other = (v&LLDPCapsOther > 0) c.Repeater = (v&LLDPCapsRepeater > 0) c.Bridge = (v&LLDPCapsBridge > 0) c.WLANAP = (v&LLDPCapsWLANAP > 0) c.Router = (v&LLDPCapsRouter > 0) c.Phone = (v&LLDPCapsPhone > 0) c.DocSis = (v&LLDPCapsDocSis > 0) c.StationOnly = (v&LLDPCapsStationOnly > 0) c.CVLAN = (v&LLDPCapsCVLAN > 0) c.SVLAN = (v&LLDPCapsSVLAN > 0) c.TMPR = (v&LLDPCapsTmpr > 0) return } func getEVBCapabilities(v uint16) (c LLDPEVBCapabilities) { c.StandardBridging = (v & LLDPEVBCapsSTD) > 0 c.StandardBridging = (v & LLDPEVBCapsSTD) > 0 c.ReflectiveRelay = (v & LLDPEVBCapsRR) > 0 c.RetransmissionTimerExponent = (v & LLDPEVBCapsRTE) > 0 c.EdgeControlProtocol = (v & LLDPEVBCapsECP) > 0 c.VSIDiscoveryProtocol = (v & LLDPEVBCapsVDP) > 0 return } func (t LLDPTLVType) String() (s string) { switch t { case LLDPTLVEnd: s = "TLV End" case LLDPTLVChassisID: s = "Chassis ID" case LLDPTLVPortID: s = "Port ID" case LLDPTLVTTL: s = "TTL" case LLDPTLVPortDescription: s = "Port Description" case LLDPTLVSysName: s = "System Name" case LLDPTLVSysDescription: s = "System Description" case LLDPTLVSysCapabilities: s = "System Capabilities" case LLDPTLVMgmtAddress: s = "Management Address" case LLDPTLVOrgSpecific: s = "Organisation Specific" default: s = "Unknown" } return } func (t LLDPChassisIDSubType) String() (s string) { switch t { case LLDPChassisIDSubTypeReserved: s = "Reserved" case LLDPChassisIDSubTypeChassisComp: s = "Chassis Component" case LLDPChassisIDSubtypeIfaceAlias: s = "Interface Alias" case LLDPChassisIDSubTypePortComp: s = "Port Component" case LLDPChassisIDSubTypeMACAddr: s = "MAC Address" case LLDPChassisIDSubTypeNetworkAddr: s = "Network Address" case LLDPChassisIDSubtypeIfaceName: s = "Interface Name" case LLDPChassisIDSubTypeLocal: s = "Local" default: s = "Unknown" } return } func (t LLDPPortIDSubType) String() (s string) { switch t { case LLDPPortIDSubtypeReserved: s = "Reserved" case LLDPPortIDSubtypeIfaceAlias: s = "Interface Alias" case LLDPPortIDSubtypePortComp: s = "Port Component" case LLDPPortIDSubtypeMACAddr: s = "MAC Address" case LLDPPortIDSubtypeNetworkAddr: s = "Network Address" case LLDPPortIDSubtypeIfaceName: s = "Interface Name" case LLDPPortIDSubtypeAgentCircuitID: s = "Agent Circuit ID" case LLDPPortIDSubtypeLocal: s = "Local" default: s = "Unknown" } return } func (t IANAAddressFamily) String() (s string) { switch t { case IANAAddressFamilyReserved: s = "Reserved" case IANAAddressFamilyIPV4: s = "IPv4" case IANAAddressFamilyIPV6: s = "IPv6" case IANAAddressFamilyNSAP: s = "NSAP" case IANAAddressFamilyHDLC: s = "HDLC" case IANAAddressFamilyBBN1822: s = "BBN 1822" case IANAAddressFamily802: s = "802 media plus Ethernet 'canonical format'" case IANAAddressFamilyE163: s = "E.163" case IANAAddressFamilyE164: s = "E.164 (SMDS, Frame Relay, ATM)" case IANAAddressFamilyF69: s = "F.69 (Telex)" case IANAAddressFamilyX121: s = "X.121, X.25, Frame Relay" case IANAAddressFamilyIPX: s = "IPX" case IANAAddressFamilyAtalk: s = "Appletalk" case IANAAddressFamilyDecnet: s = "Decnet IV" case IANAAddressFamilyBanyan: s = "Banyan Vines" case IANAAddressFamilyE164NSAP: s = "E.164 with NSAP format subaddress" case IANAAddressFamilyDNS: s = "DNS" case IANAAddressFamilyDistname: s = "Distinguished Name" case IANAAddressFamilyASNumber: s = "AS Number" case IANAAddressFamilyXTPIPV4: s = "XTP over IP version 4" case IANAAddressFamilyXTPIPV6: s = "XTP over IP version 6" case IANAAddressFamilyXTP: s = "XTP native mode XTP" case IANAAddressFamilyFcWWPN: s = "Fibre Channel World-Wide Port Name" case IANAAddressFamilyFcWWNN: s = "Fibre Channel World-Wide Node Name" case IANAAddressFamilyGWID: s = "GWID" case IANAAddressFamilyL2VPN: s = "AFI for Layer 2 VPN" default: s = "Unknown" } return } func (t LLDPInterfaceSubtype) String() (s string) { switch t { case LLDPInterfaceSubtypeUnknown: s = "Unknown" case LLDPInterfaceSubtypeifIndex: s = "IfIndex" case LLDPInterfaceSubtypeSysPort: s = "System Port Number" default: s = "Unknown" } return } func (t LLDPPowerType) String() (s string) { switch t { case 0: s = "Type 2 PSE Device" case 1: s = "Type 2 PD Device" case 2: s = "Type 1 PSE Device" case 3: s = "Type 1 PD Device" default: s = "Unknown" } return } func (t LLDPPowerSource) String() (s string) { switch t { // PD Device case 0: s = "Unknown" case 1: s = "PSE" case 2: s = "Local" case 3: s = "PSE and Local" // PSE Device (Actual value + 128) case 128: s = "Unknown" case 129: s = "Primary Power Source" case 130: s = "Backup Power Source" default: s = "Unknown" } return } func (t LLDPPowerPriority) String() (s string) { switch t { case 0: s = "Unknown" case 1: s = "Critical" case 2: s = "High" case 3: s = "Low" default: s = "Unknown" } return } func (t LLDPMediaSubtype) String() (s string) { switch t { case LLDPMediaTypeCapabilities: s = "Media Capabilities " case LLDPMediaTypeNetwork: s = "Network Policy" case LLDPMediaTypeLocation: s = "Location Identification" case LLDPMediaTypePower: s = "Extended Power-via-MDI" case LLDPMediaTypeHardware: s = "Hardware Revision" case LLDPMediaTypeFirmware: s = "Firmware Revision" case LLDPMediaTypeSoftware: s = "Software Revision" case LLDPMediaTypeSerial: s = "Serial Number" case LLDPMediaTypeManufacturer: s = "Manufacturer" case LLDPMediaTypeModel: s = "Model" case LLDPMediaTypeAssetID: s = "Asset ID" default: s = "Unknown" } return } func (t LLDPMediaClass) String() (s string) { switch t { case LLDPMediaClassUndefined: s = "Undefined" case LLDPMediaClassEndpointI: s = "Endpoint Class I" case LLDPMediaClassEndpointII: s = "Endpoint Class II" case LLDPMediaClassEndpointIII: s = "Endpoint Class III" case LLDPMediaClassNetwork: s = "Network connectivity " default: s = "Unknown" } return } func (t LLDPApplicationType) String() (s string) { switch t { case LLDPAppTypeReserved: s = "Reserved" case LLDPAppTypeVoice: s = "Voice" case LLDPappTypeVoiceSignaling: s = "Voice Signaling" case LLDPappTypeGuestVoice: s = "Guest Voice" case LLDPappTypeGuestVoiceSignaling: s = "Guest Voice Signaling" case LLDPappTypeSoftphoneVoice: s = "Softphone Voice" case LLDPappTypeVideoConferencing: s = "Video Conferencing" case LLDPappTypeStreamingVideo: s = "Streaming Video" case LLDPappTypeVideoSignaling: s = "Video Signaling" default: s = "Unknown" } return } func (t LLDPLocationFormat) String() (s string) { switch t { case LLDPLocationFormatInvalid: s = "Invalid" case LLDPLocationFormatCoordinate: s = "Coordinate-based LCI" case LLDPLocationFormatAddress: s = "Address-based LCO" case LLDPLocationFormatECS: s = "ECS ELIN" default: s = "Unknown" } return } func (t LLDPLocationAddressType) String() (s string) { switch t { case LLDPLocationAddressTypeLanguage: s = "Language" case LLDPLocationAddressTypeNational: s = "National subdivisions (province, state, etc)" case LLDPLocationAddressTypeCounty: s = "County, parish, district" case LLDPLocationAddressTypeCity: s = "City, township" case LLDPLocationAddressTypeCityDivision: s = "City division, borough, ward" case LLDPLocationAddressTypeNeighborhood: s = "Neighborhood, block" case LLDPLocationAddressTypeStreet: s = "Street" case LLDPLocationAddressTypeLeadingStreet: s = "Leading street direction" case LLDPLocationAddressTypeTrailingStreet: s = "Trailing street suffix" case LLDPLocationAddressTypeStreetSuffix: s = "Street suffix" case LLDPLocationAddressTypeHouseNum: s = "House number" case LLDPLocationAddressTypeHouseSuffix: s = "House number suffix" case LLDPLocationAddressTypeLandmark: s = "Landmark or vanity address" case LLDPLocationAddressTypeAdditional: s = "Additional location information" case LLDPLocationAddressTypeName: s = "Name" case LLDPLocationAddressTypePostal: s = "Postal/ZIP code" case LLDPLocationAddressTypeBuilding: s = "Building" case LLDPLocationAddressTypeUnit: s = "Unit" case LLDPLocationAddressTypeFloor: s = "Floor" case LLDPLocationAddressTypeRoom: s = "Room number" case LLDPLocationAddressTypePlace: s = "Place type" case LLDPLocationAddressTypeScript: s = "Script" default: s = "Unknown" } return } func checkLLDPTLVLen(v LinkLayerDiscoveryValue, l int) (err error) { if len(v.Value) < l { err = fmt.Errorf("Invalid TLV %v length %d (wanted mimimum %v", v.Type, len(v.Value), l) } return } func checkLLDPOrgSpecificLen(o LLDPOrgSpecificTLV, l int) (err error) { if len(o.Info) < l { err = fmt.Errorf("Invalid Org Specific TLV %v length %d (wanted minimum %v)", o.SubType, len(o.Info), l) } return }