Skip to content

Commit 18ecaff

Browse files
committed
support PKTINFO cmsgs for Linux/macOS/iOS
Closes #890.
1 parent c2fb79e commit 18ecaff

File tree

3 files changed

+64
-0
lines changed

3 files changed

+64
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
3333
([#857](https://github.com/nix-rust/nix/pull/857))
3434
- Added `request_code_write_int!` on FreeBSD/DragonFlyBSD
3535
([#833](https://github.com/nix-rust/nix/pull/833))
36+
- Added PKTINFO cmsg support on Linux/macOS/iOS.
37+
([#891](https://github.com/nix-rust/nix/pull/891))
3638

3739
### Changed
3840
- Display and Debug for SysControlAddr now includes all fields.

src/sys/socket/mod.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,14 @@ impl<'a> Iterator for CmsgIterator<'a> {
414414
Some(ControlMessage::ScmTimestamp(
415415
&*(cmsg_data.as_ptr() as *const _)))
416416
},
417+
#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios"))]
418+
(libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => unsafe {
419+
Some(ControlMessage::Ipv6PacketInfo(& *(cmsg_data.as_ptr() as *const _)))
420+
},
421+
#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios"))]
422+
(libc::IPPROTO_IP, libc::IP_PKTINFO) => unsafe {
423+
Some(ControlMessage::Ipv4PacketInfo(& *(cmsg_data.as_ptr() as *const _)))
424+
},
417425
(_, _) => unsafe {
418426
Some(ControlMessage::Unknown(UnknownCmsg(
419427
cmsg,
@@ -504,6 +512,10 @@ pub enum ControlMessage<'a> {
504512
/// nix::unistd::close(in_socket).unwrap();
505513
/// ```
506514
ScmTimestamp(&'a TimeVal),
515+
#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios"))]
516+
Ipv4PacketInfo(&'a libc::in_pktinfo),
517+
#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios"))]
518+
Ipv6PacketInfo(&'a libc::in6_pktinfo),
507519
#[doc(hidden)]
508520
Unknown(UnknownCmsg<'a>),
509521
}
@@ -538,6 +550,12 @@ impl<'a> ControlMessage<'a> {
538550
ControlMessage::ScmTimestamp(t) => {
539551
mem::size_of_val(t)
540552
},
553+
ControlMessage::Ipv4PacketInfo(pktinfo) => {
554+
mem::size_of_val(pktinfo)
555+
},
556+
ControlMessage::Ipv6PacketInfo(pktinfo) => {
557+
mem::size_of_val(pktinfo)
558+
},
541559
ControlMessage::Unknown(UnknownCmsg(_, bytes)) => {
542560
mem::size_of_val(bytes)
543561
}
@@ -586,6 +604,46 @@ impl<'a> ControlMessage<'a> {
586604

587605
copy_bytes(t, buf);
588606
},
607+
#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios"))]
608+
ControlMessage::Ipv4PacketInfo(pktinfo) => {
609+
let cmsg = cmsghdr {
610+
cmsg_len: self.len() as _,
611+
cmsg_level: libc::IPPROTO_IP,
612+
cmsg_type: libc::IP_PKTINFO,
613+
..mem::uninitialized()
614+
};
615+
copy_bytes(&cmsg, buf);
616+
617+
let padlen = cmsg_align(mem::size_of_val(&cmsg)) -
618+
mem::size_of_val(&cmsg);
619+
620+
let mut tmpbuf = &mut [][..];
621+
mem::swap(&mut tmpbuf, buf);
622+
let (_padding, mut remainder) = tmpbuf.split_at_mut(padlen);
623+
mem::swap(buf, &mut remainder);
624+
625+
copy_bytes(pktinfo, buf);
626+
},
627+
#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios"))]
628+
ControlMessage::Ipv6PacketInfo(pktinfo) => {
629+
let cmsg = cmsghdr {
630+
cmsg_len: self.len() as _,
631+
cmsg_level: libc::IPPROTO_IPV6,
632+
cmsg_type: libc::IPV6_PKTINFO,
633+
..mem::uninitialized()
634+
};
635+
copy_bytes(&cmsg, buf);
636+
637+
let padlen = cmsg_align(mem::size_of_val(&cmsg)) -
638+
mem::size_of_val(&cmsg);
639+
640+
let mut tmpbuf = &mut [][..];
641+
mem::swap(&mut tmpbuf, buf);
642+
let (_padding, mut remainder) = tmpbuf.split_at_mut(padlen);
643+
mem::swap(buf, &mut remainder);
644+
645+
copy_bytes(pktinfo, buf);
646+
},
589647
ControlMessage::Unknown(UnknownCmsg(orig_cmsg, bytes)) => {
590648
copy_bytes(orig_cmsg, buf);
591649
copy_bytes(bytes, buf);

src/sys/socket/sockopt.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,10 @@ sockopt_impl!(Both, BindAny, libc::SOL_SOCKET, libc::SO_BINDANY, bool);
255255
sockopt_impl!(Both, BindAny, libc::IPPROTO_IP, libc::IP_BINDANY, bool);
256256
#[cfg(target_os = "linux")]
257257
sockopt_impl!(Both, Mark, libc::SOL_SOCKET, libc::SO_MARK, u32);
258+
#[cfg(any(target_os = "android", target_os = "linux", target_os = "ios", target_os = "macos"))]
259+
sockopt_impl!(Both, Ipv4PacketInfo, libc::IPPROTO_IP, libc::IP_PKTINFO, bool);
260+
#[cfg(any(target_os = "android", target_os = "linux", target_os = "ios", target_os = "macos"))]
261+
sockopt_impl!(Both, Ipv6RecvPacketInfo, libc::IPPROTO_IPV6, libc::IPV6_RECVPKTINFO, bool);
258262

259263
/*
260264
*

0 commit comments

Comments
 (0)