nat: add 6 unit tests for IP rewrite + table management
Tests cover: - rewrite_src_ipv4: source IP changes, dst unchanged - rewrite_dst_ipv4: destination IP changes, src unchanged - rewrite_short_packet_returns_false: <20 bytes returns false - rewrite_recomputes_checksum: checksum updates after rewrite - nat_table_add_assigns_unique_ids: each rule gets unique ID - nat_ephemeral_port_allocates_unique: ports are unique across calls Total tests across filter module: 15 (5 table + 4 conntrack + 6 nat) All passing.
This commit is contained in:
@@ -358,4 +358,97 @@ pub enum NatParseError {
|
||||
BadHook(String),
|
||||
BadAddress(String),
|
||||
BadPort(String),
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn make_ipv4_udp_packet(src: [u8; 4], dst: [u8; 4]) -> Vec<u8> {
|
||||
let mut p = vec![0u8; 28];
|
||||
p[0] = 0x45; p[1] = 0x00;
|
||||
p[2] = 0x00; p[3] = 0x1c;
|
||||
p[6] = 0x00; p[7] = 0x00;
|
||||
p[8] = 64;
|
||||
p[9] = 17;
|
||||
p[10] = 0x00; p[11] = 0x00;
|
||||
p[12..16].copy_from_slice(&src);
|
||||
p[16..20].copy_from_slice(&dst);
|
||||
p[20] = 0x12; p[21] = 0x34;
|
||||
p[22] = 0x56; p[23] = 0x78;
|
||||
p[24] = 0x00; p[25] = 0x08;
|
||||
p[26] = 0x00; p[27] = 0x00;
|
||||
p
|
||||
}
|
||||
|
||||
fn read_ipv4(p: &[u8], offset: usize) -> Ipv4Address {
|
||||
Ipv4Address::new(p[offset], p[offset+1], p[offset+2], p[offset+3])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rewrite_src_changes_source_address() {
|
||||
let mut p = make_ipv4_udp_packet([10, 0, 0, 1], [192, 168, 1, 1]);
|
||||
let new_src = Ipv4Address::new(192, 168, 99, 99);
|
||||
assert!(rewrite_src_ipv4(&mut p, new_src));
|
||||
assert_eq!(read_ipv4(&p, 12), new_src, "Source IP must be rewritten");
|
||||
assert_eq!(read_ipv4(&p, 16), Ipv4Address::new(192, 168, 1, 1),
|
||||
"Destination IP must be unchanged");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rewrite_dst_changes_destination_address() {
|
||||
let mut p = make_ipv4_udp_packet([10, 0, 0, 1], [192, 168, 1, 1]);
|
||||
let new_dst = Ipv4Address::new(8, 8, 8, 8);
|
||||
assert!(rewrite_dst_ipv4(&mut p, new_dst));
|
||||
assert_eq!(read_ipv4(&p, 16), new_dst);
|
||||
assert_eq!(read_ipv4(&p, 12), Ipv4Address::new(10, 0, 0, 1),
|
||||
"Source IP must be unchanged");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rewrite_short_packet_returns_false() {
|
||||
let mut p = vec![0u8; 10];
|
||||
assert!(!rewrite_src_ipv4(&mut p, Ipv4Address::new(1, 2, 3, 4)));
|
||||
assert!(!rewrite_dst_ipv4(&mut p, Ipv4Address::new(1, 2, 3, 4)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rewrite_recomputes_checksum_when_previously_nonzero() {
|
||||
let mut p = make_ipv4_udp_packet([10, 0, 0, 1], [192, 168, 1, 1]);
|
||||
// Compute a real checksum first
|
||||
if let Ok(mut ipv4) = smoltcp::wire::Ipv4Packet::new_checked(&mut p) {
|
||||
ipv4.fill_checksum();
|
||||
}
|
||||
let original_csum = u16::from_be_bytes([p[10], p[11]]);
|
||||
assert_ne!(original_csum, 0, "Pre-condition: checksum should be non-zero");
|
||||
let _ = rewrite_src_ipv4(&mut p, Ipv4Address::new(10, 0, 0, 2));
|
||||
let new_csum = u16::from_be_bytes([p[10], p[11]]);
|
||||
assert_ne!(new_csum, original_csum,
|
||||
"Checksum must be updated after source rewrite");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nat_table_add_assigns_unique_ids() {
|
||||
let mut t = NatTable::new();
|
||||
let make_rule = || NatRule {
|
||||
id: 0,
|
||||
nat_type: NatType::Snat,
|
||||
hook: Hook::OutputLocal,
|
||||
src_match: None,
|
||||
dst_match: None,
|
||||
trans_addr: IpAddress::v4(192, 168, 1, 100),
|
||||
trans_port: None,
|
||||
match_count: 0,
|
||||
};
|
||||
let id1 = t.add(make_rule());
|
||||
let id2 = t.add(make_rule());
|
||||
assert_ne!(id1, id2, "Each rule gets a unique ID");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nat_ephemeral_port_allocates_unique() {
|
||||
let mut t = NatTable::new();
|
||||
let p1 = t.alloc_ephemeral_port();
|
||||
let p2 = t.alloc_ephemeral_port();
|
||||
assert_ne!(p1, p2, "Ephemeral ports must be unique across calls");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user