func extractLSAInformation(lstype, lsalength uint16, data []byte) (interface{}, error) {
	if lsalength < 20 {
		return nil, fmt.Errorf("Link State header length %v too short, %v required", lsalength, 20)
	}
	if len(data) < int(lsalength) {
		return nil, fmt.Errorf("Link State header length %v too short, %v required", len(data), lsalength)
	}
	var content interface{}
	switch lstype {
	case RouterLSAtypeV2:
		var routers []RouterV2
		links := binary.BigEndian.Uint16(data[22:24])
		content = RouterLSAV2{
			Flags:   data[20],
			Links:   links,
			Routers: routers,
		}
	case ASExternalLSAtypeV2:
		content = ASExternalLSAV2{
			NetworkMask:       binary.BigEndian.Uint32(data[20:24]),
			ExternalBit:       data[24] & 0x80,
			Metric:            binary.BigEndian.Uint32(data[24:28]) & 0x00FFFFFF,
			ForwardingAddress: binary.BigEndian.Uint32(data[28:32]),
			ExternalRouteTag:  binary.BigEndian.Uint32(data[32:36]),
		}
	case RouterLSAtype:
		var routers []Router
		var j uint32
		for j = 24; j < uint32(lsalength); j += 16 {
			router := Router{
				Type:                uint8(data[j]),
				Metric:              binary.BigEndian.Uint16(data[j+2 : j+4]),
				InterfaceID:         binary.BigEndian.Uint32(data[j+4 : j+8]),
				NeighborInterfaceID: binary.BigEndian.Uint32(data[j+8 : j+12]),
				NeighborRouterID:    binary.BigEndian.Uint32(data[j+12 : j+16]),
			}
			routers = append(routers, router)
		}
		content = RouterLSA{
			Flags:   uint8(data[20]),
			Options: binary.BigEndian.Uint32(data[20:24]) & 0x00FFFFFF,
			Routers: routers,
		}
	case NetworkLSAtype:
		var routers []uint32
		var j uint32
		for j = 24; j < uint32(lsalength); j += 4 {
			routers = append(routers, binary.BigEndian.Uint32(data[j:j+4]))
		}
		content = NetworkLSA{
			Options:        binary.BigEndian.Uint32(data[20:24]) & 0x00FFFFFF,
			AttachedRouter: routers,
		}
	case InterAreaPrefixLSAtype:
		content = InterAreaPrefixLSA{
			Metric:        binary.BigEndian.Uint32(data[20:24]) & 0x00FFFFFF,
			PrefixLength:  uint8(data[24]),
			PrefixOptions: uint8(data[25]),
			AddressPrefix: data[28:uint32(lsalength)],
		}
	case InterAreaRouterLSAtype:
		content = InterAreaRouterLSA{
			Options:             binary.BigEndian.Uint32(data[20:24]) & 0x00FFFFFF,
			Metric:              binary.BigEndian.Uint32(data[24:28]) & 0x00FFFFFF,
			DestinationRouterID: binary.BigEndian.Uint32(data[28:32]),
		}
	case ASExternalLSAtype:
		fallthrough
	case NSSALSAtype:
		flags := uint8(data[20])
		prefixLen := uint8(data[24]) / 8
		var forwardingAddress []byte
		if (flags & 0x02) == 0x02 {
			forwardingAddress = data[28+uint32(prefixLen) : 28+uint32(prefixLen)+16]
		}
		content = ASExternalLSA{
			Flags:             flags,
			Metric:            binary.BigEndian.Uint32(data[20:24]) & 0x00FFFFFF,
			PrefixLength:      prefixLen,
			PrefixOptions:     uint8(data[25]),
			RefLSType:         binary.BigEndian.Uint16(data[26:28]),
			AddressPrefix:     data[28 : 28+uint32(prefixLen)],
			ForwardingAddress: forwardingAddress,
		}
	case LinkLSAtype:
		var prefixes []Prefix
		var prefixOffset uint32 = 44
		var j uint32
		numOfPrefixes := binary.BigEndian.Uint32(data[40:44])
		for j = 0; j < numOfPrefixes; j++ {
			prefixLen := uint8(data[prefixOffset])
			prefix := Prefix{
				PrefixLength:  prefixLen,
				PrefixOptions: uint8(data[prefixOffset+1]),
				AddressPrefix: data[prefixOffset+4 : prefixOffset+4+uint32(prefixLen)/8],
			}
			prefixes = append(prefixes, prefix)
			prefixOffset = prefixOffset + 4 + uint32(prefixLen)/8
		}
		content = LinkLSA{
			RtrPriority:      uint8(data[20]),
			Options:          binary.BigEndian.Uint32(data[20:24]) & 0x00FFFFFF,
			LinkLocalAddress: data[24:40],
			NumOfPrefixes:    numOfPrefixes,
			Prefixes:         prefixes,
		}
	case IntraAreaPrefixLSAtype:
		var prefixes []Prefix
		var prefixOffset uint32 = 32
		var j uint16
		numOfPrefixes := binary.BigEndian.Uint16(data[20:22])
		for j = 0; j < numOfPrefixes; j++ {
			prefixLen := uint8(data[prefixOffset])
			prefix := Prefix{
				PrefixLength:  prefixLen,
				PrefixOptions: uint8(data[prefixOffset+1]),
				Metric:        binary.BigEndian.Uint16(data[prefixOffset+2 : prefixOffset+4]),
				AddressPrefix: data[prefixOffset+4 : prefixOffset+4+uint32(prefixLen)/8],
			}
			prefixes = append(prefixes, prefix)
			prefixOffset = prefixOffset + 4 + uint32(prefixLen)
		}
		content = IntraAreaPrefixLSA{
			NumOfPrefixes:  numOfPrefixes,
			RefLSType:      binary.BigEndian.Uint16(data[22:24]),
			RefLinkStateID: binary.BigEndian.Uint32(data[24:28]),
			RefAdvRouter:   binary.BigEndian.Uint32(data[28:32]),
			Prefixes:       prefixes,
		}
	default:
		return nil, fmt.Errorf("Unknown Link State type.")
	}
	return content, nil
}
extractLSAInformation extracts all the LSA information
package layers
import (
	"encoding/binary"
	"fmt"
	"github.com/google/gopacket"
)
type OSPFType uint8
const (
	OSPFHello                   OSPFType = 1
	OSPFDatabaseDescription     OSPFType = 2
	OSPFLinkStateRequest        OSPFType = 3
	OSPFLinkStateUpdate         OSPFType = 4
	OSPFLinkStateAcknowledgment OSPFType = 5
)
const (
	RouterLSAtypeV2         = 0x1
	RouterLSAtype           = 0x2001
	NetworkLSAtypeV2        = 0x2
	NetworkLSAtype          = 0x2002
	SummaryLSANetworktypeV2 = 0x3
	InterAreaPrefixLSAtype  = 0x2003
	SummaryLSAASBRtypeV2    = 0x4
	InterAreaRouterLSAtype  = 0x2004
	ASExternalLSAtypeV2     = 0x5
	ASExternalLSAtype       = 0x4005
	NSSALSAtype             = 0x2007
	LinkLSAtype             = 0x0008
	IntraAreaPrefixLSAtype  = 0x2009
)
func (i OSPFType) String() string {
	switch i {
	case OSPFHello:
		return "Hello"
	case OSPFDatabaseDescription:
		return "Database Description"
	case OSPFLinkStateRequest:
		return "Link State Request"
	case OSPFLinkStateUpdate:
		return "Link State Update"
	case OSPFLinkStateAcknowledgment:
		return "Link State Acknowledgment"
	default:
		return ""
	}
}
type Prefix struct {
	PrefixLength  uint8
	PrefixOptions uint8
	Metric        uint16
	AddressPrefix []byte
}
type IntraAreaPrefixLSA struct {
	NumOfPrefixes  uint16
	RefLSType      uint16
	RefLinkStateID uint32
	RefAdvRouter   uint32
	Prefixes       []Prefix
}
type LinkLSA struct {
	RtrPriority      uint8
	Options          uint32
	LinkLocalAddress []byte
	NumOfPrefixes    uint32
	Prefixes         []Prefix
}
type ASExternalLSAV2 struct {
	NetworkMask       uint32
	ExternalBit       uint8
	Metric            uint32
	ForwardingAddress uint32
	ExternalRouteTag  uint32
}
type ASExternalLSA struct {
	Flags             uint8
	Metric            uint32
	PrefixLength      uint8
	PrefixOptions     uint8
	RefLSType         uint16
	AddressPrefix     []byte
	ForwardingAddress []byte
	ExternalRouteTag  uint32
	RefLinkStateID    uint32
}
type InterAreaRouterLSA struct {
	Options             uint32
	Metric              uint32
	DestinationRouterID uint32
}
type InterAreaPrefixLSA struct {
	Metric        uint32
	PrefixLength  uint8
	PrefixOptions uint8
	AddressPrefix []byte
}
type NetworkLSA struct {
	Options        uint32
	AttachedRouter []uint32
}
type RouterV2 struct {
	Type     uint8
	LinkID   uint32
	LinkData uint32
	Metric   uint16
}
type RouterLSAV2 struct {
	Flags   uint8
	Links   uint16
	Routers []RouterV2
}
type Router struct {
	Type                uint8
	Metric              uint16
	InterfaceID         uint32
	NeighborInterfaceID uint32
	NeighborRouterID    uint32
}
type RouterLSA struct {
	Flags   uint8
	Options uint32
	Routers []Router
}
type LSAheader struct {
	LSAge       uint16
	LSType      uint16
	LinkStateID uint32
	AdvRouter   uint32
	LSSeqNumber uint32
	LSChecksum  uint16
	Length      uint16
	LSOptions   uint8
}
type LSA struct {
	LSAheader
	Content interface{}
}
type LSUpdate struct {
	NumOfLSAs uint32
	LSAs      []LSA
}
type LSReq struct {
	LSType    uint16
	LSID      uint32
	AdvRouter uint32
}
type DbDescPkg struct {
	Options      uint32
	InterfaceMTU uint16
	Flags        uint16
	DDSeqNumber  uint32
	LSAinfo      []LSAheader
}
type HelloPkg struct {
	InterfaceID              uint32
	RtrPriority              uint8
	Options                  uint32
	HelloInterval            uint16
	RouterDeadInterval       uint32
	DesignatedRouterID       uint32
	BackupDesignatedRouterID uint32
	NeighborID               []uint32
}
type HelloPkgV2 struct {
	HelloPkg
	NetworkMask uint32
}
type OSPF struct {
	Version      uint8
	Type         OSPFType
	PacketLength uint16
	RouterID     uint32
	AreaID       uint32
	Checksum     uint16
	Content      interface{}
}
type OSPFv2 struct {
	BaseLayer
	OSPF
	AuType         uint16
	Authentication uint64
}
type OSPFv3 struct {
	BaseLayer
	OSPF
	Instance uint8
	Reserved uint8
}
func getLSAsv2(num uint32, data []byte) ([]LSA, error) {
	var lsas []LSA
	var i uint32 = 0
	var offset uint32 = 0
	for ; i < num; i++ {
		lstype := uint16(data[offset+3])
		lsalength := binary.BigEndian.Uint16(data[offset+18 : offset+20])
		content, err := extractLSAInformation(lstype, lsalength, data[offset:])
		if err != nil {
			return nil, fmt.Errorf("Could not extract Link State type.")
		}
		lsa := LSA{
			LSAheader: LSAheader{
				LSAge:       binary.BigEndian.Uint16(data[offset : offset+2]),
				LSOptions:   data[offset+2],
				LSType:      lstype,
				LinkStateID: binary.BigEndian.Uint32(data[offset+4 : offset+8]),
				AdvRouter:   binary.BigEndian.Uint32(data[offset+8 : offset+12]),
				LSSeqNumber: binary.BigEndian.Uint32(data[offset+12 : offset+16]),
				LSChecksum:  binary.BigEndian.Uint16(data[offset+16 : offset+18]),
				Length:      lsalength,
			},
			Content: content,
		}
		lsas = append(lsas, lsa)
		offset += uint32(lsalength)
	}
	return lsas, nil
}