1use alloc::vec::Vec;
2use core::{cmp, mem, ptr, slice, str};
3use redox_protocols::protocol::{FsCall, O_CLOEXEC, SocketCall};
4use redox_rt::proc::FdGuard;
5use syscall::{self, flag::*};
6
7use super::{
8 super::{Pal, PalSocket, types::*},
9 Sys,
10 path::dir_path_and_fd_path,
11};
12use crate::{
13 error::{Errno, Result},
14 header::{
15 arpa_inet::inet_aton,
16 bits_safamily_t::sa_family_t,
17 bits_ucred::ucred,
18 errno::{
19 EAFNOSUPPORT, EDOM, EFAULT, EINVAL, EMSGSIZE, ENOMEM, ENOSYS, ENOTSOCK, EOPNOTSUPP,
20 EPROTONOSUPPORT,
21 },
22 netinet_in::{in_addr, in_port_t, sockaddr_in},
23 string::strnlen,
24 sys_select::timeval,
25 sys_socket::{
26 CMSG_ALIGN, CMSG_DATA, CMSG_FIRSTHDR, CMSG_LEN, CMSG_NXTHDR, CMSG_SPACE, cmsghdr,
27 constants::*, msghdr, sockaddr, socklen_t,
28 },
29 sys_uio::iovec,
30 sys_un::sockaddr_un,
31 },
32};
33
34unsafe fn bind_or_connect(
35 op: SocketCall,
36 socket: c_int,
37 address: *const sockaddr,
38 address_len: socklen_t,
39) -> Result<usize, Errno> {
40 if (address_len as usize) < mem::size_of::<sa_family_t>() {
41 return Err(Errno(EINVAL));
42 }
43
44 let path = match unsafe { (*address).sa_family } as c_int {
45 AF_INET => {
46 if (address_len as usize) != mem::size_of::<sockaddr_in>() {
47 return Err(Errno(EINVAL));
48 }
49
50 let data = unsafe { &*(address as *const sockaddr_in) };
51 let addr = unsafe {
52 slice::from_raw_parts(
53 &data.sin_addr.s_addr as *const _ as *const u8,
54 mem::size_of_val(&data.sin_addr.s_addr),
55 )
56 };
57 let port = in_port_t::from_be(data.sin_port);
58
59 match op {
60 SocketCall::Bind => {
61 format!("/{}.{}.{}.{}:{}", addr[0], addr[1], addr[2], addr[3], port)
62 }
63 SocketCall::Connect => {
64 format!("{}.{}.{}.{}:{}", addr[0], addr[1], addr[2], addr[3], port)
65 }
66 _ => unreachable!(),
67 }
68 }
69 AF_UNIX => {
70 log::warn!("bind/connect with AF_UNIX were replaced with SYS_CALL.");
71 return Err(Errno(EAFNOSUPPORT));
72 }
73 AF_UNSPEC => match op {
74 SocketCall::Bind => {
75 return Err(Errno(EAFNOSUPPORT));
77 }
78 SocketCall::Connect => {
79 format!("disconnect")
81 }
82 _ => unreachable!(),
83 },
84 _ => return Err(Errno(EAFNOSUPPORT)),
85 };
86 let fd = redox_rt::sys::dup(socket as usize, path.as_bytes())?;
87 Ok(fd)
88}
89
90pub unsafe fn bind_or_connect_into(
91 op: SocketCall,
92 socket: c_int,
93 address: *const sockaddr,
94 address_len: socklen_t,
95) -> Result<c_int, Errno> {
96 let fd = FdGuard::new(unsafe { bind_or_connect(op, socket, address, address_len) }?);
98 redox_rt::sys::dup2(fd.as_raw_fd(), socket as usize, &[])?;
99 Ok(0)
100}
101
102unsafe fn inner_af_unix(buf: &[u8], address: *mut sockaddr, address_len: *mut socklen_t) {
103 let data = unsafe { &mut *(address as *mut sockaddr_un) };
104
105 data.sun_family = AF_UNIX as c_ushort;
106
107 let path = unsafe {
108 slice::from_raw_parts_mut(&mut data.sun_path as *mut _ as *mut u8, data.sun_path.len())
109 };
110
111 let len = cmp::min(path.len(), buf.len());
112 path[..len].copy_from_slice(&buf[..len]);
113 if len < path.len() {
114 path[len] = 0;
115 }
116
117 unsafe { *address_len = len as socklen_t };
118}
119
120unsafe fn inner_af_inet(
121 local: bool,
122 buf: &[u8],
123 address: *mut sockaddr,
124 address_len: *mut socklen_t,
125) {
126 let mut parts = buf.split(|c| *c == b'/');
127 if local {
128 parts.next();
130 }
131 let mut unparsed_addr = Vec::from(parts.next().expect("missing address"));
132
133 let sep = memchr::memchr(b':', &unparsed_addr).expect("missing port");
134 let (raw_addr, rest) = unparsed_addr.split_at_mut(sep);
135 let (colon, raw_port) = rest.split_at_mut(1);
136 let port = str::from_utf8(raw_port)
137 .expect("non-utf8 port")
138 .parse()
139 .expect("invalid port");
140
141 colon[0] = b'\0';
143
144 log::trace!("address: {:?}, port: {:?}", str::from_utf8(&raw_addr), port);
145
146 let mut addr = in_addr::default();
147 assert_eq!(
148 unsafe { inet_aton(raw_addr.as_ptr() as *mut c_char, &mut addr) },
149 1,
150 "inet_aton might be broken, failed to parse netstack address"
151 );
152
153 let ret = sockaddr_in {
154 sin_family: AF_INET as sa_family_t,
155 sin_port: in_port_t::to_be(port),
156 sin_addr: addr,
157
158 ..sockaddr_in::default()
159 };
160 let len = cmp::min(unsafe { *address_len } as usize, mem::size_of_val(&ret));
161
162 unsafe {
163 ptr::copy_nonoverlapping(&ret as *const _ as *const u8, address as *mut u8, len);
164 *address_len = len as socklen_t;
165 }
166}
167
168unsafe fn inner_get_name_inner(
169 local: bool,
170 address: *mut sockaddr,
171 address_len: *mut socklen_t,
172 buf: &[u8],
173) -> Result<()> {
174 if buf.starts_with(b"tcp:") || buf.starts_with(b"udp:") {
175 unsafe { inner_af_inet(local, &buf[4..], address, address_len) };
176 } else if buf.starts_with(b"/scheme/tcp/") || buf.starts_with(b"/scheme/udp/") {
177 unsafe { inner_af_inet(local, &buf[12..], address, address_len) };
178 } else if buf.starts_with(b"chan:") {
179 unsafe { inner_af_unix(&buf[5..], address, address_len) };
180 } else if buf.starts_with(b"/scheme/chan/") {
181 unsafe { inner_af_unix(&buf[13..], address, address_len) };
182 } else if buf.starts_with(b"/scheme/uds_stream/") {
183 unsafe { inner_af_unix(&buf[19..], address, address_len) };
184 } else if buf.starts_with(b"/scheme/uds_dgram/") {
185 unsafe { inner_af_unix(&buf[18..], address, address_len) };
186 } else {
187 log::trace!(
189 "socket {:?} doesn't match either tcp, udp or chan schemes",
190 str::from_utf8(buf)
191 );
192 return Err(Errno(ENOTSOCK));
193 }
194 Ok(())
195}
196
197fn socket_domain_type(socket: c_int) -> Result<(c_int, c_int)> {
198 let mut buf = [0; 256];
199 let len = syscall::fpath(socket as usize, &mut buf)?;
200 Ok(
201 if buf.starts_with(b"tcp:") || buf.starts_with(b"/scheme/tcp/") {
202 (AF_INET, SOCK_STREAM)
203 } else if buf.starts_with(b"udp:") || buf.starts_with(b"/scheme/udp/") {
204 (AF_INET, SOCK_DGRAM)
205 } else if buf.starts_with(b"/scheme/uds_stream/") {
206 (AF_UNIX, SOCK_STREAM)
207 } else if buf.starts_with(b"/scheme/uds_dgram/") {
208 (AF_UNIX, SOCK_DGRAM)
209 } else {
210 return Err(Errno(ENOTSOCK));
211 },
212 )
213}
214
215fn socket_kind(mut kind: c_int) -> (c_int, usize) {
216 let mut flags = O_RDWR;
217 if kind & SOCK_NONBLOCK == SOCK_NONBLOCK {
218 kind &= !SOCK_NONBLOCK;
219 flags |= O_NONBLOCK;
220 }
221 if kind & SOCK_CLOEXEC == SOCK_CLOEXEC {
222 kind &= !SOCK_CLOEXEC;
223 flags |= O_CLOEXEC;
224 }
225 (kind, flags)
226}
227
228unsafe fn serialize_payload_to_stream(
229 msg_stream: &mut Vec<u8>,
230 iovs: &[iovec],
231 whole_iov_size: usize,
232) -> Result<usize> {
233 msg_stream.extend_from_slice(&whole_iov_size.to_le_bytes());
234
235 for iov in iovs {
236 if iov.iov_len > 0 {
237 if iov.iov_base.is_null() {
238 return Err(Errno(EFAULT));
239 }
240 let source_slice: &[u8] =
241 unsafe { slice::from_raw_parts(iov.iov_base as *const u8, iov.iov_len) };
242 msg_stream.extend_from_slice(source_slice);
243 }
244 }
245 Ok(whole_iov_size)
246}
247
248unsafe fn serialize_ancillary_data_to_stream(
249 msg: *const msghdr,
250 mhdr: &msghdr,
251 socket: c_int,
252 msg_stream: &mut Vec<u8>,
253) -> Result<()> {
254 if mhdr.msg_control.is_null() {
255 return Err(Errno(EINVAL));
256 }
257
258 let mut cmsg: *mut cmsghdr = unsafe { CMSG_FIRSTHDR(msg) };
259 while !cmsg.is_null() {
260 let current_cmsg = unsafe { &*cmsg };
261 let min_cmsg_len = unsafe { CMSG_ALIGN(mem::size_of::<cmsghdr>()) };
262 if current_cmsg.cmsg_len < min_cmsg_len {
263 return Err(Errno(EINVAL));
264 }
265
266 msg_stream.extend_from_slice(¤t_cmsg.cmsg_level.to_le_bytes());
268 msg_stream.extend_from_slice(¤t_cmsg.cmsg_type.to_le_bytes());
269
270 match (current_cmsg.cmsg_level, current_cmsg.cmsg_type) {
271 (SOL_SOCKET, SCM_RIGHTS) => {
272 let data_len = current_cmsg.cmsg_len - min_cmsg_len;
273 if data_len % mem::size_of::<c_int>() != 0 {
274 return Err(Errno(EINVAL));
275 }
276 let fd_count = data_len / mem::size_of::<c_int>();
277
278 if fd_count > 0 {
279 let fds_ptr = unsafe { CMSG_DATA(cmsg) } as *const c_int;
280 let c_fds = unsafe { slice::from_raw_parts(fds_ptr, fd_count) };
281 let fds_usize: Vec<usize> = c_fds.iter().map(|&fd| fd as usize).collect();
282 let fds_slice = unsafe {
283 slice::from_raw_parts(
284 fds_usize.as_ptr() as *const u8,
285 fds_usize.len() * mem::size_of::<usize>(),
286 )
287 };
288 redox_rt::sys::sys_call_wo(socket as usize, &fds_slice, CallFlags::FD, &[])?;
289 }
290
291 let data_for_stream_len = mem::size_of::<usize>();
294 let data_for_stream_payload = (fd_count as usize).to_le_bytes();
295
296 msg_stream.extend_from_slice(&(data_for_stream_len as usize).to_le_bytes());
297 msg_stream.extend_from_slice(&data_for_stream_payload);
298 }
299 (SOL_SOCKET, SCM_CREDENTIALS) => {
300 let data_for_stream_len = 0usize;
302 msg_stream.extend_from_slice(&(data_for_stream_len as usize).to_le_bytes());
303 }
304 _ => {
305 return Err(Errno(EOPNOTSUPP));
306 }
307 }
308 cmsg = unsafe { CMSG_NXTHDR(msg, cmsg) };
309 }
310 Ok(())
311}
312
313unsafe fn deserialize_name_from_stream(
314 mhdr: &mut msghdr,
315 msg_stream: &[u8],
316 cursor: &mut usize,
317) -> Result<()> {
318 let name_len_in_stream = read_num::<usize>(&msg_stream[*cursor..])?;
320 let name_len = cmp::min(name_len_in_stream, mhdr.msg_namelen as usize);
321 *cursor += mem::size_of::<usize>();
322
323 if name_len > 0 {
324 if *cursor + name_len > msg_stream.len() {
325 return Err(Errno(EMSGSIZE));
326 }
327 if !mhdr.msg_name.is_null() && mhdr.msg_namelen > 0 {
328 let name_buffer = &msg_stream[*cursor..*cursor + name_len_in_stream];
329 (unsafe {
330 inner_get_name_inner(
331 false,
332 mhdr.msg_name as *mut sockaddr,
333 &mut mhdr.msg_namelen,
334 name_buffer,
335 )
336 })?;
337 }
338 *cursor += name_len_in_stream;
339 } else {
340 mhdr.msg_namelen = 0;
342 }
343 Ok(())
344}
345
346unsafe fn deserialize_payload_from_stream(
347 mhdr: &mut msghdr,
348 msg_stream: &[u8],
349 iovs: &[iovec],
350 whole_iov_size: usize,
351 cursor: &mut usize,
352 test: u8,
353) -> Result<usize> {
354 let full_payload_len_from_scheme = read_num::<usize>(&msg_stream[*cursor..])?;
355 *cursor += mem::size_of::<usize>();
356 let payload_len_to_read = cmp::min(full_payload_len_from_scheme, whole_iov_size);
358 let payload_data_from_stream = &msg_stream[*cursor..*cursor + payload_len_to_read];
359 *cursor += payload_len_to_read;
360
361 let mut total_bytes_written: usize = 0;
362 if !iovs.is_empty() && payload_len_to_read > 0 {
363 let mut source_bytes_consumed: usize = 0;
364 for iov in iovs {
365 if iov.iov_len == 0 {
366 continue;
367 }
368 if iov.iov_base.is_null() {
369 return Err(Errno(EFAULT));
370 }
371
372 let source_bytes_remaining = payload_data_from_stream
373 .len()
374 .saturating_sub(source_bytes_consumed);
375 if source_bytes_remaining == 0 {
376 break;
377 }
378
379 let bytes_to_write = cmp::min(iov.iov_len, source_bytes_remaining);
380 if bytes_to_write > 0 {
381 let dest_slice: &mut [u8] =
382 unsafe { slice::from_raw_parts_mut(iov.iov_base as *mut u8, iov.iov_len) };
383
384 let source_sub_slice = &payload_data_from_stream
385 [source_bytes_consumed..source_bytes_consumed + bytes_to_write];
386 dest_slice[..bytes_to_write].copy_from_slice(source_sub_slice);
387 total_bytes_written += bytes_to_write;
388 source_bytes_consumed += bytes_to_write;
389 }
390 }
391 }
392
393 if full_payload_len_from_scheme > whole_iov_size {
394 mhdr.msg_flags |= MSG_TRUNC;
395 }
396
397 Ok(total_bytes_written)
398}
399
400unsafe fn deserialize_ancillary_data_from_stream(
401 mhdr: &mut msghdr,
402 socket: c_int,
403 msg_stream: &[u8],
404 cursor: &mut usize,
405 cmsg_space_provided: usize,
406 flags: c_int,
407) -> Result<()> {
408 let mut current_cmsg_ptr_in_user_buf = if !mhdr.msg_control.is_null() && cmsg_space_provided > 0
409 {
410 unsafe { CMSG_FIRSTHDR(mhdr) }
411 } else {
412 ptr::null_mut()
413 };
414 let mut remaining_user_cmsg_buf_len = cmsg_space_provided;
415 let mut total_csmg_bytes_written_to_user_buf: usize = 0;
416
417 while *cursor < msg_stream.len() {
418 const CMSG_HEADER_LEN_IN_STREAM: usize =
419 mem::size_of::<c_int>() * 2 + mem::size_of::<usize>();
420 if *cursor + CMSG_HEADER_LEN_IN_STREAM > msg_stream.len() {
421 if msg_stream[*cursor..].iter().any(|&b| b != 0) {
422 mhdr.msg_flags |= MSG_CTRUNC;
423 }
424 break;
425 }
426
427 let cmsg_level = read_num::<c_int>(&msg_stream[*cursor..])?;
429 *cursor += mem::size_of::<c_int>();
430 let cmsg_type = read_num::<c_int>(&msg_stream[*cursor..])?;
431 *cursor += mem::size_of::<c_int>();
432 let cmsg_data_len_in_stream = read_num::<usize>(&msg_stream[*cursor..])?;
433 *cursor += mem::size_of::<usize>();
434
435 if *cursor + cmsg_data_len_in_stream > msg_stream.len() {
436 mhdr.msg_flags |= MSG_CTRUNC;
437 break;
438 }
439
440 let cmsg_data_from_stream = &msg_stream[*cursor..*cursor + cmsg_data_len_in_stream];
441 *cursor += cmsg_data_len_in_stream;
442
443 let mut temp_posix_cmsg_data_buf: Vec<u8> = Vec::new();
444
445 let actual_posix_cmsg_data_len = match (cmsg_level, cmsg_type) {
446 (SOL_SOCKET, SCM_RIGHTS) => {
447 if cmsg_data_len_in_stream != mem::size_of::<usize>() {
448 return Err(Errno(EINVAL));
449 }
450 let fd_count = read_num::<usize>(&cmsg_data_from_stream)?;
451
452 let mut fds_usize = vec![0usize; fd_count];
453
454 let fds_bytes = unsafe {
455 slice::from_raw_parts_mut(
456 fds_usize.as_mut_ptr() as *mut u8,
457 fds_usize.len() * mem::size_of::<usize>(),
458 )
459 };
460
461 let mut call_flags = CallFlags::FD;
462 if flags & MSG_CMSG_CLOEXEC == MSG_CMSG_CLOEXEC {
463 call_flags |= CallFlags::FD_CLOEXEC;
464 }
465
466 redox_rt::sys::sys_call_ro(socket as usize, fds_bytes, call_flags, &[])?;
467
468 for fd in fds_usize {
469 temp_posix_cmsg_data_buf.extend_from_slice(&(fd as c_int).to_le_bytes());
470 }
471 temp_posix_cmsg_data_buf.len()
472 }
473 (SOL_SOCKET, SCM_CREDENTIALS) => {
474 if cmsg_data_len_in_stream
475 != mem::size_of::<pid_t>() + mem::size_of::<uid_t>() + mem::size_of::<gid_t>()
476 {
477 return Err(Errno(EINVAL));
478 }
479
480 let pid = read_num::<pid_t>(&cmsg_data_from_stream)?;
481 let uid_offset = mem::size_of::<pid_t>();
482 let uid = read_num::<uid_t>(&cmsg_data_from_stream[uid_offset..])?;
483 let gid_offset = uid_offset + mem::size_of::<uid_t>();
484 let gid = read_num::<gid_t>(&cmsg_data_from_stream[gid_offset..])?;
485 let cred = ucred { pid, uid, gid };
486
487 temp_posix_cmsg_data_buf.extend_from_slice(unsafe {
488 slice::from_raw_parts(
489 &cred as *const ucred as *const u8,
490 mem::size_of::<ucred>(),
491 )
492 });
493 temp_posix_cmsg_data_buf.len()
494 }
495 _ => {
496 return Err(Errno(EINVAL));
497 }
498 };
499
500 let space_needed_for_posix_cmsg =
501 unsafe { CMSG_SPACE(actual_posix_cmsg_data_len as u32) } as usize;
502
503 if !current_cmsg_ptr_in_user_buf.is_null()
504 && remaining_user_cmsg_buf_len >= space_needed_for_posix_cmsg
505 {
506 let cmsg_ref = unsafe { &mut *current_cmsg_ptr_in_user_buf };
507 cmsg_ref.cmsg_len = unsafe { CMSG_LEN(actual_posix_cmsg_data_len as u32) } as usize;
508 cmsg_ref.cmsg_level = cmsg_level;
509 cmsg_ref.cmsg_type = cmsg_type;
510
511 let data_ptr_in_user_cmsg = unsafe { CMSG_DATA(cmsg_ref) };
512 unsafe {
513 ptr::copy_nonoverlapping(
514 temp_posix_cmsg_data_buf.as_ptr(),
515 data_ptr_in_user_cmsg as *mut u8,
516 actual_posix_cmsg_data_len,
517 )
518 };
519
520 let aligned_len_written = unsafe { CMSG_ALIGN(cmsg_ref.cmsg_len) };
521 total_csmg_bytes_written_to_user_buf += aligned_len_written;
522 remaining_user_cmsg_buf_len -= aligned_len_written;
523 current_cmsg_ptr_in_user_buf =
524 unsafe { CMSG_NXTHDR(mhdr, current_cmsg_ptr_in_user_buf) };
525 } else {
526 mhdr.msg_flags |= MSG_CTRUNC;
527 break;
528 }
529 }
530 mhdr.msg_controllen = total_csmg_bytes_written_to_user_buf;
531 Ok(())
532}
533
534impl PalSocket for Sys {
535 unsafe fn accept(
536 socket: c_int,
537 address: *mut sockaddr,
538 address_len: *mut socklen_t,
539 ) -> Result<c_int> {
540 let stream = redox_rt::sys::dup(socket as usize, b"listen")?;
541 if address != ptr::null_mut() && address_len != ptr::null_mut() {
542 if let Err(err) = unsafe { Self::getpeername(stream as c_int, address, address_len) } {
543 let _ = redox_rt::sys::close(stream);
544 return Err(err);
545 }
546 }
547 Ok(stream as c_int)
548 }
549
550 unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> Result<()> {
551 match unsafe { (*address).sa_family } as c_int {
552 AF_INET => {
553 (unsafe { bind_or_connect_into(SocketCall::Bind, socket, address, address_len) })?;
554 }
555 AF_UNIX => {
556 let data = unsafe { &*(address as *const sockaddr_un) };
557
558 let maxlen = cmp::min(
562 data.sun_path.len(),
564 address_len as usize - data.path_offset(),
566 );
567 let len = cmp::min(
568 maxlen,
570 unsafe { strnlen(&data.sun_path as *const _, maxlen as size_t) },
572 );
573
574 let addr =
575 unsafe { slice::from_raw_parts(&data.sun_path as *const _ as *const u8, len) };
576 let path = format!("{}", str::from_utf8(addr).unwrap());
577 log::trace!("bind(): path: {:?}", path);
578
579 let (dir_path, fd_path) = dir_path_and_fd_path(&path)?;
580
581 redox_rt::sys::sys_call_wo(
582 socket as usize,
583 fd_path.as_bytes(),
584 CallFlags::empty(),
585 &[SocketCall::Bind as u64],
586 )?;
587
588 let fs_bind_result = (|| -> Result<()> {
589 let dirfd = FdGuard::open(
590 &dir_path,
591 syscall::O_RDONLY | syscall::O_DIRECTORY | O_CLOEXEC,
592 )?;
593 let fd_to_send =
594 FdGuard::new(redox_rt::sys::dup_into_upper(socket as usize, &[])?)
595 .to_upper()
596 .unwrap();
597 dirfd.call_wo(
598 &fd_to_send.as_raw_fd().to_ne_bytes(),
599 syscall::CallFlags::FD,
600 &[],
601 )?;
602 Ok(())
603 })();
604
605 if let Err(original_error) = fs_bind_result {
606 if let Err(unbind_error) = redox_rt::sys::sys_call_wo(
607 socket as usize,
608 &[],
609 CallFlags::empty(),
610 &[SocketCall::Unbind as u64],
611 ) {
612 todo_error!(
613 0,
614 unbind_error,
615 "bind: CRITICAL: failed to unbind socket after a failed transaction"
616 );
617 }
618
619 return Err(original_error);
620 }
621 }
622 _ => {
623 return Err(Errno(EAFNOSUPPORT));
624 }
625 };
626
627 Ok(())
628 }
629
630 unsafe fn connect(
631 socket: c_int,
632 address: *const sockaddr,
633 address_len: socklen_t,
634 ) -> Result<c_int> {
635 match unsafe { (*address).sa_family } as c_int {
636 AF_INET => unsafe {
637 bind_or_connect_into(SocketCall::Connect, socket, address, address_len)
638 },
639 AF_UNIX => {
640 let data = unsafe { &*(address as *const sockaddr_un) };
641
642 let maxlen = cmp::min(
646 data.sun_path.len(),
648 address_len as usize - data.path_offset(),
650 );
651 let len = cmp::min(
652 maxlen,
654 unsafe { strnlen(&data.sun_path as *const _, maxlen as size_t) },
656 );
657
658 let addr =
659 unsafe { slice::from_raw_parts(&data.sun_path as *const _ as *const u8, len) };
660 let path = format!("{}", str::from_utf8(addr).unwrap());
661 log::trace!("connect(): path: {:?}", path);
662
663 let (_, fd_path) = dir_path_and_fd_path(&path)?;
664
665 let target_path = format!("/{fd_path}");
666 let socket_file_fd = FdGuard::open(&target_path, syscall::O_RDWR)?;
667
668 const TOKEN_BUF_SIZE: usize = 16;
669
670 let mut token_buf = [0u8; TOKEN_BUF_SIZE];
671
672 redox_rt::sys::sys_call_ro(
673 socket_file_fd.as_raw_fd(),
674 &mut token_buf,
675 CallFlags::empty(),
676 &[FsCall::Connect as u64],
677 )?;
678
679 redox_rt::sys::sys_call_wo(
680 socket as usize,
681 &token_buf,
682 CallFlags::empty(),
683 &[SocketCall::Connect as u64],
684 )?;
685 Result::<c_int, Errno>::Ok(0)
686 }
687 AF_UNSPEC => unsafe {
688 bind_or_connect_into(SocketCall::Connect, socket, address, address_len)
689 },
690 _ => Err(Errno(EAFNOSUPPORT)),
691 }
692 }
693
694 unsafe fn getpeername(
695 socket: c_int,
696 address: *mut sockaddr,
697 address_len: *mut socklen_t,
698 ) -> Result<()> {
699 let mut buf = [0; 256];
700 let len = redox_rt::sys::sys_call_ro(
701 socket as usize,
702 &mut buf,
703 CallFlags::empty(),
704 &[SocketCall::GetPeerName as u64],
705 )?;
706
707 unsafe { inner_get_name_inner(false, address, address_len, &buf[..len]) }
708 }
709
710 unsafe fn getsockname(
711 socket: c_int,
712 address: *mut sockaddr,
713 address_len: *mut socklen_t,
714 ) -> Result<()> {
715 let mut buf = [0; 256];
716 let len = syscall::fpath(socket as usize, &mut buf)?;
717
718 unsafe { inner_get_name_inner(true, address, address_len, &buf[..len]) }
719 }
720
721 unsafe fn getsockopt(
722 socket: c_int,
723 level: c_int,
724 option_name: c_int,
725 option_value: *mut c_void,
726 option_len_ptr: *mut socklen_t,
727 ) -> Result<()> {
728 if option_len_ptr.is_null() {
729 return Err(Errno(EFAULT));
730 }
731 let option_len = (unsafe { *option_len_ptr }) as usize;
732
733 let option_c_int = || -> Result<&mut c_int> {
734 if option_value.is_null() {
735 return Err(Errno(EFAULT));
736 }
737
738 if option_len < mem::size_of::<c_int>() {
739 return Err(Errno(EINVAL));
740 }
741
742 Ok(unsafe { &mut *(option_value as *mut c_int) })
743 };
744
745 match level {
746 SOL_SOCKET => match option_name {
747 SO_DOMAIN => {
748 let option = option_c_int()?;
749 *option = socket_domain_type(socket)?.0;
750 unsafe { *option_len_ptr = mem::size_of::<c_int>() as socklen_t };
751 return Ok(());
752 }
753 SO_ERROR => {
754 let option = option_c_int()?;
755 *option = 0;
757 unsafe { *option_len_ptr = mem::size_of::<c_int>() as socklen_t };
758 return Ok(());
759 }
760 SO_TYPE => {
761 let option = option_c_int()?;
762 *option = socket_domain_type(socket)?.1;
763 unsafe { *option_len_ptr = mem::size_of::<c_int>() as socklen_t };
764 return Ok(());
765 }
766 _ => {
767 let metadata = [SocketCall::GetSockOpt as u64, option_name as u64];
768 let payload =
769 unsafe { slice::from_raw_parts_mut(option_value as *mut u8, option_len) };
770 let call_flags = CallFlags::empty();
771 unsafe {
772 *option_len_ptr = redox_rt::sys::sys_call_ro(
773 socket as usize,
774 payload,
775 CallFlags::empty(),
776 &metadata,
777 )? as socklen_t;
778 }
779 return Ok(());
780 }
781 },
782 _ => (),
783 }
784
785 todo_skip!(
786 0,
787 "getsockopt({}, {}, {}, {:p}, {:p})",
788 socket,
789 level,
790 option_name,
791 option_value,
792 option_len_ptr
793 );
794 Err(Errno(ENOSYS))
795 }
796
797 fn listen(socket: c_int, backlog: c_int) -> Result<()> {
798 Ok(())
800 }
801
802 unsafe fn recvfrom(
803 socket: c_int,
804 buf: *mut c_void,
805 len: size_t,
806 flags: c_int,
807 address: *mut sockaddr,
808 address_len: *mut socklen_t,
809 ) -> Result<usize> {
810 if address.is_null() && flags == 0 {
811 Self::read(socket, unsafe {
812 slice::from_raw_parts_mut(buf as *mut u8, len)
813 })
814 } else {
815 let mut iov = iovec {
817 iov_base: buf,
818 iov_len: len,
819 };
820 let mut msg = msghdr {
821 msg_name: address as *mut c_void,
822 msg_namelen: if !address_len.is_null() {
823 unsafe { *address_len }
824 } else {
825 0
826 },
827 msg_iov: &mut iov,
828 msg_iovlen: 1,
829 msg_control: ptr::null_mut(),
830 msg_controllen: 0,
831 msg_flags: 0,
832 };
833 let count = unsafe { Self::recvmsg(socket, &mut msg, flags) }?;
834 if !address_len.is_null() {
835 unsafe { *address_len = msg.msg_namelen };
836 }
837 return Ok(count);
838 }
839 }
840
841 unsafe fn recvmsg(socket: c_int, msg: *mut msghdr, flags: c_int) -> Result<usize> {
842 if msg.is_null() {
843 return Err(Errno(EINVAL));
844 }
845 let mut mhdr = unsafe { &mut *msg };
846 let iovs_slice: &[iovec] = if mhdr.msg_iov.is_null() || mhdr.msg_iovlen == 0 {
847 &[]
848 } else {
849 unsafe { slice::from_raw_parts(mhdr.msg_iov, mhdr.msg_iovlen as usize) }
850 };
851 let whole_iov_size: usize = iovs_slice.iter().map(|iov| iov.iov_len).sum();
852
853 let mut msg_stream: Vec<u8> = Vec::new();
854
855 let expected_stream_size = {
860 64 + mem::size_of::<usize>() + mhdr.msg_namelen as usize + mem::size_of::<usize>() + whole_iov_size + mem::size_of::<usize>() + mhdr.msg_controllen as usize };
868 msg_stream
869 .try_reserve_exact(expected_stream_size)
870 .map_err(|_| Errno(ENOMEM))?;
871 msg_stream.resize(expected_stream_size, 0);
872
873 let mut cursor: usize = 0;
875 msg_stream[cursor..cursor + mem::size_of::<usize>()]
876 .copy_from_slice(&(mhdr.msg_namelen as usize).to_le_bytes());
877 cursor += mem::size_of::<usize>();
878 msg_stream[cursor..cursor + mem::size_of::<usize>()]
879 .copy_from_slice(&(whole_iov_size).to_le_bytes());
880 cursor += mem::size_of::<usize>();
881 msg_stream[cursor..cursor + mem::size_of::<usize>()]
882 .copy_from_slice(&(mhdr.msg_controllen as usize).to_le_bytes());
883
884 let metadata = [SocketCall::RecvMsg as u64, flags as u64];
886 let call_flags = CallFlags::empty();
887 let actual_read_len =
888 redox_rt::sys::sys_call_rw(socket as usize, &mut msg_stream, call_flags, &metadata)?;
889 msg_stream.truncate(actual_read_len);
890
891 cursor = 0;
892 let cmsg_space_provided_by_user = mhdr.msg_controllen;
893 mhdr.msg_flags = 0;
894
895 (unsafe { deserialize_name_from_stream(&mut mhdr, &msg_stream, &mut cursor) })?;
897
898 let actual_payload_bytes_written_to_iov = unsafe {
900 deserialize_payload_from_stream(
901 &mut mhdr,
902 &msg_stream,
903 iovs_slice,
904 whole_iov_size,
905 &mut cursor,
906 0u8,
907 )
908 }?;
909
910 let has_cmsg_buffer = !mhdr.msg_control.is_null() && cmsg_space_provided_by_user > 0;
912 let has_ancillary_data = cursor < msg_stream.len();
913 if has_cmsg_buffer && has_ancillary_data {
914 (unsafe {
915 deserialize_ancillary_data_from_stream(
916 mhdr,
917 socket,
918 &msg_stream,
919 &mut cursor,
920 cmsg_space_provided_by_user as usize,
921 flags,
922 )
923 })?;
924 } else {
925 mhdr.msg_controllen = 0; }
927 Ok(actual_payload_bytes_written_to_iov)
928 }
929
930 unsafe fn sendmsg(socket: c_int, msg: *const msghdr, flags: c_int) -> Result<usize> {
931 if msg.is_null() {
932 return Err(Errno(EINVAL));
933 }
934 let mhdr = unsafe { &*msg };
935
936 let iovs_slice: &[iovec] = if mhdr.msg_iov.is_null() || mhdr.msg_iovlen == 0 {
940 &[]
941 } else {
942 unsafe { slice::from_raw_parts(mhdr.msg_iov, mhdr.msg_iovlen as usize) }
943 };
944
945 let mut msg_stream: Vec<u8> = Vec::new();
946 let whole_iov_size: usize = iovs_slice.iter().map(|iov| iov.iov_len).sum();
947 msg_stream
948 .try_reserve_exact(
949 mem::size_of::<usize>() + whole_iov_size + mhdr.msg_controllen as usize, )
953 .map_err(|_| Errno(ENOMEM))?;
954
955 let mut actual_payload_bytes_serialized = 0;
957 if !mhdr.msg_iov.is_null() && mhdr.msg_iovlen > 0 {
958 actual_payload_bytes_serialized = unsafe {
959 serialize_payload_to_stream(&mut msg_stream, &iovs_slice, whole_iov_size)
960 }?;
961 }
962 if mhdr.msg_controllen > 0 {
964 (unsafe { serialize_ancillary_data_to_stream(msg, mhdr, socket, &mut msg_stream) })?;
965 }
966
967 let metadata = [SocketCall::SendMsg as u64, flags as u64];
969 let call_flags = CallFlags::empty();
970 let written = redox_rt::sys::sys_call_rw(
971 socket as usize,
972 msg_stream.as_mut_slice(),
973 call_flags,
974 &metadata,
975 )?;
976
977 Ok(actual_payload_bytes_serialized)
978 }
979
980 unsafe fn sendto(
981 socket: c_int,
982 buf: *const c_void,
983 len: size_t,
984 flags: c_int,
985 dest_addr: *const sockaddr,
986 dest_len: socklen_t,
987 ) -> Result<usize> {
988 if flags != 0 {
989 let mut iov = iovec {
991 iov_base: buf as *mut c_void,
992 iov_len: len,
993 };
994 let msg = msghdr {
995 msg_name: dest_addr as *mut c_void,
996 msg_namelen: dest_len,
997 msg_iov: &mut iov,
998 msg_iovlen: 1,
999 msg_control: ptr::null_mut(),
1000 msg_controllen: 0,
1001 msg_flags: 0,
1002 };
1003 return unsafe { Self::sendmsg(socket, &msg, flags) };
1004 }
1005 if dest_addr == ptr::null() || dest_len == 0 {
1006 Self::write(socket, unsafe {
1007 slice::from_raw_parts(buf as *const u8, len)
1008 })
1009 } else {
1010 let fd = FdGuard::new(unsafe {
1011 bind_or_connect(SocketCall::Connect, socket, dest_addr, dest_len)
1012 }?);
1013 Self::write(fd.as_c_fd().unwrap(), unsafe {
1014 slice::from_raw_parts(buf as *const u8, len)
1015 })
1016 }
1017 }
1018
1019 unsafe fn setsockopt(
1020 socket: c_int,
1021 level: c_int,
1022 option_name: c_int,
1023 option_value: *const c_void,
1024 option_len: socklen_t,
1025 ) -> Result<()> {
1026 let set_timeout = |timeout_name: &[u8]| -> Result<()> {
1027 if option_value.is_null() {
1028 return Err(Errno(EFAULT));
1029 }
1030
1031 if (option_len as usize) < mem::size_of::<timeval>() {
1032 return Err(Errno(EINVAL));
1033 }
1034
1035 let timeval = unsafe { &*(option_value as *const timeval) };
1036
1037 let fd = FdGuard::new(redox_rt::sys::dup(socket as usize, timeout_name)?);
1038
1039 let Some(tv_nsec) = timeval.tv_usec.checked_mul(1000) else {
1040 return Err(Errno(EDOM));
1041 };
1042
1043 let timespec = syscall::TimeSpec {
1044 tv_sec: timeval.tv_sec as i64,
1045 tv_nsec,
1046 };
1047
1048 Self::write(fd.as_c_fd().unwrap(), ×pec)?;
1049 Ok(())
1050 };
1051
1052 match level {
1053 SOL_SOCKET => match option_name {
1054 SO_RCVTIMEO => return set_timeout(b"read_timeout"),
1055 SO_SNDTIMEO => return set_timeout(b"write_timeout"),
1056 _ => {
1057 let metadata = [SocketCall::SetSockOpt as u64, option_name as u64];
1058 let payload = unsafe {
1059 slice::from_raw_parts_mut(option_value as *mut u8, option_len as usize)
1060 };
1061 let call_flags = CallFlags::empty();
1062 redox_rt::sys::sys_call_rw(
1063 socket as usize,
1064 payload,
1065 CallFlags::empty(),
1066 &metadata,
1067 )?;
1068 return Ok(());
1069 }
1070 },
1071 _ => (),
1072 }
1073
1074 todo_skip!(
1075 0,
1076 "setsockopt({}, {}, {}, {:p}, {}) - unknown option",
1077 socket,
1078 level,
1079 option_name,
1080 option_value,
1081 option_len
1082 );
1083 Ok(())
1084 }
1085
1086 fn shutdown(socket: c_int, how: c_int) -> Result<()> {
1087 let metadata = [SocketCall::Shutdown as u64, how as u64];
1088 redox_rt::sys::sys_call_wo(socket as usize, &[], CallFlags::empty(), &metadata)?;
1089 Ok(())
1090 }
1091
1092 unsafe fn socket(domain: c_int, kind: c_int, protocol: c_int) -> Result<c_int> {
1093 if domain != AF_INET && domain != AF_UNIX {
1094 return Err(Errno(EAFNOSUPPORT));
1095 }
1096 let (kind, flags) = socket_kind(kind);
1102
1103 Ok(match (domain, kind) {
1106 (AF_INET, SOCK_STREAM) => redox_rt::sys::open("/scheme/tcp", flags)? as c_int,
1107 (AF_INET, SOCK_DGRAM) => redox_rt::sys::open("/scheme/udp", flags)? as c_int,
1108 (AF_UNIX, SOCK_STREAM) => {
1109 redox_rt::sys::open("/scheme/uds_stream", flags | O_CREAT)? as c_int
1110 }
1111 (AF_UNIX, SOCK_DGRAM) => {
1112 redox_rt::sys::open("/scheme/uds_dgram", flags | O_CREAT)? as c_int
1113 }
1114 _ => return Err(Errno(EPROTONOSUPPORT)),
1115 })
1116 }
1117
1118 fn socketpair(domain: c_int, kind: c_int, protocol: c_int, sv: &mut [c_int; 2]) -> Result<()> {
1119 let (kind, flags) = socket_kind(kind);
1120
1121 match (domain, kind) {
1122 (AF_UNIX, SOCK_STREAM) => {
1123 let listener = FdGuard::open("/scheme/uds_stream", flags | O_CREAT)?;
1124
1125 let fd0 = listener.dup(b"connect")?;
1130 let fd1 = listener.dup(b"listen")?;
1131
1132 sv[0] = fd0.take() as c_int;
1133 sv[1] = fd1.take() as c_int;
1134 Ok(())
1135 }
1136 (AF_UNIX, SOCK_DGRAM) => {
1137 let listener = FdGuard::open("/scheme/uds_dgram", flags | O_CREAT)?;
1138
1139 let fd0 = listener.dup(b"connect")?;
1144
1145 sv[0] = fd0.take() as c_int;
1146 sv[1] = listener.take() as c_int;
1147 Ok(())
1148 }
1149 _ => {
1150 todo_skip!(
1151 0,
1152 "socketpair({}, {}, {}, {:p})",
1153 domain,
1154 kind,
1155 protocol,
1156 sv.as_mut_ptr()
1157 );
1158 Err(Errno(EPROTONOSUPPORT))
1159 }
1160 }
1161 }
1162}
1163
1164fn read_num<T>(buffer: &[u8]) -> Result<T>
1165where
1166 T: NumFromBytes,
1167{
1168 T::from_le_bytes_slice(buffer)
1169}
1170trait NumFromBytes: Sized {
1171 fn from_le_bytes_slice(buffer: &[u8]) -> Result<Self>;
1172}
1173impl NumFromBytes for i32 {
1174 fn from_le_bytes_slice(buffer: &[u8]) -> Result<Self> {
1175 Ok(i32::from_le_bytes(
1176 buffer
1177 .get(..mem::size_of::<i32>())
1178 .and_then(|slice| slice.try_into().ok())
1179 .ok_or_else(|| Errno(EFAULT))?,
1180 ))
1181 }
1182}
1183impl NumFromBytes for usize {
1184 fn from_le_bytes_slice(buffer: &[u8]) -> Result<Self> {
1185 Ok(usize::from_le_bytes(
1186 buffer
1187 .get(..mem::size_of::<usize>())
1188 .and_then(|slice| slice.try_into().ok())
1189 .ok_or_else(|| Errno(EFAULT))?,
1190 ))
1191 }
1192}