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