github.com/sagernet/sing-box@v1.9.0-rc.20/route/rule_item_cidr.go (about) 1 package route 2 3 import ( 4 "net/netip" 5 "strings" 6 7 "github.com/sagernet/sing-box/adapter" 8 E "github.com/sagernet/sing/common/exceptions" 9 10 "go4.org/netipx" 11 ) 12 13 var _ RuleItem = (*IPCIDRItem)(nil) 14 15 type IPCIDRItem struct { 16 ipSet *netipx.IPSet 17 isSource bool 18 description string 19 } 20 21 func NewIPCIDRItem(isSource bool, prefixStrings []string) (*IPCIDRItem, error) { 22 var builder netipx.IPSetBuilder 23 for i, prefixString := range prefixStrings { 24 prefix, err := netip.ParsePrefix(prefixString) 25 if err == nil { 26 builder.AddPrefix(prefix) 27 continue 28 } 29 addr, addrErr := netip.ParseAddr(prefixString) 30 if addrErr == nil { 31 builder.Add(addr) 32 continue 33 } 34 return nil, E.Cause(err, "parse [", i, "]") 35 } 36 var description string 37 if isSource { 38 description = "source_ip_cidr=" 39 } else { 40 description = "ip_cidr=" 41 } 42 if dLen := len(prefixStrings); dLen == 1 { 43 description += prefixStrings[0] 44 } else if dLen > 3 { 45 description += "[" + strings.Join(prefixStrings[:3], " ") + "...]" 46 } else { 47 description += "[" + strings.Join(prefixStrings, " ") + "]" 48 } 49 ipSet, err := builder.IPSet() 50 if err != nil { 51 return nil, err 52 } 53 return &IPCIDRItem{ 54 ipSet: ipSet, 55 isSource: isSource, 56 description: description, 57 }, nil 58 } 59 60 func NewRawIPCIDRItem(isSource bool, ipSet *netipx.IPSet) *IPCIDRItem { 61 var description string 62 if isSource { 63 description = "source_ip_cidr=" 64 } else { 65 description = "ip_cidr=" 66 } 67 description += "<binary>" 68 return &IPCIDRItem{ 69 ipSet: ipSet, 70 isSource: isSource, 71 description: description, 72 } 73 } 74 75 func (r *IPCIDRItem) Match(metadata *adapter.InboundContext) bool { 76 if r.isSource || metadata.IPCIDRMatchSource { 77 return r.ipSet.Contains(metadata.Source.Addr) 78 } else { 79 if metadata.Destination.IsIP() { 80 return r.ipSet.Contains(metadata.Destination.Addr) 81 } else { 82 for _, address := range metadata.DestinationAddresses { 83 if r.ipSet.Contains(address) { 84 return true 85 } 86 } 87 } 88 } 89 return false 90 } 91 92 func (r *IPCIDRItem) String() string { 93 return r.description 94 }