atmos/kernel/net/
addr_util.rs1use alloc::string::String;
10
11pub fn parse_ipv4(s: &str) -> Option<[u8; 4]> {
12 let mut out = [0u8; 4];
13 let mut part_idx = 0usize;
14 let mut cur: u16 = 0;
15 let mut has_digit = false;
16
17 for ch in s.chars() {
18 if ch == '.' {
19 if !has_digit || part_idx >= 4 || cur > 255 {
20 return None;
21 }
22 out[part_idx] = cur as u8;
23 part_idx += 1;
24 cur = 0;
25 has_digit = false;
26 continue;
27 }
28
29 if !ch.is_ascii_digit() {
30 return None;
31 }
32
33 cur = cur
34 .saturating_mul(10)
35 .saturating_add((ch as u16).saturating_sub('0' as u16));
36 if cur > 255 {
37 return None;
38 }
39 has_digit = true;
40 }
41
42 if !has_digit || part_idx != 3 {
43 return None;
44 }
45
46 out[3] = cur as u8;
47 Some(out)
48}
49
50pub fn parse_mac(s: &str) -> Option<[u8; 6]> {
51 let mut mac = [0u8; 6];
52 let mut idx = 0usize;
53
54 for part in s.split(':') {
55 if idx >= 6 || part.len() != 2 {
56 return None;
57 }
58
59 let bytes = part.as_bytes();
60 let hi = hex_nibble(bytes[0])?;
61 let lo = hex_nibble(bytes[1])?;
62 mac[idx] = (hi << 4) | lo;
63 idx += 1;
64 }
65
66 if idx != 6 {
67 return None;
68 }
69
70 Some(mac)
71}
72
73pub fn format_ipv4(ip: [u8; 4]) -> String {
74 alloc::format!("{}.{}.{}.{}", ip[0], ip[1], ip[2], ip[3])
75}
76
77pub fn format_mac(mac: [u8; 6]) -> String {
78 alloc::format!(
79 "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
80 mac[0],
81 mac[1],
82 mac[2],
83 mac[3],
84 mac[4],
85 mac[5]
86 )
87}
88
89pub(crate) fn ipv4_header_checksum(header: &[u8]) -> u16 {
90 internet_checksum(header)
91}
92
93pub(crate) fn internet_checksum(data: &[u8]) -> u16 {
95 let mut sum: u32 = 0;
96 let mut i = 0usize;
97
98 while i + 1 < data.len() {
99 let word = ((data[i] as u16) << 8) | data[i + 1] as u16;
100 sum = sum.wrapping_add(word as u32);
101 i += 2;
102 }
103
104 if i < data.len() {
105 let word = (data[i] as u16) << 8;
106 sum = sum.wrapping_add(word as u32);
107 }
108
109 while (sum >> 16) != 0 {
110 sum = (sum & 0xFFFF) + (sum >> 16);
111 }
112
113 !(sum as u16)
114}
115
116fn hex_nibble(c: u8) -> Option<u8> {
117 match c {
118 b'0'..=b'9' => Some(c - b'0'),
119 b'a'..=b'f' => Some(c - b'a' + 10),
120 b'A'..=b'F' => Some(c - b'A' + 10),
121 _ => None,
122 }
123}