Skip to content

Commit d5c3de1

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

File tree

3 files changed

+66
-0
lines changed

3 files changed

+66
-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: 60 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,14 @@ impl<'a> ControlMessage<'a> {
538550
ControlMessage::ScmTimestamp(t) => {
539551
mem::size_of_val(t)
540552
},
553+
#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios"))]
554+
ControlMessage::Ipv4PacketInfo(pktinfo) => {
555+
mem::size_of_val(pktinfo)
556+
},
557+
#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios"))]
558+
ControlMessage::Ipv6PacketInfo(pktinfo) => {
559+
mem::size_of_val(pktinfo)
560+
},
541561
ControlMessage::Unknown(UnknownCmsg(_, bytes)) => {
542562
mem::size_of_val(bytes)
543563
}
@@ -586,6 +606,46 @@ impl<'a> ControlMessage<'a> {
586606

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