8
8
"math/bits"
9
9
"net"
10
10
"net/netip"
11
- "strconv"
12
11
"strings"
13
12
"syscall"
14
13
@@ -17,6 +16,7 @@ import (
17
16
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
18
17
"tailscale.com/net/interfaces"
19
18
"tailscale.com/net/netmon"
19
+ "tailscale.com/net/tsaddr"
20
20
"tailscale.com/types/logger"
21
21
)
22
22
@@ -31,17 +31,6 @@ func interfaceIndex(iface *winipcfg.IPAdapterAddresses) uint32 {
31
31
return iface .IfIndex
32
32
}
33
33
34
- // getBestInterface can be swapped out in tests.
35
- var getBestInterface func (addr windows.Sockaddr , idx * uint32 ) error = windows .GetBestInterfaceEx
36
-
37
- // isInterfaceCoderInterface can be swapped out in tests.
38
- var isInterfaceCoderInterface func (int ) bool = isInterfaceCoderInterfaceDefault
39
-
40
- func isInterfaceCoderInterfaceDefault (idx int ) bool {
41
- _ , tsif , err := interfaces .Coder ()
42
- return err == nil && tsif != nil && tsif .Index == idx
43
- }
44
-
45
34
func control (logf logger.Logf , netMon * netmon.Monitor ) func (network , address string , c syscall.RawConn ) error {
46
35
return func (network , address string , c syscall.RawConn ) error {
47
36
return controlLogf (logf , netMon , network , address , c )
@@ -98,30 +87,17 @@ func shouldBindToDefaultInterface(logf logger.Logf, address string) bool {
98
87
}
99
88
100
89
if coderSoftIsolation .Load () {
101
- sockAddr , err := getSockAddr (address )
90
+ addr , err := getAddr (address )
102
91
if err != nil {
103
- logf ("[unexpected] netns: Coder soft isolation: error getting sockaddr for %q, binding to default: %v" , address , err )
92
+ logf ("[unexpected] netns: Coder soft isolation: error getting addr for %q, binding to default: %v" , address , err )
104
93
return true
105
94
}
106
- if sockAddr == nil {
107
- // Unspecified addresses should not be bound to any interface.
95
+ if ! addr .IsValid () || addr .IsUnspecified () {
96
+ // Invalid or unspecified addresses should not be bound to any
97
+ // interface.
108
98
return false
109
99
}
110
-
111
- // Ask Windows to find the best interface for this address by consulting
112
- // the routing table.
113
- //
114
- // On macOS this value gets cached, but on Windows we don't need to
115
- // because this API is very fast and doesn't require opening an AF_ROUTE
116
- // socket.
117
- var idx uint32
118
- err = getBestInterface (sockAddr , & idx )
119
- if err != nil {
120
- logf ("[unexpected] netns: Coder soft isolation: error getting best interface, binding to default: %v" , err )
121
- return true
122
- }
123
-
124
- if isInterfaceCoderInterface (int (idx )) {
100
+ if tsaddr .IsCoderIP (addr ) {
125
101
logf ("[unexpected] netns: Coder soft isolation: detected socket destined for Coder interface, binding to default" )
126
102
return true
127
103
}
@@ -187,47 +163,31 @@ func nativeToBigEndian(i uint32) uint32 {
187
163
return bits .ReverseBytes32 (i )
188
164
}
189
165
190
- // getSockAddr returns the Windows sockaddr for the given address, or nil if
191
- // the address is not specified.
192
- func getSockAddr (address string ) (windows. Sockaddr , error ) {
193
- host , port , err := net .SplitHostPort (address )
166
+ // getAddr returns the netip.Addr for the given address, or an invalid address
167
+ // if the address is not specified. Use addr.IsValid() to check for this .
168
+ func getAddr (address string ) (netip. Addr , error ) {
169
+ host , _ , err := net .SplitHostPort (address )
194
170
if err != nil {
195
- return nil , fmt .Errorf ("invalid address %q: %w" , address , err )
171
+ return netip. Addr {} , fmt .Errorf ("invalid address %q: %w" , address , err )
196
172
}
197
173
if host == "" {
198
174
// netip.ParseAddr("") will fail
199
- return nil , nil
175
+ return netip. Addr {} , nil
200
176
}
201
177
202
178
addr , err := netip .ParseAddr (host )
203
179
if err != nil {
204
- return nil , fmt .Errorf ("invalid address %q: %w" , address , err )
180
+ return netip. Addr {} , fmt .Errorf ("invalid address %q: %w" , address , err )
205
181
}
206
182
if addr .Zone () != "" {
207
183
// Addresses with zones *can* be represented as a Sockaddr with extra
208
184
// effort, but we don't use or support them currently.
209
- return nil , fmt .Errorf ("invalid address %q, has zone: %w" , address , err )
185
+ return netip. Addr {} , fmt .Errorf ("invalid address %q, has zone: %w" , address , err )
210
186
}
211
187
if addr .IsUnspecified () {
212
188
// This covers the cases of 0.0.0.0 and [::].
213
- return nil , nil
214
- }
215
-
216
- portInt , err := strconv .ParseUint (port , 10 , 16 )
217
- if err != nil {
218
- return nil , fmt .Errorf ("invalid port %q: %w" , port , err )
189
+ return netip.Addr {}, nil
219
190
}
220
191
221
- if addr .Is4 () {
222
- return & windows.SockaddrInet4 {
223
- Port : int (portInt ), // nolint:gosec // portInt is always in range
224
- Addr : addr .As4 (),
225
- }, nil
226
- } else if addr .Is6 () {
227
- return & windows.SockaddrInet6 {
228
- Port : int (portInt ), // nolint:gosec // portInt is always in range
229
- Addr : addr .As16 (),
230
- }, nil
231
- }
232
- return nil , fmt .Errorf ("invalid address %q, is not IPv4 or IPv6: %w" , address , err )
192
+ return addr , nil
233
193
}
0 commit comments