Treat unspecified IPv4/IPv6 addresses as IpAddress::Unspecified in IpRepr::lower.

Closes #127.
v0.7.x
Egor Karavaev 2018-01-26 22:26:01 +03:00 committed by whitequark
parent 7778626788
commit 864b4b7996
1 changed files with 91 additions and 44 deletions

View File

@ -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,