Implement getaddrinfo (somewhat)

This commit is contained in:
Jeremy Soller
2019-01-21 20:36:56 -07:00
parent f3c858c151
commit c59f268fcd
10 changed files with 134 additions and 13 deletions
+1 -1
View File
@@ -41,7 +41,7 @@ redox_syscall = "0.1"
spin = "0.4.10"
[features]
#default = ["trace"]
default = []
trace = []
[profile.dev]
+76 -7
View File
@@ -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;
}
}
+1 -1
View File
@@ -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
View File
@@ -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 \
+1
View File
@@ -0,0 +1 @@
IPv4 address: 23.21.162.66 (www.redox-os.org)
View File
+50
View File
@@ -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;
}