diff --git a/Cargo.toml b/Cargo.toml index d44bbf5..f165bd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,5 +35,7 @@ tokio = { version = "1.0.1", features = ["macros", "rt", "rt-multi-thread"] } async-std = { version = "1.9.0", features = ["attributes"]} macaddr = "1.0" -#[patch.crates-io] -#netlink-packet-route = { git = "https://github.com/rust-netlink/netlink-packet-route" } +[patch.crates-io] +netlink-packet-core = { git = "https://github.com/cathay4t/netlink-packet-core.git", branch = "main" } +netlink-packet-route = { git = "https://github.com/cathay4t/netlink-packet-route.git", branch = "panic_free" } +netlink-proto = { git = "https://github.com/cathay4t/netlink-proto.git", branch = "panic_free" } diff --git a/tests/panic_free_chain.rs b/tests/panic_free_chain.rs new file mode 100644 index 0000000..658762c --- /dev/null +++ b/tests/panic_free_chain.rs @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT + +//! End-to-end validation of the panic-free emission chain: +//! +//! netlink-packet-core -> netlink-packet-route -> netlink-proto -> rtnetlink + +use rtnetlink::{ + packet_core::{ + DefaultNla, EncodeErrorKind, NetlinkHeader, NetlinkMessage, + NetlinkPayload, NLA_MAX_VALUE_LEN, + }, + packet_route::{ + route::{RouteAttribute, RouteMessage}, + RouteNetlinkMessage, + }, + proto::{NetlinkCodec, NetlinkMessageCodec}, +}; + +#[test] +fn valid_route_message_round_trips_through_proto() { + let message = NetlinkMessage::new( + NetlinkHeader::default(), + NetlinkPayload::InnerMessage(RouteNetlinkMessage::NewRoute( + RouteMessage::default(), + )), + ); + + let mut buffer = Vec::new(); + NetlinkCodec::encode(message.clone(), &mut buffer).unwrap(); + assert!(!buffer.is_empty()); + + let mut expected_header = message.header; + expected_header.length = buffer.len() as u32; + expected_header.message_type = message.payload.message_type(); + let expected = + NetlinkMessage::new(expected_header, message.payload.clone()); + + let decoded = NetlinkCodec::decode::(&mut buffer) + .unwrap() + .unwrap(); + assert_eq!(decoded, expected); +} + +#[test] +fn oversized_route_attribute_returns_error_without_panic() { + let mut route = RouteMessage::default(); + route.attributes.push(RouteAttribute::Other(DefaultNla::new( + 1, + vec![0; NLA_MAX_VALUE_LEN + 1], + ))); + let message = NetlinkMessage::new( + NetlinkHeader::default(), + NetlinkPayload::InnerMessage(RouteNetlinkMessage::NewRoute(route)), + ); + + let mut buffer = vec![0xaa]; + let error = NetlinkCodec::encode(message, &mut buffer).unwrap_err(); + assert_eq!(error.kind(), EncodeErrorKind::TooLarge); + assert_eq!(buffer, vec![0xaa]); +}