123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481 |
- package layers
- import (
- "encoding/binary"
- "errors"
- "github.com/google/gopacket"
- )
- const bfdMinimumRecordSizeInBytes int = 24
- type BFDVersion uint8
- type BFDDiagnostic uint8
- const (
- BFDDiagnosticNone BFDDiagnostic = 0
- BFDDiagnosticTimeExpired BFDDiagnostic = 1
- BFDDiagnosticEchoFailed BFDDiagnostic = 2
- BFDDiagnosticNeighborSignalDown BFDDiagnostic = 3
- BFDDiagnosticForwardPlaneReset BFDDiagnostic = 4
- BFDDiagnosticPathDown BFDDiagnostic = 5
- BFDDiagnosticConcatPathDown BFDDiagnostic = 6
- BFDDiagnosticAdminDown BFDDiagnostic = 7
- BFDDiagnosticRevConcatPathDown BFDDiagnostic = 8
- )
- func (bd BFDDiagnostic) String() string {
- switch bd {
- default:
- return "Unknown"
- case BFDDiagnosticNone:
- return "None"
- case BFDDiagnosticTimeExpired:
- return "Control Detection Time Expired"
- case BFDDiagnosticEchoFailed:
- return "Echo Function Failed"
- case BFDDiagnosticNeighborSignalDown:
- return "Neighbor Signaled Session Down"
- case BFDDiagnosticForwardPlaneReset:
- return "Forwarding Plane Reset"
- case BFDDiagnosticPathDown:
- return "Path Down"
- case BFDDiagnosticConcatPathDown:
- return "Concatenated Path Down"
- case BFDDiagnosticAdminDown:
- return "Administratively Down"
- case BFDDiagnosticRevConcatPathDown:
- return "Reverse Concatenated Path Down"
- }
- }
- type BFDState uint8
- const (
- BFDStateAdminDown BFDState = 0
- BFDStateDown BFDState = 1
- BFDStateInit BFDState = 2
- BFDStateUp BFDState = 3
- )
- func (s BFDState) String() string {
- switch s {
- default:
- return "Unknown"
- case BFDStateAdminDown:
- return "Admin Down"
- case BFDStateDown:
- return "Down"
- case BFDStateInit:
- return "Init"
- case BFDStateUp:
- return "Up"
- }
- }
- type BFDDetectMultiplier uint8
- type BFDDiscriminator uint32
- type BFDTimeInterval uint32
- type BFDAuthType uint8
- const (
- BFDAuthTypeNone BFDAuthType = 0
- BFDAuthTypePassword BFDAuthType = 1
- BFDAuthTypeKeyedMD5 BFDAuthType = 2
- BFDAuthTypeMeticulousKeyedMD5 BFDAuthType = 3
- BFDAuthTypeKeyedSHA1 BFDAuthType = 4
- BFDAuthTypeMeticulousKeyedSHA1 BFDAuthType = 5
- )
- func (at BFDAuthType) String() string {
- switch at {
- default:
- return "Unknown"
- case BFDAuthTypeNone:
- return "No Authentication"
- case BFDAuthTypePassword:
- return "Simple Password"
- case BFDAuthTypeKeyedMD5:
- return "Keyed MD5"
- case BFDAuthTypeMeticulousKeyedMD5:
- return "Meticulous Keyed MD5"
- case BFDAuthTypeKeyedSHA1:
- return "Keyed SHA1"
- case BFDAuthTypeMeticulousKeyedSHA1:
- return "Meticulous Keyed SHA1"
- }
- }
- type BFDAuthKeyID uint8
- type BFDAuthSequenceNumber uint32
- type BFDAuthData []byte
- type BFDAuthHeader struct {
- AuthType BFDAuthType
- KeyID BFDAuthKeyID
- SequenceNumber BFDAuthSequenceNumber
- Data BFDAuthData
- }
- func (h *BFDAuthHeader) Length() int {
- switch h.AuthType {
- case BFDAuthTypePassword:
- return 3 + len(h.Data)
- case BFDAuthTypeKeyedMD5, BFDAuthTypeMeticulousKeyedMD5:
- return 8 + len(h.Data)
- case BFDAuthTypeKeyedSHA1, BFDAuthTypeMeticulousKeyedSHA1:
- return 8 + len(h.Data)
- default:
- return 0
- }
- }
- type BFD struct {
- BaseLayer
- Version BFDVersion
- Diagnostic BFDDiagnostic
- State BFDState
- Poll bool
- Final bool
- ControlPlaneIndependent bool
- AuthPresent bool
- Demand bool
- Multipoint bool
- DetectMultiplier BFDDetectMultiplier
- MyDiscriminator BFDDiscriminator
- YourDiscriminator BFDDiscriminator
- DesiredMinTxInterval BFDTimeInterval
- RequiredMinRxInterval BFDTimeInterval
- RequiredMinEchoRxInterval BFDTimeInterval
- AuthHeader *BFDAuthHeader
- }
- func (d *BFD) Length() int {
- if d.AuthPresent && (d.AuthHeader != nil) {
- return bfdMinimumRecordSizeInBytes + d.AuthHeader.Length()
- }
- return bfdMinimumRecordSizeInBytes
- }
- func (d *BFD) LayerType() gopacket.LayerType {
- return LayerTypeBFD
- }
- func decodeBFD(data []byte, p gopacket.PacketBuilder) error {
-
- d := &BFD{}
- err := d.DecodeFromBytes(data, p)
- if err != nil {
- return err
- }
-
-
- p.AddLayer(d)
- p.SetApplicationLayer(d)
- return nil
- }
- func (d *BFD) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
-
- if len(data) < bfdMinimumRecordSizeInBytes {
- df.SetTruncated()
- return errors.New("BFD packet too short")
- }
- pLen := uint8(data[3])
- if len(data) != int(pLen) {
- return errors.New("BFD packet length does not match")
- }
-
-
-
-
- d.BaseLayer = BaseLayer{Contents: data[:len(data)]}
-
-
-
-
- d.Version = BFDVersion(((data[0] & 0xE0) >> 5))
- d.Diagnostic = BFDDiagnostic(data[0] & 0x1F)
- data = data[1:]
- d.State = BFDState((data[0] & 0xC0) >> 6)
- d.Poll = data[0]&0x20 != 0
- d.Final = data[0]&0x10 != 0
- d.ControlPlaneIndependent = data[0]&0x08 != 0
- d.AuthPresent = data[0]&0x04 != 0
- d.Demand = data[0]&0x02 != 0
- d.Multipoint = data[0]&0x01 != 0
- data = data[1:]
- data, d.DetectMultiplier = data[1:], BFDDetectMultiplier(data[0])
- data, _ = data[1:], uint8(data[0])
-
- data, d.MyDiscriminator = data[4:], BFDDiscriminator(binary.BigEndian.Uint32(data[:4]))
- data, d.YourDiscriminator = data[4:], BFDDiscriminator(binary.BigEndian.Uint32(data[:4]))
- data, d.DesiredMinTxInterval = data[4:], BFDTimeInterval(binary.BigEndian.Uint32(data[:4]))
- data, d.RequiredMinRxInterval = data[4:], BFDTimeInterval(binary.BigEndian.Uint32(data[:4]))
- data, d.RequiredMinEchoRxInterval = data[4:], BFDTimeInterval(binary.BigEndian.Uint32(data[:4]))
- if d.AuthPresent && (len(data) > 2) {
- d.AuthHeader = &BFDAuthHeader{}
- data, d.AuthHeader.AuthType = data[1:], BFDAuthType(data[0])
- data, _ = data[1:], uint8(data[0])
- data, d.AuthHeader.KeyID = data[1:], BFDAuthKeyID(data[0])
- switch d.AuthHeader.AuthType {
- case BFDAuthTypePassword:
- d.AuthHeader.Data = BFDAuthData(data)
- case BFDAuthTypeKeyedMD5, BFDAuthTypeMeticulousKeyedMD5:
-
- data, d.AuthHeader.SequenceNumber = data[5:], BFDAuthSequenceNumber(binary.BigEndian.Uint32(data[1:5]))
- d.AuthHeader.Data = BFDAuthData(data)
- case BFDAuthTypeKeyedSHA1, BFDAuthTypeMeticulousKeyedSHA1:
-
- data, d.AuthHeader.SequenceNumber = data[5:], BFDAuthSequenceNumber(binary.BigEndian.Uint32(data[1:5]))
- d.AuthHeader.Data = BFDAuthData(data)
- }
- }
- return nil
- }
- func (d *BFD) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
- data, err := b.PrependBytes(bfdMinimumRecordSizeInBytes)
- if err != nil {
- return err
- }
-
- data[0] = byte(byte(d.Version<<5) | byte(d.Diagnostic))
- h := uint8(0)
- h |= (uint8(d.State) << 6)
- h |= (uint8(bool2uint8(d.Poll)) << 5)
- h |= (uint8(bool2uint8(d.Final)) << 4)
- h |= (uint8(bool2uint8(d.ControlPlaneIndependent)) << 3)
- h |= (uint8(bool2uint8(d.AuthPresent)) << 2)
- h |= (uint8(bool2uint8(d.Demand)) << 1)
- h |= uint8(bool2uint8(d.Multipoint))
- data[1] = byte(h)
- data[2] = byte(d.DetectMultiplier)
- data[3] = byte(d.Length())
-
- binary.BigEndian.PutUint32(data[4:], uint32(d.MyDiscriminator))
- binary.BigEndian.PutUint32(data[8:], uint32(d.YourDiscriminator))
- binary.BigEndian.PutUint32(data[12:], uint32(d.DesiredMinTxInterval))
- binary.BigEndian.PutUint32(data[16:], uint32(d.RequiredMinRxInterval))
- binary.BigEndian.PutUint32(data[20:], uint32(d.RequiredMinEchoRxInterval))
- if d.AuthPresent && (d.AuthHeader != nil) {
- auth, err := b.AppendBytes(int(d.AuthHeader.Length()))
- if err != nil {
- return err
- }
- auth[0] = byte(d.AuthHeader.AuthType)
- auth[1] = byte(d.AuthHeader.Length())
- auth[2] = byte(d.AuthHeader.KeyID)
- switch d.AuthHeader.AuthType {
- case BFDAuthTypePassword:
- copy(auth[3:], d.AuthHeader.Data)
- case BFDAuthTypeKeyedMD5, BFDAuthTypeMeticulousKeyedMD5:
- auth[3] = byte(0)
- binary.BigEndian.PutUint32(auth[4:], uint32(d.AuthHeader.SequenceNumber))
- copy(auth[8:], d.AuthHeader.Data)
- case BFDAuthTypeKeyedSHA1, BFDAuthTypeMeticulousKeyedSHA1:
- auth[3] = byte(0)
- binary.BigEndian.PutUint32(auth[4:], uint32(d.AuthHeader.SequenceNumber))
- copy(auth[8:], d.AuthHeader.Data)
- }
- }
- return nil
- }
- func (d *BFD) CanDecode() gopacket.LayerClass {
- return LayerTypeBFD
- }
- func (d *BFD) NextLayerType() gopacket.LayerType {
- return gopacket.LayerTypeZero
- }
- func (d *BFD) Payload() []byte {
- return nil
- }
- func bool2uint8(b bool) uint8 {
- if b {
- return 1
- }
- return 0
- }
|