From 7d9dfb27eb112465b9f13991caef5949e59d0073 Mon Sep 17 00:00:00 2001 From: Kim Vandry Date: Thu, 28 Dec 2023 22:26:33 +0000 Subject: [PATCH] Handle more than one NetlinkMessage received in the same socket buffer. Without this, all but the first NetlinkMessage in each socket.recv_from_full() bufferfull is dropped, leading to overlooked interfaces, IP addresses, and other netlink objects. This used to be handled correctly but regressed in commit 15bde7f729d9dbce1a2bd0070ca219958aafd5db --- crates/erbium-net/src/netinfo.rs | 56 +++++++++++++++++--------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/crates/erbium-net/src/netinfo.rs b/crates/erbium-net/src/netinfo.rs index a2fb494..659aa21 100644 --- a/crates/erbium-net/src/netinfo.rs +++ b/crates/erbium-net/src/netinfo.rs @@ -465,33 +465,37 @@ impl NetLinkNetInfo { let mut state = State::ReadingLink; // we set the NLM_F_DUMP flag so we expect a multipart rx_packet in response. while let Ok((pkt, _)) = socket.recv_from_full().await { - let rx_packet = >::deserialize(&pkt).unwrap(); - - if NetLinkNetInfo::process_message(&sni, &rx_packet).await { - match state { - State::ReadingLink => { - trace!("Finished Link"); - NetLinkNetInfo::send_addrdump(&mut socket, &mut seq).await; - state = State::ReadingAddr - } - State::ReadingAddr => { - trace!("Finished Addr"); - NetLinkNetInfo::send_routedump(&mut socket, &mut seq, AF_INET as u8).await; - state = State::ReadingRoute4 - } - State::ReadingRoute4 => { - trace!("Finished Route4"); - NetLinkNetInfo::send_routedump(&mut socket, &mut seq, AF_INET6 as u8).await; - state = State::ReadingRoute6 - } - State::ReadingRoute6 => { - // Try and inform anyone listening that we have completed. - // But if it fails, don't worry, we'll send another one soonish. - trace!("Finished Route6"); - let _ = chan.try_send(()); - state = State::Done + let mut offset = 0; + while offset < pkt.len() { + let rx_packet = >::deserialize(&pkt[offset..]).unwrap(); + offset += rx_packet.header.length as usize; + + if NetLinkNetInfo::process_message(&sni, &rx_packet).await { + match state { + State::ReadingLink => { + trace!("Finished Link"); + NetLinkNetInfo::send_addrdump(&mut socket, &mut seq).await; + state = State::ReadingAddr + } + State::ReadingAddr => { + trace!("Finished Addr"); + NetLinkNetInfo::send_routedump(&mut socket, &mut seq, AF_INET as u8).await; + state = State::ReadingRoute4 + } + State::ReadingRoute4 => { + trace!("Finished Route4"); + NetLinkNetInfo::send_routedump(&mut socket, &mut seq, AF_INET6 as u8).await; + state = State::ReadingRoute6 + } + State::ReadingRoute6 => { + // Try and inform anyone listening that we have completed. + // But if it fails, don't worry, we'll send another one soonish. + trace!("Finished Route6"); + let _ = chan.try_send(()); + state = State::Done + } + State::Done => {} } - State::Done => {} } } }