Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/edda

crates/appliance-pid1/tests/netlink_framing_public.rs

//! **The netlink framing is public** (lane G6): Gunnar's dashboard probe dumps
//! `RTM_GETADDR` over the same `NETLINK_ROUTE` family edda's `net` writes with, and kept
//! a 40-line copy of the framing because edda's was crate-private. These are its tests
//! (gunnar-server `dashboard::probe`, 7e33c0f7), run against edda's own helpers from
//! outside the crate.
#![cfg(feature = "net")]

use appliance_pid1::net::{align4, netlink_message, netlink_socket, rtattr};

const RTM_GETADDR: u16 = 22;
const RTM_NEWADDR: u16 = 20;
const NLM_F_REQUEST: u16 = 0x0001;
const NLM_F_DUMP: u16 = 0x0300;
const NLM_F_MULTI: u16 = 0x0002;
const IFA_ADDRESS: u16 = 1;
const IFA_LABEL: u16 = 3;

/// Gunnar's `the_dump_request_is_a_request_plus_dump_over_an_empty_ifaddrmsg`.
#[test]
fn the_dump_request_is_a_request_plus_dump_over_an_empty_ifaddrmsg() {
    let m = netlink_message(RTM_GETADDR, NLM_F_REQUEST | NLM_F_DUMP, 7, &[0u8; 8]);
    assert_eq!(m.len(), 24);
    assert_eq!(u32::from_ne_bytes([m[0], m[1], m[2], m[3]]), 24, "nlmsg_len counts the header and the body");
    assert_eq!(u16::from_ne_bytes([m[4], m[5]]), RTM_GETADDR);
    assert_eq!(u16::from_ne_bytes([m[6], m[7]]), NLM_F_REQUEST | NLM_F_DUMP);
    assert_eq!(u32::from_ne_bytes([m[8], m[9], m[10], m[11]]), 7, "the sequence number");
    assert_eq!(&m[16..], &[0u8; 8]);
}

/// Gunnar's `newaddr` fixture: an `RTM_NEWADDR` with `IFA_ADDRESS` and a padded
/// `IFA_LABEL`; `rta_len` counts the header and the payload, never the padding.
#[test]
fn an_attribute_counts_its_payload_and_is_padded_to_four() {
    let label = rtattr(IFA_LABEL, b"eth0\0");
    assert_eq!(label.len(), 12, "4 + 5 bytes, padded to 12");
    assert_eq!(u16::from_ne_bytes([label[0], label[1]]), 9, "rta_len is 4 + 5, not the padded 12");
    assert_eq!(u16::from_ne_bytes([label[2], label[3]]), IFA_LABEL);
    let mut body = vec![2u8, 24, 0, 0];
    body.extend_from_slice(&2u32.to_ne_bytes());
    body.extend_from_slice(&rtattr(IFA_ADDRESS, &[10, 0, 2, 15]));
    body.extend_from_slice(&label);
    let m = netlink_message(RTM_NEWADDR, NLM_F_MULTI, 1, &body);
    assert_eq!(m.len(), align4(16 + body.len()));
    assert_eq!((align4(0), align4(1), align4(4), align4(5)), (0, 4, 4, 8));
}

/// The socket the probe dumps over: `AF_NETLINK`/`NETLINK_ROUTE`, auto-bound on first send.
#[test]
fn the_route_socket_opens() {
    let _sock: rustix::fd::OwnedFd = netlink_socket().expect("an AF_NETLINK socket opens for any user");
}