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
use prelude::*;
pub struct Icmpv6Parser;
impl Parsable<PathIp> for Icmpv6Parser {
fn parse<'a>(&mut self,
input: &'a [u8],
result: Option<&ParserResultVec>,
_: Option<&mut PathIp>)
-> IResult<&'a [u8], ParserResult> {
do_parse!(input,
expr_opt!(match result {
Some(vector) => match vector.last() {
Some(ref any) => if let Some(ipv6) = any.downcast_ref::<Ipv6Packet>() {
if ipv6.next_header == IpProtocol::Icmpv6 {
Some(())
} else {
None
}
} else {
None
},
_ => None,
},
None => Some(()),
}) >>
message_type: map_opt!(be_u8, Icmpv6Type::from_u8) >>
code: be_u8 >>
checksum: be_u16 >>
data: cond!((message_type == Icmpv6Type::EchoReply ||
message_type == Icmpv6Type::EchoRequest) &&
code == 0,
map!(IcmpEcho::parse, |x| Icmpv6Data::Echo(x))) >>
(Box::new(Icmpv6Packet {
message_type: message_type,
code: code,
checksum: checksum,
data: data,
}))
)
}
}
impl fmt::Display for Icmpv6Parser {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ICMPv6")
}
}
#[derive(Debug, Eq, PartialEq)]
pub struct Icmpv6Packet {
pub message_type: Icmpv6Type,
pub code: u8,
pub checksum: u16,
pub data: Option<Icmpv6Data>,
}
#[derive(Debug, Eq, PartialEq)]
pub enum Icmpv6Type {
EchoReply,
EchoRequest,
}
impl Icmpv6Type {
pub fn from_u8(input: u8) -> Option<Icmpv6Type> {
match input {
128 => Some(Icmpv6Type::EchoRequest),
129 => Some(Icmpv6Type::EchoReply),
_ => None,
}
}
}
#[derive(Debug, Eq, PartialEq)]
pub enum Icmpv6Data {
Echo(IcmpEcho),
}