review: parse_port rejects ranges, document IPv6 ext header limit

parse_port now rejects port ranges ('1024:65535') with a clear
error message instead of silently using only the first number.
FilterRule uses a single u16 field and cannot represent ranges.

infer_context now documents the hardcoded 40-byte IPv6 header
limitation: smoltcp's next_header() chases extension headers to
return the final protocol, but the transport offset is not
computed. Port extraction silently returns None/None for packets
with extension headers, which is safe but means port-based
filter rules won't match for such packets.
This commit is contained in:
Red Bear OS
2026-07-09 00:52:14 +03:00
parent 3101345fe6
commit 0f5a4f59f4
2 changed files with 17 additions and 2 deletions
+9 -2
View File
@@ -410,8 +410,15 @@ fn parse_protocol(value: &str) -> core::result::Result<Protocol, ParseError> {
}
fn parse_port(value: &str) -> core::result::Result<u16, ParseError> {
let port_str = value.split(':').next().unwrap_or(value);
port_str
// Accept single port (e.g. "80") but reject port ranges (e.g.
// "1024:65535"). The FilterRule struct uses a single u16 field
// and does not support ranges. Silently accepting the first
// number would make --sport 1024:65535 match only port 1024,
// which is both wrong and misleading.
if value.contains(':') {
return Err(ParseError::Msg("port ranges not supported (use a single port number)"));
}
value
.parse::<u16>()
.map_err(|_| ParseError::BadPort(value.to_string()))
}
+8
View File
@@ -515,6 +515,14 @@ fn infer_context(
if let Ok(ipv6) = Ipv6Packet::new_checked(packet) {
let nh = ipv6.next_header();
let payload_start = 40; // fixed IPv6 header
// Extension headers (Hop-by-Hop, Routing, Fragment, etc.)
// would shift the transport header to a higher offset.
// smoltcp's next_header() chases extension headers to return
// the final protocol, but we don't compute the actual
// transport offset. For packets with extension headers the
// port extraction below will read the wrong bytes and return
// None/None, which is safe: the filter matches on IP+protocol
// but silently skips port matching.
let payload = if packet.len() > payload_start {
&packet[payload_start..]
} else {