1#![allow(unsafe_code, clippy::undocumented_unsafe_blocks)]
7
8use super::msghdr::{noaddr_msghdr, with_msghdr, with_recv_msghdr};
9use super::read_sockaddr::initialize_family_to_unspec;
10use super::send_recv::{RecvFlags, ReturnFlags, SendFlags};
11use crate::backend::c;
12#[cfg(target_os = "linux")]
13use crate::backend::conv::slice_mut;
14use crate::backend::conv::{
15 by_mut, by_ref, c_int, c_uint, pass_usize, ret, ret_owned_fd, ret_usize, size_of, slice,
16 socklen_t, zero,
17};
18use crate::backend::reg::raw_arg;
19use crate::fd::{BorrowedFd, OwnedFd};
20use crate::io::{self, IoSlice, IoSliceMut};
21use crate::net::addr::SocketAddrArg;
22#[cfg(target_os = "linux")]
23use crate::net::MMsgHdr;
24use crate::net::{
25 AddressFamily, Protocol, RecvAncillaryBuffer, RecvMsg, SendAncillaryBuffer, Shutdown,
26 SocketAddrAny, SocketAddrBuf, SocketFlags, SocketType,
27};
28use core::mem::MaybeUninit;
29#[cfg(target_arch = "x86")]
30use {
31 crate::backend::conv::{slice_just_addr, x86_sys},
32 crate::backend::reg::{ArgReg, SocketArg},
33 linux_raw_sys::net::{
34 SYS_ACCEPT, SYS_ACCEPT4, SYS_BIND, SYS_CONNECT, SYS_GETPEERNAME, SYS_GETSOCKNAME,
35 SYS_LISTEN, SYS_RECV, SYS_RECVFROM, SYS_RECVMSG, SYS_SEND, SYS_SENDMMSG, SYS_SENDMSG,
36 SYS_SENDTO, SYS_SHUTDOWN, SYS_SOCKET, SYS_SOCKETPAIR,
37 },
38};
39
40#[inline]
41pub(crate) fn socket(
42 family: AddressFamily,
43 type_: SocketType,
44 protocol: Option<Protocol>,
45) -> io::Result<OwnedFd> {
46 #[cfg(not(target_arch = "x86"))]
47 unsafe {
48 ret_owned_fd(syscall_readonly!(__NR_socket, family, type_, protocol))
49 }
50 #[cfg(target_arch = "x86")]
51 unsafe {
52 ret_owned_fd(syscall_readonly!(
53 __NR_socketcall,
54 x86_sys(SYS_SOCKET),
55 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
56 family.into(),
57 type_.into(),
58 protocol.into(),
59 ])
60 ))
61 }
62}
63
64#[inline]
65pub(crate) fn socket_with(
66 family: AddressFamily,
67 type_: SocketType,
68 flags: SocketFlags,
69 protocol: Option<Protocol>,
70) -> io::Result<OwnedFd> {
71 #[cfg(not(target_arch = "x86"))]
72 unsafe {
73 ret_owned_fd(syscall_readonly!(
74 __NR_socket,
75 family,
76 (type_, flags),
77 protocol
78 ))
79 }
80 #[cfg(target_arch = "x86")]
81 unsafe {
82 ret_owned_fd(syscall_readonly!(
83 __NR_socketcall,
84 x86_sys(SYS_SOCKET),
85 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
86 family.into(),
87 (type_, flags).into(),
88 protocol.into(),
89 ])
90 ))
91 }
92}
93
94#[inline]
95pub(crate) fn socketpair(
96 family: AddressFamily,
97 type_: SocketType,
98 flags: SocketFlags,
99 protocol: Option<Protocol>,
100) -> io::Result<(OwnedFd, OwnedFd)> {
101 #[cfg(not(target_arch = "x86"))]
102 unsafe {
103 let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit();
104 ret(syscall!(
105 __NR_socketpair,
106 family,
107 (type_, flags),
108 protocol,
109 &mut result
110 ))?;
111 let [fd0, fd1] = result.assume_init();
112 Ok((fd0, fd1))
113 }
114 #[cfg(target_arch = "x86")]
115 unsafe {
116 let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit();
117 ret(syscall!(
118 __NR_socketcall,
119 x86_sys(SYS_SOCKETPAIR),
120 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
121 family.into(),
122 (type_, flags).into(),
123 protocol.into(),
124 (&mut result).into(),
125 ])
126 ))?;
127 let [fd0, fd1] = result.assume_init();
128 Ok((fd0, fd1))
129 }
130}
131
132#[inline]
133pub(crate) fn accept(fd: BorrowedFd<'_>) -> io::Result<OwnedFd> {
134 #[cfg(not(any(target_arch = "x86", target_arch = "s390x")))]
135 unsafe {
136 let fd = ret_owned_fd(syscall_readonly!(__NR_accept, fd, zero(), zero()))?;
137 Ok(fd)
138 }
139 #[cfg(target_arch = "x86")]
140 unsafe {
141 let fd = ret_owned_fd(syscall_readonly!(
142 __NR_socketcall,
143 x86_sys(SYS_ACCEPT),
144 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[fd.into(), zero(), zero()])
145 ))?;
146 Ok(fd)
147 }
148 #[cfg(target_arch = "s390x")]
149 {
150 accept_with(fd, SocketFlags::empty())
152 }
153}
154
155#[inline]
156pub(crate) fn accept_with(fd: BorrowedFd<'_>, flags: SocketFlags) -> io::Result<OwnedFd> {
157 #[cfg(not(target_arch = "x86"))]
158 unsafe {
159 let fd = ret_owned_fd(syscall_readonly!(__NR_accept4, fd, zero(), zero(), flags))?;
160 Ok(fd)
161 }
162 #[cfg(target_arch = "x86")]
163 unsafe {
164 let fd = ret_owned_fd(syscall_readonly!(
165 __NR_socketcall,
166 x86_sys(SYS_ACCEPT4),
167 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[fd.into(), zero(), zero(), flags.into()])
168 ))?;
169 Ok(fd)
170 }
171}
172
173#[inline]
174pub(crate) fn acceptfrom(fd: BorrowedFd<'_>) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
175 #[cfg(not(any(target_arch = "x86", target_arch = "s390x")))]
176 unsafe {
177 let mut addr = SocketAddrBuf::new();
178 let fd = ret_owned_fd(syscall!(
179 __NR_accept,
180 fd,
181 &mut addr.storage,
182 by_mut(&mut addr.len)
183 ))?;
184 Ok((fd, addr.into_any_option()))
185 }
186 #[cfg(target_arch = "x86")]
187 unsafe {
188 let mut addr = SocketAddrBuf::new();
189 let fd = ret_owned_fd(syscall!(
190 __NR_socketcall,
191 x86_sys(SYS_ACCEPT),
192 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
193 fd.into(),
194 (&mut addr.storage).into(),
195 by_mut(&mut addr.len),
196 ])
197 ))?;
198 Ok((fd, addr.into_any_option()))
199 }
200 #[cfg(target_arch = "s390x")]
201 {
202 acceptfrom_with(fd, SocketFlags::empty())
204 }
205}
206
207#[inline]
208pub(crate) fn acceptfrom_with(
209 fd: BorrowedFd<'_>,
210 flags: SocketFlags,
211) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
212 #[cfg(not(target_arch = "x86"))]
213 unsafe {
214 let mut addr = SocketAddrBuf::new();
215 let fd = ret_owned_fd(syscall!(
216 __NR_accept4,
217 fd,
218 &mut addr.storage,
219 by_mut(&mut addr.len),
220 flags
221 ))?;
222 Ok((fd, addr.into_any_option()))
223 }
224 #[cfg(target_arch = "x86")]
225 unsafe {
226 let mut addr = SocketAddrBuf::new();
227 let fd = ret_owned_fd(syscall!(
228 __NR_socketcall,
229 x86_sys(SYS_ACCEPT4),
230 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
231 fd.into(),
232 (&mut addr.storage).into(),
233 by_mut(&mut addr.len),
234 flags.into(),
235 ])
236 ))?;
237 Ok((fd, addr.into_any_option()))
238 }
239}
240
241#[inline]
242pub(crate) fn recvmsg(
243 sockfd: BorrowedFd<'_>,
244 iov: &mut [IoSliceMut<'_>],
245 control: &mut RecvAncillaryBuffer<'_>,
246 msg_flags: RecvFlags,
247) -> io::Result<RecvMsg> {
248 let mut addr = SocketAddrBuf::new();
249
250 let (bytes, flags) = unsafe {
253 with_recv_msghdr(&mut addr, iov, control, |msghdr| {
254 #[cfg(not(target_arch = "x86"))]
255 let result = ret_usize(syscall!(__NR_recvmsg, sockfd, by_mut(msghdr), msg_flags));
256
257 #[cfg(target_arch = "x86")]
258 let result = ret_usize(syscall!(
259 __NR_socketcall,
260 x86_sys(SYS_RECVMSG),
261 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
262 sockfd.into(),
263 by_mut(msghdr),
264 msg_flags.into(),
265 ])
266 ));
267
268 result.map(|bytes| (bytes, msghdr.msg_flags))
269 })?
270 };
271
272 Ok(RecvMsg {
274 bytes,
275 address: unsafe { addr.into_any_option() },
276 flags: ReturnFlags::from_bits_retain(flags),
277 })
278}
279
280#[inline]
281pub(crate) fn sendmsg(
282 sockfd: BorrowedFd<'_>,
283 iov: &[IoSlice<'_>],
284 control: &mut SendAncillaryBuffer<'_, '_, '_>,
285 msg_flags: SendFlags,
286) -> io::Result<usize> {
287 let msghdr = noaddr_msghdr(iov, control);
288
289 #[cfg(not(target_arch = "x86"))]
290 let result = unsafe { ret_usize(syscall!(__NR_sendmsg, sockfd, by_ref(&msghdr), msg_flags)) };
291
292 #[cfg(target_arch = "x86")]
293 let result = unsafe {
294 ret_usize(syscall!(
295 __NR_socketcall,
296 x86_sys(SYS_SENDMSG),
297 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
298 sockfd.into(),
299 by_ref(&msghdr),
300 msg_flags.into()
301 ])
302 ))
303 };
304
305 result
306}
307
308#[inline]
309pub(crate) fn sendmsg_addr(
310 sockfd: BorrowedFd<'_>,
311 addr: &impl SocketAddrArg,
312 iov: &[IoSlice<'_>],
313 control: &mut SendAncillaryBuffer<'_, '_, '_>,
314 msg_flags: SendFlags,
315) -> io::Result<usize> {
316 unsafe {
319 with_msghdr(addr, iov, control, |msghdr| {
320 #[cfg(not(target_arch = "x86"))]
321 let result = ret_usize(syscall!(__NR_sendmsg, sockfd, by_ref(msghdr), msg_flags));
322
323 #[cfg(target_arch = "x86")]
324 let result = ret_usize(syscall!(
325 __NR_socketcall,
326 x86_sys(SYS_SENDMSG),
327 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
328 sockfd.into(),
329 by_ref(msghdr),
330 msg_flags.into(),
331 ])
332 ));
333
334 result
335 })
336 }
337}
338
339#[cfg(target_os = "linux")]
340#[inline]
341pub(crate) fn sendmmsg(
342 sockfd: BorrowedFd<'_>,
343 msgs: &mut [MMsgHdr<'_>],
344 flags: SendFlags,
345) -> io::Result<usize> {
346 let (msgs, len) = slice_mut(msgs);
347
348 #[cfg(not(target_arch = "x86"))]
349 let result = unsafe { ret_usize(syscall!(__NR_sendmmsg, sockfd, msgs, len, flags)) };
350
351 #[cfg(target_arch = "x86")]
352 let result = unsafe {
353 ret_usize(syscall!(
354 __NR_socketcall,
355 x86_sys(SYS_SENDMMSG),
356 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[sockfd.into(), msgs, len, flags.into()])
357 ))
358 };
359
360 result
361}
362
363#[inline]
364pub(crate) fn shutdown(fd: BorrowedFd<'_>, how: Shutdown) -> io::Result<()> {
365 #[cfg(not(target_arch = "x86"))]
366 unsafe {
367 ret(syscall_readonly!(
368 __NR_shutdown,
369 fd,
370 c_uint(how as c::c_uint)
371 ))
372 }
373 #[cfg(target_arch = "x86")]
374 unsafe {
375 ret(syscall_readonly!(
376 __NR_socketcall,
377 x86_sys(SYS_SHUTDOWN),
378 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[fd.into(), c_uint(how as c::c_uint)])
379 ))
380 }
381}
382
383#[inline]
384pub(crate) fn send(fd: BorrowedFd<'_>, buf: &[u8], flags: SendFlags) -> io::Result<usize> {
385 let (buf_addr, buf_len) = slice(buf);
386
387 #[cfg(not(any(
388 target_arch = "aarch64",
389 target_arch = "mips64",
390 target_arch = "mips64r6",
391 target_arch = "riscv64",
392 target_arch = "s390x",
393 target_arch = "x86",
394 target_arch = "x86_64",
395 )))]
396 unsafe {
397 ret_usize(syscall_readonly!(__NR_send, fd, buf_addr, buf_len, flags))
398 }
399 #[cfg(any(
400 target_arch = "aarch64",
401 target_arch = "mips64",
402 target_arch = "mips64r6",
403 target_arch = "riscv64",
404 target_arch = "s390x",
405 target_arch = "x86_64",
406 ))]
407 unsafe {
408 ret_usize(syscall_readonly!(
409 __NR_sendto,
410 fd,
411 buf_addr,
412 buf_len,
413 flags,
414 zero(),
415 zero()
416 ))
417 }
418 #[cfg(target_arch = "x86")]
419 unsafe {
420 ret_usize(syscall_readonly!(
421 __NR_socketcall,
422 x86_sys(SYS_SEND),
423 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
424 fd.into(),
425 buf_addr,
426 buf_len,
427 flags.into()
428 ])
429 ))
430 }
431}
432
433#[inline]
434pub(crate) fn sendto(
435 fd: BorrowedFd<'_>,
436 buf: &[u8],
437 flags: SendFlags,
438 addr: &impl SocketAddrArg,
439) -> io::Result<usize> {
440 let (buf_addr, buf_len) = slice(buf);
441
442 unsafe {
445 addr.with_sockaddr(|addr_ptr, addr_len| {
446 #[cfg(not(target_arch = "x86"))]
447 {
448 ret_usize(syscall_readonly!(
449 __NR_sendto,
450 fd,
451 buf_addr,
452 buf_len,
453 flags,
454 raw_arg(addr_ptr as *mut _),
455 socklen_t(addr_len)
456 ))
457 }
458 #[cfg(target_arch = "x86")]
459 {
460 ret_usize(syscall_readonly!(
461 __NR_socketcall,
462 x86_sys(SYS_SENDTO),
463 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
464 fd.into(),
465 buf_addr,
466 buf_len,
467 flags.into(),
468 raw_arg(addr_ptr as *mut _),
469 socklen_t(addr_len)
470 ])
471 ))
472 }
473 })
474 }
475}
476
477#[inline]
478pub(crate) unsafe fn recv(
479 fd: BorrowedFd<'_>,
480 buf: (*mut u8, usize),
481 flags: RecvFlags,
482) -> io::Result<usize> {
483 #[cfg(not(any(
484 target_arch = "aarch64",
485 target_arch = "mips64",
486 target_arch = "mips64r6",
487 target_arch = "riscv64",
488 target_arch = "s390x",
489 target_arch = "x86",
490 target_arch = "x86_64",
491 )))]
492 {
493 ret_usize(syscall!(__NR_recv, fd, buf.0, pass_usize(buf.1), flags))
494 }
495 #[cfg(any(
496 target_arch = "aarch64",
497 target_arch = "mips64",
498 target_arch = "mips64r6",
499 target_arch = "riscv64",
500 target_arch = "s390x",
501 target_arch = "x86_64",
502 ))]
503 {
504 ret_usize(syscall!(
505 __NR_recvfrom,
506 fd,
507 buf.0,
508 pass_usize(buf.1),
509 flags,
510 zero(),
511 zero()
512 ))
513 }
514 #[cfg(target_arch = "x86")]
515 {
516 ret_usize(syscall!(
517 __NR_socketcall,
518 x86_sys(SYS_RECV),
519 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
520 fd.into(),
521 buf.0.into(),
522 pass_usize(buf.1),
523 flags.into(),
524 ])
525 ))
526 }
527}
528
529#[inline]
530pub(crate) unsafe fn recvfrom(
531 fd: BorrowedFd<'_>,
532 buf: (*mut u8, usize),
533 flags: RecvFlags,
534) -> io::Result<(usize, Option<SocketAddrAny>)> {
535 let mut addr = SocketAddrBuf::new();
536
537 initialize_family_to_unspec(addr.storage.as_mut_ptr().cast::<c::sockaddr>());
541
542 #[cfg(not(target_arch = "x86"))]
543 let nread = ret_usize(syscall!(
544 __NR_recvfrom,
545 fd,
546 buf.0,
547 pass_usize(buf.1),
548 flags,
549 &mut addr.storage,
550 by_mut(&mut addr.len)
551 ))?;
552 #[cfg(target_arch = "x86")]
553 let nread = ret_usize(syscall!(
554 __NR_socketcall,
555 x86_sys(SYS_RECVFROM),
556 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
557 fd.into(),
558 buf.0.into(),
559 pass_usize(buf.1),
560 flags.into(),
561 (&mut addr.storage).into(),
562 by_mut(&mut addr.len),
563 ])
564 ))?;
565
566 Ok((nread, addr.into_any_option()))
567}
568
569#[inline]
570pub(crate) fn getpeername(fd: BorrowedFd<'_>) -> io::Result<Option<SocketAddrAny>> {
571 #[cfg(not(target_arch = "x86"))]
572 unsafe {
573 let mut addr = SocketAddrBuf::new();
574 ret(syscall!(
575 __NR_getpeername,
576 fd,
577 &mut addr.storage,
578 by_mut(&mut addr.len)
579 ))?;
580 Ok(addr.into_any_option())
581 }
582 #[cfg(target_arch = "x86")]
583 unsafe {
584 let mut addr = SocketAddrBuf::new();
585 ret(syscall!(
586 __NR_socketcall,
587 x86_sys(SYS_GETPEERNAME),
588 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
589 fd.into(),
590 (&mut addr.storage).into(),
591 by_mut(&mut addr.len),
592 ])
593 ))?;
594 Ok(addr.into_any_option())
595 }
596}
597
598#[inline]
599pub(crate) fn getsockname(fd: BorrowedFd<'_>) -> io::Result<SocketAddrAny> {
600 #[cfg(not(target_arch = "x86"))]
601 unsafe {
602 let mut addr = SocketAddrBuf::new();
603 ret(syscall!(
604 __NR_getsockname,
605 fd,
606 &mut addr.storage,
607 by_mut(&mut addr.len)
608 ))?;
609 Ok(addr.into_any())
610 }
611 #[cfg(target_arch = "x86")]
612 unsafe {
613 let mut addr = SocketAddrBuf::new();
614 ret(syscall!(
615 __NR_socketcall,
616 x86_sys(SYS_GETSOCKNAME),
617 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
618 fd.into(),
619 (&mut addr.storage).into(),
620 by_mut(&mut addr.len),
621 ])
622 ))?;
623 Ok(addr.into_any())
624 }
625}
626
627#[inline]
628pub(crate) fn bind(fd: BorrowedFd<'_>, addr: &impl SocketAddrArg) -> io::Result<()> {
629 unsafe {
632 addr.with_sockaddr(|addr_ptr, addr_len| {
633 #[cfg(not(target_arch = "x86"))]
634 {
635 ret(syscall_readonly!(
636 __NR_bind,
637 fd,
638 raw_arg(addr_ptr as *mut _),
639 socklen_t(addr_len)
640 ))
641 }
642 #[cfg(target_arch = "x86")]
643 {
644 ret(syscall_readonly!(
645 __NR_socketcall,
646 x86_sys(SYS_BIND),
647 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
648 fd.into(),
649 raw_arg(addr_ptr as *mut _),
650 socklen_t(addr_len)
651 ])
652 ))
653 }
654 })
655 }
656}
657
658#[inline]
659pub(crate) fn connect(fd: BorrowedFd<'_>, addr: &impl SocketAddrArg) -> io::Result<()> {
660 unsafe {
663 addr.with_sockaddr(|addr_ptr, addr_len| {
664 #[cfg(not(target_arch = "x86"))]
665 {
666 ret(syscall_readonly!(
667 __NR_connect,
668 fd,
669 raw_arg(addr_ptr as *mut _),
670 socklen_t(addr_len)
671 ))
672 }
673 #[cfg(target_arch = "x86")]
674 {
675 ret(syscall_readonly!(
676 __NR_socketcall,
677 x86_sys(SYS_CONNECT),
678 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
679 fd.into(),
680 raw_arg(addr_ptr as *mut _),
681 socklen_t(addr_len)
682 ])
683 ))
684 }
685 })
686 }
687}
688
689#[inline]
690pub(crate) fn connect_unspec(fd: BorrowedFd<'_>) -> io::Result<()> {
691 debug_assert_eq!(c::AF_UNSPEC, 0);
692 let addr = MaybeUninit::<c::sockaddr_storage>::zeroed();
693
694 #[cfg(not(target_arch = "x86"))]
695 unsafe {
696 ret(syscall_readonly!(
697 __NR_connect,
698 fd,
699 by_ref(&addr),
700 size_of::<c::sockaddr_storage, _>()
701 ))
702 }
703 #[cfg(target_arch = "x86")]
704 unsafe {
705 ret(syscall_readonly!(
706 __NR_socketcall,
707 x86_sys(SYS_CONNECT),
708 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
709 fd.into(),
710 by_ref(&addr),
711 size_of::<c::sockaddr_storage, _>(),
712 ])
713 ))
714 }
715}
716
717#[inline]
718pub(crate) fn listen(fd: BorrowedFd<'_>, backlog: c::c_int) -> io::Result<()> {
719 #[cfg(not(target_arch = "x86"))]
720 unsafe {
721 ret(syscall_readonly!(__NR_listen, fd, c_int(backlog)))
722 }
723 #[cfg(target_arch = "x86")]
724 unsafe {
725 ret(syscall_readonly!(
726 __NR_socketcall,
727 x86_sys(SYS_LISTEN),
728 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[fd.into(), c_int(backlog)])
729 ))
730 }
731}