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")]
566sockopt_impl!(
567 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
568 IpBindAddressNoPort,
573 Both,
574 libc::IPPROTO_IP,
575 libc::IP_BIND_ADDRESS_NO_PORT,
576 bool
577);
578sockopt_impl!(
579 ReceiveTimeout,
581 Both,
582 libc::SOL_SOCKET,
583 libc::SO_RCVTIMEO,
584 TimeVal
585);
586sockopt_impl!(
587 SendTimeout,
589 Both,
590 libc::SOL_SOCKET,
591 libc::SO_SNDTIMEO,
592 TimeVal
593);
594sockopt_impl!(
595 Broadcast,
597 Both,
598 libc::SOL_SOCKET,
599 libc::SO_BROADCAST,
600 bool
601);
602sockopt_impl!(
603 OobInline,
606 Both,
607 libc::SOL_SOCKET,
608 libc::SO_OOBINLINE,
609 bool
610);
611sockopt_impl!(
612 SocketError,
614 GetOnly,
615 libc::SOL_SOCKET,
616 libc::SO_ERROR,
617 i32
618);
619sockopt_impl!(
620 DontRoute,
622 Both,
623 libc::SOL_SOCKET,
624 libc::SO_DONTROUTE,
625 bool
626);
627sockopt_impl!(
628 KeepAlive,
630 Both,
631 libc::SOL_SOCKET,
632 libc::SO_KEEPALIVE,
633 bool
634);
635#[cfg(freebsdlike)]
636sockopt_impl!(
637 LocalPeerCred,
640 GetOnly,
641 0,
642 libc::LOCAL_PEERCRED,
643 super::XuCred
644);
645#[cfg(apple_targets)]
646sockopt_impl!(
647 LocalPeerCred,
650 GetOnly,
651 libc::SOL_LOCAL,
652 libc::LOCAL_PEERCRED,
653 super::XuCred
654);
655#[cfg(apple_targets)]
656sockopt_impl!(
657 LocalPeerPid,
659 GetOnly,
660 libc::SOL_LOCAL,
661 libc::LOCAL_PEERPID,
662 libc::c_int
663);
664#[cfg(apple_targets)]
665sockopt_impl!(
666 LocalPeerToken,
669 GetOnly,
670 libc::SOL_LOCAL,
671 libc::LOCAL_PEERTOKEN,
672 super::audit_token_t
673);
674#[cfg(linux_android)]
675sockopt_impl!(
676 PeerCredentials,
678 GetOnly,
679 libc::SOL_SOCKET,
680 libc::SO_PEERCRED,
681 super::UnixCredentials
682);
683#[cfg(target_os = "linux")]
684sockopt_impl!(
685 PeerPidfd,
687 GetOnly,
688 libc::SOL_SOCKET,
689 libc::SO_PEERPIDFD,
690 OwnedFd
691);
692#[cfg(target_os = "freebsd")]
693#[cfg(feature = "net")]
694sockopt_impl!(
695 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
696 ListenQLimit,
698 GetOnly,
699 libc::SOL_SOCKET,
700 libc::SO_LISTENQLIMIT,
701 u32
702);
703#[cfg(apple_targets)]
704#[cfg(feature = "net")]
705sockopt_impl!(
706 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
707 TcpKeepAlive,
710 Both,
711 libc::IPPROTO_TCP,
712 libc::TCP_KEEPALIVE,
713 u32
714);
715#[cfg(any(freebsdlike, linux_android))]
716#[cfg(feature = "net")]
717sockopt_impl!(
718 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
719 TcpKeepIdle,
722 Both,
723 libc::IPPROTO_TCP,
724 libc::TCP_KEEPIDLE,
725 u32
726);
727cfg_if! {
728 if #[cfg(any(linux_android, apple_targets))] {
729 sockopt_impl!(
730 TcpMaxSeg, Both, libc::IPPROTO_TCP, libc::TCP_MAXSEG, u32);
732 } else if #[cfg(not(target_os = "redox"))] {
733 sockopt_impl!(
734 TcpMaxSeg, GetOnly, libc::IPPROTO_TCP, libc::TCP_MAXSEG, u32);
736 }
737}
738#[cfg(not(any(
739 target_os = "openbsd",
740 target_os = "haiku",
741 target_os = "redox"
742)))]
743#[cfg(feature = "net")]
744sockopt_impl!(
745 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
746 TcpKeepCount,
749 Both,
750 libc::IPPROTO_TCP,
751 libc::TCP_KEEPCNT,
752 u32
753);
754#[cfg(any(linux_android, target_os = "fuchsia"))]
755sockopt_impl!(
756 #[allow(missing_docs)]
757 TcpRepair,
759 Both,
760 libc::IPPROTO_TCP,
761 libc::TCP_REPAIR,
762 u32
763);
764#[cfg(not(any(
765 target_os = "openbsd",
766 target_os = "haiku",
767 target_os = "redox"
768)))]
769#[cfg(feature = "net")]
770sockopt_impl!(
771 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
772 TcpKeepInterval,
774 Both,
775 libc::IPPROTO_TCP,
776 libc::TCP_KEEPINTVL,
777 u32
778);
779#[cfg(any(target_os = "fuchsia", target_os = "linux"))]
780#[cfg(feature = "net")]
781sockopt_impl!(
782 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
783 TcpUserTimeout,
787 Both,
788 libc::IPPROTO_TCP,
789 libc::TCP_USER_TIMEOUT,
790 u32
791);
792#[cfg(linux_android)]
793#[cfg(feature = "net")]
794sockopt_impl!(
795 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
796 TcpFastOpenConnect,
807 Both,
808 libc::IPPROTO_TCP,
809 libc::TCP_FASTOPEN_CONNECT,
810 bool
811);
812sockopt_impl!(
813 RcvBuf,
815 Both,
816 libc::SOL_SOCKET,
817 libc::SO_RCVBUF,
818 usize
819);
820sockopt_impl!(
821 SndBuf,
823 Both,
824 libc::SOL_SOCKET,
825 libc::SO_SNDBUF,
826 usize
827);
828#[cfg(linux_android)]
829sockopt_impl!(
830 RcvBufForce,
834 SetOnly,
835 libc::SOL_SOCKET,
836 libc::SO_RCVBUFFORCE,
837 usize
838);
839#[cfg(linux_android)]
840sockopt_impl!(
841 SndBufForce,
845 SetOnly,
846 libc::SOL_SOCKET,
847 libc::SO_SNDBUFFORCE,
848 usize
849);
850sockopt_impl!(
851 SockType,
853 GetOnly,
854 libc::SOL_SOCKET,
855 libc::SO_TYPE,
856 super::SockType,
857 GetStruct<i32>
858);
859sockopt_impl!(
860 AcceptConn,
863 GetOnly,
864 libc::SOL_SOCKET,
865 libc::SO_ACCEPTCONN,
866 bool
867);
868#[cfg(linux_android)]
869sockopt_impl!(
870 BindToDevice,
872 Both,
873 libc::SOL_SOCKET,
874 libc::SO_BINDTODEVICE,
875 OsString<[u8; libc::IFNAMSIZ]>
876);
877#[cfg(linux_android)]
878#[cfg(feature = "net")]
879sockopt_impl!(
880 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
881 #[allow(missing_docs)]
882 OriginalDst,
884 GetOnly,
885 libc::SOL_IP,
886 libc::SO_ORIGINAL_DST,
887 libc::sockaddr_in
888);
889#[cfg(linux_android)]
890sockopt_impl!(
891 #[allow(missing_docs)]
892 Ip6tOriginalDst,
894 GetOnly,
895 libc::SOL_IPV6,
896 libc::IP6T_SO_ORIGINAL_DST,
897 libc::sockaddr_in6
898);
899#[cfg(linux_android)]
900sockopt_impl!(
901 Timestamping,
904 Both,
905 libc::SOL_SOCKET,
906 libc::SO_TIMESTAMPING,
907 super::TimestampingFlag
908);
909#[cfg(not(any(
910 target_os = "aix",
911 target_os = "haiku",
912 target_os = "hurd",
913 target_os = "redox",
914 target_os = "cygwin"
915)))]
916sockopt_impl!(
917 ReceiveTimestamp,
919 Both,
920 libc::SOL_SOCKET,
921 libc::SO_TIMESTAMP,
922 bool
923);
924#[cfg(linux_android)]
925sockopt_impl!(
926 ReceiveTimestampns,
928 Both,
929 libc::SOL_SOCKET,
930 libc::SO_TIMESTAMPNS,
931 bool
932);
933#[cfg(target_os = "freebsd")]
934sockopt_impl!(
935 TsClock,
938 Both,
939 libc::SOL_SOCKET,
940 libc::SO_TS_CLOCK,
941 super::SocketTimestamp
942);
943#[cfg(linux_android)]
944#[cfg(feature = "net")]
945sockopt_impl!(
946 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
947 IpTransparent,
949 Both,
950 libc::SOL_IP,
951 libc::IP_TRANSPARENT,
952 bool
953);
954#[cfg(target_os = "openbsd")]
955#[cfg(feature = "net")]
956sockopt_impl!(
957 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
958 BindAny,
961 Both,
962 libc::SOL_SOCKET,
963 libc::SO_BINDANY,
964 bool
965);
966#[cfg(target_os = "freebsd")]
967#[cfg(feature = "net")]
968sockopt_impl!(
969 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
970 BindAny,
973 Both,
974 libc::IPPROTO_IP,
975 libc::IP_BINDANY,
976 bool
977);
978#[cfg(target_os = "freebsd")]
979sockopt_impl!(
980 Fib,
983 SetOnly,
984 libc::SOL_SOCKET,
985 libc::SO_SETFIB,
986 i32
987);
988#[cfg(target_os = "freebsd")]
989sockopt_impl!(
990 UserCookie,
993 SetOnly,
994 libc::SOL_SOCKET,
995 libc::SO_USER_COOKIE,
996 u32
997);
998#[cfg(target_os = "openbsd")]
999sockopt_impl!(
1000 Rtable,
1003 SetOnly,
1004 libc::SOL_SOCKET,
1005 libc::SO_RTABLE,
1006 i32
1007);
1008#[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
1009sockopt_impl!(
1010 AcceptFilter,
1013 Both,
1014 libc::SOL_SOCKET,
1015 libc::SO_ACCEPTFILTER,
1016 libc::accept_filter_arg
1017);
1018#[cfg(target_os = "linux")]
1019sockopt_impl!(
1020 Mark,
1023 Both,
1024 libc::SOL_SOCKET,
1025 libc::SO_MARK,
1026 u32
1027);
1028#[cfg(linux_android)]
1029sockopt_impl!(
1030 PassCred,
1033 Both,
1034 libc::SOL_SOCKET,
1035 libc::SO_PASSCRED,
1036 bool
1037);
1038#[cfg(any(target_os = "freebsd", target_os = "linux"))]
1039#[cfg(feature = "net")]
1040sockopt_impl!(
1041 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1042 TcpCongestion,
1045 Both,
1046 libc::IPPROTO_TCP,
1047 libc::TCP_CONGESTION,
1048 OsString<[u8; TCP_CA_NAME_MAX]>
1049);
1050#[cfg(any(linux_android, apple_targets, target_os = "netbsd"))]
1051#[cfg(feature = "net")]
1052sockopt_impl!(
1053 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1054 Ipv4PacketInfo,
1057 Both,
1058 libc::IPPROTO_IP,
1059 libc::IP_PKTINFO,
1060 bool
1061);
1062#[cfg(any(linux_android, bsd))]
1063#[cfg(feature = "net")]
1064sockopt_impl!(
1065 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1066 Ipv6RecvPacketInfo,
1069 Both,
1070 libc::IPPROTO_IPV6,
1071 libc::IPV6_RECVPKTINFO,
1072 bool
1073);
1074
1075#[cfg(any(linux_android, bsd))]
1076#[cfg(feature = "net")]
1077sockopt_impl!(
1078 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1079 Ipv6PacketInfo,
1082 Both,
1083 libc::IPPROTO_IPV6,
1084 libc::IPV6_PKTINFO,
1085 bool
1086);
1087#[cfg(bsd)]
1088#[cfg(feature = "net")]
1089sockopt_impl!(
1090 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1091 Ipv4RecvIf,
1094 Both,
1095 libc::IPPROTO_IP,
1096 libc::IP_RECVIF,
1097 bool
1098);
1099#[cfg(bsd)]
1100#[cfg(feature = "net")]
1101sockopt_impl!(
1102 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1103 Ipv4RecvDstAddr,
1106 Both,
1107 libc::IPPROTO_IP,
1108 libc::IP_RECVDSTADDR,
1109 bool
1110);
1111#[cfg(any(linux_android, target_os = "freebsd"))]
1112#[cfg(feature = "net")]
1113sockopt_impl!(
1114 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1115 Ipv4OrigDstAddr,
1118 Both,
1119 libc::IPPROTO_IP,
1120 libc::IP_ORIGDSTADDR,
1121 bool
1122);
1123#[cfg(target_os = "linux")]
1124#[cfg(feature = "net")]
1125sockopt_impl!(
1126 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1127 #[allow(missing_docs)]
1128 UdpGsoSegment,
1130 Both,
1131 libc::SOL_UDP,
1132 libc::UDP_SEGMENT,
1133 libc::c_int
1134);
1135#[cfg(target_os = "linux")]
1136#[cfg(feature = "net")]
1137sockopt_impl!(
1138 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1139 #[allow(missing_docs)]
1140 UdpGroSegment,
1142 Both,
1143 libc::IPPROTO_UDP,
1144 libc::UDP_GRO,
1145 bool
1146);
1147#[cfg(target_os = "linux")]
1148sockopt_impl!(
1149 TxTime,
1152 Both,
1153 libc::SOL_SOCKET,
1154 libc::SO_TXTIME,
1155 libc::sock_txtime
1156);
1157#[cfg(any(linux_android, target_os = "fuchsia"))]
1158sockopt_impl!(
1159 RxqOvfl,
1163 Both,
1164 libc::SOL_SOCKET,
1165 libc::SO_RXQ_OVFL,
1166 libc::c_int
1167);
1168#[cfg(feature = "net")]
1169sockopt_impl!(
1170 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1171 Ipv6V6Only,
1173 Both,
1174 libc::IPPROTO_IPV6,
1175 libc::IPV6_V6ONLY,
1176 bool
1177);
1178#[cfg(linux_android)]
1179sockopt_impl!(
1180 Ipv4RecvErr,
1182 Both,
1183 libc::IPPROTO_IP,
1184 libc::IP_RECVERR,
1185 bool
1186);
1187#[cfg(linux_android)]
1188sockopt_impl!(
1189 Ipv6RecvErr,
1191 Both,
1192 libc::IPPROTO_IPV6,
1193 libc::IPV6_RECVERR,
1194 bool
1195);
1196#[cfg(linux_android)]
1197sockopt_impl!(
1198 IpMtu,
1200 GetOnly,
1201 libc::IPPROTO_IP,
1202 libc::IP_MTU,
1203 libc::c_int
1204);
1205#[cfg(any(linux_android, target_os = "freebsd"))]
1206sockopt_impl!(
1207 Ipv4Ttl,
1210 Both,
1211 libc::IPPROTO_IP,
1212 libc::IP_TTL,
1213 libc::c_int
1214);
1215#[cfg(any(linux_android, target_os = "freebsd"))]
1216#[cfg(feature = "net")]
1217sockopt_impl!(
1218 Ipv4RecvTtl,
1221 Both,
1222 libc::IPPROTO_IP,
1223 libc::IP_RECVTTL,
1224 bool
1225);
1226#[cfg(any(apple_targets, linux_android, target_os = "freebsd"))]
1227sockopt_impl!(
1228 Ipv6Ttl,
1230 Both,
1231 libc::IPPROTO_IPV6,
1232 libc::IPV6_UNICAST_HOPS,
1233 libc::c_int
1234);
1235#[cfg(any(linux_android, target_os = "freebsd"))]
1236#[cfg(feature = "net")]
1237sockopt_impl!(
1238 Ipv6RecvHopLimit,
1241 Both,
1242 libc::IPPROTO_IPV6,
1243 libc::IPV6_RECVHOPLIMIT,
1244 bool
1245);
1246#[cfg(any(linux_android, target_os = "freebsd"))]
1247#[cfg(feature = "net")]
1248sockopt_impl!(
1249 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1250 Ipv6OrigDstAddr,
1253 Both,
1254 libc::IPPROTO_IPV6,
1255 libc::IPV6_ORIGDSTADDR,
1256 bool
1257);
1258#[cfg(apple_targets)]
1259sockopt_impl!(
1260 IpDontFrag,
1262 Both,
1263 libc::IPPROTO_IP,
1264 libc::IP_DONTFRAG,
1265 bool
1266);
1267#[cfg(any(linux_android, apple_targets))]
1268sockopt_impl!(
1269 Ipv6DontFrag,
1271 Both,
1272 libc::IPPROTO_IPV6,
1273 libc::IPV6_DONTFRAG,
1274 bool
1275);
1276#[cfg(apple_targets)]
1277#[cfg(feature = "net")]
1278sockopt_impl!(
1279 UtunIfname,
1281 GetOnly,
1282 libc::SYSPROTO_CONTROL,
1283 libc::UTUN_OPT_IFNAME,
1284 CString,
1285 GetCString<[u8; libc::IFNAMSIZ]>
1286);
1287
1288#[cfg(solarish)]
1289sockopt_impl!(
1290 ExclBind,
1294 Both,
1295 libc::SOL_SOCKET,
1296 libc::SO_EXCLBIND,
1297 bool
1298);
1299#[cfg(target_os = "linux")]
1300sockopt_impl!(
1301 AttachReusePortCbpf,
1306 SetOnly,
1307 libc::SOL_SOCKET,
1308 libc::SO_ATTACH_REUSEPORT_CBPF,
1309 libc::sock_fprog
1310);
1311
1312#[allow(missing_docs)]
1313#[cfg(linux_android)]
1315#[derive(Copy, Clone, Debug)]
1316pub struct AlgSetAeadAuthSize;
1317
1318#[cfg(linux_android)]
1321impl SetSockOpt for AlgSetAeadAuthSize {
1322 type Val = usize;
1323
1324 fn set<F: AsFd>(&self, fd: &F, val: &usize) -> Result<()> {
1325 unsafe {
1326 let res = libc::setsockopt(
1327 fd.as_fd().as_raw_fd(),
1328 libc::SOL_ALG,
1329 libc::ALG_SET_AEAD_AUTHSIZE,
1330 ::std::ptr::null(),
1331 *val as libc::socklen_t,
1332 );
1333 Errno::result(res).map(drop)
1334 }
1335 }
1336}
1337
1338#[allow(missing_docs)]
1339#[cfg(linux_android)]
1341#[derive(Clone, Debug)]
1342pub struct AlgSetKey<T>(::std::marker::PhantomData<T>);
1343
1344#[cfg(linux_android)]
1345impl<T> Default for AlgSetKey<T> {
1346 fn default() -> Self {
1347 AlgSetKey(Default::default())
1348 }
1349}
1350
1351#[cfg(linux_android)]
1352impl<T> SetSockOpt for AlgSetKey<T>
1353where
1354 T: AsRef<[u8]> + Clone,
1355{
1356 type Val = T;
1357
1358 fn set<F: AsFd>(&self, fd: &F, val: &T) -> Result<()> {
1359 unsafe {
1360 let res = libc::setsockopt(
1361 fd.as_fd().as_raw_fd(),
1362 libc::SOL_ALG,
1363 libc::ALG_SET_KEY,
1364 val.as_ref().as_ptr().cast(),
1365 val.as_ref().len() as libc::socklen_t,
1366 );
1367 Errno::result(res).map(drop)
1368 }
1369 }
1370}
1371
1372#[cfg(linux_android)]
1388#[derive(Clone, Debug)]
1389pub struct TcpUlp<T>(::std::marker::PhantomData<T>);
1390
1391#[cfg(linux_android)]
1392impl<T> Default for TcpUlp<T> {
1393 fn default() -> Self {
1394 TcpUlp(Default::default())
1395 }
1396}
1397
1398#[cfg(linux_android)]
1399impl<T> SetSockOpt for TcpUlp<T>
1400where
1401 T: AsRef<[u8]> + Clone,
1402{
1403 type Val = T;
1404
1405 fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()> {
1406 unsafe {
1407 let res = libc::setsockopt(
1408 fd.as_fd().as_raw_fd(),
1409 libc::SOL_TCP,
1410 libc::TCP_ULP,
1411 val.as_ref().as_ptr().cast(),
1412 val.as_ref().len() as libc::socklen_t,
1413 );
1414 Errno::result(res).map(drop)
1415 }
1416 }
1417}
1418
1419#[cfg(target_os = "linux")]
1421#[derive(Copy, Clone, Debug)]
1422pub enum TlsCryptoInfo {
1423 Aes128Gcm(libc::tls12_crypto_info_aes_gcm_128),
1425
1426 Aes256Gcm(libc::tls12_crypto_info_aes_gcm_256),
1428
1429 Chacha20Poly1305(libc::tls12_crypto_info_chacha20_poly1305),
1431}
1432
1433#[cfg(target_os = "linux")]
1447#[derive(Copy, Clone, Debug)]
1448pub struct TcpTlsTx;
1449
1450#[cfg(target_os = "linux")]
1451impl SetSockOpt for TcpTlsTx {
1452 type Val = TlsCryptoInfo;
1453
1454 fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()> {
1455 let (ffi_ptr, ffi_len) = match val {
1456 TlsCryptoInfo::Aes128Gcm(crypto_info) => {
1457 (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info))
1458 }
1459 TlsCryptoInfo::Aes256Gcm(crypto_info) => {
1460 (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info))
1461 }
1462 TlsCryptoInfo::Chacha20Poly1305(crypto_info) => {
1463 (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info))
1464 }
1465 };
1466 unsafe {
1467 let res = libc::setsockopt(
1468 fd.as_fd().as_raw_fd(),
1469 libc::SOL_TLS,
1470 libc::TLS_TX,
1471 ffi_ptr,
1472 ffi_len as libc::socklen_t,
1473 );
1474 Errno::result(res).map(drop)
1475 }
1476 }
1477}
1478
1479#[cfg(target_os = "linux")]
1493#[derive(Copy, Clone, Debug)]
1494pub struct TcpTlsRx;
1495
1496#[cfg(target_os = "linux")]
1497impl SetSockOpt for TcpTlsRx {
1498 type Val = TlsCryptoInfo;
1499
1500 fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()> {
1501 let (ffi_ptr, ffi_len) = match val {
1502 TlsCryptoInfo::Aes128Gcm(crypto_info) => {
1503 (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info))
1504 }
1505 TlsCryptoInfo::Aes256Gcm(crypto_info) => {
1506 (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info))
1507 }
1508 TlsCryptoInfo::Chacha20Poly1305(crypto_info) => {
1509 (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info))
1510 }
1511 };
1512 unsafe {
1513 let res = libc::setsockopt(
1514 fd.as_fd().as_raw_fd(),
1515 libc::SOL_TLS,
1516 libc::TLS_RX,
1517 ffi_ptr,
1518 ffi_len as libc::socklen_t,
1519 );
1520 Errno::result(res).map(drop)
1521 }
1522 }
1523}
1524
1525#[cfg(target_os = "illumos")]
1526#[derive(Copy, Clone, Debug)]
1527pub struct FilterAttach;
1530
1531#[cfg(target_os = "illumos")]
1532impl SetSockOpt for FilterAttach {
1533 type Val = OsStr;
1534
1535 fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()> {
1536 if val.len() > libc::FILNAME_MAX as usize {
1537 return Err(Errno::EINVAL);
1538 }
1539 unsafe {
1540 let res = libc::setsockopt(
1541 fd.as_fd().as_raw_fd(),
1542 libc::SOL_FILTER,
1543 libc::FIL_ATTACH,
1544 val.as_bytes().as_ptr().cast(),
1545 val.len() as libc::socklen_t,
1546 );
1547 Errno::result(res).map(drop)
1548 }
1549 }
1550}
1551
1552#[cfg(target_os = "illumos")]
1553#[derive(Copy, Clone, Debug)]
1554pub struct FilterDetach;
1556
1557#[cfg(target_os = "illumos")]
1558impl SetSockOpt for FilterDetach {
1559 type Val = OsStr;
1560
1561 fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()> {
1562 if val.len() > libc::FILNAME_MAX as usize {
1563 return Err(Errno::EINVAL);
1564 }
1565 unsafe {
1566 let res = libc::setsockopt(
1567 fd.as_fd().as_raw_fd(),
1568 libc::SOL_FILTER,
1569 libc::FIL_DETACH,
1570 val.as_bytes().as_ptr().cast(),
1571 val.len() as libc::socklen_t,
1572 );
1573 Errno::result(res).map(drop)
1574 }
1575 }
1576}
1577#[doc(hidden)]
1586pub trait Get<T> {
1587 fn uninit() -> Self;
1589 fn ffi_ptr(&mut self) -> *mut c_void;
1592 fn ffi_len(&mut self) -> *mut socklen_t;
1595 unsafe fn assume_init(self) -> T;
1597}
1598
1599#[doc(hidden)]
1602pub trait Set<'a, T> {
1603 fn new(val: &'a T) -> Self;
1605 fn ffi_ptr(&self) -> *const c_void;
1608 fn ffi_len(&self) -> socklen_t;
1611}
1612
1613#[doc(hidden)]
1616#[derive(Debug)]
1617pub struct GetStruct<T> {
1618 len: socklen_t,
1619 val: MaybeUninit<T>,
1620}
1621
1622impl<T> Get<T> for GetStruct<T> {
1623 fn uninit() -> Self {
1624 GetStruct {
1625 len: mem::size_of::<T>() as socklen_t,
1626 val: MaybeUninit::uninit(),
1627 }
1628 }
1629
1630 fn ffi_ptr(&mut self) -> *mut c_void {
1631 self.val.as_mut_ptr().cast()
1632 }
1633
1634 fn ffi_len(&mut self) -> *mut socklen_t {
1635 &mut self.len
1636 }
1637
1638 unsafe fn assume_init(self) -> T {
1639 assert_eq!(
1640 self.len as usize,
1641 mem::size_of::<T>(),
1642 "invalid getsockopt implementation"
1643 );
1644 unsafe { self.val.assume_init() }
1645 }
1646}
1647
1648#[doc(hidden)]
1651#[derive(Debug)]
1652pub struct SetStruct<'a, T: 'static> {
1653 ptr: &'a T,
1654}
1655
1656impl<'a, T> Set<'a, T> for SetStruct<'a, T> {
1657 fn new(ptr: &'a T) -> SetStruct<'a, T> {
1658 SetStruct { ptr }
1659 }
1660
1661 fn ffi_ptr(&self) -> *const c_void {
1662 self.ptr as *const T as *const c_void
1663 }
1664
1665 fn ffi_len(&self) -> socklen_t {
1666 mem::size_of::<T>() as socklen_t
1667 }
1668}
1669
1670#[doc(hidden)]
1673#[derive(Clone, Copy, Debug)]
1674pub struct GetBool {
1675 len: socklen_t,
1676 val: MaybeUninit<c_int>,
1677}
1678
1679impl Get<bool> for GetBool {
1680 fn uninit() -> Self {
1681 GetBool {
1682 len: mem::size_of::<c_int>() as socklen_t,
1683 val: MaybeUninit::uninit(),
1684 }
1685 }
1686
1687 fn ffi_ptr(&mut self) -> *mut c_void {
1688 self.val.as_mut_ptr().cast()
1689 }
1690
1691 fn ffi_len(&mut self) -> *mut socklen_t {
1692 &mut self.len
1693 }
1694
1695 unsafe fn assume_init(self) -> bool {
1696 assert_eq!(
1697 self.len as usize,
1698 mem::size_of::<c_int>(),
1699 "invalid getsockopt implementation"
1700 );
1701 unsafe { self.val.assume_init() != 0 }
1702 }
1703}
1704
1705#[doc(hidden)]
1708#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1709pub struct SetBool {
1710 val: c_int,
1711}
1712
1713impl<'a> Set<'a, bool> for SetBool {
1714 fn new(val: &'a bool) -> SetBool {
1715 SetBool {
1716 val: i32::from(*val),
1717 }
1718 }
1719
1720 fn ffi_ptr(&self) -> *const c_void {
1721 &self.val as *const c_int as *const c_void
1722 }
1723
1724 fn ffi_len(&self) -> socklen_t {
1725 mem::size_of_val(&self.val) as socklen_t
1726 }
1727}
1728
1729#[cfg(feature = "net")]
1731#[doc(hidden)]
1733#[derive(Clone, Copy, Debug)]
1734pub struct GetU8 {
1735 len: socklen_t,
1736 val: MaybeUninit<u8>,
1737}
1738
1739#[cfg(feature = "net")]
1740impl Get<u8> for GetU8 {
1741 fn uninit() -> Self {
1742 GetU8 {
1743 len: mem::size_of::<u8>() as socklen_t,
1744 val: MaybeUninit::uninit(),
1745 }
1746 }
1747
1748 fn ffi_ptr(&mut self) -> *mut c_void {
1749 self.val.as_mut_ptr().cast()
1750 }
1751
1752 fn ffi_len(&mut self) -> *mut socklen_t {
1753 &mut self.len
1754 }
1755
1756 unsafe fn assume_init(self) -> u8 {
1757 assert_eq!(
1758 self.len as usize,
1759 mem::size_of::<u8>(),
1760 "invalid getsockopt implementation"
1761 );
1762 unsafe { self.val.assume_init() }
1763 }
1764}
1765
1766#[doc(hidden)]
1769#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1770pub struct SetU8 {
1771 val: u8,
1772}
1773
1774#[cfg(feature = "net")]
1775impl<'a> Set<'a, u8> for SetU8 {
1776 fn new(val: &'a u8) -> SetU8 {
1777 SetU8 { val: *val }
1778 }
1779
1780 fn ffi_ptr(&self) -> *const c_void {
1781 &self.val as *const u8 as *const c_void
1782 }
1783
1784 fn ffi_len(&self) -> socklen_t {
1785 mem::size_of_val(&self.val) as socklen_t
1786 }
1787}
1788
1789#[doc(hidden)]
1792#[derive(Clone, Copy, Debug)]
1793pub struct GetUsize {
1794 len: socklen_t,
1795 val: MaybeUninit<c_int>,
1796}
1797
1798impl Get<usize> for GetUsize {
1799 fn uninit() -> Self {
1800 GetUsize {
1801 len: mem::size_of::<c_int>() as socklen_t,
1802 val: MaybeUninit::uninit(),
1803 }
1804 }
1805
1806 fn ffi_ptr(&mut self) -> *mut c_void {
1807 self.val.as_mut_ptr().cast()
1808 }
1809
1810 fn ffi_len(&mut self) -> *mut socklen_t {
1811 &mut self.len
1812 }
1813
1814 unsafe fn assume_init(self) -> usize {
1815 assert_eq!(
1816 self.len as usize,
1817 mem::size_of::<c_int>(),
1818 "invalid getsockopt implementation"
1819 );
1820 unsafe { self.val.assume_init() as usize }
1821 }
1822}
1823
1824#[doc(hidden)]
1827#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1828pub struct SetUsize {
1829 val: c_int,
1830}
1831
1832impl<'a> Set<'a, usize> for SetUsize {
1833 fn new(val: &'a usize) -> SetUsize {
1834 SetUsize { val: *val as c_int }
1835 }
1836
1837 fn ffi_ptr(&self) -> *const c_void {
1838 &self.val as *const c_int as *const c_void
1839 }
1840
1841 fn ffi_len(&self) -> socklen_t {
1842 mem::size_of_val(&self.val) as socklen_t
1843 }
1844}
1845
1846
1847#[doc(hidden)]
1850#[derive(Clone, Copy, Debug)]
1851pub struct GetOwnedFd {
1852 len: socklen_t,
1853 val: MaybeUninit<c_int>,
1854}
1855
1856impl Get<OwnedFd> for GetOwnedFd {
1857 fn uninit() -> Self {
1858 GetOwnedFd {
1859 len: mem::size_of::<c_int>() as socklen_t,
1860 val: MaybeUninit::uninit(),
1861 }
1862 }
1863
1864 fn ffi_ptr(&mut self) -> *mut c_void {
1865 self.val.as_mut_ptr().cast()
1866 }
1867
1868 fn ffi_len(&mut self) -> *mut socklen_t {
1869 &mut self.len
1870 }
1871
1872 unsafe fn assume_init(self) -> OwnedFd {
1873 use std::os::fd::{FromRawFd, RawFd};
1874
1875 assert_eq!(
1876 self.len as usize,
1877 mem::size_of::<c_int>(),
1878 "invalid getsockopt implementation"
1879 );
1880 unsafe { OwnedFd::from_raw_fd(self.val.assume_init() as RawFd) }
1881 }
1882}
1883
1884#[doc(hidden)]
1887#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1888pub struct SetOwnedFd {
1889 val: c_int,
1890}
1891
1892impl<'a> Set<'a, OwnedFd> for SetOwnedFd {
1893 fn new(val: &'a OwnedFd) -> SetOwnedFd {
1894 use std::os::fd::AsRawFd;
1895
1896 SetOwnedFd { val: val.as_raw_fd() as c_int }
1897 }
1898
1899 fn ffi_ptr(&self) -> *const c_void {
1900 &self.val as *const c_int as *const c_void
1901 }
1902
1903 fn ffi_len(&self) -> socklen_t {
1904 mem::size_of_val(&self.val) as socklen_t
1905 }
1906}
1907
1908#[doc(hidden)]
1911#[derive(Debug)]
1912pub struct GetOsString<T: AsMut<[u8]>> {
1913 len: socklen_t,
1914 val: MaybeUninit<T>,
1915}
1916
1917impl<T: AsMut<[u8]>> Get<OsString> for GetOsString<T> {
1918 fn uninit() -> Self {
1919 GetOsString {
1920 len: mem::size_of::<T>() as socklen_t,
1921 val: MaybeUninit::uninit(),
1922 }
1923 }
1924
1925 fn ffi_ptr(&mut self) -> *mut c_void {
1926 self.val.as_mut_ptr().cast()
1927 }
1928
1929 fn ffi_len(&mut self) -> *mut socklen_t {
1930 &mut self.len
1931 }
1932
1933 unsafe fn assume_init(self) -> OsString {
1934 let len = self.len as usize;
1935 let mut v = unsafe { self.val.assume_init() };
1936 if let Ok(cs) = CStr::from_bytes_until_nul(&v.as_mut()[0..len]) {
1937 OsStr::from_bytes(cs.to_bytes())
1940 } else {
1941 OsStr::from_bytes(&v.as_mut()[0..len])
1943 }
1944 .to_owned()
1945 }
1946}
1947
1948#[doc(hidden)]
1951#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1952pub struct SetOsString<'a> {
1953 val: &'a OsStr,
1954}
1955
1956#[cfg(any(target_os = "freebsd", linux_android, target_os = "illumos"))]
1957impl<'a> Set<'a, OsString> for SetOsString<'a> {
1958 fn new(val: &OsString) -> SetOsString {
1959 SetOsString {
1960 val: val.as_os_str(),
1961 }
1962 }
1963
1964 fn ffi_ptr(&self) -> *const c_void {
1965 self.val.as_bytes().as_ptr().cast()
1966 }
1967
1968 fn ffi_len(&self) -> socklen_t {
1969 self.val.len() as socklen_t
1970 }
1971}
1972
1973#[cfg(apple_targets)]
1975struct GetCString<T: AsMut<[u8]>> {
1976 len: socklen_t,
1977 val: MaybeUninit<T>,
1978}
1979
1980#[cfg(apple_targets)]
1981impl<T: AsMut<[u8]>> Get<CString> for GetCString<T> {
1982 fn uninit() -> Self {
1983 GetCString {
1984 len: mem::size_of::<T>() as socklen_t,
1985 val: MaybeUninit::uninit(),
1986 }
1987 }
1988
1989 fn ffi_ptr(&mut self) -> *mut c_void {
1990 self.val.as_mut_ptr().cast()
1991 }
1992
1993 fn ffi_len(&mut self) -> *mut socklen_t {
1994 &mut self.len
1995 }
1996
1997 unsafe fn assume_init(self) -> CString {
1998 let mut v = unsafe { self.val.assume_init() };
1999 CStr::from_bytes_until_nul(v.as_mut())
2000 .expect("string should be null-terminated")
2001 .to_owned()
2002 }
2003}