# crate and it aims
to provide some features with safe APIs currently missing from `socket2`. As the result, this
library can be used as a drop-in replacement of `socket2`.
The following are the additional features or APIs:
- [`socket::Socket::recv_from_initialized`]
- [`socket::Socket::recvmsg_initialized`]
- [`socket::Socket::set_pktinfo_v4`]
- [`socket::Socket::set_recv_pktinfo_v6`]
- [`MsgHdrInit`]: support `recvmsg` message header operations.
- [`CMsgHdr`]: support Control Messages used in `recvmsg_initialized`.
"#
)]
#![deny(missing_docs, missing_debug_implementations, rust_2018_idioms)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(test, deny(warnings))]
#![doc(test(attr(deny(warnings))))]
use std::fmt;
#[cfg(not(target_os = "redox"))]
use std::io::IoSlice;
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",
target_os = "redox",
target_os = "vita",
)))]
use std::io::IoSliceMut;
#[cfg(not(target_os = "redox"))]
use std::marker::PhantomData;
#[cfg(not(target_os = "redox"))]
use std::mem;
use std::mem::MaybeUninit;
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr};
use std::ops::{Deref, DerefMut};
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",
target_os = "redox",
target_os = "vita",
)))]
use std::ptr;
use std::time::Duration;
macro_rules! impl_debug {
(
// Type name for which to implement `fmt::Debug`.
$type: path,
$(
$(#[$target: meta])*
// The flag(s) to check.
$libc: ident :: $flag: ident
),+ $(,)*
) => {
impl std::fmt::Debug for $type {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let string = match self.0 {
$(
$(#[$target])*
$libc :: $flag => stringify!($flag),
)+
n => return write!(f, "{n}"),
};
f.write_str(string)
}
}
};
}
macro_rules! from {
($from: ty, $for: ty) => {
impl From<$from> for $for {
fn from(socket: $from) -> $for {
#[cfg(unix)]
unsafe {
<$for>::from_raw_fd(socket.into_raw_fd())
}
#[cfg(windows)]
unsafe {
<$for>::from_raw_socket(socket.into_raw_socket())
}
}
}
};
}
#[rustfmt::skip]
macro_rules! man_links {
($syscall: tt ( $section: tt ) ) => {
concat!(
man_links!(__ intro),
man_links!(__ unix $syscall($section)),
man_links!(__ windows $syscall($section)),
)
};
(unix: $syscall: tt ( $section: tt ) ) => {
concat!(
man_links!(__ intro),
man_links!(__ unix $syscall($section)),
)
};
(windows: $syscall: tt ( $section: tt ) ) => {
concat!(
man_links!(__ intro),
man_links!(__ windows $syscall($section)),
)
};
(__ intro) => {
"\n\nAdditional documentation can be found in manual of the OS:\n\n"
};
(__ unix $syscall: tt ( $section: tt ) ) => {
concat!(
" * DragonFly BSD: <https://man.dragonflybsd.org/?command=", stringify!($syscall), "§ion=", stringify!($section), ">\n",
" * FreeBSD: <https://www.freebsd.org/cgi/man.cgi?query=", stringify!($syscall), "&sektion=", stringify!($section), ">\n",
" * Linux: <https://man7.org/linux/man-pages/man", stringify!($section), "/", stringify!($syscall), ".", stringify!($section), ".html>\n",
" * macOS: <https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/", stringify!($syscall), ".", stringify!($section), ".html> (archived, actually for iOS)\n",
" * NetBSD: <https://man.netbsd.org/", stringify!($syscall), ".", stringify!($section), ">\n",
" * OpenBSD: <https://man.openbsd.org/", stringify!($syscall), ".", stringify!($section), ">\n",
" * iOS: <https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/", stringify!($syscall), ".", stringify!($section), ".html> (archived)\n",
" * illumos: <https://illumos.org/man/3SOCKET/", stringify!($syscall), ">\n",
)
};
(__ windows $syscall: tt ( $section: tt ) ) => {
concat!(
" * Windows: <https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-", stringify!($syscall), ">\n",
)
};
}
mod sockaddr;
mod socket;
mod sockref;
#[cfg_attr(unix, path = "sys/unix.rs")]
#[cfg_attr(windows, path = "sys/windows.rs")]
mod sys;
#[cfg(not(any(windows, unix)))]
compile_error!("Socket2 doesn't support the compile target");
use sys::c_int;
pub use sockaddr::SockAddr;
pub use socket::Socket;
pub use sockref::SockRef;
#[cfg(not(any(
target_os = "haiku",
target_os = "illumos",
target_os = "netbsd",
target_os = "redox",
target_os = "solaris",
)))]
pub use socket::InterfaceIndexOrAddress;
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Domain(c_int);
impl Domain {
pub const IPV4: Domain = Domain(sys::AF_INET);
pub const IPV6: Domain = Domain(sys::AF_INET6);
pub const UNIX: Domain = Domain(sys::AF_UNIX);
pub const fn for_address(address: SocketAddr) -> Domain {
match address {
SocketAddr::V4(_) => Domain::IPV4,
SocketAddr::V6(_) => Domain::IPV6,
}
}
}
impl From<c_int> for Domain {
fn from(d: c_int) -> Domain {
Domain(d)
}
}
impl From<Domain> for c_int {
fn from(d: Domain) -> c_int {
d.0
}
}
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Type(c_int);
impl Type {
pub const STREAM: Type = Type(sys::SOCK_STREAM);
pub const DGRAM: Type = Type(sys::SOCK_DGRAM);
#[cfg(all(feature = "all", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "all", target_os = "linux"))))]
pub const DCCP: Type = Type(sys::SOCK_DCCP);
#[cfg(all(feature = "all", not(target_os = "espidf")))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "all", not(target_os = "espidf")))))]
pub const SEQPACKET: Type = Type(sys::SOCK_SEQPACKET);
#[cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf"))))]
#[cfg_attr(
docsrs,
doc(cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf")))))
)]
pub const RAW: Type = Type(sys::SOCK_RAW);
}
impl From<c_int> for Type {
fn from(t: c_int) -> Type {
Type(t)
}
}
impl From<Type> for c_int {
fn from(t: Type) -> c_int {
t.0
}
}
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Protocol(c_int);
impl Protocol {
pub const ICMPV4: Protocol = Protocol(sys::IPPROTO_ICMP);
pub const ICMPV6: Protocol = Protocol(sys::IPPROTO_ICMPV6);
pub const TCP: Protocol = Protocol(sys::IPPROTO_TCP);
pub const UDP: Protocol = Protocol(sys::IPPROTO_UDP);
#[cfg(target_os = "linux")]
pub const MPTCP: Protocol = Protocol(sys::IPPROTO_MPTCP);
#[cfg(all(feature = "all", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "all", target_os = "linux"))))]
pub const DCCP: Protocol = Protocol(sys::IPPROTO_DCCP);
#[cfg(all(feature = "all", any(target_os = "freebsd", target_os = "linux")))]
pub const SCTP: Protocol = Protocol(sys::IPPROTO_SCTP);
#[cfg(all(
feature = "all",
any(
target_os = "android",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "linux",
)
))]
pub const UDPLITE: Protocol = Protocol(sys::IPPROTO_UDPLITE);
#[cfg(all(feature = "all", any(target_os = "freebsd", target_os = "openbsd")))]
pub const DIVERT: Protocol = Protocol(sys::IPPROTO_DIVERT);
}
impl From<c_int> for Protocol {
fn from(p: c_int) -> Protocol {
Protocol(p)
}
}
impl From<Protocol> for c_int {
fn from(p: Protocol) -> c_int {
p.0
}
}
#[cfg(not(target_os = "redox"))]
#[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct RecvFlags(c_int);
#[cfg(not(target_os = "redox"))]
impl RecvFlags {
#[cfg(not(target_os = "espidf"))]
pub const fn is_truncated(self) -> bool {
self.0 & sys::MSG_TRUNC != 0
}
}
#[repr(transparent)]
pub struct MaybeUninitSlice<'a>(sys::MaybeUninitSlice<'a>);
impl<'a> fmt::Debug for MaybeUninitSlice<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self.0.as_slice(), fmt)
}
}
impl<'a> MaybeUninitSlice<'a> {
pub fn new(buf: &'a mut [MaybeUninit<u8>]) -> MaybeUninitSlice<'a> {
MaybeUninitSlice(sys::MaybeUninitSlice::new(buf))
}
}
impl<'a> Deref for MaybeUninitSlice<'a> {
type Target = [MaybeUninit<u8>];
fn deref(&self) -> &[MaybeUninit<u8>] {
self.0.as_slice()
}
}
impl<'a> DerefMut for MaybeUninitSlice<'a> {
fn deref_mut(&mut self) -> &mut [MaybeUninit<u8>] {
self.0.as_mut_slice()
}
}
#[derive(Debug, Clone)]
pub struct TcpKeepalive {
#[cfg_attr(
any(target_os = "openbsd", target_os = "haiku", target_os = "vita"),
allow(dead_code)
)]
time: Option<Duration>,
#[cfg(not(any(
target_os = "openbsd",
target_os = "redox",
target_os = "solaris",
target_os = "nto",
target_os = "espidf",
target_os = "vita",
target_os = "haiku",
)))]
interval: Option<Duration>,
#[cfg(not(any(
target_os = "openbsd",
target_os = "redox",
target_os = "solaris",
target_os = "windows",
target_os = "nto",
target_os = "espidf",
target_os = "vita",
target_os = "haiku",
)))]
retries: Option<u32>,
}
impl TcpKeepalive {
pub const fn new() -> TcpKeepalive {
TcpKeepalive {
time: None,
#[cfg(not(any(
target_os = "openbsd",
target_os = "redox",
target_os = "solaris",
target_os = "nto",
target_os = "espidf",
target_os = "vita",
target_os = "haiku",
)))]
interval: None,
#[cfg(not(any(
target_os = "openbsd",
target_os = "redox",
target_os = "solaris",
target_os = "windows",
target_os = "nto",
target_os = "espidf",
target_os = "vita",
target_os = "haiku",
)))]
retries: None,
}
}
pub const fn with_time(self, time: Duration) -> Self {
Self {
time: Some(time),
..self
}
}
#[cfg(any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "illumos",
target_os = "ios",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
target_os = "tvos",
target_os = "watchos",
target_os = "windows",
))]
#[cfg_attr(
docsrs,
doc(cfg(any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "illumos",
target_os = "ios",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
target_os = "tvos",
target_os = "watchos",
target_os = "windows",
)))
)]
pub const fn with_interval(self, interval: Duration) -> Self {
Self {
interval: Some(interval),
..self
}
}
#[cfg(all(
feature = "all",
any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "illumos",
target_os = "ios",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
target_os = "tvos",
target_os = "watchos",
)
))]
#[cfg_attr(
docsrs,
doc(cfg(all(
feature = "all",
any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "illumos",
target_os = "ios",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
target_os = "tvos",
target_os = "watchos",
)
)))
)]
pub const fn with_retries(self, retries: u32) -> Self {
Self {
retries: Some(retries),
..self
}
}
}
impl Default for TcpKeepalive {
fn default() -> Self {
Self::new()
}
}
#[cfg(not(target_os = "redox"))]
pub struct MsgHdr<'addr, 'bufs, 'control> {
inner: sys::msghdr,
#[allow(clippy::type_complexity)]
_lifetimes: PhantomData<(&'addr SockAddr, &'bufs IoSlice<'bufs>, &'control [u8])>,
}
#[cfg(not(target_os = "redox"))]
impl<'addr, 'bufs, 'control> MsgHdr<'addr, 'bufs, 'control> {
#[allow(clippy::new_without_default)]
pub fn new() -> MsgHdr<'addr, 'bufs, 'control> {
MsgHdr {
inner: unsafe { mem::zeroed() },
_lifetimes: PhantomData,
}
}
pub fn with_addr(mut self, addr: &'addr SockAddr) -> Self {
sys::set_msghdr_name(&mut self.inner, addr);
self
}
pub fn with_buffers(mut self, bufs: &'bufs [IoSlice<'_>]) -> Self {
let ptr = bufs.as_ptr() as *mut _;
sys::set_msghdr_iov(&mut self.inner, ptr, bufs.len());
self
}
pub fn with_control(mut self, buf: &'control [u8]) -> Self {
let ptr = buf.as_ptr() as *mut _;
sys::set_msghdr_control(&mut self.inner, ptr, buf.len());
self
}
pub fn with_flags(mut self, flags: sys::c_int) -> Self {
sys::set_msghdr_flags(&mut self.inner, flags);
self
}
}
#[cfg(not(target_os = "redox"))]
impl<'name, 'bufs, 'control> fmt::Debug for MsgHdr<'name, 'bufs, 'control> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
"MsgHdr".fmt(fmt)
}
}
#[cfg(not(target_os = "redox"))]
pub struct MsgHdrMut<'addr, 'bufs, 'control> {
inner: sys::msghdr,
#[allow(clippy::type_complexity)]
_lifetimes: PhantomData<(
&'addr mut SockAddr,
&'bufs mut MaybeUninitSlice<'bufs>,
&'control mut [u8],
)>,
}
#[cfg(not(target_os = "redox"))]
impl<'addr, 'bufs, 'control> MsgHdrMut<'addr, 'bufs, 'control> {
#[allow(clippy::new_without_default)]
pub fn new() -> MsgHdrMut<'addr, 'bufs, 'control> {
MsgHdrMut {
inner: unsafe { mem::zeroed() },
_lifetimes: PhantomData,
}
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn with_addr(mut self, addr: &'addr mut SockAddr) -> Self {
sys::set_msghdr_name(&mut self.inner, addr);
self
}
pub fn with_buffers(mut self, bufs: &'bufs mut [MaybeUninitSlice<'_>]) -> Self {
sys::set_msghdr_iov(&mut self.inner, bufs.as_mut_ptr().cast(), bufs.len());
self
}
pub fn with_control(mut self, buf: &'control mut [MaybeUninit<u8>]) -> Self {
sys::set_msghdr_control(&mut self.inner, buf.as_mut_ptr().cast(), buf.len());
self
}
pub fn flags(&self) -> RecvFlags {
sys::msghdr_flags(&self.inner)
}
pub fn control_len(&self) -> usize {
sys::msghdr_control_len(&self.inner)
}
}
#[cfg(not(target_os = "redox"))]
impl<'name, 'bufs, 'control> fmt::Debug for MsgHdrMut<'name, 'bufs, 'control> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
"MsgHdrMut".fmt(fmt)
}
}
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",
target_os = "redox",
target_os = "vita",
)))]
pub struct MsgHdrInit<'addr, 'bufs, 'control> {
inner: sys::msghdr,
src: Option<&'addr mut SockAddr>,
_lifetimes: PhantomData<(&'bufs [IoSliceMut<'bufs>], &'control [u8])>,
}
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",
target_os = "redox",
target_os = "vita",
)))]
impl<'addr, 'bufs, 'control> MsgHdrInit<'addr, 'bufs, 'control> {
#[allow(clippy::new_without_default)]
pub fn new() -> MsgHdrInit<'addr, 'bufs, 'control> {
MsgHdrInit {
inner: unsafe { mem::zeroed() },
src: None,
_lifetimes: PhantomData,
}
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn with_addr(mut self, addr: &'addr mut SockAddr) -> Self {
sys::set_msghdr_name(&mut self.inner, addr);
self.src = Some(addr);
self
}
pub fn with_buffers(mut self, buf_list: &'bufs mut [IoSliceMut<'_>]) -> Self {
sys::set_msghdr_iov(
&mut self.inner,
buf_list.as_mut_ptr().cast(),
buf_list.len(),
);
self
}
pub fn with_control(mut self, buf: &'control mut [u8]) -> Self {
sys::set_msghdr_control(&mut self.inner, buf.as_mut_ptr().cast(), buf.len());
self
}
pub fn cmsg_hdr_vec(&self) -> Vec<CMsgHdr<'_>> {
let mut cmsg_vec = Vec::new();
let mut cmsg = self.inner.cmsg_first_hdr();
if !cmsg.is_null() {
let cmsg_hdr = unsafe { CMsgHdr { inner: &*cmsg } };
cmsg_vec.push(cmsg_hdr);
cmsg = self.inner.cmsg_next_hdr(unsafe { &*cmsg });
while !cmsg.is_null() {
let cmsg_hdr = unsafe { CMsgHdr { inner: &*cmsg } };
cmsg_vec.push(cmsg_hdr);
}
}
cmsg_vec
}
pub fn get_addr(&self) -> Option<&SockAddr> {
self.src.as_deref()
}
}
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",
target_os = "redox",
target_os = "vita",
)))]
impl fmt::Debug for MsgHdrInit<'_, '_, '_> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
"MsgHdrInit".fmt(fmt)
}
}
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",
target_os = "redox",
target_os = "vita",
)))]
pub(crate) trait MsgHdrOps {
fn cmsg_first_hdr(&self) -> *mut sys::cmsghdr;
fn cmsg_next_hdr(&self, cmsg: &sys::cmsghdr) -> *mut sys::cmsghdr;
}
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",
target_os = "redox",
target_os = "vita",
)))]
pub struct CMsgHdr<'a> {
inner: &'a sys::cmsghdr,
}
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",
target_os = "redox",
target_os = "vita",
)))]
impl CMsgHdr<'_> {
pub fn get_level(&self) -> CMsgLevel {
self.inner.cmsg_level
}
pub fn get_type(&self) -> CMsgType {
self.inner.cmsg_type
}
pub fn as_pktinfo_v4(&self) -> Option<PktInfoV4> {
if self.inner.cmsg_level != sys::IPPROTO_IP {
return None;
}
if self.inner.cmsg_type != sys::IP_PKTINFO {
return None;
}
let data_ptr = self.inner.cmsg_data();
let pktinfo = unsafe { ptr::read_unaligned(data_ptr as *const sys::InPktInfo) };
#[cfg(not(windows))]
let addr_dst = Ipv4Addr::from(u32::from_be(pktinfo.ipi_addr.s_addr));
#[cfg(windows)]
let addr_dst = Ipv4Addr::from(u32::from_be(unsafe { pktinfo.ipi_addr.S_un.S_addr }));
Some(PktInfoV4 {
if_index: pktinfo.ipi_ifindex as _,
addr_dst,
})
}
pub fn as_recvpktinfo_v6(&self) -> Option<PktInfoV6> {
if self.inner.cmsg_level != sys::IPPROTO_IPV6 {
return None;
}
if self.inner.cmsg_type != sys::IPV6_PKTINFO {
return None;
}
let data_ptr = self.inner.cmsg_data();
let pktinfo = unsafe { ptr::read_unaligned(data_ptr as *const sys::In6PktInfo) };
#[cfg(windows)]
let addr_dst = Ipv6Addr::from(unsafe { pktinfo.ipi6_addr.u.Byte });
#[cfg(not(windows))]
let addr_dst = Ipv6Addr::from(pktinfo.ipi6_addr.s6_addr);
Some(PktInfoV6 {
if_index: pktinfo.ipi6_ifindex as _,
addr_dst,
})
}
}
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",
target_os = "redox",
target_os = "vita",
)))]
pub(crate) trait CMsgHdrOps {
fn cmsg_data(&self) -> *mut u8;
}
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",
target_os = "redox",
target_os = "vita",
)))]
pub const fn cmsg_space(data_len: usize) -> usize {
sys::_cmsg_space(data_len)
}
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",
target_os = "redox",
target_os = "vita",
)))]
impl fmt::Debug for CMsgHdr<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"(len: {} level: {} type: {})",
self.inner.cmsg_len, self.inner.cmsg_level, self.inner.cmsg_type
)
}
}
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",
target_os = "redox",
target_os = "vita",
)))]
const IN_PKTINFO_SIZE: usize = mem::size_of::<sys::InPktInfo>();
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",
target_os = "redox",
target_os = "vita",
)))]
const IN6_PKTINFO_SIZE: usize = mem::size_of::<sys::In6PktInfo>();
#[derive(Debug)]
pub struct PktInfoV4 {
pub if_index: u64,
pub addr_dst: Ipv4Addr,
}
impl PktInfoV4 {
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",
target_os = "redox",
target_os = "vita",
)))]
pub const fn size() -> usize {
IN_PKTINFO_SIZE
}
}
#[derive(Debug)]
pub struct PktInfoV6 {
pub if_index: u64,
pub addr_dst: Ipv6Addr,
}
impl PktInfoV6 {
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",
target_os = "redox",
target_os = "vita",
)))]
pub const fn size() -> usize {
IN6_PKTINFO_SIZE
}
}
pub type CMsgLevel = i32;
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",
target_os = "redox",
target_os = "vita",
)))]
pub const CMSG_LEVEL_IPPROTO_IP: CMsgLevel = sys::IPPROTO_IP;
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",
target_os = "redox",
target_os = "vita",
)))]
pub const CMSG_LEVEL_IPPROTO_IPV6: CMsgLevel = sys::IPPROTO_IPV6;
pub type CMsgType = i32;
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",
target_os = "redox",
target_os = "vita",
)))]
pub const CMSG_TYPE_IP_PKTINFO: CMsgType = sys::IP_PKTINFO;
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",
target_os = "redox",
target_os = "vita",
)))]
pub const CMSG_TYPE_IPV6_PKTINFO: CMsgType = sys::IPV6_PKTINFO;