diff --git a/component/geodata/init.go b/component/geodata/init.go new file mode 100644 index 00000000..2b36b626 --- /dev/null +++ b/component/geodata/init.go @@ -0,0 +1,52 @@ +package geodata + +import ( + "fmt" + C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/log" + "io" + "net/http" + "os" +) + +var initFlag bool + +func InitGeoSite() error { + if _, err := os.Stat(C.Path.GeoSite()); os.IsNotExist(err) { + log.Infoln("Can't find GeoSite.dat, start download") + if err := downloadGeoSite(C.Path.GeoSite()); err != nil { + return fmt.Errorf("can't download GeoSite.dat: %s", err.Error()) + } + log.Infoln("Download GeoSite.dat finish") + } + if !initFlag { + if err := Verify(C.GeositeName); err != nil { + log.Warnln("GeoSite.dat invalid, remove and download: %s", err) + if err := os.Remove(C.Path.GeoSite()); err != nil { + return fmt.Errorf("can't remove invalid GeoSite.dat: %s", err.Error()) + } + if err := downloadGeoSite(C.Path.GeoSite()); err != nil { + return fmt.Errorf("can't download GeoSite.dat: %s", err.Error()) + } + } + initFlag = true + } + return nil +} + +func downloadGeoSite(path string) (err error) { + resp, err := http.Get(C.GeoSiteUrl) + if err != nil { + return + } + defer resp.Body.Close() + + f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0o644) + if err != nil { + return err + } + defer f.Close() + _, err = io.Copy(f, resp.Body) + + return err +} diff --git a/config/config.go b/config/config.go index 5f7eff65..e552751f 100644 --- a/config/config.go +++ b/config/config.go @@ -533,7 +533,7 @@ func parseRules(cfg *RawConfig, proxies map[string]C.Proxy) ([]C.Rule, map[strin log.Infoln("Geodata Loader mode: %s", geodata.LoaderName()) // parse rule provider for name, mapping := range cfg.RuleProvider { - rp, err := RP.ParseRuleProvider(name, mapping) + rp, err := RP.ParseRuleProvider(name, mapping, R.ParseRule) if err != nil { return nil, nil, err } @@ -723,7 +723,7 @@ func parseFallbackIPCIDR(ips []string) ([]*netip.Prefix, error) { func parseFallbackGeoSite(countries []string, rules []C.Rule) ([]*router.DomainMatcher, error) { var sites []*router.DomainMatcher if len(countries) > 0 { - if err := initGeoSite(); err != nil { + if err := geodata.InitGeoSite(); err != nil { return nil, fmt.Errorf("can't initial GeoSite: %s", err) } } diff --git a/config/initial.go b/config/initial.go index b41fdd1a..d819168f 100644 --- a/config/initial.go +++ b/config/initial.go @@ -12,8 +12,6 @@ import ( "github.com/Dreamacro/clash/log" ) -var initFlag bool - func downloadMMDB(path string) (err error) { resp, err := http.Get(C.MmdbUrl) if err != nil { @@ -48,46 +46,6 @@ func downloadGeoIP(path string) (err error) { return err } -func downloadGeoSite(path string) (err error) { - resp, err := http.Get(C.GeoSiteUrl) - if err != nil { - return - } - defer resp.Body.Close() - - f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0o644) - if err != nil { - return err - } - defer f.Close() - _, err = io.Copy(f, resp.Body) - - return err -} - -func initGeoSite() error { - if _, err := os.Stat(C.Path.GeoSite()); os.IsNotExist(err) { - log.Infoln("Can't find GeoSite.dat, start download") - if err := downloadGeoSite(C.Path.GeoSite()); err != nil { - return fmt.Errorf("can't download GeoSite.dat: %s", err.Error()) - } - log.Infoln("Download GeoSite.dat finish") - } - if !initFlag { - if err := geodata.Verify(C.GeositeName); err != nil { - log.Warnln("GeoSite.dat invalid, remove and download: %s", err) - if err := os.Remove(C.Path.GeoSite()); err != nil { - return fmt.Errorf("can't remove invalid GeoSite.dat: %s", err.Error()) - } - if err := downloadGeoSite(C.Path.GeoSite()); err != nil { - return fmt.Errorf("can't download GeoSite.dat: %s", err.Error()) - } - } - initFlag = true - } - return nil -} - func initGeoIP() error { if C.GeodataMode { if _, err := os.Stat(C.Path.GeoIP()); os.IsNotExist(err) { diff --git a/rules/common/geosite.go b/rules/common/geosite.go index 10fe3152..c88fd78d 100644 --- a/rules/common/geosite.go +++ b/rules/common/geosite.go @@ -11,9 +11,6 @@ import ( _ "unsafe" ) -//go:linkname initGeoSite github.com/Dreamacro/clash/config.initGeoSite -func initGeoSite() error - type GEOSITE struct { *Base country string @@ -53,7 +50,7 @@ func (gs *GEOSITE) GetRecodeSize() int { func NewGEOSITE(country string, adapter string) (*GEOSITE, error) { if !initFlag { - if err := initGeoSite(); err != nil { + if err := geodata.InitGeoSite(); err != nil { log.Errorln("can't initial GeoSite: %s", err) return nil, err } diff --git a/rules/logic/and.go b/rules/logic/and.go index edcb0e04..5a9b4d0f 100644 --- a/rules/logic/and.go +++ b/rules/logic/and.go @@ -19,9 +19,10 @@ func (A *AND) ShouldFindProcess() bool { return false } -func NewAND(payload string, adapter string) (*AND, error) { +func NewAND(payload string, adapter string, + parse func(tp, payload, target string, params []string) (parsed C.Rule, parseErr error)) (*AND, error) { and := &AND{Base: &common.Base{}, payload: payload, adapter: adapter} - rules, err := parseRuleByPayload(payload) + rules, err := parseRuleByPayload(payload, parse) if err != nil { return nil, err } diff --git a/rules/logic/common.go b/rules/logic/common.go index d3d68100..736ead43 100644 --- a/rules/logic/common.go +++ b/rules/logic/common.go @@ -9,10 +9,7 @@ import ( _ "unsafe" ) -//go:linkname parseRule github.com/Dreamacro/clash/rules.ParseRule -func parseRule(tp, payload, target string, params []string) (parsed C.Rule, parseErr error) - -func parseRuleByPayload(payload string) ([]C.Rule, error) { +func parseRuleByPayload(payload string, parseRule func(tp, payload, target string, params []string) (parsed C.Rule, parseErr error)) ([]C.Rule, error) { regex, err := regexp.Compile("\\(.*\\)") if err != nil { return nil, err @@ -29,7 +26,7 @@ func parseRuleByPayload(payload string) ([]C.Rule, error) { for _, subRange := range subRanges { subPayload := payload[subRange.start+1 : subRange.end] - rule, err := payloadToRule(subPayload) + rule, err := payloadToRule(subPayload, parseLogicSubRule(parseRule)) if err != nil { return nil, err } @@ -47,7 +44,7 @@ func containRange(r Range, preStart, preEnd int) bool { return preStart < r.start && preEnd > r.end } -func payloadToRule(subPayload string) (C.Rule, error) { +func payloadToRule(subPayload string, parseRule func(tp, payload, target string, params []string) (parsed C.Rule, parseErr error)) (C.Rule, error) { splitStr := strings.SplitN(subPayload, ",", 2) if len(splitStr) < 2 { return nil, fmt.Errorf("[%s] format is error", subPayload) @@ -62,6 +59,17 @@ func payloadToRule(subPayload string) (C.Rule, error) { return parseRule(tp, param[0], "", param[1:]) } +func parseLogicSubRule(parseRule func(tp, payload, target string, params []string) (parsed C.Rule, parseErr error)) func(tp, payload, target string, params []string) (parsed C.Rule, parseErr error) { + return func(tp, payload, target string, params []string) (parsed C.Rule, parseErr error) { + switch tp { + case "MATCH": + return nil, fmt.Errorf("unsupported rule type on logic rule") + default: + return parseRule(tp, payload, target, params) + } + } +} + type Range struct { start int end int diff --git a/rules/logic/logic_test.go b/rules/logic/logic_test.go index c279995b..b7ea9ebe 100644 --- a/rules/logic/logic_test.go +++ b/rules/logic/logic_test.go @@ -1,13 +1,72 @@ package logic import ( + "fmt" "github.com/Dreamacro/clash/constant" + RC "github.com/Dreamacro/clash/rules/common" + RP "github.com/Dreamacro/clash/rules/provider" "github.com/stretchr/testify/assert" "testing" ) +func ParseRule(tp, payload, target string, params []string) (parsed constant.Rule, parseErr error) { + switch tp { + case "DOMAIN": + parsed = RC.NewDomain(payload, target) + case "DOMAIN-SUFFIX": + parsed = RC.NewDomainSuffix(payload, target) + case "DOMAIN-KEYWORD": + parsed = RC.NewDomainKeyword(payload, target) + case "GEOSITE": + parsed, parseErr = RC.NewGEOSITE(payload, target) + case "GEOIP": + noResolve := RC.HasNoResolve(params) + parsed, parseErr = RC.NewGEOIP(payload, target, noResolve) + case "IP-CIDR", "IP-CIDR6": + noResolve := RC.HasNoResolve(params) + parsed, parseErr = RC.NewIPCIDR(payload, target, RC.WithIPCIDRNoResolve(noResolve)) + case "SRC-IP-CIDR": + parsed, parseErr = RC.NewIPCIDR(payload, target, RC.WithIPCIDRSourceIP(true), RC.WithIPCIDRNoResolve(true)) + case "IP-SUFFIX": + noResolve := RC.HasNoResolve(params) + parsed, parseErr = RC.NewIPSuffix(payload, target, false, noResolve) + case "SRC-IP-SUFFIX": + parsed, parseErr = RC.NewIPSuffix(payload, target, true, true) + case "SRC-PORT": + parsed, parseErr = RC.NewPort(payload, target, true) + case "DST-PORT": + parsed, parseErr = RC.NewPort(payload, target, false) + case "PROCESS-NAME": + parsed, parseErr = RC.NewProcess(payload, target, true) + case "PROCESS-PATH": + parsed, parseErr = RC.NewProcess(payload, target, false) + case "NETWORK": + parsed, parseErr = RC.NewNetworkType(payload, target) + case "UID": + parsed, parseErr = RC.NewUid(payload, target) + case "IN-TYPE": + parsed, parseErr = RC.NewInType(payload, target) + case "AND": + parsed, parseErr = NewAND(payload, target, ParseRule) + case "OR": + parsed, parseErr = NewOR(payload, target, ParseRule) + case "NOT": + parsed, parseErr = NewNOT(payload, target, ParseRule) + case "RULE-SET": + noResolve := RC.HasNoResolve(params) + parsed, parseErr = RP.NewRuleSet(payload, target, noResolve, ParseRule) + case "MATCH": + parsed = RC.NewMatch(target) + parseErr = nil + default: + parseErr = fmt.Errorf("unsupported rule type %s", tp) + } + + return +} + func TestAND(t *testing.T) { - and, err := NewAND("((DOMAIN,baidu.com),(NETWORK,TCP),(DST-PORT,10001-65535))", "DIRECT") + and, err := NewAND("((DOMAIN,baidu.com),(NETWORK,TCP),(DST-PORT,10001-65535))", "DIRECT", ParseRule) assert.Equal(t, nil, err) assert.Equal(t, "DIRECT", and.adapter) assert.Equal(t, false, and.ShouldResolveIP()) @@ -18,29 +77,29 @@ func TestAND(t *testing.T) { DstPort: "20000", })) - and, err = NewAND("(DOMAIN,baidu.com),(NETWORK,TCP),(DST-PORT,10001-65535))", "DIRECT") + and, err = NewAND("(DOMAIN,baidu.com),(NETWORK,TCP),(DST-PORT,10001-65535))", "DIRECT", ParseRule) assert.NotEqual(t, nil, err) - and, err = NewAND("((AND,(DOMAIN,baidu.com),(NETWORK,TCP)),(NETWORK,TCP),(DST-PORT,10001-65535))", "DIRECT") + and, err = NewAND("((AND,(DOMAIN,baidu.com),(NETWORK,TCP)),(NETWORK,TCP),(DST-PORT,10001-65535))", "DIRECT", ParseRule) assert.Equal(t, nil, err) } func TestNOT(t *testing.T) { - not, err := NewNOT("((DST-PORT,6000-6500))", "REJECT") + not, err := NewNOT("((DST-PORT,6000-6500))", "REJECT", ParseRule) assert.Equal(t, nil, err) assert.Equal(t, false, not.Match(&constant.Metadata{ DstPort: "6100", })) - _, err = NewNOT("((DST-PORT,5600-6666),(DOMAIN,baidu.com))", "DIRECT") + _, err = NewNOT("((DST-PORT,5600-6666),(DOMAIN,baidu.com))", "DIRECT", ParseRule) assert.NotEqual(t, nil, err) - _, err = NewNOT("(())", "DIRECT") + _, err = NewNOT("(())", "DIRECT", ParseRule) assert.NotEqual(t, nil, err) } func TestOR(t *testing.T) { - or, err := NewOR("((DOMAIN,baidu.com),(NETWORK,TCP),(DST-PORT,10001-65535))", "DIRECT") + or, err := NewOR("((DOMAIN,baidu.com),(NETWORK,TCP),(DST-PORT,10001-65535))", "DIRECT", ParseRule) assert.Equal(t, nil, err) assert.Equal(t, true, or.Match(&constant.Metadata{ NetWork: constant.TCP, diff --git a/rules/logic/not.go b/rules/logic/not.go index d72076fc..dc14e1d1 100644 --- a/rules/logic/not.go +++ b/rules/logic/not.go @@ -17,9 +17,9 @@ func (not *NOT) ShouldFindProcess() bool { return false } -func NewNOT(payload string, adapter string) (*NOT, error) { +func NewNOT(payload string, adapter string, parse func(tp, payload, target string, params []string) (parsed C.Rule, parseErr error)) (*NOT, error) { not := &NOT{Base: &common.Base{}, adapter: adapter} - rule, err := parseRuleByPayload(payload) + rule, err := parseRuleByPayload(payload, parse) if err != nil { return nil, err } diff --git a/rules/logic/or.go b/rules/logic/or.go index f8295552..08698b02 100644 --- a/rules/logic/or.go +++ b/rules/logic/or.go @@ -45,9 +45,9 @@ func (or *OR) ShouldResolveIP() bool { return or.needIP } -func NewOR(payload string, adapter string) (*OR, error) { +func NewOR(payload string, adapter string, parse func(tp, payload, target string, params []string) (parsed C.Rule, parseErr error)) (*OR, error) { or := &OR{Base: &common.Base{}, payload: payload, adapter: adapter} - rules, err := parseRuleByPayload(payload) + rules, err := parseRuleByPayload(payload, parse) if err != nil { return nil, err } diff --git a/rules/parser.go b/rules/parser.go index 13154dc3..6ddd63a8 100644 --- a/rules/parser.go +++ b/rules/parser.go @@ -1,29 +1,64 @@ package rules import ( + "fmt" C "github.com/Dreamacro/clash/constant" RC "github.com/Dreamacro/clash/rules/common" "github.com/Dreamacro/clash/rules/logic" RP "github.com/Dreamacro/clash/rules/provider" - "github.com/Dreamacro/clash/rules/ruleparser" ) func ParseRule(tp, payload, target string, params []string) (parsed C.Rule, parseErr error) { switch tp { + case "DOMAIN": + parsed = RC.NewDomain(payload, target) + case "DOMAIN-SUFFIX": + parsed = RC.NewDomainSuffix(payload, target) + case "DOMAIN-KEYWORD": + parsed = RC.NewDomainKeyword(payload, target) + case "GEOSITE": + parsed, parseErr = RC.NewGEOSITE(payload, target) + case "GEOIP": + noResolve := RC.HasNoResolve(params) + parsed, parseErr = RC.NewGEOIP(payload, target, noResolve) + case "IP-CIDR", "IP-CIDR6": + noResolve := RC.HasNoResolve(params) + parsed, parseErr = RC.NewIPCIDR(payload, target, RC.WithIPCIDRNoResolve(noResolve)) + case "SRC-IP-CIDR": + parsed, parseErr = RC.NewIPCIDR(payload, target, RC.WithIPCIDRSourceIP(true), RC.WithIPCIDRNoResolve(true)) + case "IP-SUFFIX": + noResolve := RC.HasNoResolve(params) + parsed, parseErr = RC.NewIPSuffix(payload, target, false, noResolve) + case "SRC-IP-SUFFIX": + parsed, parseErr = RC.NewIPSuffix(payload, target, true, true) + case "SRC-PORT": + parsed, parseErr = RC.NewPort(payload, target, true) + case "DST-PORT": + parsed, parseErr = RC.NewPort(payload, target, false) + case "PROCESS-NAME": + parsed, parseErr = RC.NewProcess(payload, target, true) + case "PROCESS-PATH": + parsed, parseErr = RC.NewProcess(payload, target, false) + case "NETWORK": + parsed, parseErr = RC.NewNetworkType(payload, target) + case "UID": + parsed, parseErr = RC.NewUid(payload, target) + case "IN-TYPE": + parsed, parseErr = RC.NewInType(payload, target) case "AND": - parsed, parseErr = logic.NewAND(payload, target) + parsed, parseErr = logic.NewAND(payload, target, ParseRule) case "OR": - parsed, parseErr = logic.NewOR(payload, target) + parsed, parseErr = logic.NewOR(payload, target, ParseRule) case "NOT": - parsed, parseErr = logic.NewNOT(payload, target) + parsed, parseErr = logic.NewNOT(payload, target, ParseRule) case "RULE-SET": noResolve := RC.HasNoResolve(params) - parsed, parseErr = RP.NewRuleSet(payload, target, noResolve) + parsed, parseErr = RP.NewRuleSet(payload, target, noResolve, ParseRule) case "MATCH": parsed = RC.NewMatch(target) parseErr = nil default: - parsed, parseErr = ruleparser.ParseSameRule(tp, payload, target, params) + parseErr = fmt.Errorf("unsupported rule type %s", tp) } if parseErr != nil { diff --git a/rules/provider/classical_strategy.go b/rules/provider/classical_strategy.go index 297ad32f..2fc52090 100644 --- a/rules/provider/classical_strategy.go +++ b/rules/provider/classical_strategy.go @@ -1,6 +1,7 @@ package provider import ( + "fmt" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/log" ) @@ -9,6 +10,7 @@ type classicalStrategy struct { rules []C.Rule count int shouldResolveIP bool + parse func(tp, payload, target string, params []string) (parsed C.Rule, parseErr error) } func (c *classicalStrategy) Match(metadata *C.Metadata) bool { @@ -34,7 +36,7 @@ func (c *classicalStrategy) OnUpdate(rules []string) { shouldResolveIP := false for _, rawRule := range rules { ruleType, rule, params := ruleParse(rawRule) - r, err := parseRule(ruleType, rule, "", params) + r, err := c.parse(ruleType, rule, "", params) if err != nil { log.Warnln("parse rule error:[%s]", err.Error()) } else { @@ -50,6 +52,13 @@ func (c *classicalStrategy) OnUpdate(rules []string) { c.count = len(classicalRules) } -func NewClassicalStrategy() *classicalStrategy { - return &classicalStrategy{rules: []C.Rule{}} +func NewClassicalStrategy(parse func(tp, payload, target string, params []string) (parsed C.Rule, parseErr error)) *classicalStrategy { + return &classicalStrategy{rules: []C.Rule{}, parse: func(tp, payload, target string, params []string) (parsed C.Rule, parseErr error) { + switch tp { + case "MATCH": + return nil, fmt.Errorf("unsupported rule type on rule-set") + default: + return parse(tp, payload, target, params) + } + }} } diff --git a/rules/provider/parse.go b/rules/provider/parse.go index 51452d09..de366802 100644 --- a/rules/provider/parse.go +++ b/rules/provider/parse.go @@ -6,8 +6,6 @@ import ( "github.com/Dreamacro/clash/common/structure" C "github.com/Dreamacro/clash/constant" P "github.com/Dreamacro/clash/constant/provider" - RC "github.com/Dreamacro/clash/rules/common" - "github.com/Dreamacro/clash/rules/ruleparser" "time" ) @@ -19,7 +17,7 @@ type ruleProviderSchema struct { Interval int `provider:"interval,omitempty"` } -func ParseRuleProvider(name string, mapping map[string]interface{}) (P.RuleProvider, error) { +func ParseRuleProvider(name string, mapping map[string]interface{}, parse func(tp, payload, target string, params []string) (parsed C.Rule, parseErr error)) (P.RuleProvider, error) { schema := &ruleProviderSchema{} decoder := structure.NewDecoder(structure.Option{TagName: "provider", WeaklyTypedInput: true}) if err := decoder.Decode(mapping, schema); err != nil { @@ -49,19 +47,5 @@ func ParseRuleProvider(name string, mapping map[string]interface{}) (P.RuleProvi return nil, fmt.Errorf("unsupported vehicle type: %s", schema.Type) } - return NewRuleSetProvider(name, behavior, time.Duration(uint(schema.Interval))*time.Second, vehicle), nil -} - -func parseRule(tp, payload, target string, params []string) (parsed C.Rule, parseErr error) { - parsed, parseErr = ruleparser.ParseSameRule(tp, payload, target, params) - - if parseErr != nil { - return nil, parseErr - } - ruleExtra := &C.RuleExtra{ - Network: RC.FindNetwork(params), - SourceIPs: RC.FindSourceIPs(params), - } - parsed.SetRuleExtra(ruleExtra) - return parsed, parseErr + return NewRuleSetProvider(name, behavior, time.Duration(uint(schema.Interval))*time.Second, vehicle, parse), nil } diff --git a/rules/provider/provider.go b/rules/provider/provider.go index a92df718..32f57b5b 100644 --- a/rules/provider/provider.go +++ b/rules/provider/provider.go @@ -99,7 +99,8 @@ func (rp *ruleSetProvider) MarshalJSON() ([]byte, error) { }) } -func NewRuleSetProvider(name string, behavior P.RuleType, interval time.Duration, vehicle P.Vehicle) P.RuleProvider { +func NewRuleSetProvider(name string, behavior P.RuleType, interval time.Duration, vehicle P.Vehicle, + parse func(tp, payload, target string, params []string) (parsed C.Rule, parseErr error)) P.RuleProvider { rp := &ruleSetProvider{ behavior: behavior, } @@ -112,7 +113,7 @@ func NewRuleSetProvider(name string, behavior P.RuleType, interval time.Duration fetcher := newFetcher(name, interval, vehicle, rulesParse, onUpdate) rp.fetcher = fetcher - rp.strategy = newStrategy(behavior) + rp.strategy = newStrategy(behavior, parse) wrapper := &RuleSetProvider{ rp, @@ -123,7 +124,7 @@ func NewRuleSetProvider(name string, behavior P.RuleType, interval time.Duration return wrapper } -func newStrategy(behavior P.RuleType) ruleStrategy { +func newStrategy(behavior P.RuleType, parse func(tp, payload, target string, params []string) (parsed C.Rule, parseErr error)) ruleStrategy { switch behavior { case P.Domain: strategy := NewDomainStrategy() @@ -132,7 +133,7 @@ func newStrategy(behavior P.RuleType) ruleStrategy { strategy := NewIPCidrStrategy() return strategy case P.Classical: - strategy := NewClassicalStrategy() + strategy := NewClassicalStrategy(parse) return strategy default: return nil diff --git a/rules/provider/rule_set.go b/rules/provider/rule_set.go index 81419818..84aaf0fb 100644 --- a/rules/provider/rule_set.go +++ b/rules/provider/rule_set.go @@ -47,7 +47,7 @@ func (rs *RuleSet) getProviders() P.RuleProvider { return rs.ruleProvider } -func NewRuleSet(ruleProviderName string, adapter string, noResolveIP bool) (*RuleSet, error) { +func NewRuleSet(ruleProviderName string, adapter string, noResolveIP bool, parse func(tp, payload, target string, params []string) (parsed C.Rule, parseErr error)) (*RuleSet, error) { rp, ok := RuleProviders()[ruleProviderName] if !ok { return nil, fmt.Errorf("rule set %s not found", ruleProviderName) diff --git a/rules/ruleparser/ruleparser.go b/rules/ruleparser/ruleparser.go deleted file mode 100644 index 64294374..00000000 --- a/rules/ruleparser/ruleparser.go +++ /dev/null @@ -1,50 +0,0 @@ -package ruleparser - -import ( - "fmt" - C "github.com/Dreamacro/clash/constant" - RC "github.com/Dreamacro/clash/rules/common" -) - -func ParseSameRule(tp, payload, target string, params []string) (parsed C.Rule, parseErr error) { - switch tp { - case "DOMAIN": - parsed = RC.NewDomain(payload, target) - case "DOMAIN-SUFFIX": - parsed = RC.NewDomainSuffix(payload, target) - case "DOMAIN-KEYWORD": - parsed = RC.NewDomainKeyword(payload, target) - case "GEOSITE": - parsed, parseErr = RC.NewGEOSITE(payload, target) - case "GEOIP": - noResolve := RC.HasNoResolve(params) - parsed, parseErr = RC.NewGEOIP(payload, target, noResolve) - case "IP-CIDR", "IP-CIDR6": - noResolve := RC.HasNoResolve(params) - parsed, parseErr = RC.NewIPCIDR(payload, target, RC.WithIPCIDRNoResolve(noResolve)) - case "SRC-IP-CIDR": - parsed, parseErr = RC.NewIPCIDR(payload, target, RC.WithIPCIDRSourceIP(true), RC.WithIPCIDRNoResolve(true)) - case "IP-SUFFIX": - noResolve := RC.HasNoResolve(params) - parsed, parseErr = RC.NewIPSuffix(payload, target, false, noResolve) - case "SRC-IP-SUFFIX": - parsed, parseErr = RC.NewIPSuffix(payload, target, true, true) - case "SRC-PORT": - parsed, parseErr = RC.NewPort(payload, target, true) - case "DST-PORT": - parsed, parseErr = RC.NewPort(payload, target, false) - case "PROCESS-NAME": - parsed, parseErr = RC.NewProcess(payload, target, true) - case "PROCESS-PATH": - parsed, parseErr = RC.NewProcess(payload, target, false) - case "NETWORK": - parsed, parseErr = RC.NewNetworkType(payload, target) - case "UID": - parsed, parseErr = RC.NewUid(payload, target) - case "IN-TYPE": - parsed, parseErr = RC.NewInType(payload, target) - default: - parseErr = fmt.Errorf("unsupported rule type %s", tp) - } - return -}