mrt.go (11322B)
1 package mrt 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "errors" 7 "fmt" 8 "io" 9 "log" 10 "net" 11 "os" 12 "unicode/utf8" 13 //"runtime" 14 ) 15 16 var logger = log.New(os.Stderr, "go-mrt: ", log.Ldate|log.Llongfile) 17 18 type MrtHdr struct { 19 Mrt_timestamp uint32 20 Mrt_type uint16 21 Mrt_subtype uint16 22 Mrt_len uint32 23 } 24 25 type parsefunc func([]byte) MrtSubTyper 26 27 type MrtMsg struct { 28 Hdr MrtHdr 29 Msg []byte 30 } 31 32 type MrtSubTyper interface { 33 Type() string //almost dummy functionality 34 String() string 35 } 36 37 type Mrter interface { 38 Hdr() MrtHdr 39 Type() uint16 40 SubType() uint16 41 Len() uint32 42 Msg() []byte 43 } 44 45 type MrtOSPFHdr struct { 46 otype uint16 47 RemoteIP uint32 48 LocalIP uint32 49 } 50 51 func (m *MrtOSPFHdr) Type() string { 52 return "OSPFHdr" 53 } 54 55 func (m *MrtOSPFHdr) String() string { 56 remip := make(net.IP, 4) 57 locip := make(net.IP, 4) 58 remip[0] = byte(m.RemoteIP) 59 remip[1] = byte(m.RemoteIP >> 8) 60 remip[2] = byte(m.RemoteIP >> 16) 61 remip[3] = byte(m.RemoteIP >> 24) 62 locip[0] = byte(m.LocalIP) 63 locip[1] = byte(m.LocalIP >> 8) 64 locip[2] = byte(m.LocalIP >> 16) 65 locip[3] = byte(m.LocalIP >> 24) 66 return fmt.Sprintf("OSPF Header. Type [%d] Remote IP [%s] Local IP [%s]", m.otype, remip, locip) 67 } 68 69 type MrtInfoMsg struct { 70 inftype uint16 71 optmsg string 72 } 73 74 func (m *MrtInfoMsg) String() string { 75 return fmt.Sprintf("Informational Message. Type [%v] Optstring [%s]", m.inftype, m.optmsg) 76 } 77 78 func (m *MrtInfoMsg) Type() string { 79 return m.String() 80 } 81 82 func (m *MrtMsg) PFunc() (ret parsefunc, ok bool) { 83 var subtype = m.Hdr.Mrt_subtype 84 var mtype = m.Hdr.Mrt_type 85 infofunc := func(a []byte) MrtSubTyper { 86 runes := []rune{} 87 infomsg := &MrtInfoMsg{inftype: mtype, optmsg: "No Optional Message"} 88 for len(a) > 0 { 89 r, sz := utf8.DecodeRune(a) 90 if r == utf8.RuneError { 91 logger.Println("failed to decode rune in optional message") 92 return infomsg 93 } 94 a = a[sz:] 95 runes = append(runes, r) 96 } 97 if len(runes) > 0 { 98 infomsg.optmsg = string(runes) 99 } 100 return infomsg 101 } 102 103 ospffunc := func(a []byte) MrtSubTyper { 104 ret := &MrtOSPFHdr{otype: subtype} 105 buf := bytes.NewReader(a) 106 err := binary.Read(buf, binary.BigEndian, &ret.RemoteIP) 107 err = binary.Read(buf, binary.BigEndian, &ret.LocalIP) 108 if err != nil { 109 panic(fmt.Sprintf("error while reading binary OSPF header: %s", err)) 110 } 111 return ret 112 } 113 114 bgp4mpscfunc := func(a []byte) MrtSubTyper { 115 ret := &MrtBGP4MPStateChangeHdr{} 116 buf := bytes.NewReader(a) 117 if subtype == BGP4MP_STATE_CHANGE { 118 ret.PeerASN = make([]byte, 2) 119 ret.LocalASN = make([]byte, 2) 120 } else { 121 ret.PeerASN = make([]byte, 4) 122 ret.LocalASN = make([]byte, 4) 123 } 124 err := binary.Read(buf, binary.BigEndian, &ret.PeerASN) 125 if err != nil { 126 panic(fmt.Sprintf("error while reading binary BGP4MP header: %s", err)) 127 } 128 binary.Read(buf, binary.BigEndian, &ret.LocalASN) 129 binary.Read(buf, binary.BigEndian, &ret.InterfaceInd) 130 binary.Read(buf, binary.BigEndian, &ret.AddrFamily) 131 if ret.AddrFamily == 1 { 132 ret.PeerIP = make([]byte, 4) 133 ret.LocalIP = make([]byte, 4) 134 } else if ret.AddrFamily == 2 { 135 ret.PeerIP = make([]byte, 16) 136 ret.LocalIP = make([]byte, 16) 137 } 138 binary.Read(buf, binary.BigEndian, &ret.PeerIP) 139 binary.Read(buf, binary.BigEndian, &ret.LocalIP) 140 binary.Read(buf, binary.BigEndian, &ret.OldState) 141 binary.Read(buf, binary.BigEndian, &ret.NewState) 142 return ret 143 } 144 145 bgp4mpmsgfunc := func(a []byte) MrtSubTyper { 146 ret := &MrtBGP4MPMsgHdr{} 147 buf := bytes.NewReader(a) 148 if subtype == BGP4MP_MESSAGE { 149 ret.PeerASN = make([]byte, 2) 150 ret.LocalASN = make([]byte, 2) 151 } else if subtype == BGP4MP_MESSAGE_AS4 { 152 ret.PeerASN = make([]byte, 4) 153 ret.LocalASN = make([]byte, 4) 154 } 155 err := binary.Read(buf, binary.BigEndian, &ret.PeerASN) 156 if err != nil { 157 panic(fmt.Sprintf("error while reading binary BGP4MP header: %s", err)) 158 } 159 binary.Read(buf, binary.BigEndian, &ret.LocalASN) 160 binary.Read(buf, binary.BigEndian, &ret.InterfaceInd) 161 //fmt.Printf("ADdr family should be:%v\n", binary.BigEndian.Uint16(a[6:8])) 162 binary.Read(buf, binary.BigEndian, &ret.AddrFamily) 163 if ret.AddrFamily == 1 { 164 ret.PeerIP = make([]byte, 4) 165 ret.LocalIP = make([]byte, 4) 166 } else if ret.AddrFamily == 2 { 167 ret.PeerIP = make([]byte, 16) 168 ret.LocalIP = make([]byte, 16) 169 } else { 170 panic("Address Family in BGP4MP msg func is wrong") 171 } 172 binary.Read(buf, binary.BigEndian, &ret.PeerIP) 173 binary.Read(buf, binary.BigEndian, &ret.LocalIP) 174 return ret 175 } 176 177 ret = nil 178 ok = false 179 switch mtype { 180 case MSG_PROTOCOL_BGP4MP: 181 if subtype == BGP4MP_STATE_CHANGE || subtype == BGP4MP_STATE_CHANGE_AS4 { 182 ret, ok = bgp4mpscfunc, true 183 } else if subtype == BGP4MP_MESSAGE || subtype == BGP4MP_MESSAGE_AS4 || 184 subtype == BGP4MP_MESSAGE_LOCAL || subtype == BGP4MP_MESSAGE_AS4_LOCAL { 185 ret, ok = bgp4mpmsgfunc, true 186 } 187 case MSG_START, MSG_I_AM_DEAD: 188 if subtype == 0 { 189 ret, ok = infofunc, true 190 } else { 191 logger.Println("Mrt type is Informational but Subtype non-zero") 192 } 193 case MSG_PROTOCOL_OSPF: 194 if subtype == 0 || subtype == 1 { 195 ret, ok = ospffunc, true 196 } else { 197 logger.Println("Mrt type is OSPF but Subtype is neither 0 or 1") 198 } 199 case MSG_NULL, MSG_DIE, MSG_PEER_DOWN, MSG_PROTOCOL_BGP, MSG_PROTOCOL_IDRP, MSG_PROTOCOL_BGP4PLUS, MSG_PROTOCOL_BGP4PLUS1: 200 logger.Println("Deprecated message type") 201 default: 202 logger.Printf("unknown. header [%v]\n", m.Hdr) 203 } 204 return 205 } 206 207 type MrtBGP4MPStateChangeHdr struct { 208 PeerASN []byte 209 LocalASN []byte 210 InterfaceInd uint16 211 AddrFamily uint16 212 PeerIP []byte 213 LocalIP []byte 214 OldState uint16 215 NewState uint16 216 } 217 218 func (m *MrtBGP4MPStateChangeHdr) Type() string { 219 return "BGP4MPStateChange" 220 } 221 222 func (m *MrtBGP4MPStateChangeHdr) String() string { 223 return "BGP4MPStateChange" 224 } 225 226 type MrtBGP4MPMsgHdr struct { 227 PeerASN []byte 228 LocalASN []byte 229 InterfaceInd uint16 230 AddrFamily uint16 231 PeerIP []byte 232 LocalIP []byte 233 } 234 235 func (m *MrtBGP4MPMsgHdr) Type() string { 236 return "BGP4MPMsg" 237 } 238 239 func (m *MrtBGP4MPMsgHdr) String() string { 240 if len(m.PeerIP) < 4 || len(m.LocalIP) < 4 { 241 return "BGP4MPMsg unable to read IPs" 242 } 243 return fmt.Sprintf("LocalIP:%s RemoteIP:%s", net.IPv4(m.PeerIP[0], m.PeerIP[1], m.PeerIP[2], m.PeerIP[3]), net.IPv4(m.LocalIP[0], m.LocalIP[1], m.LocalIP[2], m.LocalIP[3])) 244 } 245 246 type MrtTableDumpV1Hdr struct { 247 ViewNum uint16 248 SeqNum uint16 249 Prefix []byte 250 PrefixLen uint8 251 Status uint8 252 OrigTime uint32 253 PeerIP []byte 254 PeerAS uint16 255 AttrLen uint16 256 } 257 258 func (m *MrtTableDumpV1Hdr) Type() string { 259 return "TableDumpV1Hdr" 260 } 261 262 func (m *MrtTableDumpV1Hdr) String() string { 263 return "TableDumpV1Hdr" 264 } 265 266 type MrtTableDumpV2PIHdr struct { 267 CollectorID uint32 268 ViewNameLen []byte 269 PeerCount uint16 270 Peers []MrtTableDumpV2PeerEntry 271 } 272 273 type MrtTableDumpV2PeerEntry struct { 274 PeerType uint8 275 PeerBGPID uint32 276 PeerIP []byte 277 PeerAS []byte 278 } 279 280 type MrtTableDumpV2RIBDef struct { 281 SequenceNum uint32 282 PrefixLen uint8 283 Prefix uint32 284 EntryCount uint16 285 Entries []MrtTableDumpV2RIBEntry 286 } 287 288 type MrtTableDumpV2RIBGen struct { 289 SequenceNum uint32 290 AFI uint16 291 SAFI uint8 292 NLRI []byte 293 EntryCount uint16 294 Entries []MrtTableDumpV2RIBEntry 295 } 296 297 type MrtTableDumpV2RIBEntry struct { 298 PeerIndex uint16 299 OrigTime uint32 300 AttrLen uint16 301 BGPAttrs []byte 302 } 303 304 type MrtFile struct { 305 file io.Reader 306 entries uint32 307 off int64 308 } 309 310 const ( 311 MrtHdr_size = 12 312 dump_size = 10000 313 ) 314 315 // mrt-type consts 316 const ( 317 MSG_NULL = iota // 0 empty msg (deprecated) 318 MSG_START // 1 sender is starting up 319 MSG_DIE // 2 receiver should shut down (deprecated) 320 MSG_I_AM_DEAD // 3 sender is shutting down 321 MSG_PEER_DOWN // 4 sender's peer is down (deprecated) 322 MSG_PROTOCOL_BGP // 5 msg is a BGP packet (deprecated) 323 MSG_PROTOCOL_RIP // 6 msg is a RIP packet 324 MSG_PROTOCOL_IDRP // 7 msg is an IDRP packet (deprecated) 325 MSG_PROTOCOL_RIPNG // 8 msg is a RIPNG packet 326 MSG_PROTOCOL_BGP4PLUS // 9 msg is a BGP4+ packet (deprecated) 327 MSG_PROTOCOL_BGP4PLUS1 // 10 msg is a BGP4+ (draft 01) (deprecated) 328 MSG_PROTOCOL_OSPF // 11 msg is an OSPF packet 329 MSG_TABLE_DUMP // 12 routing table dump 330 MSG_TABLE_DUMP_V2 // 13 routing table dump 331 MSG_PROTOCOL_BGP4MP = 16 // 16 zebras own packet format 332 MSG_PROTOCOL_BGP4MP_ET = 17 333 MSG_PROTOCOL_ISIS = 32 // 32 msg is a ISIS package 334 MSG_PROTOCOL_ISIS_ET = 33 335 MSG_PROTOCOL_OSPFV3 = 48 // 48 msg is a OSPFv3 package 336 MSG_PROTOCOL_OSPFV3_ET = 49 337 ) 338 339 // mrt-subtype consts 340 const ( 341 BGP4MP_STATE_CHANGE = 0 // state change 342 BGP4MP_MESSAGE = 1 // bgp message 343 BGP4MP_MESSAGE_AS4 = 4 // same as BGP4MP_MESSAGE with 4byte AS 344 BGP4MP_STATE_CHANGE_AS4 = 5 345 BGP4MP_MESSAGE_LOCAL = 6 // same as BGP4MP_MESSAGE but for self 346 BGP4MP_MESSAGE_AS4_LOCAL = 7 // originated updates. Not implemented 347 ) 348 349 const ( 350 OSPF_STATE_CHANGE = iota 351 OSPF_LSA_UPDATE 352 ) 353 354 const ( 355 PEER_INDEX_TABLE = iota + 1 356 RIB_IPV4_UNICAST 357 RIB_IPV4_MULTICAST 358 RIB_IPV6_UNICAST 359 RIB_IPV6_MULTICAST 360 RIB_GENERIC 361 ) 362 363 func NewMrtHdr(b []byte) (ret MrtHdr, err error) { 364 buf := bytes.NewReader(b) 365 err = binary.Read(buf, binary.BigEndian, &ret) 366 return 367 } 368 369 func NewMrtFile(f io.Reader) (ret MrtFile) { 370 ret = MrtFile{f, 0, 0} 371 return 372 } 373 374 //This function can be passed into a bufio.Scanner.Split() to read buffered 375 //mrt msgs 376 func SplitMrt(data []byte, atEOF bool) (advance int, token []byte, err error) { 377 if atEOF && len(data) == 0 { 378 return 0, nil, nil 379 } 380 if cap(data) < MrtHdr_size { // read more 381 return 0, nil, nil 382 } 383 //this reads the data and (they are big endian so it handles that) 384 hdr, errh := NewMrtHdr(data[:MrtHdr_size]) 385 if errh != nil { 386 return 0, nil, errh 387 } 388 totlen := int(hdr.Mrt_len + MrtHdr_size) 389 if len(data) < totlen { //need to read more 390 return 0, nil, nil 391 } 392 //logger.Printf("scanned mrt with len:%d datalen is :%d", totlen, len(data)) 393 return totlen, data[0:totlen], nil 394 } 395 396 func (f *MrtFile) Read(b []byte) (n int, err error) { 397 //fmt.Printf(" b len:%v cap:%v\n",len(b), cap(b)) 398 if cap(b) < MrtHdr_size { 399 err = errors.New("buffer size less than header size") 400 return 401 } 402 n, err = f.file.Read(b[:MrtHdr_size]) 403 if err != nil { 404 return 405 } 406 hdr, errh := NewMrtHdr(b[:MrtHdr_size]) 407 if errh != nil { 408 err = errors.New(fmt.Sprintf("error in reading header from offset %v : %s", f.off, errh)) 409 return 410 } 411 //fmt.Printf("got header at offset:%d ! :%v\n", f.off, hdr) 412 //n = int(hdr.Mrt_len+MrtHdr_size) 413 //f.off = f.off + int64(n) 414 f.entries = f.entries + 1 415 //this will just jump over the msg 416 //noff,errs := f.file.Seek(int64(hdr.Mrt_len), os.SEEK_CUR) 417 if dump_size-(hdr.Mrt_len+MrtHdr_size) <= 0 { 418 err = errors.New(fmt.Sprintf("bgp message of size:%v at offset is too large", hdr.Mrt_len, f.off+MrtHdr_size)) 419 return 420 } 421 //fmt.Printf("i will access b[%v:%v] len:%v cap:%v\n",MrtHdr_size, hdr.Mrt_len+MrtHdr_size, len(b), cap(b)) 422 nr, err := f.file.Read(b[MrtHdr_size : hdr.Mrt_len+MrtHdr_size]) 423 if nr != int(hdr.Mrt_len) { 424 n = n + nr //header + len of read 425 err = errors.New(fmt.Sprintf("error in reading bgp message of size :%v . got :%v bytes.", hdr.Mrt_len, n)) 426 return 427 } 428 n = n + nr 429 f.off += int64(n) 430 //fmt.Printf("seeked at offset:%d \n", f.off) 431 return 432 }