Skip to content
Snippets Groups Projects
Verified Commit f8b49936 authored by jD91mZM2's avatar jD91mZM2
Browse files

Various unix socket fixes (+socketpair!)

parent b7053b67
No related branches found
No related tags found
No related merge requests found
......@@ -5,3 +5,12 @@ pub struct sockaddr_un {
pub sun_family: sa_family_t,
pub sun_path: [c_char; 108],
}
impl sockaddr_un {
pub fn path_len(&self) -> usize {
let base = self as *const _ as usize;
let path = &self.sun_path as *const _ as usize;
trace!("base: {:#X}, path: {:#X}", base, path);
path - base
}
}
......@@ -29,9 +29,9 @@ impl PalEpoll for Sys {
id: fd as usize,
flags: syscall::EventFlags::from_bits(unsafe { (*event).events as usize })
.expect("epoll: invalid bit pattern"),
// NOTE: Danger when using non 64-bit systems. If this is
// needed, use a box or something
data: unsafe { mem::transmute((*event).data) },
// NOTE: Danger when using something smaller than 64-bit
// systems. If this is needed, use a box or something
data: unsafe { (*event).data.u64 as usize },
},
) as c_int
}
......@@ -102,7 +102,7 @@ impl PalEpoll for Sys {
if bytes_read == -1 {
return -1;
}
let read = bytes_read as usize / mem::size_of::<epoll_event>();
let read = bytes_read as usize / mem::size_of::<syscall::Event>();
let mut count = 0;
for i in 0..read {
......@@ -117,7 +117,7 @@ impl PalEpoll for Sys {
}
*event_ptr = epoll_event {
events: event.flags.bits() as _,
data: mem::transmute(event.data),
data: epoll_data { u64: event.data as u64, },
..Default::default()
};
count += 1;
......
......@@ -32,13 +32,17 @@ macro_rules! bind_or_connect {
0
}};
($mode:ident copy, $socket:expr, $address:expr, $address_len:expr) => {{
if ($address_len as usize) < mem::size_of::<sockaddr>() {
if ($address_len as usize) < mem::size_of::<sa_family_t>() {
errno = syscall::EINVAL;
return -1;
}
let path = match (*$address).sa_family as c_int {
AF_INET => {
if ($address_len as usize) != mem::size_of::<sockaddr_in>() {
errno = syscall::EINVAL;
return -1;
}
let data = &*($address as *const sockaddr_in);
let addr = slice::from_raw_parts(
&data.sin_addr.s_addr as *const _ as *const u8,
......@@ -58,9 +62,10 @@ macro_rules! bind_or_connect {
},
AF_UNIX => {
let data = &*($address as *const sockaddr_un);
trace!("address: {:p}, data: {:p}, data2: {:#X}", $address, data, data as *const _ as usize);
let addr = slice::from_raw_parts(
&data.sun_path as *const _ as *const u8,
mem::size_of_val(&data.sun_path),
$address_len as usize - data.path_len(),
);
let path = format!(
"{}",
......@@ -91,7 +96,7 @@ unsafe fn inner_af_unix(buf: &[u8], address: *mut sockaddr, address_len: *mut so
let path = slice::from_raw_parts_mut(
&mut data.sun_path as *mut _ as *mut u8,
mem::size_of_val(&data.sun_path),
data.path_len(),
);
let len = cmp::min(path.len(), buf.len());
......@@ -165,6 +170,19 @@ unsafe fn inner_get_name(
Ok(0)
}
fn socket_kind(mut kind: c_int) -> (c_int, usize) {
let mut flags = O_RDWR;
if kind & SOCK_NONBLOCK == SOCK_NONBLOCK {
kind &= !SOCK_NONBLOCK;
flags |= O_NONBLOCK;
}
if kind & SOCK_CLOEXEC == SOCK_CLOEXEC {
kind &= !SOCK_CLOEXEC;
flags |= O_CLOEXEC;
}
(kind, flags)
}
impl PalSocket for Sys {
unsafe fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int {
let stream = e(syscall::dup(socket as usize, b"listen")) as c_int;
......@@ -357,7 +375,7 @@ impl PalSocket for Sys {
e(Err(syscall::Error::new(syscall::ENOSYS))) as c_int
}
unsafe fn socket(domain: c_int, mut kind: c_int, protocol: c_int) -> c_int {
unsafe fn socket(domain: c_int, kind: c_int, protocol: c_int) -> c_int {
if domain != AF_INET && domain != AF_UNIX {
errno = syscall::EAFNOSUPPORT;
return -1;
......@@ -367,15 +385,7 @@ impl PalSocket for Sys {
// return -1;
// }
let mut flags = O_RDWR;
if kind & SOCK_NONBLOCK == SOCK_NONBLOCK {
kind &= !SOCK_NONBLOCK;
flags |= O_NONBLOCK;
}
if kind & SOCK_CLOEXEC == SOCK_CLOEXEC {
kind &= !SOCK_CLOEXEC;
flags |= O_CLOEXEC;
}
let (kind, flags) = socket_kind(kind);
// The tcp: and udp: schemes allow using no path,
// and later specifying one using `dup`.
......@@ -386,19 +396,52 @@ impl PalSocket for Sys {
_ => {
errno = syscall::EPROTONOSUPPORT;
-1
}
},
}
}
fn socketpair(domain: c_int, kind: c_int, protocol: c_int, sv: &mut [c_int; 2]) -> c_int {
eprintln!(
"socketpair({}, {}, {}, {:p})",
domain,
kind,
protocol,
sv.as_mut_ptr()
);
unsafe { errno = syscall::ENOSYS };
return -1;
let (kind, flags) = socket_kind(kind);
match (domain, kind) {
(AF_UNIX, SOCK_STREAM) => {
let listener = e(syscall::open("chan:", flags | O_CREAT));
if listener == !0 {
return -1;
}
// For now, chan: lets connects be instant, and instead blocks
// on any I/O performed. So we don't need to mark this as
// nonblocking.
let fd0 = e(syscall::dup(listener, b"connect"));
if fd0 == !0 {
let _ = syscall::close(listener);
return -1;
}
let fd1 = e(syscall::dup(listener, b"listen"));
if fd1 == !0 {
let _ = syscall::close(fd0);
let _ = syscall::close(listener);
return -1;
}
sv[0] = fd0 as c_int;
sv[1] = fd1 as c_int;
0
},
_ => unsafe {
eprintln!(
"socketpair({}, {}, {}, {:p})",
domain,
kind,
protocol,
sv.as_mut_ptr()
);
errno = syscall::EPROTONOSUPPORT;
-1
},
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment