1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use byteorder::{BigEndian, ReadBytesExt};
use std::io::{Error, ErrorKind, Read};
use std::net::Ipv6Addr;
use crate::Header;
#[derive(Debug)]
#[allow(missing_docs)]
#[allow(non_camel_case_types)]
pub enum BGP4PLUS {
NULL,
UPDATE(MESSAGE),
PREF_UPDATE,
STATE_CHANGE(STATE_CHANGE),
SYNC(SYNC),
OPEN(MESSAGE),
NOTIFY(MESSAGE),
KEEPALIVE(MESSAGE),
}
impl BGP4PLUS {
pub(crate) fn parse(header: &Header, stream: &mut Read) -> Result<BGP4PLUS, Error> {
match header.sub_type {
0 => Ok(BGP4PLUS::NULL),
1 => Ok(BGP4PLUS::UPDATE(MESSAGE::parse(header, stream)?)),
2 => Ok(BGP4PLUS::PREF_UPDATE),
3 => Ok(BGP4PLUS::STATE_CHANGE(STATE_CHANGE::parse(stream)?)),
4 => Ok(BGP4PLUS::SYNC(SYNC::parse(stream)?)),
5 => Ok(BGP4PLUS::OPEN(MESSAGE::parse(header, stream)?)),
6 => Ok(BGP4PLUS::NOTIFY(MESSAGE::parse(header, stream)?)),
7 => Ok(BGP4PLUS::KEEPALIVE(MESSAGE::parse(header, stream)?)),
_ => Err(Error::new(
ErrorKind::Other,
"Unknown MRT record subtype found in MRTHeader",
)),
}
}
}
#[derive(Debug)]
#[allow(non_camel_case_types)]
pub struct MESSAGE {
pub peer_as: u16,
pub peer_ip: Ipv6Addr,
pub local_as: u16,
pub local_ip: Ipv6Addr,
pub message: Vec<u8>,
}
impl MESSAGE {
fn parse(header: &Header, stream: &mut Read) -> Result<MESSAGE, Error> {
let peer_as = stream.read_u16::<BigEndian>()?;
let peer_ip = Ipv6Addr::from(stream.read_u128::<BigEndian>()?);
let local_as = stream.read_u16::<BigEndian>()?;
let local_ip = Ipv6Addr::from(stream.read_u128::<BigEndian>()?);
let length = header.length - 12;
let mut message = vec![0; length as usize];
stream.read_exact(&mut message)?;
Ok(MESSAGE {
peer_as,
peer_ip,
local_as,
local_ip,
message,
})
}
}
#[derive(Debug)]
#[allow(non_camel_case_types)]
pub struct STATE_CHANGE {
pub peer_as: u16,
pub peer_ip: Ipv6Addr,
pub old_state: u16,
pub new_state: u16,
}
impl STATE_CHANGE {
fn parse(stream: &mut Read) -> Result<STATE_CHANGE, Error> {
Ok(STATE_CHANGE {
peer_as: stream.read_u16::<BigEndian>()?,
peer_ip: Ipv6Addr::from(stream.read_u128::<BigEndian>()?),
old_state: stream.read_u16::<BigEndian>()?,
new_state: stream.read_u16::<BigEndian>()?,
})
}
}
#[derive(Debug)]
#[allow(non_camel_case_types)]
pub struct SYNC {
pub view_number: u16,
pub filename: Vec<u8>,
}
impl SYNC {
fn parse(stream: &mut Read) -> Result<SYNC, Error> {
let view_number = stream.read_u16::<BigEndian>()?;
let mut filename = Vec::new();
let mut buffer = stream.read_u8()?;
while buffer != b'\0' {
filename.push(buffer);
buffer = stream.read_u8()?;
}
Ok(SYNC {
view_number,
filename,
})
}
}