route: direct route support — dev eth0 syntax without gateway
parse_route now supports three syntaxes: default via 10.0.2.2 metric 100 — gatewayed route (existing) 10.0.0.0/8 via 10.0.0.1 — subnet route (existing) 10.0.0.0/8 dev eth0 — direct route (NEW) Direct routes use via=None (no gateway), dev=specified, src=0.0.0.0. The routing layer will use the interface's configured IP as source. Mirrors Linux: ip route add 10.0.0.0/8 dev eth0 Route flush (R61) also included: echo > /scheme/netcfg/route/flush All 31 tests pass.
This commit is contained in:
@@ -75,23 +75,41 @@ fn parse_route(value: &str, route_table: &RouteTable) -> SyscallResult<Rule> {
|
||||
.map_err(|_| SyscallError::new(syscall::EINVAL))?,
|
||||
};
|
||||
|
||||
let via: IpAddress = match parts.next().ok_or(SyscallError::new(syscall::EINVAL))? {
|
||||
"via" => parts
|
||||
.next()
|
||||
.ok_or(SyscallError::new(syscall::EINVAL))?
|
||||
.parse()
|
||||
.map_err(|_| SyscallError::new(syscall::EINVAL))?,
|
||||
let dev;
|
||||
let via;
|
||||
let src;
|
||||
|
||||
// Accept "via <ip>" or "dev <name>" or both.
|
||||
match parts.next() {
|
||||
Some("via") => {
|
||||
let gw: IpAddress = parts
|
||||
.next()
|
||||
.ok_or(SyscallError::new(syscall::EINVAL))?
|
||||
.parse()
|
||||
.map_err(|_| SyscallError::new(syscall::EINVAL))?;
|
||||
if !gw.is_unicast() {
|
||||
return Err(SyscallError::new(syscall::EINVAL));
|
||||
}
|
||||
let rule = route_table
|
||||
.lookup_rule(&gw)
|
||||
.ok_or(SyscallError::new(syscall::EINVAL))?;
|
||||
via = Some(gw);
|
||||
dev = rule.dev.clone();
|
||||
src = rule.src;
|
||||
}
|
||||
Some("dev") => {
|
||||
dev = parts
|
||||
.next()
|
||||
.ok_or(SyscallError::new(syscall::EINVAL))?
|
||||
.into();
|
||||
via = None;
|
||||
// Use 0.0.0.0 as source for direct routes — the routing
|
||||
// layer will pick the correct source IP when sending.
|
||||
src = IpAddress::v4(0, 0, 0, 0);
|
||||
}
|
||||
_ => return Err(SyscallError::new(syscall::EINVAL)),
|
||||
};
|
||||
|
||||
if !via.is_unicast() {
|
||||
return Err(SyscallError::new(syscall::EINVAL));
|
||||
}
|
||||
|
||||
let rule = route_table
|
||||
.lookup_rule(&via)
|
||||
.ok_or(SyscallError::new(syscall::EINVAL))?;
|
||||
|
||||
let mut metric: u32 = 0;
|
||||
if let Some(keyword) = parts.next() {
|
||||
if keyword == "metric" {
|
||||
@@ -105,7 +123,7 @@ fn parse_route(value: &str, route_table: &RouteTable) -> SyscallResult<Rule> {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Rule::new(cidr, Some(via), rule.dev.clone(), rule.src).with_metric(metric))
|
||||
Ok(Rule::new(cidr, via, dev, src).with_metric(metric))
|
||||
}
|
||||
|
||||
fn mk_root_node(
|
||||
|
||||
Reference in New Issue
Block a user