fix arpa_inet/inet_addr

This commit is contained in:
sourceturner
2026-05-27 23:39:44 +02:00
parent ef7b690626
commit 538db929cf
+36 -27
View File
@@ -44,42 +44,51 @@ pub unsafe extern "C" fn inet_addr(cp: *const c_char) -> in_addr_t {
#[unsafe(no_mangle)]
pub unsafe extern "C" fn inet_aton(cp: *const c_char, inp: *mut in_addr) -> c_int {
let cp_cstr = unsafe { CStr::from_ptr(cp) };
let mut four_parts_decimal_only = false;
if cp_cstr.contains(b'.') {
// 2, 3 or 4 part address
let parts = unsafe { str::from_utf8_unchecked(cp_cstr.to_bytes()).split('.') };
let mut count = 0;
for part in parts {
let parts = unsafe { str::from_utf8_unchecked(cp_cstr.to_bytes()).split('.') };
let count = parts.clone().count();
if count > 4 {
return 0;
}
let mut result = 0;
let mut parts_iter = parts.peekable();
let mut index = 0u32;
while index < 4
&& let Some(part) = parts_iter.next()
{
if let Ok(parsed_value) = {
if let Some(hex_or_oct) = part.strip_prefix('0')
&& part.len() > 1
{
match hex_or_oct.bytes().next() {
Some(b'x' | b'X') => todo_skip!(0, "parsing hex values unimplemented"),
// TODO: C2Y accept `0o` or `0O` as octal prefixes, C23 and below only use `0`
_ => todo_skip!(0, "parsing octal values unimplemented"),
Some(b'x' | b'X') => u32::from_str_radix(&hex_or_oct[1..], 16),
Some(b'o' | b'O') => u32::from_str_radix(&hex_or_oct[1..], 8),
_ => u32::from_str_radix(&hex_or_oct, 8),
}
} else {
count += 1;
u32::from_str_radix(&part, 10)
}
} {
if parts_iter.peek().is_some() {
// this is not the last part
if parsed_value > 0xff {
return 0;
}
result += parsed_value << (24 - index * 8);
} else {
// this is the last part
if index > 0 && parsed_value >= 1 << (32 - index * 8) {
return 0;
} else {
result += parsed_value;
}
}
} else {
return 0;
}
if count == 4 {
four_parts_decimal_only = true;
}
} else if cp_cstr.len() == 4 {
// 1 part address (32 bit value to be stored directly into address without byte rearrangement)
let s_addr_bytes: [u8; 4] = cp_cstr.to_bytes().try_into().expect("guaranteed 4 bytes");
unsafe {
(*inp.cast::<in_addr>()).s_addr = in_addr_t::from_ne_bytes(s_addr_bytes);
}
return 1; // successful
}
if four_parts_decimal_only {
unsafe { inet_pton(AF_INET, cp, inp.cast::<c_void>()) }
} else {
todo_skip!(0, "parsing 2 or more non-decimal values unimplemented");
// TODO convert octal and hexadecimal parts into decimal and feed into `inet_pton`
0 // indicates `cp` is an invalid string
index += 1;
}
unsafe { (*inp.cast::<in_addr>()).s_addr = result.to_be() };
1
}
/// See <https://pubs.opengroup.org/onlinepubs/7908799/xns/inet_lnaof.html>.