diff --git a/Cargo.lock b/Cargo.lock index 59821e1..0817c1e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,7 +27,7 @@ checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" [[package]] name = "nat_emulation" -version = "0.1.0" +version = "0.0.2" dependencies = [ "rand", ] diff --git a/Cargo.toml b/Cargo.toml index d11f4fc..e645461 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nat_emulation" -version = "0.1.0" +version = "0.0.2" authors = ["Monica Moniot"] edition = "2021" diff --git a/src/nat.rs b/src/nat.rs index 9870f7d..bcf911f 100644 --- a/src/nat.rs +++ b/src/nat.rs @@ -55,7 +55,6 @@ pub struct Nat { external_addresses: [u32; M], map: [Vec; M], intranet: HashMap, - max_routing_table_len: usize, rng: R, assigned_external_ports: RangeInclusive, assigned_internal_addresses: RangeInclusive, @@ -151,9 +150,6 @@ impl Nat { external_addresses: external_addresses, map: std::array::from_fn(|_| Vec::new()), mapping_timeout, - // We need to make sure if port_parity is on the NAT does not crash from not being able - // to generate a unique port. - max_routing_table_len: external_dynamic_ports.len() * 2 / 5, rng, assigned_external_ports: external_dynamic_ports, assigned_internal_addresses: internal_addresses, @@ -281,7 +277,9 @@ impl Nat { // If we can't do any port preservation we have to randomly generate the port and address let mut random_addr; let mut random_port; + let mut attempt_until_force = 8; 'regen: loop { + attempt_until_force -= 1; random_addr = paired_addr_idx.unwrap_or_else(|| { if M == 1 { 0 @@ -294,9 +292,15 @@ impl Nat { // Force the port to have the same parity as the src_port. random_port = (random_port & !1u16) | (src_port & 1u16); } - for route in &self.map[random_addr] { - if route.external_port == random_port { - continue 'regen; + let routing_table = &mut self.map[random_addr]; + for i in 0..routing_table.len() { + if routing_table[i].external_port == random_port { + if attempt_until_force > 0 { + continue 'regen; + } + // Remove this mapping so our random port is unique. + routing_table.swap_remove(i); + break; } } break; @@ -353,8 +357,6 @@ impl Nat { let expiry = current_time - self.mapping_timeout; for address_idx in 0..self.external_addresses_len { let routing_table = &mut self.map[address_idx]; - let mut oldest_time = i64::MAX; - let mut oldest_idx = 0; let mut i = 0; while i < routing_table.len() { let route = &mut routing_table[i]; @@ -384,15 +386,8 @@ impl Nat { previous_mapping.replace((address_idx, Some(route_ex_port))); } } - if oldest_time >= route.last_used_time { - oldest_time = route.last_used_time; - oldest_idx = i; - } i += 1; } - if routing_table.len() >= self.max_routing_table_len { - routing_table.swap_remove(oldest_idx); - } } let (external_address_idx, external_port) = { // Attempt to reuse the previous mapping if we can.