github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/route/rule_item_cidr.go (about) 1 package route 2 3 import ( 4 "net/netip" 5 "strings" 6 7 "github.com/inazumav/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 ip_cidr [", i, "]") 35 } 36 var description string 37 if isSource { 38 description = "source_ipcidr=" 39 } else { 40 description = "ipcidr=" 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 (r *IPCIDRItem) Match(metadata *adapter.InboundContext) bool { 61 if r.isSource { 62 return r.ipSet.Contains(metadata.Source.Addr) 63 } else { 64 if metadata.Destination.IsIP() { 65 return r.ipSet.Contains(metadata.Destination.Addr) 66 } else { 67 for _, address := range metadata.DestinationAddresses { 68 if r.ipSet.Contains(address) { 69 return true 70 } 71 } 72 } 73 } 74 return false 75 } 76 77 func (r *IPCIDRItem) String() string { 78 return r.description 79 }