Implement getaddrinfo (somewhat)
This commit is contained in:
+1
-1
@@ -41,7 +41,7 @@ redox_syscall = "0.1"
|
||||
spin = "0.4.10"
|
||||
|
||||
[features]
|
||||
#default = ["trace"]
|
||||
default = []
|
||||
trace = []
|
||||
|
||||
[profile.dev]
|
||||
|
||||
+76
-7
@@ -5,6 +5,7 @@ mod dns;
|
||||
use core::str::FromStr;
|
||||
use core::{mem, ptr, slice, str};
|
||||
|
||||
use alloc::borrow::ToOwned;
|
||||
use alloc::boxed::Box;
|
||||
use alloc::str::SplitWhitespace;
|
||||
use alloc::vec::Vec;
|
||||
@@ -13,11 +14,11 @@ use c_str::{CStr, CString};
|
||||
use header::arpa_inet::htons;
|
||||
use header::errno::*;
|
||||
use header::fcntl::O_RDONLY;
|
||||
use header::netinet_in::{in_addr, sockaddr_in};
|
||||
use header::netinet_in::{in_addr, sockaddr_in, sockaddr_in6};
|
||||
use header::stdlib::atoi;
|
||||
use header::strings::strcasecmp;
|
||||
use header::sys_socket::constants::{AF_UNSPEC, AF_INET};
|
||||
use header::sys_socket::{sockaddr, socklen_t};
|
||||
use header::sys_socket::{sa_family_t, sockaddr, socklen_t};
|
||||
use header::unistd::SEEK_SET;
|
||||
use platform;
|
||||
use platform::rlb::{Line, RawLineBuffer};
|
||||
@@ -670,15 +671,72 @@ pub unsafe extern "C" fn getaddrinfo(
|
||||
|
||||
let hints_opt = if hints.is_null() { None } else { Some(&*hints) };
|
||||
|
||||
eprintln!(
|
||||
trace!(
|
||||
"getaddrinfo({:?}, {:?}, {:?})",
|
||||
node_opt.map(|c| str::from_utf8_unchecked(c.to_bytes())),
|
||||
service_opt.map(|c| str::from_utf8_unchecked(c.to_bytes())),
|
||||
hints_opt
|
||||
);
|
||||
|
||||
platform::errno = ENOSYS;
|
||||
EAI_SYSTEM
|
||||
//TODO: Use hints
|
||||
let mut ai_flags = hints_opt.map_or(0, |hints| hints.ai_flags);
|
||||
let mut ai_family = hints_opt.map_or(AF_UNSPEC, |hints| hints.ai_family);
|
||||
let mut ai_socktype = hints_opt.map_or(0, |hints| hints.ai_socktype);
|
||||
let mut ai_protocol = hints_opt.map_or(0, |hints| hints.ai_protocol);
|
||||
|
||||
*res = ptr::null_mut();
|
||||
|
||||
//TODO: Check hosts file
|
||||
if let Some(node) = node_opt {
|
||||
let lookuphost = match lookup_host(str::from_utf8_unchecked(node.to_bytes())) {
|
||||
Ok(lookuphost) => lookuphost,
|
||||
Err(e) => {
|
||||
platform::errno = e;
|
||||
return EAI_SYSTEM;
|
||||
}
|
||||
};
|
||||
|
||||
for in_addr in lookuphost {
|
||||
ai_family = AF_INET;
|
||||
ai_socktype = AF_UNSPEC;
|
||||
ai_protocol = 0;
|
||||
|
||||
let ai_addr = Box::into_raw(Box::new(sockaddr_in {
|
||||
sin_family: AF_INET as sa_family_t,
|
||||
sin_port: 0,
|
||||
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().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);
|
||||
}
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -721,8 +779,19 @@ pub unsafe extern "C" fn freeaddrinfo(res: *mut addrinfo) {
|
||||
let mut ai = res;
|
||||
while !ai.is_null() {
|
||||
let bai = Box::from_raw(ai);
|
||||
ai = (*ai).ai_next;
|
||||
drop(bai);
|
||||
if !bai.ai_canonname.is_null() {
|
||||
CString::from_raw(bai.ai_canonname);
|
||||
}
|
||||
if !bai.ai_addr.is_null() {
|
||||
if bai.ai_addrlen == mem::size_of::<sockaddr_in>() {
|
||||
Box::from_raw(bai.ai_addr as *mut sockaddr_in);
|
||||
} else if bai.ai_addrlen == mem::size_of::<sockaddr_in6>() {
|
||||
Box::from_raw(bai.ai_addr as *mut sockaddr_in6);
|
||||
} else {
|
||||
eprintln!("freeaddrinfo: unknown ai_addrlen {}", bai.ai_addrlen);
|
||||
}
|
||||
}
|
||||
ai = bai.ai_next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ pub type socklen_t = u32;
|
||||
#[derive(Default)]
|
||||
pub struct sockaddr {
|
||||
pub sa_family: sa_family_t,
|
||||
pub data: [c_char; 14],
|
||||
pub sa_data: [c_char; 14],
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
||||
+5
-4
@@ -15,7 +15,8 @@ EXPECT_BINS=\
|
||||
libgen \
|
||||
locale \
|
||||
math \
|
||||
netdb \
|
||||
netdb/netdb \
|
||||
netdb/getaddrinfo \
|
||||
regex \
|
||||
select \
|
||||
setjmp \
|
||||
@@ -112,7 +113,6 @@ BINS=\
|
||||
.PHONY: all $(BINS) clean run expected verify
|
||||
|
||||
all: $(BINS)
|
||||
expect: $(EXPECT_BINS)
|
||||
|
||||
$(BINS): %: bins/%
|
||||
|
||||
@@ -126,7 +126,7 @@ run: | ../sysroot all
|
||||
"bins/$${bin}" test args || exit $$?; \
|
||||
done
|
||||
|
||||
expected: | ../sysroot expect
|
||||
expected: | ../sysroot $(EXPECT_BINS)
|
||||
rm -rf expected
|
||||
mkdir -p expected
|
||||
for bin in $(EXPECT_BINS); \
|
||||
@@ -136,7 +136,7 @@ expected: | ../sysroot expect
|
||||
"bins/$${bin}" test args > "expected/$${bin}.stdout" 2> "expected/$${bin}.stderr" || exit $$?; \
|
||||
done
|
||||
|
||||
verify: | ../sysroot expect
|
||||
verify: | ../sysroot $(EXPECT_BINS)
|
||||
rm -rf gen
|
||||
mkdir -p gen
|
||||
for bin in $(EXPECT_BINS); \
|
||||
@@ -151,6 +151,7 @@ verify: | ../sysroot expect
|
||||
CFLAGS=\
|
||||
-fno-builtin \
|
||||
-fno-stack-protector \
|
||||
-static \
|
||||
-Wall \
|
||||
-g \
|
||||
-nostdinc \
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
IPv4 address: 23.21.162.66 (www.redox-os.org)
|
||||
@@ -0,0 +1,50 @@
|
||||
// Adapted from https://gist.github.com/jirihnidek/bf7a2363e480491da72301b228b35d5d
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
int main(void) {
|
||||
struct addrinfo hints, *res;
|
||||
int errcode;
|
||||
char addrstr[INET6_ADDRSTRLEN];
|
||||
void *ptr;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags |= AI_CANONNAME;
|
||||
|
||||
errcode = getaddrinfo("www.redox-os.org", NULL, &hints, &res);
|
||||
if (errcode != 0) {
|
||||
perror("getaddrinfo");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (res) {
|
||||
switch (res->ai_family) {
|
||||
case AF_INET:
|
||||
ptr = &((struct sockaddr_in *) res->ai_addr)->sin_addr;
|
||||
break;
|
||||
case AF_INET6:
|
||||
ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
|
||||
break;
|
||||
}
|
||||
inet_ntop(res->ai_family, ptr, addrstr, INET6_ADDRSTRLEN);
|
||||
|
||||
printf(
|
||||
"IPv%d address: %s (%s)\n",
|
||||
res->ai_family == PF_INET6 ? 6 : 4,
|
||||
addrstr,
|
||||
res->ai_canonname
|
||||
);
|
||||
|
||||
res = res->ai_next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user