1 // Copyright 2017 Google, Inc. All rights reserved.
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
13 "github.com/google/gopacket"
16 // OSPFType denotes what kind of OSPF type it is
19 // Potential values for OSPF.Type.
21 OSPFHello OSPFType = 1
22 OSPFDatabaseDescription OSPFType = 2
23 OSPFLinkStateRequest OSPFType = 3
24 OSPFLinkStateUpdate OSPFType = 4
25 OSPFLinkStateAcknowledgment OSPFType = 5
28 // LSA Function Codes for LSAheader.LSType
30 RouterLSAtype = 0x2001
31 NetworkLSAtype = 0x2002
32 InterAreaPrefixLSAtype = 0x2003
33 InterAreaRouterLSAtype = 0x2004
34 ASExternalLSAtype = 0x4005
37 IntraAreaPrefixLSAtype = 0x2009
40 // String conversions for OSPFType
41 func (i OSPFType) String() string {
45 case OSPFDatabaseDescription:
46 return "Database Description"
47 case OSPFLinkStateRequest:
48 return "Link State Request"
49 case OSPFLinkStateUpdate:
50 return "Link State Update"
51 case OSPFLinkStateAcknowledgment:
52 return "Link State Acknowledgment"
58 // Prefix extends IntraAreaPrefixLSA
66 // IntraAreaPrefixLSA is the struct from RFC 5340 A.4.10.
67 type IntraAreaPrefixLSA struct {
75 // LinkLSA is the struct from RFC 5340 A.4.9.
79 LinkLocalAddress []byte
84 // ASExternalLSA is the struct from RFC 5340 A.4.7.
85 type ASExternalLSA struct {
92 ForwardingAddress []byte
93 ExternalRouteTag uint32
97 // InterAreaRouterLSA is the struct from RFC 5340 A.4.6.
98 type InterAreaRouterLSA struct {
101 DestinationRouterID uint32
104 // InterAreaPrefixLSA is the struct from RFC 5340 A.4.5.
105 type InterAreaPrefixLSA struct {
112 // NetworkLSA is the struct from RFC 5340 A.4.4.
113 type NetworkLSA struct {
115 AttachedRouter []uint32
118 // Router extends RouterLSA
123 NeighborInterfaceID uint32
124 NeighborRouterID uint32
127 // RouterLSA is the struct from RFC 5340 A.4.3.
128 type RouterLSA struct {
134 // LSAheader is the struct from RFC 5340 A.4.2.
135 type LSAheader struct {
145 // LSA links LSAheader with the structs from RFC 5340 A.4.
151 // LSUpdate is the struct from RFC 5340 A.3.5.
152 type LSUpdate struct {
157 // LSReq is the struct from RFC 5340 A.3.4.
164 // DbDescPkg is the struct from RFC 5340 A.3.3.
165 type DbDescPkg struct {
173 // HelloPkg is the struct from RFC 5340 A.3.2.
174 type HelloPkg struct {
179 RouterDeadInterval uint16
180 DesignatedRouterID uint32
181 BackupDesignatedRouterID uint32
185 // HelloPkgV2 extends the HelloPkg struct with OSPFv2 information
186 type HelloPkgV2 struct {
191 // OSPF is a basic OSPF packet header with common fields of Version 2 and Version 3.
202 //OSPFv2 extend the OSPF head with version 2 specific fields
207 Authentication uint64
210 // OSPFv3 extend the OSPF head with version 3 specific fields
218 // getLSAs parses the LSA information from the packet
219 func getLSAs(num uint32, data []byte) ([]LSA, error) {
222 var offset uint32 = 0
224 var content interface{}
225 lstype := binary.BigEndian.Uint16(data[offset+2 : offset+4])
226 lsalength := binary.BigEndian.Uint16(data[offset+18 : offset+20])
232 for j = 24; j < uint32(lsalength); j += 16 {
234 Type: uint8(data[offset+j]),
235 Metric: binary.BigEndian.Uint16(data[offset+j+2 : offset+j+4]),
236 InterfaceID: binary.BigEndian.Uint32(data[offset+j+4 : offset+j+8]),
237 NeighborInterfaceID: binary.BigEndian.Uint32(data[offset+j+8 : offset+j+12]),
238 NeighborRouterID: binary.BigEndian.Uint32(data[offset+j+12 : offset+j+16]),
240 routers = append(routers, router)
243 Flags: uint8(data[offset+20]),
244 Options: binary.BigEndian.Uint32(data[offset+20:offset+24]) & 0x00FFFFFF,
250 for j = 24; j < uint32(lsalength); j += 4 {
251 routers = append(routers, binary.BigEndian.Uint32(data[offset+j:offset+j+4]))
253 content = NetworkLSA{
254 Options: binary.BigEndian.Uint32(data[offset+20:offset+24]) & 0x00FFFFFF,
255 AttachedRouter: routers,
257 case InterAreaPrefixLSAtype:
258 content = InterAreaPrefixLSA{
259 Metric: binary.BigEndian.Uint32(data[offset+20:offset+24]) & 0x00FFFFFF,
260 PrefixLength: uint8(data[offset+24]),
261 PrefixOptions: uint8(data[offset+25]),
262 AddressPrefix: data[offset+28 : offset+uint32(lsalength)],
264 case InterAreaRouterLSAtype:
265 content = InterAreaRouterLSA{
266 Options: binary.BigEndian.Uint32(data[offset+20:offset+24]) & 0x00FFFFFF,
267 Metric: binary.BigEndian.Uint32(data[offset+24:offset+28]) & 0x00FFFFFF,
268 DestinationRouterID: binary.BigEndian.Uint32(data[offset+28 : offset+32]),
270 case ASExternalLSAtype:
274 flags := uint8(data[offset+20])
275 prefixLen := uint8(data[offset+24]) / 8
276 var forwardingAddress []byte
277 if (flags & 0x02) == 0x02 {
278 forwardingAddress = data[offset+28+uint32(prefixLen) : offset+28+uint32(prefixLen)+16]
280 content = ASExternalLSA{
282 Metric: binary.BigEndian.Uint32(data[offset+20:offset+24]) & 0x00FFFFFF,
283 PrefixLength: prefixLen,
284 PrefixOptions: uint8(data[offset+25]),
285 RefLSType: binary.BigEndian.Uint16(data[offset+26 : offset+28]),
286 AddressPrefix: data[offset+28 : offset+28+uint32(prefixLen)],
287 ForwardingAddress: forwardingAddress,
290 var prefixes []Prefix
291 var prefixOffset uint32 = offset + 44
293 numOfPrefixes := binary.BigEndian.Uint32(data[offset+40 : offset+44])
294 for j = 0; j < numOfPrefixes; j++ {
295 prefixLen := uint8(data[prefixOffset])
297 PrefixLength: prefixLen,
298 PrefixOptions: uint8(data[prefixOffset+1]),
299 AddressPrefix: data[prefixOffset+4 : prefixOffset+4+uint32(prefixLen)/8],
301 prefixes = append(prefixes, prefix)
302 prefixOffset = prefixOffset + 4 + uint32(prefixLen)/8
305 RtrPriority: uint8(data[offset+20]),
306 Options: binary.BigEndian.Uint32(data[offset+20:offset+24]) & 0x00FFFFFF,
307 LinkLocalAddress: data[offset+24 : offset+40],
308 NumOfPrefixes: numOfPrefixes,
311 case IntraAreaPrefixLSAtype:
312 var prefixes []Prefix
313 var prefixOffset uint32 = offset + 32
315 numOfPrefixes := binary.BigEndian.Uint16(data[offset+20 : offset+22])
316 for j = 0; j < numOfPrefixes; j++ {
317 prefixLen := uint8(data[prefixOffset])
319 PrefixLength: prefixLen,
320 PrefixOptions: uint8(data[prefixOffset+1]),
321 Metric: binary.BigEndian.Uint16(data[prefixOffset+2 : prefixOffset+4]),
322 AddressPrefix: data[prefixOffset+4 : prefixOffset+4+uint32(prefixLen)/8],
324 prefixes = append(prefixes, prefix)
325 prefixOffset = prefixOffset + 4 + uint32(prefixLen)
327 content = IntraAreaPrefixLSA{
328 NumOfPrefixes: numOfPrefixes,
329 RefLSType: binary.BigEndian.Uint16(data[offset+22 : offset+24]),
330 RefLinkStateID: binary.BigEndian.Uint32(data[offset+24 : offset+28]),
331 RefAdvRouter: binary.BigEndian.Uint32(data[offset+28 : offset+32]),
335 return nil, fmt.Errorf("Unknown Link State type.")
338 LSAheader: LSAheader{
339 LSAge: binary.BigEndian.Uint16(data[offset : offset+2]),
341 LinkStateID: binary.BigEndian.Uint32(data[offset+4 : offset+8]),
342 AdvRouter: binary.BigEndian.Uint32(data[offset+8 : offset+12]),
343 LSSeqNumber: binary.BigEndian.Uint32(data[offset+12 : offset+16]),
344 LSChecksum: binary.BigEndian.Uint16(data[offset+16 : offset+18]),
349 lsas = append(lsas, lsa)
350 offset += uint32(lsalength)
355 // DecodeFromBytes decodes the given bytes into the OSPF layer.
356 func (ospf *OSPFv2) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
358 return fmt.Errorf("Packet too smal for OSPF Version 2")
361 ospf.Version = uint8(data[0])
362 ospf.Type = OSPFType(data[1])
363 ospf.PacketLength = binary.BigEndian.Uint16(data[2:4])
364 ospf.RouterID = binary.BigEndian.Uint32(data[4:8])
365 ospf.AreaID = binary.BigEndian.Uint32(data[8:12])
366 ospf.Checksum = binary.BigEndian.Uint16(data[12:14])
367 ospf.AuType = binary.BigEndian.Uint16(data[14:16])
368 ospf.Authentication = binary.BigEndian.Uint64(data[16:24])
373 // DecodeFromBytes decodes the given bytes into the OSPF layer.
374 func (ospf *OSPFv3) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
377 return fmt.Errorf("Packet too smal for OSPF Version 3")
380 ospf.Version = uint8(data[0])
381 ospf.Type = OSPFType(data[1])
382 ospf.PacketLength = binary.BigEndian.Uint16(data[2:4])
383 ospf.RouterID = binary.BigEndian.Uint32(data[4:8])
384 ospf.AreaID = binary.BigEndian.Uint32(data[8:12])
385 ospf.Checksum = binary.BigEndian.Uint16(data[12:14])
386 ospf.Instance = uint8(data[14])
387 ospf.Reserved = uint8(data[15])
391 var neighbors []uint32
392 for i := 36; uint16(i+4) <= ospf.PacketLength; i += 4 {
393 neighbors = append(neighbors, binary.BigEndian.Uint32(data[i:i+4]))
395 ospf.Content = HelloPkg{
396 InterfaceID: binary.BigEndian.Uint32(data[16:20]),
397 RtrPriority: uint8(data[20]),
398 Options: binary.BigEndian.Uint32(data[21:25]) >> 8,
399 HelloInterval: binary.BigEndian.Uint16(data[24:26]),
400 RouterDeadInterval: binary.BigEndian.Uint16(data[26:28]),
401 DesignatedRouterID: binary.BigEndian.Uint32(data[28:32]),
402 BackupDesignatedRouterID: binary.BigEndian.Uint32(data[32:36]),
403 NeighborID: neighbors,
405 case OSPFDatabaseDescription:
407 for i := 28; uint16(i+20) <= ospf.PacketLength; i += 20 {
409 LSAge: binary.BigEndian.Uint16(data[i : i+2]),
410 LSType: binary.BigEndian.Uint16(data[i+2 : i+4]),
411 LinkStateID: binary.BigEndian.Uint32(data[i+4 : i+8]),
412 AdvRouter: binary.BigEndian.Uint32(data[i+8 : i+12]),
413 LSSeqNumber: binary.BigEndian.Uint32(data[i+12 : i+16]),
414 LSChecksum: binary.BigEndian.Uint16(data[i+16 : i+18]),
415 Length: binary.BigEndian.Uint16(data[i+18 : i+20]),
417 lsas = append(lsas, lsa)
419 ospf.Content = DbDescPkg{
420 Options: binary.BigEndian.Uint32(data[16:20]) & 0x00FFFFFF,
421 InterfaceMTU: binary.BigEndian.Uint16(data[20:22]),
422 Flags: binary.BigEndian.Uint16(data[22:24]),
423 DDSeqNumber: binary.BigEndian.Uint32(data[24:28]),
426 case OSPFLinkStateRequest:
428 for i := 16; uint16(i+12) <= ospf.PacketLength; i += 12 {
430 LSType: binary.BigEndian.Uint16(data[i+2 : i+4]),
431 LSID: binary.BigEndian.Uint32(data[i+4 : i+8]),
432 AdvRouter: binary.BigEndian.Uint32(data[i+8 : i+12]),
434 lsrs = append(lsrs, lsr)
437 case OSPFLinkStateUpdate:
438 num := binary.BigEndian.Uint32(data[16:20])
439 lsas, err := getLSAs(num, data[20:])
441 return fmt.Errorf("Cannot parse Link State Update packet: %v", err)
443 ospf.Content = LSUpdate{
448 case OSPFLinkStateAcknowledgment:
450 for i := 16; uint16(i+20) <= ospf.PacketLength; i += 20 {
452 LSAge: binary.BigEndian.Uint16(data[i : i+2]),
453 LSType: binary.BigEndian.Uint16(data[i+2 : i+4]),
454 LinkStateID: binary.BigEndian.Uint32(data[i+4 : i+8]),
455 AdvRouter: binary.BigEndian.Uint32(data[i+8 : i+12]),
456 LSSeqNumber: binary.BigEndian.Uint32(data[i+12 : i+16]),
457 LSChecksum: binary.BigEndian.Uint16(data[i+16 : i+18]),
458 Length: binary.BigEndian.Uint16(data[i+18 : i+20]),
460 lsas = append(lsas, lsa)
469 // LayerType returns LayerTypeOSPF
470 func (ospf *OSPFv2) LayerType() gopacket.LayerType {
473 func (ospf *OSPFv3) LayerType() gopacket.LayerType {
477 // NextLayerType returns the layer type contained by this DecodingLayer.
478 func (ospf *OSPFv2) NextLayerType() gopacket.LayerType {
479 return gopacket.LayerTypeZero
481 func (ospf *OSPFv3) NextLayerType() gopacket.LayerType {
482 return gopacket.LayerTypeZero
485 // CanDecode returns the set of layer types that this DecodingLayer can decode.
486 func (ospf *OSPFv2) CanDecode() gopacket.LayerClass {
489 func (ospf *OSPFv3) CanDecode() gopacket.LayerClass {
493 func decodeOSPF(data []byte, p gopacket.PacketBuilder) error {
495 return fmt.Errorf("Packet too smal for OSPF")
498 switch uint8(data[0]) {
501 return decodingLayerDecoder(ospf, data, p)
504 return decodingLayerDecoder(ospf, data, p)
508 return fmt.Errorf("Unable to determine OSPF type.")