summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--packet/bgp.go558
1 files changed, 535 insertions, 23 deletions
diff --git a/packet/bgp.go b/packet/bgp.go
index 5b927050..a2b5aa5c 100644
--- a/packet/bgp.go
+++ b/packet/bgp.go
@@ -20,8 +20,6 @@ import (
"fmt"
"math"
"net"
- "reflect"
- "strings"
)
// move somewhere else
@@ -84,13 +82,9 @@ func (c BGPCapabilityCode) String() string {
return "Unknown"
}
-func structName(m interface{}) string {
- r := reflect.TypeOf(m)
- return strings.TrimLeft(r.String(), "*bgp.")
-}
-
type ParameterCapabilityInterface interface {
DecodeFromBytes([]byte) error
+ Serialize() ([]byte, error)
Len() int
}
@@ -110,6 +104,17 @@ func (c *DefaultParameterCapability) DecodeFromBytes(data []byte) error {
return nil
}
+func (c *DefaultParameterCapability) Serialize() ([]byte, error) {
+ buf := make([]byte, 2)
+ buf[0] = uint8(c.CapCode)
+ if c.CapLen == 0 {
+ c.CapLen = uint8(len(c.CapValue) + 2)
+ }
+ buf[1] = c.CapLen
+ buf = append(buf, c.CapValue...)
+ return buf, nil
+}
+
func (c *DefaultParameterCapability) Len() int {
return int(c.CapLen + 2)
}
@@ -135,6 +140,15 @@ func (c *CapMultiProtocol) DecodeFromBytes(data []byte) error {
return nil
}
+func (c *CapMultiProtocol) Serialize() ([]byte, error) {
+ buf := make([]byte, 6)
+ buf[0] = uint8(BGP_CAP_MULTIPROTOCOL)
+ buf[1] = 4
+ binary.BigEndian.PutUint16(buf[2:4], c.CapValue.AFI)
+ buf[5] = c.CapValue.SAFI
+ return buf, nil
+}
+
type CapRouteRefresh struct {
DefaultParameterCapability
}
@@ -176,6 +190,21 @@ func (c *CapGracefulRestart) DecodeFromBytes(data []byte) error {
return nil
}
+func (c *CapGracefulRestart) Serialize() ([]byte, error) {
+ buf := make([]byte, 4)
+ buf[0] = uint8(BGP_CAP_MULTIPROTOCOL)
+ binary.BigEndian.PutUint16(buf[2:4], uint16(c.CapValue.Flags)<<12|c.CapValue.Time)
+ for _, t := range c.CapValue.Tuples {
+ tbuf := make([]byte, 4)
+ binary.BigEndian.PutUint16(tbuf[0:2], t.AFI)
+ tbuf[2] = t.SAFI
+ tbuf[3] = t.Flags
+ buf = append(buf, tbuf...)
+ }
+ buf[1] = uint8(len(buf) - 2)
+ return buf, nil
+}
+
type CapFourOctetASNumber struct {
DefaultParameterCapability
CapValue uint32
@@ -191,6 +220,14 @@ func (c *CapFourOctetASNumber) DecodeFromBytes(data []byte) error {
return nil
}
+func (c *CapFourOctetASNumber) Serialize() ([]byte, error) {
+ buf := make([]byte, 6)
+ buf[0] = uint8(BGP_CAP_FOUR_OCTET_AS_NUMBER)
+ buf[1] = uint8(len(buf))
+ binary.BigEndian.PutUint32(buf[2:6], c.CapValue)
+ return buf, nil
+}
+
type CapEnhancedRouteRefresh struct {
DefaultParameterCapability
}
@@ -204,6 +241,7 @@ type CapUnknown struct {
}
type OptionParameterInterface interface {
+ Serialize() ([]byte, error)
}
type OptionParameterCapability struct {
@@ -212,12 +250,6 @@ type OptionParameterCapability struct {
Capability []ParameterCapabilityInterface
}
-type OptionParameterUnknown struct {
- ParamType uint8
- ParamLen uint8
- Value []byte
-}
-
func (o *OptionParameterCapability) DecodeFromBytes(data []byte) error {
if uint8(len(data)) < o.ParamLen {
return fmt.Errorf("Not all OptionParameterCapability bytes available")
@@ -252,6 +284,37 @@ func (o *OptionParameterCapability) DecodeFromBytes(data []byte) error {
return nil
}
+func (o *OptionParameterCapability) Serialize() ([]byte, error) {
+ buf := make([]byte, 2)
+ buf[0] = o.ParamType
+ //buf[1] = o.ParamLen
+ for _, p := range o.Capability {
+ pbuf, err := p.Serialize()
+ if err != nil {
+ return nil, err
+ }
+ buf = append(buf, pbuf...)
+ }
+ buf[1] = uint8(len(buf) - 2)
+ return buf, nil
+}
+
+type OptionParameterUnknown struct {
+ ParamType uint8
+ ParamLen uint8
+ Value []byte
+}
+
+func (o *OptionParameterUnknown) Serialize() ([]byte, error) {
+ buf := make([]byte, 2)
+ buf[0] = o.ParamType
+ if o.ParamLen == 0 {
+ o.ParamLen = uint8(len(o.Value))
+ }
+ buf[1] = o.ParamLen
+ return append(buf, o.Value...), nil
+}
+
type BGPOpen struct {
Version uint8
MyAS uint16
@@ -278,13 +341,13 @@ func (msg *BGPOpen) DecodeFromBytes(data []byte) error {
rest -= paramlen + 2
if paramtype == BGP_OPT_CAPABILITY {
- p := OptionParameterCapability{}
+ p := &OptionParameterCapability{}
p.ParamType = paramtype
p.ParamLen = paramlen
p.DecodeFromBytes(data[2 : 2+paramlen])
msg.OptParams = append(msg.OptParams, p)
} else {
- p := OptionParameterUnknown{}
+ p := &OptionParameterUnknown{}
p.ParamType = paramtype
p.ParamLen = paramlen
p.Value = data[2 : 2+paramlen]
@@ -295,8 +358,28 @@ func (msg *BGPOpen) DecodeFromBytes(data []byte) error {
return nil
}
+func (msg *BGPOpen) Serialize() ([]byte, error) {
+ buf := make([]byte, 10)
+ buf[0] = msg.Version
+ binary.BigEndian.PutUint16(buf[1:3], msg.MyAS)
+ binary.BigEndian.PutUint16(buf[3:5], msg.HoldTime)
+ copy(buf[5:9], msg.ID)
+ for _, p := range msg.OptParams {
+ pbuf, err := p.Serialize()
+ if err != nil {
+ return nil, err
+ }
+ buf = append(buf, pbuf...)
+ }
+ buf[9] = uint8(len(buf) - 10)
+ return buf, nil
+}
+
type AddrPrefixInterface interface {
DecodeFromBytes([]byte) error
+ Serialize() ([]byte, error)
+ AFI() uint16
+ SAFI() uint8
Len() int
}
@@ -313,6 +396,20 @@ func (r *IPAddrPrefixDefault) decodePrefix(data []byte, bitlen uint8, addrlen ui
return nil
}
+func (r *IPAddrPrefixDefault) serializePrefix(bitlen uint8) ([]byte, error) {
+ bytelen := (bitlen + 7) / 8
+ buf := make([]byte, bytelen)
+ copy(buf, r.Prefix)
+ // clear trailing bits in the last byte. rfc doesn't require
+ // this though.
+ if bitlen%8 != 0 {
+ mask := 0xff00 >> (bitlen % 8)
+ last_byte_value := buf[bytelen-1] & byte(mask)
+ buf[bytelen-1] = last_byte_value
+ }
+ return buf, nil
+}
+
func (r *IPAddrPrefixDefault) Len() int {
return int(1 + ((r.Length + 7) / 8))
}
@@ -331,10 +428,32 @@ func (r *IPAddrPrefix) DecodeFromBytes(data []byte) error {
return nil
}
+func (r *IPAddrPrefix) Serialize() ([]byte, error) {
+ buf := make([]byte, 1)
+ buf[0] = r.Length
+ pbuf, err := r.serializePrefix(r.Length)
+ if err != nil {
+ return nil, err
+ }
+ return append(buf, pbuf...), nil
+}
+
+func (r *IPAddrPrefix) AFI() uint16 {
+ return AFI_IP
+}
+
+func (r *IPAddrPrefix) SAFI() uint8 {
+ return SAFI_UNICAST
+}
+
type IPv6AddrPrefix struct {
IPAddrPrefix
}
+func (r *IPv6AddrPrefix) AFI() uint16 {
+ return AFI_IP6
+}
+
func NewIPv6AddrPrefix() *IPv6AddrPrefix {
p := &IPv6AddrPrefix{}
p.addrlen = 16
@@ -353,6 +472,7 @@ const (
type RouteDistinguisherInterface interface {
DecodeFromBytes([]byte) error
+ Serialize() ([]byte, error)
Len() int
}
@@ -361,12 +481,19 @@ type DefaultRouteDistinguisher struct {
Value []byte
}
-func (rd DefaultRouteDistinguisher) DecodeFromBytes(data []byte) error {
+func (rd *DefaultRouteDistinguisher) DecodeFromBytes(data []byte) error {
rd.Type = binary.BigEndian.Uint16(data[0:2])
rd.Value = data[2:8]
return nil
}
+func (rd *DefaultRouteDistinguisher) Serialize() ([]byte, error) {
+ buf := make([]byte, 8)
+ binary.BigEndian.PutUint16(buf, rd.Type)
+ copy(buf[2:], rd.Value)
+ return buf, nil
+}
+
func (rd *DefaultRouteDistinguisher) Len() int { return 8 }
type RouteDistinguisherTwoOctetASValue struct {
@@ -379,6 +506,14 @@ type RouteDistinguisherTwoOctetAS struct {
Value RouteDistinguisherTwoOctetASValue
}
+func (rd *RouteDistinguisherTwoOctetAS) Serialize() ([]byte, error) {
+ buf := make([]byte, 6)
+ binary.BigEndian.PutUint16(buf[0:], rd.Value.Admin)
+ binary.BigEndian.PutUint32(buf[2:], rd.Value.Assigned)
+ rd.DefaultRouteDistinguisher.Value = buf
+ return rd.DefaultRouteDistinguisher.Serialize()
+}
+
type RouteDistinguisherIPAddressASValue struct {
Admin net.IP
Assigned uint16
@@ -389,6 +524,14 @@ type RouteDistinguisherIPAddressAS struct {
Value RouteDistinguisherIPAddressASValue
}
+func (rd *RouteDistinguisherIPAddressAS) Serialize() ([]byte, error) {
+ buf := make([]byte, 6)
+ copy(buf[0:], rd.Value.Admin)
+ binary.BigEndian.PutUint16(buf[4:], rd.Value.Assigned)
+ rd.DefaultRouteDistinguisher.Value = buf
+ return rd.DefaultRouteDistinguisher.Serialize()
+}
+
type RouteDistinguisherFourOctetASValue struct {
Admin uint32
Assigned uint16
@@ -399,30 +542,43 @@ type RouteDistinguisherFourOctetAS struct {
Value RouteDistinguisherFourOctetASValue
}
+func (rd *RouteDistinguisherFourOctetAS) Serialize() ([]byte, error) {
+ buf := make([]byte, 6)
+ binary.BigEndian.PutUint32(buf[0:], rd.Value.Admin)
+ binary.BigEndian.PutUint16(buf[4:], rd.Value.Assigned)
+ rd.DefaultRouteDistinguisher.Value = buf
+ return rd.DefaultRouteDistinguisher.Serialize()
+}
+
type RouteDistinguisherUnknown struct {
DefaultRouteDistinguisher
}
func getRouteDistinguisher(data []byte) RouteDistinguisherInterface {
- switch binary.BigEndian.Uint16(data[0:2]) {
+ rdtype := binary.BigEndian.Uint16(data[0:2])
+ switch rdtype {
case BGP_RD_TWO_OCTET_AS:
rd := &RouteDistinguisherTwoOctetAS{}
+ rd.Type = rdtype
rd.Value.Admin = binary.BigEndian.Uint16(data[2:4])
rd.Value.Assigned = binary.BigEndian.Uint32(data[4:8])
return rd
case BGP_RD_IPV4_ADDRESS:
rd := &RouteDistinguisherIPAddressAS{}
+ rd.Type = rdtype
rd.Value.Admin = data[2:6]
rd.Value.Assigned = binary.BigEndian.Uint16(data[6:8])
return rd
case BGP_RD_FOUR_OCTET_AS:
rd := &RouteDistinguisherFourOctetAS{}
+ rd.Type = rdtype
rd.Value.Admin = binary.BigEndian.Uint32(data[2:6])
rd.Value.Assigned = binary.BigEndian.Uint16(data[6:8])
return rd
}
-
- return &RouteDistinguisherUnknown{}
+ rd := &RouteDistinguisherUnknown{}
+ rd.Type = rdtype
+ return rd
}
type Label struct {
@@ -449,6 +605,18 @@ func (l *Label) DecodeFromBytes(data []byte) error {
return nil
}
+func (l *Label) Serialize() ([]byte, error) {
+ buf := make([]byte, len(l.Labels)*3)
+ for i, label := range l.Labels {
+ label = label << 4
+ buf[i*3] = byte((label >> 16) & 0xff)
+ buf[i*3+1] = byte((label >> 8) & 0xff)
+ buf[i*3+2] = byte(label & 0xff)
+ }
+ buf[len(buf)-1] |= 1
+ return buf, nil
+}
+
func (l *Label) Len() int { return 3 * len(l.Labels) }
type LabelledVPNIPAddrPrefix struct {
@@ -473,6 +641,36 @@ func (l *LabelledVPNIPAddrPrefix) DecodeFromBytes(data []byte) error {
return nil
}
+func (l *LabelledVPNIPAddrPrefix) Serialize() ([]byte, error) {
+ buf := make([]byte, 1)
+ buf[0] = l.Length
+ lbuf, err := l.Labels.Serialize()
+ if err != nil {
+ return nil, err
+ }
+ buf = append(buf, lbuf...)
+ rbuf, err := l.RD.Serialize()
+ if err != nil {
+ return nil, err
+ }
+ buf = append(buf, rbuf...)
+ restbits := int(l.Length) - 8*(l.Labels.Len()+l.RD.Len())
+ pbuf, err := l.serializePrefix(uint8(restbits))
+ if err != nil {
+ return nil, err
+ }
+ buf = append(buf, pbuf...)
+ return buf, nil
+}
+
+func (l *LabelledVPNIPAddrPrefix) AFI() uint16 {
+ return AFI_IP
+}
+
+func (l *LabelledVPNIPAddrPrefix) SAFI() uint8 {
+ return SAFI_MPLS_VPN
+}
+
func NewLabelledVPNIPAddrPrefix() *LabelledVPNIPAddrPrefix {
p := &LabelledVPNIPAddrPrefix{}
p.addrlen = 4
@@ -483,6 +681,10 @@ type LabelledVPNIPv6AddrPrefix struct {
LabelledVPNIPAddrPrefix
}
+func (l *LabelledVPNIPv6AddrPrefix) AFI() uint16 {
+ return AFI_IP6
+}
+
func NewLabelledVPNIPv6AddrPrefix() *LabelledVPNIPv6AddrPrefix {
p := &LabelledVPNIPv6AddrPrefix{}
p.addrlen = 16
@@ -495,6 +697,14 @@ type LabelledIPAddrPrefix struct {
addrlen uint8
}
+func (r *LabelledIPAddrPrefix) AFI() uint16 {
+ return AFI_IP
+}
+
+func (r *LabelledIPAddrPrefix) SAFI() uint8 {
+ return SAFI_MPLS_LABEL
+}
+
func (r *IPAddrPrefix) decodeNextHop(data []byte) net.IP {
if r.addrlen == 0 {
r.addrlen = 4
@@ -527,6 +737,23 @@ func (l *LabelledIPAddrPrefix) DecodeFromBytes(data []byte) error {
return nil
}
+func (l *LabelledIPAddrPrefix) Serialize() ([]byte, error) {
+ buf := make([]byte, 1)
+ buf[0] = l.Length
+ restbits := int(l.Length) - 8*(l.Labels.Len())
+ lbuf, err := l.Labels.Serialize()
+ if err != nil {
+ return nil, err
+ }
+ buf = append(buf, lbuf...)
+ pbuf, err := l.serializePrefix(uint8(restbits))
+ if err != nil {
+ return nil, err
+ }
+ buf = append(buf, pbuf...)
+ return buf, nil
+}
+
func NewLabelledIPAddrPrefix() *LabelledIPAddrPrefix {
p := &LabelledIPAddrPrefix{}
p.addrlen = 4
@@ -554,6 +781,24 @@ func (n *RouteTargetMembershipNLRI) DecodeFromBytes(data []byte) error {
return nil
}
+func (n *RouteTargetMembershipNLRI) Serialize() ([]byte, error) {
+ buf := make([]byte, 4)
+ binary.BigEndian.PutUint32(buf, n.AS)
+ ebuf, err := n.RouteTarget.Serialize()
+ if err != nil {
+ return nil, err
+ }
+ return append(buf, ebuf...), nil
+}
+
+func (n *RouteTargetMembershipNLRI) AFI() uint16 {
+ return AFI_IP
+}
+
+func (n *RouteTargetMembershipNLRI) SAFI() uint8 {
+ return SAFI_ROUTE_TARGET_CONSTRTAINS
+}
+
func (n *RouteTargetMembershipNLRI) Len() int { return 12 }
func rfshift(afi uint16, safi uint8) int {
@@ -692,6 +937,7 @@ const (
type PathAttributeInterface interface {
DecodeFromBytes([]byte) error
+ Serialize() ([]byte, error)
Len() int
}
@@ -728,6 +974,26 @@ func (p *PathAttribute) DecodeFromBytes(data []byte) error {
return nil
}
+func (p *PathAttribute) Serialize() ([]byte, error) {
+ p.Length = uint16(len(p.Value))
+ if p.Length > 255 {
+ p.Flags |= BGP_ATTR_FLAG_EXTENDED_LENGTH
+ } else {
+ p.Flags &^= BGP_ATTR_FLAG_EXTENDED_LENGTH
+ }
+ buf := make([]byte, p.Len())
+ buf[0] = p.Flags
+ buf[1] = p.Type
+ if p.Flags&BGP_ATTR_FLAG_EXTENDED_LENGTH != 0 {
+ binary.BigEndian.PutUint16(buf[2:4], p.Length)
+ copy(buf[4:], p.Value)
+ } else {
+ buf[2] = byte(p.Length)
+ copy(buf[3:], p.Value)
+ }
+ return buf, nil
+}
+
type PathAttributeOrigin struct {
PathAttribute
}
@@ -808,6 +1074,21 @@ func (p *PathAttributeAsPath) DecodeFromBytes(data []byte) error {
return nil
}
+func (p *PathAttributeAsPath) Serialize() ([]byte, error) {
+ buf := make([]byte, 0)
+ for _, v := range p.Value {
+ vbuf := make([]byte, 2+len(v.AS)*2)
+ vbuf[0] = v.Type
+ vbuf[1] = v.Num
+ for j, as := range v.AS {
+ binary.BigEndian.PutUint16(vbuf[2+j*2:], uint16(as))
+ }
+ buf = append(buf, vbuf...)
+ }
+ p.PathAttribute.Value = buf
+ return p.PathAttribute.Serialize()
+}
+
type PathAttributeNextHop struct {
PathAttribute
Value net.IP
@@ -819,6 +1100,11 @@ func (p *PathAttributeNextHop) DecodeFromBytes(data []byte) error {
return nil
}
+func (p *PathAttributeNextHop) Serialize() ([]byte, error) {
+ p.PathAttribute.Value = p.Value
+ return p.PathAttribute.Serialize()
+}
+
type PathAttributeMultiExitDisc struct {
PathAttribute
Value uint32
@@ -830,6 +1116,13 @@ func (p *PathAttributeMultiExitDisc) DecodeFromBytes(data []byte) error {
return nil
}
+func (p *PathAttributeMultiExitDisc) Serialize() ([]byte, error) {
+ buf := make([]byte, 4)
+ binary.BigEndian.PutUint32(buf, p.Value)
+ p.PathAttribute.Value = buf
+ return p.PathAttribute.Serialize()
+}
+
type PathAttributeLocalPref struct {
PathAttribute
Value uint32
@@ -841,6 +1134,13 @@ func (p *PathAttributeLocalPref) DecodeFromBytes(data []byte) error {
return nil
}
+func (p *PathAttributeLocalPref) Serialize() ([]byte, error) {
+ buf := make([]byte, 4)
+ binary.BigEndian.PutUint32(buf, p.Value)
+ p.PathAttribute.Value = buf
+ return p.PathAttribute.Serialize()
+}
+
type PathAttributeAtomicAggregate struct {
PathAttribute
}
@@ -867,6 +1167,14 @@ func (p *PathAttributeAggregator) DecodeFromBytes(data []byte) error {
return nil
}
+func (p *PathAttributeAggregator) Serialize() ([]byte, error) {
+ buf := make([]byte, 6)
+ binary.BigEndian.PutUint16(buf, uint16(p.Value.AS))
+ copy(buf[2:], p.Value.Address)
+ p.PathAttribute.Value = buf
+ return p.PathAttribute.Serialize()
+}
+
type PathAttributeCommunities struct {
PathAttribute
Value []uint32
@@ -882,6 +1190,15 @@ func (p *PathAttributeCommunities) DecodeFromBytes(data []byte) error {
return nil
}
+func (p *PathAttributeCommunities) Serialize() ([]byte, error) {
+ buf := make([]byte, len(p.Value)*4)
+ for i, v := range p.Value {
+ binary.BigEndian.PutUint32(buf[i*4:], v)
+ }
+ p.PathAttribute.Value = buf
+ return p.PathAttribute.Serialize()
+}
+
type PathAttributeOriginatorId struct {
PathAttribute
Value net.IP
@@ -893,6 +1210,13 @@ func (p *PathAttributeOriginatorId) DecodeFromBytes(data []byte) error {
return nil
}
+func (p *PathAttributeOriginatorId) Serialize() ([]byte, error) {
+ buf := make([]byte, 4)
+ copy(buf, p.Value)
+ p.PathAttribute.Value = buf
+ return p.PathAttribute.Serialize()
+}
+
type PathAttributeClusterList struct {
PathAttribute
Value []net.IP
@@ -908,6 +1232,15 @@ func (p *PathAttributeClusterList) DecodeFromBytes(data []byte) error {
return nil
}
+func (p *PathAttributeClusterList) Serialize() ([]byte, error) {
+ buf := make([]byte, len(p.Value)*4)
+ for i, v := range p.Value {
+ copy(buf[i*4:], v)
+ }
+ p.PathAttribute.Value = buf
+ return p.PathAttribute.Serialize()
+}
+
type PathAttributeMpReachNLRI struct {
PathAttribute
Nexthop net.IP
@@ -945,6 +1278,35 @@ func (p *PathAttributeMpReachNLRI) DecodeFromBytes(data []byte) error {
return nil
}
+func (p *PathAttributeMpReachNLRI) Serialize() ([]byte, error) {
+ afi := p.Value[0].AFI()
+ safi := p.Value[0].SAFI()
+ nexthoplen := 4
+ if afi == AFI_IP6 {
+ nexthoplen = 16
+ }
+ offset := 0
+ if safi == SAFI_MPLS_VPN {
+ offset = 8
+ nexthoplen += 8
+ }
+ buf := make([]byte, 4+nexthoplen)
+ binary.BigEndian.PutUint16(buf[0:], afi)
+ buf[2] = safi
+ buf[3] = uint8(nexthoplen)
+ copy(buf[4+offset:], p.Nexthop)
+ buf = append(buf, make([]byte, 1)...)
+ for _, prefix := range p.Value {
+ pbuf, err := prefix.Serialize()
+ if err != nil {
+ return nil, err
+ }
+ buf = append(buf, pbuf...)
+ }
+ p.PathAttribute.Value = buf
+ return p.PathAttribute.Serialize()
+}
+
type PathAttributeMpUnreachNLRI struct {
PathAttribute
Value []AddrPrefixInterface
@@ -956,10 +1318,9 @@ func (p *PathAttributeMpUnreachNLRI) DecodeFromBytes(data []byte) error {
value := p.PathAttribute.Value
afi := binary.BigEndian.Uint16(value[0:2])
safi := value[2]
- addrprefix := routeFamilyPrefix(afi, safi)
value = value[3:]
for len(value) > 0 {
- prefix := addrprefix
+ prefix := routeFamilyPrefix(afi, safi)
prefix.DecodeFromBytes(value)
value = value[prefix.Len():]
p.Value = append(p.Value, prefix)
@@ -967,33 +1328,95 @@ func (p *PathAttributeMpUnreachNLRI) DecodeFromBytes(data []byte) error {
return nil
}
+func (p *PathAttributeMpUnreachNLRI) Serialize() ([]byte, error) {
+ buf := make([]byte, 3)
+ afi := p.Value[0].AFI()
+ safi := p.Value[0].SAFI()
+ binary.BigEndian.PutUint16(buf, afi)
+ buf[2] = safi
+ for _, prefix := range p.Value {
+ pbuf, err := prefix.Serialize()
+ if err != nil {
+ return nil, err
+ }
+ buf = append(buf, pbuf...)
+ }
+ p.PathAttribute.Value = buf
+ return p.PathAttribute.Serialize()
+}
+
type ExtendedCommunityInterface interface {
+ Serialize() ([]byte, error)
}
type TwoOctetAsSpecificExtended struct {
+ SubType uint8
AS uint16
LocalAdmin uint32
}
+func (e *TwoOctetAsSpecificExtended) Serialize() ([]byte, error) {
+ buf := make([]byte, 8)
+ buf[0] = 0x00
+ buf[1] = e.SubType
+ binary.BigEndian.PutUint16(buf[2:], e.AS)
+ binary.BigEndian.PutUint32(buf[4:], e.LocalAdmin)
+ return buf, nil
+}
+
type IPv4AddressSpecificExtended struct {
SubType uint8
IPv4 net.IP
LocalAdmin uint16
}
+func (e *IPv4AddressSpecificExtended) Serialize() ([]byte, error) {
+ buf := make([]byte, 8)
+ buf[0] = 0x01
+ buf[1] = e.SubType
+ copy(buf[2:6], e.IPv4)
+ binary.BigEndian.PutUint16(buf[6:], e.LocalAdmin)
+ return buf, nil
+}
+
type FourOctetAsSpecificExtended struct {
- AS net.IP
+ SubType uint8
+ AS uint32
LocalAdmin uint16
}
+func (e *FourOctetAsSpecificExtended) Serialize() ([]byte, error) {
+ buf := make([]byte, 8)
+ buf[0] = 0x02
+ buf[1] = e.SubType
+ binary.BigEndian.PutUint32(buf[2:], e.AS)
+ binary.BigEndian.PutUint16(buf[6:], e.LocalAdmin)
+ return buf, nil
+}
+
type OpaqueExtended struct {
Value []byte
}
+func (e *OpaqueExtended) Serialize() ([]byte, error) {
+ buf := make([]byte, 8)
+ buf[0] = 0x03
+ copy(buf[1:], e.Value)
+ return buf, nil
+}
+
type UnknownExtended struct {
+ Type uint8
Value []byte
}
+func (e *UnknownExtended) Serialize() ([]byte, error) {
+ buf := make([]byte, 8)
+ buf[0] = e.Type
+ copy(buf[1:], e.Value)
+ return buf, nil
+}
+
type PathAttributeExtendedCommunities struct {
PathAttribute
Value []ExtendedCommunityInterface
@@ -1004,6 +1427,7 @@ func parseExtended(data []byte) ExtendedCommunityInterface {
switch typehigh {
case 0:
e := &TwoOctetAsSpecificExtended{}
+ e.SubType = data[1]
e.AS = binary.BigEndian.Uint16(data[2:4])
e.LocalAdmin = binary.BigEndian.Uint32(data[4:8])
return e
@@ -1015,7 +1439,8 @@ func parseExtended(data []byte) ExtendedCommunityInterface {
return e
case 2:
e := &FourOctetAsSpecificExtended{}
- e.AS = data[2:6]
+ e.SubType = data[1]
+ e.AS = binary.BigEndian.Uint32(data[2:6])
e.LocalAdmin = binary.BigEndian.Uint16(data[6:8])
return e
case 3:
@@ -1024,6 +1449,7 @@ func parseExtended(data []byte) ExtendedCommunityInterface {
return e
}
e := &UnknownExtended{}
+ e.Type = data[1]
e.Value = data[2:8]
return e
}
@@ -1065,6 +1491,14 @@ func (p *PathAttributeAs4Aggregator) DecodeFromBytes(data []byte) error {
return nil
}
+func (p *PathAttributeAs4Aggregator) Serialize() ([]byte, error) {
+ buf := make([]byte, 8)
+ binary.BigEndian.PutUint32(buf[0:], p.Value.AS)
+ copy(buf[4:], p.Value.Address)
+ p.PathAttribute.Value = buf
+ return p.PathAttribute.Serialize()
+}
+
type PathAttributeUnknown struct {
PathAttribute
}
@@ -1148,6 +1582,38 @@ func (msg *BGPUpdate) DecodeFromBytes(data []byte) error {
return nil
}
+func (msg *BGPUpdate) Serialize() ([]byte, error) {
+ wbuf := make([]byte, 2)
+ for _, w := range msg.WithdrawnRoutes {
+ onewbuf, err := w.Serialize()
+ if err != nil {
+ return nil, err
+ }
+ wbuf = append(wbuf, onewbuf...)
+ }
+ binary.BigEndian.PutUint16(wbuf, uint16(len(wbuf)-2))
+
+ pbuf := make([]byte, 2)
+ for _, p := range msg.PathAttributes {
+ onepbuf, err := p.Serialize()
+ if err != nil {
+ return nil, err
+ }
+ pbuf = append(pbuf, onepbuf...)
+ }
+ binary.BigEndian.PutUint16(pbuf, uint16(len(pbuf)-2))
+
+ buf := append(wbuf, pbuf...)
+ for _, n := range msg.NLRI {
+ nbuf, err := n.Serialize()
+ if err != nil {
+ return nil, err
+ }
+ buf = append(buf, nbuf...)
+ }
+ return buf, nil
+}
+
type BGPNotification struct {
ErrorCode uint8
ErrorSubcode uint8
@@ -1166,6 +1632,14 @@ func (msg *BGPNotification) DecodeFromBytes(data []byte) error {
return nil
}
+func (msg *BGPNotification) Serialize() ([]byte, error) {
+ buf := make([]byte, 2)
+ buf[0] = msg.ErrorCode
+ buf[1] = msg.ErrorSubcode
+ buf = append(buf, msg.Data...)
+ return buf, nil
+}
+
type BGPKeepAlive struct {
}
@@ -1173,6 +1647,10 @@ func (msg *BGPKeepAlive) DecodeFromBytes(data []byte) error {
return nil
}
+func (msg *BGPKeepAlive) Serialize() ([]byte, error) {
+ return nil, nil
+}
+
type BGPRouteRefresh struct {
AFI uint16
Demarcation uint8
@@ -1189,8 +1667,17 @@ func (msg *BGPRouteRefresh) DecodeFromBytes(data []byte) error {
return nil
}
+func (msg *BGPRouteRefresh) Serialize() ([]byte, error) {
+ buf := make([]byte, 4)
+ binary.BigEndian.PutUint16(buf[0:2], msg.AFI)
+ buf[2] = msg.Demarcation
+ buf[3] = msg.SAFI
+ return buf, nil
+}
+
type BGPBody interface {
DecodeFromBytes([]byte) error
+ Serialize() ([]byte, error)
}
type BGPHeader struct {
@@ -1212,6 +1699,16 @@ func (msg *BGPHeader) DecodeFromBytes(data []byte) error {
return nil
}
+func (msg *BGPHeader) Serialize() ([]byte, error) {
+ buf := make([]byte, 19)
+ for i, _ := range buf[:16] {
+ buf[i] = 0xff
+ }
+ binary.BigEndian.PutUint16(buf[16:18], msg.Len)
+ buf[18] = msg.Type
+ return buf, nil
+}
+
type BGPMessage struct {
Header BGPHeader
Body BGPBody
@@ -1243,6 +1740,21 @@ func ParseBGPMessage(data []byte) (*BGPMessage, error) {
return msg, nil
}
+func (msg *BGPMessage) Serialize() ([]byte, error) {
+ b, err := msg.Body.Serialize()
+ if err != nil {
+ return nil, err
+ }
+ if msg.Header.Len == 0 {
+ msg.Header.Len = 19 + uint16(len(b))
+ }
+ h, err := msg.Header.Serialize()
+ if err != nil {
+ return nil, err
+ }
+ return append(h, b...), nil
+}
+
// BMP
type BMPHeader struct {