Skip to content

Instantly share code, notes, and snippets.

@proelbtn
Last active January 28, 2021 11:01
Show Gist options
  • Save proelbtn/c35d086c724bb42c7ffbe8137347501d to your computer and use it in GitHub Desktop.
Save proelbtn/c35d086c724bb42c7ffbe8137347501d to your computer and use it in GitHub Desktop.
recvmsg / sendmsg with Rust
// in Cargo.toml
// [dependencies]
// libc = "0.2.83"
// nix = "0.19.0"
use std::os::unix::io::AsRawFd;
use std::net::UdpSocket;
use std::net::SocketAddr;
use nix::cmsg_space;
use nix::sys::uio::IoVec;
use nix::sys::socket::recvmsg;
use nix::sys::socket::sendmsg;
use nix::sys::socket::setsockopt;
use nix::sys::socket::ControlMessage;
use nix::sys::socket::ControlMessageOwned;
use nix::sys::socket::MsgFlags;
use nix::sys::socket::sockopt::Ipv4PacketInfo;
use libc::in_addr;
use libc::in_pktinfo;
fn main() {
let listen_addr = "0.0.0.0:8080".parse::<SocketAddr>().unwrap();
let sock = UdpSocket::bind(listen_addr).unwrap();
let fd = sock.as_raw_fd();
let mut cmsg = cmsg_space!(in_pktinfo);
// 1. setsockopt IP_PKTINFO
setsockopt(fd, Ipv4PacketInfo, &true).unwrap();
loop {
// 2. recvmsg from socket
let buf: &mut [u8] = &mut [0; 2048];
let iov = &[IoVec::from_mut_slice(buf)];
let res = recvmsg(fd, iov, Some(&mut cmsg), MsgFlags::empty()).unwrap();
match res.cmsgs().next().unwrap() {
ControlMessageOwned::Ipv4PacketInfo(info) => {
let iov = &[IoVec::from_slice(buf)];
let info = in_pktinfo {
ipi_ifindex: info.ipi_ifindex,
ipi_spec_dst: in_addr { s_addr: 0 },
ipi_addr: in_addr { s_addr: 0 },
};
sendmsg(fd, iov, &[ControlMessage::Ipv4PacketInfo(&info)], MsgFlags::empty(), res.address.as_ref()).unwrap();
},
_ => break,
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment