relibc/header/arpa_inet/
mod.rs1use core::{
6 ptr, slice,
7 str::{self, FromStr},
8};
9
10use crate::{
11 c_str::CStr,
12 header::{
13 bits_arpainet::ntohl,
14 errno::{EAFNOSUPPORT, ENOSPC},
15 netinet_in::{INADDR_NONE, in_addr, in_addr_t, in6_addr},
16 sys_socket::{
17 constants::{AF_INET, AF_INET6},
18 socklen_t,
19 },
20 },
21 io::Write,
22 platform::{
23 self,
24 types::{c_char, c_int, c_void},
25 },
26 raw_cell::RawCell,
27};
28
29#[deprecated]
48#[unsafe(no_mangle)]
49pub unsafe extern "C" fn inet_addr(cp: *const c_char) -> in_addr_t {
50 let mut val: in_addr = in_addr { s_addr: 0 };
51
52 if unsafe { inet_aton(cp, &raw mut val) } > 0 {
53 val.s_addr
54 } else {
55 INADDR_NONE
56 }
57}
58
59#[unsafe(no_mangle)]
65pub unsafe extern "C" fn inet_aton(cp: *const c_char, inp: *mut in_addr) -> c_int {
66 let cp_cstr = unsafe { CStr::from_ptr(cp) };
67 let parts = unsafe { str::from_utf8_unchecked(cp_cstr.to_bytes()).split('.') };
68 let count = parts.clone().count();
69 if count > 4 {
70 return 0;
71 }
72 let mut result = 0;
73 let mut parts_iter = parts.peekable();
74 let mut index = 0u32;
75 while index < 4
76 && let Some(part) = parts_iter.next()
77 {
78 if let Ok(parsed_value) = {
79 if let Some(hex_or_oct) = part.strip_prefix('0')
80 && part.len() > 1
81 {
82 match hex_or_oct.bytes().next() {
83 Some(b'x' | b'X') => u32::from_str_radix(&hex_or_oct[1..], 16),
84 _ => u32::from_str_radix(hex_or_oct, 8),
88 }
89 } else {
90 part.parse::<u32>()
91 }
92 } {
93 if parts_iter.peek().is_some() {
94 if parsed_value > 0xff {
96 return 0;
97 }
98 result += parsed_value << (24 - index * 8);
99 } else {
100 if index > 0 && parsed_value >= 1 << (32 - index * 8) {
102 return 0;
103 } else {
104 result += parsed_value;
105 }
106 }
107 } else {
108 return 0;
109 }
110 index += 1;
111 }
112 unsafe { (*inp.cast::<in_addr>()).s_addr = result.to_be() };
113 1
114}
115
116#[deprecated]
125#[unsafe(no_mangle)]
126pub extern "C" fn inet_lnaof(r#in: in_addr) -> in_addr_t {
127 if r#in.s_addr >> 24 < 128 {
128 r#in.s_addr & 0xff_ffff
129 } else if r#in.s_addr >> 24 < 192 {
130 r#in.s_addr & 0xffff
131 } else {
132 r#in.s_addr & 0xff
133 }
134}
135
136#[deprecated]
146#[unsafe(no_mangle)]
147pub extern "C" fn inet_makeaddr(net: in_addr_t, lna: in_addr_t) -> in_addr {
148 let mut output: in_addr = in_addr { s_addr: 0 };
149
150 if net < 256 {
151 output.s_addr = lna | net << 24;
152 } else if net < 65536 {
153 output.s_addr = lna | net << 16;
154 } else {
155 output.s_addr = lna | net << 8;
156 }
157
158 output
159}
160
161#[deprecated]
170#[unsafe(no_mangle)]
171pub extern "C" fn inet_netof(r#in: in_addr) -> in_addr_t {
172 if r#in.s_addr >> 24 < 128 {
173 r#in.s_addr & 0xff_ffff
174 } else if r#in.s_addr >> 24 < 192 {
175 r#in.s_addr & 0xffff
176 } else {
177 r#in.s_addr & 0xff
178 }
179}
180
181#[deprecated]
191#[unsafe(no_mangle)]
192pub unsafe extern "C" fn inet_network(cp: *const c_char) -> in_addr_t {
193 ntohl(unsafe {
194 #[allow(deprecated)]
195 inet_addr(cp)
196 })
197}
198
199#[deprecated]
211#[unsafe(no_mangle)]
212pub unsafe extern "C" fn inet_ntoa(r#in: in_addr) -> *mut c_char {
213 static NTOA_ADDR: RawCell<[c_char; 16]> = RawCell::new([0; 16]);
214
215 unsafe {
216 let ptr = inet_ntop(
217 AF_INET,
218 ptr::from_ref::<in_addr>(&r#in).cast::<c_void>(),
219 NTOA_ADDR.unsafe_mut().as_mut_ptr(),
220 NTOA_ADDR.unsafe_ref().len() as socklen_t,
221 );
222 ptr.cast_mut()
224 }
225}
226
227#[unsafe(no_mangle)]
231pub unsafe extern "C" fn inet_ntop(
232 af: c_int,
233 src: *const c_void,
234 dst: *mut c_char,
235 size: socklen_t,
236) -> *const c_char {
237 if af != AF_INET {
238 platform::ERRNO.set(EAFNOSUPPORT);
239 ptr::null()
240 } else if size < 16 {
241 platform::ERRNO.set(ENOSPC);
242 ptr::null()
243 } else {
244 let s_addr = unsafe {
245 slice::from_raw_parts(
246 ptr::from_ref(&(*(src.cast::<in_addr>())).s_addr).cast::<u8>(),
247 4,
248 )
249 };
250 let mut w = platform::StringWriter(dst, size as usize);
251 let _ = write!(
252 w,
253 "{}.{}.{}.{}\0",
254 s_addr[0], s_addr[1], s_addr[2], s_addr[3]
255 );
256 dst
257 }
258}
259
260#[unsafe(no_mangle)]
265pub unsafe extern "C" fn inet_pton(af: c_int, src: *const c_char, dst: *mut c_void) -> c_int {
266 if af == AF_INET {
267 let s_addr = unsafe {
268 slice::from_raw_parts_mut(
269 ptr::from_mut(&mut (*dst.cast::<in_addr>()).s_addr).cast::<u8>(),
270 4,
271 )
272 };
273 let src_cstr = unsafe { CStr::from_ptr(src) };
274 let mut octets = unsafe { str::from_utf8_unchecked(src_cstr.to_bytes()).split('.') };
275 for part in s_addr.iter_mut().take(4) {
276 if let Some(n) = octets
277 .next()
278 .filter(|x| x.len() <= 3)
279 .and_then(|x| u8::from_str(x).ok())
280 {
281 *part = n;
282 } else {
283 return 0;
284 }
285 }
286 if octets.next().is_none() {
287 1 } else {
289 0
290 }
291 } else if af == AF_INET6 {
292 let src_str = unsafe { str::from_utf8_unchecked(CStr::from_ptr(src).to_bytes()) };
293 let mut chunks = vec![src_str];
294 let colons = src_str.bytes().filter(|&c| c == b':').count();
295 if !(2..=7).contains(&colons) {
296 return 0;
297 }
298 let dots = src_str.bytes().filter(|&c| c == b'.').count();
299 if dots != 0 && dots != 3 {
300 return 0;
301 }
302 let double_colon = src_str.find("::");
303 if colons < 2
304 || double_colon.is_some() && ((dots == 0 && colons > 7) || (dots == 3 && colons > 6))
305 || double_colon.is_none() && ((dots == 0 && colons != 7) || (dots == 3 && colons != 6))
306 {
307 return 0;
308 }
309 if dots == 3
310 && let Some(first_dot) = src_str.find('.')
311 && let Some(last_colon) = src_str.find(':')
312 && last_colon > first_dot
313 {
314 return 0;
315 }
316 if let Some(first) = src_str.find("::")
317 && let Some(last) = src_str.rfind("::")
318 {
319 if first != last {
321 return 0;
322 }
323 chunks = vec![&src_str[..first], &src_str[(first + 2)..]]
324 }
325
326 let s6_addr = unsafe {
327 slice::from_raw_parts_mut(
328 ptr::from_mut(&mut (*dst.cast::<in6_addr>()).s6_addr).cast::<u16>(),
329 8,
330 )
331 };
332 s6_addr.iter_mut().for_each(|w| *w = 0);
333
334 for (count, &chunk) in chunks
335 .iter()
336 .enumerate()
337 .filter(|&(_, &chunk)| !chunk.is_empty())
338 {
339 let mut parts = s6_addr
340 .iter_mut()
341 .skip(count * (8 - chunk.split(':').count() - dots / 3));
342 let mut words = chunk.split(':');
343 while let Some(word) = words.next()
344 && let Some(part) = parts.next()
345 {
346 if word.is_empty() {
347 break;
348 } else if word.len() <= 4
349 && let Some(n) = u16::from_str_radix(word, 16).ok()
350 {
351 *part = n.to_be();
352 } else if word.contains('.') {
353 let bytes =
354 unsafe { slice::from_raw_parts_mut(ptr::from_mut(part).cast::<u8>(), 4) };
355 let mut octets = word.split('.');
356 for byte in bytes {
357 if let Some(octet) = octets.next() {
358 if octet.len() > 1 && octet.starts_with('0') {
359 return 0;
360 }
361 if let Ok(value) = u8::from_str(octet) {
362 *byte = value
363 } else {
364 return 0;
365 }
366 }
367 }
368 } else {
369 return 0;
370 }
371 }
372 }
373 1 } else {
375 platform::ERRNO.set(EAFNOSUPPORT);
376 -1
377 }
378}