Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions Sources/ContainerResource/Network/Attachment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ public struct Attachment: Codable, Sendable {
/// The CIDR address describing the interface IPv4 address, with the prefix length of the subnet.
public let ipv4Address: CIDRv4
/// The IPv4 gateway address.
public let ipv4Gateway: IPv4Address
/// The CIDR address describing the interface IPv6 address, with the prefix length of the subnet.
public let ipv4Gateway: IPv4Address? /// The CIDR address describing the interface IPv6 address, with the prefix length of the subnet.
/// The address is nil if the IPv6 subnet could not be determined at network creation time.
public let ipv6Address: CIDRv6?
/// The MAC address associated with the attachment (optional).
Expand All @@ -40,7 +39,7 @@ public struct Attachment: Codable, Sendable {
network: String,
hostname: String,
ipv4Address: CIDRv4,
ipv4Gateway: IPv4Address,
ipv4Gateway: IPv4Address?,
ipv6Address: CIDRv6?,
macAddress: MACAddress?,
mtu: UInt32? = nil,
Expand Down
4 changes: 2 additions & 2 deletions Sources/ContainerResource/Network/NetworkStatus.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ public struct NetworkStatus: Codable, Sendable {
public let ipv4Subnet: CIDRv4

/// The IPv4 gateway address.
public let ipv4Gateway: IPv4Address
public let ipv4Gateway: IPv4Address?

/// The IPv6 subnet assigned to the network, if IPv6 is enabled.
public let ipv6Subnet: CIDRv6?

public init(
ipv4Subnet: CIDRv4,
ipv4Gateway: IPv4Address,
ipv4Gateway: IPv4Address?,
ipv6Subnet: CIDRv6?
) {
self.ipv4Subnet = ipv4Subnet
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public final class ReservedVmnetNetwork: ContainerNetworkServer.Network {
private struct NetworkInfo {
let network: vmnet_network_ref
let ipv4Subnet: CIDRv4
let ipv4Gateway: IPv4Address
let ipv4Gateway: IPv4Address?
let ipv6Subnet: CIDRv6
}

Expand Down Expand Up @@ -168,7 +168,7 @@ public final class ReservedVmnetNetwork: ContainerNetworkServer.Network {
let lower = IPv4Address(subnetValue & maskValue)
let upper = IPv4Address(lower.value + ~maskValue)
let runningSubnet = try CIDRv4(lower: lower, upper: upper)
let runningGateway = IPv4Address(runningSubnet.lower.value + 1)
let runningGateway: IPv4Address? = configuration.mode == .hostOnly ? nil : IPv4Address(runningSubnet.lower.value + 1)

var prefixAddr = in6_addr()
var prefixLength = UInt8(0)
Expand Down
4 changes: 3 additions & 1 deletion Sources/Services/RuntimeLinux/Server/RuntimeService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1149,7 +1149,9 @@ public actor RuntimeService {

private nonisolated func getDefaultNameservers(from attachments: [Attachment]) -> [String] {
for attachment in attachments {
return [attachment.ipv4Gateway.description]
if let gateway = attachment.ipv4Gateway {
return [gateway.description]
}
}
return []
}
Expand Down
14 changes: 6 additions & 8 deletions Tests/IntegrationTests/Network/TestCLINetwork.swift
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,7 @@ struct TestCLINetwork {
}

@available(macOS 26, *)
@Test func testIsolatedNetwork() async {
await withKnownIssue("curl error 7 despite retries", isIntermittent: true) {
@Test func testIsolatedNetwork() async throws {
try await ContainerFixture.with { f in
let net = "\(f.testID)-net"
let server = "\(f.testID)-server"
Expand Down Expand Up @@ -163,15 +162,15 @@ struct TestCLINetwork {
return result.status == 0
}

// External connection should be blocked — the isolated network has no gateway.
// Reaching a literal IP proves egress is open regardless of DNS state.
let externalResult = try f.run([
"run", "--rm", "--network", net, curlImage,
"curl", "--connect-timeout", "5", "http://google.com",
"curl", "-sSk", "--connect-timeout", "5", "https://1.1.1.1/",
])
let hostOnlyBlockedCodes: Set<Int32> = [6, 7, 28]
#expect(
hostOnlyBlockedCodes.contains(externalResult.status),
"external connection from isolated network should be blocked, got exit \(externalResult.status)")
externalResult.status != 0,
"hostOnly network must not reach external IPs. curl exited with \(externalResult.status)"
)
}
}
}
Expand Down Expand Up @@ -210,4 +209,3 @@ struct TestCLINetwork {
#expect(result.error.contains("network not found"))
}
}
}