@@ -18,18 +18,19 @@ import ContainerizationError
1818import ContainerizationExtras
1919import DNSServer
2020import Foundation
21+ import SystemPackage
2122
2223public struct PacketFilter {
2324 public static let anchor = " com.apple.container "
24- public static let defaultConfigPath = URL ( filePath : " /etc/pf.conf " )
25- public static let defaultAnchorsPath = URL ( filePath : " /etc/pf.anchors " )
25+ public static let defaultConfigPath = FilePath ( " /etc/pf.conf " )
26+ public static let defaultAnchorsPath = FilePath ( " /etc/pf.anchors " )
2627
27- private let configURL : URL
28- private let anchorsURL : URL
28+ private let configPath : FilePath
29+ private let anchorsPath : FilePath
2930
30- public init ( configURL : URL = Self . defaultConfigPath, anchorsURL : URL = Self . defaultAnchorsPath) {
31- self . configURL = configURL
32- self . anchorsURL = anchorsURL
31+ public init ( configPath : FilePath = Self . defaultConfigPath, anchorsPath : FilePath = Self . defaultAnchorsPath) {
32+ self . configPath = configPath
33+ self . anchorsPath = anchorsPath
3334 }
3435
3536 public func createRedirectRule( from: IPAddress , to: IPAddress , domain: DNSName ) throws {
@@ -39,7 +40,7 @@ public struct PacketFilter {
3940
4041 let fm : FileManager = FileManager . default
4142
42- let anchorURL = self . anchorsURL . appending ( path : Self . anchor)
43+ let anchorPath = self . anchorsPath . appending ( Self . anchor)
4344
4445 let inet : String
4546 switch from {
@@ -49,8 +50,8 @@ public struct PacketFilter {
4950 let redirectRule = " rdr \( inet) from any to \( from. description) -> \( to. description) # \( domain. pqdn) "
5051
5152 var content = " "
52- if fm. fileExists ( atPath: anchorURL . path ) {
53- content = try String ( contentsOfFile: anchorURL . path , encoding: . utf8)
53+ if fm. fileExists ( atPath: anchorPath . string ) {
54+ content = try String ( contentsOfFile: anchorPath . string , encoding: . utf8)
5455 } else {
5556 try addAnchorToConfig ( )
5657 }
@@ -60,7 +61,7 @@ public struct PacketFilter {
6061 lines. insert ( redirectRule, at: lines. endIndex - 1 )
6162 }
6263
63- try lines. joined ( separator: " \n " ) . write ( toFile: anchorURL . path , atomically: true , encoding: . utf8)
64+ try lines. joined ( separator: " \n " ) . write ( toFile: anchorPath . string , atomically: true , encoding: . utf8)
6465 }
6566
6667 public func removeRedirectRule( from: IPAddress , to: IPAddress , domain: DNSName ) throws {
@@ -70,7 +71,7 @@ public struct PacketFilter {
7071
7172 let fm : FileManager = FileManager . default
7273
73- let anchorURL = self . anchorsURL . appending ( path : Self . anchor)
74+ let anchorPath = self . anchorsPath . appending ( Self . anchor)
7475
7576 let inet : String
7677 switch from {
@@ -79,40 +80,40 @@ public struct PacketFilter {
7980 }
8081 let redirectRule = " rdr \( inet) from any to \( from. description) -> \( to. description) # \( domain. pqdn) "
8182
82- guard fm. fileExists ( atPath: anchorURL . path ) else {
83+ guard fm. fileExists ( atPath: anchorPath . string ) else {
8384 return
8485 }
8586
86- let content = try String ( contentsOfFile: anchorURL . path , encoding: . utf8)
87+ let content = try String ( contentsOfFile: anchorPath . string , encoding: . utf8)
8788 let lines = content. components ( separatedBy: . newlines)
8889
8990 let removedLines = lines. filter { l in
9091 l != redirectRule
9192 }
9293
9394 if removedLines == [ " " ] {
94- try fm. removeItem ( atPath: anchorURL . path )
95+ try fm. removeItem ( atPath: anchorPath . string )
9596 try removeAnchorFromConfig ( )
9697 } else {
97- try removedLines. joined ( separator: " \n " ) . write ( toFile: anchorURL . path , atomically: true , encoding: . utf8)
98+ try removedLines. joined ( separator: " \n " ) . write ( toFile: anchorPath . string , atomically: true , encoding: . utf8)
9899 }
99100 }
100101
101102 private func addAnchorToConfig( ) throws {
102103 let fm : FileManager = FileManager . default
103104
104- let anchorURL = self . anchorsURL . appending ( path : Self . anchor)
105+ let anchorPath = self . anchorsPath . appending ( Self . anchor)
105106
106107 /* PF requires strict ordering of anchors:
107108 scrub-anchor, nat-anchor, rdr-anchor, dummynet-anchor, anchor, load anchor
108109 */
109110 let anchorKeywords = [ " scrub-anchor " , " nat-anchor " , " rdr-anchor " , " dummynet-anchor " , " anchor " , " load anchor " ]
110- let loadAnchorText = " load anchor \" \( Self . anchor) \" from \" \( anchorURL . path ) \" "
111+ let loadAnchorText = " load anchor \" \( Self . anchor) \" from \" \( anchorPath . string ) \" "
111112
112113 var content : String = " "
113114 var lines : [ String ] = [ ]
114- if fm. fileExists ( atPath: self . configURL . path ) {
115- content = try String ( contentsOfFile: self . configURL . path , encoding: . utf8)
115+ if fm. fileExists ( atPath: self . configPath . string ) {
116+ content = try String ( contentsOfFile: self . configPath . string , encoding: . utf8)
116117 }
117118 lines = content. components ( separatedBy: . newlines)
118119
@@ -134,28 +135,28 @@ public struct PacketFilter {
134135 }
135136
136137 do {
137- try lines. joined ( separator: " \n " ) . write ( toFile: self . configURL . path , atomically: true , encoding: . utf8)
138+ try lines. joined ( separator: " \n " ) . write ( toFile: self . configPath . string , atomically: true , encoding: . utf8)
138139 } catch {
139- throw ContainerizationError ( . invalidState, message: " failed to write \" \( self . configURL . path ) \" " )
140+ throw ContainerizationError ( . invalidState, message: " failed to write \" \( self . configPath . string ) \" " )
140141 }
141142 }
142143
143144 private func removeAnchorFromConfig( ) throws {
144145 let fm : FileManager = FileManager . default
145146
146- guard fm. fileExists ( atPath: configURL . path ) else {
147+ guard fm. fileExists ( atPath: configPath . string ) else {
147148 return
148149 }
149150
150- let content = try String ( contentsOfFile: configURL . path , encoding: . utf8)
151+ let content = try String ( contentsOfFile: configPath . string , encoding: . utf8)
151152 let lines = content. components ( separatedBy: . newlines)
152153
153154 let removedLines = lines. filter { l in !l. contains ( Self . anchor) }
154155
155156 do {
156- try removedLines. joined ( separator: " \n " ) . write ( toFile: configURL . path , atomically: true , encoding: . utf8)
157+ try removedLines. joined ( separator: " \n " ) . write ( toFile: configPath . string , atomically: true , encoding: . utf8)
157158 } catch {
158- throw ContainerizationError ( . invalidState, message: " failed to write \" \( configURL . path ) \" " )
159+ throw ContainerizationError ( . invalidState, message: " failed to write \" \( configPath . string ) \" " )
159160 }
160161 }
161162
@@ -165,7 +166,7 @@ public struct PacketFilter {
165166 let checkProcess = Foundation . Process ( )
166167 var checkStatus : Int32
167168 checkProcess. executableURL = URL ( fileURLWithPath: " /sbin/pfctl " )
168- checkProcess. arguments = [ " -n " , " -f " , configURL . path ]
169+ checkProcess. arguments = [ " -n " , " -f " , configPath . string ]
169170 checkProcess. standardOutput = null
170171 checkProcess. standardError = null
171172
@@ -178,14 +179,14 @@ public struct PacketFilter {
178179 checkProcess. waitUntilExit ( )
179180 checkStatus = checkProcess. terminationStatus
180181 guard checkStatus == 0 else {
181- throw ContainerizationError ( . internalError, message: " invalid pf config \" \( configURL . path ) \" " )
182+ throw ContainerizationError ( . internalError, message: " invalid pf config \" \( configPath . string ) \" " )
182183 }
183184
184185 let reloadProcess = Foundation . Process ( )
185186 var reloadStatus : Int32
186187
187188 reloadProcess. executableURL = URL ( fileURLWithPath: " /sbin/pfctl " )
188- reloadProcess. arguments = [ " -f " , configURL . path ]
189+ reloadProcess. arguments = [ " -f " , configPath . string ]
189190 reloadProcess. standardOutput = null
190191 reloadProcess. standardError = null
191192
@@ -197,7 +198,7 @@ public struct PacketFilter {
197198 reloadProcess. waitUntilExit ( )
198199 reloadStatus = reloadProcess. terminationStatus
199200 guard reloadStatus == 0 else {
200- throw ContainerizationError ( . invalidState, message: " pfctl -f \" \( configURL . path ) \" failed with status \( reloadStatus) " )
201+ throw ContainerizationError ( . invalidState, message: " pfctl -f \" \( configPath . string ) \" failed with status \( reloadStatus) " )
201202 }
202203 }
203204}
0 commit comments