//===----------------------------------------------------------------------===// // Copyright © 2026 Apple Inc. and the container project authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //===----------------------------------------------------------------------===// import ContainerizationError import ContainerizationExtras import DNSServer import Foundation import SystemPackage import Testing @testable import ContainerAPIClient struct PacketFilterTest { @Test func testRedirectRuleUpdate() async throws { let fm = FileManager.default let tempURL = try fm.url( for: .itemReplacementDirectory, in: .userDomainMask, appropriateFor: .temporaryDirectory, create: true ) let tempPath = FilePath(tempURL.path) defer { try? FileManager.default.removeItem(at: tempURL) } let configPath = tempPath.appending("pf.conf") let pf = PacketFilter(configPath: configPath, anchorsPath: tempPath) let from1 = try! IPAddress("203.0.113.113") let domain1 = try! DNSName("aaa.com") let to = try! IPAddress("127.0.0.1") try pf.createRedirectRule(from: from1, to: to, domain: domain1) let anchorPath = tempPath.appending("com.apple.container") var actualAnchorText = try String(contentsOfFile: anchorPath.string, encoding: .utf8) var expectedAnchorTest = """ rdr inet from any to \(from1) -> \(to) # \(domain1.pqdn)\n """ #expect(actualAnchorText == expectedAnchorTest) let from2 = try! IPAddress("172.31.72.1") let domain2 = try! DNSName("bbb.com") try pf.createRedirectRule(from: from2, to: to, domain: domain2) actualAnchorText = try String(contentsOfFile: anchorPath.string, encoding: .utf8) expectedAnchorTest += """ rdr inet from any to \(from2) -> \(to) # \(domain2.pqdn)\n """ #expect(actualAnchorText == expectedAnchorTest) let actualConfigText = try String(contentsOfFile: configPath.string, encoding: .utf8) let expectedConfigText = try Regex( #""" scrub-anchor "([^"]+)" nat-anchor "([^"]+)" rdr-anchor "([^"]+)" dummynet-anchor "([^"]+)" anchor "([^"]+)" load anchor "([^"]+)" from "[^"]+" """# ) #expect(actualConfigText.contains(expectedConfigText)) try pf.removeRedirectRule(from: from1, to: to, domain: domain1) try pf.removeRedirectRule(from: from2, to: to, domain: domain2) #expect(!fm.fileExists(atPath: anchorPath.string)) let configText = try String(contentsOfFile: configPath.string, encoding: .utf8) #expect(configText == "") } @Test func testPacketFilterReinitialize() async throws { let pf = PacketFilter() #expect(throws: ContainerizationError.self) { try pf.reinitialize() } } }