From 283109caca138b06c12c8cb11062e0098eb123d3 Mon Sep 17 00:00:00 2001 From: Egor Karavaev Date: Fri, 26 Jan 2018 22:26:01 +0300 Subject: [PATCH] Treat unspecified IPv4/IPv6 addresses as IpAddress::Unspecified in IpRepr::lower. Closes #127. --- src/wire/ip.rs | 135 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 91 insertions(+), 44 deletions(-) diff --git a/src/wire/ip.rs b/src/wire/ip.rs index 52d832ea..83982a32 100644 --- a/src/wire/ip.rs +++ b/src/wire/ip.rs @@ -494,6 +494,63 @@ impl Repr { } match self { + #[cfg(feature = "proto-ipv4")] + &Repr::Unspecified { + src_addr: src_addr @ Address::Unspecified, + dst_addr: Address::Ipv4(dst_addr), + protocol, payload_len, hop_limit + } | + &Repr::Unspecified { + src_addr: src_addr @ Address::Ipv4(_), + dst_addr: Address::Ipv4(dst_addr), + protocol, payload_len, hop_limit + } if src_addr.is_unspecified() => { + let mut src_addr = if let Address::Ipv4(src_ipv4_addr) = src_addr { + Some(src_ipv4_addr) + } else { + None + }; + for cidr in fallback_src_addrs { + if let Address::Ipv4(addr) = cidr.address() { + src_addr = Some(addr); + break; + } + } + Ok(Repr::Ipv4(Ipv4Repr { + src_addr: src_addr.ok_or(Error::Unaddressable)?, + dst_addr, protocol, payload_len, hop_limit + })) + } + + #[cfg(feature = "proto-ipv6")] + &Repr::Unspecified { + src_addr: src_addr @ Address::Unspecified, + dst_addr: Address::Ipv6(dst_addr), + protocol, payload_len, hop_limit + } | + &Repr::Unspecified { + src_addr: src_addr @ Address::Ipv6(_), + dst_addr: Address::Ipv6(dst_addr), + protocol, payload_len, hop_limit + } if src_addr.is_unspecified() => { + let mut src_addr = if let Address::Ipv6(src_ipv6_addr) = src_addr { + Some(src_ipv6_addr) + } else { + None + }; + for cidr in fallback_src_addrs { + if let Address::Ipv6(addr) = cidr.address() { + src_addr = Some(addr); + break; + } + } + Ok(Repr::Ipv6(Ipv6Repr { + src_addr: src_addr.ok_or(Error::Unaddressable)?, + next_header: protocol, + dst_addr, payload_len, hop_limit + })) + } + #[cfg(feature = "proto-ipv4")] &Repr::Unspecified { src_addr: Address::Ipv4(src_addr), @@ -523,50 +580,6 @@ impl Repr { })) } - #[cfg(feature = "proto-ipv4")] - &Repr::Unspecified { - src_addr: Address::Unspecified, - dst_addr: Address::Ipv4(dst_addr), - protocol, payload_len, hop_limit - } => { - let mut src_addr = None; - for cidr in fallback_src_addrs { - match cidr.address() { - Address::Ipv4(addr) => { - src_addr = Some(addr); - break - } - _ => () - } - } - Ok(Repr::Ipv4(Ipv4Repr { - src_addr: src_addr.ok_or(Error::Unaddressable)?, - dst_addr, protocol, payload_len, hop_limit - })) - } - - #[cfg(feature = "proto-ipv6")] - &Repr::Unspecified { - src_addr: Address::Unspecified, - dst_addr: Address::Ipv6(dst_addr), - protocol, payload_len, hop_limit - } => { - // Find a fallback address to use - match fallback_src_addrs.iter().filter_map(|cidr| match cidr.address() { - Address::Ipv6(addr) => Some(addr), - _ => None - }).next() { - Some(addr) => - Ok(Repr::Ipv6(Ipv6Repr { - src_addr: addr, - next_header: protocol, - hop_limit: hop_limit, - dst_addr, payload_len - })), - None => Err(Error::Unaddressable) - } - } - #[cfg(feature = "proto-ipv4")] &Repr::Ipv4(mut repr) => resolve_unspecified!(Repr::Ipv4, Address::Ipv4, repr, fallback_src_addrs), @@ -875,6 +888,40 @@ pub(crate) mod test { })) ); + assert_eq!( + Repr::Unspecified{ + src_addr: IpAddress::Ipv4(Ipv4Address::UNSPECIFIED), + dst_addr: IpAddress::Ipv4(ip_addr_b), + protocol: proto, + hop_limit: 64, + payload_len + }.lower(&[IpCidr::new(IpAddress::Ipv4(ip_addr_a), 24)]), + Ok(Repr::Ipv4(Ipv4Repr{ + src_addr: ip_addr_a, + dst_addr: ip_addr_b, + protocol: proto, + hop_limit: 64, + payload_len + })) + ); + + assert_eq!( + Repr::Unspecified{ + src_addr: IpAddress::Ipv4(Ipv4Address::UNSPECIFIED), + dst_addr: IpAddress::Ipv4(ip_addr_b), + protocol: proto, + hop_limit: 64, + payload_len + }.lower(&[]), + Ok(Repr::Ipv4(Ipv4Repr{ + src_addr: Ipv4Address::UNSPECIFIED, + dst_addr: ip_addr_b, + protocol: proto, + hop_limit: 64, + payload_len + })) + ); + assert_eq!( Repr::Ipv4(Ipv4Repr{ src_addr: ip_addr_a,