go-bgp

a collection of golang BGP tools to monitor, archive and serve
git clone git://git.2f30.org/go-bgp
Log | Files | Refs | README

bgp.go (2465B)


      1 package bgp
      2 
      3 import (
      4 	"bytes"
      5 	"encoding/binary"
      6 	"fmt"
      7 	"io/ioutil"
      8 )
      9 
     10 type uint128 struct {
     11 	H uint64
     12 	L uint64
     13 }
     14 
     15 // magic numbers explained
     16 const (
     17 	MinMsgLen       = 19
     18 	MinNotifiMsgLen = 21
     19 )
     20 
     21 // bgp msg types
     22 const (
     23 	_ = iota
     24 	OPEN
     25 	UPDATE
     26 	NOTIFICATION
     27 	KEEPALIVE
     28 )
     29 
     30 type BgpHdr struct {
     31 	Marker uint128
     32 	Len    uint16
     33 	Type   uint8
     34 }
     35 
     36 type BgpMsg struct {
     37 	h BgpHdr
     38 }
     39 
     40 type BgpOpenMsg struct {
     41 	Hdr    BgpHdr
     42 	Ver    uint8
     43 	MyAs   uint16
     44 	Htime  uint16
     45 	BgpId  uint32
     46 	OptLen uint8
     47 	Opt    []byte
     48 }
     49 
     50 type BgpUpdateMsg struct {
     51 	Hdr               BgpHdr
     52 	UnfRoutesLen      uint16
     53 	WithdRoutes       []byte
     54 	TotalPathAttrLen  uint16
     55 	NetLayerReachInfo []byte
     56 }
     57 type BgpNotifiMsg struct {
     58 	Hdr        BgpHdr
     59 	ErrCode    uint8
     60 	ErrSubCode uint8
     61 	Data       []byte
     62 }
     63 
     64 type BgpKeepaliveMsg struct {
     65 	Hdr BgpHdr
     66 }
     67 
     68 func parse(b []byte) (interface{}, error) {
     69 	var h BgpHdr
     70 
     71 	// parse header
     72 	buf := bytes.NewReader(b)
     73 	err := binary.Read(buf, binary.BigEndian, &h.Marker)
     74 
     75 	err = binary.Read(buf, binary.BigEndian, &h.Len)
     76 	err = binary.Read(buf, binary.BigEndian, &h.Type)
     77 
     78 	switch h.Type {
     79 	case OPEN:
     80 		var m BgpOpenMsg
     81 		m.Hdr = h
     82 
     83 		err = binary.Read(buf, binary.BigEndian, &m.Ver)
     84 		err = binary.Read(buf, binary.BigEndian, &m.MyAs)
     85 		err = binary.Read(buf, binary.BigEndian, &m.Htime)
     86 		err = binary.Read(buf, binary.BigEndian, &m.BgpId)
     87 		err = binary.Read(buf, binary.BigEndian, &m.OptLen)
     88 
     89 		if m.OptLen > 0 {
     90 			m.Opt = make([]byte, m.OptLen)
     91 			err = binary.Read(buf, binary.BigEndian, &m.Opt)
     92 		}
     93 		return m, nil
     94 
     95 	case UPDATE:
     96 		var m BgpUpdateMsg
     97 		m.Hdr = h
     98 
     99 		if h.Len == MinMsgLen {
    100 			return m, nil
    101 		}
    102 
    103 		err = binary.Read(buf, binary.BigEndian, &m.UnfRoutesLen)
    104 		if m.UnfRoutesLen > 0 {
    105 			m.WithdRoutes = make([]byte, m.UnfRoutesLen)
    106 			err = binary.Read(buf, binary.BigEndian, &m.WithdRoutes)
    107 		}
    108 
    109 		err = binary.Read(buf, binary.BigEndian, &m.TotalPathAttrLen)
    110 		if m.TotalPathAttrLen > 0 {
    111 			m.NetLayerReachInfo = make([]byte, m.TotalPathAttrLen)
    112 			err = binary.Read(buf, binary.BigEndian, &m.NetLayerReachInfo)
    113 		}
    114 		return m, nil
    115 
    116 	case NOTIFICATION:
    117 		var m BgpNotifiMsg
    118 		m.Hdr = h
    119 
    120 		err = binary.Read(buf, binary.BigEndian, &m.ErrCode)
    121 		err = binary.Read(buf, binary.BigEndian, &m.ErrSubCode)
    122 
    123 		if h.Len > MinNotifiMsgLen {
    124 			m.Data = make([]byte, h.Len-MinNotifiMsgLen)
    125 			err = binary.Read(buf, binary.BigEndian, &m.ErrSubCode)
    126 		}
    127 
    128 		return m, nil
    129 
    130 	case KEEPALIVE:
    131 		return BgpKeepaliveMsg{h}, nil
    132 	}
    133 	return nil, err
    134 }