wireguard-control: support multipart wireguard responses

previously, any messages beyond the first were ignored, so
innernet wouldn't be aware of all peers on the interface.

fixes #187
pull/186/head
Jake McGinty 2022-01-12 16:22:02 -06:00
parent 6541605319
commit dc40e20fcf
1 changed files with 30 additions and 18 deletions

View File

@ -130,18 +130,18 @@ impl<'a> TryFrom<Vec<WgPeerAttrs>> for PeerInfo {
} }
} }
impl<'a> TryFrom<&'a Wireguard> for Device { impl<'a> TryFrom<&'a [WgDeviceAttrs]> for Device {
type Error = io::Error; type Error = io::Error;
fn try_from(wg: &'a Wireguard) -> Result<Self, Self::Error> { fn try_from(nlas: &'a [WgDeviceAttrs]) -> Result<Self, Self::Error> {
let name = get_nla_value!(wg.nlas, WgDeviceAttrs, IfName) let name = get_nla_value!(nlas, WgDeviceAttrs, IfName)
.ok_or_else(|| io::ErrorKind::NotFound)? .ok_or_else(|| io::ErrorKind::NotFound)?
.parse()?; .parse()?;
let public_key = get_nla_value!(wg.nlas, WgDeviceAttrs, PublicKey).map(|key| Key(*key)); let public_key = get_nla_value!(nlas, WgDeviceAttrs, PublicKey).map(|key| Key(*key));
let private_key = get_nla_value!(wg.nlas, WgDeviceAttrs, PrivateKey).map(|key| Key(*key)); let private_key = get_nla_value!(nlas, WgDeviceAttrs, PrivateKey).map(|key| Key(*key));
let listen_port = get_nla_value!(wg.nlas, WgDeviceAttrs, ListenPort).cloned(); let listen_port = get_nla_value!(nlas, WgDeviceAttrs, ListenPort).cloned();
let fwmark = get_nla_value!(wg.nlas, WgDeviceAttrs, Fwmark).cloned(); let fwmark = get_nla_value!(nlas, WgDeviceAttrs, Fwmark).cloned();
let peers = get_nla_value!(wg.nlas, WgDeviceAttrs, Peers) let peers = get_nla_value!(nlas, WgDeviceAttrs, Peers)
.cloned() .cloned()
.unwrap_or_default() .unwrap_or_default()
.into_iter() .into_iter()
@ -359,17 +359,29 @@ pub fn get_by_name(name: &InterfaceName) -> Result<Device, io::Error> {
nlas: vec![WgDeviceAttrs::IfName(name.as_str_lossy().to_string())], nlas: vec![WgDeviceAttrs::IfName(name.as_str_lossy().to_string())],
}); });
let responses = netlink_request_genl(genlmsg, Some(NLM_F_REQUEST | NLM_F_DUMP | NLM_F_ACK))?; let responses = netlink_request_genl(genlmsg, Some(NLM_F_REQUEST | NLM_F_DUMP | NLM_F_ACK))?;
log::debug!("get_by_name: got {} response message(s) from netlink request", responses.len());
match responses.get(0) { let nlas =
Some(NetlinkMessage { responses
.into_iter()
.fold(Ok(vec![]), |nlas_res, nlmsg| {
let mut nlas = nlas_res?;
let mut message = match nlmsg {
NetlinkMessage {
payload: NetlinkPayload::InnerMessage(message), payload: NetlinkPayload::InnerMessage(message),
.. ..
}) => Device::try_from(&message.payload), } => message,
_ => Err(io::Error::new( _ => return Err(io::Error::new(
io::ErrorKind::InvalidData, io::ErrorKind::InvalidData,
"Unexpected netlink payload", format!("unexpected netlink payload: {:?}", nlmsg),
)), )),
} };
nlas.append(&mut message.payload.nlas);
Ok(nlas)
})?;
let device = Device::try_from(&nlas[..])?;
log::debug!("get_by_name: parsed wireguard device {} with {} peer(s)", device.name, device.peers.len());
Ok(device)
} }
pub fn delete_interface(iface: &InterfaceName) -> io::Result<()> { pub fn delete_interface(iface: &InterfaceName) -> io::Result<()> {