Skip to content

Commit

Permalink
aya: Return error messages from netlink
Browse files Browse the repository at this point in the history
This returns error strings from netlink since they are more informative
than the raw os error. For example:

"Device or Resource Busy" vs. "XDP program already attached".

Signed-off-by: Dave Tucker <dave@dtucker.co.uk>
  • Loading branch information
dave-tucker committed Jul 26, 2023
1 parent 53d36a3 commit c7cb0bb
Showing 1 changed file with 38 additions and 12 deletions.
50 changes: 38 additions & 12 deletions aya/src/sys/netlink.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
use object::Endianness;
use std::{collections::HashMap, ffi::CStr, io, mem, os::unix::io::RawFd, ptr, slice};
use thiserror::Error;

use libc::{
close, getsockname, nlattr, nlmsgerr, nlmsghdr, recv, send, setsockopt, sockaddr_nl, socket,
AF_NETLINK, AF_UNSPEC, ETH_P_ALL, IFLA_XDP, NETLINK_EXT_ACK, NETLINK_ROUTE, NLA_ALIGNTO,
NLA_F_NESTED, NLA_TYPE_MASK, NLMSG_DONE, NLMSG_ERROR, NLM_F_ACK, NLM_F_CREATE, NLM_F_DUMP,
NLM_F_ECHO, NLM_F_EXCL, NLM_F_MULTI, NLM_F_REQUEST, RTM_DELTFILTER, RTM_GETTFILTER,
RTM_NEWQDISC, RTM_NEWTFILTER, RTM_SETLINK, SOCK_RAW, SOL_NETLINK,
AF_NETLINK, AF_PACKET, AF_UNSPEC, ETH_P_ALL, IFLA_XDP, NETLINK_CAP_ACK, NETLINK_EXT_ACK,
NETLINK_ROUTE, NLA_ALIGNTO, NLA_F_NESTED, NLA_TYPE_MASK, NLMSG_DONE, NLMSG_ERROR, NLM_F_ACK,
NLM_F_CREATE, NLM_F_DUMP, NLM_F_ECHO, NLM_F_EXCL, NLM_F_MULTI, NLM_F_REQUEST, RTM_DELTFILTER,
RTM_GETLINK, RTM_GETTFILTER, RTM_NEWLINK, RTM_NEWQDISC, RTM_NEWTFILTER, RTM_SETLINK, SOCK_RAW,
SOL_NETLINK,
};

use crate::{
generated::{
ifinfomsg, tcmsg, IFLA_XDP_EXPECTED_FD, IFLA_XDP_FD, IFLA_XDP_FLAGS, NLMSG_ALIGNTO,
TCA_BPF_FD, TCA_BPF_FLAGS, TCA_BPF_FLAG_ACT_DIRECT, TCA_BPF_NAME, TCA_KIND, TCA_OPTIONS,
TC_H_CLSACT, TC_H_INGRESS, TC_H_MAJ_MASK, TC_H_UNSPEC, XDP_FLAGS_REPLACE,
ifinfomsg, tcmsg, IFLA_XDP_EXPECTED_FD, IFLA_XDP_FD, IFLA_XDP_FLAGS, IFLA_XDP_PROG_ID,
NLMSG_ALIGNTO, TCA_BPF_FD, TCA_BPF_FLAGS, TCA_BPF_FLAG_ACT_DIRECT, TCA_BPF_NAME, TCA_KIND,
TCA_OPTIONS, TC_H_CLSACT, TC_H_INGRESS, TC_H_MAJ_MASK, TC_H_UNSPEC, XDP_FLAGS_REPLACE,
},
programs::TcAttachType,
util::tc_handler_make,
};

const NLMSGERR_ATTR_MSG: u16 = 0x01;
const NLA_HDR_LEN: usize = align_to(mem::size_of::<nlattr>(), NLA_ALIGNTO as usize);

// Safety: marking this as unsafe overall because of all the pointer math required to comply with
Expand Down Expand Up @@ -62,9 +65,7 @@ pub(crate) unsafe fn netlink_set_xdp_fd(
req.header.nlmsg_len += align_to(nla_len, NLA_ALIGNTO as usize) as u32;

sock.send(&bytes_of(&req)[..req.header.nlmsg_len as usize])?;

sock.recv()?;

Ok(())
}

Expand Down Expand Up @@ -270,13 +271,22 @@ impl NetlinkSocket {
let enable = 1i32;
// Safety: libc wrapper
unsafe {
// Set NETLINK_EXT_ACK to get extended attributes
setsockopt(
sock,
SOL_NETLINK,
NETLINK_EXT_ACK,
&enable as *const _ as *const _,
mem::size_of::<i32>() as u32,
)
);
// Set NETLINK_CAP_ACK to avoid getting copies of request payload
setsockopt(
sock,
SOL_NETLINK,
NETLINK_CAP_ACK,
&enable as *const _ as *const _,
mem::size_of::<i32>() as u32,
);
};

// Safety: sockaddr_nl is POD so this is safe
Expand Down Expand Up @@ -330,7 +340,23 @@ impl NetlinkSocket {
// this is an ACK
continue;
}
return Err(io::Error::from_raw_os_error(-err.error));
let attrs = parse_attrs(&message.data)?;
let err_msg = attrs.get(&NLMSGERR_ATTR_MSG).and_then(|msg| {
CStr::from_bytes_with_nul(msg.data)
.ok()
.map(|s| s.to_string_lossy().into_owned())
});
match err_msg {
Some(err_msg) => {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("netlink error: {}", err_msg),
));
}
None => {
return Err(io::Error::from_raw_os_error(-err.error));
}
}
}
NLMSG_DONE => break 'out,
_ => messages.push(message),
Expand Down Expand Up @@ -377,7 +403,7 @@ impl NetlinkMessage {
));
}
(
Vec::new(),
buf[data_offset + mem::size_of::<nlmsgerr>()..msg_len].to_vec(),
// Safety: nlmsgerr is POD so read is safe
Some(unsafe {
ptr::read_unaligned(buf[data_offset..].as_ptr() as *const nlmsgerr)
Expand Down

0 comments on commit c7cb0bb

Please sign in to comment.