github.com/gopacket/gopacket@v1.1.0/layers/ospf.go (about)

     1  // Copyright 2017 Google, Inc. All rights reserved.
     2  //
     3  // Use of this source code is governed by a BSD-style license
     4  // that can be found in the LICENSE file in the root of the source
     5  // tree.
     6  
     7  package layers
     8  
     9  import (
    10  	"encoding/binary"
    11  	"errors"
    12  	"fmt"
    13  
    14  	"github.com/gopacket/gopacket"
    15  )
    16  
    17  // OSPFType denotes what kind of OSPF type it is
    18  type OSPFType uint8
    19  
    20  // Potential values for OSPF.Type.
    21  const (
    22  	OSPFHello                   OSPFType = 1
    23  	OSPFDatabaseDescription     OSPFType = 2
    24  	OSPFLinkStateRequest        OSPFType = 3
    25  	OSPFLinkStateUpdate         OSPFType = 4
    26  	OSPFLinkStateAcknowledgment OSPFType = 5
    27  )
    28  
    29  // LSA Function Codes for LSAheader.LSType
    30  const (
    31  	RouterLSAtypeV2         = 0x1
    32  	RouterLSAtype           = 0x2001
    33  	NetworkLSAtypeV2        = 0x2
    34  	NetworkLSAtype          = 0x2002
    35  	SummaryLSANetworktypeV2 = 0x3
    36  	InterAreaPrefixLSAtype  = 0x2003
    37  	SummaryLSAASBRtypeV2    = 0x4
    38  	InterAreaRouterLSAtype  = 0x2004
    39  	ASExternalLSAtypeV2     = 0x5
    40  	ASExternalLSAtype       = 0x4005
    41  	NSSALSAtype             = 0x2007
    42  	NSSALSAtypeV2           = 0x7
    43  	LinkLSAtype             = 0x0008
    44  	IntraAreaPrefixLSAtype  = 0x2009
    45  )
    46  
    47  // String conversions for OSPFType
    48  func (i OSPFType) String() string {
    49  	switch i {
    50  	case OSPFHello:
    51  		return "Hello"
    52  	case OSPFDatabaseDescription:
    53  		return "Database Description"
    54  	case OSPFLinkStateRequest:
    55  		return "Link State Request"
    56  	case OSPFLinkStateUpdate:
    57  		return "Link State Update"
    58  	case OSPFLinkStateAcknowledgment:
    59  		return "Link State Acknowledgment"
    60  	default:
    61  		return ""
    62  	}
    63  }
    64  
    65  // Prefix extends IntraAreaPrefixLSA
    66  type Prefix struct {
    67  	PrefixLength  uint8
    68  	PrefixOptions uint8
    69  	Metric        uint16
    70  	AddressPrefix []byte
    71  }
    72  
    73  // IntraAreaPrefixLSA is the struct from RFC 5340  A.4.10.
    74  type IntraAreaPrefixLSA struct {
    75  	NumOfPrefixes  uint16
    76  	RefLSType      uint16
    77  	RefLinkStateID uint32
    78  	RefAdvRouter   uint32
    79  	Prefixes       []Prefix
    80  }
    81  
    82  // LinkLSA is the struct from RFC 5340  A.4.9.
    83  type LinkLSA struct {
    84  	RtrPriority      uint8
    85  	Options          uint32
    86  	LinkLocalAddress []byte
    87  	NumOfPrefixes    uint32
    88  	Prefixes         []Prefix
    89  }
    90  
    91  // ASExternalLSAV2 is the struct from RFC 2328  A.4.5.
    92  type ASExternalLSAV2 struct {
    93  	NetworkMask       uint32
    94  	ExternalBit       uint8
    95  	Metric            uint32
    96  	ForwardingAddress uint32
    97  	ExternalRouteTag  uint32
    98  }
    99  
   100  // ASExternalLSA is the struct from RFC 5340  A.4.7.
   101  type ASExternalLSA struct {
   102  	Flags             uint8
   103  	Metric            uint32
   104  	PrefixLength      uint8
   105  	PrefixOptions     uint8
   106  	RefLSType         uint16
   107  	AddressPrefix     []byte
   108  	ForwardingAddress []byte
   109  	ExternalRouteTag  uint32
   110  	RefLinkStateID    uint32
   111  }
   112  
   113  // InterAreaRouterLSA is the struct from RFC 5340  A.4.6.
   114  type InterAreaRouterLSA struct {
   115  	Options             uint32
   116  	Metric              uint32
   117  	DestinationRouterID uint32
   118  }
   119  
   120  // InterAreaPrefixLSA is the struct from RFC 5340  A.4.5.
   121  type InterAreaPrefixLSA struct {
   122  	Metric        uint32
   123  	PrefixLength  uint8
   124  	PrefixOptions uint8
   125  	AddressPrefix []byte
   126  }
   127  
   128  // NetworkLSA is the struct from RFC 5340  A.4.4.
   129  type NetworkLSA struct {
   130  	Options        uint32
   131  	AttachedRouter []uint32
   132  }
   133  
   134  // NetworkLSAV2 is the struct from RFC 2328  A.4.3.
   135  type NetworkLSAV2 struct {
   136  	NetworkMask    uint32
   137  	AttachedRouter []uint32
   138  }
   139  
   140  // RouterV2 extends RouterLSAV2
   141  type RouterV2 struct {
   142  	Type     uint8
   143  	LinkID   uint32
   144  	LinkData uint32
   145  	Metric   uint16
   146  }
   147  
   148  // RouterLSAV2 is the struct from RFC 2328  A.4.2.
   149  type RouterLSAV2 struct {
   150  	Flags   uint8
   151  	Links   uint16
   152  	Routers []RouterV2
   153  }
   154  
   155  // Router extends RouterLSA
   156  type Router struct {
   157  	Type                uint8
   158  	Metric              uint16
   159  	InterfaceID         uint32
   160  	NeighborInterfaceID uint32
   161  	NeighborRouterID    uint32
   162  }
   163  
   164  // RouterLSA is the struct from RFC 5340  A.4.3.
   165  type RouterLSA struct {
   166  	Flags   uint8
   167  	Options uint32
   168  	Routers []Router
   169  }
   170  
   171  // LSAheader is the struct from RFC 5340  A.4.2 and RFC 2328 A.4.1.
   172  type LSAheader struct {
   173  	LSAge       uint16
   174  	LSType      uint16
   175  	LinkStateID uint32
   176  	AdvRouter   uint32
   177  	LSSeqNumber uint32
   178  	LSChecksum  uint16
   179  	Length      uint16
   180  	LSOptions   uint8
   181  }
   182  
   183  // LSA links LSAheader with the structs from RFC 5340  A.4.
   184  type LSA struct {
   185  	LSAheader
   186  	Content interface{}
   187  }
   188  
   189  // LSUpdate is the struct from RFC 5340  A.3.5.
   190  type LSUpdate struct {
   191  	NumOfLSAs uint32
   192  	LSAs      []LSA
   193  }
   194  
   195  // LSReq is the struct from RFC 5340  A.3.4.
   196  type LSReq struct {
   197  	LSType    uint16
   198  	LSID      uint32
   199  	AdvRouter uint32
   200  }
   201  
   202  // DbDescPkg is the struct from RFC 5340  A.3.3.
   203  type DbDescPkg struct {
   204  	Options      uint32
   205  	InterfaceMTU uint16
   206  	Flags        uint16
   207  	DDSeqNumber  uint32
   208  	LSAinfo      []LSAheader
   209  }
   210  
   211  // HelloPkg  is the struct from RFC 5340  A.3.2.
   212  type HelloPkg struct {
   213  	InterfaceID              uint32
   214  	RtrPriority              uint8
   215  	Options                  uint32
   216  	HelloInterval            uint16
   217  	RouterDeadInterval       uint32
   218  	DesignatedRouterID       uint32
   219  	BackupDesignatedRouterID uint32
   220  	NeighborID               []uint32
   221  }
   222  
   223  // HelloPkgV2 extends the HelloPkg struct with OSPFv2 information
   224  type HelloPkgV2 struct {
   225  	HelloPkg
   226  	NetworkMask uint32
   227  }
   228  
   229  // OSPF is a basic OSPF packet header with common fields of Version 2 and Version 3.
   230  type OSPF struct {
   231  	Version      uint8
   232  	Type         OSPFType
   233  	PacketLength uint16
   234  	RouterID     uint32
   235  	AreaID       uint32
   236  	Checksum     uint16
   237  	Content      interface{}
   238  }
   239  
   240  // OSPFv2 extend the OSPF head with version 2 specific fields
   241  type OSPFv2 struct {
   242  	BaseLayer
   243  	OSPF
   244  	AuType         uint16
   245  	Authentication uint64
   246  }
   247  
   248  // OSPFv3 extend the OSPF head with version 3 specific fields
   249  type OSPFv3 struct {
   250  	BaseLayer
   251  	OSPF
   252  	Instance uint8
   253  	Reserved uint8
   254  }
   255  
   256  // getLSAsv2 parses the LSA information from the packet for OSPFv2
   257  func getLSAsv2(num uint32, data []byte) ([]LSA, error) {
   258  	var lsas []LSA
   259  	var i uint32 = 0
   260  	var offset uint32 = 0
   261  	for ; i < num; i++ {
   262  		lstype := uint16(data[offset+3])
   263  		lsalength := binary.BigEndian.Uint16(data[offset+18 : offset+20])
   264  		content, err := extractLSAInformation(lstype, lsalength, data[offset:])
   265  		if err != nil {
   266  			return nil, fmt.Errorf("Could not extract Link State type.")
   267  		}
   268  		lsa := LSA{
   269  			LSAheader: LSAheader{
   270  				LSAge:       binary.BigEndian.Uint16(data[offset : offset+2]),
   271  				LSOptions:   data[offset+2],
   272  				LSType:      lstype,
   273  				LinkStateID: binary.BigEndian.Uint32(data[offset+4 : offset+8]),
   274  				AdvRouter:   binary.BigEndian.Uint32(data[offset+8 : offset+12]),
   275  				LSSeqNumber: binary.BigEndian.Uint32(data[offset+12 : offset+16]),
   276  				LSChecksum:  binary.BigEndian.Uint16(data[offset+16 : offset+18]),
   277  				Length:      lsalength,
   278  			},
   279  			Content: content,
   280  		}
   281  		lsas = append(lsas, lsa)
   282  		offset += uint32(lsalength)
   283  	}
   284  	return lsas, nil
   285  }
   286  
   287  // extractLSAInformation extracts all the LSA information
   288  func extractLSAInformation(lstype, lsalength uint16, data []byte) (interface{}, error) {
   289  	if lsalength < 20 {
   290  		return nil, fmt.Errorf("Link State header length %v too short, %v required", lsalength, 20)
   291  	}
   292  	if len(data) < int(lsalength) {
   293  		return nil, fmt.Errorf("Link State header length %v too short, %v required", len(data), lsalength)
   294  	}
   295  	var content interface{}
   296  	switch lstype {
   297  	case RouterLSAtypeV2:
   298  		var routers []RouterV2
   299  		var j uint32
   300  		for j = 24; j < uint32(lsalength); j += 12 {
   301  			if len(data) < int(j+12) {
   302  				return nil, errors.New("LSAtypeV2 too small")
   303  			}
   304  			router := RouterV2{
   305  				LinkID:   binary.BigEndian.Uint32(data[j : j+4]),
   306  				LinkData: binary.BigEndian.Uint32(data[j+4 : j+8]),
   307  				Type:     uint8(data[j+8]),
   308  				Metric:   binary.BigEndian.Uint16(data[j+10 : j+12]),
   309  			}
   310  			routers = append(routers, router)
   311  		}
   312  		if len(data) < 24 {
   313  			return nil, errors.New("LSAtypeV2 too small")
   314  		}
   315  		links := binary.BigEndian.Uint16(data[22:24])
   316  		content = RouterLSAV2{
   317  			Flags:   data[20],
   318  			Links:   links,
   319  			Routers: routers,
   320  		}
   321  	case NSSALSAtypeV2:
   322  		fallthrough
   323  	case ASExternalLSAtypeV2:
   324  		content = ASExternalLSAV2{
   325  			NetworkMask:       binary.BigEndian.Uint32(data[20:24]),
   326  			ExternalBit:       data[24] & 0x80,
   327  			Metric:            binary.BigEndian.Uint32(data[24:28]) & 0x00FFFFFF,
   328  			ForwardingAddress: binary.BigEndian.Uint32(data[28:32]),
   329  			ExternalRouteTag:  binary.BigEndian.Uint32(data[32:36]),
   330  		}
   331  	case NetworkLSAtypeV2:
   332  		var routers []uint32
   333  		var j uint32
   334  		for j = 24; j < uint32(lsalength); j += 4 {
   335  			routers = append(routers, binary.BigEndian.Uint32(data[j:j+4]))
   336  		}
   337  		content = NetworkLSAV2{
   338  			NetworkMask:    binary.BigEndian.Uint32(data[20:24]),
   339  			AttachedRouter: routers,
   340  		}
   341  	case RouterLSAtype:
   342  		var routers []Router
   343  		var j uint32
   344  		for j = 24; j < uint32(lsalength); j += 16 {
   345  			router := Router{
   346  				Type:                uint8(data[j]),
   347  				Metric:              binary.BigEndian.Uint16(data[j+2 : j+4]),
   348  				InterfaceID:         binary.BigEndian.Uint32(data[j+4 : j+8]),
   349  				NeighborInterfaceID: binary.BigEndian.Uint32(data[j+8 : j+12]),
   350  				NeighborRouterID:    binary.BigEndian.Uint32(data[j+12 : j+16]),
   351  			}
   352  			routers = append(routers, router)
   353  		}
   354  		content = RouterLSA{
   355  			Flags:   uint8(data[20]),
   356  			Options: binary.BigEndian.Uint32(data[20:24]) & 0x00FFFFFF,
   357  			Routers: routers,
   358  		}
   359  	case NetworkLSAtype:
   360  		var routers []uint32
   361  		var j uint32
   362  		for j = 24; j < uint32(lsalength); j += 4 {
   363  			routers = append(routers, binary.BigEndian.Uint32(data[j:j+4]))
   364  		}
   365  		content = NetworkLSA{
   366  			Options:        binary.BigEndian.Uint32(data[20:24]) & 0x00FFFFFF,
   367  			AttachedRouter: routers,
   368  		}
   369  	case InterAreaPrefixLSAtype:
   370  		content = InterAreaPrefixLSA{
   371  			Metric:        binary.BigEndian.Uint32(data[20:24]) & 0x00FFFFFF,
   372  			PrefixLength:  uint8(data[24]),
   373  			PrefixOptions: uint8(data[25]),
   374  			AddressPrefix: data[28:uint32(lsalength)],
   375  		}
   376  	case InterAreaRouterLSAtype:
   377  		content = InterAreaRouterLSA{
   378  			Options:             binary.BigEndian.Uint32(data[20:24]) & 0x00FFFFFF,
   379  			Metric:              binary.BigEndian.Uint32(data[24:28]) & 0x00FFFFFF,
   380  			DestinationRouterID: binary.BigEndian.Uint32(data[28:32]),
   381  		}
   382  	case ASExternalLSAtype:
   383  		fallthrough
   384  	case NSSALSAtype:
   385  		flags := uint8(data[20])
   386  		prefixLen := uint8(data[24]) / 8
   387  		var forwardingAddress []byte
   388  		if (flags & 0x02) == 0x02 {
   389  			forwardingAddress = data[28+uint32(prefixLen) : 28+uint32(prefixLen)+16]
   390  		}
   391  		content = ASExternalLSA{
   392  			Flags:             flags,
   393  			Metric:            binary.BigEndian.Uint32(data[20:24]) & 0x00FFFFFF,
   394  			PrefixLength:      prefixLen,
   395  			PrefixOptions:     uint8(data[25]),
   396  			RefLSType:         binary.BigEndian.Uint16(data[26:28]),
   397  			AddressPrefix:     data[28 : 28+uint32(prefixLen)],
   398  			ForwardingAddress: forwardingAddress,
   399  		}
   400  	case LinkLSAtype:
   401  		var prefixes []Prefix
   402  		var prefixOffset uint32 = 44
   403  		var j uint32
   404  		numOfPrefixes := binary.BigEndian.Uint32(data[40:44])
   405  		for j = 0; j < numOfPrefixes; j++ {
   406  			prefixLen := uint8(data[prefixOffset])
   407  			prefix := Prefix{
   408  				PrefixLength:  prefixLen,
   409  				PrefixOptions: uint8(data[prefixOffset+1]),
   410  				AddressPrefix: data[prefixOffset+4 : prefixOffset+4+uint32(prefixLen)/8],
   411  			}
   412  			prefixes = append(prefixes, prefix)
   413  			prefixOffset = prefixOffset + 4 + uint32(prefixLen)/8
   414  		}
   415  		content = LinkLSA{
   416  			RtrPriority:      uint8(data[20]),
   417  			Options:          binary.BigEndian.Uint32(data[20:24]) & 0x00FFFFFF,
   418  			LinkLocalAddress: data[24:40],
   419  			NumOfPrefixes:    numOfPrefixes,
   420  			Prefixes:         prefixes,
   421  		}
   422  	case IntraAreaPrefixLSAtype:
   423  		var prefixes []Prefix
   424  		var prefixOffset uint32 = 32
   425  		var j uint16
   426  		numOfPrefixes := binary.BigEndian.Uint16(data[20:22])
   427  		for j = 0; j < numOfPrefixes; j++ {
   428  			prefixLen := uint8(data[prefixOffset])
   429  			prefix := Prefix{
   430  				PrefixLength:  prefixLen,
   431  				PrefixOptions: uint8(data[prefixOffset+1]),
   432  				Metric:        binary.BigEndian.Uint16(data[prefixOffset+2 : prefixOffset+4]),
   433  				AddressPrefix: data[prefixOffset+4 : prefixOffset+4+uint32(prefixLen)/8],
   434  			}
   435  			prefixes = append(prefixes, prefix)
   436  			prefixOffset = prefixOffset + 4 + uint32(prefixLen)
   437  		}
   438  		content = IntraAreaPrefixLSA{
   439  			NumOfPrefixes:  numOfPrefixes,
   440  			RefLSType:      binary.BigEndian.Uint16(data[22:24]),
   441  			RefLinkStateID: binary.BigEndian.Uint32(data[24:28]),
   442  			RefAdvRouter:   binary.BigEndian.Uint32(data[28:32]),
   443  			Prefixes:       prefixes,
   444  		}
   445  	default:
   446  		return nil, fmt.Errorf("Unknown Link State type.")
   447  	}
   448  	return content, nil
   449  }
   450  
   451  // getLSAs parses the LSA information from the packet for OSPFv3
   452  func getLSAs(num uint32, data []byte) ([]LSA, error) {
   453  	var lsas []LSA
   454  	var i uint32 = 0
   455  	var offset uint32 = 0
   456  	for ; i < num; i++ {
   457  		var content interface{}
   458  		lstype := binary.BigEndian.Uint16(data[offset+2 : offset+4])
   459  		lsalength := binary.BigEndian.Uint16(data[offset+18 : offset+20])
   460  
   461  		content, err := extractLSAInformation(lstype, lsalength, data[offset:])
   462  		if err != nil {
   463  			return nil, fmt.Errorf("Could not extract Link State type.")
   464  		}
   465  		lsa := LSA{
   466  			LSAheader: LSAheader{
   467  				LSAge:       binary.BigEndian.Uint16(data[offset : offset+2]),
   468  				LSType:      lstype,
   469  				LinkStateID: binary.BigEndian.Uint32(data[offset+4 : offset+8]),
   470  				AdvRouter:   binary.BigEndian.Uint32(data[offset+8 : offset+12]),
   471  				LSSeqNumber: binary.BigEndian.Uint32(data[offset+12 : offset+16]),
   472  				LSChecksum:  binary.BigEndian.Uint16(data[offset+16 : offset+18]),
   473  				Length:      lsalength,
   474  			},
   475  			Content: content,
   476  		}
   477  		lsas = append(lsas, lsa)
   478  		offset += uint32(lsalength)
   479  	}
   480  	return lsas, nil
   481  }
   482  
   483  // DecodeFromBytes decodes the given bytes into the OSPF layer.
   484  func (ospf *OSPFv2) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
   485  	if len(data) < 24 {
   486  		return fmt.Errorf("Packet too smal for OSPF Version 2")
   487  	}
   488  
   489  	ospf.Version = uint8(data[0])
   490  	ospf.Type = OSPFType(data[1])
   491  	ospf.PacketLength = binary.BigEndian.Uint16(data[2:4])
   492  	ospf.RouterID = binary.BigEndian.Uint32(data[4:8])
   493  	ospf.AreaID = binary.BigEndian.Uint32(data[8:12])
   494  	ospf.Checksum = binary.BigEndian.Uint16(data[12:14])
   495  	ospf.AuType = binary.BigEndian.Uint16(data[14:16])
   496  	ospf.Authentication = binary.BigEndian.Uint64(data[16:24])
   497  
   498  	switch ospf.Type {
   499  	case OSPFHello:
   500  		var neighbors []uint32
   501  		for i := 44; uint16(i+4) <= ospf.PacketLength; i += 4 {
   502  			neighbors = append(neighbors, binary.BigEndian.Uint32(data[i:i+4]))
   503  		}
   504  		ospf.Content = HelloPkgV2{
   505  			NetworkMask: binary.BigEndian.Uint32(data[24:28]),
   506  			HelloPkg: HelloPkg{
   507  				HelloInterval:            binary.BigEndian.Uint16(data[28:30]),
   508  				Options:                  uint32(data[30]),
   509  				RtrPriority:              uint8(data[31]),
   510  				RouterDeadInterval:       binary.BigEndian.Uint32(data[32:36]),
   511  				DesignatedRouterID:       binary.BigEndian.Uint32(data[36:40]),
   512  				BackupDesignatedRouterID: binary.BigEndian.Uint32(data[40:44]),
   513  				NeighborID:               neighbors,
   514  			},
   515  		}
   516  	case OSPFDatabaseDescription:
   517  		var lsas []LSAheader
   518  		for i := 32; uint16(i+20) <= ospf.PacketLength; i += 20 {
   519  			lsa := LSAheader{
   520  				LSAge:       binary.BigEndian.Uint16(data[i : i+2]),
   521  				LSType:      binary.BigEndian.Uint16(data[i+2 : i+4]),
   522  				LinkStateID: binary.BigEndian.Uint32(data[i+4 : i+8]),
   523  				AdvRouter:   binary.BigEndian.Uint32(data[i+8 : i+12]),
   524  				LSSeqNumber: binary.BigEndian.Uint32(data[i+12 : i+16]),
   525  				LSChecksum:  binary.BigEndian.Uint16(data[i+16 : i+18]),
   526  				Length:      binary.BigEndian.Uint16(data[i+18 : i+20]),
   527  			}
   528  			lsas = append(lsas, lsa)
   529  		}
   530  		ospf.Content = DbDescPkg{
   531  			InterfaceMTU: binary.BigEndian.Uint16(data[24:26]),
   532  			Options:      uint32(data[26]),
   533  			Flags:        uint16(data[27]),
   534  			DDSeqNumber:  binary.BigEndian.Uint32(data[28:32]),
   535  			LSAinfo:      lsas,
   536  		}
   537  	case OSPFLinkStateRequest:
   538  		var lsrs []LSReq
   539  		for i := 24; uint16(i+12) <= ospf.PacketLength; i += 12 {
   540  			lsr := LSReq{
   541  				LSType:    binary.BigEndian.Uint16(data[i+2 : i+4]),
   542  				LSID:      binary.BigEndian.Uint32(data[i+4 : i+8]),
   543  				AdvRouter: binary.BigEndian.Uint32(data[i+8 : i+12]),
   544  			}
   545  			lsrs = append(lsrs, lsr)
   546  		}
   547  		ospf.Content = lsrs
   548  	case OSPFLinkStateUpdate:
   549  		num := binary.BigEndian.Uint32(data[24:28])
   550  
   551  		lsas, err := getLSAsv2(num, data[28:])
   552  		if err != nil {
   553  			return fmt.Errorf("Cannot parse Link State Update packet: %v", err)
   554  		}
   555  		ospf.Content = LSUpdate{
   556  			NumOfLSAs: num,
   557  			LSAs:      lsas,
   558  		}
   559  	case OSPFLinkStateAcknowledgment:
   560  		var lsas []LSAheader
   561  		for i := 24; uint16(i+20) <= ospf.PacketLength; i += 20 {
   562  			lsa := LSAheader{
   563  				LSAge:       binary.BigEndian.Uint16(data[i : i+2]),
   564  				LSOptions:   data[i+2],
   565  				LSType:      uint16(data[i+3]),
   566  				LinkStateID: binary.BigEndian.Uint32(data[i+4 : i+8]),
   567  				AdvRouter:   binary.BigEndian.Uint32(data[i+8 : i+12]),
   568  				LSSeqNumber: binary.BigEndian.Uint32(data[i+12 : i+16]),
   569  				LSChecksum:  binary.BigEndian.Uint16(data[i+16 : i+18]),
   570  				Length:      binary.BigEndian.Uint16(data[i+18 : i+20]),
   571  			}
   572  			lsas = append(lsas, lsa)
   573  		}
   574  		ospf.Content = lsas
   575  	}
   576  	return nil
   577  }
   578  
   579  // DecodeFromBytes decodes the given bytes into the OSPF layer.
   580  func (ospf *OSPFv3) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
   581  
   582  	if len(data) < 16 {
   583  		return fmt.Errorf("Packet too smal for OSPF Version 3")
   584  	}
   585  
   586  	ospf.Version = uint8(data[0])
   587  	ospf.Type = OSPFType(data[1])
   588  	ospf.PacketLength = binary.BigEndian.Uint16(data[2:4])
   589  	ospf.RouterID = binary.BigEndian.Uint32(data[4:8])
   590  	ospf.AreaID = binary.BigEndian.Uint32(data[8:12])
   591  	ospf.Checksum = binary.BigEndian.Uint16(data[12:14])
   592  	ospf.Instance = uint8(data[14])
   593  	ospf.Reserved = uint8(data[15])
   594  
   595  	switch ospf.Type {
   596  	case OSPFHello:
   597  		var neighbors []uint32
   598  		for i := 36; uint16(i+4) <= ospf.PacketLength; i += 4 {
   599  			neighbors = append(neighbors, binary.BigEndian.Uint32(data[i:i+4]))
   600  		}
   601  		ospf.Content = HelloPkg{
   602  			InterfaceID:              binary.BigEndian.Uint32(data[16:20]),
   603  			RtrPriority:              uint8(data[20]),
   604  			Options:                  binary.BigEndian.Uint32(data[21:25]) >> 8,
   605  			HelloInterval:            binary.BigEndian.Uint16(data[24:26]),
   606  			RouterDeadInterval:       uint32(binary.BigEndian.Uint16(data[26:28])),
   607  			DesignatedRouterID:       binary.BigEndian.Uint32(data[28:32]),
   608  			BackupDesignatedRouterID: binary.BigEndian.Uint32(data[32:36]),
   609  			NeighborID:               neighbors,
   610  		}
   611  	case OSPFDatabaseDescription:
   612  		var lsas []LSAheader
   613  		for i := 28; uint16(i+20) <= ospf.PacketLength; i += 20 {
   614  			lsa := LSAheader{
   615  				LSAge:       binary.BigEndian.Uint16(data[i : i+2]),
   616  				LSType:      binary.BigEndian.Uint16(data[i+2 : i+4]),
   617  				LinkStateID: binary.BigEndian.Uint32(data[i+4 : i+8]),
   618  				AdvRouter:   binary.BigEndian.Uint32(data[i+8 : i+12]),
   619  				LSSeqNumber: binary.BigEndian.Uint32(data[i+12 : i+16]),
   620  				LSChecksum:  binary.BigEndian.Uint16(data[i+16 : i+18]),
   621  				Length:      binary.BigEndian.Uint16(data[i+18 : i+20]),
   622  			}
   623  			lsas = append(lsas, lsa)
   624  		}
   625  		ospf.Content = DbDescPkg{
   626  			Options:      binary.BigEndian.Uint32(data[16:20]) & 0x00FFFFFF,
   627  			InterfaceMTU: binary.BigEndian.Uint16(data[20:22]),
   628  			Flags:        binary.BigEndian.Uint16(data[22:24]),
   629  			DDSeqNumber:  binary.BigEndian.Uint32(data[24:28]),
   630  			LSAinfo:      lsas,
   631  		}
   632  	case OSPFLinkStateRequest:
   633  		var lsrs []LSReq
   634  		for i := 16; uint16(i+12) <= ospf.PacketLength; i += 12 {
   635  			lsr := LSReq{
   636  				LSType:    binary.BigEndian.Uint16(data[i+2 : i+4]),
   637  				LSID:      binary.BigEndian.Uint32(data[i+4 : i+8]),
   638  				AdvRouter: binary.BigEndian.Uint32(data[i+8 : i+12]),
   639  			}
   640  			lsrs = append(lsrs, lsr)
   641  		}
   642  		ospf.Content = lsrs
   643  	case OSPFLinkStateUpdate:
   644  		num := binary.BigEndian.Uint32(data[16:20])
   645  		lsas, err := getLSAs(num, data[20:])
   646  		if err != nil {
   647  			return fmt.Errorf("Cannot parse Link State Update packet: %v", err)
   648  		}
   649  		ospf.Content = LSUpdate{
   650  			NumOfLSAs: num,
   651  			LSAs:      lsas,
   652  		}
   653  
   654  	case OSPFLinkStateAcknowledgment:
   655  		var lsas []LSAheader
   656  		for i := 16; uint16(i+20) <= ospf.PacketLength; i += 20 {
   657  			lsa := LSAheader{
   658  				LSAge:       binary.BigEndian.Uint16(data[i : i+2]),
   659  				LSType:      binary.BigEndian.Uint16(data[i+2 : i+4]),
   660  				LinkStateID: binary.BigEndian.Uint32(data[i+4 : i+8]),
   661  				AdvRouter:   binary.BigEndian.Uint32(data[i+8 : i+12]),
   662  				LSSeqNumber: binary.BigEndian.Uint32(data[i+12 : i+16]),
   663  				LSChecksum:  binary.BigEndian.Uint16(data[i+16 : i+18]),
   664  				Length:      binary.BigEndian.Uint16(data[i+18 : i+20]),
   665  			}
   666  			lsas = append(lsas, lsa)
   667  		}
   668  		ospf.Content = lsas
   669  	default:
   670  	}
   671  
   672  	return nil
   673  }
   674  
   675  // LayerType returns LayerTypeOSPF
   676  func (ospf *OSPFv2) LayerType() gopacket.LayerType {
   677  	return LayerTypeOSPF
   678  }
   679  func (ospf *OSPFv3) LayerType() gopacket.LayerType {
   680  	return LayerTypeOSPF
   681  }
   682  
   683  // NextLayerType returns the layer type contained by this DecodingLayer.
   684  func (ospf *OSPFv2) NextLayerType() gopacket.LayerType {
   685  	return gopacket.LayerTypeZero
   686  }
   687  func (ospf *OSPFv3) NextLayerType() gopacket.LayerType {
   688  	return gopacket.LayerTypeZero
   689  }
   690  
   691  // CanDecode returns the set of layer types that this DecodingLayer can decode.
   692  func (ospf *OSPFv2) CanDecode() gopacket.LayerClass {
   693  	return LayerTypeOSPF
   694  }
   695  func (ospf *OSPFv3) CanDecode() gopacket.LayerClass {
   696  	return LayerTypeOSPF
   697  }
   698  
   699  func decodeOSPF(data []byte, p gopacket.PacketBuilder) error {
   700  	if len(data) < 14 {
   701  		return fmt.Errorf("Packet too smal for OSPF")
   702  	}
   703  
   704  	switch uint8(data[0]) {
   705  	case 2:
   706  		ospf := &OSPFv2{}
   707  		return decodingLayerDecoder(ospf, data, p)
   708  	case 3:
   709  		ospf := &OSPFv3{}
   710  		return decodingLayerDecoder(ospf, data, p)
   711  	default:
   712  	}
   713  
   714  	return fmt.Errorf("Unable to determine OSPF type.")
   715  }