798 lines
19 KiB
Go
798 lines
19 KiB
Go
package messages
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"net"
|
|
"time"
|
|
)
|
|
|
|
type BGPAttribute_NEXTHOP struct {
|
|
NextHop net.IP
|
|
}
|
|
|
|
type BGPAttribute_ORIGIN struct {
|
|
Origin byte
|
|
}
|
|
|
|
type BGPAttribute_MED struct {
|
|
Med uint32
|
|
}
|
|
|
|
type BGPAttribute_LOCPREF struct {
|
|
LocPref uint32
|
|
}
|
|
|
|
type BGPAttribute_COMMUNITIES struct {
|
|
Communities []uint32
|
|
}
|
|
|
|
type ASPath_Segment struct {
|
|
SType byte
|
|
ASPath []uint32
|
|
}
|
|
|
|
type BGPAttribute_ASPATH struct {
|
|
Segments []ASPath_Segment
|
|
Enc2Bytes bool
|
|
}
|
|
|
|
type BGPAttribute_MP_UNREACH struct {
|
|
Afi uint16
|
|
Safi byte
|
|
NLRI []NLRI
|
|
|
|
EnableAddPath bool
|
|
}
|
|
|
|
type BGPAttribute_MP_REACH struct {
|
|
Afi uint16
|
|
Safi byte
|
|
NextHop net.IP
|
|
NLRI []NLRI
|
|
|
|
EnableAddPath bool
|
|
}
|
|
|
|
type BGPAttribute_ATOMIC_AGGREGATE struct {
|
|
}
|
|
|
|
type BGPAttribute_AGGREGATOR struct {
|
|
ASN uint32
|
|
Identifier []byte
|
|
Enc2Bytes bool
|
|
}
|
|
|
|
type BGPAttributeIf SerializableInterface
|
|
|
|
type BGPAttribute struct {
|
|
Flags byte
|
|
Code byte
|
|
Data []byte
|
|
}
|
|
|
|
type BGPMessageUpdate struct {
|
|
BGPMessageHead
|
|
WithdrawnRoutes []NLRI
|
|
PathAttributes []BGPAttributeIf
|
|
NLRI []NLRI
|
|
|
|
EnableAddPath bool
|
|
}
|
|
|
|
func (m BGPAttribute_ORIGIN) String() string {
|
|
return fmt.Sprintf("Origin: %v", m.Origin)
|
|
}
|
|
|
|
func (m BGPAttribute_AGGREGATOR) String() string {
|
|
id := net.IP(m.Identifier)
|
|
return fmt.Sprintf("Aggregator: ASN: %v / Id: %v", m.ASN, id)
|
|
}
|
|
|
|
func (m BGPAttribute_ATOMIC_AGGREGATE) String() string {
|
|
return "Atomic aggregate"
|
|
}
|
|
|
|
func (m BGPAttribute_MED) String() string {
|
|
return fmt.Sprintf("Med: %v", m.Med)
|
|
}
|
|
|
|
func (m BGPAttribute_LOCPREF) String() string {
|
|
return fmt.Sprintf("LocPref: %v", m.LocPref)
|
|
}
|
|
|
|
func (m BGPAttribute_ASPATH) String() string {
|
|
return fmt.Sprintf("ASPath: %v", m.Segments)
|
|
}
|
|
|
|
func (m ASPath_Segment) String() string {
|
|
return fmt.Sprintf("Segment (type: %v | len: %v): %v", m.SType, len(m.ASPath), m.ASPath)
|
|
}
|
|
|
|
func (m BGPAttribute_COMMUNITIES) String() string {
|
|
var comlist string
|
|
for i := range m.Communities {
|
|
comlist += fmt.Sprintf("%v:%v, ", m.Communities[i]&0xFFFF0000>>16, m.Communities[i]&0xFFFF)
|
|
}
|
|
|
|
return fmt.Sprintf("Communities: [ %v]", comlist)
|
|
}
|
|
|
|
func (m BGPAttribute_MP_REACH) String() string {
|
|
var NLRI string
|
|
for i := range m.NLRI {
|
|
NLRI += m.NLRI[i].String() + ", "
|
|
}
|
|
|
|
return fmt.Sprintf("MP Reach: %v-%v (%v) (%v) / Nexthop: %v / NLRI: [ %v]", AfiToStr[m.Afi], SafiToStr[m.Safi], m.Afi, m.Safi, m.NextHop, NLRI)
|
|
}
|
|
|
|
func (m BGPAttribute_MP_UNREACH) String() string {
|
|
var NLRI string
|
|
for i := range m.NLRI {
|
|
NLRI += m.NLRI[i].String() + ", "
|
|
}
|
|
|
|
return fmt.Sprintf("MP Unreach: %v-%v (%v) (%v) / NLRI: [ %v]", AfiToStr[m.Afi], SafiToStr[m.Safi], m.Afi, m.Safi, NLRI)
|
|
}
|
|
|
|
func (m BGPAttribute_NEXTHOP) String() string {
|
|
return fmt.Sprintf("Nexthop %v", m.NextHop.String())
|
|
}
|
|
|
|
func (m BGPAttribute) String() string {
|
|
str := "%b %v (%v): %v"
|
|
return fmt.Sprintf(str, m.Flags, BgpAttributes[int(m.Code)], m.Code, m.Data)
|
|
}
|
|
|
|
func (m BGPMessageUpdate) String() string {
|
|
// To be completed
|
|
return fmt.Sprintf("BGP Update: Withdraw: %v / PathAttributes: %v / NLRI: %v", m.WithdrawnRoutes, m.PathAttributes, m.NLRI)
|
|
}
|
|
|
|
func (m BGPMessageUpdate) LenWithdrawn() int {
|
|
var sumW int
|
|
for i := range m.WithdrawnRoutes {
|
|
sumW += m.WithdrawnRoutes[i].Len(m.EnableAddPath)
|
|
}
|
|
return sumW
|
|
}
|
|
|
|
func (m BGPMessageUpdate) LenPathAttribute() int {
|
|
var sumPA int
|
|
for i := range m.PathAttributes {
|
|
sumPA += m.PathAttributes[i].Len()
|
|
}
|
|
return sumPA
|
|
}
|
|
|
|
func (m BGPMessageUpdate) LenContent() int {
|
|
sumW := m.LenWithdrawn()
|
|
sumPA := m.LenPathAttribute()
|
|
|
|
var sumA int
|
|
for i := range m.NLRI {
|
|
sumA += m.NLRI[i].Len(m.EnableAddPath)
|
|
}
|
|
|
|
return 2 + sumW + 2 + sumPA + sumA
|
|
}
|
|
|
|
func (m BGPMessageUpdate) Len() int {
|
|
return GetBGPHeaderLen() + m.LenContent()
|
|
}
|
|
|
|
func (m BGPMessageUpdate) Write(bw io.Writer) {
|
|
WriteBGPHeader(MESSAGE_UPDATE, uint16(m.LenContent()), bw)
|
|
|
|
binary.Write(bw, binary.BigEndian, uint16(m.LenWithdrawn()))
|
|
for i := range m.WithdrawnRoutes {
|
|
m.WithdrawnRoutes[i].Write(bw, m.EnableAddPath)
|
|
}
|
|
|
|
binary.Write(bw, binary.BigEndian, uint16(m.LenPathAttribute()))
|
|
for i := range m.PathAttributes {
|
|
m.PathAttributes[i].Write(bw)
|
|
}
|
|
|
|
for i := range m.NLRI {
|
|
m.NLRI[i].Write(bw, m.EnableAddPath)
|
|
}
|
|
}
|
|
|
|
func (m BGPAttribute_ORIGIN) Len() int {
|
|
return AttributeHeaderLen(1) + 1
|
|
}
|
|
|
|
func (m BGPAttribute_ORIGIN) Write(bw io.Writer) {
|
|
binary.Write(bw, binary.BigEndian, byte(ATTRIBUTE_TRANSITIVE))
|
|
binary.Write(bw, binary.BigEndian, byte(ATTRIBUTE_ORIGIN))
|
|
binary.Write(bw, binary.BigEndian, byte(1))
|
|
binary.Write(bw, binary.BigEndian, m.Origin)
|
|
}
|
|
|
|
func (m BGPAttribute_AGGREGATOR) Len() int {
|
|
return AttributeHeaderLen(8) + 8
|
|
}
|
|
|
|
func (m BGPAttribute_AGGREGATOR) Write(bw io.Writer) {
|
|
// May cause issue as ASN is 32 bits
|
|
|
|
binary.Write(bw, binary.BigEndian, byte(ATTRIBUTE_OPTIONAL))
|
|
binary.Write(bw, binary.BigEndian, byte(ATTRIBUTE_AGGREGATOR))
|
|
binary.Write(bw, binary.BigEndian, byte(8))
|
|
binary.Write(bw, binary.BigEndian, m.ASN)
|
|
binary.Write(bw, binary.BigEndian, m.Identifier)
|
|
}
|
|
|
|
func (m BGPAttribute_ATOMIC_AGGREGATE) Len() int {
|
|
return AttributeHeaderLen(0)
|
|
}
|
|
|
|
func (m BGPAttribute_ATOMIC_AGGREGATE) Write(bw io.Writer) {
|
|
WriteAttributeHeader(bw, 0, ATTRIBUTE_OPTIONAL, ATTRIBUTE_ATOMIC_AGGREGATE)
|
|
}
|
|
|
|
func (m BGPAttribute_MED) Len() int {
|
|
return AttributeHeaderLen(4) + 4
|
|
}
|
|
|
|
func (m BGPAttribute_MED) Write(bw io.Writer) {
|
|
binary.Write(bw, binary.BigEndian, byte(ATTRIBUTE_OPTIONAL))
|
|
binary.Write(bw, binary.BigEndian, byte(ATTRIBUTE_MED))
|
|
binary.Write(bw, binary.BigEndian, byte(4))
|
|
binary.Write(bw, binary.BigEndian, m.Med)
|
|
}
|
|
|
|
func (m BGPAttribute_LOCPREF) Len() int {
|
|
return AttributeHeaderLen(4) + 4
|
|
}
|
|
|
|
func (m BGPAttribute_LOCPREF) Write(bw io.Writer) {
|
|
WriteAttributeHeader(bw, 4, ATTRIBUTE_OPTIONAL, ATTRIBUTE_LOCPREF)
|
|
binary.Write(bw, binary.BigEndian, m.LocPref)
|
|
}
|
|
|
|
func (m BGPAttribute_ASPATH) Len() int {
|
|
var size int
|
|
for i := range m.Segments {
|
|
size += m.Segments[i].LenContent(m.Enc2Bytes)
|
|
}
|
|
return AttributeHeaderLen(size) + size
|
|
}
|
|
|
|
func (m BGPAttribute_ASPATH) Write(bw io.Writer) {
|
|
WriteAttributeHeader(bw, m.LenContent(), ATTRIBUTE_TRANSITIVE, ATTRIBUTE_ASPATH)
|
|
if len(m.Segments) == 0 {
|
|
return
|
|
}
|
|
|
|
for i := range m.Segments {
|
|
m.Segments[i].Write(bw, m.Enc2Bytes)
|
|
}
|
|
}
|
|
|
|
func (m BGPAttribute_ASPATH) LenContent() int {
|
|
var size int
|
|
for i := range m.Segments {
|
|
size += m.Segments[i].LenContent(m.Enc2Bytes)
|
|
}
|
|
return size
|
|
}
|
|
|
|
func (m ASPath_Segment) LenSets() int {
|
|
aspathlen := len(m.ASPath)
|
|
itera := aspathlen / 0xff
|
|
if aspathlen%0xff != 0 {
|
|
itera += 1
|
|
}
|
|
return itera
|
|
}
|
|
|
|
func (m ASPath_Segment) LenContent(enc2bytes bool) int {
|
|
if len(m.ASPath) == 0 {
|
|
return 0
|
|
}
|
|
|
|
numsets := m.LenSets()
|
|
if enc2bytes {
|
|
return 2*numsets + 2*len(m.ASPath)
|
|
}
|
|
return 2*numsets + 4*len(m.ASPath)
|
|
}
|
|
|
|
func (m ASPath_Segment) Write(bw io.Writer, enc2bytes bool) {
|
|
if len(m.ASPath) == 0 {
|
|
return
|
|
}
|
|
|
|
itera := m.LenSets()
|
|
var cursetlen byte
|
|
|
|
for i := 0; i < itera; i++ {
|
|
cursetlen = 0xff
|
|
if i == itera-1 {
|
|
cursetlen = byte(len(m.ASPath) % 0xff)
|
|
}
|
|
binary.Write(bw, binary.BigEndian, m.SType)
|
|
binary.Write(bw, binary.BigEndian, byte(cursetlen))
|
|
for j := 0xff * i; j < len(m.ASPath) && j < 0xff*(i+1); j++ {
|
|
if enc2bytes {
|
|
binary.Write(bw, binary.BigEndian, uint16(m.ASPath[j]))
|
|
} else {
|
|
binary.Write(bw, binary.BigEndian, m.ASPath[j])
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func AttributeHeaderLen(size int) int {
|
|
if size > 0xff {
|
|
return 4
|
|
} else {
|
|
return 3
|
|
}
|
|
}
|
|
|
|
func IPtoBytes(ip net.IP) []byte {
|
|
if ip.To4() == nil {
|
|
return ip.To16()
|
|
}
|
|
return ip.To4()
|
|
}
|
|
|
|
func WriteAttributeHeader(bw io.Writer, size int, attrflag byte, attrcode byte) {
|
|
var extended byte
|
|
if size > 0xff {
|
|
extended = ATTRIBUTE_EXTENDED
|
|
}
|
|
binary.Write(bw, binary.BigEndian, byte(attrflag|extended))
|
|
binary.Write(bw, binary.BigEndian, attrcode)
|
|
if extended != 0 {
|
|
binary.Write(bw, binary.BigEndian, byte((size&0xff00)>>8))
|
|
}
|
|
binary.Write(bw, binary.BigEndian, byte(size&0xff))
|
|
}
|
|
|
|
func (m BGPAttribute_COMMUNITIES) LenContent() int {
|
|
return 4 * len(m.Communities)
|
|
}
|
|
|
|
func (m BGPAttribute_COMMUNITIES) Len() int {
|
|
size := m.LenContent()
|
|
return AttributeHeaderLen(size) + size
|
|
}
|
|
|
|
func (m BGPAttribute_COMMUNITIES) Write(bw io.Writer) {
|
|
WriteAttributeHeader(bw, m.LenContent(), ATTRIBUTE_TRANSITIVEOPT, ATTRIBUTE_COMMUNITIES)
|
|
for i := range m.Communities {
|
|
binary.Write(bw, binary.BigEndian, m.Communities[i])
|
|
}
|
|
}
|
|
|
|
func (m BGPAttribute_MP_REACH) LenMrt() uint16 {
|
|
ip := IPtoBytes(m.NextHop)
|
|
return 2 + 1 + 1 + uint16(len(ip))
|
|
}
|
|
|
|
func (m BGPAttribute_MP_REACH) WriteMrt(buf io.Writer) {
|
|
binary.Write(buf, binary.BigEndian, byte(ATTRIBUTE_OPTIONAL))
|
|
binary.Write(buf, binary.BigEndian, byte(ATTRIBUTE_REACH))
|
|
|
|
nhb := IPtoBytes(m.NextHop)
|
|
lengthnh := len(nhb)
|
|
|
|
binary.Write(buf, binary.BigEndian, byte(1+lengthnh))
|
|
binary.Write(buf, binary.BigEndian, byte(lengthnh))
|
|
binary.Write(buf, binary.BigEndian, nhb)
|
|
}
|
|
|
|
func (m BGPAttribute_MP_REACH) GetNextHopLen() int {
|
|
return len(IPtoBytes(m.NextHop))
|
|
}
|
|
|
|
func (m BGPAttribute_MP_REACH) ContentLen() int {
|
|
var sum int
|
|
for i := range m.NLRI {
|
|
sum += m.NLRI[i].Len(m.EnableAddPath)
|
|
}
|
|
|
|
size := 4 + m.GetNextHopLen() + 1 + sum
|
|
return size
|
|
}
|
|
|
|
func (m BGPAttribute_MP_REACH) Len() int {
|
|
size := m.ContentLen()
|
|
return AttributeHeaderLen(size) + size
|
|
}
|
|
|
|
func (m BGPAttribute_MP_REACH) Write(bw io.Writer) {
|
|
WriteAttributeHeader(bw, m.ContentLen(), ATTRIBUTE_OPTIONAL, ATTRIBUTE_REACH)
|
|
|
|
binary.Write(bw, binary.BigEndian, m.Afi)
|
|
binary.Write(bw, binary.BigEndian, m.Safi)
|
|
binary.Write(bw, binary.BigEndian, byte(m.GetNextHopLen()))
|
|
binary.Write(bw, binary.BigEndian, IPtoBytes(m.NextHop))
|
|
binary.Write(bw, binary.BigEndian, byte(0))
|
|
for i := range m.NLRI {
|
|
m.NLRI[i].Write(bw, m.EnableAddPath)
|
|
}
|
|
}
|
|
func (m BGPAttribute_MP_UNREACH) ContentLen() int {
|
|
var sum int
|
|
for i := range m.NLRI {
|
|
sum += m.NLRI[i].Len(m.EnableAddPath)
|
|
}
|
|
size := 3 + sum
|
|
return size
|
|
}
|
|
|
|
func (m BGPAttribute_MP_UNREACH) Len() int {
|
|
size := m.ContentLen()
|
|
return AttributeHeaderLen(size) + size
|
|
}
|
|
|
|
func (m BGPAttribute_MP_UNREACH) Write(bw io.Writer) {
|
|
WriteAttributeHeader(bw, m.ContentLen(), ATTRIBUTE_OPTIONAL, ATTRIBUTE_UNREACH)
|
|
|
|
binary.Write(bw, binary.BigEndian, m.Afi)
|
|
binary.Write(bw, binary.BigEndian, m.Safi)
|
|
for i := range m.NLRI {
|
|
m.NLRI[i].Write(bw, m.EnableAddPath)
|
|
}
|
|
}
|
|
|
|
func (m BGPAttribute_NEXTHOP) ContentLen() int {
|
|
ip := IPtoBytes(m.NextHop)
|
|
return len(ip)
|
|
}
|
|
|
|
func (m BGPAttribute_NEXTHOP) Len() int {
|
|
size := m.ContentLen()
|
|
return AttributeHeaderLen(size) + size
|
|
}
|
|
|
|
func (m BGPAttribute_NEXTHOP) Write(bw io.Writer) {
|
|
WriteAttributeHeader(bw, m.ContentLen(), ATTRIBUTE_TRANSITIVE, ATTRIBUTE_NEXTHOP)
|
|
|
|
ip := IPtoBytes(m.NextHop)
|
|
binary.Write(bw, binary.BigEndian, ip)
|
|
}
|
|
|
|
func (m BGPAttribute) Len() int {
|
|
size := len(m.Data)
|
|
return AttributeHeaderLen(size) + size
|
|
}
|
|
|
|
func (m BGPAttribute) Write(bw io.Writer) {
|
|
WriteAttributeHeader(bw, len(m.Data), m.Flags, m.Code)
|
|
binary.Write(bw, binary.BigEndian, m.Data)
|
|
}
|
|
|
|
/*func (m *BGPMessageUpdate) AddASNToPath(asn uint32) {
|
|
for i := range(m.PathAttributes) {
|
|
if v,ok := m.PathAttributes[i].(BGPAttribute_ASPATH); ok {
|
|
v.ASPath = append(v.ASPath, asn)
|
|
m.PathAttributes[i] = v
|
|
return
|
|
}
|
|
}
|
|
m.PathAttributes = append(m.PathAttributes, BGPAttribute_ASPATH{
|
|
SType: 2,
|
|
ASPath: []uint32{asn,},
|
|
})
|
|
}*/
|
|
|
|
func ParseNLRI(b []byte, afi uint16, safi byte, path bool) ([]NLRI, error) {
|
|
prefixlist := make([]NLRI, 0)
|
|
|
|
if afi != AFI_IPV4 && afi != AFI_IPV6 {
|
|
return prefixlist, errors.New(fmt.Sprintf("ParseNLRI: cannot decode this Afi/Safi %v/%v", afi, safi))
|
|
}
|
|
|
|
psize := 32
|
|
asize := 4
|
|
if afi == AFI_IPV6 {
|
|
psize = 128
|
|
asize = 16
|
|
}
|
|
|
|
i := 0
|
|
|
|
for i < len(b) {
|
|
|
|
var pathid uint32
|
|
if path {
|
|
if len(b)-i < 5 {
|
|
return nil, errors.New(fmt.Sprintf("ParseNLRI: wrong NLRI size with add-path: %v < 5", len(b)))
|
|
}
|
|
pathid = uint32(b[i])<<24 | uint32(b[i+1])<<16 | uint32(b[i+2])<<8 | uint32(b[i+3])
|
|
i += 4
|
|
}
|
|
|
|
length := int(b[i])
|
|
lengthb := length
|
|
add := 0
|
|
if length%8 != 0 {
|
|
add = 1
|
|
}
|
|
length = length/8 + add
|
|
i++
|
|
if i+length > len(b) {
|
|
return prefixlist, errors.New(fmt.Sprintf("ParseNLRI: wrong NLRI size: %v > %v", i+length, len(b)))
|
|
}
|
|
prefix := b[i : i+length]
|
|
|
|
mask := net.CIDRMask(lengthb, psize)
|
|
ip := make([]byte, asize)
|
|
|
|
if len(prefix) > len(ip) {
|
|
return prefixlist, errors.New(fmt.Sprintf("ParseNLRI: wrong IP size: %v > %v", len(prefix), len(ip)))
|
|
}
|
|
|
|
for j := range prefix {
|
|
ip[j] = prefix[j]
|
|
}
|
|
ipnet := net.IPNet{
|
|
IP: ip,
|
|
Mask: mask,
|
|
}
|
|
prefixlist = append(prefixlist, NLRI_IPPrefix{
|
|
Prefix: ipnet,
|
|
PathId: pathid,
|
|
})
|
|
|
|
i += length
|
|
}
|
|
return prefixlist, nil
|
|
}
|
|
|
|
func ParsePathAttribute(b []byte, addpathlist []AfiSafi, enc2bytes bool) ([]BGPAttributeIf, error) {
|
|
attributes := make([]BGPAttributeIf, 0)
|
|
i := 0
|
|
for i < len(b) {
|
|
if len(b)-i < 3 {
|
|
return attributes, errors.New(fmt.Sprintf("ParsePathAttribute: attribute size (need 3 bytes, got %v)", len(b)-i))
|
|
}
|
|
attrflag := b[i]
|
|
attrcode := b[i+1]
|
|
extended := byte((attrflag & ATTRIBUTE_EXTENDED) >> 4)
|
|
length := int(b[i+2])
|
|
|
|
if extended != 0 && i+3 > len(b)-1 {
|
|
return attributes, errors.New(fmt.Sprintf("ParsePathAttribute: wrong extended size: %v > %v", i+3, len(b)-1))
|
|
}
|
|
|
|
offset := 0
|
|
if extended != 0 {
|
|
length = int(uint16(b[i+2])<<8 | uint16(b[i+3]))
|
|
offset = 1
|
|
}
|
|
if i+offset+3+length > len(b) || i+offset+3 > len(b) {
|
|
return attributes, errors.New(fmt.Sprintf("ParsePathAttribute: wrong size: %v > %v or %v > %v (ext: %v / %v)", i+offset+3+length, len(b), i+offset+3, len(b), i, extended))
|
|
}
|
|
|
|
data := b[i+offset+3 : i+offset+3+length]
|
|
|
|
if i+3+offset+length > len(b) {
|
|
return attributes, errors.New(fmt.Sprintf("ParsePathAttribute: wrong attribute size: %v > %v", i+3+length, len(b)))
|
|
}
|
|
|
|
var intf SerializableInterface
|
|
buf := bytes.NewBuffer(data)
|
|
|
|
switch attrcode {
|
|
case ATTRIBUTE_ORIGIN:
|
|
o := byte(2)
|
|
if len(data) > 0 {
|
|
o = data[0]
|
|
} else {
|
|
return attributes, errors.New(fmt.Sprintf("ParsePathAttribute: empty data for ORIGIN attribute"))
|
|
}
|
|
a := BGPAttribute_ORIGIN{
|
|
Origin: o,
|
|
}
|
|
intf = a
|
|
case ATTRIBUTE_MED:
|
|
a := BGPAttribute_MED{}
|
|
binary.Read(buf, binary.BigEndian, &(a.Med))
|
|
intf = a
|
|
case ATTRIBUTE_AGGREGATOR:
|
|
a := BGPAttribute_AGGREGATOR{}
|
|
if len(data) == 8 && !enc2bytes {
|
|
binary.Read(buf, binary.BigEndian, &(a.ASN))
|
|
a.Identifier = data[4:8]
|
|
} else if len(data) == 6 && enc2bytes {
|
|
var tmpas uint16
|
|
binary.Read(buf, binary.BigEndian, &tmpas)
|
|
a.ASN = uint32(tmpas)
|
|
a.Identifier = data[2:6]
|
|
}
|
|
a.Enc2Bytes = enc2bytes
|
|
intf = a
|
|
case ATTRIBUTE_ATOMIC_AGGREGATE:
|
|
a := BGPAttribute_ATOMIC_AGGREGATE{}
|
|
intf = a
|
|
case ATTRIBUTE_LOCPREF:
|
|
a := BGPAttribute_LOCPREF{}
|
|
binary.Read(buf, binary.BigEndian, &(a.LocPref))
|
|
intf = a
|
|
case ATTRIBUTE_ASPATH:
|
|
a := BGPAttribute_ASPATH{Segments: make([]ASPath_Segment, 0)}
|
|
|
|
var aslen byte
|
|
var err_rd error
|
|
var stype byte
|
|
stype, err_rd = buf.ReadByte()
|
|
for err_rd == nil {
|
|
aslen, err_rd = buf.ReadByte()
|
|
if err_rd != nil {
|
|
break
|
|
}
|
|
|
|
s := ASPath_Segment{SType: stype, ASPath: make([]uint32, 0)}
|
|
|
|
if err_rd != nil {
|
|
break
|
|
}
|
|
if !enc2bytes {
|
|
var tmpas uint32
|
|
if err_rd != nil {
|
|
break
|
|
}
|
|
for j := 0; j < int(aslen) && j <= 255; j++ {
|
|
binary.Read(buf, binary.BigEndian, &tmpas)
|
|
s.ASPath = append(s.ASPath, tmpas)
|
|
}
|
|
|
|
} else {
|
|
var tmpas uint16
|
|
if err_rd != nil {
|
|
break
|
|
}
|
|
for j := 0; j < int(aslen) && j <= 255; j++ {
|
|
binary.Read(buf, binary.BigEndian, &tmpas)
|
|
s.ASPath = append(s.ASPath, uint32(tmpas))
|
|
}
|
|
|
|
}
|
|
a.Segments = append(a.Segments, s)
|
|
stype, err_rd = buf.ReadByte()
|
|
if err_rd != nil {
|
|
break
|
|
}
|
|
}
|
|
a.Enc2Bytes = enc2bytes
|
|
intf = a
|
|
case ATTRIBUTE_NEXTHOP:
|
|
intf = BGPAttribute_NEXTHOP{NextHop: data[0:4]}
|
|
case ATTRIBUTE_COMMUNITIES:
|
|
a := BGPAttribute_COMMUNITIES{Communities: make([]uint32, length/4)}
|
|
for j := 0; j < length/4; j++ {
|
|
binary.Read(buf, binary.BigEndian, &(a.Communities[j]))
|
|
}
|
|
intf = a
|
|
case ATTRIBUTE_REACH:
|
|
a := BGPAttribute_MP_REACH{}
|
|
binary.Read(buf, binary.BigEndian, &(a.Afi))
|
|
binary.Read(buf, binary.BigEndian, &(a.Safi))
|
|
nhlen, _ := buf.ReadByte()
|
|
nh := make([]byte, nhlen)
|
|
buf.Read(nh)
|
|
a.NextHop = nh
|
|
buf.ReadByte()
|
|
parseinfo := InAfiSafi(a.Afi, a.Safi, addpathlist)
|
|
a.NLRI, _ = ParseNLRI(buf.Bytes(), a.Afi, a.Safi, parseinfo)
|
|
a.EnableAddPath = parseinfo
|
|
intf = a
|
|
case ATTRIBUTE_UNREACH:
|
|
a := BGPAttribute_MP_UNREACH{}
|
|
binary.Read(buf, binary.BigEndian, &(a.Afi))
|
|
binary.Read(buf, binary.BigEndian, &(a.Safi))
|
|
parseinfo := InAfiSafi(a.Afi, a.Safi, addpathlist)
|
|
a.NLRI, _ = ParseNLRI(buf.Bytes(), a.Afi, a.Safi, parseinfo)
|
|
intf = a
|
|
default:
|
|
intf = BGPAttribute{
|
|
attrflag,
|
|
attrcode,
|
|
data,
|
|
}
|
|
}
|
|
|
|
attributes = append(attributes, intf)
|
|
|
|
i += 3 + length + offset
|
|
}
|
|
return attributes, nil
|
|
}
|
|
|
|
func ParseUpdate(b []byte, addpathlist []AfiSafi, enc2bytes bool) (*BGPMessageUpdate, error) {
|
|
m := &BGPMessageUpdate{}
|
|
var err error
|
|
|
|
addpath_ipv4uni := InAfiSafi(AFI_IPV4, SAFI_UNICAST, addpathlist)
|
|
m.EnableAddPath = addpath_ipv4uni
|
|
|
|
if len(b) < 4 {
|
|
return nil, errors.New(fmt.Sprintf("ParseUpdate: wrong withdrawn routes size: %v < 4", len(b)))
|
|
}
|
|
|
|
wdrouteslen := int(uint16(b[0])<<8 | uint16(b[1]))
|
|
|
|
if wdrouteslen+4 > len(b) {
|
|
return nil, errors.New(fmt.Sprintf("ParseUpdate: wrong withdrawn routes size: %v > %v", wdrouteslen+4, len(b)))
|
|
}
|
|
offset := 2
|
|
withdrawnroutes := b[offset : offset+wdrouteslen]
|
|
m.WithdrawnRoutes, err = ParseNLRI(withdrawnroutes, AFI_IPV4, SAFI_UNICAST, addpath_ipv4uni)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
offset += wdrouteslen
|
|
|
|
tplen := int(uint16(b[offset])<<8 | uint16(b[offset+1]))
|
|
offset += 2
|
|
|
|
if tplen+offset > len(b) {
|
|
return nil, errors.New(fmt.Sprintf("ParseUpdate: wrong total path size: %v > %v", tplen+offset, len(b)))
|
|
}
|
|
pathattributes := b[offset : offset+tplen]
|
|
m.PathAttributes, err = ParsePathAttribute(pathattributes, addpathlist, enc2bytes)
|
|
if err != nil {
|
|
return m, err
|
|
}
|
|
|
|
offset += tplen
|
|
NLRI := b[offset:]
|
|
m.NLRI, err = ParseNLRI(NLRI, AFI_IPV4, SAFI_UNICAST, addpath_ipv4uni)
|
|
if err != nil {
|
|
return m, err
|
|
}
|
|
|
|
return m, nil
|
|
}
|
|
|
|
func CraftUpdateMessage() *BGPMessageUpdate {
|
|
//_, prefix, _ := net.ParseCIDR("8.8.8.8/24")
|
|
|
|
_, prefixtest, _ := net.ParseCIDR("2001::/46")
|
|
ip := net.ParseIP("2002::1")
|
|
pa := []BGPAttributeIf{
|
|
BGPAttribute_ORIGIN{
|
|
Origin: 2,
|
|
},
|
|
BGPAttribute_ASPATH{
|
|
Segments: []ASPath_Segment{ASPath_Segment{ASPath: []uint32{65001}}},
|
|
},
|
|
BGPAttribute_COMMUNITIES{
|
|
Communities: []uint32{0x7b0929},
|
|
},
|
|
//BGPAttribute_NEXTHOP{
|
|
// NextHop: []byte{1,2,3,4},
|
|
//},
|
|
BGPAttribute_MP_REACH{
|
|
Afi: AFI_IPV6,
|
|
Safi: SAFI_UNICAST,
|
|
NextHop: ip,
|
|
//enableAddPath: true,
|
|
NLRI: []NLRI{
|
|
NLRI_IPPrefix{
|
|
PathId: uint32(time.Now().UTC().Unix()),
|
|
Prefix: *prefixtest,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
m := &BGPMessageUpdate{
|
|
//NLRI: []NLRI{NLRI{Prefix: *prefix,PathId:123,},},
|
|
PathAttributes: pa,
|
|
}
|
|
|
|
return m
|
|
}
|