capsules_extra/net/icmpv6/
icmpv6.rs1use crate::net::stream::SResult;
12use crate::net::stream::{decode_u16, decode_u32, decode_u8};
13use crate::net::stream::{encode_u16, encode_u32, encode_u8};
14
15#[derive(Copy, Clone)]
17pub struct ICMP6Header {
18 pub code: u8,
19 pub cksum: u16,
20 pub options: ICMP6HeaderOptions,
21 pub len: u16, }
23
24#[derive(Copy, Clone)]
25pub enum ICMP6HeaderOptions {
26 Type1 { unused: u32 },
27 Type3 { unused: u32 },
28 Type128 { id: u16, seqno: u16 },
29 Type129 { id: u16, seqno: u16 },
30}
31
32#[derive(Copy, Clone)]
33pub enum ICMP6Type {
34 Type1, Type3, Type128, Type129, }
39
40impl ICMP6Header {
41 pub fn new(icmp_type: ICMP6Type) -> ICMP6Header {
42 let options = match icmp_type {
43 ICMP6Type::Type1 => ICMP6HeaderOptions::Type1 { unused: 0 },
44 ICMP6Type::Type3 => ICMP6HeaderOptions::Type3 { unused: 0 },
45 ICMP6Type::Type128 => ICMP6HeaderOptions::Type128 { id: 0, seqno: 0 },
46 ICMP6Type::Type129 => ICMP6HeaderOptions::Type129 { id: 0, seqno: 0 },
47 };
48
49 ICMP6Header {
50 code: 0,
51 cksum: 0,
52 options,
53 len: 0,
54 }
55 }
56
57 pub fn set_type(&mut self, icmp_type: ICMP6Type) {
58 match icmp_type {
59 ICMP6Type::Type1 => self.set_options(ICMP6HeaderOptions::Type1 { unused: 0 }),
60 ICMP6Type::Type3 => self.set_options(ICMP6HeaderOptions::Type3 { unused: 0 }),
61 ICMP6Type::Type128 => self.set_options(ICMP6HeaderOptions::Type128 { id: 0, seqno: 0 }),
62 ICMP6Type::Type129 => self.set_options(ICMP6HeaderOptions::Type129 { id: 0, seqno: 0 }),
63 }
64 }
65
66 pub fn set_code(&mut self, code: u8) {
67 self.code = code;
68 }
69
70 pub fn set_cksum(&mut self, cksum: u16) {
71 self.cksum = cksum;
72 }
73
74 pub fn set_options(&mut self, options: ICMP6HeaderOptions) {
75 self.options = options;
76 }
77
78 pub fn set_len(&mut self, len: u16) {
79 self.len = len;
80 }
81
82 pub fn get_type(&self) -> ICMP6Type {
83 match self.options {
84 ICMP6HeaderOptions::Type1 { .. } => ICMP6Type::Type1,
85 ICMP6HeaderOptions::Type3 { .. } => ICMP6Type::Type3,
86 ICMP6HeaderOptions::Type128 { .. } => ICMP6Type::Type128,
87 ICMP6HeaderOptions::Type129 { .. } => ICMP6Type::Type129,
88 }
89 }
90
91 pub fn get_type_as_int(&self) -> u8 {
92 match self.get_type() {
93 ICMP6Type::Type1 => 1,
94 ICMP6Type::Type3 => 3,
95 ICMP6Type::Type128 => 128,
96 ICMP6Type::Type129 => 129,
97 }
98 }
99
100 pub fn get_code(&self) -> u8 {
101 self.code
102 }
103
104 pub fn get_cksum(&self) -> u16 {
105 self.cksum
106 }
107
108 pub fn get_options(&self) -> ICMP6HeaderOptions {
109 self.options
110 }
111
112 pub fn get_len(&self) -> u16 {
113 self.len
114 }
115
116 pub fn get_hdr_size(&self) -> usize {
117 8
118 }
119
120 pub fn encode(&self, buf: &mut [u8], offset: usize) -> SResult<usize> {
132 let mut off = offset;
133
134 off = enc_consume!(buf, off; encode_u8, self.get_type_as_int());
135 off = enc_consume!(buf, off; encode_u8, self.code);
136 off = enc_consume!(buf, off; encode_u16, self.cksum);
137
138 match self.options {
139 ICMP6HeaderOptions::Type1 { unused } | ICMP6HeaderOptions::Type3 { unused } => {
140 off = enc_consume!(buf, off; encode_u32, unused);
141 }
142 ICMP6HeaderOptions::Type128 { id, seqno }
143 | ICMP6HeaderOptions::Type129 { id, seqno } => {
144 off = enc_consume!(buf, off; encode_u16, id);
145 off = enc_consume!(buf, off; encode_u16, seqno);
146 }
147 }
148
149 stream_done!(off, off);
150 }
151
152 pub fn decode(buf: &[u8]) -> SResult<ICMP6Header> {
162 let off = 0;
163 let (off, type_num) = dec_try!(buf, off; decode_u8);
164
165 let icmp_type = match type_num {
166 1 => ICMP6Type::Type1,
167 3 => ICMP6Type::Type3,
168 128 => ICMP6Type::Type128,
169 129 => ICMP6Type::Type129,
170 _ => return SResult::Error(()),
171 };
172
173 let mut icmp_header = Self::new(icmp_type);
174
175 let (off, code) = dec_try!(buf, off; decode_u8);
176 icmp_header.set_code(code);
177 let (off, cksum) = dec_try!(buf, off; decode_u16);
178 icmp_header.set_cksum(u16::from_be(cksum));
179
180 match icmp_type {
181 ICMP6Type::Type1 => {
182 let (_off, unused) = dec_try!(buf, off; decode_u32);
183 let unused = u32::from_be(unused);
184 icmp_header.set_options(ICMP6HeaderOptions::Type1 { unused });
185 }
186 ICMP6Type::Type3 => {
187 let (_off, unused) = dec_try!(buf, off; decode_u32);
188 let unused = u32::from_be(unused);
189 icmp_header.set_options(ICMP6HeaderOptions::Type3 { unused });
190 }
191 ICMP6Type::Type128 => {
192 let (_off, id) = dec_try!(buf, off; decode_u16);
193 let id = u16::from_be(id);
194 let (_off, seqno) = dec_try!(buf, off; decode_u16);
195 let seqno = u16::from_be(seqno);
196 icmp_header.set_options(ICMP6HeaderOptions::Type128 { id, seqno });
197 }
198 ICMP6Type::Type129 => {
199 let (_off, id) = dec_try!(buf, off; decode_u16);
200 let id = u16::from_be(id);
201 let (_off, seqno) = dec_try!(buf, off; decode_u16);
202 let seqno = u16::from_be(seqno);
203 icmp_header.set_options(ICMP6HeaderOptions::Type129 { id, seqno });
204 }
205 }
206
207 stream_done!(off, icmp_header);
208 }
209}