1mod async_impl;
6mod config;
7mod sync_impl;
8
9use std::io;
10
11use socket2::Socket;
12
13use crate::SocketFamily;
14
15#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
16fn set_bool_sockopt(
17 socket: &Socket,
18 level: libc::c_int,
19 optname: libc::c_int,
20 on: bool,
21) -> io::Result<()> {
22 use std::os::fd::AsRawFd;
23 let value: libc::c_int = if on { 1 } else { 0 };
24 let ret = unsafe {
25 libc::setsockopt(
26 socket.as_raw_fd(),
27 level,
28 optname,
29 (&value as *const libc::c_int).cast(),
30 std::mem::size_of::<libc::c_int>() as libc::socklen_t,
31 )
32 };
33 if ret == 0 {
34 Ok(())
35 } else {
36 Err(io::Error::last_os_error())
37 }
38}
39
40#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
41fn get_bool_sockopt(socket: &Socket, level: libc::c_int, optname: libc::c_int) -> io::Result<bool> {
42 use std::os::fd::AsRawFd;
43 let mut value: libc::c_int = 0;
44 let mut len = std::mem::size_of::<libc::c_int>() as libc::socklen_t;
45 let ret = unsafe {
46 libc::getsockopt(
47 socket.as_raw_fd(),
48 level,
49 optname,
50 (&mut value as *mut libc::c_int).cast(),
51 &mut len,
52 )
53 };
54 if ret == 0 {
55 Ok(value != 0)
56 } else {
57 Err(io::Error::last_os_error())
58 }
59}
60
61pub(crate) fn set_recv_pktinfo(socket: &Socket, family: SocketFamily, on: bool) -> io::Result<()> {
62 match family {
63 SocketFamily::IPV4 => set_recv_pktinfo_v4(socket, on),
64 SocketFamily::IPV6 => set_recv_pktinfo_v6(socket, on),
65 }
66}
67
68#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
69pub(crate) fn set_recv_pktinfo_v4(socket: &Socket, on: bool) -> io::Result<()> {
70 set_bool_sockopt(socket, libc::IPPROTO_IP, libc::IP_PKTINFO, on)
71}
72
73#[cfg(not(any(target_os = "android", target_os = "fuchsia", target_os = "linux")))]
74pub(crate) fn set_recv_pktinfo_v4(_socket: &Socket, _on: bool) -> io::Result<()> {
75 Err(io::Error::new(
76 io::ErrorKind::Unsupported,
77 "IP_PKTINFO is not supported on this platform",
78 ))
79}
80
81#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
82pub(crate) fn set_recv_pktinfo_v6(socket: &Socket, on: bool) -> io::Result<()> {
83 set_bool_sockopt(socket, libc::IPPROTO_IPV6, libc::IPV6_RECVPKTINFO, on)
84}
85
86#[cfg(not(any(target_os = "android", target_os = "fuchsia", target_os = "linux")))]
87pub(crate) fn set_recv_pktinfo_v6(_socket: &Socket, _on: bool) -> io::Result<()> {
88 Err(io::Error::new(
89 io::ErrorKind::Unsupported,
90 "IPV6_RECVPKTINFO is not supported on this platform",
91 ))
92}
93
94#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
95pub(crate) fn recv_pktinfo_v4(socket: &Socket) -> io::Result<bool> {
96 get_bool_sockopt(socket, libc::IPPROTO_IP, libc::IP_PKTINFO)
97}
98
99#[cfg(not(any(target_os = "android", target_os = "fuchsia", target_os = "linux")))]
100pub(crate) fn recv_pktinfo_v4(_socket: &Socket) -> io::Result<bool> {
101 Err(io::Error::new(
102 io::ErrorKind::Unsupported,
103 "IP_PKTINFO is not supported on this platform",
104 ))
105}
106
107#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
108pub(crate) fn recv_pktinfo_v6(socket: &Socket) -> io::Result<bool> {
109 get_bool_sockopt(socket, libc::IPPROTO_IPV6, libc::IPV6_RECVPKTINFO)
110}
111
112#[cfg(not(any(target_os = "android", target_os = "fuchsia", target_os = "linux")))]
113pub(crate) fn recv_pktinfo_v6(_socket: &Socket) -> io::Result<bool> {
114 Err(io::Error::new(
115 io::ErrorKind::Unsupported,
116 "IPV6_RECVPKTINFO is not supported on this platform",
117 ))
118}
119
120pub use async_impl::*;
121pub use config::*;
122pub use sync_impl::*;