diff --git a/Sources/Containerization/LinuxContainer.swift b/Sources/Containerization/LinuxContainer.swift index 75c774b4..4f6d7ea9 100644 --- a/Sources/Containerization/LinuxContainer.swift +++ b/Sources/Containerization/LinuxContainer.swift @@ -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) } } diff --git a/Sources/Containerization/LinuxPod.swift b/Sources/Containerization/LinuxPod.swift index 7574d697..1ad6efc5 100644 --- a/Sources/Containerization/LinuxPod.swift +++ b/Sources/Containerization/LinuxPod.swift @@ -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) } } diff --git a/Sources/Containerization/VirtualMachineAgent.swift b/Sources/Containerization/VirtualMachineAgent.swift index b1b0c406..d01089e2 100644 --- a/Sources/Containerization/VirtualMachineAgent.swift +++ b/Sources/Containerization/VirtualMachineAgent.swift @@ -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 diff --git a/Sources/Containerization/Vminitd.swift b/Sources/Containerization/Vminitd.swift index 363a2131..2d2cbdbe 100644 --- a/Sources/Containerization/Vminitd.swift +++ b/Sources/Containerization/Vminitd.swift @@ -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 ?? "" }) } diff --git a/Sources/ContainerizationNetlink/NetlinkSession.swift b/Sources/ContainerizationNetlink/NetlinkSession.swift index e10acb35..19478f0b 100644 --- a/Sources/ContainerizationNetlink/NetlinkSession.swift +++ b/Sources/ContainerizationNetlink/NetlinkSession.swift @@ -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.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 diff --git a/vminitd/Sources/vminitd/Server+GRPC.swift b/vminitd/Sources/vminitd/Server+GRPC.swift index 405ae42b..c651727c 100644 --- a/vminitd/Sources/vminitd/Server+GRPC.swift +++ b/vminitd/Sources/vminitd/Server+GRPC.swift @@ -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(