blob: 16a5bbadad981e48c502ac1e37d304c9974c385b [file] [log] [blame]
Naveen Sampath04696f72022-06-13 15:19:14 +05301// 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 for _, v := range c.Values {
783 vb, err := b.AppendBytes(int(v.Length) + 2) // +2 for TLV type and length; 1 byte for subtype is included in v.Value
784 if err != nil {
785 return err
786 }
787 idLen := ((uint16(v.Type) << 9) | v.Length)
788 binary.BigEndian.PutUint16(vb[0:2], idLen)
789 copy(vb[2:], v.Value)
790 }
791
792 vb, err = b.AppendBytes(2) // End Tlv, 2 bytes
793 if err != nil {
794 return err
795 }
796 binary.BigEndian.PutUint16(vb[len(vb)-2:], uint16(0)) //End tlv, 2 bytes, all zero
797 return nil
798
799}
800
801func decodeLinkLayerDiscovery(data []byte, p gopacket.PacketBuilder) error {
802 var vals []LinkLayerDiscoveryValue
803 vData := data[0:]
804 for len(vData) > 0 {
805 if len(vData) < 2 {
806 p.SetTruncated()
807 return errors.New("LLDP vdata < 2 bytes")
808 }
809 nbit := vData[0] & 0x01
810 t := LLDPTLVType(vData[0] >> 1)
811 val := LinkLayerDiscoveryValue{Type: t, Length: uint16(nbit)<<8 + uint16(vData[1])}
812 if val.Length > 0 {
813 if len(vData) < int(val.Length+2) {
814 p.SetTruncated()
815 return fmt.Errorf("LLDP VData < %d bytes", val.Length+2)
816 }
817 val.Value = vData[2 : val.Length+2]
818 }
819 vals = append(vals, val)
820 if t == LLDPTLVEnd {
821 break
822 }
823 if len(vData) < int(2+val.Length) {
824 return errors.New("Malformed LinkLayerDiscovery Header")
825 }
826 vData = vData[2+val.Length:]
827 }
828 if len(vals) < 4 {
829 return errors.New("Missing mandatory LinkLayerDiscovery TLV")
830 }
831 c := &LinkLayerDiscovery{}
832 gotEnd := false
833 for _, v := range vals {
834 switch v.Type {
835 case LLDPTLVEnd:
836 gotEnd = true
837 case LLDPTLVChassisID:
838 if len(v.Value) < 2 {
839 return errors.New("Malformed LinkLayerDiscovery ChassisID TLV")
840 }
841 c.ChassisID.Subtype = LLDPChassisIDSubType(v.Value[0])
842 c.ChassisID.ID = v.Value[1:]
843 case LLDPTLVPortID:
844 if len(v.Value) < 2 {
845 return errors.New("Malformed LinkLayerDiscovery PortID TLV")
846 }
847 c.PortID.Subtype = LLDPPortIDSubType(v.Value[0])
848 c.PortID.ID = v.Value[1:]
849 case LLDPTLVTTL:
850 if len(v.Value) < 2 {
851 return errors.New("Malformed LinkLayerDiscovery TTL TLV")
852 }
853 c.TTL = binary.BigEndian.Uint16(v.Value[0:2])
854 default:
855 c.Values = append(c.Values, v)
856 }
857 }
858 if c.ChassisID.Subtype == 0 || c.PortID.Subtype == 0 || !gotEnd {
859 return errors.New("Missing mandatory LinkLayerDiscovery TLV")
860 }
861 c.Contents = data
862 p.AddLayer(c)
863
864 info := &LinkLayerDiscoveryInfo{}
865 p.AddLayer(info)
866 for _, v := range c.Values {
867 switch v.Type {
868 case LLDPTLVPortDescription:
869 info.PortDescription = string(v.Value)
870 case LLDPTLVSysName:
871 info.SysName = string(v.Value)
872 case LLDPTLVSysDescription:
873 info.SysDescription = string(v.Value)
874 case LLDPTLVSysCapabilities:
875 if err := checkLLDPTLVLen(v, 4); err != nil {
876 return err
877 }
878 info.SysCapabilities.SystemCap = getCapabilities(binary.BigEndian.Uint16(v.Value[0:2]))
879 info.SysCapabilities.EnabledCap = getCapabilities(binary.BigEndian.Uint16(v.Value[2:4]))
880 case LLDPTLVMgmtAddress:
881 if err := checkLLDPTLVLen(v, 9); err != nil {
882 return err
883 }
884 mlen := v.Value[0]
885 if err := checkLLDPTLVLen(v, int(mlen+7)); err != nil {
886 return err
887 }
888 info.MgmtAddress.Subtype = IANAAddressFamily(v.Value[1])
889 info.MgmtAddress.Address = v.Value[2 : mlen+1]
890 info.MgmtAddress.InterfaceSubtype = LLDPInterfaceSubtype(v.Value[mlen+1])
891 info.MgmtAddress.InterfaceNumber = binary.BigEndian.Uint32(v.Value[mlen+2 : mlen+6])
892 olen := v.Value[mlen+6]
893 if err := checkLLDPTLVLen(v, int(mlen+7+olen)); err != nil {
894 return err
895 }
896 info.MgmtAddress.OID = string(v.Value[mlen+7 : mlen+7+olen])
897 case LLDPTLVOrgSpecific:
898 if err := checkLLDPTLVLen(v, 4); err != nil {
899 return err
900 }
901 info.OrgTLVs = append(info.OrgTLVs, LLDPOrgSpecificTLV{IEEEOUI(binary.BigEndian.Uint32(append([]byte{byte(0)}, v.Value[0:3]...))), uint8(v.Value[3]), v.Value[4:]})
902 }
903 }
904 return nil
905}
906
907func (l *LinkLayerDiscoveryInfo) Decode8021() (info LLDPInfo8021, err error) {
908 for _, o := range l.OrgTLVs {
909 if o.OUI != IEEEOUI8021 {
910 continue
911 }
912 switch o.SubType {
913 case LLDP8021SubtypePortVLANID:
914 if err = checkLLDPOrgSpecificLen(o, 2); err != nil {
915 return
916 }
917 info.PVID = binary.BigEndian.Uint16(o.Info[0:2])
918 case LLDP8021SubtypeProtocolVLANID:
919 if err = checkLLDPOrgSpecificLen(o, 3); err != nil {
920 return
921 }
922 sup := (o.Info[0]&LLDPProtocolVLANIDCapability > 0)
923 en := (o.Info[0]&LLDPProtocolVLANIDStatus > 0)
924 id := binary.BigEndian.Uint16(o.Info[1:3])
925 info.PPVIDs = append(info.PPVIDs, PortProtocolVLANID{sup, en, id})
926 case LLDP8021SubtypeVLANName:
927 if err = checkLLDPOrgSpecificLen(o, 2); err != nil {
928 return
929 }
930 id := binary.BigEndian.Uint16(o.Info[0:2])
931 info.VLANNames = append(info.VLANNames, VLANName{id, string(o.Info[3:])})
932 case LLDP8021SubtypeProtocolIdentity:
933 if err = checkLLDPOrgSpecificLen(o, 1); err != nil {
934 return
935 }
936 l := int(o.Info[0])
937 if l > 0 {
938 info.ProtocolIdentities = append(info.ProtocolIdentities, o.Info[1:1+l])
939 }
940 case LLDP8021SubtypeVDIUsageDigest:
941 if err = checkLLDPOrgSpecificLen(o, 4); err != nil {
942 return
943 }
944 info.VIDUsageDigest = binary.BigEndian.Uint32(o.Info[0:4])
945 case LLDP8021SubtypeManagementVID:
946 if err = checkLLDPOrgSpecificLen(o, 2); err != nil {
947 return
948 }
949 info.ManagementVID = binary.BigEndian.Uint16(o.Info[0:2])
950 case LLDP8021SubtypeLinkAggregation:
951 if err = checkLLDPOrgSpecificLen(o, 5); err != nil {
952 return
953 }
954 sup := (o.Info[0]&LLDPAggregationCapability > 0)
955 en := (o.Info[0]&LLDPAggregationStatus > 0)
956 info.LinkAggregation = LLDPLinkAggregation{sup, en, binary.BigEndian.Uint32(o.Info[1:5])}
957 }
958 }
959 return
960}
961
962func (l *LinkLayerDiscoveryInfo) Decode8023() (info LLDPInfo8023, err error) {
963 for _, o := range l.OrgTLVs {
964 if o.OUI != IEEEOUI8023 {
965 continue
966 }
967 switch o.SubType {
968 case LLDP8023SubtypeMACPHY:
969 if err = checkLLDPOrgSpecificLen(o, 5); err != nil {
970 return
971 }
972 sup := (o.Info[0]&LLDPMACPHYCapability > 0)
973 en := (o.Info[0]&LLDPMACPHYStatus > 0)
974 ca := binary.BigEndian.Uint16(o.Info[1:3])
975 mau := binary.BigEndian.Uint16(o.Info[3:5])
976 info.MACPHYConfigStatus = LLDPMACPHYConfigStatus{sup, en, ca, mau}
977 case LLDP8023SubtypeMDIPower:
978 if err = checkLLDPOrgSpecificLen(o, 3); err != nil {
979 return
980 }
981 info.PowerViaMDI.PortClassPSE = (o.Info[0]&LLDPMDIPowerPortClass > 0)
982 info.PowerViaMDI.PSESupported = (o.Info[0]&LLDPMDIPowerCapability > 0)
983 info.PowerViaMDI.PSEEnabled = (o.Info[0]&LLDPMDIPowerStatus > 0)
984 info.PowerViaMDI.PSEPairsAbility = (o.Info[0]&LLDPMDIPowerPairsAbility > 0)
985 info.PowerViaMDI.PSEPowerPair = uint8(o.Info[1])
986 info.PowerViaMDI.PSEClass = uint8(o.Info[2])
987 if len(o.Info) >= 7 {
988 info.PowerViaMDI.Type = LLDPPowerType((o.Info[3] & 0xc0) >> 6)
989 info.PowerViaMDI.Source = LLDPPowerSource((o.Info[3] & 0x30) >> 4)
990 if info.PowerViaMDI.Type == 1 || info.PowerViaMDI.Type == 3 {
991 info.PowerViaMDI.Source += 128 // For Stringify purposes
992 }
993 info.PowerViaMDI.Priority = LLDPPowerPriority(o.Info[3] & 0x0f)
994 info.PowerViaMDI.Requested = binary.BigEndian.Uint16(o.Info[4:6])
995 info.PowerViaMDI.Allocated = binary.BigEndian.Uint16(o.Info[6:8])
996 }
997 case LLDP8023SubtypeLinkAggregation:
998 if err = checkLLDPOrgSpecificLen(o, 5); err != nil {
999 return
1000 }
1001 sup := (o.Info[0]&LLDPAggregationCapability > 0)
1002 en := (o.Info[0]&LLDPAggregationStatus > 0)
1003 info.LinkAggregation = LLDPLinkAggregation{sup, en, binary.BigEndian.Uint32(o.Info[1:5])}
1004 case LLDP8023SubtypeMTU:
1005 if err = checkLLDPOrgSpecificLen(o, 2); err != nil {
1006 return
1007 }
1008 info.MTU = binary.BigEndian.Uint16(o.Info[0:2])
1009 }
1010 }
1011 return
1012}
1013
1014func (l *LinkLayerDiscoveryInfo) Decode8021Qbg() (info LLDPInfo8021Qbg, err error) {
1015 for _, o := range l.OrgTLVs {
1016 if o.OUI != IEEEOUI8021Qbg {
1017 continue
1018 }
1019 switch o.SubType {
1020 case LLDP8021QbgEVB:
1021 if err = checkLLDPOrgSpecificLen(o, 9); err != nil {
1022 return
1023 }
1024 info.EVBSettings.Supported = getEVBCapabilities(binary.BigEndian.Uint16(o.Info[0:2]))
1025 info.EVBSettings.Enabled = getEVBCapabilities(binary.BigEndian.Uint16(o.Info[2:4]))
1026 info.EVBSettings.SupportedVSIs = binary.BigEndian.Uint16(o.Info[4:6])
1027 info.EVBSettings.ConfiguredVSIs = binary.BigEndian.Uint16(o.Info[6:8])
1028 info.EVBSettings.RTEExponent = uint8(o.Info[8])
1029 }
1030 }
1031 return
1032}
1033
1034func (l *LinkLayerDiscoveryInfo) DecodeMedia() (info LLDPInfoMedia, err error) {
1035 for _, o := range l.OrgTLVs {
1036 if o.OUI != IEEEOUIMedia {
1037 continue
1038 }
1039 switch LLDPMediaSubtype(o.SubType) {
1040 case LLDPMediaTypeCapabilities:
1041 if err = checkLLDPOrgSpecificLen(o, 3); err != nil {
1042 return
1043 }
1044 b := binary.BigEndian.Uint16(o.Info[0:2])
1045 info.MediaCapabilities.Capabilities = (b & LLDPMediaCapsLLDP) > 0
1046 info.MediaCapabilities.NetworkPolicy = (b & LLDPMediaCapsNetwork) > 0
1047 info.MediaCapabilities.Location = (b & LLDPMediaCapsLocation) > 0
1048 info.MediaCapabilities.PowerPSE = (b & LLDPMediaCapsPowerPSE) > 0
1049 info.MediaCapabilities.PowerPD = (b & LLDPMediaCapsPowerPD) > 0
1050 info.MediaCapabilities.Inventory = (b & LLDPMediaCapsInventory) > 0
1051 info.MediaCapabilities.Class = LLDPMediaClass(o.Info[2])
1052 case LLDPMediaTypeNetwork:
1053 if err = checkLLDPOrgSpecificLen(o, 4); err != nil {
1054 return
1055 }
1056 info.NetworkPolicy.ApplicationType = LLDPApplicationType(o.Info[0])
1057 b := binary.BigEndian.Uint16(o.Info[1:3])
1058 info.NetworkPolicy.Defined = (b & 0x8000) == 0
1059 info.NetworkPolicy.Tagged = (b & 0x4000) > 0
1060 info.NetworkPolicy.VLANId = (b & 0x1ffe) >> 1
1061 b = binary.BigEndian.Uint16(o.Info[2:4])
1062 info.NetworkPolicy.L2Priority = (b & 0x01c0) >> 6
1063 info.NetworkPolicy.DSCPValue = uint8(o.Info[3] & 0x3f)
1064 case LLDPMediaTypeLocation:
1065 if err = checkLLDPOrgSpecificLen(o, 1); err != nil {
1066 return
1067 }
1068 info.Location.Format = LLDPLocationFormat(o.Info[0])
1069 o.Info = o.Info[1:]
1070 switch info.Location.Format {
1071 case LLDPLocationFormatCoordinate:
1072 if err = checkLLDPOrgSpecificLen(o, 16); err != nil {
1073 return
1074 }
1075 info.Location.Coordinate.LatitudeResolution = uint8(o.Info[0]&0xfc) >> 2
1076 b := binary.BigEndian.Uint64(o.Info[0:8])
1077 info.Location.Coordinate.Latitude = (b & 0x03ffffffff000000) >> 24
1078 info.Location.Coordinate.LongitudeResolution = uint8(o.Info[5]&0xfc) >> 2
1079 b = binary.BigEndian.Uint64(o.Info[5:13])
1080 info.Location.Coordinate.Longitude = (b & 0x03ffffffff000000) >> 24
1081 info.Location.Coordinate.AltitudeType = uint8((o.Info[10] & 0x30) >> 4)
1082 b1 := binary.BigEndian.Uint16(o.Info[10:12])
1083 info.Location.Coordinate.AltitudeResolution = (b1 & 0xfc0) >> 6
1084 b2 := binary.BigEndian.Uint32(o.Info[11:15])
1085 info.Location.Coordinate.Altitude = b2 & 0x3fffffff
1086 info.Location.Coordinate.Datum = uint8(o.Info[15])
1087 case LLDPLocationFormatAddress:
1088 if err = checkLLDPOrgSpecificLen(o, 3); err != nil {
1089 return
1090 }
1091 //ll := uint8(o.Info[0])
1092 info.Location.Address.What = LLDPLocationAddressWhat(o.Info[1])
1093 info.Location.Address.CountryCode = string(o.Info[2:4])
1094 data := o.Info[4:]
1095 for len(data) > 1 {
1096 aType := LLDPLocationAddressType(data[0])
1097 aLen := int(data[1])
1098 if len(data) >= aLen+2 {
1099 info.Location.Address.AddressLines = append(info.Location.Address.AddressLines, LLDPLocationAddressLine{aType, string(data[2 : aLen+2])})
1100 data = data[aLen+2:]
1101 } else {
1102 break
1103 }
1104 }
1105 case LLDPLocationFormatECS:
1106 info.Location.ECS.ELIN = string(o.Info)
1107 }
1108 case LLDPMediaTypePower:
1109 if err = checkLLDPOrgSpecificLen(o, 3); err != nil {
1110 return
1111 }
1112 info.PowerViaMDI.Type = LLDPPowerType((o.Info[0] & 0xc0) >> 6)
1113 info.PowerViaMDI.Source = LLDPPowerSource((o.Info[0] & 0x30) >> 4)
1114 if info.PowerViaMDI.Type == 1 || info.PowerViaMDI.Type == 3 {
1115 info.PowerViaMDI.Source += 128 // For Stringify purposes
1116 }
1117 info.PowerViaMDI.Priority = LLDPPowerPriority(o.Info[0] & 0x0f)
1118 info.PowerViaMDI.Value = binary.BigEndian.Uint16(o.Info[1:3]) * 100 // 0 to 102.3 w, 0.1W increments
1119 case LLDPMediaTypeHardware:
1120 info.HardwareRevision = string(o.Info)
1121 case LLDPMediaTypeFirmware:
1122 info.FirmwareRevision = string(o.Info)
1123 case LLDPMediaTypeSoftware:
1124 info.SoftwareRevision = string(o.Info)
1125 case LLDPMediaTypeSerial:
1126 info.SerialNumber = string(o.Info)
1127 case LLDPMediaTypeManufacturer:
1128 info.Manufacturer = string(o.Info)
1129 case LLDPMediaTypeModel:
1130 info.Model = string(o.Info)
1131 case LLDPMediaTypeAssetID:
1132 info.AssetID = string(o.Info)
1133 }
1134 }
1135 return
1136}
1137
1138func (l *LinkLayerDiscoveryInfo) DecodeCisco2() (info LLDPInfoCisco2, err error) {
1139 for _, o := range l.OrgTLVs {
1140 if o.OUI != IEEEOUICisco2 {
1141 continue
1142 }
1143 switch LLDPCisco2Subtype(o.SubType) {
1144 case LLDPCisco2PowerViaMDI:
1145 if err = checkLLDPOrgSpecificLen(o, 1); err != nil {
1146 return
1147 }
1148 info.PSEFourWirePoESupported = (o.Info[0] & LLDPCiscoPSESupport) > 0
1149 info.PDSparePairArchitectureShared = (o.Info[0] & LLDPCiscoArchShared) > 0
1150 info.PDRequestSparePairPoEOn = (o.Info[0] & LLDPCiscoPDSparePair) > 0
1151 info.PSESparePairPoEOn = (o.Info[0] & LLDPCiscoPSESparePair) > 0
1152 }
1153 }
1154 return
1155}
1156
1157func (l *LinkLayerDiscoveryInfo) DecodeProfinet() (info LLDPInfoProfinet, err error) {
1158 for _, o := range l.OrgTLVs {
1159 if o.OUI != IEEEOUIProfinet {
1160 continue
1161 }
1162 switch LLDPProfinetSubtype(o.SubType) {
1163 case LLDPProfinetPNIODelay:
1164 if err = checkLLDPOrgSpecificLen(o, 20); err != nil {
1165 return
1166 }
1167 info.PNIODelay.RXLocal = binary.BigEndian.Uint32(o.Info[0:4])
1168 info.PNIODelay.RXRemote = binary.BigEndian.Uint32(o.Info[4:8])
1169 info.PNIODelay.TXLocal = binary.BigEndian.Uint32(o.Info[8:12])
1170 info.PNIODelay.TXRemote = binary.BigEndian.Uint32(o.Info[12:16])
1171 info.PNIODelay.CableLocal = binary.BigEndian.Uint32(o.Info[16:20])
1172 case LLDPProfinetPNIOPortStatus:
1173 if err = checkLLDPOrgSpecificLen(o, 4); err != nil {
1174 return
1175 }
1176 info.PNIOPortStatus.Class2 = binary.BigEndian.Uint16(o.Info[0:2])
1177 info.PNIOPortStatus.Class3 = binary.BigEndian.Uint16(o.Info[2:4])
1178 case LLDPProfinetPNIOMRPPortStatus:
1179 if err = checkLLDPOrgSpecificLen(o, 18); err != nil {
1180 return
1181 }
1182 info.PNIOMRPPortStatus.UUID = o.Info[0:16]
1183 info.PNIOMRPPortStatus.Status = binary.BigEndian.Uint16(o.Info[16:18])
1184 case LLDPProfinetPNIOChassisMAC:
1185 if err = checkLLDPOrgSpecificLen(o, 6); err != nil {
1186 return
1187 }
1188 info.ChassisMAC = o.Info[0:6]
1189 case LLDPProfinetPNIOPTCPStatus:
1190 if err = checkLLDPOrgSpecificLen(o, 54); err != nil {
1191 return
1192 }
1193 info.PNIOPTCPStatus.MasterAddress = o.Info[0:6]
1194 info.PNIOPTCPStatus.SubdomainUUID = o.Info[6:22]
1195 info.PNIOPTCPStatus.IRDataUUID = o.Info[22:38]
1196 b := binary.BigEndian.Uint32(o.Info[38:42])
1197 info.PNIOPTCPStatus.PeriodValid = (b & 0x80000000) > 0
1198 info.PNIOPTCPStatus.PeriodLength = b & 0x7fffffff
1199 b = binary.BigEndian.Uint32(o.Info[42:46])
1200 info.PNIOPTCPStatus.RedPeriodValid = (b & 0x80000000) > 0
1201 info.PNIOPTCPStatus.RedPeriodBegin = b & 0x7fffffff
1202 b = binary.BigEndian.Uint32(o.Info[46:50])
1203 info.PNIOPTCPStatus.OrangePeriodValid = (b & 0x80000000) > 0
1204 info.PNIOPTCPStatus.OrangePeriodBegin = b & 0x7fffffff
1205 b = binary.BigEndian.Uint32(o.Info[50:54])
1206 info.PNIOPTCPStatus.GreenPeriodValid = (b & 0x80000000) > 0
1207 info.PNIOPTCPStatus.GreenPeriodBegin = b & 0x7fffffff
1208 }
1209 }
1210 return
1211}
1212
1213// LayerType returns gopacket.LayerTypeLinkLayerDiscoveryInfo.
1214func (c *LinkLayerDiscoveryInfo) LayerType() gopacket.LayerType {
1215 return LayerTypeLinkLayerDiscoveryInfo
1216}
1217
1218func getCapabilities(v uint16) (c LLDPCapabilities) {
1219 c.Other = (v&LLDPCapsOther > 0)
1220 c.Repeater = (v&LLDPCapsRepeater > 0)
1221 c.Bridge = (v&LLDPCapsBridge > 0)
1222 c.WLANAP = (v&LLDPCapsWLANAP > 0)
1223 c.Router = (v&LLDPCapsRouter > 0)
1224 c.Phone = (v&LLDPCapsPhone > 0)
1225 c.DocSis = (v&LLDPCapsDocSis > 0)
1226 c.StationOnly = (v&LLDPCapsStationOnly > 0)
1227 c.CVLAN = (v&LLDPCapsCVLAN > 0)
1228 c.SVLAN = (v&LLDPCapsSVLAN > 0)
1229 c.TMPR = (v&LLDPCapsTmpr > 0)
1230 return
1231}
1232
1233func getEVBCapabilities(v uint16) (c LLDPEVBCapabilities) {
1234 c.StandardBridging = (v & LLDPEVBCapsSTD) > 0
1235 c.StandardBridging = (v & LLDPEVBCapsSTD) > 0
1236 c.ReflectiveRelay = (v & LLDPEVBCapsRR) > 0
1237 c.RetransmissionTimerExponent = (v & LLDPEVBCapsRTE) > 0
1238 c.EdgeControlProtocol = (v & LLDPEVBCapsECP) > 0
1239 c.VSIDiscoveryProtocol = (v & LLDPEVBCapsVDP) > 0
1240 return
1241}
1242
1243func (t LLDPTLVType) String() (s string) {
1244 switch t {
1245 case LLDPTLVEnd:
1246 s = "TLV End"
1247 case LLDPTLVChassisID:
1248 s = "Chassis ID"
1249 case LLDPTLVPortID:
1250 s = "Port ID"
1251 case LLDPTLVTTL:
1252 s = "TTL"
1253 case LLDPTLVPortDescription:
1254 s = "Port Description"
1255 case LLDPTLVSysName:
1256 s = "System Name"
1257 case LLDPTLVSysDescription:
1258 s = "System Description"
1259 case LLDPTLVSysCapabilities:
1260 s = "System Capabilities"
1261 case LLDPTLVMgmtAddress:
1262 s = "Management Address"
1263 case LLDPTLVOrgSpecific:
1264 s = "Organisation Specific"
1265 default:
1266 s = "Unknown"
1267 }
1268 return
1269}
1270
1271func (t LLDPChassisIDSubType) String() (s string) {
1272 switch t {
1273 case LLDPChassisIDSubTypeReserved:
1274 s = "Reserved"
1275 case LLDPChassisIDSubTypeChassisComp:
1276 s = "Chassis Component"
1277 case LLDPChassisIDSubtypeIfaceAlias:
1278 s = "Interface Alias"
1279 case LLDPChassisIDSubTypePortComp:
1280 s = "Port Component"
1281 case LLDPChassisIDSubTypeMACAddr:
1282 s = "MAC Address"
1283 case LLDPChassisIDSubTypeNetworkAddr:
1284 s = "Network Address"
1285 case LLDPChassisIDSubtypeIfaceName:
1286 s = "Interface Name"
1287 case LLDPChassisIDSubTypeLocal:
1288 s = "Local"
1289 default:
1290 s = "Unknown"
1291 }
1292 return
1293}
1294
1295func (t LLDPPortIDSubType) String() (s string) {
1296 switch t {
1297 case LLDPPortIDSubtypeReserved:
1298 s = "Reserved"
1299 case LLDPPortIDSubtypeIfaceAlias:
1300 s = "Interface Alias"
1301 case LLDPPortIDSubtypePortComp:
1302 s = "Port Component"
1303 case LLDPPortIDSubtypeMACAddr:
1304 s = "MAC Address"
1305 case LLDPPortIDSubtypeNetworkAddr:
1306 s = "Network Address"
1307 case LLDPPortIDSubtypeIfaceName:
1308 s = "Interface Name"
1309 case LLDPPortIDSubtypeAgentCircuitID:
1310 s = "Agent Circuit ID"
1311 case LLDPPortIDSubtypeLocal:
1312 s = "Local"
1313 default:
1314 s = "Unknown"
1315 }
1316 return
1317}
1318
1319func (t IANAAddressFamily) String() (s string) {
1320 switch t {
1321 case IANAAddressFamilyReserved:
1322 s = "Reserved"
1323 case IANAAddressFamilyIPV4:
1324 s = "IPv4"
1325 case IANAAddressFamilyIPV6:
1326 s = "IPv6"
1327 case IANAAddressFamilyNSAP:
1328 s = "NSAP"
1329 case IANAAddressFamilyHDLC:
1330 s = "HDLC"
1331 case IANAAddressFamilyBBN1822:
1332 s = "BBN 1822"
1333 case IANAAddressFamily802:
1334 s = "802 media plus Ethernet 'canonical format'"
1335 case IANAAddressFamilyE163:
1336 s = "E.163"
1337 case IANAAddressFamilyE164:
1338 s = "E.164 (SMDS, Frame Relay, ATM)"
1339 case IANAAddressFamilyF69:
1340 s = "F.69 (Telex)"
1341 case IANAAddressFamilyX121:
1342 s = "X.121, X.25, Frame Relay"
1343 case IANAAddressFamilyIPX:
1344 s = "IPX"
1345 case IANAAddressFamilyAtalk:
1346 s = "Appletalk"
1347 case IANAAddressFamilyDecnet:
1348 s = "Decnet IV"
1349 case IANAAddressFamilyBanyan:
1350 s = "Banyan Vines"
1351 case IANAAddressFamilyE164NSAP:
1352 s = "E.164 with NSAP format subaddress"
1353 case IANAAddressFamilyDNS:
1354 s = "DNS"
1355 case IANAAddressFamilyDistname:
1356 s = "Distinguished Name"
1357 case IANAAddressFamilyASNumber:
1358 s = "AS Number"
1359 case IANAAddressFamilyXTPIPV4:
1360 s = "XTP over IP version 4"
1361 case IANAAddressFamilyXTPIPV6:
1362 s = "XTP over IP version 6"
1363 case IANAAddressFamilyXTP:
1364 s = "XTP native mode XTP"
1365 case IANAAddressFamilyFcWWPN:
1366 s = "Fibre Channel World-Wide Port Name"
1367 case IANAAddressFamilyFcWWNN:
1368 s = "Fibre Channel World-Wide Node Name"
1369 case IANAAddressFamilyGWID:
1370 s = "GWID"
1371 case IANAAddressFamilyL2VPN:
1372 s = "AFI for Layer 2 VPN"
1373 default:
1374 s = "Unknown"
1375 }
1376 return
1377}
1378
1379func (t LLDPInterfaceSubtype) String() (s string) {
1380 switch t {
1381 case LLDPInterfaceSubtypeUnknown:
1382 s = "Unknown"
1383 case LLDPInterfaceSubtypeifIndex:
1384 s = "IfIndex"
1385 case LLDPInterfaceSubtypeSysPort:
1386 s = "System Port Number"
1387 default:
1388 s = "Unknown"
1389 }
1390 return
1391}
1392
1393func (t LLDPPowerType) String() (s string) {
1394 switch t {
1395 case 0:
1396 s = "Type 2 PSE Device"
1397 case 1:
1398 s = "Type 2 PD Device"
1399 case 2:
1400 s = "Type 1 PSE Device"
1401 case 3:
1402 s = "Type 1 PD Device"
1403 default:
1404 s = "Unknown"
1405 }
1406 return
1407}
1408
1409func (t LLDPPowerSource) String() (s string) {
1410 switch t {
1411 // PD Device
1412 case 0:
1413 s = "Unknown"
1414 case 1:
1415 s = "PSE"
1416 case 2:
1417 s = "Local"
1418 case 3:
1419 s = "PSE and Local"
1420 // PSE Device (Actual value + 128)
1421 case 128:
1422 s = "Unknown"
1423 case 129:
1424 s = "Primary Power Source"
1425 case 130:
1426 s = "Backup Power Source"
1427 default:
1428 s = "Unknown"
1429 }
1430 return
1431}
1432
1433func (t LLDPPowerPriority) String() (s string) {
1434 switch t {
1435 case 0:
1436 s = "Unknown"
1437 case 1:
1438 s = "Critical"
1439 case 2:
1440 s = "High"
1441 case 3:
1442 s = "Low"
1443 default:
1444 s = "Unknown"
1445 }
1446 return
1447}
1448
1449func (t LLDPMediaSubtype) String() (s string) {
1450 switch t {
1451 case LLDPMediaTypeCapabilities:
1452 s = "Media Capabilities "
1453 case LLDPMediaTypeNetwork:
1454 s = "Network Policy"
1455 case LLDPMediaTypeLocation:
1456 s = "Location Identification"
1457 case LLDPMediaTypePower:
1458 s = "Extended Power-via-MDI"
1459 case LLDPMediaTypeHardware:
1460 s = "Hardware Revision"
1461 case LLDPMediaTypeFirmware:
1462 s = "Firmware Revision"
1463 case LLDPMediaTypeSoftware:
1464 s = "Software Revision"
1465 case LLDPMediaTypeSerial:
1466 s = "Serial Number"
1467 case LLDPMediaTypeManufacturer:
1468 s = "Manufacturer"
1469 case LLDPMediaTypeModel:
1470 s = "Model"
1471 case LLDPMediaTypeAssetID:
1472 s = "Asset ID"
1473 default:
1474 s = "Unknown"
1475 }
1476 return
1477}
1478
1479func (t LLDPMediaClass) String() (s string) {
1480 switch t {
1481 case LLDPMediaClassUndefined:
1482 s = "Undefined"
1483 case LLDPMediaClassEndpointI:
1484 s = "Endpoint Class I"
1485 case LLDPMediaClassEndpointII:
1486 s = "Endpoint Class II"
1487 case LLDPMediaClassEndpointIII:
1488 s = "Endpoint Class III"
1489 case LLDPMediaClassNetwork:
1490 s = "Network connectivity "
1491 default:
1492 s = "Unknown"
1493 }
1494 return
1495}
1496
1497func (t LLDPApplicationType) String() (s string) {
1498 switch t {
1499 case LLDPAppTypeReserved:
1500 s = "Reserved"
1501 case LLDPAppTypeVoice:
1502 s = "Voice"
1503 case LLDPappTypeVoiceSignaling:
1504 s = "Voice Signaling"
1505 case LLDPappTypeGuestVoice:
1506 s = "Guest Voice"
1507 case LLDPappTypeGuestVoiceSignaling:
1508 s = "Guest Voice Signaling"
1509 case LLDPappTypeSoftphoneVoice:
1510 s = "Softphone Voice"
1511 case LLDPappTypeVideoConferencing:
1512 s = "Video Conferencing"
1513 case LLDPappTypeStreamingVideo:
1514 s = "Streaming Video"
1515 case LLDPappTypeVideoSignaling:
1516 s = "Video Signaling"
1517 default:
1518 s = "Unknown"
1519 }
1520 return
1521}
1522
1523func (t LLDPLocationFormat) String() (s string) {
1524 switch t {
1525 case LLDPLocationFormatInvalid:
1526 s = "Invalid"
1527 case LLDPLocationFormatCoordinate:
1528 s = "Coordinate-based LCI"
1529 case LLDPLocationFormatAddress:
1530 s = "Address-based LCO"
1531 case LLDPLocationFormatECS:
1532 s = "ECS ELIN"
1533 default:
1534 s = "Unknown"
1535 }
1536 return
1537}
1538
1539func (t LLDPLocationAddressType) String() (s string) {
1540 switch t {
1541 case LLDPLocationAddressTypeLanguage:
1542 s = "Language"
1543 case LLDPLocationAddressTypeNational:
1544 s = "National subdivisions (province, state, etc)"
1545 case LLDPLocationAddressTypeCounty:
1546 s = "County, parish, district"
1547 case LLDPLocationAddressTypeCity:
1548 s = "City, township"
1549 case LLDPLocationAddressTypeCityDivision:
1550 s = "City division, borough, ward"
1551 case LLDPLocationAddressTypeNeighborhood:
1552 s = "Neighborhood, block"
1553 case LLDPLocationAddressTypeStreet:
1554 s = "Street"
1555 case LLDPLocationAddressTypeLeadingStreet:
1556 s = "Leading street direction"
1557 case LLDPLocationAddressTypeTrailingStreet:
1558 s = "Trailing street suffix"
1559 case LLDPLocationAddressTypeStreetSuffix:
1560 s = "Street suffix"
1561 case LLDPLocationAddressTypeHouseNum:
1562 s = "House number"
1563 case LLDPLocationAddressTypeHouseSuffix:
1564 s = "House number suffix"
1565 case LLDPLocationAddressTypeLandmark:
1566 s = "Landmark or vanity address"
1567 case LLDPLocationAddressTypeAdditional:
1568 s = "Additional location information"
1569 case LLDPLocationAddressTypeName:
1570 s = "Name"
1571 case LLDPLocationAddressTypePostal:
1572 s = "Postal/ZIP code"
1573 case LLDPLocationAddressTypeBuilding:
1574 s = "Building"
1575 case LLDPLocationAddressTypeUnit:
1576 s = "Unit"
1577 case LLDPLocationAddressTypeFloor:
1578 s = "Floor"
1579 case LLDPLocationAddressTypeRoom:
1580 s = "Room number"
1581 case LLDPLocationAddressTypePlace:
1582 s = "Place type"
1583 case LLDPLocationAddressTypeScript:
1584 s = "Script"
1585 default:
1586 s = "Unknown"
1587 }
1588 return
1589}
1590
1591func checkLLDPTLVLen(v LinkLayerDiscoveryValue, l int) (err error) {
1592 if len(v.Value) < l {
1593 err = fmt.Errorf("Invalid TLV %v length %d (wanted mimimum %v", v.Type, len(v.Value), l)
1594 }
1595 return
1596}
1597
1598func checkLLDPOrgSpecificLen(o LLDPOrgSpecificTLV, l int) (err error) {
1599 if len(o.Info) < l {
1600 err = fmt.Errorf("Invalid Org Specific TLV %v length %d (wanted minimum %v)", o.SubType, len(o.Info), l)
1601 }
1602 return
1603}