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