lldp.go 45 KB

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