summaryrefslogtreecommitdiffhomepage
path: root/packet/bmp/bmp.go
diff options
context:
space:
mode:
Diffstat (limited to 'packet/bmp/bmp.go')
-rw-r--r--packet/bmp/bmp.go1071
1 files changed, 0 insertions, 1071 deletions
diff --git a/packet/bmp/bmp.go b/packet/bmp/bmp.go
deleted file mode 100644
index eb2ce185..00000000
--- a/packet/bmp/bmp.go
+++ /dev/null
@@ -1,1071 +0,0 @@
-// Copyright (C) 2014,2015 Nippon Telegraph and Telephone Corporation.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package bmp
-
-import (
- "encoding/binary"
- "fmt"
- "github.com/osrg/gobgp/packet/bgp"
- "math"
- "net"
-)
-
-type BMPHeader struct {
- Version uint8
- Length uint32
- Type uint8
-}
-
-const (
- BMP_VERSION = 3
- BMP_HEADER_SIZE = 6
- BMP_PEER_HEADER_SIZE = 42
-)
-
-const (
- BMP_DEFAULT_PORT = 11019
-)
-
-const (
- BMP_PEER_TYPE_GLOBAL uint8 = iota
- BMP_PEER_TYPE_L3VPN
- BMP_PEER_TYPE_LOCAL
- BMP_PEER_TYPE_LOCAL_RIB
-)
-
-const (
- BMP_PEER_FLAG_IPV6 = 1 << 7
- BMP_PEER_FLAG_POST_POLICY = 1 << 6
- BMP_PEER_FLAG_TWO_AS = 1 << 5
- BMP_PEER_FLAG_FILTERED = 1 << 6
-)
-
-func (h *BMPHeader) DecodeFromBytes(data []byte) error {
- h.Version = data[0]
- if data[0] != BMP_VERSION {
- return fmt.Errorf("error version")
- }
- h.Length = binary.BigEndian.Uint32(data[1:5])
- h.Type = data[5]
- return nil
-}
-
-func (h *BMPHeader) Serialize() ([]byte, error) {
- buf := make([]byte, BMP_HEADER_SIZE)
- buf[0] = h.Version
- binary.BigEndian.PutUint32(buf[1:], h.Length)
- buf[5] = h.Type
- return buf, nil
-}
-
-type BMPPeerHeader struct {
- PeerType uint8
- Flags uint8
- PeerDistinguisher uint64
- PeerAddress net.IP
- PeerAS uint32
- PeerBGPID net.IP
- Timestamp float64
-}
-
-func NewBMPPeerHeader(t uint8, flags uint8, dist uint64, address string, as uint32, id string, stamp float64) *BMPPeerHeader {
- h := &BMPPeerHeader{
- PeerType: t,
- Flags: flags,
- PeerDistinguisher: dist,
- PeerAS: as,
- PeerBGPID: net.ParseIP(id).To4(),
- Timestamp: stamp,
- }
- if net.ParseIP(address).To4() != nil {
- h.PeerAddress = net.ParseIP(address).To4()
- } else {
- h.PeerAddress = net.ParseIP(address).To16()
- h.Flags |= BMP_PEER_FLAG_IPV6
- }
- return h
-}
-
-func (h *BMPPeerHeader) IsPostPolicy() bool {
- if h.Flags&BMP_PEER_FLAG_POST_POLICY != 0 {
- return true
- } else {
- return false
- }
-}
-
-func (h *BMPPeerHeader) DecodeFromBytes(data []byte) error {
- h.PeerType = data[0]
- h.Flags = data[1]
- h.PeerDistinguisher = binary.BigEndian.Uint64(data[2:10])
- if h.Flags&BMP_PEER_FLAG_IPV6 != 0 {
- h.PeerAddress = net.IP(data[10:26]).To16()
- } else {
- h.PeerAddress = net.IP(data[22:26]).To4()
- }
- h.PeerAS = binary.BigEndian.Uint32(data[26:30])
- h.PeerBGPID = data[30:34]
-
- timestamp1 := binary.BigEndian.Uint32(data[34:38])
- timestamp2 := binary.BigEndian.Uint32(data[38:42])
- h.Timestamp = float64(timestamp1) + float64(timestamp2)*math.Pow10(-6)
- return nil
-}
-
-func (h *BMPPeerHeader) Serialize() ([]byte, error) {
- buf := make([]byte, BMP_PEER_HEADER_SIZE)
- buf[0] = h.PeerType
- buf[1] = h.Flags
- binary.BigEndian.PutUint64(buf[2:10], h.PeerDistinguisher)
- if h.Flags&BMP_PEER_FLAG_IPV6 != 0 {
- copy(buf[10:26], h.PeerAddress)
- } else {
- copy(buf[22:26], h.PeerAddress.To4())
- }
- binary.BigEndian.PutUint32(buf[26:30], h.PeerAS)
- copy(buf[30:34], h.PeerBGPID)
- t1, t2 := math.Modf(h.Timestamp)
- t2 = math.Ceil(t2 * math.Pow10(6))
- binary.BigEndian.PutUint32(buf[34:38], uint32(t1))
- binary.BigEndian.PutUint32(buf[38:42], uint32(t2))
- return buf, nil
-}
-
-type BMPRouteMonitoring struct {
- BGPUpdate *bgp.BGPMessage
- BGPUpdatePayload []byte
-}
-
-func NewBMPRouteMonitoring(p BMPPeerHeader, update *bgp.BGPMessage) *BMPMessage {
- return &BMPMessage{
- Header: BMPHeader{
- Version: BMP_VERSION,
- Type: BMP_MSG_ROUTE_MONITORING,
- },
- PeerHeader: p,
- Body: &BMPRouteMonitoring{
- BGPUpdate: update,
- },
- }
-}
-
-func (body *BMPRouteMonitoring) ParseBody(msg *BMPMessage, data []byte) error {
- update, err := bgp.ParseBGPMessage(data)
- if err != nil {
- return err
- }
- body.BGPUpdate = update
- return nil
-}
-
-func (body *BMPRouteMonitoring) Serialize() ([]byte, error) {
- if body.BGPUpdatePayload != nil {
- return body.BGPUpdatePayload, nil
- }
- return body.BGPUpdate.Serialize()
-}
-
-const (
- BMP_STAT_TYPE_REJECTED = iota
- BMP_STAT_TYPE_DUPLICATE_PREFIX
- BMP_STAT_TYPE_DUPLICATE_WITHDRAW
- BMP_STAT_TYPE_INV_UPDATE_DUE_TO_CLUSTER_LIST_LOOP
- BMP_STAT_TYPE_INV_UPDATE_DUE_TO_AS_PATH_LOOP
- BMP_STAT_TYPE_INV_UPDATE_DUE_TO_ORIGINATOR_ID
- BMP_STAT_TYPE_INV_UPDATE_DUE_TO_AS_CONFED_LOOP
- BMP_STAT_TYPE_ADJ_RIB_IN
- BMP_STAT_TYPE_LOC_RIB
- BMP_STAT_TYPE_PER_AFI_SAFI_ADJ_RIB_IN
- BMP_STAT_TYPE_PER_AFI_SAFI_LOC_RIB
- BMP_STAT_TYPE_WITHDRAW_UPDATE
- BMP_STAT_TYPE_WITHDRAW_PREFIX
- BMP_STAT_TYPE_DUPLICATE_UPDATE
-)
-
-type BMPStatsTLVInterface interface {
- ParseValue([]byte) error
- Serialize() ([]byte, error)
-}
-
-type BMPStatsTLV struct {
- Type uint16
- Length uint16
-}
-
-type BMPStatsTLV32 struct {
- BMPStatsTLV
- Value uint32
-}
-
-func NewBMPStatsTLV32(t uint16, v uint32) *BMPStatsTLV32 {
- return &BMPStatsTLV32{
- BMPStatsTLV: BMPStatsTLV{
- Type: t,
- Length: 4,
- },
- Value: v,
- }
-}
-
-func (s *BMPStatsTLV32) ParseValue(data []byte) error {
- if s.Length != 4 {
- return fmt.Errorf("invalid length: %d bytes (%d bytes expected)", s.Length, 4)
- }
- s.Value = binary.BigEndian.Uint32(data[:8])
- return nil
-}
-
-func (s *BMPStatsTLV32) Serialize() ([]byte, error) {
- buf := make([]byte, 8)
- binary.BigEndian.PutUint16(buf[0:2], s.Type)
- binary.BigEndian.PutUint16(buf[2:4], 4)
- binary.BigEndian.PutUint32(buf[4:8], s.Value)
- return buf, nil
-}
-
-type BMPStatsTLV64 struct {
- BMPStatsTLV
- Value uint64
-}
-
-func NewBMPStatsTLV64(t uint16, v uint64) *BMPStatsTLV64 {
- return &BMPStatsTLV64{
- BMPStatsTLV: BMPStatsTLV{
- Type: t,
- Length: 8,
- },
- Value: v,
- }
-}
-
-func (s *BMPStatsTLV64) ParseValue(data []byte) error {
- if s.Length != 8 {
- return fmt.Errorf("invalid length: %d bytes (%d bytes expected)", s.Length, 8)
- }
- s.Value = binary.BigEndian.Uint64(data[:8])
- return nil
-}
-
-func (s *BMPStatsTLV64) Serialize() ([]byte, error) {
- buf := make([]byte, 12)
- binary.BigEndian.PutUint16(buf[0:2], s.Type)
- binary.BigEndian.PutUint16(buf[2:4], 8)
- binary.BigEndian.PutUint64(buf[4:12], s.Value)
- return buf, nil
-}
-
-type BMPStatsTLVPerAfiSafi64 struct {
- BMPStatsTLV
- AFI uint16
- SAFI uint8
- Value uint64
-}
-
-func NewBMPStatsTLVPerAfiSafi64(t uint16, afi uint16, safi uint8, v uint64) *BMPStatsTLVPerAfiSafi64 {
- return &BMPStatsTLVPerAfiSafi64{
- BMPStatsTLV: BMPStatsTLV{
- Type: t,
- Length: 11,
- },
- AFI: afi,
- SAFI: safi,
- Value: v,
- }
-}
-
-func (s *BMPStatsTLVPerAfiSafi64) ParseValue(data []byte) error {
- if s.Length != 11 {
- return fmt.Errorf("invalid length: %d bytes (%d bytes expected)", s.Length, 11)
- }
- s.AFI = binary.BigEndian.Uint16(data[0:2])
- s.SAFI = data[2]
- s.Value = binary.BigEndian.Uint64(data[3:11])
- return nil
-}
-
-func (s *BMPStatsTLVPerAfiSafi64) Serialize() ([]byte, error) {
- buf := make([]byte, 15)
- binary.BigEndian.PutUint16(buf[0:2], s.Type)
- binary.BigEndian.PutUint16(buf[2:4], 11)
- binary.BigEndian.PutUint16(buf[4:6], s.AFI)
- buf[6] = s.SAFI
- binary.BigEndian.PutUint64(buf[7:15], s.Value)
- return buf, nil
-}
-
-type BMPStatisticsReport struct {
- Count uint32
- Stats []BMPStatsTLVInterface
-}
-
-func NewBMPStatisticsReport(p BMPPeerHeader, stats []BMPStatsTLVInterface) *BMPMessage {
- return &BMPMessage{
- Header: BMPHeader{
- Version: BMP_VERSION,
- Type: BMP_MSG_STATISTICS_REPORT,
- },
- PeerHeader: p,
- Body: &BMPStatisticsReport{
- Count: uint32(len(stats)),
- Stats: stats,
- },
- }
-}
-
-func (body *BMPStatisticsReport) ParseBody(msg *BMPMessage, data []byte) error {
- body.Count = binary.BigEndian.Uint32(data[0:4])
- data = data[4:]
- for len(data) >= 4 {
- tl := BMPStatsTLV{
- Type: binary.BigEndian.Uint16(data[0:2]),
- Length: binary.BigEndian.Uint16(data[2:4]),
- }
- data = data[4:]
- if len(data) < int(tl.Length) {
- return fmt.Errorf("value length is not enough: %d bytes (%d bytes expected)", len(data), tl.Length)
- }
- var s BMPStatsTLVInterface
- switch tl.Type {
- case BMP_STAT_TYPE_ADJ_RIB_IN, BMP_STAT_TYPE_LOC_RIB:
- s = &BMPStatsTLV64{BMPStatsTLV: tl}
- case BMP_STAT_TYPE_PER_AFI_SAFI_ADJ_RIB_IN, BMP_STAT_TYPE_PER_AFI_SAFI_LOC_RIB:
- s = &BMPStatsTLVPerAfiSafi64{BMPStatsTLV: tl}
- default:
- s = &BMPStatsTLV32{BMPStatsTLV: tl}
- }
- if err := s.ParseValue(data); err != nil {
- return err
- }
- body.Stats = append(body.Stats, s)
- data = data[tl.Length:]
- }
- return nil
-}
-
-func (body *BMPStatisticsReport) Serialize() ([]byte, error) {
- buf := make([]byte, 4)
- body.Count = uint32(len(body.Stats))
- binary.BigEndian.PutUint32(buf[0:4], body.Count)
- for _, tlv := range body.Stats {
- tlvBuf, err := tlv.Serialize()
- if err != nil {
- return nil, err
- }
- buf = append(buf, tlvBuf...)
- }
- return buf, nil
-}
-
-const (
- BMP_PEER_DOWN_REASON_UNKNOWN = iota
- BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION
- BMP_PEER_DOWN_REASON_LOCAL_NO_NOTIFICATION
- BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION
- BMP_PEER_DOWN_REASON_REMOTE_NO_NOTIFICATION
- BMP_PEER_DOWN_REASON_PEER_DE_CONFIGURED
-)
-
-type BMPPeerDownNotification struct {
- Reason uint8
- BGPNotification *bgp.BGPMessage
- Data []byte
-}
-
-func NewBMPPeerDownNotification(p BMPPeerHeader, reason uint8, notification *bgp.BGPMessage, data []byte) *BMPMessage {
- b := &BMPPeerDownNotification{
- Reason: reason,
- }
- switch reason {
- case BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION, BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION:
- b.BGPNotification = notification
- case BMP_PEER_DOWN_REASON_LOCAL_NO_NOTIFICATION:
- b.Data = data
- default:
- }
- return &BMPMessage{
- Header: BMPHeader{
- Version: BMP_VERSION,
- Type: BMP_MSG_PEER_DOWN_NOTIFICATION,
- },
- PeerHeader: p,
- Body: b,
- }
-}
-
-func (body *BMPPeerDownNotification) ParseBody(msg *BMPMessage, data []byte) error {
- body.Reason = data[0]
- data = data[1:]
- if body.Reason == BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION || body.Reason == BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION {
- notification, err := bgp.ParseBGPMessage(data)
- if err != nil {
- return err
- }
- body.BGPNotification = notification
- } else {
- body.Data = data
- }
- return nil
-}
-
-func (body *BMPPeerDownNotification) Serialize() ([]byte, error) {
- buf := make([]byte, 1)
- buf[0] = body.Reason
- switch body.Reason {
- case BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION, BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION:
- if body.BGPNotification != nil {
- b, err := body.BGPNotification.Serialize()
- if err != nil {
- return nil, err
- } else {
- buf = append(buf, b...)
- }
- }
- default:
- if body.Data != nil {
- buf = append(buf, body.Data...)
- }
- }
- return buf, nil
-}
-
-type BMPPeerUpNotification struct {
- LocalAddress net.IP
- LocalPort uint16
- RemotePort uint16
- SentOpenMsg *bgp.BGPMessage
- ReceivedOpenMsg *bgp.BGPMessage
-}
-
-func NewBMPPeerUpNotification(p BMPPeerHeader, lAddr string, lPort, rPort uint16, sent, recv *bgp.BGPMessage) *BMPMessage {
- b := &BMPPeerUpNotification{
- LocalPort: lPort,
- RemotePort: rPort,
- SentOpenMsg: sent,
- ReceivedOpenMsg: recv,
- }
- addr := net.ParseIP(lAddr)
- if addr.To4() != nil {
- b.LocalAddress = addr.To4()
- } else {
- b.LocalAddress = addr.To16()
- }
- return &BMPMessage{
- Header: BMPHeader{
- Version: BMP_VERSION,
- Type: BMP_MSG_PEER_UP_NOTIFICATION,
- },
- PeerHeader: p,
- Body: b,
- }
-}
-
-func (body *BMPPeerUpNotification) ParseBody(msg *BMPMessage, data []byte) error {
- if msg.PeerHeader.Flags&BMP_PEER_FLAG_IPV6 != 0 {
- body.LocalAddress = net.IP(data[:16]).To16()
- } else {
- body.LocalAddress = net.IP(data[12:16]).To4()
- }
-
- body.LocalPort = binary.BigEndian.Uint16(data[16:18])
- body.RemotePort = binary.BigEndian.Uint16(data[18:20])
-
- data = data[20:]
- sentopen, err := bgp.ParseBGPMessage(data)
- if err != nil {
- return err
- }
- body.SentOpenMsg = sentopen
- data = data[body.SentOpenMsg.Header.Len:]
- body.ReceivedOpenMsg, err = bgp.ParseBGPMessage(data)
- if err != nil {
- return err
- }
- return nil
-}
-
-func (body *BMPPeerUpNotification) Serialize() ([]byte, error) {
- buf := make([]byte, 20)
- if body.LocalAddress.To4() != nil {
- copy(buf[12:16], body.LocalAddress.To4())
- } else {
- copy(buf[:16], body.LocalAddress.To16())
- }
-
- binary.BigEndian.PutUint16(buf[16:18], body.LocalPort)
- binary.BigEndian.PutUint16(buf[18:20], body.RemotePort)
-
- m, _ := body.SentOpenMsg.Serialize()
- buf = append(buf, m...)
- m, _ = body.ReceivedOpenMsg.Serialize()
- buf = append(buf, m...)
- return buf, nil
-}
-
-const (
- BMP_INIT_TLV_TYPE_STRING = iota
- BMP_INIT_TLV_TYPE_SYS_DESCR
- BMP_INIT_TLV_TYPE_SYS_NAME
-)
-
-type BMPInfoTLVInterface interface {
- ParseValue([]byte) error
- Serialize() ([]byte, error)
-}
-
-type BMPInfoTLV struct {
- Type uint16
- Length uint16
-}
-
-type BMPInfoTLVString struct {
- BMPInfoTLV
- Value string
-}
-
-func NewBMPInfoTLVString(t uint16, v string) *BMPInfoTLVString {
- return &BMPInfoTLVString{
- BMPInfoTLV: BMPInfoTLV{Type: t},
- Value: v,
- }
-}
-
-func (s *BMPInfoTLVString) ParseValue(data []byte) error {
- s.Value = string(data[:s.Length])
- return nil
-}
-
-func (s *BMPInfoTLVString) Serialize() ([]byte, error) {
- s.Length = uint16(len([]byte(s.Value)))
- buf := make([]byte, 4)
- binary.BigEndian.PutUint16(buf[0:2], s.Type)
- binary.BigEndian.PutUint16(buf[2:4], s.Length)
- buf = append(buf, []byte(s.Value)...)
- return buf, nil
-}
-
-type BMPInfoTLVUnknown struct {
- BMPInfoTLV
- Value []byte
-}
-
-func NewBMPInfoTLVUnknown(t uint16, v []byte) *BMPInfoTLVUnknown {
- return &BMPInfoTLVUnknown{
- BMPInfoTLV: BMPInfoTLV{Type: t},
- Value: v,
- }
-}
-
-func (s *BMPInfoTLVUnknown) ParseValue(data []byte) error {
- s.Value = data[:s.Length]
- return nil
-}
-
-func (s *BMPInfoTLVUnknown) Serialize() ([]byte, error) {
- s.Length = uint16(len([]byte(s.Value)))
- buf := make([]byte, 4)
- binary.BigEndian.PutUint16(buf[0:2], s.Type)
- binary.BigEndian.PutUint16(buf[2:4], s.Length)
- buf = append(buf, s.Value...)
- return buf, nil
-}
-
-type BMPInitiation struct {
- Info []BMPInfoTLVInterface
-}
-
-func NewBMPInitiation(info []BMPInfoTLVInterface) *BMPMessage {
- return &BMPMessage{
- Header: BMPHeader{
- Version: BMP_VERSION,
- Type: BMP_MSG_INITIATION,
- },
- Body: &BMPInitiation{
- Info: info,
- },
- }
-}
-
-func (body *BMPInitiation) ParseBody(msg *BMPMessage, data []byte) error {
- for len(data) >= 4 {
- tl := BMPInfoTLV{
- Type: binary.BigEndian.Uint16(data[0:2]),
- Length: binary.BigEndian.Uint16(data[2:4]),
- }
- data = data[4:]
- if len(data) < int(tl.Length) {
- return fmt.Errorf("value length is not enough: %d bytes (%d bytes expected)", len(data), tl.Length)
- }
- var tlv BMPInfoTLVInterface
- switch tl.Type {
- case BMP_INIT_TLV_TYPE_STRING, BMP_INIT_TLV_TYPE_SYS_DESCR, BMP_INIT_TLV_TYPE_SYS_NAME:
- tlv = &BMPInfoTLVString{BMPInfoTLV: tl}
- default:
- tlv = &BMPInfoTLVUnknown{BMPInfoTLV: tl}
- }
- if err := tlv.ParseValue(data); err != nil {
- return err
- }
- body.Info = append(body.Info, tlv)
- data = data[tl.Length:]
- }
- return nil
-}
-
-func (body *BMPInitiation) Serialize() ([]byte, error) {
- buf := make([]byte, 0)
- for _, tlv := range body.Info {
- b, err := tlv.Serialize()
- if err != nil {
- return buf, err
- }
- buf = append(buf, b...)
- }
- return buf, nil
-}
-
-const (
- BMP_TERM_TLV_TYPE_STRING = iota
- BMP_TERM_TLV_TYPE_REASON
-)
-
-const (
- BMP_TERM_REASON_ADMIN = iota
- BMP_TERM_REASON_UNSPEC
- BMP_TERM_REASON_OUT_OF_RESOURCES
- BMP_TERM_REASON_REDUNDANT_CONNECTION
- BMP_TERM_REASON_PERMANENTLY_ADMIN
-)
-
-type BMPTermTLVInterface interface {
- ParseValue([]byte) error
- Serialize() ([]byte, error)
-}
-
-type BMPTermTLV struct {
- Type uint16
- Length uint16
-}
-
-type BMPTermTLVString struct {
- BMPTermTLV
- Value string
-}
-
-func NewBMPTermTLVString(t uint16, v string) *BMPTermTLVString {
- return &BMPTermTLVString{
- BMPTermTLV: BMPTermTLV{Type: t},
- Value: v,
- }
-}
-
-func (s *BMPTermTLVString) ParseValue(data []byte) error {
- s.Value = string(data[:s.Length])
- return nil
-}
-
-func (s *BMPTermTLVString) Serialize() ([]byte, error) {
- s.Length = uint16(len([]byte(s.Value)))
- buf := make([]byte, 4)
- binary.BigEndian.PutUint16(buf[0:2], s.Type)
- binary.BigEndian.PutUint16(buf[2:4], s.Length)
- buf = append(buf, []byte(s.Value)...)
- return buf, nil
-}
-
-type BMPTermTLV16 struct {
- BMPTermTLV
- Value uint16
-}
-
-func NewBMPTermTLV16(t uint16, v uint16) *BMPTermTLV16 {
- return &BMPTermTLV16{
- BMPTermTLV: BMPTermTLV{Type: t},
- Value: v,
- }
-}
-
-func (s *BMPTermTLV16) ParseValue(data []byte) error {
- s.Value = binary.BigEndian.Uint16(data[:2])
- return nil
-}
-
-func (s *BMPTermTLV16) Serialize() ([]byte, error) {
- s.Length = 2
- buf := make([]byte, 6)
- binary.BigEndian.PutUint16(buf[0:2], s.Type)
- binary.BigEndian.PutUint16(buf[2:4], s.Length)
- binary.BigEndian.PutUint16(buf[4:6], s.Value)
- return buf, nil
-}
-
-type BMPTermTLVUnknown struct {
- BMPTermTLV
- Value []byte
-}
-
-func NewBMPTermTLVUnknown(t uint16, v []byte) *BMPTermTLVUnknown {
- return &BMPTermTLVUnknown{
- BMPTermTLV: BMPTermTLV{Type: t},
- Value: v,
- }
-}
-
-func (s *BMPTermTLVUnknown) ParseValue(data []byte) error {
- s.Value = data[:s.Length]
- return nil
-}
-
-func (s *BMPTermTLVUnknown) Serialize() ([]byte, error) {
- s.Length = uint16(len([]byte(s.Value)))
- buf := make([]byte, 4)
- binary.BigEndian.PutUint16(buf[0:2], s.Type)
- binary.BigEndian.PutUint16(buf[2:4], s.Length)
- buf = append(buf, s.Value...)
- return buf, nil
-}
-
-type BMPTermination struct {
- Info []BMPTermTLVInterface
-}
-
-func NewBMPTermination(info []BMPTermTLVInterface) *BMPMessage {
- return &BMPMessage{
- Header: BMPHeader{
- Version: BMP_VERSION,
- Type: BMP_MSG_TERMINATION,
- },
- Body: &BMPTermination{
- Info: info,
- },
- }
-}
-
-func (body *BMPTermination) ParseBody(msg *BMPMessage, data []byte) error {
- for len(data) >= 4 {
- tl := BMPTermTLV{
- Type: binary.BigEndian.Uint16(data[0:2]),
- Length: binary.BigEndian.Uint16(data[2:4]),
- }
- data = data[4:]
- if len(data) < int(tl.Length) {
- return fmt.Errorf("value length is not enough: %d bytes (%d bytes expected)", len(data), tl.Length)
- }
- var tlv BMPTermTLVInterface
- switch tl.Type {
- case BMP_TERM_TLV_TYPE_STRING:
- tlv = &BMPTermTLVString{BMPTermTLV: tl}
- case BMP_TERM_TLV_TYPE_REASON:
- tlv = &BMPTermTLV16{BMPTermTLV: tl}
- default:
- tlv = &BMPTermTLVUnknown{BMPTermTLV: tl}
- }
- if err := tlv.ParseValue(data); err != nil {
- return err
- }
- body.Info = append(body.Info, tlv)
- data = data[tl.Length:]
- }
- return nil
-}
-
-func (body *BMPTermination) Serialize() ([]byte, error) {
- buf := make([]byte, 0)
- for _, tlv := range body.Info {
- b, err := tlv.Serialize()
- if err != nil {
- return buf, err
- }
- buf = append(buf, b...)
- }
- return buf, nil
-}
-
-const (
- BMP_ROUTE_MIRRORING_TLV_TYPE_BGP_MSG = iota
- BMP_ROUTE_MIRRORING_TLV_TYPE_INFO
-)
-
-const (
- BMP_ROUTE_MIRRORING_INFO_ERR_PDU = iota
- BMP_ROUTE_MIRRORING_INFO_MSG_LOST
-)
-
-type BMPRouteMirrTLVInterface interface {
- ParseValue([]byte) error
- Serialize() ([]byte, error)
-}
-
-type BMPRouteMirrTLV struct {
- Type uint16
- Length uint16
-}
-
-type BMPRouteMirrTLVBGPMsg struct {
- BMPRouteMirrTLV
- Value *bgp.BGPMessage
-}
-
-func NewBMPRouteMirrTLVBGPMsg(t uint16, v *bgp.BGPMessage) *BMPRouteMirrTLVBGPMsg {
- return &BMPRouteMirrTLVBGPMsg{
- BMPRouteMirrTLV: BMPRouteMirrTLV{Type: t},
- Value: v,
- }
-}
-
-func (s *BMPRouteMirrTLVBGPMsg) ParseValue(data []byte) error {
- v, err := bgp.ParseBGPMessage(data)
- if err != nil {
- return err
- }
- s.Value = v
- return nil
-}
-
-func (s *BMPRouteMirrTLVBGPMsg) Serialize() ([]byte, error) {
- m, err := s.Value.Serialize()
- if err != nil {
- return nil, err
- }
- s.Length = uint16(len(m))
- buf := make([]byte, 4)
- binary.BigEndian.PutUint16(buf[0:2], s.Type)
- binary.BigEndian.PutUint16(buf[2:4], s.Length)
- buf = append(buf, m...)
- return buf, nil
-}
-
-type BMPRouteMirrTLV16 struct {
- BMPRouteMirrTLV
- Value uint16
-}
-
-func NewBMPRouteMirrTLV16(t uint16, v uint16) *BMPRouteMirrTLV16 {
- return &BMPRouteMirrTLV16{
- BMPRouteMirrTLV: BMPRouteMirrTLV{Type: t},
- Value: v,
- }
-}
-
-func (s *BMPRouteMirrTLV16) ParseValue(data []byte) error {
- s.Value = binary.BigEndian.Uint16(data[:2])
- return nil
-}
-
-func (s *BMPRouteMirrTLV16) Serialize() ([]byte, error) {
- s.Length = 2
- buf := make([]byte, 6)
- binary.BigEndian.PutUint16(buf[0:2], s.Type)
- binary.BigEndian.PutUint16(buf[2:4], s.Length)
- binary.BigEndian.PutUint16(buf[4:6], s.Value)
- return buf, nil
-}
-
-type BMPRouteMirrTLVUnknown struct {
- BMPRouteMirrTLV
- Value []byte
-}
-
-func NewBMPRouteMirrTLVUnknown(t uint16, v []byte) *BMPRouteMirrTLVUnknown {
- return &BMPRouteMirrTLVUnknown{
- BMPRouteMirrTLV: BMPRouteMirrTLV{Type: t},
- Value: v,
- }
-}
-
-func (s *BMPRouteMirrTLVUnknown) ParseValue(data []byte) error {
- s.Value = data[:s.Length]
- return nil
-}
-
-func (s *BMPRouteMirrTLVUnknown) Serialize() ([]byte, error) {
- s.Length = uint16(len([]byte(s.Value)))
- buf := make([]byte, 4)
- binary.BigEndian.PutUint16(buf[0:2], s.Type)
- binary.BigEndian.PutUint16(buf[2:4], s.Length)
- buf = append(buf, s.Value...)
- return buf, nil
-}
-
-type BMPRouteMirroring struct {
- Info []BMPRouteMirrTLVInterface
-}
-
-func NewBMPRouteMirroring(p BMPPeerHeader, info []BMPRouteMirrTLVInterface) *BMPMessage {
- return &BMPMessage{
- Header: BMPHeader{
- Version: BMP_VERSION,
- Type: BMP_MSG_ROUTE_MIRRORING,
- },
- PeerHeader: p,
- Body: &BMPRouteMirroring{
- Info: info,
- },
- }
-}
-
-func (body *BMPRouteMirroring) ParseBody(msg *BMPMessage, data []byte) error {
- for len(data) >= 4 {
- tl := BMPRouteMirrTLV{
- Type: binary.BigEndian.Uint16(data[0:2]),
- Length: binary.BigEndian.Uint16(data[2:4]),
- }
- data = data[4:]
- if len(data) < int(tl.Length) {
- return fmt.Errorf("value length is not enough: %d bytes (%d bytes expected)", len(data), tl.Length)
- }
- var tlv BMPRouteMirrTLVInterface
- switch tl.Type {
- case BMP_ROUTE_MIRRORING_TLV_TYPE_BGP_MSG:
- tlv = &BMPRouteMirrTLVBGPMsg{BMPRouteMirrTLV: tl}
- case BMP_ROUTE_MIRRORING_TLV_TYPE_INFO:
- tlv = &BMPRouteMirrTLV16{BMPRouteMirrTLV: tl}
- default:
- tlv = &BMPRouteMirrTLVUnknown{BMPRouteMirrTLV: tl}
- }
- if err := tlv.ParseValue(data); err != nil {
- return err
- }
- body.Info = append(body.Info, tlv)
- data = data[tl.Length:]
- }
- return nil
-}
-
-func (body *BMPRouteMirroring) Serialize() ([]byte, error) {
- buf := make([]byte, 0)
- for _, tlv := range body.Info {
- b, err := tlv.Serialize()
- if err != nil {
- return buf, err
- }
- buf = append(buf, b...)
- }
- return buf, nil
-}
-
-type BMPBody interface {
- // Sigh, some body messages need a BMPHeader to parse the body
- // data so we need to pass BMPHeader (avoid DecodeFromBytes
- // function name).
- ParseBody(*BMPMessage, []byte) error
- Serialize() ([]byte, error)
-}
-
-type BMPMessage struct {
- Header BMPHeader
- PeerHeader BMPPeerHeader
- Body BMPBody
-}
-
-func (msg *BMPMessage) Serialize() ([]byte, error) {
- buf := make([]byte, 0)
- if msg.Header.Type != BMP_MSG_INITIATION && msg.Header.Type != BMP_MSG_TERMINATION {
- p, err := msg.PeerHeader.Serialize()
- if err != nil {
- return nil, err
- }
- buf = append(buf, p...)
- }
-
- b, err := msg.Body.Serialize()
- if err != nil {
- return nil, err
- }
- buf = append(buf, b...)
-
- if msg.Header.Length == 0 {
- msg.Header.Length = uint32(BMP_HEADER_SIZE + len(buf))
- }
-
- h, err := msg.Header.Serialize()
- if err != nil {
- return nil, err
- }
- return append(h, buf...), nil
-}
-
-func (msg *BMPMessage) Len() int {
- return int(msg.Header.Length)
-}
-
-const (
- BMP_MSG_ROUTE_MONITORING = iota
- BMP_MSG_STATISTICS_REPORT
- BMP_MSG_PEER_DOWN_NOTIFICATION
- BMP_MSG_PEER_UP_NOTIFICATION
- BMP_MSG_INITIATION
- BMP_MSG_TERMINATION
- BMP_MSG_ROUTE_MIRRORING
-)
-
-func ParseBMPMessage(data []byte) (msg *BMPMessage, err error) {
- defer func() {
- if r := recover(); r != nil {
- err = fmt.Errorf("not all data bytes are available")
- }
- }()
-
- msg = &BMPMessage{}
- err = msg.Header.DecodeFromBytes(data)
- if err != nil {
- return nil, err
- }
- data = data[BMP_HEADER_SIZE:msg.Header.Length]
-
- switch msg.Header.Type {
- case BMP_MSG_ROUTE_MONITORING:
- msg.Body = &BMPRouteMonitoring{}
- case BMP_MSG_STATISTICS_REPORT:
- msg.Body = &BMPStatisticsReport{}
- case BMP_MSG_PEER_DOWN_NOTIFICATION:
- msg.Body = &BMPPeerDownNotification{}
- case BMP_MSG_PEER_UP_NOTIFICATION:
- msg.Body = &BMPPeerUpNotification{}
- case BMP_MSG_INITIATION:
- msg.Body = &BMPInitiation{}
- case BMP_MSG_TERMINATION:
- msg.Body = &BMPTermination{}
- case BMP_MSG_ROUTE_MIRRORING:
- msg.Body = &BMPRouteMirroring{}
- default:
- return nil, fmt.Errorf("unsupported BMP message type: %d", msg.Header.Type)
- }
-
- if msg.Header.Type != BMP_MSG_INITIATION && msg.Header.Type != BMP_MSG_TERMINATION {
- msg.PeerHeader.DecodeFromBytes(data)
- data = data[BMP_PEER_HEADER_SIZE:]
- }
-
- err = msg.Body.ParseBody(msg, data)
- if err != nil {
- return nil, err
- }
- return msg, nil
-}
-
-func SplitBMP(data []byte, atEOF bool) (advance int, token []byte, err error) {
- if atEOF && len(data) == 0 || len(data) < BMP_HEADER_SIZE {
- return 0, nil, nil
- }
-
- msg := &BMPMessage{}
- msg.Header.DecodeFromBytes(data)
- if uint32(len(data)) < msg.Header.Length {
- return 0, nil, nil
- }
-
- return int(msg.Header.Length), data[0:msg.Header.Length], nil
-}