Skip to content

Failure to deserialize a new neighbor notification. #300

@dvaembit

Description

@dvaembit

Version of neli

Both 0.7.1 and commit dbacf64

Describe the bug

Failure to deserialize a new neighbor notification.

To Reproduce

Steps to reproduce the behavior:

  1. Run this program as root:
use std::error::Error;

use neli::consts::socket::NlFamily;
use neli::router::synchronous::NlRouter;
use neli::utils::Groups;

const RTMGRP_NOTIFY: u32 = 2;
const RTMGRP_NEIGH: u32 = 4;

fn main() -> Result<(), Box<dyn Error>> {
    simple_logger::SimpleLogger::new()
        .env()
        .init()
        .expect("Failure to initialize simpler_logger");

    let nl_rte_groups = Groups::new_bitmask(RTMGRP_NEIGH | RTMGRP_NOTIFY);
    let (nl_rte_router, nl_recv_handle) =
        NlRouter::connect(NlFamily::Route, None, nl_rte_groups)
            .map_err(|e| format!("Failed to connect to netlink: {e}"))?;

    nl_rte_router.enable_strict_checking(false)?;
    println!("Waiting for netlink notifications.");

    for maybe_msghdr in nl_recv_handle {
        match maybe_msghdr {
            Err(e) => eprintln!("Failed to receive netlink message header: {e}"),
            Ok(msghdr) => println!("{:?}", msghdr),
        };
    }

    Ok(())
}
  1. Run this command:
sudo ip neigh add 192.168.148.181 lladdr ca:bd:31:de:dc:c7 dev wlp4s0
  1. Observe deserialization error:
2025-10-06T22:15:30.831Z TRACE [neli::utils::synchronous] Semaphore acquired; current count is 1, available is 2
2025-10-06T22:15:32.962Z TRACE [neli::socket::synchronous] Buffer received: [76, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 68, 0, 16, 0, 2, 0, 0, 0, 3, 0, 0, 0, 128, 0, 0, 1, 8, 0, 1, 0, 192, 168, 148, 181, 10, 0, 2, 0, 202, 189, 49, 222, 220, 199, 0, 0, 8, 0, 4, 0, 0, 0, 0, 0, 20, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
2025-10-06T22:15:32.962Z TRACE [neli::nl] Deserializing data type Nlmsghdr
2025-10-06T22:15:32.962Z TRACE [neli::nl] Deserializing field type u32
2025-10-06T22:15:32.962Z TRACE [neli::nl] Buffer to be deserialized: [76, 0, 0, 0]
2025-10-06T22:15:32.962Z TRACE [neli::nl] Field deserialized: 76
2025-10-06T22:15:32.962Z TRACE [neli::nl] Deserializing field type u16
2025-10-06T22:15:32.962Z TRACE [neli::nl] Buffer to be deserialized: [28, 0]
2025-10-06T22:15:32.962Z TRACE [neli::nl] Field deserialized: 28
2025-10-06T22:15:32.962Z TRACE [neli::nl] Deserializing field type neli::consts::nl::NlmF
2025-10-06T22:15:32.962Z TRACE [neli::nl] Buffer to be deserialized: [0, 0]
2025-10-06T22:15:32.962Z TRACE [neli::consts::nl] Deserializing data type NlmF
2025-10-06T22:15:32.962Z TRACE [neli::consts::nl] Deserializing field type u16
2025-10-06T22:15:32.962Z TRACE [neli::consts::nl] Buffer to be deserialized: [0, 0]
2025-10-06T22:15:32.962Z TRACE [neli::consts::nl] Field deserialized: 0
2025-10-06T22:15:32.962Z TRACE [neli::nl] Field deserialized: NlmF(0)
2025-10-06T22:15:32.962Z TRACE [neli::nl] Deserializing field type u32
2025-10-06T22:15:32.962Z TRACE [neli::nl] Buffer to be deserialized: [0, 0, 0, 0]
2025-10-06T22:15:32.962Z TRACE [neli::nl] Field deserialized: 0
2025-10-06T22:15:32.962Z TRACE [neli::nl] Deserializing field type u32
2025-10-06T22:15:32.962Z TRACE [neli::nl] Buffer to be deserialized: [68, 0, 16, 0]
2025-10-06T22:15:32.962Z TRACE [neli::nl] Field deserialized: 1048644
2025-10-06T22:15:32.962Z TRACE [neli::nl] Deserializing field type neli::nl::NlPayload<u16, neli::types::Buffer>
2025-10-06T22:15:32.962Z TRACE [neli::nl] Buffer to be deserialized: [2, 0, 0, 0, 3, 0, 0, 0, 128, 0, 0, 1, 8, 0, 1, 0, 192, 168, 148, 181, 10, 0, 2, 0, 202, 189, 49, 222, 220, 199, 0, 0, 8, 0, 4, 0, 0, 0, 0, 0, 20, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
2025-10-06T22:15:32.962Z TRACE [neli::nl] Deserializing data type neli::nl::NlPayload<u16, neli::types::Buffer>
2025-10-06T22:15:32.962Z TRACE [neli::nl] Field deserialized: Payload(Buffer)
2025-10-06T22:15:32.962Z TRACE [neli::iter] Message received: Nlmsghdr { nl_len: 76, nl_type: 28, nl_flags: NlmF(0), nl_seq: 0, nl_pid: 1048644, nl_payload: Payload(Buffer) }
2025-10-06T22:15:32.962Z TRACE [neli::router::synchronous] Message received: Ok(Nlmsghdr { nl_len: 76, nl_type: 28, nl_flags: NlmF(0), nl_seq: 0, nl_pid: 1048644, nl_payload: Payload(Buffer) })
2025-10-06T22:15:32.962Z TRACE [neli::genl] Deserializing data type Genlmsghdr
2025-10-06T22:15:32.962Z TRACE [neli::genl] Deserializing field type u8
2025-10-06T22:15:32.962Z TRACE [neli::genl] Buffer to be deserialized: [2]
2025-10-06T22:15:32.962Z TRACE [neli::genl] Field deserialized: 2
2025-10-06T22:15:32.962Z TRACE [neli::genl] Deserializing field type u8
2025-10-06T22:15:32.962Z TRACE [neli::genl] Buffer to be deserialized: [0]
2025-10-06T22:15:32.962Z TRACE [neli::genl] Field deserialized: 0
2025-10-06T22:15:32.962Z TRACE [neli::genl] Deserializing field type u16
2025-10-06T22:15:32.963Z TRACE [neli::genl] Buffer to be deserialized: [0, 0]
2025-10-06T22:15:32.963Z TRACE [neli::genl] Field deserialized: 0
2025-10-06T22:15:32.963Z TRACE [neli::genl] Deserializing field type neli::genl::NoUserHeader
2025-10-06T22:15:32.963Z TRACE [neli::genl] Buffer to be deserialized: []
2025-10-06T22:15:32.963Z TRACE [neli::genl] Field deserialized: NoUserHeader
2025-10-06T22:15:32.963Z TRACE [neli::genl] Deserializing field type neli::types::GenlBuffer<u16, neli::types::Buffer>
2025-10-06T22:15:32.963Z TRACE [neli::genl] Buffer to be deserialized: [3, 0, 0, 0, 128, 0, 0, 1, 8, 0, 1, 0, 192, 168, 148, 181, 10, 0, 2, 0, 202, 189, 49, 222, 220, 199, 0, 0, 8, 0, 4, 0, 0, 0, 0, 0, 20, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
2025-10-06T22:15:32.963Z TRACE [neli::types] Deserializing data type GenlBuffer
2025-10-06T22:15:32.963Z TRACE [neli::types] Deserializing field type alloc::vec::Vec<neli::genl::Nlattr<u16, neli::types::Buffer>>
2025-10-06T22:15:32.963Z TRACE [neli::types] Buffer to be deserialized: [3, 0, 0, 0, 128, 0, 0, 1, 8, 0, 1, 0, 192, 168, 148, 181, 10, 0, 2, 0, 202, 189, 49, 222, 220, 199, 0, 0, 8, 0, 4, 0, 0, 0, 0, 0, 20, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
2025-10-06T22:15:32.963Z TRACE [neli::genl] Deserializing data type Nlattr
2025-10-06T22:15:32.963Z TRACE [neli::genl] Deserializing field type u16
2025-10-06T22:15:32.963Z TRACE [neli::genl] Buffer to be deserialized: [3, 0]
2025-10-06T22:15:32.963Z TRACE [neli::genl] Field deserialized: 3
2025-10-06T22:15:32.963Z TRACE [neli::genl] Deserializing field type neli::genl::AttrType<u16>
2025-10-06T22:15:32.963Z TRACE [neli::genl] Buffer to be deserialized: [0, 0]
2025-10-06T22:15:32.963Z TRACE [neli::genl] Field deserialized: AttrType { nla_nested: false, nla_network_order: false, nla_type: 0 }
Failed to receive netlink message header: Deserialization failed: Invalid input was provided: 3

Please provide a minimal, ready-to-compile example that reproduces the bug
See above.

Expected behavior

  1. I expect this message to deserialize okay since it was authored by the kernel.
  2. I also expect the NlRouterReceiveHandle to be able to continue receiving additional messages. In other words, I am surprised this is considered a fatal error.

Additional context

Test on kernel: 6.16.7+deb14-amd64
Compiled with rust 1.89.0

I used an nlmon device to capture netlink traffix while running a similar ip neigh add command. Based on the wireshark decoding of those packets, I believe the 3 in the neli trace is supposed to be the interface index:

Image

Metadata

Metadata

Assignees

Labels

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions