Merge branch 'null_getaddrinfo' into 'master'

Implement getaddrinfo NULL nodename, AI_PASSIVE, AI_NUMERICHOST

Closes #223

See merge request redox-os/relibc!710
This commit is contained in:
Jeremy Soller
2025-09-15 06:47:27 -06:00
3 changed files with 108 additions and 46 deletions
+8 -6
View File
@@ -32,15 +32,17 @@ impl Iterator for LookupHost {
}
}
impl From<u32> for LookupHost {
/// from ipv4 address
fn from(s_addr: u32) -> Self {
LookupHost(vec![in_addr { s_addr }].into_iter())
}
}
pub fn lookup_host(host: &str) -> Result<LookupHost, c_int> {
if let Some(host_direct_addr) = parse_ipv4_string(host) {
// already an ip address
return Ok(LookupHost(
vec![in_addr {
s_addr: host_direct_addr,
}]
.into_iter(),
));
return Ok(host_direct_addr.into());
}
let dns_string = get_dns_server().map_err(|e| e.0)?;
+55 -40
View File
@@ -771,7 +771,6 @@ pub unsafe extern "C" fn getaddrinfo(
hints: *const addrinfo,
res: *mut *mut addrinfo,
) -> c_int {
//TODO: getaddrinfo
let node_opt = CStr::from_nullable_ptr(node);
let service_opt = CStr::from_nullable_ptr(service);
@@ -800,55 +799,71 @@ pub unsafe extern "C" fn getaddrinfo(
Err(_err) => (),
}
}
let node = node_opt.unwrap_or_else(|| {
//TODO: Optimize by bypassing string parsing
if ai_flags & AI_PASSIVE > 0 {
c"0.0.0.0".into()
} else {
c"127.0.0.1".into()
}
});
//TODO: Check hosts file
if let Some(node) = node_opt {
//TODO: Support AI_NUMERICHOST
let lookuphost = match lookup_host(str::from_utf8_unchecked(node.to_bytes())) {
let lookuphost = if ai_flags & AI_NUMERICHOST > 0 {
match parse_ipv4_string(str::from_utf8_unchecked(node.to_bytes())) {
Some(s_addr) => s_addr.into(),
None => {
return EAI_NONAME;
}
}
} else {
match lookup_host(str::from_utf8_unchecked(node.to_bytes())) {
Ok(lookuphost) => lookuphost,
Err(e) => {
platform::ERRNO.set(e);
return EAI_SYSTEM;
}
}
};
for in_addr in lookuphost {
ai_family = AF_INET;
ai_protocol = 0;
let ai_addr = Box::into_raw(Box::new(sockaddr_in {
sin_family: ai_family as sa_family_t,
sin_port: htons(port),
sin_addr: in_addr,
sin_zero: [0; 8],
})) as *mut sockaddr;
let ai_addrlen = mem::size_of::<sockaddr_in>();
let ai_canonname = if ai_flags & AI_CANONNAME > 0 {
if node_opt.is_none() {
return EAI_BADFLAGS;
}
ai_flags &= !AI_CANONNAME;
node.to_owned_cstring().into_raw()
} else {
ptr::null_mut()
};
for in_addr in lookuphost {
ai_family = AF_INET;
ai_protocol = 0;
let addrinfo = Box::new(addrinfo {
ai_flags: 0,
ai_family,
ai_socktype,
ai_protocol,
ai_addrlen,
ai_canonname,
ai_addr,
ai_next: ptr::null_mut(),
});
let ai_addr = Box::into_raw(Box::new(sockaddr_in {
sin_family: ai_family as sa_family_t,
sin_port: htons(port),
sin_addr: in_addr,
sin_zero: [0; 8],
})) as *mut sockaddr;
let ai_addrlen = mem::size_of::<sockaddr_in>();
let ai_canonname = if ai_flags & AI_CANONNAME > 0 {
ai_flags &= !AI_CANONNAME;
node.to_owned_cstring().into_raw()
} else {
ptr::null_mut()
};
let addrinfo = Box::new(addrinfo {
ai_flags: 0,
ai_family,
ai_socktype,
ai_protocol,
ai_addrlen,
ai_canonname,
ai_addr,
ai_next: ptr::null_mut(),
});
let mut indirect = res;
while !(*indirect).is_null() {
indirect = &mut (**indirect).ai_next;
}
*indirect = Box::into_raw(addrinfo);
let mut indirect = res;
while !(*indirect).is_null() {
indirect = &mut (**indirect).ai_next;
}
*indirect = Box::into_raw(addrinfo);
}
0
+45
View File
@@ -0,0 +1,45 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include "test_helpers.h"
int test_getaddrinfo(int ai_flags, size_t* ipv4_addr) {
struct addrinfo hints, *res;
int status;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = ai_flags;
if ((status = getaddrinfo(NULL, "8080", &hints, &res)) != 0) {
return status;
}
*ipv4_addr = ((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr;
freeaddrinfo(res);
return 0;
}
int main() {
size_t ipv4_addr;
char addrstr[INET_ADDRSTRLEN];
int status = test_getaddrinfo(0, &ipv4_addr);
ERROR_IF(getaddrinfo, status, != 0);
ERROR_IF(getaddrinfo_ai_addr, ipv4_addr, == 0);
inet_ntop(AF_INET, &ipv4_addr, addrstr, INET_ADDRSTRLEN);
printf("local IPv4 address 1: %s\n", addrstr);
status = test_getaddrinfo(AI_PASSIVE, &ipv4_addr);
ERROR_IF(getaddrinfo, status, != 0);
ERROR_IF(getaddrinfo_ai_addr, ipv4_addr, != 0);
inet_ntop(AF_INET, &ipv4_addr, addrstr, INET_ADDRSTRLEN);
printf("local IPv4 address 2: %s\n", addrstr);
}