1 use core::{mem, ptr, slice, str}; 2 use syscall::{self, flag::*, Result}; 3 4 use super::{ 5 super::{errno, types::*, Pal, PalSocket}, 6 e, Sys, 7 }; 8 use crate::header::{ 9 netinet_in::{in_port_t, sockaddr_in}, 10 sys_socket::{constants::*, sockaddr, socklen_t}, 11 sys_time::timeval, 12 sys_un::sockaddr_un, 13 }; 14 15 macro_rules! bind_or_connect { 16 (bind $path:expr) => { 17 concat!("/", $path) 18 }; 19 (connect $path:expr) => { 20 $path 21 }; 22 ($mode:ident into, $socket:expr, $address:expr, $address_len:expr) => {{ 23 let fd = bind_or_connect!($mode copy, $socket, $address, $address_len); 24 25 let result = syscall::dup2(fd, $socket as usize, &[]); 26 let _ = syscall::close(fd); 27 if (e(result) as c_int) < 0 { 28 return -1; 29 } 30 0 31 }}; 32 ($mode:ident copy, $socket:expr, $address:expr, $address_len:expr) => {{ 33 if ($address_len as usize) < mem::size_of::<sockaddr>() { 34 errno = syscall::EINVAL; 35 return -1; 36 } 37 38 let path = match (*$address).sa_family as c_int { 39 AF_INET => { 40 let data = &*($address as *const sockaddr_in); 41 let addr = slice::from_raw_parts( 42 &data.sin_addr.s_addr as *const _ as *const u8, 43 mem::size_of_val(&data.sin_addr.s_addr), 44 ); 45 let port = in_port_t::from_be(data.sin_port); 46 let path = format!( 47 bind_or_connect!($mode "{}.{}.{}.{}:{}"), 48 addr[0], 49 addr[1], 50 addr[2], 51 addr[3], 52 port 53 ); 54 55 path 56 }, 57 AF_UNIX => { 58 let data = &*($address as *const sockaddr_un); 59 let addr = slice::from_raw_parts( 60 &data.sun_path as *const _ as *const u8, 61 mem::size_of_val(&data.sun_path), 62 ); 63 let path = format!( 64 "{}", 65 str::from_utf8(addr).unwrap() 66 ); 67 68 path 69 }, 70 _ => { 71 errno = syscall::EAFNOSUPPORT; 72 return -1; 73 }, 74 }; 75 76 // Duplicate the socket, and then duplicate the copy back to the original fd 77 let fd = e(syscall::dup($socket as usize, path.as_bytes())); 78 if (fd as c_int) < 0 { 79 return -1; 80 } 81 fd 82 }}; 83 } 84 85 unsafe fn inner_af_unix(buf: &[u8], address: *mut sockaddr, address_len: *mut socklen_t) { 86 let data = &mut *(address as *mut sockaddr_un); 87 88 data.sun_family = AF_UNIX as c_ushort; 89 90 let path = slice::from_raw_parts_mut( 91 &mut data.sun_path as *mut _ as *mut u8, 92 mem::size_of_val(&data.sun_path), 93 ); 94 95 let len = path.len().min(buf.len()); 96 path[..len].copy_from_slice(&buf[..len]); 97 98 *address_len = len as socklen_t; 99 } 100 101 unsafe fn inner_af_inet( 102 local: bool, 103 buf: &[u8], 104 address: *mut sockaddr, 105 address_len: *mut socklen_t, 106 ) { 107 let mut parts = buf.split(|c| *c == b'/'); 108 if local { 109 // Skip the remote part 110 parts.next(); 111 } 112 let part = parts.next().expect("Invalid reply from netstack"); 113 114 trace!("path: {}", ::core::str::from_utf8_unchecked(&part)); 115 116 (*address).sa_family = AF_INET as c_ushort; 117 118 let data = slice::from_raw_parts_mut( 119 &mut (*address).sa_data as *mut _ as *mut u8, 120 (*address).sa_data.len(), 121 ); 122 123 let len = data.len().min(part.len()); 124 data[..len].copy_from_slice(&part[..len]); 125 126 *address_len = len as socklen_t; 127 } 128 129 unsafe fn inner_get_name( 130 local: bool, 131 socket: c_int, 132 address: *mut sockaddr, 133 address_len: *mut socklen_t, 134 ) -> Result<usize> { 135 // 32 should probably be large enough. 136 // Format: [udp|tcp:]remote/local, chan:path 137 let mut buf = [0; 32]; 138 let len = syscall::fpath(socket as usize, &mut buf)?; 139 let buf = &buf[..len]; 140 assert!(&buf[..4] == b"tcp:" || &buf[..4] == b"udp:" || &buf[..5] == b"chan:"); 141 142 match &buf[..5] { 143 b"tcp:" | b"udp:" => { 144 inner_af_inet(local, &buf[4..], address, address_len); 145 } 146 b"chan:" => { 147 inner_af_unix(&buf[5..], address, address_len); 148 } 149 // Socket doesn't belong to any scheme 150 _ => panic!("socket doesn't match either tcp, udp or chan schemes"), 151 }; 152 153 Ok(0) 154 } 155 156 impl PalSocket for Sys { 157 unsafe fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int { 158 let stream = e(syscall::dup(socket as usize, b"listen")) as c_int; 159 if stream < 0 { 160 return -1; 161 } 162 if address != ptr::null_mut() 163 && address_len != ptr::null_mut() 164 && Self::getpeername(stream, address, address_len) < 0 165 { 166 return -1; 167 } 168 stream 169 } 170 171 unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int { 172 bind_or_connect!(bind into, socket, address, address_len) 173 } 174 175 unsafe fn connect(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int { 176 bind_or_connect!(connect into, socket, address, address_len) 177 } 178 179 unsafe fn getpeername( 180 socket: c_int, 181 address: *mut sockaddr, 182 address_len: *mut socklen_t, 183 ) -> c_int { 184 e(inner_get_name(false, socket, address, address_len)) as c_int 185 } 186 187 unsafe fn getsockname( 188 socket: c_int, 189 address: *mut sockaddr, 190 address_len: *mut socklen_t, 191 ) -> c_int { 192 e(inner_get_name(true, socket, address, address_len)) as c_int 193 } 194 195 fn getsockopt( 196 socket: c_int, 197 level: c_int, 198 option_name: c_int, 199 option_value: *mut c_void, 200 option_len: *mut socklen_t, 201 ) -> c_int { 202 match level { 203 SOL_SOCKET => match option_name { 204 SO_ERROR => { 205 if option_value.is_null() { 206 return e(Err(syscall::Error::new(syscall::EFAULT))) as c_int; 207 } 208 209 if (option_len as usize) < mem::size_of::<c_int>() { 210 return e(Err(syscall::Error::new(syscall::EINVAL))) as c_int; 211 } 212 213 let error = unsafe { &mut *(option_value as *mut c_int) }; 214 //TODO: Socket nonblock connection error 215 *error = 0; 216 217 return 0; 218 }, 219 _ => (), 220 }, 221 _ => (), 222 } 223 224 eprintln!( 225 "getsockopt({}, {}, {}, {:p}, {:p})", 226 socket, level, option_name, option_value, option_len 227 ); 228 e(Err(syscall::Error::new(syscall::ENOSYS))) as c_int 229 } 230 231 fn listen(socket: c_int, backlog: c_int) -> c_int { 232 // Redox has no need to listen 233 0 234 } 235 236 unsafe fn recvfrom( 237 socket: c_int, 238 buf: *mut c_void, 239 len: size_t, 240 flags: c_int, 241 address: *mut sockaddr, 242 address_len: *mut socklen_t, 243 ) -> ssize_t { 244 if flags != 0 { 245 errno = syscall::EOPNOTSUPP; 246 return -1; 247 } 248 if address == ptr::null_mut() || address_len == ptr::null_mut() { 249 Self::read(socket, slice::from_raw_parts_mut(buf as *mut u8, len)) 250 } else { 251 let fd = e(syscall::dup(socket as usize, b"listen")); 252 if fd == !0 { 253 return -1; 254 } 255 if Self::getpeername(fd as c_int, address, address_len) < 0 { 256 let _ = syscall::close(fd); 257 return -1; 258 } 259 260 let ret = Self::read(fd as c_int, slice::from_raw_parts_mut(buf as *mut u8, len)); 261 let _ = syscall::close(fd); 262 ret 263 } 264 } 265 266 unsafe fn sendto( 267 socket: c_int, 268 buf: *const c_void, 269 len: size_t, 270 flags: c_int, 271 dest_addr: *const sockaddr, 272 dest_len: socklen_t, 273 ) -> ssize_t { 274 if flags != 0 { 275 errno = syscall::EOPNOTSUPP; 276 return -1; 277 } 278 if dest_addr == ptr::null() || dest_len == 0 { 279 Self::write(socket, slice::from_raw_parts(buf as *const u8, len)) 280 } else { 281 let fd = bind_or_connect!(connect copy, socket, dest_addr, dest_len); 282 let ret = Self::write(fd as c_int, slice::from_raw_parts(buf as *const u8, len)); 283 let _ = syscall::close(fd); 284 ret 285 } 286 } 287 288 fn setsockopt( 289 socket: c_int, 290 level: c_int, 291 option_name: c_int, 292 option_value: *const c_void, 293 option_len: socklen_t, 294 ) -> c_int { 295 let set_timeout = |timeout_name: &[u8]| -> c_int { 296 if option_value.is_null() { 297 return e(Err(syscall::Error::new(syscall::EFAULT))) as c_int; 298 } 299 300 if (option_len as usize) < mem::size_of::<timeval>() { 301 return e(Err(syscall::Error::new(syscall::EINVAL))) as c_int; 302 } 303 304 let timeval = unsafe { &*(option_value as *const timeval) }; 305 306 let fd = e(syscall::dup(socket as usize, timeout_name)); 307 if fd == !0 { 308 return -1; 309 } 310 311 let timespec = syscall::TimeSpec { 312 tv_sec: timeval.tv_sec, 313 tv_nsec: timeval.tv_usec * 1000, 314 }; 315 316 let ret = Self::write(fd as c_int, ×pec); 317 318 let _ = syscall::close(fd); 319 320 if ret >= 0 { 321 0 322 } else { 323 -1 324 } 325 }; 326 327 match level { 328 SOL_SOCKET => match option_name { 329 SO_RCVTIMEO => return set_timeout(b"read_timeout"), 330 SO_SNDTIMEO => return set_timeout(b"write_timeout"), 331 _ => (), 332 }, 333 _ => (), 334 } 335 336 eprintln!( 337 "setsockopt({}, {}, {}, {:p}, {})", 338 socket, level, option_name, option_value, option_len 339 ); 340 e(Err(syscall::Error::new(syscall::ENOSYS))) as c_int 341 } 342 343 fn shutdown(socket: c_int, how: c_int) -> c_int { 344 eprintln!("shutdown({}, {})", socket, how); 345 e(Err(syscall::Error::new(syscall::ENOSYS))) as c_int 346 } 347 348 unsafe fn socket(domain: c_int, mut kind: c_int, protocol: c_int) -> c_int { 349 if domain != AF_INET && domain != AF_UNIX { 350 errno = syscall::EAFNOSUPPORT; 351 return -1; 352 } 353 // if protocol != 0 { 354 // errno = syscall::EPROTONOSUPPORT; 355 // return -1; 356 // } 357 358 let mut flags = O_RDWR; 359 if kind & SOCK_NONBLOCK == SOCK_NONBLOCK { 360 kind &= !SOCK_NONBLOCK; 361 flags |= O_NONBLOCK; 362 } 363 if kind & SOCK_CLOEXEC == SOCK_CLOEXEC { 364 kind &= !SOCK_CLOEXEC; 365 flags |= O_CLOEXEC; 366 } 367 368 // The tcp: and udp: schemes allow using no path, 369 // and later specifying one using `dup`. 370 match (domain, kind) { 371 (AF_INET, SOCK_STREAM) => e(syscall::open("tcp:", flags)) as c_int, 372 (AF_INET, SOCK_DGRAM) => e(syscall::open("udp:", flags)) as c_int, 373 (AF_UNIX, SOCK_STREAM) => e(syscall::open("chan:", flags | O_CREAT)) as c_int, 374 _ => { 375 errno = syscall::EPROTONOSUPPORT; 376 -1 377 } 378 } 379 } 380 381 fn socketpair(domain: c_int, kind: c_int, protocol: c_int, sv: &mut [c_int; 2]) -> c_int { 382 eprintln!( 383 "socketpair({}, {}, {}, {:p})", 384 domain, 385 kind, 386 protocol, 387 sv.as_mut_ptr() 388 ); 389 unsafe { errno = syscall::ENOSYS }; 390 return -1; 391 } 392 } 393