diff --git a/cmd/sing-box/cmd.go b/cmd/sing-box/cmd.go index f6c37ff7..9ae3a268 100644 --- a/cmd/sing-box/cmd.go +++ b/cmd/sing-box/cmd.go @@ -7,8 +7,10 @@ import ( "strconv" "time" + "github.com/sagernet/sing-box/experimental/deprecated" _ "github.com/sagernet/sing-box/include" "github.com/sagernet/sing-box/log" + "github.com/sagernet/sing/service" "github.com/sagernet/sing/service/filemanager" "github.com/spf13/cobra" @@ -65,4 +67,5 @@ func preRun(cmd *cobra.Command, args []string) { if len(configPaths) == 0 && len(configDirectories) == 0 { configPaths = append(configPaths, "config.json") } + globalCtx = service.ContextWith(globalCtx, deprecated.NewEnvManager(log.StdLogger())) } diff --git a/experimental/deprecated/constants.go b/experimental/deprecated/constants.go new file mode 100644 index 00000000..34ea5fc3 --- /dev/null +++ b/experimental/deprecated/constants.go @@ -0,0 +1,86 @@ +package deprecated + +import ( + C "github.com/sagernet/sing-box/constant" + F "github.com/sagernet/sing/common/format" + + "golang.org/x/mod/semver" +) + +type Note struct { + Name string + Description string + DeprecatedVersion string + ScheduledVersion string + EnvName string + MigrationLink string +} + +func (n Note) Impending() bool { + if n.ScheduledVersion == "" { + return false + } + if !semver.IsValid("v" + C.Version) { + return false + } + versionMinor := semver.Compare(semver.MajorMinor("v"+C.Version), "v"+n.ScheduledVersion) + if versionMinor < 0 { + panic("invalid deprecated note: " + n.Name) + } + return versionMinor <= 1 +} + +func (n Note) Message() string { + return F.ToString( + n.Description, " is deprecated in sing-box ", n.DeprecatedVersion, + " and will be removed in sing-box ", n.ScheduledVersion, ", please checkout documentation for migration.", + ) +} + +func (n Note) MessageWithLink() string { + return F.ToString( + n.Description, " is deprecated in sing-box ", n.DeprecatedVersion, + " and will be removed in sing-box ", n.ScheduledVersion, ", checkout documentation for migration: ", n.MigrationLink, + ) +} + +var OptionBadMatchSource = Note{ + Name: "bad-match-source", + Description: "legacy match source rule item", + DeprecatedVersion: "1.10.0", + ScheduledVersion: "1.11.0", + MigrationLink: "https://sing-box.sagernet.org/deprecated/#match-source-rule-items-are-renamed", +} + +var OptionGEOIP = Note{ + Name: "geoip", + Description: "geoip database", + DeprecatedVersion: "1.8.0", + ScheduledVersion: "1.12.0", + EnvName: "GEOIP", + MigrationLink: "https://sing-box.sagernet.org/migration/#migrate-geoip-to-rule-sets", +} + +var OptionGEOSITE = Note{ + Name: "geosite", + Description: "geosite database", + DeprecatedVersion: "1.8.0", + ScheduledVersion: "1.12.0", + EnvName: "GEOSITE", + MigrationLink: "https://sing-box.sagernet.org/migration/#migrate-geosite-to-rule-sets", +} + +var OptionTUNAddressX = Note{ + Name: "tun-address-x", + Description: "legacy tun address fields", + DeprecatedVersion: "1.10.0", + ScheduledVersion: "1.12.0", + MigrationLink: "https://sing-box.sagernet.org/migration/#tun-address-fields-are-merged", +} + +var Options = []Note{ + OptionBadMatchSource, + OptionGEOIP, + OptionGEOSITE, + OptionTUNAddressX, +} diff --git a/experimental/deprecated/env.go b/experimental/deprecated/env.go new file mode 100644 index 00000000..113b8717 --- /dev/null +++ b/experimental/deprecated/env.go @@ -0,0 +1,30 @@ +package deprecated + +import ( + "os" + "strconv" + + "github.com/sagernet/sing/common/logger" +) + +type envManager struct { + logger logger.Logger +} + +func NewEnvManager(logger logger.Logger) Manager { + return &envManager{logger: logger} +} + +func (f *envManager) ReportDeprecated(feature Note) { + if !feature.Impending() { + f.logger.Warn(feature.MessageWithLink()) + return + } + enable, enableErr := strconv.ParseBool(os.Getenv("ENABLE_DEPRECATED_" + feature.EnvName)) + if enableErr == nil && enable { + f.logger.Warn(feature.MessageWithLink()) + return + } + f.logger.Error(feature.MessageWithLink()) + f.logger.Fatal("to continuing using this feature, set ENABLE_DEPRECATED_" + feature.EnvName + "=true") +} diff --git a/experimental/deprecated/manager.go b/experimental/deprecated/manager.go new file mode 100644 index 00000000..d12acf48 --- /dev/null +++ b/experimental/deprecated/manager.go @@ -0,0 +1,19 @@ +package deprecated + +import ( + "context" + + "github.com/sagernet/sing/service" +) + +type Manager interface { + ReportDeprecated(feature Note) +} + +func Report(ctx context.Context, feature Note) { + manager := service.FromContext[Manager](ctx) + if manager == nil { + return + } + manager.ReportDeprecated(feature) +} diff --git a/experimental/libbox/command.go b/experimental/libbox/command.go index f9aca13f..3eb57dd4 100644 --- a/experimental/libbox/command.go +++ b/experimental/libbox/command.go @@ -16,4 +16,5 @@ const ( CommandSetSystemProxyEnabled CommandConnections CommandCloseConnection + CommandGetDeprecatedNotes ) diff --git a/experimental/libbox/command_close_connection.go b/experimental/libbox/command_close_connection.go index 1edd5911..a2b05e56 100644 --- a/experimental/libbox/command_close_connection.go +++ b/experimental/libbox/command_close_connection.go @@ -18,6 +18,10 @@ func (c *CommandClient) CloseConnection(connId string) error { return err } defer conn.Close() + err = binary.Write(conn, binary.BigEndian, uint8(CommandCloseConnection)) + if err != nil { + return err + } writer := bufio.NewWriter(conn) err = varbin.Write(writer, binary.BigEndian, connId) if err != nil { diff --git a/experimental/libbox/command_deprecated_report.go b/experimental/libbox/command_deprecated_report.go new file mode 100644 index 00000000..5772124c --- /dev/null +++ b/experimental/libbox/command_deprecated_report.go @@ -0,0 +1,46 @@ +package libbox + +import ( + "encoding/binary" + "net" + + "github.com/sagernet/sing-box/experimental/deprecated" + "github.com/sagernet/sing/common" + E "github.com/sagernet/sing/common/exceptions" + "github.com/sagernet/sing/common/varbin" + "github.com/sagernet/sing/service" +) + +func (c *CommandClient) GetDeprecatedNotes() (DeprecatedNoteIterator, error) { + conn, err := c.directConnect() + if err != nil { + return nil, err + } + defer conn.Close() + err = binary.Write(conn, binary.BigEndian, uint8(CommandGetDeprecatedNotes)) + if err != nil { + return nil, err + } + err = readError(conn) + if err != nil { + return nil, err + } + var features []deprecated.Note + err = varbin.Read(conn, binary.BigEndian, &features) + if err != nil { + return nil, err + } + return newIterator(common.Map(features, func(it deprecated.Note) *DeprecatedNote { return (*DeprecatedNote)(&it) })), nil +} + +func (s *CommandServer) handleGetDeprecatedNotes(conn net.Conn) error { + boxService := s.service + if boxService == nil { + return writeError(conn, E.New("service not ready")) + } + err := writeError(conn, nil) + if err != nil { + return err + } + return varbin.Write(conn, binary.BigEndian, service.FromContext[deprecated.Manager](boxService.ctx).(*deprecatedManager).Get()) +} diff --git a/experimental/libbox/command_server.go b/experimental/libbox/command_server.go index f913191d..26b4aa79 100644 --- a/experimental/libbox/command_server.go +++ b/experimental/libbox/command_server.go @@ -174,6 +174,8 @@ func (s *CommandServer) handleConnection(conn net.Conn) error { return s.handleConnectionsConn(conn) case CommandCloseConnection: return s.handleCloseConnection(conn) + case CommandGetDeprecatedNotes: + return s.handleGetDeprecatedNotes(conn) default: return E.New("unknown command: ", command) } diff --git a/experimental/libbox/deprecated.go b/experimental/libbox/deprecated.go new file mode 100644 index 00000000..b953014f --- /dev/null +++ b/experimental/libbox/deprecated.go @@ -0,0 +1,56 @@ +package libbox + +import ( + "sync" + + "github.com/sagernet/sing-box/experimental/deprecated" +) + +var _ deprecated.Manager = (*deprecatedManager)(nil) + +type deprecatedManager struct { + access sync.Mutex + features []deprecated.Note +} + +func (m *deprecatedManager) ReportDeprecated(feature deprecated.Note) { + m.access.Lock() + defer m.access.Unlock() + m.features = append(m.features, feature) +} + +func (m *deprecatedManager) Get() []deprecated.Note { + m.access.Lock() + defer m.access.Unlock() + features := m.features + m.features = nil + return features +} + +var _ = deprecated.Note(DeprecatedNote{}) + +type DeprecatedNote struct { + Name string + Description string + DeprecatedVersion string + ScheduledVersion string + EnvName string + MigrationLink string +} + +func (n DeprecatedNote) Impending() bool { + return deprecated.Note(n).Impending() +} + +func (n DeprecatedNote) Message() string { + return deprecated.Note(n).Message() +} + +func (n DeprecatedNote) MessageWithLink() string { + return deprecated.Note(n).MessageWithLink() +} + +type DeprecatedNoteIterator interface { + HasNext() bool + Next() *DeprecatedNote +} diff --git a/experimental/libbox/service.go b/experimental/libbox/service.go index c6509010..c87c960c 100644 --- a/experimental/libbox/service.go +++ b/experimental/libbox/service.go @@ -14,6 +14,7 @@ import ( "github.com/sagernet/sing-box/common/process" "github.com/sagernet/sing-box/common/urltest" C "github.com/sagernet/sing-box/constant" + "github.com/sagernet/sing-box/experimental/deprecated" "github.com/sagernet/sing-box/experimental/libbox/internal/procfs" "github.com/sagernet/sing-box/experimental/libbox/platform" "github.com/sagernet/sing-box/log" @@ -49,6 +50,7 @@ func NewService(configContent string, platformInterface PlatformInterface) (*Box ctx = filemanager.WithDefault(ctx, sWorkingPath, sTempPath, sUserID, sGroupID) urlTestHistoryStorage := urltest.NewHistoryStorage() ctx = service.ContextWithPtr(ctx, urlTestHistoryStorage) + ctx = service.ContextWith[deprecated.Manager](ctx, new(deprecatedManager)) platformWrapper := &platformInterfaceWrapper{iif: platformInterface, useProcFS: platformInterface.UseProcFS()} instance, err := box.New(box.Options{ Context: ctx, diff --git a/go.mod b/go.mod index 5d10b44d..d7012283 100644 --- a/go.mod +++ b/go.mod @@ -46,6 +46,7 @@ require ( go4.org/netipx v0.0.0-20231129151722-fdeea329fbba golang.org/x/crypto v0.25.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 + golang.org/x/mod v0.19.0 golang.org/x/net v0.27.0 golang.org/x/sys v0.25.0 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 @@ -89,7 +90,6 @@ require ( github.com/vishvananda/netns v0.0.4 // indirect github.com/zeebo/blake3 v0.2.3 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/mod v0.19.0 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/text v0.18.0 // indirect golang.org/x/time v0.5.0 // indirect diff --git a/inbound/tun.go b/inbound/tun.go index 6cb65de2..721112d7 100644 --- a/inbound/tun.go +++ b/inbound/tun.go @@ -13,6 +13,7 @@ import ( "github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/common/taskmonitor" C "github.com/sagernet/sing-box/constant" + "github.com/sagernet/sing-box/experimental/deprecated" "github.com/sagernet/sing-box/experimental/libbox/platform" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" @@ -54,15 +55,18 @@ type Tun struct { func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TunInboundOptions, platformInterface platform.Interface) (*Tun, error) { address := options.Address + var deprecatedAddressUsed bool //nolint:staticcheck //goland:noinspection GoDeprecation if len(options.Inet4Address) > 0 { address = append(address, options.Inet4Address...) + deprecatedAddressUsed = true } //nolint:staticcheck //goland:noinspection GoDeprecation if len(options.Inet6Address) > 0 { address = append(address, options.Inet6Address...) + deprecatedAddressUsed = true } inet4Address := common.Filter(address, func(it netip.Prefix) bool { return it.Addr().Is4() @@ -76,11 +80,13 @@ func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger //goland:noinspection GoDeprecation if len(options.Inet4RouteAddress) > 0 { routeAddress = append(routeAddress, options.Inet4RouteAddress...) + deprecatedAddressUsed = true } //nolint:staticcheck //goland:noinspection GoDeprecation if len(options.Inet6RouteAddress) > 0 { routeAddress = append(routeAddress, options.Inet6RouteAddress...) + deprecatedAddressUsed = true } inet4RouteAddress := common.Filter(routeAddress, func(it netip.Prefix) bool { return it.Addr().Is4() @@ -94,11 +100,13 @@ func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger //goland:noinspection GoDeprecation if len(options.Inet4RouteExcludeAddress) > 0 { routeExcludeAddress = append(routeExcludeAddress, options.Inet4RouteExcludeAddress...) + deprecatedAddressUsed = true } //nolint:staticcheck //goland:noinspection GoDeprecation if len(options.Inet6RouteExcludeAddress) > 0 { routeExcludeAddress = append(routeExcludeAddress, options.Inet6RouteExcludeAddress...) + deprecatedAddressUsed = true } inet4RouteExcludeAddress := common.Filter(routeExcludeAddress, func(it netip.Prefix) bool { return it.Addr().Is4() @@ -107,6 +115,10 @@ func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger return it.Addr().Is6() }) + if deprecatedAddressUsed { + deprecated.Report(ctx, deprecated.OptionTUNAddressX) + } + tunMTU := options.MTU if tunMTU == 0 { tunMTU = 9000 diff --git a/option/rule.go b/option/rule.go index 5f15645c..0c66ab1d 100644 --- a/option/rule.go +++ b/option/rule.go @@ -64,7 +64,7 @@ func (r Rule) IsValid() bool { } } -type _DefaultRule struct { +type DefaultRule struct { Inbound Listable[string] `json:"inbound,omitempty"` IPVersion int `json:"ip_version,omitempty"` Network Listable[string] `json:"network,omitempty"` @@ -104,22 +104,6 @@ type _DefaultRule struct { Deprecated_RulesetIPCIDRMatchSource bool `json:"rule_set_ipcidr_match_source,omitempty"` } -type DefaultRule _DefaultRule - -func (r *DefaultRule) UnmarshalJSON(bytes []byte) error { - err := json.Unmarshal(bytes, (*_DefaultRule)(r)) - if err != nil { - return err - } - //nolint:staticcheck - //goland:noinspection GoDeprecation - if r.Deprecated_RulesetIPCIDRMatchSource { - r.Deprecated_RulesetIPCIDRMatchSource = false - r.RuleSetIPCIDRMatchSource = true - } - return nil -} - func (r *DefaultRule) IsValid() bool { var defaultValue DefaultRule defaultValue.Invert = r.Invert diff --git a/option/rule_dns.go b/option/rule_dns.go index 2e03b425..2e52d6c5 100644 --- a/option/rule_dns.go +++ b/option/rule_dns.go @@ -64,7 +64,7 @@ func (r DNSRule) IsValid() bool { } } -type _DefaultDNSRule struct { +type DefaultDNSRule struct { Inbound Listable[string] `json:"inbound,omitempty"` IPVersion int `json:"ip_version,omitempty"` QueryType Listable[DNSQueryType] `json:"query_type,omitempty"` @@ -109,22 +109,6 @@ type _DefaultDNSRule struct { Deprecated_RulesetIPCIDRMatchSource bool `json:"rule_set_ipcidr_match_source,omitempty"` } -type DefaultDNSRule _DefaultDNSRule - -func (r *DefaultDNSRule) UnmarshalJSON(bytes []byte) error { - err := json.UnmarshalDisallowUnknownFields(bytes, (*_DefaultDNSRule)(r)) - if err != nil { - return err - } - //nolint:staticcheck - //goland:noinspection GoDeprecation - if r.Deprecated_RulesetIPCIDRMatchSource { - r.Deprecated_RulesetIPCIDRMatchSource = false - r.RuleSetIPCIDRMatchSource = true - } - return nil -} - func (r *DefaultDNSRule) IsValid() bool { var defaultValue DefaultDNSRule defaultValue.Invert = r.Invert diff --git a/route/router.go b/route/router.go index aac5f603..2aaffbbb 100644 --- a/route/router.go +++ b/route/router.go @@ -153,14 +153,14 @@ func NewRouter( Logger: router.dnsLogger, }) for i, ruleOptions := range options.Rules { - routeRule, err := NewRule(router, router.logger, ruleOptions, true) + routeRule, err := NewRule(ctx, router, router.logger, ruleOptions, true) if err != nil { return nil, E.Cause(err, "parse rule[", i, "]") } router.rules = append(router.rules, routeRule) } for i, dnsRuleOptions := range dnsOptions.Rules { - dnsRule, err := NewDNSRule(router, router.logger, dnsRuleOptions, true) + dnsRule, err := NewDNSRule(ctx, router, router.logger, dnsRuleOptions, true) if err != nil { return nil, E.Cause(err, "parse dns rule[", i, "]") } diff --git a/route/router_geo_resources.go b/route/router_geo_resources.go index 14364d21..181f1efa 100644 --- a/route/router_geo_resources.go +++ b/route/router_geo_resources.go @@ -13,6 +13,7 @@ import ( "github.com/sagernet/sing-box/common/geoip" "github.com/sagernet/sing-box/common/geosite" C "github.com/sagernet/sing-box/constant" + "github.com/sagernet/sing-box/experimental/deprecated" E "github.com/sagernet/sing/common/exceptions" M "github.com/sagernet/sing/common/metadata" "github.com/sagernet/sing/common/rw" @@ -32,7 +33,7 @@ func (r *Router) LoadGeosite(code string) (adapter.Rule, error) { if err != nil { return nil, err } - rule, err = NewDefaultRule(r, nil, geosite.Compile(items)) + rule, err = NewDefaultRule(r.ctx, r, nil, geosite.Compile(items)) if err != nil { return nil, err } @@ -41,6 +42,7 @@ func (r *Router) LoadGeosite(code string) (adapter.Rule, error) { } func (r *Router) prepareGeoIPDatabase() error { + deprecated.Report(r.ctx, deprecated.OptionGEOIP) var geoPath string if r.geoIPOptions.Path != "" { geoPath = r.geoIPOptions.Path @@ -87,6 +89,7 @@ func (r *Router) prepareGeoIPDatabase() error { } func (r *Router) prepareGeositeDatabase() error { + deprecated.Report(r.ctx, deprecated.OptionGEOSITE) var geoPath string if r.geositeOptions.Path != "" { geoPath = r.geositeOptions.Path diff --git a/route/rule_default.go b/route/rule_default.go index 40b93e5f..fb4f6d82 100644 --- a/route/rule_default.go +++ b/route/rule_default.go @@ -1,14 +1,17 @@ package route import ( + "context" + "github.com/sagernet/sing-box/adapter" C "github.com/sagernet/sing-box/constant" + "github.com/sagernet/sing-box/experimental/deprecated" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" E "github.com/sagernet/sing/common/exceptions" ) -func NewRule(router adapter.Router, logger log.ContextLogger, options option.Rule, checkOutbound bool) (adapter.Rule, error) { +func NewRule(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.Rule, checkOutbound bool) (adapter.Rule, error) { switch options.Type { case "", C.RuleTypeDefault: if !options.DefaultOptions.IsValid() { @@ -17,7 +20,7 @@ func NewRule(router adapter.Router, logger log.ContextLogger, options option.Rul if options.DefaultOptions.Outbound == "" && checkOutbound { return nil, E.New("missing outbound field") } - return NewDefaultRule(router, logger, options.DefaultOptions) + return NewDefaultRule(ctx, router, logger, options.DefaultOptions) case C.RuleTypeLogical: if !options.LogicalOptions.IsValid() { return nil, E.New("missing conditions") @@ -25,7 +28,7 @@ func NewRule(router adapter.Router, logger log.ContextLogger, options option.Rul if options.LogicalOptions.Outbound == "" && checkOutbound { return nil, E.New("missing outbound field") } - return NewLogicalRule(router, logger, options.LogicalOptions) + return NewLogicalRule(ctx, router, logger, options.LogicalOptions) default: return nil, E.New("unknown rule type: ", options.Type) } @@ -42,7 +45,7 @@ type RuleItem interface { String() string } -func NewDefaultRule(router adapter.Router, logger log.ContextLogger, options option.DefaultRule) (*DefaultRule, error) { +func NewDefaultRule(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.DefaultRule) (*DefaultRule, error) { rule := &DefaultRule{ abstractDefaultRule{ invert: options.Invert, @@ -218,7 +221,16 @@ func NewDefaultRule(router adapter.Router, logger log.ContextLogger, options opt rule.allItems = append(rule.allItems, item) } if len(options.RuleSet) > 0 { - item := NewRuleSetItem(router, options.RuleSet, options.RuleSetIPCIDRMatchSource, false) + var matchSource bool + if options.RuleSetIPCIDRMatchSource { + matchSource = true + } else + //nolint:staticcheck + if options.Deprecated_RulesetIPCIDRMatchSource { + matchSource = true + deprecated.Report(ctx, deprecated.OptionBadMatchSource) + } + item := NewRuleSetItem(router, options.RuleSet, matchSource, false) rule.items = append(rule.items, item) rule.allItems = append(rule.allItems, item) } @@ -231,7 +243,7 @@ type LogicalRule struct { abstractLogicalRule } -func NewLogicalRule(router adapter.Router, logger log.ContextLogger, options option.LogicalRule) (*LogicalRule, error) { +func NewLogicalRule(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.LogicalRule) (*LogicalRule, error) { r := &LogicalRule{ abstractLogicalRule{ rules: make([]adapter.HeadlessRule, len(options.Rules)), @@ -248,7 +260,7 @@ func NewLogicalRule(router adapter.Router, logger log.ContextLogger, options opt return nil, E.New("unknown logical mode: ", options.Mode) } for i, subRule := range options.Rules { - rule, err := NewRule(router, logger, subRule, false) + rule, err := NewRule(ctx, router, logger, subRule, false) if err != nil { return nil, E.Cause(err, "sub rule[", i, "]") } diff --git a/route/rule_dns.go b/route/rule_dns.go index 616f956a..4740488e 100644 --- a/route/rule_dns.go +++ b/route/rule_dns.go @@ -1,17 +1,19 @@ package route import ( + "context" "net/netip" "github.com/sagernet/sing-box/adapter" C "github.com/sagernet/sing-box/constant" + "github.com/sagernet/sing-box/experimental/deprecated" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" "github.com/sagernet/sing/common" E "github.com/sagernet/sing/common/exceptions" ) -func NewDNSRule(router adapter.Router, logger log.ContextLogger, options option.DNSRule, checkServer bool) (adapter.DNSRule, error) { +func NewDNSRule(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.DNSRule, checkServer bool) (adapter.DNSRule, error) { switch options.Type { case "", C.RuleTypeDefault: if !options.DefaultOptions.IsValid() { @@ -20,7 +22,7 @@ func NewDNSRule(router adapter.Router, logger log.ContextLogger, options option. if options.DefaultOptions.Server == "" && checkServer { return nil, E.New("missing server field") } - return NewDefaultDNSRule(router, logger, options.DefaultOptions) + return NewDefaultDNSRule(ctx, router, logger, options.DefaultOptions) case C.RuleTypeLogical: if !options.LogicalOptions.IsValid() { return nil, E.New("missing conditions") @@ -28,7 +30,7 @@ func NewDNSRule(router adapter.Router, logger log.ContextLogger, options option. if options.LogicalOptions.Server == "" && checkServer { return nil, E.New("missing server field") } - return NewLogicalDNSRule(router, logger, options.LogicalOptions) + return NewLogicalDNSRule(ctx, router, logger, options.LogicalOptions) default: return nil, E.New("unknown rule type: ", options.Type) } @@ -43,7 +45,7 @@ type DefaultDNSRule struct { clientSubnet *netip.Prefix } -func NewDefaultDNSRule(router adapter.Router, logger log.ContextLogger, options option.DefaultDNSRule) (*DefaultDNSRule, error) { +func NewDefaultDNSRule(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.DefaultDNSRule) (*DefaultDNSRule, error) { rule := &DefaultDNSRule{ abstractDefaultRule: abstractDefaultRule{ invert: options.Invert, @@ -227,7 +229,16 @@ func NewDefaultDNSRule(router adapter.Router, logger log.ContextLogger, options rule.allItems = append(rule.allItems, item) } if len(options.RuleSet) > 0 { - item := NewRuleSetItem(router, options.RuleSet, options.RuleSetIPCIDRMatchSource, options.RuleSetIPCIDRAcceptEmpty) + var matchSource bool + if options.RuleSetIPCIDRMatchSource { + matchSource = true + } else + //nolint:staticcheck + if options.Deprecated_RulesetIPCIDRMatchSource { + matchSource = true + deprecated.Report(ctx, deprecated.OptionBadMatchSource) + } + item := NewRuleSetItem(router, options.RuleSet, matchSource, options.RuleSetIPCIDRAcceptEmpty) rule.items = append(rule.items, item) rule.allItems = append(rule.allItems, item) } @@ -283,7 +294,7 @@ type LogicalDNSRule struct { clientSubnet *netip.Prefix } -func NewLogicalDNSRule(router adapter.Router, logger log.ContextLogger, options option.LogicalDNSRule) (*LogicalDNSRule, error) { +func NewLogicalDNSRule(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.LogicalDNSRule) (*LogicalDNSRule, error) { r := &LogicalDNSRule{ abstractLogicalRule: abstractLogicalRule{ rules: make([]adapter.HeadlessRule, len(options.Rules)), @@ -303,7 +314,7 @@ func NewLogicalDNSRule(router adapter.Router, logger log.ContextLogger, options return nil, E.New("unknown logical mode: ", options.Mode) } for i, subRule := range options.Rules { - rule, err := NewDNSRule(router, logger, subRule, false) + rule, err := NewDNSRule(ctx, router, logger, subRule, false) if err != nil { return nil, E.Cause(err, "sub rule[", i, "]") }