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:
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user