1#[cfg(any(linux_android, target_os = "illumos"))]
3use super::SetSockOpt;
4use crate::sys::time::TimeVal;
5#[cfg(any(linux_android, target_os = "illumos"))]
6use crate::{errno::Errno, Result};
7use cfg_if::cfg_if;
8use libc::{self, c_int, c_void, socklen_t};
9#[cfg(apple_targets)]
10use std::ffi::CString;
11use std::ffi::{CStr, OsStr, OsString};
12use std::mem::{self, MaybeUninit};
13use std::os::fd::OwnedFd;
14use std::os::unix::ffi::OsStrExt;
15#[cfg(any(linux_android, target_os = "illumos"))]
16use std::os::unix::io::{AsFd, AsRawFd};
17
18#[cfg(any(target_os = "freebsd", target_os = "linux"))]
21#[cfg(feature = "net")]
22const TCP_CA_NAME_MAX: usize = 16;
23
24#[macro_export]
47macro_rules! setsockopt_impl {
48 ($name:ident, $level:expr, $flag:path, $ty:ty, $setter:ty) => {
49 #[allow(deprecated)] impl $crate::sys::socket::SetSockOpt for $name {
51 type Val = $ty;
52
53 fn set<F: std::os::unix::io::AsFd>(
54 &self,
55 fd: &F,
56 val: &$ty,
57 ) -> $crate::Result<()> {
58 use std::os::fd::AsRawFd;
59 use $crate::sys::socket::sockopt::Set;
60 let setter: $setter = Set::new(val);
61 let level = $level;
62 let flag = $flag;
63 let res = unsafe {
64 libc::setsockopt(
65 fd.as_fd().as_raw_fd(),
66 level,
67 flag,
68 setter.ffi_ptr(),
69 setter.ffi_len(),
70 )
71 };
72 $crate::errno::Errno::result(res).map(drop)
73 }
74 }
75 };
76}
77
78#[macro_export]
101macro_rules! getsockopt_impl {
102 ($name:ident, $level:expr, $flag:path, $ty:ty, $getter:ty) => {
103 #[allow(deprecated)] impl $crate::sys::socket::GetSockOpt for $name {
105 type Val = $ty;
106
107 fn get<F: std::os::unix::io::AsFd>(
108 &self,
109 fd: &F,
110 ) -> $crate::Result<$ty> {
111 use std::os::fd::AsRawFd;
112 use $crate::sys::socket::sockopt::Get;
113 let mut getter: $getter = Get::uninit();
114 let level = $level;
115 let flag = $flag;
116 let res = unsafe {
117 libc::getsockopt(
118 fd.as_fd().as_raw_fd(),
119 level,
120 flag,
121 getter.ffi_ptr(),
122 getter.ffi_len(),
123 )
124 };
125 $crate::errno::Errno::result(res)?;
126
127 let gotten = unsafe { getter.assume_init() };
129 match <$ty>::try_from(gotten) {
130 #[allow(unreachable_patterns)]
144 Err(_) => Err($crate::errno::Errno::EINVAL),
145 Ok(r) => Ok(r),
146 }
147 }
148 }
149 };
150}
151
152#[allow(unused_macro_rules)]
179#[macro_export]
180macro_rules! sockopt_impl {
181 ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, bool) => {
182 sockopt_impl!($(#[$attr])*
183 $name, GetOnly, $level, $flag, bool, $crate::sys::socket::sockopt::GetBool);
184 };
185
186 ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, u8) => {
187 sockopt_impl!($(#[$attr])* $name, GetOnly, $level, $flag, u8, $crate::sys::socket::sockopt::GetU8);
188 };
189
190 ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, usize) =>
191 {
192 sockopt_impl!($(#[$attr])*
193 $name, GetOnly, $level, $flag, usize, $crate::sys::socket::sockopt::GetUsize);
194 };
195
196 ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, OwnedFd) =>
197 {
198 sockopt_impl!($(#[$attr])*
199 $name, GetOnly, $level, $flag, OwnedFd, $crate::sys::socket::sockopt::GetOwnedFd);
200 };
201
202 ($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, bool) => {
203 sockopt_impl!($(#[$attr])*
204 $name, SetOnly, $level, $flag, bool, $crate::sys::socket::sockopt::SetBool);
205 };
206
207 ($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, u8) => {
208 sockopt_impl!($(#[$attr])* $name, SetOnly, $level, $flag, u8, $crate::sys::socket::sockopt::SetU8);
209 };
210
211 ($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, usize) =>
212 {
213 sockopt_impl!($(#[$attr])*
214 $name, SetOnly, $level, $flag, usize, $crate::sys::socket::sockopt::SetUsize);
215 };
216
217 ($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, OwnedFd) =>
218 {
219 sockopt_impl!($(#[$attr])*
220 $name, SetOnly, $level, $flag, OwnedFd, $crate::sys::socket::sockopt::SetOwnedFd);
221 };
222
223 ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, bool) => {
224 sockopt_impl!($(#[$attr])*
225 $name, Both, $level, $flag, bool, $crate::sys::socket::sockopt::GetBool, $crate::sys::socket::sockopt::SetBool);
226 };
227
228 ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, u8) => {
229 sockopt_impl!($(#[$attr])*
230 $name, Both, $level, $flag, u8, $crate::sys::socket::sockopt::GetU8, $crate::sys::socket::sockopt::SetU8);
231 };
232
233 ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, usize) => {
234 sockopt_impl!($(#[$attr])*
235 $name, Both, $level, $flag, usize, $crate::sys::socket::sockopt::GetUsize, $crate::sys::socket::sockopt::SetUsize);
236 };
237
238 ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, OwnedFd) => {
239 sockopt_impl!($(#[$attr])*
240 $name, Both, $level, $flag, OwnedFd, $crate::sys::socket::sockopt::GetOwnedFd, $crate::sys::socket::sockopt::SetOwnedFd);
241 };
242
243 ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path,
244 OsString<$array:ty>) =>
245 {
246 sockopt_impl!($(#[$attr])*
247 $name, Both, $level, $flag, std::ffi::OsString, $crate::sys::socket::sockopt::GetOsString<$array>,
248 $crate::sys::socket::sockopt::SetOsString);
249 };
250
251 ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, $ty:ty) =>
256 {
257 sockopt_impl!($(#[$attr])*
258 $name, GetOnly, $level, $flag, $ty, $crate::sys::socket::sockopt::GetStruct<$ty>);
259 };
260
261 ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, $ty:ty,
262 $getter:ty) =>
263 {
264 $(#[$attr])*
265 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
266 pub struct $name;
267
268 getsockopt_impl!($name, $level, $flag, $ty, $getter);
269 };
270
271 ($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, $ty:ty) =>
272 {
273 sockopt_impl!($(#[$attr])*
274 $name, SetOnly, $level, $flag, $ty, $crate::sys::socket::sockopt::SetStruct<$ty>);
275 };
276
277 ($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, $ty:ty,
278 $setter:ty) =>
279 {
280 $(#[$attr])*
281 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
282 pub struct $name;
283
284 setsockopt_impl!($name, $level, $flag, $ty, $setter);
285 };
286
287 ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, $ty:ty,
288 $getter:ty, $setter:ty) =>
289 {
290 $(#[$attr])*
291 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
292 pub struct $name;
293
294 setsockopt_impl!($name, $level, $flag, $ty, $setter);
295 getsockopt_impl!($name, $level, $flag, $ty, $getter);
296 };
297
298 ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, $ty:ty) => {
299 sockopt_impl!($(#[$attr])*
300 $name, Both, $level, $flag, $ty, $crate::sys::socket::sockopt::GetStruct<$ty>,
301 $crate::sys::socket::sockopt::SetStruct<$ty>);
302 };
303}
304
305sockopt_impl!(
312 ReuseAddr,
314 Both,
315 libc::SOL_SOCKET,
316 libc::SO_REUSEADDR,
317 bool
318);
319#[cfg(not(any(solarish, target_os = "cygwin")))]
320sockopt_impl!(
321 ReusePort,
324 Both,
325 libc::SOL_SOCKET,
326 libc::SO_REUSEPORT,
327 bool
328);
329#[cfg(target_os = "freebsd")]
330sockopt_impl!(
331 ReusePortLb,
334 Both,
335 libc::SOL_SOCKET,
336 libc::SO_REUSEPORT_LB,
337 bool
338);
339#[cfg(target_os = "freebsd")]
340#[cfg(feature = "net")]
341sockopt_impl!(
342 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
343 TcpFunctionBlk,
346 Both,
347 libc::IPPROTO_TCP,
348 libc::TCP_FUNCTION_BLK,
349 libc::tcp_function_set
350);
351#[cfg(target_os = "freebsd")]
352#[cfg(feature = "net")]
353sockopt_impl!(
354 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
355 TcpFunctionAlias,
359 GetOnly,
360 libc::IPPROTO_TCP,
361 libc::TCP_FUNCTION_ALIAS,
362 libc::tcp_function_set
363);
364sockopt_impl!(
365 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
366 TcpNoDelay,
378 Both,
379 libc::IPPROTO_TCP,
380 libc::TCP_NODELAY,
381 bool
382);
383sockopt_impl!(
384 Linger,
388 Both,
389 libc::SOL_SOCKET,
390 libc::SO_LINGER,
391 libc::linger
392);
393#[cfg(apple_targets)]
394sockopt_impl!(
395 LingerSec,
397 Both,
398 libc::SOL_SOCKET,
399 libc::SO_LINGER_SEC,
400 libc::linger
401);
402#[cfg(feature = "net")]
403sockopt_impl!(
404 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
405 IpAddMembership,
407 SetOnly,
408 libc::IPPROTO_IP,
409 libc::IP_ADD_MEMBERSHIP,
410 super::IpMembershipRequest
411);
412#[cfg(feature = "net")]
413sockopt_impl!(
414 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
415 IpDropMembership,
417 SetOnly,
418 libc::IPPROTO_IP,
419 libc::IP_DROP_MEMBERSHIP,
420 super::IpMembershipRequest
421);
422cfg_if! {
423 if #[cfg(linux_android)] {
424 #[cfg(feature = "net")]
425 sockopt_impl!(
426 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
427 Ipv6AddMembership, SetOnly, libc::IPPROTO_IPV6, libc::IPV6_ADD_MEMBERSHIP, super::Ipv6MembershipRequest);
429 #[cfg(feature = "net")]
430 sockopt_impl!(
431 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
432 Ipv6DropMembership, SetOnly, libc::IPPROTO_IPV6, libc::IPV6_DROP_MEMBERSHIP, super::Ipv6MembershipRequest);
434 } else if #[cfg(any(bsd, solarish))] {
435 #[cfg(feature = "net")]
436 sockopt_impl!(
437 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
438 Ipv6AddMembership, SetOnly, libc::IPPROTO_IPV6,
440 libc::IPV6_JOIN_GROUP, super::Ipv6MembershipRequest);
441 #[cfg(feature = "net")]
442 sockopt_impl!(
443 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
444 Ipv6DropMembership, SetOnly, libc::IPPROTO_IPV6,
446 libc::IPV6_LEAVE_GROUP, super::Ipv6MembershipRequest);
447 }
448}
449#[cfg(feature = "net")]
450sockopt_impl!(
451 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
452 IpMulticastTtl,
455 Both,
456 libc::IPPROTO_IP,
457 libc::IP_MULTICAST_TTL,
458 u8
459);
460#[cfg(feature = "net")]
461sockopt_impl!(
462 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
463 Ipv6MulticastHops,
466 Both,
467 libc::IPPROTO_IPV6,
468 libc::IPV6_MULTICAST_HOPS,
469 libc::c_int
470);
471#[cfg(feature = "net")]
472sockopt_impl!(
473 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
474 IpMulticastLoop,
477 Both,
478 libc::IPPROTO_IP,
479 libc::IP_MULTICAST_LOOP,
480 bool
481);
482#[cfg(target_os = "linux")]
483#[cfg(feature = "net")]
484sockopt_impl!(
485 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
486 Priority,
489 Both,
490 libc::SOL_SOCKET,
491 libc::SO_PRIORITY,
492 libc::c_int
493);
494#[cfg(any(linux_android, target_os = "freebsd"))]
495#[cfg(feature = "net")]
496sockopt_impl!(
497 #[deprecated(since = "0.30.0", note = "Use Ipv4Tos instead")]
498 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
499 IpTos,
502 Both,
503 libc::IPPROTO_IP,
504 libc::IP_TOS,
505 libc::c_int
506);
507#[cfg(any(linux_android, target_os = "freebsd"))]
508#[cfg(feature = "net")]
509sockopt_impl!(
510 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
511 Ipv4Tos,
514 Both,
515 libc::IPPROTO_IP,
516 libc::IP_TOS,
517 libc::c_int
518);
519#[cfg(any(linux_android, target_os = "freebsd"))]
520#[cfg(feature = "net")]
521sockopt_impl!(
522 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
523 IpRecvTos,
525 Both,
526 libc::IPPROTO_IP,
527 libc::IP_RECVTOS,
528 bool
529);
530#[cfg(any(linux_android, target_os = "freebsd"))]
531#[cfg(feature = "net")]
532sockopt_impl!(
533 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
534 Ipv6TClass,
536 Both,
537 libc::IPPROTO_IPV6,
538 libc::IPV6_TCLASS,
539 libc::c_int
540);
541#[cfg(any(linux_android, target_os = "freebsd"))]
542#[cfg(feature = "net")]
543sockopt_impl!(
544 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
545 Ipv6RecvTClass,
547 Both,
548 libc::IPPROTO_IPV6,
549 libc::IPV6_RECVTCLASS,
550 bool
551);
552#[cfg(any(linux_android, target_os = "fuchsia"))]
553#[cfg(feature = "net")]
554sockopt_impl!(
555 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
556 IpFreebind,
559 Both,
560 libc::IPPROTO_IP,
561 libc::IP_FREEBIND,
562 bool
563);
564#[cfg(linux_android)]
565#[cfg(feature = "net")]
566#[cfg(not(target_env = "uclibc"))]
567sockopt_impl!(
568 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
569 IpBindAddressNoPort,
574 Both,
575 libc::IPPROTO_IP,
576 libc::IP_BIND_ADDRESS_NO_PORT,
577 bool
578);
579sockopt_impl!(
580 ReceiveTimeout,
582 Both,
583 libc::SOL_SOCKET,
584 libc::SO_RCVTIMEO,
585 TimeVal
586);
587sockopt_impl!(
588 SendTimeout,
590 Both,
591 libc::SOL_SOCKET,
592 libc::SO_SNDTIMEO,
593 TimeVal
594);
595sockopt_impl!(
596 Broadcast,
598 Both,
599 libc::SOL_SOCKET,
600 libc::SO_BROADCAST,
601 bool
602);
603sockopt_impl!(
604 OobInline,
607 Both,
608 libc::SOL_SOCKET,
609 libc::SO_OOBINLINE,
610 bool
611);
612sockopt_impl!(
613 SocketError,
615 GetOnly,
616 libc::SOL_SOCKET,
617 libc::SO_ERROR,
618 i32
619);
620sockopt_impl!(
621 DontRoute,
623 Both,
624 libc::SOL_SOCKET,
625 libc::SO_DONTROUTE,
626 bool
627);
628sockopt_impl!(
629 KeepAlive,
631 Both,
632 libc::SOL_SOCKET,
633 libc::SO_KEEPALIVE,
634 bool
635);
636#[cfg(freebsdlike)]
637sockopt_impl!(
638 LocalPeerCred,
641 GetOnly,
642 0,
643 libc::LOCAL_PEERCRED,
644 super::XuCred
645);
646#[cfg(apple_targets)]
647sockopt_impl!(
648 LocalPeerCred,
651 GetOnly,
652 libc::SOL_LOCAL,
653 libc::LOCAL_PEERCRED,
654 super::XuCred
655);
656#[cfg(apple_targets)]
657sockopt_impl!(
658 LocalPeerPid,
660 GetOnly,
661 libc::SOL_LOCAL,
662 libc::LOCAL_PEERPID,
663 libc::c_int
664);
665#[cfg(apple_targets)]
666sockopt_impl!(
667 LocalPeerToken,
670 GetOnly,
671 libc::SOL_LOCAL,
672 libc::LOCAL_PEERTOKEN,
673 super::audit_token_t
674);
675#[cfg(linux_android)]
676sockopt_impl!(
677 PeerCredentials,
679 GetOnly,
680 libc::SOL_SOCKET,
681 libc::SO_PEERCRED,
682 super::UnixCredentials
683);
684#[cfg(target_os = "linux")]
685sockopt_impl!(
686 PeerPidfd,
688 GetOnly,
689 libc::SOL_SOCKET,
690 libc::SO_PEERPIDFD,
691 OwnedFd
692);
693#[cfg(target_os = "freebsd")]
694#[cfg(feature = "net")]
695sockopt_impl!(
696 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
697 ListenQLimit,
699 GetOnly,
700 libc::SOL_SOCKET,
701 libc::SO_LISTENQLIMIT,
702 u32
703);
704#[cfg(apple_targets)]
705#[cfg(feature = "net")]
706sockopt_impl!(
707 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
708 TcpKeepAlive,
711 Both,
712 libc::IPPROTO_TCP,
713 libc::TCP_KEEPALIVE,
714 u32
715);
716#[cfg(any(freebsdlike, linux_android))]
717#[cfg(feature = "net")]
718sockopt_impl!(
719 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
720 TcpKeepIdle,
723 Both,
724 libc::IPPROTO_TCP,
725 libc::TCP_KEEPIDLE,
726 u32
727);
728cfg_if! {
729 if #[cfg(any(linux_android, apple_targets))] {
730 sockopt_impl!(
731 TcpMaxSeg, Both, libc::IPPROTO_TCP, libc::TCP_MAXSEG, u32);
733 } else if #[cfg(not(target_os = "redox"))] {
734 sockopt_impl!(
735 TcpMaxSeg, GetOnly, libc::IPPROTO_TCP, libc::TCP_MAXSEG, u32);
737 }
738}
739#[cfg(not(any(
740 target_os = "openbsd",
741 target_os = "haiku",
742 target_os = "redox"
743)))]
744#[cfg(feature = "net")]
745sockopt_impl!(
746 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
747 TcpKeepCount,
750 Both,
751 libc::IPPROTO_TCP,
752 libc::TCP_KEEPCNT,
753 u32
754);
755#[cfg(any(linux_android, target_os = "fuchsia"))]
756sockopt_impl!(
757 #[allow(missing_docs)]
758 TcpRepair,
760 Both,
761 libc::IPPROTO_TCP,
762 libc::TCP_REPAIR,
763 u32
764);
765#[cfg(not(any(
766 target_os = "openbsd",
767 target_os = "haiku",
768 target_os = "redox"
769)))]
770#[cfg(feature = "net")]
771sockopt_impl!(
772 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
773 TcpKeepInterval,
775 Both,
776 libc::IPPROTO_TCP,
777 libc::TCP_KEEPINTVL,
778 u32
779);
780#[cfg(any(target_os = "fuchsia", target_os = "linux"))]
781#[cfg(feature = "net")]
782sockopt_impl!(
783 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
784 TcpUserTimeout,
788 Both,
789 libc::IPPROTO_TCP,
790 libc::TCP_USER_TIMEOUT,
791 u32
792);
793#[cfg(linux_android)]
794#[cfg(feature = "net")]
795sockopt_impl!(
796 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
797 TcpFastOpenConnect,
808 Both,
809 libc::IPPROTO_TCP,
810 libc::TCP_FASTOPEN_CONNECT,
811 bool
812);
813sockopt_impl!(
814 RcvBuf,
816 Both,
817 libc::SOL_SOCKET,
818 libc::SO_RCVBUF,
819 usize
820);
821sockopt_impl!(
822 SndBuf,
824 Both,
825 libc::SOL_SOCKET,
826 libc::SO_SNDBUF,
827 usize
828);
829#[cfg(linux_android)]
830sockopt_impl!(
831 RcvBufForce,
835 SetOnly,
836 libc::SOL_SOCKET,
837 libc::SO_RCVBUFFORCE,
838 usize
839);
840#[cfg(linux_android)]
841sockopt_impl!(
842 SndBufForce,
846 SetOnly,
847 libc::SOL_SOCKET,
848 libc::SO_SNDBUFFORCE,
849 usize
850);
851sockopt_impl!(
852 SockType,
854 GetOnly,
855 libc::SOL_SOCKET,
856 libc::SO_TYPE,
857 super::SockType,
858 GetStruct<i32>
859);
860sockopt_impl!(
861 AcceptConn,
864 GetOnly,
865 libc::SOL_SOCKET,
866 libc::SO_ACCEPTCONN,
867 bool
868);
869#[cfg(linux_android)]
870sockopt_impl!(
871 BindToDevice,
873 Both,
874 libc::SOL_SOCKET,
875 libc::SO_BINDTODEVICE,
876 OsString<[u8; libc::IFNAMSIZ]>
877);
878#[cfg(linux_android)]
879#[cfg(feature = "net")]
880sockopt_impl!(
881 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
882 #[allow(missing_docs)]
883 OriginalDst,
885 GetOnly,
886 libc::SOL_IP,
887 libc::SO_ORIGINAL_DST,
888 libc::sockaddr_in
889);
890#[cfg(linux_android)]
891sockopt_impl!(
892 #[allow(missing_docs)]
893 Ip6tOriginalDst,
895 GetOnly,
896 libc::SOL_IPV6,
897 libc::IP6T_SO_ORIGINAL_DST,
898 libc::sockaddr_in6
899);
900#[cfg(linux_android)]
901sockopt_impl!(
902 Timestamping,
905 Both,
906 libc::SOL_SOCKET,
907 libc::SO_TIMESTAMPING,
908 super::TimestampingFlag
909);
910#[cfg(not(any(
911 target_os = "aix",
912 target_os = "haiku",
913 target_os = "hurd",
914 target_os = "redox",
915 target_os = "cygwin"
916)))]
917sockopt_impl!(
918 ReceiveTimestamp,
920 Both,
921 libc::SOL_SOCKET,
922 libc::SO_TIMESTAMP,
923 bool
924);
925#[cfg(linux_android)]
926sockopt_impl!(
927 ReceiveTimestampns,
929 Both,
930 libc::SOL_SOCKET,
931 libc::SO_TIMESTAMPNS,
932 bool
933);
934#[cfg(target_os = "freebsd")]
935sockopt_impl!(
936 TsClock,
939 Both,
940 libc::SOL_SOCKET,
941 libc::SO_TS_CLOCK,
942 super::SocketTimestamp
943);
944#[cfg(linux_android)]
945#[cfg(feature = "net")]
946sockopt_impl!(
947 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
948 IpTransparent,
950 Both,
951 libc::SOL_IP,
952 libc::IP_TRANSPARENT,
953 bool
954);
955#[cfg(target_os = "openbsd")]
956#[cfg(feature = "net")]
957sockopt_impl!(
958 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
959 BindAny,
962 Both,
963 libc::SOL_SOCKET,
964 libc::SO_BINDANY,
965 bool
966);
967#[cfg(target_os = "freebsd")]
968#[cfg(feature = "net")]
969sockopt_impl!(
970 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
971 BindAny,
974 Both,
975 libc::IPPROTO_IP,
976 libc::IP_BINDANY,
977 bool
978);
979#[cfg(target_os = "freebsd")]
980sockopt_impl!(
981 Fib,
984 SetOnly,
985 libc::SOL_SOCKET,
986 libc::SO_SETFIB,
987 i32
988);
989#[cfg(target_os = "freebsd")]
990sockopt_impl!(
991 UserCookie,
994 SetOnly,
995 libc::SOL_SOCKET,
996 libc::SO_USER_COOKIE,
997 u32
998);
999#[cfg(target_os = "openbsd")]
1000sockopt_impl!(
1001 Rtable,
1004 SetOnly,
1005 libc::SOL_SOCKET,
1006 libc::SO_RTABLE,
1007 i32
1008);
1009#[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
1010sockopt_impl!(
1011 AcceptFilter,
1014 Both,
1015 libc::SOL_SOCKET,
1016 libc::SO_ACCEPTFILTER,
1017 libc::accept_filter_arg
1018);
1019#[cfg(target_os = "linux")]
1020sockopt_impl!(
1021 Mark,
1024 Both,
1025 libc::SOL_SOCKET,
1026 libc::SO_MARK,
1027 u32
1028);
1029#[cfg(linux_android)]
1030sockopt_impl!(
1031 PassCred,
1034 Both,
1035 libc::SOL_SOCKET,
1036 libc::SO_PASSCRED,
1037 bool
1038);
1039#[cfg(any(target_os = "freebsd", target_os = "linux"))]
1040#[cfg(feature = "net")]
1041sockopt_impl!(
1042 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1043 TcpCongestion,
1046 Both,
1047 libc::IPPROTO_TCP,
1048 libc::TCP_CONGESTION,
1049 OsString<[u8; TCP_CA_NAME_MAX]>
1050);
1051#[cfg(any(linux_android, apple_targets, target_os = "netbsd"))]
1052#[cfg(feature = "net")]
1053sockopt_impl!(
1054 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1055 Ipv4PacketInfo,
1058 Both,
1059 libc::IPPROTO_IP,
1060 libc::IP_PKTINFO,
1061 bool
1062);
1063#[cfg(any(linux_android, bsd))]
1064#[cfg(feature = "net")]
1065sockopt_impl!(
1066 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1067 Ipv6RecvPacketInfo,
1070 Both,
1071 libc::IPPROTO_IPV6,
1072 libc::IPV6_RECVPKTINFO,
1073 bool
1074);
1075
1076#[cfg(any(linux_android, bsd))]
1077#[cfg(feature = "net")]
1078sockopt_impl!(
1079 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1080 Ipv6PacketInfo,
1083 Both,
1084 libc::IPPROTO_IPV6,
1085 libc::IPV6_PKTINFO,
1086 bool
1087);
1088#[cfg(bsd)]
1089#[cfg(feature = "net")]
1090sockopt_impl!(
1091 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1092 Ipv4RecvIf,
1095 Both,
1096 libc::IPPROTO_IP,
1097 libc::IP_RECVIF,
1098 bool
1099);
1100#[cfg(bsd)]
1101#[cfg(feature = "net")]
1102sockopt_impl!(
1103 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1104 Ipv4RecvDstAddr,
1107 Both,
1108 libc::IPPROTO_IP,
1109 libc::IP_RECVDSTADDR,
1110 bool
1111);
1112#[cfg(any(linux_android, target_os = "freebsd"))]
1113#[cfg(feature = "net")]
1114sockopt_impl!(
1115 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1116 Ipv4OrigDstAddr,
1119 Both,
1120 libc::IPPROTO_IP,
1121 libc::IP_ORIGDSTADDR,
1122 bool
1123);
1124#[cfg(linux_android)]
1125#[cfg(feature = "net")]
1126sockopt_impl!(
1127 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1128 #[allow(missing_docs)]
1129 UdpGsoSegment,
1131 Both,
1132 libc::SOL_UDP,
1133 libc::UDP_SEGMENT,
1134 libc::c_int
1135);
1136#[cfg(linux_android)]
1137#[cfg(feature = "net")]
1138sockopt_impl!(
1139 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1140 #[allow(missing_docs)]
1141 UdpGroSegment,
1143 Both,
1144 libc::IPPROTO_UDP,
1145 libc::UDP_GRO,
1146 bool
1147);
1148#[cfg(target_os = "linux")]
1149sockopt_impl!(
1150 TxTime,
1153 Both,
1154 libc::SOL_SOCKET,
1155 libc::SO_TXTIME,
1156 libc::sock_txtime
1157);
1158#[cfg(any(linux_android, target_os = "fuchsia"))]
1159sockopt_impl!(
1160 RxqOvfl,
1164 Both,
1165 libc::SOL_SOCKET,
1166 libc::SO_RXQ_OVFL,
1167 libc::c_int
1168);
1169#[cfg(feature = "net")]
1170sockopt_impl!(
1171 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1172 Ipv6V6Only,
1174 Both,
1175 libc::IPPROTO_IPV6,
1176 libc::IPV6_V6ONLY,
1177 bool
1178);
1179#[cfg(linux_android)]
1180sockopt_impl!(
1181 Ipv4RecvErr,
1183 Both,
1184 libc::IPPROTO_IP,
1185 libc::IP_RECVERR,
1186 bool
1187);
1188#[cfg(linux_android)]
1189sockopt_impl!(
1190 Ipv6RecvErr,
1192 Both,
1193 libc::IPPROTO_IPV6,
1194 libc::IPV6_RECVERR,
1195 bool
1196);
1197#[cfg(linux_android)]
1198sockopt_impl!(
1199 IpMtu,
1201 GetOnly,
1202 libc::IPPROTO_IP,
1203 libc::IP_MTU,
1204 libc::c_int
1205);
1206#[cfg(any(linux_android, target_os = "freebsd"))]
1207sockopt_impl!(
1208 Ipv4Ttl,
1211 Both,
1212 libc::IPPROTO_IP,
1213 libc::IP_TTL,
1214 libc::c_int
1215);
1216#[cfg(any(linux_android, target_os = "freebsd"))]
1217#[cfg(feature = "net")]
1218sockopt_impl!(
1219 Ipv4RecvTtl,
1222 Both,
1223 libc::IPPROTO_IP,
1224 libc::IP_RECVTTL,
1225 bool
1226);
1227#[cfg(any(apple_targets, linux_android, target_os = "freebsd"))]
1228sockopt_impl!(
1229 Ipv6Ttl,
1231 Both,
1232 libc::IPPROTO_IPV6,
1233 libc::IPV6_UNICAST_HOPS,
1234 libc::c_int
1235);
1236#[cfg(any(linux_android, target_os = "freebsd"))]
1237#[cfg(feature = "net")]
1238sockopt_impl!(
1239 Ipv6RecvHopLimit,
1242 Both,
1243 libc::IPPROTO_IPV6,
1244 libc::IPV6_RECVHOPLIMIT,
1245 bool
1246);
1247#[cfg(any(
1248 all(linux_android, not(target_env = "uclibc")),
1249 target_os = "freebsd"
1250))]
1251#[cfg(feature = "net")]
1252sockopt_impl!(
1253 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1254 Ipv6OrigDstAddr,
1257 Both,
1258 libc::IPPROTO_IPV6,
1259 libc::IPV6_ORIGDSTADDR,
1260 bool
1261);
1262#[cfg(apple_targets)]
1263sockopt_impl!(
1264 IpDontFrag,
1266 Both,
1267 libc::IPPROTO_IP,
1268 libc::IP_DONTFRAG,
1269 bool
1270);
1271#[cfg(any(
1272 all(linux_android, not(target_env = "uclibc")),
1273 apple_targets
1274))]
1275sockopt_impl!(
1276 Ipv6DontFrag,
1278 Both,
1279 libc::IPPROTO_IPV6,
1280 libc::IPV6_DONTFRAG,
1281 bool
1282);
1283#[cfg(apple_targets)]
1284#[cfg(feature = "net")]
1285sockopt_impl!(
1286 UtunIfname,
1288 GetOnly,
1289 libc::SYSPROTO_CONTROL,
1290 libc::UTUN_OPT_IFNAME,
1291 CString,
1292 GetCString<[u8; libc::IFNAMSIZ]>
1293);
1294
1295#[cfg(solarish)]
1296sockopt_impl!(
1297 ExclBind,
1301 Both,
1302 libc::SOL_SOCKET,
1303 libc::SO_EXCLBIND,
1304 bool
1305);
1306#[cfg(target_os = "linux")]
1307sockopt_impl!(
1308 AttachReusePortCbpf,
1313 SetOnly,
1314 libc::SOL_SOCKET,
1315 libc::SO_ATTACH_REUSEPORT_CBPF,
1316 libc::sock_fprog
1317);
1318
1319#[allow(missing_docs)]
1320#[cfg(linux_android)]
1322#[derive(Copy, Clone, Debug)]
1323pub struct AlgSetAeadAuthSize;
1324
1325#[cfg(linux_android)]
1328impl SetSockOpt for AlgSetAeadAuthSize {
1329 type Val = usize;
1330
1331 fn set<F: AsFd>(&self, fd: &F, val: &usize) -> Result<()> {
1332 unsafe {
1333 let res = libc::setsockopt(
1334 fd.as_fd().as_raw_fd(),
1335 libc::SOL_ALG,
1336 libc::ALG_SET_AEAD_AUTHSIZE,
1337 ::std::ptr::null(),
1338 *val as libc::socklen_t,
1339 );
1340 Errno::result(res).map(drop)
1341 }
1342 }
1343}
1344
1345#[allow(missing_docs)]
1346#[cfg(linux_android)]
1348#[derive(Clone, Debug)]
1349pub struct AlgSetKey<T>(::std::marker::PhantomData<T>);
1350
1351#[cfg(linux_android)]
1352impl<T> Default for AlgSetKey<T> {
1353 fn default() -> Self {
1354 AlgSetKey(Default::default())
1355 }
1356}
1357
1358#[cfg(linux_android)]
1359impl<T> SetSockOpt for AlgSetKey<T>
1360where
1361 T: AsRef<[u8]> + Clone,
1362{
1363 type Val = T;
1364
1365 fn set<F: AsFd>(&self, fd: &F, val: &T) -> Result<()> {
1366 unsafe {
1367 let res = libc::setsockopt(
1368 fd.as_fd().as_raw_fd(),
1369 libc::SOL_ALG,
1370 libc::ALG_SET_KEY,
1371 val.as_ref().as_ptr().cast(),
1372 val.as_ref().len() as libc::socklen_t,
1373 );
1374 Errno::result(res).map(drop)
1375 }
1376 }
1377}
1378
1379#[cfg(linux_android)]
1395#[derive(Clone, Debug)]
1396pub struct TcpUlp<T>(::std::marker::PhantomData<T>);
1397
1398#[cfg(linux_android)]
1399impl<T> Default for TcpUlp<T> {
1400 fn default() -> Self {
1401 TcpUlp(Default::default())
1402 }
1403}
1404
1405#[cfg(linux_android)]
1406impl<T> SetSockOpt for TcpUlp<T>
1407where
1408 T: AsRef<[u8]> + Clone,
1409{
1410 type Val = T;
1411
1412 fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()> {
1413 unsafe {
1414 let res = libc::setsockopt(
1415 fd.as_fd().as_raw_fd(),
1416 libc::SOL_TCP,
1417 libc::TCP_ULP,
1418 val.as_ref().as_ptr().cast(),
1419 val.as_ref().len() as libc::socklen_t,
1420 );
1421 Errno::result(res).map(drop)
1422 }
1423 }
1424}
1425
1426#[cfg(target_os = "linux")]
1428#[derive(Copy, Clone, Debug)]
1429pub enum TlsCryptoInfo {
1430 Aes128Gcm(libc::tls12_crypto_info_aes_gcm_128),
1432
1433 Aes256Gcm(libc::tls12_crypto_info_aes_gcm_256),
1435
1436 Chacha20Poly1305(libc::tls12_crypto_info_chacha20_poly1305),
1438}
1439
1440#[cfg(target_os = "linux")]
1454#[derive(Copy, Clone, Debug)]
1455pub struct TcpTlsTx;
1456
1457#[cfg(target_os = "linux")]
1458impl SetSockOpt for TcpTlsTx {
1459 type Val = TlsCryptoInfo;
1460
1461 fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()> {
1462 let (ffi_ptr, ffi_len) = match val {
1463 TlsCryptoInfo::Aes128Gcm(crypto_info) => {
1464 (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info))
1465 }
1466 TlsCryptoInfo::Aes256Gcm(crypto_info) => {
1467 (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info))
1468 }
1469 TlsCryptoInfo::Chacha20Poly1305(crypto_info) => {
1470 (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info))
1471 }
1472 };
1473 unsafe {
1474 let res = libc::setsockopt(
1475 fd.as_fd().as_raw_fd(),
1476 libc::SOL_TLS,
1477 libc::TLS_TX,
1478 ffi_ptr,
1479 ffi_len as libc::socklen_t,
1480 );
1481 Errno::result(res).map(drop)
1482 }
1483 }
1484}
1485
1486#[cfg(target_os = "linux")]
1500#[derive(Copy, Clone, Debug)]
1501pub struct TcpTlsRx;
1502
1503#[cfg(target_os = "linux")]
1504impl SetSockOpt for TcpTlsRx {
1505 type Val = TlsCryptoInfo;
1506
1507 fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()> {
1508 let (ffi_ptr, ffi_len) = match val {
1509 TlsCryptoInfo::Aes128Gcm(crypto_info) => {
1510 (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info))
1511 }
1512 TlsCryptoInfo::Aes256Gcm(crypto_info) => {
1513 (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info))
1514 }
1515 TlsCryptoInfo::Chacha20Poly1305(crypto_info) => {
1516 (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info))
1517 }
1518 };
1519 unsafe {
1520 let res = libc::setsockopt(
1521 fd.as_fd().as_raw_fd(),
1522 libc::SOL_TLS,
1523 libc::TLS_RX,
1524 ffi_ptr,
1525 ffi_len as libc::socklen_t,
1526 );
1527 Errno::result(res).map(drop)
1528 }
1529 }
1530}
1531
1532#[cfg(target_os = "illumos")]
1533#[derive(Copy, Clone, Debug)]
1534pub struct FilterAttach;
1537
1538#[cfg(target_os = "illumos")]
1539impl SetSockOpt for FilterAttach {
1540 type Val = OsStr;
1541
1542 fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()> {
1543 if val.len() > libc::FILNAME_MAX as usize {
1544 return Err(Errno::EINVAL);
1545 }
1546 unsafe {
1547 let res = libc::setsockopt(
1548 fd.as_fd().as_raw_fd(),
1549 libc::SOL_FILTER,
1550 libc::FIL_ATTACH,
1551 val.as_bytes().as_ptr().cast(),
1552 val.len() as libc::socklen_t,
1553 );
1554 Errno::result(res).map(drop)
1555 }
1556 }
1557}
1558
1559#[cfg(target_os = "illumos")]
1560#[derive(Copy, Clone, Debug)]
1561pub struct FilterDetach;
1563
1564#[cfg(target_os = "illumos")]
1565impl SetSockOpt for FilterDetach {
1566 type Val = OsStr;
1567
1568 fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()> {
1569 if val.len() > libc::FILNAME_MAX as usize {
1570 return Err(Errno::EINVAL);
1571 }
1572 unsafe {
1573 let res = libc::setsockopt(
1574 fd.as_fd().as_raw_fd(),
1575 libc::SOL_FILTER,
1576 libc::FIL_DETACH,
1577 val.as_bytes().as_ptr().cast(),
1578 val.len() as libc::socklen_t,
1579 );
1580 Errno::result(res).map(drop)
1581 }
1582 }
1583}
1584#[doc(hidden)]
1593pub trait Get<T> {
1594 fn uninit() -> Self;
1596 fn ffi_ptr(&mut self) -> *mut c_void;
1599 fn ffi_len(&mut self) -> *mut socklen_t;
1602 unsafe fn assume_init(self) -> T;
1604}
1605
1606#[doc(hidden)]
1609pub trait Set<'a, T> {
1610 fn new(val: &'a T) -> Self;
1612 fn ffi_ptr(&self) -> *const c_void;
1615 fn ffi_len(&self) -> socklen_t;
1618}
1619
1620#[doc(hidden)]
1623#[derive(Debug)]
1624pub struct GetStruct<T> {
1625 len: socklen_t,
1626 val: MaybeUninit<T>,
1627}
1628
1629impl<T> Get<T> for GetStruct<T> {
1630 fn uninit() -> Self {
1631 GetStruct {
1632 len: mem::size_of::<T>() as socklen_t,
1633 val: MaybeUninit::uninit(),
1634 }
1635 }
1636
1637 fn ffi_ptr(&mut self) -> *mut c_void {
1638 self.val.as_mut_ptr().cast()
1639 }
1640
1641 fn ffi_len(&mut self) -> *mut socklen_t {
1642 &mut self.len
1643 }
1644
1645 unsafe fn assume_init(self) -> T {
1646 assert_eq!(
1647 self.len as usize,
1648 mem::size_of::<T>(),
1649 "invalid getsockopt implementation"
1650 );
1651 unsafe { self.val.assume_init() }
1652 }
1653}
1654
1655#[doc(hidden)]
1658#[derive(Debug)]
1659pub struct SetStruct<'a, T: 'static> {
1660 ptr: &'a T,
1661}
1662
1663impl<'a, T> Set<'a, T> for SetStruct<'a, T> {
1664 fn new(ptr: &'a T) -> SetStruct<'a, T> {
1665 SetStruct { ptr }
1666 }
1667
1668 fn ffi_ptr(&self) -> *const c_void {
1669 self.ptr as *const T as *const c_void
1670 }
1671
1672 fn ffi_len(&self) -> socklen_t {
1673 mem::size_of::<T>() as socklen_t
1674 }
1675}
1676
1677#[doc(hidden)]
1680#[derive(Clone, Copy, Debug)]
1681pub struct GetBool {
1682 len: socklen_t,
1683 val: MaybeUninit<c_int>,
1684}
1685
1686impl Get<bool> for GetBool {
1687 fn uninit() -> Self {
1688 GetBool {
1689 len: mem::size_of::<c_int>() as socklen_t,
1690 val: MaybeUninit::uninit(),
1691 }
1692 }
1693
1694 fn ffi_ptr(&mut self) -> *mut c_void {
1695 self.val.as_mut_ptr().cast()
1696 }
1697
1698 fn ffi_len(&mut self) -> *mut socklen_t {
1699 &mut self.len
1700 }
1701
1702 unsafe fn assume_init(self) -> bool {
1703 assert_eq!(
1704 self.len as usize,
1705 mem::size_of::<c_int>(),
1706 "invalid getsockopt implementation"
1707 );
1708 unsafe { self.val.assume_init() != 0 }
1709 }
1710}
1711
1712#[doc(hidden)]
1715#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1716pub struct SetBool {
1717 val: c_int,
1718}
1719
1720impl<'a> Set<'a, bool> for SetBool {
1721 fn new(val: &'a bool) -> SetBool {
1722 SetBool {
1723 val: i32::from(*val),
1724 }
1725 }
1726
1727 fn ffi_ptr(&self) -> *const c_void {
1728 &self.val as *const c_int as *const c_void
1729 }
1730
1731 fn ffi_len(&self) -> socklen_t {
1732 mem::size_of_val(&self.val) as socklen_t
1733 }
1734}
1735
1736#[cfg(feature = "net")]
1738#[doc(hidden)]
1740#[derive(Clone, Copy, Debug)]
1741pub struct GetU8 {
1742 len: socklen_t,
1743 val: MaybeUninit<u8>,
1744}
1745
1746#[cfg(feature = "net")]
1747impl Get<u8> for GetU8 {
1748 fn uninit() -> Self {
1749 GetU8 {
1750 len: mem::size_of::<u8>() as socklen_t,
1751 val: MaybeUninit::uninit(),
1752 }
1753 }
1754
1755 fn ffi_ptr(&mut self) -> *mut c_void {
1756 self.val.as_mut_ptr().cast()
1757 }
1758
1759 fn ffi_len(&mut self) -> *mut socklen_t {
1760 &mut self.len
1761 }
1762
1763 unsafe fn assume_init(self) -> u8 {
1764 assert_eq!(
1765 self.len as usize,
1766 mem::size_of::<u8>(),
1767 "invalid getsockopt implementation"
1768 );
1769 unsafe { self.val.assume_init() }
1770 }
1771}
1772
1773#[doc(hidden)]
1776#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1777pub struct SetU8 {
1778 val: u8,
1779}
1780
1781#[cfg(feature = "net")]
1782impl<'a> Set<'a, u8> for SetU8 {
1783 fn new(val: &'a u8) -> SetU8 {
1784 SetU8 { val: *val }
1785 }
1786
1787 fn ffi_ptr(&self) -> *const c_void {
1788 &self.val as *const u8 as *const c_void
1789 }
1790
1791 fn ffi_len(&self) -> socklen_t {
1792 mem::size_of_val(&self.val) as socklen_t
1793 }
1794}
1795
1796#[doc(hidden)]
1799#[derive(Clone, Copy, Debug)]
1800pub struct GetUsize {
1801 len: socklen_t,
1802 val: MaybeUninit<c_int>,
1803}
1804
1805impl Get<usize> for GetUsize {
1806 fn uninit() -> Self {
1807 GetUsize {
1808 len: mem::size_of::<c_int>() as socklen_t,
1809 val: MaybeUninit::uninit(),
1810 }
1811 }
1812
1813 fn ffi_ptr(&mut self) -> *mut c_void {
1814 self.val.as_mut_ptr().cast()
1815 }
1816
1817 fn ffi_len(&mut self) -> *mut socklen_t {
1818 &mut self.len
1819 }
1820
1821 unsafe fn assume_init(self) -> usize {
1822 assert_eq!(
1823 self.len as usize,
1824 mem::size_of::<c_int>(),
1825 "invalid getsockopt implementation"
1826 );
1827 unsafe { self.val.assume_init() as usize }
1828 }
1829}
1830
1831#[doc(hidden)]
1834#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1835pub struct SetUsize {
1836 val: c_int,
1837}
1838
1839impl<'a> Set<'a, usize> for SetUsize {
1840 fn new(val: &'a usize) -> SetUsize {
1841 SetUsize { val: *val as c_int }
1842 }
1843
1844 fn ffi_ptr(&self) -> *const c_void {
1845 &self.val as *const c_int as *const c_void
1846 }
1847
1848 fn ffi_len(&self) -> socklen_t {
1849 mem::size_of_val(&self.val) as socklen_t
1850 }
1851}
1852
1853
1854#[doc(hidden)]
1857#[derive(Clone, Copy, Debug)]
1858pub struct GetOwnedFd {
1859 len: socklen_t,
1860 val: MaybeUninit<c_int>,
1861}
1862
1863impl Get<OwnedFd> for GetOwnedFd {
1864 fn uninit() -> Self {
1865 GetOwnedFd {
1866 len: mem::size_of::<c_int>() as socklen_t,
1867 val: MaybeUninit::uninit(),
1868 }
1869 }
1870
1871 fn ffi_ptr(&mut self) -> *mut c_void {
1872 self.val.as_mut_ptr().cast()
1873 }
1874
1875 fn ffi_len(&mut self) -> *mut socklen_t {
1876 &mut self.len
1877 }
1878
1879 unsafe fn assume_init(self) -> OwnedFd {
1880 use std::os::fd::{FromRawFd, RawFd};
1881
1882 assert_eq!(
1883 self.len as usize,
1884 mem::size_of::<c_int>(),
1885 "invalid getsockopt implementation"
1886 );
1887 unsafe { OwnedFd::from_raw_fd(self.val.assume_init() as RawFd) }
1888 }
1889}
1890
1891#[doc(hidden)]
1894#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1895pub struct SetOwnedFd {
1896 val: c_int,
1897}
1898
1899impl<'a> Set<'a, OwnedFd> for SetOwnedFd {
1900 fn new(val: &'a OwnedFd) -> SetOwnedFd {
1901 use std::os::fd::AsRawFd;
1902
1903 SetOwnedFd { val: val.as_raw_fd() as c_int }
1904 }
1905
1906 fn ffi_ptr(&self) -> *const c_void {
1907 &self.val as *const c_int as *const c_void
1908 }
1909
1910 fn ffi_len(&self) -> socklen_t {
1911 mem::size_of_val(&self.val) as socklen_t
1912 }
1913}
1914
1915#[doc(hidden)]
1918#[derive(Debug)]
1919pub struct GetOsString<T: AsMut<[u8]>> {
1920 len: socklen_t,
1921 val: MaybeUninit<T>,
1922}
1923
1924impl<T: AsMut<[u8]>> Get<OsString> for GetOsString<T> {
1925 fn uninit() -> Self {
1926 GetOsString {
1927 len: mem::size_of::<T>() as socklen_t,
1928 val: MaybeUninit::uninit(),
1929 }
1930 }
1931
1932 fn ffi_ptr(&mut self) -> *mut c_void {
1933 self.val.as_mut_ptr().cast()
1934 }
1935
1936 fn ffi_len(&mut self) -> *mut socklen_t {
1937 &mut self.len
1938 }
1939
1940 unsafe fn assume_init(self) -> OsString {
1941 let len = self.len as usize;
1942 let mut v = unsafe { self.val.assume_init() };
1943 if let Ok(cs) = CStr::from_bytes_until_nul(&v.as_mut()[0..len]) {
1944 OsStr::from_bytes(cs.to_bytes())
1947 } else {
1948 OsStr::from_bytes(&v.as_mut()[0..len])
1950 }
1951 .to_owned()
1952 }
1953}
1954
1955#[doc(hidden)]
1958#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1959pub struct SetOsString<'a> {
1960 val: &'a OsStr,
1961}
1962
1963#[cfg(any(target_os = "freebsd", linux_android, target_os = "illumos"))]
1964impl<'a> Set<'a, OsString> for SetOsString<'a> {
1965 fn new(val: &OsString) -> SetOsString<'_> {
1966 SetOsString {
1967 val: val.as_os_str(),
1968 }
1969 }
1970
1971 fn ffi_ptr(&self) -> *const c_void {
1972 self.val.as_bytes().as_ptr().cast()
1973 }
1974
1975 fn ffi_len(&self) -> socklen_t {
1976 self.val.len() as socklen_t
1977 }
1978}
1979
1980#[cfg(apple_targets)]
1982#[cfg(feature = "net")]
1983struct GetCString<T: AsMut<[u8]>> {
1984 len: socklen_t,
1985 val: MaybeUninit<T>,
1986}
1987
1988#[cfg(apple_targets)]
1989#[cfg(feature = "net")]
1990impl<T: AsMut<[u8]>> Get<CString> for GetCString<T> {
1991 fn uninit() -> Self {
1992 GetCString {
1993 len: mem::size_of::<T>() as socklen_t,
1994 val: MaybeUninit::uninit(),
1995 }
1996 }
1997
1998 fn ffi_ptr(&mut self) -> *mut c_void {
1999 self.val.as_mut_ptr().cast()
2000 }
2001
2002 fn ffi_len(&mut self) -> *mut socklen_t {
2003 &mut self.len
2004 }
2005
2006 unsafe fn assume_init(self) -> CString {
2007 let mut v = unsafe { self.val.assume_init() };
2008 CStr::from_bytes_until_nul(v.as_mut())
2009 .expect("string should be null-terminated")
2010 .to_owned()
2011 }
2012}