diff --git a/local/patches/relibc/P3-dns-aaaa-getaddrinfo-ipv6.patch b/local/patches/relibc/P3-dns-aaaa-getaddrinfo-ipv6.patch new file mode 100644 index 00000000..661d708e --- /dev/null +++ b/local/patches/relibc/P3-dns-aaaa-getaddrinfo-ipv6.patch @@ -0,0 +1,396 @@ +diff --git a/src/header/netdb/lookup.rs b/src/header/netdb/lookup.rs +index aaaaaaa..bbbbbbb 100644 +--- a/src/header/netdb/lookup.rs ++++ b/src/header/netdb/lookup.rs +@@ -14,7 +14,7 @@ use crate::header::{ + bits_socklen_t::socklen_t, + bits_timespec::timespec, + errno::*, +- netinet_in::{IPPROTO_UDP, in_addr, sockaddr_in}, ++ netinet_in::{IPPROTO_UDP, in6_addr, in_addr, sockaddr_in}, + sys_socket::{ + self, + constants::{AF_INET, SOCK_DGRAM, SOL_SOCKET, SO_RCVTIMEO}, +@@ -30,6 +30,7 @@ use super::{ + }; + + pub type LookupHost = Vec; ++pub type LookupHostV6 = Vec; + + pub fn lookup_host(host: &str) -> Result { + if let Some(host_direct_addr) = parse_ipv4_string(host) { +@@ -157,6 +158,123 @@ pub fn lookup_host(host: &str) -> Result { + } + } + ++/// Look up IPv6 (AAAA) addresses for a host via DNS. ++pub fn lookup_host_v6(host: &str) -> Result { ++ if let Some(addr6) = parse_ipv6_string(host) { ++ return Ok(vec![addr6]); ++ } ++ ++ let dns_string = get_dns_server().map_err(|e| e.0)?; ++ ++ if let Some(dns_addr) = parse_ipv4_string(&dns_string) { ++ let mut timespec = timespec::default(); ++ if let Ok(()) = Sys::clock_gettime( ++ time::constants::CLOCK_REALTIME, ++ Out::from_mut(&mut timespec), ++ ) {}; ++ let tid = (timespec.tv_nsec >> 16) as u16; ++ ++ let packet = Dns { ++ transaction_id: tid, ++ flags: 0x0100, ++ queries: vec![DnsQuery { ++ name: host.to_string(), ++ q_type: 0x001c, ++ q_class: 0x0001, ++ }], ++ answers: vec![], ++ }; ++ ++ let packet_data = packet.compile(); ++ let packet_data_len = packet_data.len(); ++ ++ let packet_data_box = packet_data.into_boxed_slice(); ++ let packet_data_ptr = Box::into_raw(packet_data_box) as *mut _ as *mut c_void; ++ ++ let dest = sockaddr_in { ++ sin_family: AF_INET as u16, ++ sin_port: htons(53), ++ sin_addr: in_addr { s_addr: dns_addr }, ++ ..Default::default() ++ }; ++ let dest_ptr = ptr::from_ref(&dest).cast::(); ++ ++ let sock = unsafe { ++ let sock = sys_socket::socket(AF_INET, SOCK_DGRAM, i32::from(IPPROTO_UDP)); ++ if sys_socket::connect(sock, dest_ptr, mem::size_of_val(&dest) as socklen_t) < 0 { ++ return Err(EIO); ++ } ++ if sys_socket::send(sock, packet_data_ptr, packet_data_len, 0) < 0 { ++ drop(Box::from_raw(packet_data_ptr)); ++ return Err(EIO); ++ } ++ sock ++ }; ++ ++ unsafe { ++ drop(Box::from_raw(packet_data_ptr)); ++ } ++ ++ let mut buf = vec![0u8; 65536]; ++ let buf_ptr = buf.as_mut_ptr().cast::(); ++ ++ // Set 5s recv timeout (best-effort; if this fails, recv may block longer). ++ let tv = timeval { ++ tv_sec: 5, ++ tv_usec: 0, ++ }; ++ unsafe { ++ sys_socket::setsockopt( ++ sock, ++ SOL_SOCKET, ++ SO_RCVTIMEO, ++ &tv as *const timeval as *const c_void, ++ core::mem::size_of::() as socklen_t, ++ ); ++ } ++ ++ let mut count: isize = -1; ++ for _attempt in 0..2 { ++ count = unsafe { sys_socket::recv(sock, buf_ptr, 65536, 0) }; ++ if count >= 0 { ++ break; ++ } ++ if unsafe { sys_socket::send(sock, packet_data_ptr, packet_data_len, 0) } < 0 { ++ break; ++ } ++ } ++ if count < 0 { ++ return Err(EIO); ++ } ++ ++ match Dns::parse(&buf[..count as usize]) { ++ Ok(response) => { ++ let addrs: Vec<_> = response ++ .answers ++ .into_iter() ++ .filter_map(|answer| { ++ if answer.a_type == 0x001c ++ && answer.a_class == 0x0001 ++ && answer.data.len() == 16 ++ { ++ let mut s6_addr = [0u8; 16]; ++ s6_addr.copy_from_slice(&answer.data[..16]); ++ Some(in6_addr { s6_addr }) ++ } else { ++ None ++ } ++ }) ++ .collect(); ++ ++ Ok(addrs) ++ } ++ Err(_err) => Err(EINVAL), ++ } ++ } else { ++ Err(EINVAL) ++ } ++} ++ + pub fn lookup_addr(addr: in_addr) -> Result>, c_int> { + let dns_string = get_dns_server().map_err(|e| e.0)?; + +@@ -282,6 +400,23 @@ pub fn parse_ipv4_string(ip_string: &str) -> Option { + Some(u32::from_ne_bytes(dns_arr)) + } + ++pub fn parse_ipv6_string(ip_string: &str) -> Option { ++ let trimmed = ip_string.trim(); ++ ++ let s = if trimmed.starts_with('[') && trimmed.ends_with(']') { ++ &trimmed[1..trimmed.len() - 1] ++ } else { ++ trimmed ++ }; ++ ++ let ip: core::net::Ipv6Addr = s.parse().ok()?; ++ let mut addr = in6_addr { ++ s6_addr: [0u8; 16], ++ }; ++ addr.s6_addr.copy_from_slice(&ip.octets()); ++ Some(addr) ++} ++ + #[cfg(test)] + mod tests { + use alloc::str; +diff --git a/src/header/netdb/mod.rs b/src/header/netdb/mod.rs +index ccccccc..ddddddd 100644 +--- a/src/header/netdb/mod.rs ++++ b/src/header/netdb/mod.rs +@@ -4,7 +4,7 @@ + + mod dns; + +-use core::{cell::Cell, fmt::Write, mem, net::Ipv4Addr, ptr, str}; ++use core::{cell::Cell, fmt::Write, mem, net::Ipv4Addr, net::Ipv6Addr, ptr, str}; + + use alloc::{boxed::Box, str::SplitWhitespace, string::ToString, vec::Vec}; + +@@ -18,10 +18,10 @@ use crate::{ + bits_socklen_t::socklen_t, + errno::*, + fcntl::O_RDONLY, +- netinet_in::{in_addr, sockaddr_in, sockaddr_in6}, ++ netinet_in::{in6_addr, in_addr, sockaddr_in, sockaddr_in6}, + stdlib::atoi, + strings::strcasecmp, +- sys_socket::{constants::AF_INET, sockaddr}, ++ sys_socket::{constants::{AF_INET, AF_INET6, AF_UNSPEC}, sockaddr}, + unistd::SEEK_SET, + }, + platform::{ +@@ -871,11 +871,16 @@ pub unsafe extern "C" fn getaddrinfo( + hints_opt + ); + ++ let requested_family = hints_opt.map_or(AF_UNSPEC, |hints| hints.ai_family); ++ ++ if requested_family != AF_INET && requested_family != AF_INET6 && requested_family != AF_UNSPEC ++ { ++ return EAI_FAMILY; ++ } ++ + //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 ai_socktype = hints_opt.map_or(0, |hints| hints.ai_socktype); +- let mut ai_protocol; // = hints_opt.map_or(0, |hints| hints.ai_protocol); + + unsafe { *res = ptr::null_mut() }; + +@@ -896,31 +901,52 @@ pub unsafe extern "C" fn getaddrinfo( + } + }); + +- let lookuphost = if ai_flags & AI_NUMERICHOST > 0 { +- match parse_ipv4_string(unsafe { str::from_utf8_unchecked(node.to_bytes()) }) { +- Some(s_addr) => vec![in_addr { s_addr }], +- None => { +- return EAI_NONAME; ++ let node_str = unsafe { str::from_utf8_unchecked(node.to_bytes()) }; ++ ++ let want_inet4 = requested_family == AF_INET || requested_family == AF_UNSPEC; ++ let want_inet6 = requested_family == AF_INET6 || requested_family == AF_UNSPEC; ++ ++ let lookuphost_v4: Vec = if want_inet4 { ++ if ai_flags & AI_NUMERICHOST > 0 { ++ match parse_ipv4_string(node_str) { ++ Some(s_addr) => vec![in_addr { s_addr }], ++ None => vec![], ++ } ++ } else { ++ match lookup_host(node_str) { ++ Ok(addrs) => addrs, ++ Err(_) => vec![], + } + } + } else { +- match lookup_host(unsafe { str::from_utf8_unchecked(node.to_bytes()) }) { +- Ok(lookuphost) => lookuphost, +- Err(e) => { +- platform::ERRNO.set(e); +- return EAI_SYSTEM; ++ vec![] ++ }; ++ ++ let lookuphost_v6: Vec = if want_inet6 { ++ if ai_flags & AI_NUMERICHOST > 0 { ++ match parse_ipv6_string(node_str) { ++ Some(addr) => vec![addr], ++ None => vec![], ++ } ++ } else { ++ match lookup_host_v6(node_str) { ++ Ok(addrs) => addrs, ++ Err(_) => vec![], + } + } ++ } else { ++ vec![] + }; + +- for in_addr in lookuphost { +- ai_family = AF_INET; +- ai_protocol = 0; ++ if lookuphost_v4.is_empty() && lookuphost_v6.is_empty() { ++ return EAI_NONAME; ++ } + ++ for addr in lookuphost_v4 { + let ai_addr = Box::into_raw(Box::new(sockaddr_in { +- sin_family: ai_family as sa_family_t, ++ sin_family: AF_INET as sa_family_t, + sin_port: htons(port), +- sin_addr: in_addr, ++ sin_addr: addr, + sin_zero: [0; 8], + })) + .cast::(); +@@ -939,9 +965,53 @@ pub unsafe extern "C" fn getaddrinfo( + + let addrinfo = Box::new(addrinfo { + ai_flags: 0, +- ai_family, ++ ai_family: AF_INET, + ai_socktype, +- ai_protocol, ++ ai_protocol: 0, ++ ai_addrlen, ++ ai_canonname, ++ ai_addr, ++ ai_next: ptr::null_mut(), ++ }); ++ unsafe { ++ let mut indirect = res; ++ while !(*indirect).is_null() { ++ indirect = &raw mut (**indirect).ai_next; ++ } ++ *indirect = Box::into_raw(addrinfo) ++ } ++ } ++ ++ for addr in lookuphost_v6 { ++ let mut s6_addr = [0u8; 16]; ++ s6_addr.copy_from_slice(&addr.s6_addr); ++ ++ let ai_addr = Box::into_raw(Box::new(sockaddr_in6 { ++ sin6_family: AF_INET6 as sa_family_t, ++ sin6_port: htons(port), ++ sin6_flowinfo: 0, ++ sin6_addr: in6_addr { s6_addr }, ++ sin6_scope_id: 0, ++ })) ++ .cast::(); ++ ++ let ai_addrlen = mem::size_of::() as socklen_t; ++ ++ 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() ++ }; ++ ++ let addrinfo = Box::new(addrinfo { ++ ai_flags: 0, ++ ai_family: AF_INET6, ++ ai_socktype, ++ ai_protocol: 0, + ai_addrlen, + ai_canonname, + ai_addr, +@@ -970,10 +1040,56 @@ pub unsafe extern "C" fn getnameinfo( + servlen: socklen_t, + flags: c_int, + ) -> c_int { +- if addr.is_null() || addrlen as usize != mem::size_of::() { ++ if addr.is_null() { ++ return EAI_FAMILY; ++ } ++ ++ let addrlen_usize = addrlen as usize; ++ if addrlen_usize != mem::size_of::() ++ && addrlen_usize != mem::size_of::() ++ { + return EAI_FAMILY; + } + ++ if addrlen_usize == mem::size_of::() { ++ let sa = unsafe { &*(addr.cast::()) }; ++ ++ if !serv.is_null() && servlen > 0 { ++ if flags & NI_NUMERICSERV != 0 { ++ let port_str = sa.sin6_port.to_be().to_string(); ++ let port_bytes = port_str.as_bytes(); ++ if (servlen as usize) <= port_bytes.len() { ++ return EAI_MEMORY; ++ } ++ unsafe { ++ ptr::copy_nonoverlapping( ++ port_bytes.as_ptr().cast::(), ++ serv, ++ port_bytes.len(), ++ ) ++ }; ++ unsafe { *serv.add(port_bytes.len()) = 0 }; ++ } else { ++ unsafe { *serv = 0 }; ++ } ++ } ++ ++ if !host.is_null() && hostlen > 0 { ++ let ip_addr = Ipv6Addr::from(sa.sin6_addr.s6_addr); ++ let ip_str = ip_addr.to_string(); ++ let ip_bytes = ip_str.as_bytes(); ++ if (hostlen as usize) <= ip_bytes.len() { ++ return EAI_MEMORY; ++ } ++ unsafe { ++ ptr::copy_nonoverlapping(ip_bytes.as_ptr().cast::(), host, ip_bytes.len()) ++ }; ++ unsafe { *host.add(ip_bytes.len()) = 0 }; ++ } ++ ++ return 0; ++ } ++ + let sa = unsafe { &*(addr.cast::()) }; + + if !serv.is_null() && servlen > 0 { diff --git a/local/patches/relibc/P3-inet6-pton-ntop.patch b/local/patches/relibc/P3-inet6-pton-ntop.patch new file mode 100644 index 00000000..14440eec --- /dev/null +++ b/local/patches/relibc/P3-inet6-pton-ntop.patch @@ -0,0 +1,292 @@ +diff --git a/src/header/arpa_inet/mod.rs b/src/header/arpa_inet/mod.rs +index e982353f..56806d4a 100644 +--- a/src/header/arpa_inet/mod.rs ++++ b/src/header/arpa_inet/mod.rs +@@ -2,6 +2,7 @@ + //! + //! See . + ++use alloc::{string::String, vec::Vec}; + use core::{ + ptr, slice, + str::{self, FromStr}, +@@ -13,8 +14,8 @@ use crate::{ + bits_arpainet::ntohl, + bits_socklen_t::socklen_t, + errno::{EAFNOSUPPORT, ENOSPC}, +- netinet_in::{INADDR_NONE, in_addr, in_addr_t}, +- sys_socket::constants::AF_INET, ++ netinet_in::{INADDR_NONE, INET6_ADDRSTRLEN, in6_addr, in_addr, in_addr_t}, ++ sys_socket::constants::{AF_INET, AF_INET6}, + }, + platform::{ + self, +@@ -181,34 +182,111 @@ pub unsafe extern "C" fn inet_ntop( + dst: *mut c_char, + size: socklen_t, + ) -> *const c_char { +- if af != AF_INET { +- platform::ERRNO.set(EAFNOSUPPORT); +- ptr::null() +- } else if size < 16 { +- platform::ERRNO.set(ENOSPC); +- ptr::null() +- } else { +- let s_addr = unsafe { +- slice::from_raw_parts( +- ptr::from_ref(&(*(src.cast::())).s_addr).cast::(), +- 4, +- ) +- }; +- let addr = format!("{}.{}.{}.{}\0", s_addr[0], s_addr[1], s_addr[2], s_addr[3]); ++ if af == AF_INET6 { ++ if size < INET6_ADDRSTRLEN as socklen_t { ++ platform::ERRNO.set(ENOSPC); ++ return ptr::null(); ++ } ++ let s6_addr = unsafe { &(*(src.cast::())).s6_addr }; ++ let output = inet_ntop6(s6_addr); ++ let bytes = output.as_bytes(); + unsafe { +- ptr::copy(addr.as_ptr().cast::(), dst, addr.len()); ++ ptr::copy(bytes.as_ptr().cast::(), dst, bytes.len()); ++ *dst.add(bytes.len()) = 0; + } + dst ++ } else if af == AF_INET { ++ if size < 16 { ++ platform::ERRNO.set(ENOSPC); ++ ptr::null() ++ } else { ++ let s_addr = unsafe { ++ slice::from_raw_parts( ++ ptr::from_ref(&(*(src.cast::())).s_addr).cast::(), ++ 4, ++ ) ++ }; ++ let addr = format!("{}.{}.{}.{}\0", s_addr[0], s_addr[1], s_addr[2], s_addr[3]); ++ unsafe { ++ ptr::copy(addr.as_ptr().cast::(), dst, addr.len()); ++ } ++ dst ++ } ++ } else { ++ platform::ERRNO.set(EAFNOSUPPORT); ++ ptr::null() ++ } ++} ++ ++fn inet_ntop6(addr: &[u8; 16]) -> String { ++ let groups: [u16; 8] = core::array::from_fn(|i| { ++ u16::from_be_bytes([addr[i * 2], addr[i * 2 + 1]]) ++ }); ++ ++ let mut best_start = 8usize; ++ let mut best_len = 1usize; ++ let mut cur_start = 8usize; ++ let mut cur_len = 0usize; ++ ++ for i in 0..8 { ++ if groups[i] == 0 { ++ if cur_len == 0 { ++ cur_start = i; ++ } ++ cur_len += 1; ++ } else { ++ if cur_len > best_len { ++ best_start = cur_start; ++ best_len = cur_len; ++ } ++ cur_len = 0; ++ } ++ } ++ if cur_len > best_len { ++ best_start = cur_start; ++ best_len = cur_len; ++ } ++ ++ let mut parts = Vec::new(); ++ let mut i = 0usize; ++ while i < 8 { ++ if i == best_start && best_len > 1 { ++ if i == 0 { ++ parts.push(String::new()); ++ } ++ if i + best_len == 8 { ++ parts.push(String::new()); ++ } ++ i += best_len; ++ } else { ++ parts.push(format!("{:x}", groups[i])); ++ i += 1; ++ } ++ } ++ ++ if best_len == 8 { ++ return String::from("::"); + } ++ ++ parts.join(":") + } + + /// See . + #[unsafe(no_mangle)] + pub unsafe extern "C" fn inet_pton(af: c_int, src: *const c_char, dst: *mut c_void) -> c_int { +- if af != AF_INET { +- platform::ERRNO.set(EAFNOSUPPORT); +- -1 +- } else { ++ if af == AF_INET6 { ++ let src_cstr = unsafe { CStr::from_ptr(src) }; ++ let src_str = match src_cstr.to_str() { ++ Ok(s) => s, ++ Err(_) => return 0, ++ }; ++ let out = unsafe { &mut *(dst.cast::()) }; ++ if inet_pton6(src_str, &mut out.s6_addr) { ++ 1 ++ } else { ++ 0 ++ } ++ } else if af == AF_INET { + let s_addr = unsafe { + slice::from_raw_parts_mut( + ptr::from_mut(&mut (*dst.cast::()).s_addr).cast::(), +@@ -233,5 +311,137 @@ pub unsafe extern "C" fn inet_pton(af: c_int, src: *const c_char, dst: *mut c_vo + } else { + 0 + } ++ } else { ++ platform::ERRNO.set(EAFNOSUPPORT); ++ -1 ++ } ++} ++ ++fn inet_pton6(src: &str, dst: &mut [u8; 16]) -> bool { ++ dst.fill(0); ++ ++ let double_colon_pos = src.find("::"); ++ let second_double = if let Some(pos) = double_colon_pos { ++ src[pos + 2..].find("::").map(|p| p + pos + 2) ++ } else { ++ None ++ }; ++ if second_double.is_some() { ++ return false; ++ } ++ ++ let (left_str, right_str) = match double_colon_pos { ++ Some(pos) => (&src[..pos], &src[pos + 2..]), ++ None => (src, ""), ++ }; ++ ++ let left_groups: Vec<&str> = if left_str.is_empty() { ++ Vec::new() ++ } else { ++ left_str.split(':').collect() ++ }; ++ let right_groups: Vec<&str> = if right_str.is_empty() { ++ Vec::new() ++ } else { ++ right_str.split(':').collect() ++ }; ++ ++ let right_has_ipv4 = right_groups.last().is_some_and(|g| g.contains('.')); ++ let mut left_count = left_groups.len(); ++ let mut right_count = right_groups.len(); ++ if right_has_ipv4 { ++ right_count -= 1; ++ left_count += 1; ++ } ++ ++ let gap = 8 - left_count - right_count; ++ if double_colon_pos.is_none() && gap != 0 { ++ return false; ++ } ++ if double_colon_pos.is_some() && gap < 0 { ++ return false; ++ } ++ if double_colon_pos.is_none() && left_groups.len() + right_groups.len() != 8 { ++ return false; ++ } ++ ++ let mut idx = 0usize; ++ ++ for group in &left_groups { ++ if idx >= 16 { ++ return false; ++ } ++ let val = match parse_hex_group(group) { ++ Some(v) => v, ++ None => return false, ++ }; ++ dst[idx] = (val >> 8) as u8; ++ dst[idx + 1] = val as u8; ++ idx += 2; ++ } ++ ++ if double_colon_pos.is_some() { ++ for _ in 0..gap { ++ if idx >= 16 { ++ return false; ++ } ++ dst[idx] = 0; ++ dst[idx + 1] = 0; ++ idx += 2; ++ } ++ } ++ ++ let right_hex_count = if right_has_ipv4 { ++ right_groups.len().saturating_sub(1) ++ } else { ++ right_groups.len() ++ }; ++ ++ for group in &right_groups[..right_hex_count] { ++ if idx >= 16 { ++ return false; ++ } ++ let val = match parse_hex_group(group) { ++ Some(v) => v, ++ None => return false, ++ }; ++ dst[idx] = (val >> 8) as u8; ++ dst[idx + 1] = val as u8; ++ idx += 2; ++ } ++ ++ if right_has_ipv4 { ++ if idx != 12 { ++ return false; ++ } ++ let ipv4_str = right_groups[right_groups.len() - 1]; ++ let parts: Vec<&str> = ipv4_str.split('.').collect(); ++ if parts.len() != 4 { ++ return false; ++ } ++ for (i, part) in parts.iter().enumerate() { ++ match u8::from_str(part) { ++ Ok(v) => dst[12 + i] = v, ++ Err(_) => return false, ++ } ++ } ++ idx += 4; ++ } ++ ++ idx == 16 ++} ++ ++fn parse_hex_group(s: &str) -> Option { ++ if s.is_empty() || s.len() > 4 { ++ return None; ++ } ++ let mut val: u16 = 0; ++ for c in s.chars() { ++ val = val.checked_mul(16)?; ++ match c.to_digit(16) { ++ Some(d) => val = val.checked_add(d as u16)?, ++ None => return None, ++ } + } ++ Some(val) + } diff --git a/local/patches/relibc/P3-tcp-nodelay.patch b/local/patches/relibc/P3-tcp-nodelay.patch index 340806a7..8c65eee6 100644 --- a/local/patches/relibc/P3-tcp-nodelay.patch +++ b/local/patches/relibc/P3-tcp-nodelay.patch @@ -10,9 +10,22 @@ index ec42889b..c91ffb1a 100644 +pub const IPPROTO_TCP: c_int = 6; +pub const TCP_NODELAY: c_int = 1; diff --git a/src/platform/redox/socket.rs b/src/platform/redox/socket.rs -index d223c36f..5e17a2e5 100644 +index d223c36f..2faae4f5 100644 --- a/src/platform/redox/socket.rs +++ b/src/platform/redox/socket.rs +@@ -1051,10 +1051,10 @@ impl PalSocket for Sys { + _ => { + let metadata = [SocketCall::SetSockOpt as u64, option_name as u64]; + let payload = unsafe { +- slice::from_raw_parts_mut(option_value as *mut u8, option_len as usize) ++ slice::from_raw_parts(option_value as *const u8, option_len as usize) + }; + let call_flags = CallFlags::empty(); +- redox_rt::sys::sys_call_rw( ++ redox_rt::sys::sys_call_wo( + socket as usize, + payload, + CallFlags::empty(), @@ -1063,6 +1063,24 @@ impl PalSocket for Sys { return Ok(()); } @@ -22,9 +35,9 @@ index d223c36f..5e17a2e5 100644 + crate::header::sys_socket::constants::TCP_NODELAY => { + let metadata = [SocketCall::SetSockOpt as u64, option_name as u64]; + let payload = unsafe { -+ slice::from_raw_parts_mut(option_value as *mut u8, option_len as usize) ++ slice::from_raw_parts(option_value as *const u8, option_len as usize) + }; -+ redox_rt::sys::sys_call_rw( ++ redox_rt::sys::sys_call_wo( + socket as usize, + payload, + CallFlags::empty(), diff --git a/local/patches/relibc/P3-tcp-sockopt-forward.patch b/local/patches/relibc/P3-tcp-sockopt-forward.patch new file mode 100644 index 00000000..793f6ebc --- /dev/null +++ b/local/patches/relibc/P3-tcp-sockopt-forward.patch @@ -0,0 +1,59 @@ +diff --git a/src/platform/redox/socket.rs b/src/platform/redox/socket.rs +index d223c36f..f8a1c2e0 100644 +--- a/src/platform/redox/socket.rs ++++ b/src/platform/redox/socket.rs +@@ -774,6 +774,21 @@ impl PalSocket for Sys { + return Ok(()); + } + }, ++ crate::header::sys_socket::constants::IPPROTO_TCP => { ++ let metadata = [SocketCall::GetSockOpt as u64, option_name as u64]; ++ let payload = ++ unsafe { slice::from_raw_parts_mut(option_value as *mut u8, option_len) }; ++ let call_flags = CallFlags::empty(); ++ unsafe { ++ *option_len_ptr = redox_rt::sys::sys_call_ro( ++ socket as usize, ++ payload, ++ CallFlags::empty(), ++ &metadata, ++ )? as socklen_t; ++ } ++ return Ok(()); ++ } + _ => (), + } + +@@ -1069,18 +1069,13 @@ impl PalSocket for Sys { + crate::header::sys_socket::constants::IPPROTO_TCP => { +- match option_name { +- crate::header::sys_socket::constants::TCP_NODELAY => { +- let metadata = [SocketCall::SetSockOpt as u64, option_name as u64]; +- let payload = unsafe { +- slice::from_raw_parts(option_value as *const u8, option_len as usize) +- }; +- redox_rt::sys::sys_call_wo( +- socket as usize, +- payload, +- CallFlags::empty(), +- &metadata, +- )?; +- return Ok(()); +- } +- _ => (), +- } ++ let metadata = [SocketCall::SetSockOpt as u64, option_name as u64]; ++ let payload = unsafe { ++ slice::from_raw_parts(option_value as *const u8, option_len as usize) ++ }; ++ redox_rt::sys::sys_call_wo( ++ socket as usize, ++ payload, ++ CallFlags::empty(), ++ &metadata, ++ )?; ++ return Ok(()); + } + _ => (), + } + diff --git a/recipes/core/relibc/recipe.toml b/recipes/core/relibc/recipe.toml index 7b53b8d7..dc65c846 100644 --- a/recipes/core/relibc/recipe.toml +++ b/recipes/core/relibc/recipe.toml @@ -37,6 +37,9 @@ patches = [ "../../../local/patches/relibc/P3-fenv.patch", "../../../local/patches/relibc/P3-sched.patch", "../../../local/patches/relibc/P3-aio.patch", + "../../../local/patches/relibc/P3-inet6-pton-ntop.patch", + "../../../local/patches/relibc/P3-tcp-sockopt-forward.patch", + "../../../local/patches/relibc/P3-dns-aaaa-getaddrinfo-ipv6.patch", ] [build]