Skip to content

Commit d6bc9e2

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

File tree

3 files changed

+58
-0
lines changed

3 files changed

+58
-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: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,12 @@ impl<'a> Iterator for CmsgIterator<'a> {
414414
Some(ControlMessage::ScmTimestamp(
415415
&*(cmsg_data.as_ptr() as *const _)))
416416
},
417+
(libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => unsafe {
418+
Some(ControlMessage::Ipv6PacketInfo(& *(cmsg_data.as_ptr() as *const _)))
419+
},
420+
(libc::IPPROTO_IP, libc::IP_PKTINFO) => unsafe {
421+
Some(ControlMessage::Ipv4PacketInfo(& *(cmsg_data.as_ptr() as *const _)))
422+
},
417423
(_, _) => unsafe {
418424
Some(ControlMessage::Unknown(UnknownCmsg(
419425
cmsg,
@@ -504,6 +510,8 @@ pub enum ControlMessage<'a> {
504510
/// nix::unistd::close(in_socket).unwrap();
505511
/// ```
506512
ScmTimestamp(&'a TimeVal),
513+
Ipv4PacketInfo(&'a libc::in_pktinfo),
514+
Ipv6PacketInfo(&'a libc::in6_pktinfo),
507515
#[doc(hidden)]
508516
Unknown(UnknownCmsg<'a>),
509517
}
@@ -538,6 +546,12 @@ impl<'a> ControlMessage<'a> {
538546
ControlMessage::ScmTimestamp(t) => {
539547
mem::size_of_val(t)
540548
},
549+
ControlMessage::Ipv4PacketInfo(pktinfo) => {
550+
mem::size_of_val(pktinfo)
551+
},
552+
ControlMessage::Ipv6PacketInfo(pktinfo) => {
553+
mem::size_of_val(pktinfo)
554+
},
541555
ControlMessage::Unknown(UnknownCmsg(_, bytes)) => {
542556
mem::size_of_val(bytes)
543557
}
@@ -586,6 +600,44 @@ impl<'a> ControlMessage<'a> {
586600

587601
copy_bytes(t, buf);
588602
},
603+
ControlMessage::Ipv4PacketInfo(pktinfo) => {
604+
let cmsg = cmsghdr {
605+
cmsg_len: self.len() as _,
606+
cmsg_level: libc::IPPROTO_IP,
607+
cmsg_type: libc::IP_PKTINFO,
608+
..mem::uninitialized()
609+
};
610+
copy_bytes(&cmsg, buf);
611+
612+
let padlen = cmsg_align(mem::size_of_val(&cmsg)) -
613+
mem::size_of_val(&cmsg);
614+
615+
let mut tmpbuf = &mut [][..];
616+
mem::swap(&mut tmpbuf, buf);
617+
let (_padding, mut remainder) = tmpbuf.split_at_mut(padlen);
618+
mem::swap(buf, &mut remainder);
619+
620+
copy_bytes(pktinfo, buf);
621+
},
622+
ControlMessage::Ipv6PacketInfo(pktinfo) => {
623+
let cmsg = cmsghdr {
624+
cmsg_len: self.len() as _,
625+
cmsg_level: libc::IPPROTO_IPV6,
626+
cmsg_type: libc::IPV6_PKTINFO,
627+
..mem::uninitialized()
628+
};
629+
copy_bytes(&cmsg, buf);
630+
631+
let padlen = cmsg_align(mem::size_of_val(&cmsg)) -
632+
mem::size_of_val(&cmsg);
633+
634+
let mut tmpbuf = &mut [][..];
635+
mem::swap(&mut tmpbuf, buf);
636+
let (_padding, mut remainder) = tmpbuf.split_at_mut(padlen);
637+
mem::swap(buf, &mut remainder);
638+
639+
copy_bytes(pktinfo, buf);
640+
},
589641
ControlMessage::Unknown(UnknownCmsg(orig_cmsg, bytes)) => {
590642
copy_bytes(orig_cmsg, buf);
591643
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)