1#![allow(unsafe_code, clippy::undocumented_unsafe_blocks)]
7
8#[cfg(target_os = "linux")]
9use super::msghdr::with_xdp_msghdr;
10use super::msghdr::{
11 with_noaddr_msghdr, with_recv_msghdr, with_unix_msghdr, with_v4_msghdr, with_v6_msghdr,
12};
13use super::read_sockaddr::{initialize_family_to_unspec, maybe_read_sockaddr_os, read_sockaddr_os};
14use super::send_recv::{RecvFlags, SendFlags};
15#[cfg(target_os = "linux")]
16use super::write_sockaddr::encode_sockaddr_xdp;
17use super::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6};
18use crate::backend::c;
19use crate::backend::conv::{
20 by_mut, by_ref, c_int, c_uint, pass_usize, ret, ret_owned_fd, ret_usize, size_of, slice,
21 socklen_t, zero,
22};
23use crate::fd::{BorrowedFd, OwnedFd};
24use crate::io::{self, IoSlice, IoSliceMut};
25#[cfg(target_os = "linux")]
26use crate::net::xdp::SocketAddrXdp;
27use crate::net::{
28 AddressFamily, Protocol, RecvAncillaryBuffer, RecvMsgReturn, SendAncillaryBuffer, Shutdown,
29 SocketAddrAny, SocketAddrUnix, SocketAddrV4, SocketAddrV6, SocketFlags, SocketType,
30};
31use c::{sockaddr, sockaddr_in, sockaddr_in6, socklen_t};
32use core::mem::MaybeUninit;
33#[cfg(target_arch = "x86")]
34use {
35 crate::backend::conv::{slice_just_addr, x86_sys},
36 crate::backend::reg::{ArgReg, SocketArg},
37 linux_raw_sys::net::{
38 SYS_ACCEPT, SYS_ACCEPT4, SYS_BIND, SYS_CONNECT, SYS_GETPEERNAME, SYS_GETSOCKNAME,
39 SYS_LISTEN, SYS_RECV, SYS_RECVFROM, SYS_RECVMSG, SYS_SEND, SYS_SENDMSG, SYS_SENDTO,
40 SYS_SHUTDOWN, SYS_SOCKET, SYS_SOCKETPAIR,
41 },
42};
43
44#[inline]
45pub(crate) fn socket(
46 family: AddressFamily,
47 type_: SocketType,
48 protocol: Option<Protocol>,
49) -> io::Result<OwnedFd> {
50 #[cfg(not(target_arch = "x86"))]
51 unsafe {
52 ret_owned_fd(syscall_readonly!(__NR_socket, family, type_, protocol))
53 }
54 #[cfg(target_arch = "x86")]
55 unsafe {
56 ret_owned_fd(syscall_readonly!(
57 __NR_socketcall,
58 x86_sys(SYS_SOCKET),
59 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
60 family.into(),
61 type_.into(),
62 protocol.into(),
63 ])
64 ))
65 }
66}
67
68#[inline]
69pub(crate) fn socket_with(
70 family: AddressFamily,
71 type_: SocketType,
72 flags: SocketFlags,
73 protocol: Option<Protocol>,
74) -> io::Result<OwnedFd> {
75 #[cfg(not(target_arch = "x86"))]
76 unsafe {
77 ret_owned_fd(syscall_readonly!(
78 __NR_socket,
79 family,
80 (type_, flags),
81 protocol
82 ))
83 }
84 #[cfg(target_arch = "x86")]
85 unsafe {
86 ret_owned_fd(syscall_readonly!(
87 __NR_socketcall,
88 x86_sys(SYS_SOCKET),
89 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
90 family.into(),
91 (type_, flags).into(),
92 protocol.into(),
93 ])
94 ))
95 }
96}
97
98#[inline]
99pub(crate) fn socketpair(
100 family: AddressFamily,
101 type_: SocketType,
102 flags: SocketFlags,
103 protocol: Option<Protocol>,
104) -> io::Result<(OwnedFd, OwnedFd)> {
105 #[cfg(not(target_arch = "x86"))]
106 unsafe {
107 let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit();
108 ret(syscall!(
109 __NR_socketpair,
110 family,
111 (type_, flags),
112 protocol,
113 &mut result
114 ))?;
115 let [fd0, fd1] = result.assume_init();
116 Ok((fd0, fd1))
117 }
118 #[cfg(target_arch = "x86")]
119 unsafe {
120 let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit();
121 ret(syscall!(
122 __NR_socketcall,
123 x86_sys(SYS_SOCKETPAIR),
124 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
125 family.into(),
126 (type_, flags).into(),
127 protocol.into(),
128 (&mut result).into(),
129 ])
130 ))?;
131 let [fd0, fd1] = result.assume_init();
132 Ok((fd0, fd1))
133 }
134}
135
136#[inline]
137pub(crate) fn accept(fd: BorrowedFd<'_>) -> io::Result<OwnedFd> {
138 #[cfg(not(any(target_arch = "x86", target_arch = "s390x")))]
139 unsafe {
140 let fd = ret_owned_fd(syscall_readonly!(__NR_accept, fd, zero(), zero()))?;
141 Ok(fd)
142 }
143 #[cfg(target_arch = "x86")]
144 unsafe {
145 let fd = ret_owned_fd(syscall_readonly!(
146 __NR_socketcall,
147 x86_sys(SYS_ACCEPT),
148 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[fd.into(), zero(), zero()])
149 ))?;
150 Ok(fd)
151 }
152 #[cfg(target_arch = "s390x")]
153 {
154 accept_with(fd, SocketFlags::empty())
156 }
157}
158
159#[inline]
160pub(crate) fn accept_with(fd: BorrowedFd<'_>, flags: SocketFlags) -> io::Result<OwnedFd> {
161 #[cfg(not(target_arch = "x86"))]
162 unsafe {
163 let fd = ret_owned_fd(syscall_readonly!(__NR_accept4, fd, zero(), zero(), flags))?;
164 Ok(fd)
165 }
166 #[cfg(target_arch = "x86")]
167 unsafe {
168 let fd = ret_owned_fd(syscall_readonly!(
169 __NR_socketcall,
170 x86_sys(SYS_ACCEPT4),
171 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[fd.into(), zero(), zero(), flags.into()])
172 ))?;
173 Ok(fd)
174 }
175}
176
177#[inline]
178pub(crate) fn acceptfrom(fd: BorrowedFd<'_>) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
179 #[cfg(not(any(target_arch = "x86", target_arch = "s390x")))]
180 unsafe {
181 let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
182 let mut storage = MaybeUninit::<sockaddr>::uninit();
183 let fd = ret_owned_fd(syscall!(
184 __NR_accept,
185 fd,
186 &mut storage,
187 by_mut(&mut addrlen)
188 ))?;
189 Ok((
190 fd,
191 maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()),
192 ))
193 }
194 #[cfg(target_arch = "x86")]
195 unsafe {
196 let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
197 let mut storage = MaybeUninit::<sockaddr>::uninit();
198 let fd = ret_owned_fd(syscall!(
199 __NR_socketcall,
200 x86_sys(SYS_ACCEPT),
201 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
202 fd.into(),
203 (&mut storage).into(),
204 by_mut(&mut addrlen),
205 ])
206 ))?;
207 Ok((
208 fd,
209 maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()),
210 ))
211 }
212 #[cfg(target_arch = "s390x")]
213 {
214 acceptfrom_with(fd, SocketFlags::empty())
216 }
217}
218
219#[inline]
220pub(crate) fn acceptfrom_with(
221 fd: BorrowedFd<'_>,
222 flags: SocketFlags,
223) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
224 #[cfg(not(target_arch = "x86"))]
225 unsafe {
226 let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
227 let mut storage = MaybeUninit::<sockaddr>::uninit();
228 let fd = ret_owned_fd(syscall!(
229 __NR_accept4,
230 fd,
231 &mut storage,
232 by_mut(&mut addrlen),
233 flags
234 ))?;
235 Ok((
236 fd,
237 maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()),
238 ))
239 }
240 #[cfg(target_arch = "x86")]
241 unsafe {
242 let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
243 let mut storage = MaybeUninit::<sockaddr>::uninit();
244 let fd = ret_owned_fd(syscall!(
245 __NR_socketcall,
246 x86_sys(SYS_ACCEPT4),
247 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
248 fd.into(),
249 (&mut storage).into(),
250 by_mut(&mut addrlen),
251 flags.into(),
252 ])
253 ))?;
254 Ok((
255 fd,
256 maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()),
257 ))
258 }
259}
260
261#[inline]
262pub(crate) fn recvmsg(
263 sockfd: BorrowedFd<'_>,
264 iov: &mut [IoSliceMut<'_>],
265 control: &mut RecvAncillaryBuffer<'_>,
266 msg_flags: RecvFlags,
267) -> io::Result<RecvMsgReturn> {
268 let mut storage = MaybeUninit::<c::sockaddr_storage>::uninit();
269
270 with_recv_msghdr(&mut storage, iov, control, |msghdr| {
271 #[cfg(not(target_arch = "x86"))]
272 let result =
273 unsafe { ret_usize(syscall!(__NR_recvmsg, sockfd, by_mut(msghdr), msg_flags)) };
274
275 #[cfg(target_arch = "x86")]
276 let result = unsafe {
277 ret_usize(syscall!(
278 __NR_socketcall,
279 x86_sys(SYS_RECVMSG),
280 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
281 sockfd.into(),
282 by_mut(msghdr),
283 msg_flags.into(),
284 ])
285 ))
286 };
287
288 result.map(|bytes| {
289 let addr =
291 unsafe { maybe_read_sockaddr_os(msghdr.msg_name as _, msghdr.msg_namelen as _) };
292
293 RecvMsgReturn {
294 bytes,
295 address: addr,
296 flags: RecvFlags::from_bits_retain(msghdr.msg_flags),
297 }
298 })
299 })
300}
301
302#[inline]
303pub(crate) fn sendmsg(
304 sockfd: BorrowedFd<'_>,
305 iov: &[IoSlice<'_>],
306 control: &mut SendAncillaryBuffer<'_, '_, '_>,
307 msg_flags: SendFlags,
308) -> io::Result<usize> {
309 with_noaddr_msghdr(iov, control, |msghdr| {
310 #[cfg(not(target_arch = "x86"))]
311 let result =
312 unsafe { ret_usize(syscall!(__NR_sendmsg, sockfd, by_ref(&msghdr), msg_flags)) };
313
314 #[cfg(target_arch = "x86")]
315 let result = unsafe {
316 ret_usize(syscall!(
317 __NR_socketcall,
318 x86_sys(SYS_SENDMSG),
319 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
320 sockfd.into(),
321 by_ref(&msghdr),
322 msg_flags.into()
323 ])
324 ))
325 };
326
327 result
328 })
329}
330
331#[inline]
332pub(crate) fn sendmsg_v4(
333 sockfd: BorrowedFd<'_>,
334 addr: &SocketAddrV4,
335 iov: &[IoSlice<'_>],
336 control: &mut SendAncillaryBuffer<'_, '_, '_>,
337 msg_flags: SendFlags,
338) -> io::Result<usize> {
339 with_v4_msghdr(addr, iov, control, |msghdr| {
340 #[cfg(not(target_arch = "x86"))]
341 let result =
342 unsafe { ret_usize(syscall!(__NR_sendmsg, sockfd, by_ref(&msghdr), msg_flags)) };
343
344 #[cfg(target_arch = "x86")]
345 let result = unsafe {
346 ret_usize(syscall!(
347 __NR_socketcall,
348 x86_sys(SYS_SENDMSG),
349 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
350 sockfd.into(),
351 by_ref(&msghdr),
352 msg_flags.into(),
353 ])
354 ))
355 };
356
357 result
358 })
359}
360
361#[inline]
362pub(crate) fn sendmsg_v6(
363 sockfd: BorrowedFd<'_>,
364 addr: &SocketAddrV6,
365 iov: &[IoSlice<'_>],
366 control: &mut SendAncillaryBuffer<'_, '_, '_>,
367 msg_flags: SendFlags,
368) -> io::Result<usize> {
369 with_v6_msghdr(addr, iov, control, |msghdr| {
370 #[cfg(not(target_arch = "x86"))]
371 let result =
372 unsafe { ret_usize(syscall!(__NR_sendmsg, sockfd, by_ref(&msghdr), msg_flags)) };
373
374 #[cfg(target_arch = "x86")]
375 let result = unsafe {
376 ret_usize(syscall!(
377 __NR_socketcall,
378 x86_sys(SYS_SENDMSG),
379 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
380 sockfd.into(),
381 by_ref(&msghdr),
382 msg_flags.into()
383 ])
384 ))
385 };
386
387 result
388 })
389}
390
391#[inline]
392pub(crate) fn sendmsg_unix(
393 sockfd: BorrowedFd<'_>,
394 addr: &SocketAddrUnix,
395 iov: &[IoSlice<'_>],
396 control: &mut SendAncillaryBuffer<'_, '_, '_>,
397 msg_flags: SendFlags,
398) -> io::Result<usize> {
399 with_unix_msghdr(addr, iov, control, |msghdr| {
400 #[cfg(not(target_arch = "x86"))]
401 let result =
402 unsafe { ret_usize(syscall!(__NR_sendmsg, sockfd, by_ref(&msghdr), msg_flags)) };
403
404 #[cfg(target_arch = "x86")]
405 let result = unsafe {
406 ret_usize(syscall!(
407 __NR_socketcall,
408 x86_sys(SYS_SENDMSG),
409 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
410 sockfd.into(),
411 by_ref(&msghdr),
412 msg_flags.into()
413 ])
414 ))
415 };
416
417 result
418 })
419}
420
421#[cfg(target_os = "linux")]
422#[inline]
423pub(crate) fn sendmsg_xdp(
424 sockfd: BorrowedFd<'_>,
425 addr: &SocketAddrXdp,
426 iov: &[IoSlice<'_>],
427 control: &mut SendAncillaryBuffer<'_, '_, '_>,
428 msg_flags: SendFlags,
429) -> io::Result<usize> {
430 with_xdp_msghdr(addr, iov, control, |msghdr| {
431 #[cfg(not(target_arch = "x86"))]
432 let result =
433 unsafe { ret_usize(syscall!(__NR_sendmsg, sockfd, by_ref(&msghdr), msg_flags)) };
434
435 #[cfg(target_arch = "x86")]
436 let result = unsafe {
437 ret_usize(syscall!(
438 __NR_socketcall,
439 x86_sys(SYS_SENDMSG),
440 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
441 sockfd.into(),
442 by_ref(&msghdr),
443 msg_flags.into()
444 ])
445 ))
446 };
447
448 result
449 })
450}
451
452#[inline]
453pub(crate) fn shutdown(fd: BorrowedFd<'_>, how: Shutdown) -> io::Result<()> {
454 #[cfg(not(target_arch = "x86"))]
455 unsafe {
456 ret(syscall_readonly!(
457 __NR_shutdown,
458 fd,
459 c_uint(how as c::c_uint)
460 ))
461 }
462 #[cfg(target_arch = "x86")]
463 unsafe {
464 ret(syscall_readonly!(
465 __NR_socketcall,
466 x86_sys(SYS_SHUTDOWN),
467 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[fd.into(), c_uint(how as c::c_uint)])
468 ))
469 }
470}
471
472#[inline]
473pub(crate) fn send(fd: BorrowedFd<'_>, buf: &[u8], flags: SendFlags) -> io::Result<usize> {
474 let (buf_addr, buf_len) = slice(buf);
475
476 #[cfg(not(any(
477 target_arch = "aarch64",
478 target_arch = "mips64",
479 target_arch = "mips64r6",
480 target_arch = "riscv64",
481 target_arch = "s390x",
482 target_arch = "x86",
483 target_arch = "x86_64",
484 )))]
485 unsafe {
486 ret_usize(syscall_readonly!(__NR_send, fd, buf_addr, buf_len, flags))
487 }
488 #[cfg(any(
489 target_arch = "aarch64",
490 target_arch = "mips64",
491 target_arch = "mips64r6",
492 target_arch = "riscv64",
493 target_arch = "s390x",
494 target_arch = "x86_64",
495 ))]
496 unsafe {
497 ret_usize(syscall_readonly!(
498 __NR_sendto,
499 fd,
500 buf_addr,
501 buf_len,
502 flags,
503 zero(),
504 zero()
505 ))
506 }
507 #[cfg(target_arch = "x86")]
508 unsafe {
509 ret_usize(syscall_readonly!(
510 __NR_socketcall,
511 x86_sys(SYS_SEND),
512 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
513 fd.into(),
514 buf_addr,
515 buf_len,
516 flags.into()
517 ])
518 ))
519 }
520}
521
522#[inline]
523pub(crate) fn sendto_v4(
524 fd: BorrowedFd<'_>,
525 buf: &[u8],
526 flags: SendFlags,
527 addr: &SocketAddrV4,
528) -> io::Result<usize> {
529 let (buf_addr, buf_len) = slice(buf);
530
531 #[cfg(not(target_arch = "x86"))]
532 unsafe {
533 ret_usize(syscall_readonly!(
534 __NR_sendto,
535 fd,
536 buf_addr,
537 buf_len,
538 flags,
539 by_ref(&encode_sockaddr_v4(addr)),
540 size_of::<sockaddr_in, _>()
541 ))
542 }
543 #[cfg(target_arch = "x86")]
544 unsafe {
545 ret_usize(syscall_readonly!(
546 __NR_socketcall,
547 x86_sys(SYS_SENDTO),
548 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
549 fd.into(),
550 buf_addr,
551 buf_len,
552 flags.into(),
553 by_ref(&encode_sockaddr_v4(addr)),
554 size_of::<sockaddr_in, _>(),
555 ])
556 ))
557 }
558}
559
560#[inline]
561pub(crate) fn sendto_v6(
562 fd: BorrowedFd<'_>,
563 buf: &[u8],
564 flags: SendFlags,
565 addr: &SocketAddrV6,
566) -> io::Result<usize> {
567 let (buf_addr, buf_len) = slice(buf);
568
569 #[cfg(not(target_arch = "x86"))]
570 unsafe {
571 ret_usize(syscall_readonly!(
572 __NR_sendto,
573 fd,
574 buf_addr,
575 buf_len,
576 flags,
577 by_ref(&encode_sockaddr_v6(addr)),
578 size_of::<sockaddr_in6, _>()
579 ))
580 }
581 #[cfg(target_arch = "x86")]
582 unsafe {
583 ret_usize(syscall_readonly!(
584 __NR_socketcall,
585 x86_sys(SYS_SENDTO),
586 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
587 fd.into(),
588 buf_addr,
589 buf_len,
590 flags.into(),
591 by_ref(&encode_sockaddr_v6(addr)),
592 size_of::<sockaddr_in6, _>(),
593 ])
594 ))
595 }
596}
597
598#[inline]
599pub(crate) fn sendto_unix(
600 fd: BorrowedFd<'_>,
601 buf: &[u8],
602 flags: SendFlags,
603 addr: &SocketAddrUnix,
604) -> io::Result<usize> {
605 let (buf_addr, buf_len) = slice(buf);
606
607 #[cfg(not(target_arch = "x86"))]
608 unsafe {
609 ret_usize(syscall_readonly!(
610 __NR_sendto,
611 fd,
612 buf_addr,
613 buf_len,
614 flags,
615 by_ref(&addr.unix),
616 socklen_t(addr.addr_len())
617 ))
618 }
619 #[cfg(target_arch = "x86")]
620 unsafe {
621 ret_usize(syscall_readonly!(
622 __NR_socketcall,
623 x86_sys(SYS_SENDTO),
624 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
625 fd.into(),
626 buf_addr,
627 buf_len,
628 flags.into(),
629 by_ref(&addr.unix),
630 socklen_t(addr.addr_len()),
631 ])
632 ))
633 }
634}
635
636#[cfg(target_os = "linux")]
637#[inline]
638pub(crate) fn sendto_xdp(
639 fd: BorrowedFd<'_>,
640 buf: &[u8],
641 flags: SendFlags,
642 addr: &SocketAddrXdp,
643) -> io::Result<usize> {
644 let (buf_addr, buf_len) = slice(buf);
645
646 #[cfg(not(target_arch = "x86"))]
647 unsafe {
648 ret_usize(syscall_readonly!(
649 __NR_sendto,
650 fd,
651 buf_addr,
652 buf_len,
653 flags,
654 by_ref(&encode_sockaddr_xdp(addr)),
655 size_of::<c::sockaddr_xdp, _>()
656 ))
657 }
658 #[cfg(target_arch = "x86")]
659 unsafe {
660 ret_usize(syscall_readonly!(
661 __NR_socketcall,
662 x86_sys(SYS_SENDTO),
663 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
664 fd.into(),
665 buf_addr,
666 buf_len,
667 flags.into(),
668 by_ref(&encode_sockaddr_xdp(addr)),
669 size_of::<c::sockaddr_xdp, _>(),
670 ])
671 ))
672 }
673}
674
675#[inline]
676pub(crate) unsafe fn recv(
677 fd: BorrowedFd<'_>,
678 buf: *mut u8,
679 len: usize,
680 flags: RecvFlags,
681) -> io::Result<usize> {
682 #[cfg(not(any(
683 target_arch = "aarch64",
684 target_arch = "mips64",
685 target_arch = "mips64r6",
686 target_arch = "riscv64",
687 target_arch = "s390x",
688 target_arch = "x86",
689 target_arch = "x86_64",
690 )))]
691 {
692 ret_usize(syscall!(__NR_recv, fd, buf, pass_usize(len), flags))
693 }
694 #[cfg(any(
695 target_arch = "aarch64",
696 target_arch = "mips64",
697 target_arch = "mips64r6",
698 target_arch = "riscv64",
699 target_arch = "s390x",
700 target_arch = "x86_64",
701 ))]
702 {
703 ret_usize(syscall!(
704 __NR_recvfrom,
705 fd,
706 buf,
707 pass_usize(len),
708 flags,
709 zero(),
710 zero()
711 ))
712 }
713 #[cfg(target_arch = "x86")]
714 {
715 ret_usize(syscall!(
716 __NR_socketcall,
717 x86_sys(SYS_RECV),
718 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
719 fd.into(),
720 buf.into(),
721 pass_usize(len),
722 flags.into(),
723 ])
724 ))
725 }
726}
727
728#[inline]
729pub(crate) unsafe fn recvfrom(
730 fd: BorrowedFd<'_>,
731 buf: *mut u8,
732 len: usize,
733 flags: RecvFlags,
734) -> io::Result<(usize, Option<SocketAddrAny>)> {
735 let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
736 let mut storage = MaybeUninit::<sockaddr>::uninit();
737
738 initialize_family_to_unspec(storage.as_mut_ptr());
742
743 #[cfg(not(target_arch = "x86"))]
744 let nread = ret_usize(syscall!(
745 __NR_recvfrom,
746 fd,
747 buf,
748 pass_usize(len),
749 flags,
750 &mut storage,
751 by_mut(&mut addrlen)
752 ))?;
753 #[cfg(target_arch = "x86")]
754 let nread = ret_usize(syscall!(
755 __NR_socketcall,
756 x86_sys(SYS_RECVFROM),
757 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
758 fd.into(),
759 buf.into(),
760 pass_usize(len),
761 flags.into(),
762 (&mut storage).into(),
763 by_mut(&mut addrlen),
764 ])
765 ))?;
766
767 Ok((
768 nread,
769 maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()),
770 ))
771}
772
773#[inline]
774pub(crate) fn getpeername(fd: BorrowedFd<'_>) -> io::Result<Option<SocketAddrAny>> {
775 #[cfg(not(target_arch = "x86"))]
776 unsafe {
777 let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
778 let mut storage = MaybeUninit::<sockaddr>::uninit();
779 ret(syscall!(
780 __NR_getpeername,
781 fd,
782 &mut storage,
783 by_mut(&mut addrlen)
784 ))?;
785 Ok(maybe_read_sockaddr_os(
786 &storage.assume_init(),
787 addrlen.try_into().unwrap(),
788 ))
789 }
790 #[cfg(target_arch = "x86")]
791 unsafe {
792 let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
793 let mut storage = MaybeUninit::<sockaddr>::uninit();
794 ret(syscall!(
795 __NR_socketcall,
796 x86_sys(SYS_GETPEERNAME),
797 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
798 fd.into(),
799 (&mut storage).into(),
800 by_mut(&mut addrlen),
801 ])
802 ))?;
803 Ok(maybe_read_sockaddr_os(
804 &storage.assume_init(),
805 addrlen.try_into().unwrap(),
806 ))
807 }
808}
809
810#[inline]
811pub(crate) fn getsockname(fd: BorrowedFd<'_>) -> io::Result<SocketAddrAny> {
812 #[cfg(not(target_arch = "x86"))]
813 unsafe {
814 let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
815 let mut storage = MaybeUninit::<sockaddr>::uninit();
816 ret(syscall!(
817 __NR_getsockname,
818 fd,
819 &mut storage,
820 by_mut(&mut addrlen)
821 ))?;
822 Ok(read_sockaddr_os(
823 &storage.assume_init(),
824 addrlen.try_into().unwrap(),
825 ))
826 }
827 #[cfg(target_arch = "x86")]
828 unsafe {
829 let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
830 let mut storage = MaybeUninit::<sockaddr>::uninit();
831 ret(syscall!(
832 __NR_socketcall,
833 x86_sys(SYS_GETSOCKNAME),
834 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
835 fd.into(),
836 (&mut storage).into(),
837 by_mut(&mut addrlen),
838 ])
839 ))?;
840 Ok(read_sockaddr_os(
841 &storage.assume_init(),
842 addrlen.try_into().unwrap(),
843 ))
844 }
845}
846
847#[inline]
848pub(crate) fn bind_v4(fd: BorrowedFd<'_>, addr: &SocketAddrV4) -> io::Result<()> {
849 #[cfg(not(target_arch = "x86"))]
850 unsafe {
851 ret(syscall_readonly!(
852 __NR_bind,
853 fd,
854 by_ref(&encode_sockaddr_v4(addr)),
855 size_of::<sockaddr_in, _>()
856 ))
857 }
858 #[cfg(target_arch = "x86")]
859 unsafe {
860 ret(syscall_readonly!(
861 __NR_socketcall,
862 x86_sys(SYS_BIND),
863 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
864 fd.into(),
865 by_ref(&encode_sockaddr_v4(addr)),
866 size_of::<sockaddr_in, _>(),
867 ])
868 ))
869 }
870}
871
872#[inline]
873pub(crate) fn bind_v6(fd: BorrowedFd<'_>, addr: &SocketAddrV6) -> io::Result<()> {
874 #[cfg(not(target_arch = "x86"))]
875 unsafe {
876 ret(syscall_readonly!(
877 __NR_bind,
878 fd,
879 by_ref(&encode_sockaddr_v6(addr)),
880 size_of::<sockaddr_in6, _>()
881 ))
882 }
883 #[cfg(target_arch = "x86")]
884 unsafe {
885 ret(syscall_readonly!(
886 __NR_socketcall,
887 x86_sys(SYS_BIND),
888 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
889 fd.into(),
890 by_ref(&encode_sockaddr_v6(addr)),
891 size_of::<sockaddr_in6, _>(),
892 ])
893 ))
894 }
895}
896
897#[inline]
898pub(crate) fn bind_unix(fd: BorrowedFd<'_>, addr: &SocketAddrUnix) -> io::Result<()> {
899 #[cfg(not(target_arch = "x86"))]
900 unsafe {
901 ret(syscall_readonly!(
902 __NR_bind,
903 fd,
904 by_ref(&addr.unix),
905 socklen_t(addr.addr_len())
906 ))
907 }
908 #[cfg(target_arch = "x86")]
909 unsafe {
910 ret(syscall_readonly!(
911 __NR_socketcall,
912 x86_sys(SYS_BIND),
913 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
914 fd.into(),
915 by_ref(&addr.unix),
916 socklen_t(addr.addr_len()),
917 ])
918 ))
919 }
920}
921
922#[cfg(target_os = "linux")]
923#[inline]
924pub(crate) fn bind_xdp(fd: BorrowedFd<'_>, addr: &SocketAddrXdp) -> io::Result<()> {
925 #[cfg(not(target_arch = "x86"))]
926 unsafe {
927 ret(syscall_readonly!(
928 __NR_bind,
929 fd,
930 by_ref(&encode_sockaddr_xdp(addr)),
931 size_of::<c::sockaddr_xdp, _>()
932 ))
933 }
934 #[cfg(target_arch = "x86")]
935 unsafe {
936 ret(syscall_readonly!(
937 __NR_socketcall,
938 x86_sys(SYS_BIND),
939 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
940 fd.into(),
941 by_ref(&encode_sockaddr_xdp(addr)),
942 size_of::<c::sockaddr_xdp, _>(),
943 ])
944 ))
945 }
946}
947
948#[inline]
949pub(crate) fn connect_v4(fd: BorrowedFd<'_>, addr: &SocketAddrV4) -> io::Result<()> {
950 #[cfg(not(target_arch = "x86"))]
951 unsafe {
952 ret(syscall_readonly!(
953 __NR_connect,
954 fd,
955 by_ref(&encode_sockaddr_v4(addr)),
956 size_of::<sockaddr_in, _>()
957 ))
958 }
959 #[cfg(target_arch = "x86")]
960 unsafe {
961 ret(syscall_readonly!(
962 __NR_socketcall,
963 x86_sys(SYS_CONNECT),
964 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
965 fd.into(),
966 by_ref(&encode_sockaddr_v4(addr)),
967 size_of::<sockaddr_in, _>(),
968 ])
969 ))
970 }
971}
972
973#[inline]
974pub(crate) fn connect_v6(fd: BorrowedFd<'_>, addr: &SocketAddrV6) -> io::Result<()> {
975 #[cfg(not(target_arch = "x86"))]
976 unsafe {
977 ret(syscall_readonly!(
978 __NR_connect,
979 fd,
980 by_ref(&encode_sockaddr_v6(addr)),
981 size_of::<sockaddr_in6, _>()
982 ))
983 }
984 #[cfg(target_arch = "x86")]
985 unsafe {
986 ret(syscall_readonly!(
987 __NR_socketcall,
988 x86_sys(SYS_CONNECT),
989 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
990 fd.into(),
991 by_ref(&encode_sockaddr_v6(addr)),
992 size_of::<sockaddr_in6, _>(),
993 ])
994 ))
995 }
996}
997
998#[inline]
999pub(crate) fn connect_unix(fd: BorrowedFd<'_>, addr: &SocketAddrUnix) -> io::Result<()> {
1000 #[cfg(not(target_arch = "x86"))]
1001 unsafe {
1002 ret(syscall_readonly!(
1003 __NR_connect,
1004 fd,
1005 by_ref(&addr.unix),
1006 socklen_t(addr.addr_len())
1007 ))
1008 }
1009 #[cfg(target_arch = "x86")]
1010 unsafe {
1011 ret(syscall_readonly!(
1012 __NR_socketcall,
1013 x86_sys(SYS_CONNECT),
1014 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
1015 fd.into(),
1016 by_ref(&addr.unix),
1017 socklen_t(addr.addr_len()),
1018 ])
1019 ))
1020 }
1021}
1022
1023#[inline]
1024pub(crate) fn connect_unspec(fd: BorrowedFd<'_>) -> io::Result<()> {
1025 debug_assert_eq!(c::AF_UNSPEC, 0);
1026 let addr = MaybeUninit::<c::sockaddr_storage>::zeroed();
1027
1028 #[cfg(not(target_arch = "x86"))]
1029 unsafe {
1030 ret(syscall_readonly!(
1031 __NR_connect,
1032 fd,
1033 by_ref(&addr),
1034 size_of::<c::sockaddr_storage, _>()
1035 ))
1036 }
1037 #[cfg(target_arch = "x86")]
1038 unsafe {
1039 ret(syscall_readonly!(
1040 __NR_socketcall,
1041 x86_sys(SYS_CONNECT),
1042 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
1043 fd.into(),
1044 by_ref(&addr),
1045 size_of::<c::sockaddr_storage, _>(),
1046 ])
1047 ))
1048 }
1049}
1050
1051#[inline]
1052pub(crate) fn listen(fd: BorrowedFd<'_>, backlog: c::c_int) -> io::Result<()> {
1053 #[cfg(not(target_arch = "x86"))]
1054 unsafe {
1055 ret(syscall_readonly!(__NR_listen, fd, c_int(backlog)))
1056 }
1057 #[cfg(target_arch = "x86")]
1058 unsafe {
1059 ret(syscall_readonly!(
1060 __NR_socketcall,
1061 x86_sys(SYS_LISTEN),
1062 slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[fd.into(), c_int(backlog)])
1063 ))
1064 }
1065}