@ -345,9 +345,18 @@ func (s *State) String() string {
return sb . String ( )
return sb . String ( )
}
}
// An InterfaceFilter indicates whether EqualFiltered should use i when deciding whether two States are equal.
// ips are all the IPPrefixes associated with i.
type InterfaceFilter func ( i Interface , ips [ ] netaddr . IPPrefix ) bool
// An IPFilter indicates whether EqualFiltered should use ip when deciding whether two States are equal.
// ip is an ip address associated with some interface under consideration.
type IPFilter func ( ip netaddr . IP ) bool
// EqualFiltered reports whether s and s2 are equal,
// EqualFiltered reports whether s and s2 are equal,
// considering only interfaces in s for which filter returns true.
// considering only interfaces in s for which filter returns true,
func ( s * State ) EqualFiltered ( s2 * State , filter func ( i Interface , ips [ ] netaddr . IPPrefix ) bool ) bool {
// and considering only IPs for those interfaces for which filterIP returns true.
func ( s * State ) EqualFiltered ( s2 * State , useInterface InterfaceFilter , useIP IPFilter ) bool {
if s == nil && s2 == nil {
if s == nil && s2 == nil {
return true
return true
}
}
@ -364,7 +373,7 @@ func (s *State) EqualFiltered(s2 *State, filter func(i Interface, ips []netaddr.
}
}
for iname , i := range s . Interface {
for iname , i := range s . Interface {
ips := s . InterfaceIPs [ iname ]
ips := s . InterfaceIPs [ iname ]
if ! filter ( i , ips ) {
if ! useInterface ( i , ips ) {
continue
continue
}
}
i2 , ok := s2 . Interface [ iname ]
i2 , ok := s2 . Interface [ iname ]
@ -375,7 +384,7 @@ func (s *State) EqualFiltered(s2 *State, filter func(i Interface, ips []netaddr.
if ! ok {
if ! ok {
return false
return false
}
}
if ! interfacesEqual ( i , i2 ) || ! prefixesEqual ( ips , ips2 ) {
if ! interfacesEqual ( i , i2 ) || ! prefixesEqual Filtered ( ips , ips2 , useIP ) {
return false
return false
}
}
}
}
@ -390,6 +399,21 @@ func interfacesEqual(a, b Interface) bool {
bytes . Equal ( [ ] byte ( a . HardwareAddr ) , [ ] byte ( b . HardwareAddr ) )
bytes . Equal ( [ ] byte ( a . HardwareAddr ) , [ ] byte ( b . HardwareAddr ) )
}
}
func filteredIPPs ( ipps [ ] netaddr . IPPrefix , useIP IPFilter ) [ ] netaddr . IPPrefix {
// TODO: rewrite prefixesEqualFiltered to avoid making copies
x := make ( [ ] netaddr . IPPrefix , 0 , len ( ipps ) )
for _ , ipp := range ipps {
if useIP ( ipp . IP ( ) ) {
x = append ( x , ipp )
}
}
return x
}
func prefixesEqualFiltered ( a , b [ ] netaddr . IPPrefix , useIP IPFilter ) bool {
return prefixesEqual ( filteredIPPs ( a , useIP ) , filteredIPPs ( b , useIP ) )
}
func prefixesEqual ( a , b [ ] netaddr . IPPrefix ) bool {
func prefixesEqual ( a , b [ ] netaddr . IPPrefix ) bool {
if len ( a ) != len ( b ) {
if len ( a ) != len ( b ) {
return false
return false
@ -402,13 +426,24 @@ func prefixesEqual(a, b []netaddr.IPPrefix) bool {
return true
return true
}
}
// FilterInteresting reports whether i is an interesting non-Tailscale interface.
// UseInterestingInterfaces is an InterfaceFilter that reports whether i is an interesting interface.
func FilterInteresting ( i Interface , ips [ ] netaddr . IPPrefix ) bool {
// An interesting interface if it is (a) not owned by Tailscale and (b) routes interesting IP addresses.
// See UseInterestingIPs for the defition of an interesting IP address.
func UseInterestingInterfaces ( i Interface , ips [ ] netaddr . IPPrefix ) bool {
return ! isTailscaleInterface ( i . Name , ips ) && anyInterestingIP ( ips )
return ! isTailscaleInterface ( i . Name , ips ) && anyInterestingIP ( ips )
}
}
// FilterAll always returns true, to use EqualFiltered against all interfaces.
// UseInterestingIPs is an IPFilter that reports whether ip is an interesting IP address.
func FilterAll ( i Interface , ips [ ] netaddr . IPPrefix ) bool { return true }
// An IP address is interesting if it is neither a lopback not a link local unicast IP address.
func UseInterestingIPs ( ip netaddr . IP ) bool {
return isInterestingIP ( ip )
}
// UseAllInterfaces is an InterfaceFilter that includes all interfaces.
func UseAllInterfaces ( i Interface , ips [ ] netaddr . IPPrefix ) bool { return true }
// UseAllIPs is an IPFilter that includes all all IPs.
func UseAllIPs ( ips netaddr . IP ) bool { return true }
func ( s * State ) HasPAC ( ) bool { return s != nil && s . PAC != "" }
func ( s * State ) HasPAC ( ) bool { return s != nil && s . PAC != "" }
@ -594,10 +629,7 @@ func anyInterestingIP(pfxs []netaddr.IPPrefix) bool {
// should log in interfaces.State logging. We don't need to show
// should log in interfaces.State logging. We don't need to show
// localhost or link-local addresses.
// localhost or link-local addresses.
func isInterestingIP ( ip netaddr . IP ) bool {
func isInterestingIP ( ip netaddr . IP ) bool {
if ip . IsLoopback ( ) || ip . IsLinkLocalUnicast ( ) {
return ! ip . IsLoopback ( ) && ! ip . IsLinkLocalUnicast ( )
return false
}
return true
}
}
var altNetInterfaces func ( ) ( [ ] Interface , error )
var altNetInterfaces func ( ) ( [ ] Interface , error )