sing-box/route/rule_cidr.go

77 lines
1.6 KiB
Go
Raw Normal View History

2022-07-02 14:55:10 +00:00
package route
import (
"net/netip"
"strings"
2022-07-08 15:03:57 +00:00
"github.com/sagernet/sing-box/adapter"
2022-07-02 14:55:10 +00:00
"github.com/sagernet/sing/common"
2022-07-04 07:51:41 +00:00
E "github.com/sagernet/sing/common/exceptions"
2022-07-02 14:55:10 +00:00
F "github.com/sagernet/sing/common/format"
)
var _ RuleItem = (*IPCIDRItem)(nil)
type IPCIDRItem struct {
prefixes []netip.Prefix
isSource bool
}
func NewIPCIDRItem(isSource bool, prefixStrings []string) (*IPCIDRItem, error) {
prefixes := make([]netip.Prefix, 0, len(prefixStrings))
2022-07-04 07:51:41 +00:00
for i, prefixString := range prefixStrings {
2022-07-02 14:55:10 +00:00
prefix, err := netip.ParsePrefix(prefixString)
if err != nil {
2022-07-04 07:51:41 +00:00
return nil, E.Cause(err, "parse prefix [", i, "]")
2022-07-02 14:55:10 +00:00
}
prefixes = append(prefixes, prefix)
}
return &IPCIDRItem{
prefixes: prefixes,
isSource: isSource,
}, nil
}
func (r *IPCIDRItem) Match(metadata *adapter.InboundContext) bool {
if r.isSource {
for _, prefix := range r.prefixes {
if prefix.Contains(metadata.Source.Addr) {
return true
}
}
} else {
2022-07-07 15:36:32 +00:00
if metadata.Destination.IsIP() {
for _, prefix := range r.prefixes {
if prefix.Contains(metadata.Destination.Addr) {
return true
}
}
} else {
for _, address := range metadata.DestinationAddresses {
for _, prefix := range r.prefixes {
if prefix.Contains(address) {
return true
}
}
2022-07-02 14:55:10 +00:00
}
}
}
return false
}
func (r *IPCIDRItem) String() string {
var description string
if r.isSource {
description = "source_ipcidr="
} else {
description = "ipcidr="
}
pLen := len(r.prefixes)
if pLen == 1 {
description += r.prefixes[0].String()
} else {
description += "[" + strings.Join(common.Map(r.prefixes, F.ToString0[netip.Prefix]), " ") + "]"
}
return description
}