Skip to content

Commit 6ba23e7

Browse files
[fix] minor: make ssm validation consistent with Omicron expectations (#132)
1 parent 40f9237 commit 6ba23e7

File tree

1 file changed

+21
-6
lines changed

1 file changed

+21
-6
lines changed

dpd/src/mcast/validate.rs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ fn validate_ipv4_multicast(
9595
}
9696
// If sources are defined for an SSM address, it's valid
9797
return Ok(());
98-
} else if sources.is_some() {
98+
} else if sources.is_some() && !sources.unwrap().is_empty() {
9999
// If this is not SSM but sources are defined, it's invalid
100100
return Err(DpdError::Invalid(format!(
101101
"{addr} is not a Source-Specific Multicast address but sources were provided",
@@ -158,7 +158,7 @@ fn validate_ipv6_multicast(
158158
}
159159
// If sources are defined for an IPv6 SSM address, it's valid
160160
return Ok(());
161-
} else if sources.is_some() {
161+
} else if sources.is_some() && !sources.unwrap().is_empty() {
162162
// If this is not SSM but sources are defined, it's invalid
163163
return Err(DpdError::Invalid(format!(
164164
"{addr} is not a Source-Specific Multicast address but sources were provided",
@@ -237,21 +237,28 @@ fn validate_exact_source_address(ip: IpAddr) -> DpdResult<()> {
237237

238238
/// Validates IPv4 source addresses for problematic types.
239239
fn validate_ipv4_source_address(ipv4: Ipv4Addr) -> DpdResult<()> {
240-
if ipv4.is_loopback() || ipv4.is_broadcast() || ipv4.is_unspecified() {
240+
if ipv4.is_loopback()
241+
|| ipv4.is_broadcast()
242+
|| ipv4.is_unspecified()
243+
|| ipv4.is_link_local()
244+
{
241245
return Err(DpdError::Invalid(format!(
242246
"Source IP {ipv4} is not a valid source address \
243-
(loopback, broadcast, and unspecified addresses are not allowed)",
247+
(loopback, broadcast, unspecified, and link-local addresses are not allowed)",
244248
)));
245249
}
246250
Ok(())
247251
}
248252

249253
/// Validates IPv6 source addresses for problematic types.
250254
fn validate_ipv6_source_address(ipv6: Ipv6Addr) -> DpdResult<()> {
251-
if ipv6.is_loopback() || ipv6.is_unspecified() {
255+
if ipv6.is_loopback()
256+
|| ipv6.is_unspecified()
257+
|| ((ipv6.segments()[0] & 0xffc0) == 0xfe80)
258+
{
252259
return Err(DpdError::Invalid(format!(
253260
"Source IP {ipv6} is not a valid source address \
254-
(loopback and unspecified addresses are not allowed)",
261+
(loopback, unspecified, and link-local addresses are not allowed)",
255262
)));
256263
}
257264
Ok(())
@@ -389,6 +396,10 @@ mod tests {
389396
.is_err());
390397
assert!(validate_ipv4_multicast(non_ssm_addr, Some(&mixed_sources))
391398
.is_err());
399+
400+
// Non-SSM address without sources - should pass
401+
assert!(validate_ipv4_multicast(non_ssm_addr, None).is_ok());
402+
assert!(validate_ipv4_multicast(non_ssm_addr, Some(&[])).is_ok());
392403
}
393404

394405
#[test]
@@ -411,6 +422,10 @@ mod tests {
411422
// Non-SSM address with IPv6 source - should fail
412423
assert!(validate_ipv6_multicast(non_ssm_global, Some(&ip6_sources))
413424
.is_err());
425+
426+
// Non-SSM address without sources - should pass
427+
assert!(validate_ipv6_multicast(non_ssm_global, None).is_ok());
428+
assert!(validate_ipv6_multicast(non_ssm_global, Some(&[])).is_ok());
414429
}
415430

416431
#[test]

0 commit comments

Comments
 (0)