123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651 |
- // 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.
- // Enum types courtesy of...
- // http://search.cpan.org/~mchapman/Net-CDP-0.09/lib/Net/CDP.pm
- // https://code.google.com/p/ladvd/
- // http://anonsvn.wireshark.org/viewvc/releases/wireshark-1.8.6/epan/dissectors/packet-cdp.c
- package layers
- import (
- "encoding/binary"
- "fmt"
- "net"
- "github.com/google/gopacket"
- )
- // CDPTLVType is the type of each TLV value in a CiscoDiscovery packet.
- type CDPTLVType uint16
- // CDPTLVType values.
- const (
- CDPTLVDevID CDPTLVType = 0x0001
- CDPTLVAddress CDPTLVType = 0x0002
- CDPTLVPortID CDPTLVType = 0x0003
- CDPTLVCapabilities CDPTLVType = 0x0004
- CDPTLVVersion CDPTLVType = 0x0005
- CDPTLVPlatform CDPTLVType = 0x0006
- CDPTLVIPPrefix CDPTLVType = 0x0007
- CDPTLVHello CDPTLVType = 0x0008
- CDPTLVVTPDomain CDPTLVType = 0x0009
- CDPTLVNativeVLAN CDPTLVType = 0x000a
- CDPTLVFullDuplex CDPTLVType = 0x000b
- CDPTLVVLANReply CDPTLVType = 0x000e
- CDPTLVVLANQuery CDPTLVType = 0x000f
- CDPTLVPower CDPTLVType = 0x0010
- CDPTLVMTU CDPTLVType = 0x0011
- CDPTLVExtendedTrust CDPTLVType = 0x0012
- CDPTLVUntrustedCOS CDPTLVType = 0x0013
- CDPTLVSysName CDPTLVType = 0x0014
- CDPTLVSysOID CDPTLVType = 0x0015
- CDPTLVMgmtAddresses CDPTLVType = 0x0016
- CDPTLVLocation CDPTLVType = 0x0017
- CDPTLVExternalPortID CDPTLVType = 0x0018
- CDPTLVPowerRequested CDPTLVType = 0x0019
- CDPTLVPowerAvailable CDPTLVType = 0x001a
- CDPTLVPortUnidirectional CDPTLVType = 0x001b
- CDPTLVEnergyWise CDPTLVType = 0x001d
- CDPTLVSparePairPOE CDPTLVType = 0x001f
- )
- // CiscoDiscoveryValue is a TLV value inside a CiscoDiscovery packet layer.
- type CiscoDiscoveryValue struct {
- Type CDPTLVType
- Length uint16
- Value []byte
- }
- // CiscoDiscovery is a packet layer containing the Cisco Discovery Protocol.
- // See http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm#31885
- type CiscoDiscovery struct {
- BaseLayer
- Version byte
- TTL byte
- Checksum uint16
- Values []CiscoDiscoveryValue
- }
- // CDPCapability is the set of capabilities advertised by a CDP device.
- type CDPCapability uint32
- // CDPCapability values.
- const (
- CDPCapMaskRouter CDPCapability = 0x0001
- CDPCapMaskTBBridge CDPCapability = 0x0002
- CDPCapMaskSPBridge CDPCapability = 0x0004
- CDPCapMaskSwitch CDPCapability = 0x0008
- CDPCapMaskHost CDPCapability = 0x0010
- CDPCapMaskIGMPFilter CDPCapability = 0x0020
- CDPCapMaskRepeater CDPCapability = 0x0040
- CDPCapMaskPhone CDPCapability = 0x0080
- CDPCapMaskRemote CDPCapability = 0x0100
- )
- // CDPCapabilities represents the capabilities of a device
- type CDPCapabilities struct {
- L3Router bool
- TBBridge bool
- SPBridge bool
- L2Switch bool
- IsHost bool
- IGMPFilter bool
- L1Repeater bool
- IsPhone bool
- RemotelyManaged bool
- }
- // CDP Power-over-Ethernet values.
- const (
- CDPPoEFourWire byte = 0x01
- CDPPoEPDArch byte = 0x02
- CDPPoEPDRequest byte = 0x04
- CDPPoEPSE byte = 0x08
- )
- // CDPSparePairPoE provides information on PoE.
- type CDPSparePairPoE struct {
- PSEFourWire bool // Supported / Not supported
- PDArchShared bool // Shared / Independent
- PDRequestOn bool // On / Off
- PSEOn bool // On / Off
- }
- // CDPVLANDialogue encapsulates a VLAN Query/Reply
- type CDPVLANDialogue struct {
- ID uint8
- VLAN uint16
- }
- // CDPPowerDialogue encapsulates a Power Query/Reply
- type CDPPowerDialogue struct {
- ID uint16
- MgmtID uint16
- Values []uint32
- }
- // CDPLocation provides location information for a CDP device.
- type CDPLocation struct {
- Type uint8 // Undocumented
- Location string
- }
- // CDPHello is a Cisco Hello message (undocumented, hence the "Unknown" fields)
- type CDPHello struct {
- OUI []byte
- ProtocolID uint16
- ClusterMaster net.IP
- Unknown1 net.IP
- Version byte
- SubVersion byte
- Status byte
- Unknown2 byte
- ClusterCommander net.HardwareAddr
- SwitchMAC net.HardwareAddr
- Unknown3 byte
- ManagementVLAN uint16
- }
- // CDPEnergyWiseSubtype is used within CDP to define TLV values.
- type CDPEnergyWiseSubtype uint32
- // CDPEnergyWiseSubtype values.
- const (
- CDPEnergyWiseRole CDPEnergyWiseSubtype = 0x00000007
- CDPEnergyWiseDomain CDPEnergyWiseSubtype = 0x00000008
- CDPEnergyWiseName CDPEnergyWiseSubtype = 0x00000009
- CDPEnergyWiseReplyTo CDPEnergyWiseSubtype = 0x00000017
- )
- // CDPEnergyWise is used by CDP to monitor and control power usage.
- type CDPEnergyWise struct {
- EncryptedData []byte
- Unknown1 uint32
- SequenceNumber uint32
- ModelNumber string
- Unknown2 uint16
- HardwareID string
- SerialNum string
- Unknown3 []byte
- Role string
- Domain string
- Name string
- ReplyUnknown1 []byte
- ReplyPort []byte
- ReplyAddress []byte
- ReplyUnknown2 []byte
- ReplyUnknown3 []byte
- }
- // CiscoDiscoveryInfo represents the decoded details for a set of CiscoDiscoveryValues
- type CiscoDiscoveryInfo struct {
- BaseLayer
- CDPHello
- DeviceID string
- Addresses []net.IP
- PortID string
- Capabilities CDPCapabilities
- Version string
- Platform string
- IPPrefixes []net.IPNet
- VTPDomain string
- NativeVLAN uint16
- FullDuplex bool
- VLANReply CDPVLANDialogue
- VLANQuery CDPVLANDialogue
- PowerConsumption uint16
- MTU uint32
- ExtendedTrust uint8
- UntrustedCOS uint8
- SysName string
- SysOID string
- MgmtAddresses []net.IP
- Location CDPLocation
- PowerRequest CDPPowerDialogue
- PowerAvailable CDPPowerDialogue
- SparePairPoe CDPSparePairPoE
- EnergyWise CDPEnergyWise
- Unknown []CiscoDiscoveryValue
- }
- // LayerType returns gopacket.LayerTypeCiscoDiscovery.
- func (c *CiscoDiscovery) LayerType() gopacket.LayerType {
- return LayerTypeCiscoDiscovery
- }
- func decodeCiscoDiscovery(data []byte, p gopacket.PacketBuilder) error {
- c := &CiscoDiscovery{
- Version: data[0],
- TTL: data[1],
- Checksum: binary.BigEndian.Uint16(data[2:4]),
- }
- if c.Version != 1 && c.Version != 2 {
- return fmt.Errorf("Invalid CiscoDiscovery version number %d", c.Version)
- }
- var err error
- c.Values, err = decodeCiscoDiscoveryTLVs(data[4:])
- if err != nil {
- return err
- }
- c.Contents = data[0:4]
- c.Payload = data[4:]
- p.AddLayer(c)
- return p.NextDecoder(gopacket.DecodeFunc(decodeCiscoDiscoveryInfo))
- }
- // LayerType returns gopacket.LayerTypeCiscoDiscoveryInfo.
- func (c *CiscoDiscoveryInfo) LayerType() gopacket.LayerType {
- return LayerTypeCiscoDiscoveryInfo
- }
- func decodeCiscoDiscoveryTLVs(data []byte) (values []CiscoDiscoveryValue, err error) {
- for len(data) > 0 {
- val := CiscoDiscoveryValue{
- Type: CDPTLVType(binary.BigEndian.Uint16(data[:2])),
- Length: binary.BigEndian.Uint16(data[2:4]),
- }
- if val.Length < 4 {
- err = fmt.Errorf("Invalid CiscoDiscovery value length %d", val.Length)
- break
- }
- val.Value = data[4:val.Length]
- values = append(values, val)
- data = data[val.Length:]
- }
- return
- }
- func decodeCiscoDiscoveryInfo(data []byte, p gopacket.PacketBuilder) error {
- var err error
- info := &CiscoDiscoveryInfo{BaseLayer: BaseLayer{Contents: data}}
- p.AddLayer(info)
- values, err := decodeCiscoDiscoveryTLVs(data)
- if err != nil { // Unlikely, as parent decode will fail, but better safe...
- return err
- }
- for _, val := range values {
- switch val.Type {
- case CDPTLVDevID:
- info.DeviceID = string(val.Value)
- case CDPTLVAddress:
- if err = checkCDPTLVLen(val, 4); err != nil {
- return err
- }
- info.Addresses, err = decodeAddresses(val.Value)
- if err != nil {
- return err
- }
- case CDPTLVPortID:
- info.PortID = string(val.Value)
- case CDPTLVCapabilities:
- if err = checkCDPTLVLen(val, 4); err != nil {
- return err
- }
- val := CDPCapability(binary.BigEndian.Uint32(val.Value[0:4]))
- info.Capabilities.L3Router = (val&CDPCapMaskRouter > 0)
- info.Capabilities.TBBridge = (val&CDPCapMaskTBBridge > 0)
- info.Capabilities.SPBridge = (val&CDPCapMaskSPBridge > 0)
- info.Capabilities.L2Switch = (val&CDPCapMaskSwitch > 0)
- info.Capabilities.IsHost = (val&CDPCapMaskHost > 0)
- info.Capabilities.IGMPFilter = (val&CDPCapMaskIGMPFilter > 0)
- info.Capabilities.L1Repeater = (val&CDPCapMaskRepeater > 0)
- info.Capabilities.IsPhone = (val&CDPCapMaskPhone > 0)
- info.Capabilities.RemotelyManaged = (val&CDPCapMaskRemote > 0)
- case CDPTLVVersion:
- info.Version = string(val.Value)
- case CDPTLVPlatform:
- info.Platform = string(val.Value)
- case CDPTLVIPPrefix:
- v := val.Value
- l := len(v)
- if l%5 == 0 && l >= 5 {
- for len(v) > 0 {
- _, ipnet, _ := net.ParseCIDR(fmt.Sprintf("%d.%d.%d.%d/%d", v[0], v[1], v[2], v[3], v[4]))
- info.IPPrefixes = append(info.IPPrefixes, *ipnet)
- v = v[5:]
- }
- } else {
- return fmt.Errorf("Invalid TLV %v length %d", val.Type, len(val.Value))
- }
- case CDPTLVHello:
- if err = checkCDPTLVLen(val, 32); err != nil {
- return err
- }
- v := val.Value
- info.CDPHello.OUI = v[0:3]
- info.CDPHello.ProtocolID = binary.BigEndian.Uint16(v[3:5])
- info.CDPHello.ClusterMaster = v[5:9]
- info.CDPHello.Unknown1 = v[9:13]
- info.CDPHello.Version = v[13]
- info.CDPHello.SubVersion = v[14]
- info.CDPHello.Status = v[15]
- info.CDPHello.Unknown2 = v[16]
- info.CDPHello.ClusterCommander = v[17:23]
- info.CDPHello.SwitchMAC = v[23:29]
- info.CDPHello.Unknown3 = v[29]
- info.CDPHello.ManagementVLAN = binary.BigEndian.Uint16(v[30:32])
- case CDPTLVVTPDomain:
- info.VTPDomain = string(val.Value)
- case CDPTLVNativeVLAN:
- if err = checkCDPTLVLen(val, 2); err != nil {
- return err
- }
- info.NativeVLAN = binary.BigEndian.Uint16(val.Value[0:2])
- case CDPTLVFullDuplex:
- if err = checkCDPTLVLen(val, 1); err != nil {
- return err
- }
- info.FullDuplex = (val.Value[0] == 1)
- case CDPTLVVLANReply:
- if err = checkCDPTLVLen(val, 3); err != nil {
- return err
- }
- info.VLANReply.ID = uint8(val.Value[0])
- info.VLANReply.VLAN = binary.BigEndian.Uint16(val.Value[1:3])
- case CDPTLVVLANQuery:
- if err = checkCDPTLVLen(val, 3); err != nil {
- return err
- }
- info.VLANQuery.ID = uint8(val.Value[0])
- info.VLANQuery.VLAN = binary.BigEndian.Uint16(val.Value[1:3])
- case CDPTLVPower:
- if err = checkCDPTLVLen(val, 2); err != nil {
- return err
- }
- info.PowerConsumption = binary.BigEndian.Uint16(val.Value[0:2])
- case CDPTLVMTU:
- if err = checkCDPTLVLen(val, 4); err != nil {
- return err
- }
- info.MTU = binary.BigEndian.Uint32(val.Value[0:4])
- case CDPTLVExtendedTrust:
- if err = checkCDPTLVLen(val, 1); err != nil {
- return err
- }
- info.ExtendedTrust = uint8(val.Value[0])
- case CDPTLVUntrustedCOS:
- if err = checkCDPTLVLen(val, 1); err != nil {
- return err
- }
- info.UntrustedCOS = uint8(val.Value[0])
- case CDPTLVSysName:
- info.SysName = string(val.Value)
- case CDPTLVSysOID:
- info.SysOID = string(val.Value)
- case CDPTLVMgmtAddresses:
- if err = checkCDPTLVLen(val, 4); err != nil {
- return err
- }
- info.MgmtAddresses, err = decodeAddresses(val.Value)
- if err != nil {
- return err
- }
- case CDPTLVLocation:
- if err = checkCDPTLVLen(val, 2); err != nil {
- return err
- }
- info.Location.Type = uint8(val.Value[0])
- info.Location.Location = string(val.Value[1:])
- // case CDPTLVLExternalPortID:
- // Undocumented
- case CDPTLVPowerRequested:
- if err = checkCDPTLVLen(val, 4); err != nil {
- return err
- }
- info.PowerRequest.ID = binary.BigEndian.Uint16(val.Value[0:2])
- info.PowerRequest.MgmtID = binary.BigEndian.Uint16(val.Value[2:4])
- for n := 4; n < len(val.Value); n += 4 {
- info.PowerRequest.Values = append(info.PowerRequest.Values, binary.BigEndian.Uint32(val.Value[n:n+4]))
- }
- case CDPTLVPowerAvailable:
- if err = checkCDPTLVLen(val, 4); err != nil {
- return err
- }
- info.PowerAvailable.ID = binary.BigEndian.Uint16(val.Value[0:2])
- info.PowerAvailable.MgmtID = binary.BigEndian.Uint16(val.Value[2:4])
- for n := 4; n < len(val.Value); n += 4 {
- info.PowerAvailable.Values = append(info.PowerAvailable.Values, binary.BigEndian.Uint32(val.Value[n:n+4]))
- }
- // case CDPTLVPortUnidirectional
- // Undocumented
- case CDPTLVEnergyWise:
- if err = checkCDPTLVLen(val, 72); err != nil {
- return err
- }
- info.EnergyWise.EncryptedData = val.Value[0:20]
- info.EnergyWise.Unknown1 = binary.BigEndian.Uint32(val.Value[20:24])
- info.EnergyWise.SequenceNumber = binary.BigEndian.Uint32(val.Value[24:28])
- info.EnergyWise.ModelNumber = string(val.Value[28:44])
- info.EnergyWise.Unknown2 = binary.BigEndian.Uint16(val.Value[44:46])
- info.EnergyWise.HardwareID = string(val.Value[46:49])
- info.EnergyWise.SerialNum = string(val.Value[49:60])
- info.EnergyWise.Unknown3 = val.Value[60:68]
- tlvLen := binary.BigEndian.Uint16(val.Value[68:70])
- tlvNum := binary.BigEndian.Uint16(val.Value[70:72])
- data := val.Value[72:]
- if len(data) < int(tlvLen) {
- return fmt.Errorf("Invalid TLV length %d vs %d", tlvLen, len(data))
- }
- numSeen := 0
- for len(data) > 8 {
- numSeen++
- if numSeen > int(tlvNum) { // Too many TLV's ?
- return fmt.Errorf("Too many TLV's - wanted %d, saw %d", tlvNum, numSeen)
- }
- tType := CDPEnergyWiseSubtype(binary.BigEndian.Uint32(data[0:4]))
- tLen := int(binary.BigEndian.Uint32(data[4:8]))
- if tLen > len(data)-8 {
- return fmt.Errorf("Invalid TLV length %d vs %d", tLen, len(data)-8)
- }
- data = data[8:]
- switch tType {
- case CDPEnergyWiseRole:
- info.EnergyWise.Role = string(data[:])
- case CDPEnergyWiseDomain:
- info.EnergyWise.Domain = string(data[:])
- case CDPEnergyWiseName:
- info.EnergyWise.Name = string(data[:])
- case CDPEnergyWiseReplyTo:
- if len(data) >= 18 {
- info.EnergyWise.ReplyUnknown1 = data[0:2]
- info.EnergyWise.ReplyPort = data[2:4]
- info.EnergyWise.ReplyAddress = data[4:8]
- info.EnergyWise.ReplyUnknown2 = data[8:10]
- info.EnergyWise.ReplyUnknown3 = data[10:14]
- }
- }
- data = data[tLen:]
- }
- case CDPTLVSparePairPOE:
- if err = checkCDPTLVLen(val, 1); err != nil {
- return err
- }
- v := val.Value[0]
- info.SparePairPoe.PSEFourWire = (v&CDPPoEFourWire > 0)
- info.SparePairPoe.PDArchShared = (v&CDPPoEPDArch > 0)
- info.SparePairPoe.PDRequestOn = (v&CDPPoEPDRequest > 0)
- info.SparePairPoe.PSEOn = (v&CDPPoEPSE > 0)
- default:
- info.Unknown = append(info.Unknown, val)
- }
- }
- return nil
- }
- // CDP Protocol Types
- const (
- CDPProtocolTypeNLPID byte = 1
- CDPProtocolType802_2 byte = 2
- )
- // CDPAddressType is used to define TLV values within CDP addresses.
- type CDPAddressType uint64
- // CDP Address types.
- const (
- CDPAddressTypeCLNP CDPAddressType = 0x81
- CDPAddressTypeIPV4 CDPAddressType = 0xcc
- CDPAddressTypeIPV6 CDPAddressType = 0xaaaa030000000800
- CDPAddressTypeDECNET CDPAddressType = 0xaaaa030000006003
- CDPAddressTypeAPPLETALK CDPAddressType = 0xaaaa03000000809b
- CDPAddressTypeIPX CDPAddressType = 0xaaaa030000008137
- CDPAddressTypeVINES CDPAddressType = 0xaaaa0300000080c4
- CDPAddressTypeXNS CDPAddressType = 0xaaaa030000000600
- CDPAddressTypeAPOLLO CDPAddressType = 0xaaaa030000008019
- )
- func decodeAddresses(v []byte) (addresses []net.IP, err error) {
- numaddr := int(binary.BigEndian.Uint32(v[0:4]))
- if numaddr < 1 {
- return nil, fmt.Errorf("Invalid Address TLV number %d", numaddr)
- }
- v = v[4:]
- if len(v) < numaddr*8 {
- return nil, fmt.Errorf("Invalid Address TLV length %d", len(v))
- }
- for i := 0; i < numaddr; i++ {
- prottype := v[0]
- if prottype != CDPProtocolTypeNLPID && prottype != CDPProtocolType802_2 { // invalid protocol type
- return nil, fmt.Errorf("Invalid Address Protocol %d", prottype)
- }
- protlen := int(v[1])
- if (prottype == CDPProtocolTypeNLPID && protlen != 1) ||
- (prottype == CDPProtocolType802_2 && protlen != 3 && protlen != 8) { // invalid length
- return nil, fmt.Errorf("Invalid Address Protocol length %d", protlen)
- }
- plen := make([]byte, 8)
- copy(plen[8-protlen:], v[2:2+protlen])
- protocol := CDPAddressType(binary.BigEndian.Uint64(plen))
- v = v[2+protlen:]
- addrlen := binary.BigEndian.Uint16(v[0:2])
- ab := v[2 : 2+addrlen]
- if protocol == CDPAddressTypeIPV4 && addrlen == 4 {
- addresses = append(addresses, net.IPv4(ab[0], ab[1], ab[2], ab[3]))
- } else if protocol == CDPAddressTypeIPV6 && addrlen == 16 {
- addresses = append(addresses, net.IP(ab))
- } else {
- // only handle IPV4 & IPV6 for now
- }
- v = v[2+addrlen:]
- if len(v) < 8 {
- break
- }
- }
- return
- }
- func (t CDPTLVType) String() (s string) {
- switch t {
- case CDPTLVDevID:
- s = "Device ID"
- case CDPTLVAddress:
- s = "Addresses"
- case CDPTLVPortID:
- s = "Port ID"
- case CDPTLVCapabilities:
- s = "Capabilities"
- case CDPTLVVersion:
- s = "Software Version"
- case CDPTLVPlatform:
- s = "Platform"
- case CDPTLVIPPrefix:
- s = "IP Prefix"
- case CDPTLVHello:
- s = "Protocol Hello"
- case CDPTLVVTPDomain:
- s = "VTP Management Domain"
- case CDPTLVNativeVLAN:
- s = "Native VLAN"
- case CDPTLVFullDuplex:
- s = "Full Duplex"
- case CDPTLVVLANReply:
- s = "VoIP VLAN Reply"
- case CDPTLVVLANQuery:
- s = "VLANQuery"
- case CDPTLVPower:
- s = "Power consumption"
- case CDPTLVMTU:
- s = "MTU"
- case CDPTLVExtendedTrust:
- s = "Extended Trust Bitmap"
- case CDPTLVUntrustedCOS:
- s = "Untrusted Port CoS"
- case CDPTLVSysName:
- s = "System Name"
- case CDPTLVSysOID:
- s = "System OID"
- case CDPTLVMgmtAddresses:
- s = "Management Addresses"
- case CDPTLVLocation:
- s = "Location"
- case CDPTLVExternalPortID:
- s = "External Port ID"
- case CDPTLVPowerRequested:
- s = "Power Requested"
- case CDPTLVPowerAvailable:
- s = "Power Available"
- case CDPTLVPortUnidirectional:
- s = "Port Unidirectional"
- case CDPTLVEnergyWise:
- s = "Energy Wise"
- case CDPTLVSparePairPOE:
- s = "Spare Pair POE"
- default:
- s = "Unknown"
- }
- return
- }
- func (a CDPAddressType) String() (s string) {
- switch a {
- case CDPAddressTypeCLNP:
- s = "Connectionless Network Protocol"
- case CDPAddressTypeIPV4:
- s = "IPv4"
- case CDPAddressTypeIPV6:
- s = "IPv6"
- case CDPAddressTypeDECNET:
- s = "DECnet Phase IV"
- case CDPAddressTypeAPPLETALK:
- s = "Apple Talk"
- case CDPAddressTypeIPX:
- s = "Novell IPX"
- case CDPAddressTypeVINES:
- s = "Banyan VINES"
- case CDPAddressTypeXNS:
- s = "Xerox Network Systems"
- case CDPAddressTypeAPOLLO:
- s = "Apollo"
- default:
- s = "Unknown"
- }
- return
- }
- func (t CDPEnergyWiseSubtype) String() (s string) {
- switch t {
- case CDPEnergyWiseRole:
- s = "Role"
- case CDPEnergyWiseDomain:
- s = "Domain"
- case CDPEnergyWiseName:
- s = "Name"
- case CDPEnergyWiseReplyTo:
- s = "ReplyTo"
- default:
- s = "Unknown"
- }
- return
- }
- func checkCDPTLVLen(v CiscoDiscoveryValue, l int) (err error) {
- if len(v.Value) < l {
- err = fmt.Errorf("Invalid TLV %v length %d", v.Type, len(v.Value))
- }
- return
- }
|