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 }