Add interface address rule items
This commit is contained in:
64
route/rule/rule_network_interface_address.go
Normal file
64
route/rule/rule_network_interface_address.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package rule
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"strings"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/json/badjson"
|
||||
"github.com/sagernet/sing/common/json/badoption"
|
||||
)
|
||||
|
||||
var _ RuleItem = (*NetworkInterfaceAddressItem)(nil)
|
||||
|
||||
type NetworkInterfaceAddressItem struct {
|
||||
networkManager adapter.NetworkManager
|
||||
interfaceAddresses map[C.InterfaceType][]netip.Prefix
|
||||
description string
|
||||
}
|
||||
|
||||
func NewNetworkInterfaceAddressItem(networkManager adapter.NetworkManager, interfaceAddresses *badjson.TypedMap[option.InterfaceType, badoption.Listable[badoption.Prefixable]]) *NetworkInterfaceAddressItem {
|
||||
item := &NetworkInterfaceAddressItem{
|
||||
networkManager: networkManager,
|
||||
interfaceAddresses: make(map[C.InterfaceType][]netip.Prefix, interfaceAddresses.Size()),
|
||||
}
|
||||
var entryDescriptions []string
|
||||
for _, entry := range interfaceAddresses.Entries() {
|
||||
prefixes := make([]netip.Prefix, 0, len(entry.Value))
|
||||
for _, prefixable := range entry.Value {
|
||||
prefixes = append(prefixes, prefixable.Build(netip.Prefix{}))
|
||||
}
|
||||
item.interfaceAddresses[entry.Key.Build()] = prefixes
|
||||
entryDescriptions = append(entryDescriptions, entry.Key.Build().String()+"="+strings.Join(common.Map(prefixes, netip.Prefix.String), ","))
|
||||
}
|
||||
item.description = "network_interface_address=[" + strings.Join(entryDescriptions, " ") + "]"
|
||||
return item
|
||||
}
|
||||
|
||||
func (r *NetworkInterfaceAddressItem) Match(metadata *adapter.InboundContext) bool {
|
||||
interfaces := r.networkManager.NetworkInterfaces()
|
||||
match:
|
||||
for ifType, addresses := range r.interfaceAddresses {
|
||||
for _, networkInterface := range interfaces {
|
||||
if networkInterface.Type != ifType {
|
||||
continue
|
||||
}
|
||||
if common.Any(networkInterface.Addresses, func(it netip.Prefix) bool {
|
||||
return common.Any(addresses, func(prefix netip.Prefix) bool {
|
||||
return prefix.Overlaps(it)
|
||||
})
|
||||
}) {
|
||||
continue match
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *NetworkInterfaceAddressItem) String() string {
|
||||
return r.description
|
||||
}
|
||||
Reference in New Issue
Block a user