Skip to content

Commit f404d9d

Browse files
bors[bot]pusateri
andcommitted
Merge #990
990: Add cmsg PKTINFO for IPv4 and IPv6. r=asomers a=pusateri Replaces #891 and attempts to address all previous concerns. Co-authored-by: Tom Pusateri <pusateri@bangj.com>
2 parents 51bd085 + 940a8de commit f404d9d

File tree

4 files changed

+374
-7
lines changed

4 files changed

+374
-7
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file.
44
This project adheres to [Semantic Versioning](http://semver.org/).
55

66
## [Unreleased]
7+
- Added PKTINFO(V4) & V6PKTINFO cmsg support - Android/FreeBSD/iOS/Linux/MacOS.
8+
([#990](https://github.com/nix-rust/nix/pull/990))
79
### Added
810
- Added support of CString type in `setsockopt`.
911
([#972](https://github.com/nix-rust/nix/pull/972))

src/sys/socket/mod.rs

Lines changed: 123 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ pub use self::addr::{
2828
Ipv6Addr,
2929
LinkAddr,
3030
};
31-
#[cfg(any(target_os = "linux", target_os = "android"))]
31+
#[cfg(any(target_os = "android", target_os = "linux"))]
3232
pub use ::sys::socket::addr::netlink::NetlinkAddr;
3333

3434
pub use libc::{
@@ -153,7 +153,7 @@ libc_bitflags!{
153153
/// This flag specifies that queued errors should be received from
154154
/// the socket error queue. (For more details, see
155155
/// [recvfrom(2)](https://linux.die.net/man/2/recvfrom))
156-
#[cfg(any(target_os = "linux", target_os = "android"))]
156+
#[cfg(any(target_os = "android", target_os = "linux"))]
157157
MSG_ERRQUEUE;
158158
/// Set the `close-on-exec` flag for the file descriptor received via a UNIX domain
159159
/// file descriptor using the `SCM_RIGHTS` operation (described in
@@ -526,6 +526,23 @@ pub enum ControlMessage<'a> {
526526
/// nix::unistd::close(in_socket).unwrap();
527527
/// ```
528528
ScmTimestamp(&'a TimeVal),
529+
530+
#[cfg(any(
531+
target_os = "android",
532+
target_os = "ios",
533+
target_os = "linux",
534+
target_os = "macos"
535+
))]
536+
Ipv4PacketInfo(&'a libc::in_pktinfo),
537+
#[cfg(any(
538+
target_os = "android",
539+
target_os = "freebsd",
540+
target_os = "ios",
541+
target_os = "linux",
542+
target_os = "macos"
543+
))]
544+
Ipv6PacketInfo(&'a libc::in6_pktinfo),
545+
529546
/// Catch-all variant for unimplemented cmsg types.
530547
#[doc(hidden)]
531548
Unknown(UnknownCmsg<'a>),
@@ -565,19 +582,79 @@ impl<'a> ControlMessage<'a> {
565582
ControlMessage::ScmTimestamp(t) => {
566583
mem::size_of_val(t)
567584
},
585+
#[cfg(any(
586+
target_os = "android",
587+
target_os = "ios",
588+
target_os = "linux",
589+
target_os = "macos"
590+
))]
591+
ControlMessage::Ipv4PacketInfo(pktinfo) => {
592+
mem::size_of_val(pktinfo)
593+
},
594+
#[cfg(any(
595+
target_os = "android",
596+
target_os = "freebsd",
597+
target_os = "ios",
598+
target_os = "linux",
599+
target_os = "macos"
600+
))]
601+
ControlMessage::Ipv6PacketInfo(pktinfo) => {
602+
mem::size_of_val(pktinfo)
603+
},
568604
ControlMessage::Unknown(UnknownCmsg(_, bytes)) => {
569605
mem::size_of_val(bytes)
570606
}
571607
}
572608
}
573609

610+
/// Returns the value to put into the `cmsg_level` field of the header.
611+
fn cmsg_level(&self) -> libc::c_int {
612+
match *self {
613+
ControlMessage::ScmRights(_) => libc::SOL_SOCKET,
614+
#[cfg(any(target_os = "android", target_os = "linux"))]
615+
ControlMessage::ScmCredentials(_) => libc::SOL_SOCKET,
616+
ControlMessage::ScmTimestamp(_) => libc::SOL_SOCKET,
617+
#[cfg(any(
618+
target_os = "android",
619+
target_os = "ios",
620+
target_os = "linux",
621+
target_os = "macos"
622+
))]
623+
ControlMessage::Ipv4PacketInfo(_) => libc::IPPROTO_IP,
624+
#[cfg(any(
625+
target_os = "android",
626+
target_os = "freebsd",
627+
target_os = "ios",
628+
target_os = "linux",
629+
target_os = "macos"
630+
))]
631+
ControlMessage::Ipv6PacketInfo(_) => libc::IPPROTO_IPV6,
632+
ControlMessage::Unknown(ref cmsg) => cmsg.0.cmsg_level,
633+
}
634+
}
635+
574636
/// Returns the value to put into the `cmsg_type` field of the header.
575637
fn cmsg_type(&self) -> libc::c_int {
576638
match *self {
577639
ControlMessage::ScmRights(_) => libc::SCM_RIGHTS,
578640
#[cfg(any(target_os = "android", target_os = "linux"))]
579641
ControlMessage::ScmCredentials(_) => libc::SCM_CREDENTIALS,
580642
ControlMessage::ScmTimestamp(_) => libc::SCM_TIMESTAMP,
643+
#[cfg(any(
644+
target_os = "android",
645+
target_os = "ios",
646+
target_os = "linux",
647+
target_os = "macos"
648+
))]
649+
ControlMessage::Ipv4PacketInfo(_) => libc::IP_PKTINFO,
650+
#[cfg(any(
651+
target_os = "android",
652+
target_os = "freebsd",
653+
target_os = "ios",
654+
target_os = "linux",
655+
target_os = "macos"
656+
))]
657+
ControlMessage::Ipv6PacketInfo(_) => libc::IPV6_PKTINFO,
581658
ControlMessage::Unknown(ref cmsg) => cmsg.0.cmsg_type,
582659
}
583660
}
@@ -598,7 +675,7 @@ impl<'a> ControlMessage<'a> {
598675
} else {
599676
let cmsg = cmsghdr {
600677
cmsg_len: self.len() as _,
601-
cmsg_level: libc::SOL_SOCKET,
678+
cmsg_level: self.cmsg_level(),
602679
cmsg_type: self.cmsg_type(),
603680
..mem::zeroed() // zero out platform-dependent padding fields
604681
};
@@ -615,10 +692,29 @@ impl<'a> ControlMessage<'a> {
615692
#[cfg(any(target_os = "android", target_os = "linux"))]
616693
ControlMessage::ScmCredentials(creds) => {
617694
copy_bytes(creds, buf)
618-
}
695+
},
619696
ControlMessage::ScmTimestamp(t) => {
620697
copy_bytes(t, buf)
621698
},
699+
#[cfg(any(
700+
target_os = "android",
701+
target_os = "ios",
702+
target_os = "linux",
703+
target_os = "macos"
704+
))]
705+
ControlMessage::Ipv4PacketInfo(pktinfo) => {
706+
copy_bytes(pktinfo, buf)
707+
},
708+
#[cfg(any(
709+
target_os = "android",
710+
target_os = "freebsd",
711+
target_os = "ios",
712+
target_os = "linux",
713+
target_os = "macos"
714+
))]
715+
ControlMessage::Ipv6PacketInfo(pktinfo) => {
716+
copy_bytes(pktinfo, buf)
717+
}
622718
ControlMessage::Unknown(_) => unreachable!(),
623719
}
624720
};
@@ -650,6 +746,28 @@ impl<'a> ControlMessage<'a> {
650746
ControlMessage::ScmTimestamp(
651747
&*(data.as_ptr() as *const _))
652748
},
749+
#[cfg(any(
750+
target_os = "android",
751+
target_os = "freebsd",
752+
target_os = "ios",
753+
target_os = "linux",
754+
target_os = "macos"
755+
))]
756+
(libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => {
757+
ControlMessage::Ipv6PacketInfo(
758+
&*(data.as_ptr() as *const _))
759+
}
760+
#[cfg(any(
761+
target_os = "android",
762+
target_os = "ios",
763+
target_os = "linux",
764+
target_os = "macos"
765+
))]
766+
(libc::IPPROTO_IP, libc::IP_PKTINFO) => {
767+
ControlMessage::Ipv4PacketInfo(
768+
&*(data.as_ptr() as *const _))
769+
}
770+
653771
(_, _) => {
654772
ControlMessage::Unknown(UnknownCmsg(header, data))
655773
}
@@ -1055,7 +1173,7 @@ pub unsafe fn sockaddr_storage_to_addr(
10551173
let pathlen = len - offset_of!(sockaddr_un, sun_path);
10561174
Ok(SockAddr::Unix(UnixAddr(sun, pathlen)))
10571175
}
1058-
#[cfg(any(target_os = "linux", target_os = "android"))]
1176+
#[cfg(any(target_os = "android", target_os = "linux"))]
10591177
libc::AF_NETLINK => {
10601178
use libc::sockaddr_nl;
10611179
Ok(SockAddr::Netlink(NetlinkAddr(*(addr as *const _ as *const sockaddr_nl))))

src/sys/socket/sockopt.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,22 @@ sockopt_impl!(Both, Mark, libc::SOL_SOCKET, libc::SO_MARK, u32);
271271
sockopt_impl!(Both, PassCred, libc::SOL_SOCKET, libc::SO_PASSCRED, bool);
272272
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
273273
sockopt_impl!(Both, TcpCongestion, libc::IPPROTO_TCP, libc::TCP_CONGESTION, OsString<[u8; TCP_CA_NAME_MAX]>);
274+
#[cfg(any(
275+
target_os = "android",
276+
target_os = "ios",
277+
target_os = "linux",
278+
target_os = "macos"
279+
))]
280+
sockopt_impl!(Both, Ipv4PacketInfo, libc::IPPROTO_IP, libc::IP_PKTINFO, bool);
281+
#[cfg(any(
282+
target_os = "android",
283+
target_os = "freebsd",
284+
target_os = "ios",
285+
target_os = "linux",
286+
target_os = "macos"
287+
))]
288+
sockopt_impl!(Both, Ipv6RecvPacketInfo, libc::IPPROTO_IPV6, libc::IPV6_RECVPKTINFO, bool);
289+
274290

275291
/*
276292
*

0 commit comments

Comments
 (0)