Support a default route without a gateway (#628)

Adds the support for a default route without a gateway.

```
/ # ip route show default
default dev eth0 scope link 
```
This commit is contained in:
Dmitry Kovba authored and GitHub committed 2026-04-02 14:27:56 -07:00
1 parent 4040ce20c2
commit 11bbbbb852
6 files changed
+30 -14

No files matched your search

@@ -598,6 +598,9 @@ extension LinuxContainer {
try await agent.routeAddLink(name: name, dstIPv4Addr: ipv4Gateway, srcIPv4Addr: i.ipv4Address.address)
}
try await agent.routeAddDefault(name: name, ipv4Gateway: ipv4Gateway)
} else {
self.logger?.debug("no gateway for \(name)")
try await agent.routeAddDefault(name: name, ipv4Gateway: nil)
}
}
+3
View File
@@ -457,6 +457,9 @@ extension LinuxPod {
try await agent.routeAddLink(name: name, dstIPv4Addr: ipv4Gateway, srcIPv4Addr: nil)
}
try await agent.routeAddDefault(name: name, ipv4Gateway: ipv4Gateway)
} else {
self.logger?.debug("no gateway for \(name)")
try await agent.routeAddDefault(name: name, ipv4Gateway: nil)
}
}
@@ -69,7 +69,7 @@ public protocol VirtualMachineAgent: Sendable {
func down(name: String) async throws
func addressAdd(name: String, ipv4Address: CIDRv4) async throws
func routeAddLink(name: String, dstIPv4Addr: IPv4Address, srcIPv4Addr: IPv4Address?) async throws
func routeAddDefault(name: String, ipv4Gateway: IPv4Address) async throws
func routeAddDefault(name: String, ipv4Gateway: IPv4Address?) async throws
func configureDNS(config: DNS, location: String) async throws
func configureHosts(config: Hosts, location: String) async throws
+2 -2
View File
@@ -398,11 +398,11 @@ extension Vminitd {
}
/// Set the default route in the sandbox's environment.
public func routeAddDefault(name: String, ipv4Gateway: IPv4Address) async throws {
public func routeAddDefault(name: String, ipv4Gateway: IPv4Address?) async throws {
_ = try await client.ipRouteAddDefault(
.with {
$0.interface = name
$0.ipv4Gateway = ipv4Gateway.description
$0.ipv4Gateway = ipv4Gateway?.description ?? ""
})
}
@@ -348,14 +348,20 @@ public struct NetlinkSession {
/// Adds a default IPv4 route to an interface.
/// - Parameters:
/// - interface: The name of the interface.
/// - ipv4Gateway: The gateway address.
/// - ipv4Gateway: The gateway address, or nil.
public func routeAddDefault(
interface: String,
ipv4Gateway: IPv4Address
ipv4Gateway: IPv4Address?
) throws {
// ip route add default via [dst-address] src [src-address]
let dstAddrBytes = ipv4Gateway.bytes
let dstAddrAttrSize = RTAttribute.size + dstAddrBytes.count
// ip route add default via [gateway] dev [interface] or
// ip route add default dev [interface]
let dstAddrBytes = ipv4Gateway?.bytes
let dstAddrAttrSize: Int
if let dstAddrBytes {
dstAddrAttrSize = RTAttribute.size + dstAddrBytes.count
} else {
dstAddrAttrSize = 0
}
let interfaceAttrSize = RTAttribute.size + MemoryLayout<UInt32>.size
let interfaceIndex = try getInterfaceIndex(interface)
@@ -379,16 +385,20 @@ public struct NetlinkSession {
tos: 0,
table: RouteTable.MAIN,
proto: RouteProtocol.BOOT,
scope: RouteScope.UNIVERSE,
scope: ipv4Gateway != nil ? RouteScope.UNIVERSE : RouteScope.LINK,
type: RouteType.UNICAST,
flags: 0)
requestOffset = try requestInfo.appendBuffer(&requestBuffer, offset: requestOffset)
let dstAddrAttr = RTAttribute(len: UInt16(dstAddrAttrSize), type: RouteAttributeType.GATEWAY)
requestOffset = try dstAddrAttr.appendBuffer(&requestBuffer, offset: requestOffset)
guard var requestOffset = requestBuffer.copyIn(buffer: dstAddrBytes, offset: requestOffset) else {
throw BindError.sendMarshalFailure(type: "RTAttribute", field: "RTA_GATEWAY")
if let dstAddrBytes {
let dstAddrAttr = RTAttribute(len: UInt16(dstAddrAttrSize), type: RouteAttributeType.GATEWAY)
requestOffset = try dstAddrAttr.appendBuffer(&requestBuffer, offset: requestOffset)
guard let newOffset = requestBuffer.copyIn(buffer: dstAddrBytes, offset: requestOffset) else {
throw BindError.sendMarshalFailure(type: "RTAttribute", field: "RTA_GATEWAY")
}
requestOffset = newOffset
}
let interfaceAttr = RTAttribute(len: UInt16(interfaceAttrSize), type: RouteAttributeType.OIF)
requestOffset = try interfaceAttr.appendBuffer(&requestBuffer, offset: requestOffset)
guard
+1 -1
View File
@@ -1177,7 +1177,7 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid
do {
let socket = try DefaultNetlinkSocket()
let session = NetlinkSession(socket: socket, log: log)
let ipv4Gateway = try IPv4Address(request.ipv4Gateway)
let ipv4Gateway = !request.ipv4Gateway.isEmpty ? try IPv4Address(request.ipv4Gateway) : nil
try session.routeAddDefault(interface: request.interface, ipv4Gateway: ipv4Gateway)
} catch {
log.error(