capsules_extra/net/ipv6/
ip_utils.rs1use crate::net::icmpv6::{ICMP6Header, ICMP6HeaderOptions};
12use crate::net::ieee802154::MacAddress;
13use crate::net::ipv6::IP6Header;
14use crate::net::udp::UDPHeader;
15
16#[derive(Copy, Clone, PartialEq)]
17pub enum MacAddr {
18 ShortAddr(u16),
19 LongAddr([u8; 8]),
20}
21
22pub mod ip6_nh {
23 pub const HOP_OPTS: u8 = 0;
24 pub const TCP: u8 = 6;
25 pub const UDP: u8 = 17;
26 pub const IP6: u8 = 41;
27 pub const ROUTING: u8 = 43;
28 pub const FRAGMENT: u8 = 44;
29 pub const ICMP: u8 = 58;
30 pub const NO_NEXT: u8 = 59;
31 pub const DST_OPTS: u8 = 60;
32 pub const MOBILITY: u8 = 135;
33}
34
35#[derive(Copy, Clone, Debug)]
36pub struct IPAddr(pub [u8; 16]);
37
38impl PartialEq for IPAddr {
39 fn eq(&self, other: &IPAddr) -> bool {
40 self.0 == other.0
41 }
42}
43
44impl Eq for IPAddr {}
45
46impl IPAddr {
47 pub fn new() -> IPAddr {
48 IPAddr([0; 16])
50 }
51
52 pub fn generate_from_mac(mac_addr: MacAddress) -> IPAddr {
55 let mut ip_addr = IPAddr([0; 16]);
56 match mac_addr {
57 MacAddress::Long(ref long_addr) => {
58 ip_addr.set_unicast_link_local();
59 ip_addr.0[15] = long_addr[7];
60 ip_addr.0[14] = long_addr[6];
61 ip_addr.0[13] = long_addr[5];
62 ip_addr.0[12] = long_addr[4];
63 ip_addr.0[11] = long_addr[3];
64 ip_addr.0[10] = long_addr[2];
65 ip_addr.0[9] = long_addr[1];
66 ip_addr.0[8] = long_addr[0] ^ 0b00000010;
67 }
68 MacAddress::Short(ref short_addr) => {
69 ip_addr.set_unicast_link_local();
70 ip_addr.0[15] = (short_addr & 0x00ff) as u8;
71 ip_addr.0[14] = ((short_addr & 0xff00) >> 8) as u8;
72 ip_addr.0[13] = 0x00;
73 ip_addr.0[12] = 0xfe;
74 ip_addr.0[11] = 0xff;
75 ip_addr.0[10] = 0x00;
76 ip_addr.0[9] = 0x00;
77 ip_addr.0[8] = 0x00;
78 }
79 }
80 ip_addr
81 }
82
83 pub fn is_unspecified(&self) -> bool {
84 self.0.iter().all(|&b| b == 0)
85 }
86
87 pub fn is_unicast_link_local(&self) -> bool {
88 self.0[0] == 0xfe
89 && (self.0[1] & 0xc0) == 0x80
90 && (self.0[1] & 0x3f) == 0
91 && self.0[2..8].iter().all(|&b| b == 0)
92 }
93
94 pub fn set_unicast_link_local(&mut self) {
95 self.0[0] = 0xfe;
96 self.0[1] = 0x80;
97 for i in 2..8 {
98 self.0[i] = 0;
99 }
100 }
101
102 pub fn set_prefix(&mut self, prefix: &[u8], prefix_len: u8) {
104 let full_bytes = (prefix_len / 8) as usize;
105 let remaining = (prefix_len & 0x7) as usize;
106 let bytes = full_bytes + usize::from(remaining != 0);
107 assert!(bytes <= prefix.len() && bytes <= 16);
108
109 self.0[0..full_bytes].copy_from_slice(&prefix[0..full_bytes]);
110 if remaining != 0 {
111 let mask = 0xff_u8 << (8 - remaining);
112 self.0[full_bytes] &= !mask;
113 self.0[full_bytes] |= mask & prefix[full_bytes];
114 }
115 }
116
117 pub fn is_multicast(&self) -> bool {
118 self.0[0] == 0xff
119 }
120}
121
122pub fn compute_udp_checksum(
123 ip6_header: &IP6Header,
124 udp_header: &UDPHeader,
125 udp_length: u16,
126 payload: &[u8],
127) -> u16 {
128 let src_port = udp_header.get_src_port();
131 let dst_port = udp_header.get_dst_port();
132 let mut sum: u32 = 0;
133 {
134 let mut i = 0;
136 while i <= 14 {
137 let msb_src: u16 = ((ip6_header.src_addr.0[i]) as u16) << 8;
138 let lsb_src: u16 = ip6_header.src_addr.0[i + 1] as u16;
139 let temp_src: u16 = msb_src + lsb_src;
140 sum += temp_src as u32;
141
142 let msb_dst: u16 = ((ip6_header.dst_addr.0[i]) as u16) << 8;
143 let lsb_dst: u16 = ip6_header.dst_addr.0[i + 1] as u16;
144 let temp_dst: u16 = msb_dst + lsb_dst;
145 sum += temp_dst as u32;
146
147 i += 2; }
149 }
150 sum += udp_header.get_len() as u32;
151 sum += 17; sum += src_port as u32;
157 sum += dst_port as u32;
158 sum += udp_header.get_len() as u32;
159 sum += udp_header.get_cksum() as u32;
160 {
162 let mut i: usize = 0;
163 while i < ((udp_length - 8) as usize) {
164 let msb_dat: u16 = ((payload[i]) as u16) << 8;
165 let mut lsb_dat: u16 = 0;
166 if i + 1 < udp_length as usize - 8 {
167 lsb_dat = payload[i + 1] as u16;
168 }
169 let temp_dat: u16 = msb_dat + lsb_dat;
170 sum += temp_dat as u32;
171
172 i += 2; }
174 }
175 while sum > 65535 {
178 let sum_high: u32 = sum >> 16; let sum_low: u32 = sum & 65535; sum = sum_high + sum_low;
181 }
182
183 sum = !sum;
185 sum &= 65535; sum as u16 }
188
189pub fn compute_icmp_checksum(
190 ipv6_header: &IP6Header,
191 icmp_header: &ICMP6Header,
192 payload: &[u8],
193) -> u16 {
194 let mut sum: u32 = 0;
195
196 sum += compute_ipv6_ph_sum(ipv6_header);
198
199 let msb = (icmp_header.get_type_as_int() as u32) << 8;
201 let lsb = icmp_header.get_code() as u32;
202 sum += msb + lsb;
203
204 match icmp_header.get_options() {
206 ICMP6HeaderOptions::Type1 { unused } | ICMP6HeaderOptions::Type3 { unused } => {
207 sum += unused >> 16; sum += unused & 0xffff; }
210 ICMP6HeaderOptions::Type128 { id, seqno } | ICMP6HeaderOptions::Type129 { id, seqno } => {
211 sum += id as u32;
212 sum += seqno as u32;
213 }
214 }
215
216 let payload_len = icmp_header.get_len() - icmp_header.get_hdr_size() as u16;
218 sum += compute_sum(payload, payload_len);
219
220 while sum > 0xffff {
222 let sum_upper = sum >> 16;
223 let sum_lower = sum & 0xffff;
224 sum += sum_upper + sum_lower;
225 }
226
227 sum = !sum;
228 sum &= 0xffff;
229
230 sum as u16
231}
232
233pub fn compute_ipv6_ph_sum(ip6_header: &IP6Header) -> u32 {
234 let mut sum: u32 = 0;
235
236 let mut i = 0;
238 while i < 16 {
239 let msb_src = (ip6_header.src_addr.0[i] as u32) << 8;
240 let lsb_src = ip6_header.src_addr.0[i + 1] as u32;
241 sum += msb_src + lsb_src;
242
243 let msb_dst = (ip6_header.dst_addr.0[i] as u32) << 8;
244 let lsb_dst = ip6_header.dst_addr.0[i + 1] as u32;
245 sum += msb_dst + lsb_dst;
246
247 i += 2;
248 }
249
250 sum += ip6_header.payload_len as u32;
251 sum += ip6_header.next_header as u32;
252
253 sum
254}
255
256pub fn compute_sum(buf: &[u8], len: u16) -> u32 {
257 let mut sum: u32 = 0;
258
259 let mut i: usize = 0;
260 while i < (len as usize) {
261 let msb = (buf[i] as u32) << 8;
262 let lsb = buf[i + 1] as u32;
263 sum += msb + lsb;
264 i += 2;
265 }
266
267 sum
268}