in src/bsd.rs [317:378]
fn if_index_mtu(remote: IpAddr) -> Result<(u16, Option<usize>)> {
// Open route socket.
let mut fd = RouteSocket::new(PF_ROUTE, AF_UNSPEC)?;
// Send route message.
let query_seq = RouteSocket::new_seq();
let query = RouteMessage::new(remote, query_seq)?;
let query_version = query.version();
let query_type = query.kind();
fd.write_all((&query).into())?;
// Read route messages.
let pid = unsafe { getpid() };
loop {
let mut buf = vec![
0u8;
size_of::<rt_msghdr>() +
// There will never be `RTAX_MAX` sockaddrs attached, but it's a safe upper bound.
(RTAX_MAX as usize * size_of::<sockaddr_storage>())
];
let len = fd.read(&mut buf[..])?;
if len < size_of::<rt_msghdr>() {
return Err(default_err());
}
let (reply, mut sa) = buf.split_at(size_of::<rt_msghdr>());
let reply: rt_msghdr = reply.into();
if !(reply.rtm_version == query_version
&& reply.rtm_pid == pid
&& reply.rtm_seq == query_seq)
{
continue;
}
if reply.rtm_type != query_type {
return Err(default_err());
}
// This is a reply to our query.
// This is the reply we are looking for.
// Some BSDs let us get the interface index and MTU directly from the reply.
let mtu = (reply.rtm_rmx.rmx_mtu != 0)
.then(|| usize::try_from(reply.rtm_rmx.rmx_mtu))
.transpose()
.map_err(|e: TryFromIntError| unlikely_err(e.to_string()))?;
if reply.rtm_index != 0 {
// Some BSDs return the interface index directly.
return Ok((reply.rtm_index, mtu));
}
// For others, we need to extract it from the sockaddrs.
for i in 0..RTAX_MAX {
if (reply.rtm_addrs & (1 << i)) == 0 {
continue;
}
let saddr = unsafe { ptr::read_unaligned(sa.as_ptr().cast::<sockaddr>()) };
if saddr.sa_family != AF_LINK {
(_, sa) = sa.split_at(sockaddr_len(saddr.sa_family)?);
continue;
}
let sdl = unsafe { ptr::read_unaligned(sa.as_ptr().cast::<sockaddr_dl>()) };
return Ok((sdl.sdl_index, mtu));
}
}
}