2024-10-21 23:38:34 +08:00
|
|
|
package option
|
|
|
|
|
|
|
|
import (
|
|
|
|
C "github.com/sagernet/sing-box/constant"
|
|
|
|
E "github.com/sagernet/sing/common/exceptions"
|
|
|
|
"github.com/sagernet/sing/common/json"
|
2024-11-02 00:39:02 +08:00
|
|
|
"github.com/sagernet/sing/common/json/badjson"
|
2024-10-21 23:38:34 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
type _RuleAction struct {
|
|
|
|
Action string `json:"action,omitempty"`
|
|
|
|
RouteOptions RouteActionOptions `json:"-"`
|
|
|
|
RejectOptions RejectActionOptions `json:"-"`
|
|
|
|
SniffOptions RouteActionSniff `json:"-"`
|
|
|
|
ResolveOptions RouteActionResolve `json:"-"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type RuleAction _RuleAction
|
|
|
|
|
|
|
|
func (r RuleAction) MarshalJSON() ([]byte, error) {
|
|
|
|
var v any
|
|
|
|
switch r.Action {
|
|
|
|
case C.RuleActionTypeRoute:
|
|
|
|
r.Action = ""
|
|
|
|
v = r.RouteOptions
|
|
|
|
case C.RuleActionTypeReturn:
|
|
|
|
v = nil
|
|
|
|
case C.RuleActionTypeReject:
|
|
|
|
v = r.RejectOptions
|
|
|
|
case C.RuleActionTypeHijackDNS:
|
|
|
|
v = nil
|
|
|
|
case C.RuleActionTypeSniff:
|
|
|
|
v = r.SniffOptions
|
|
|
|
case C.RuleActionTypeResolve:
|
|
|
|
v = r.ResolveOptions
|
|
|
|
default:
|
|
|
|
return nil, E.New("unknown rule action: " + r.Action)
|
|
|
|
}
|
|
|
|
if v == nil {
|
2024-11-02 00:39:02 +08:00
|
|
|
return badjson.MarshallObjects((_RuleAction)(r))
|
2024-10-21 23:38:34 +08:00
|
|
|
}
|
2024-11-02 00:39:02 +08:00
|
|
|
return badjson.MarshallObjects((_RuleAction)(r), v)
|
2024-10-21 23:38:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *RuleAction) UnmarshalJSON(data []byte) error {
|
|
|
|
err := json.Unmarshal(data, (*_RuleAction)(r))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
var v any
|
|
|
|
switch r.Action {
|
|
|
|
case "", C.RuleActionTypeRoute:
|
|
|
|
r.Action = C.RuleActionTypeRoute
|
|
|
|
v = &r.RouteOptions
|
|
|
|
case C.RuleActionTypeReturn:
|
|
|
|
v = nil
|
|
|
|
case C.RuleActionTypeReject:
|
|
|
|
v = &r.RejectOptions
|
|
|
|
case C.RuleActionTypeHijackDNS:
|
|
|
|
v = nil
|
|
|
|
case C.RuleActionTypeSniff:
|
|
|
|
v = &r.SniffOptions
|
|
|
|
case C.RuleActionTypeResolve:
|
|
|
|
v = &r.ResolveOptions
|
|
|
|
default:
|
|
|
|
return E.New("unknown rule action: " + r.Action)
|
|
|
|
}
|
|
|
|
if v == nil {
|
|
|
|
// check unknown fields
|
|
|
|
return json.UnmarshalDisallowUnknownFields(data, &_RuleAction{})
|
|
|
|
}
|
2024-11-02 00:39:02 +08:00
|
|
|
return badjson.UnmarshallExcluded(data, (*_RuleAction)(r), v)
|
2024-10-21 23:38:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
type _DNSRuleAction struct {
|
2024-11-06 17:23:00 +08:00
|
|
|
Action string `json:"action,omitempty"`
|
|
|
|
RouteOptions DNSRouteActionOptions `json:"-"`
|
|
|
|
RejectOptions RejectActionOptions `json:"-"`
|
2024-10-21 23:38:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
type DNSRuleAction _DNSRuleAction
|
|
|
|
|
|
|
|
func (r DNSRuleAction) MarshalJSON() ([]byte, error) {
|
|
|
|
var v any
|
|
|
|
switch r.Action {
|
|
|
|
case C.RuleActionTypeRoute:
|
|
|
|
r.Action = ""
|
|
|
|
v = r.RouteOptions
|
|
|
|
case C.RuleActionTypeReturn:
|
|
|
|
v = nil
|
|
|
|
case C.RuleActionTypeReject:
|
|
|
|
v = r.RejectOptions
|
|
|
|
default:
|
|
|
|
return nil, E.New("unknown DNS rule action: " + r.Action)
|
|
|
|
}
|
|
|
|
if v == nil {
|
2024-11-02 00:39:02 +08:00
|
|
|
return badjson.MarshallObjects((_DNSRuleAction)(r))
|
2024-10-21 23:38:34 +08:00
|
|
|
}
|
2024-11-02 00:39:02 +08:00
|
|
|
return badjson.MarshallObjects((_DNSRuleAction)(r), v)
|
2024-10-21 23:38:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *DNSRuleAction) UnmarshalJSON(data []byte) error {
|
|
|
|
err := json.Unmarshal(data, (*_DNSRuleAction)(r))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
var v any
|
|
|
|
switch r.Action {
|
|
|
|
case "", C.RuleActionTypeRoute:
|
|
|
|
r.Action = C.RuleActionTypeRoute
|
|
|
|
v = &r.RouteOptions
|
|
|
|
case C.RuleActionTypeReturn:
|
|
|
|
v = nil
|
|
|
|
case C.RuleActionTypeReject:
|
|
|
|
v = &r.RejectOptions
|
|
|
|
default:
|
|
|
|
return E.New("unknown DNS rule action: " + r.Action)
|
|
|
|
}
|
|
|
|
if v == nil {
|
|
|
|
// check unknown fields
|
|
|
|
return json.UnmarshalDisallowUnknownFields(data, &_DNSRuleAction{})
|
|
|
|
}
|
2024-11-02 00:39:02 +08:00
|
|
|
return badjson.UnmarshallExcluded(data, (*_DNSRuleAction)(r), v)
|
2024-10-21 23:38:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
type RouteActionOptions struct {
|
|
|
|
Outbound string `json:"outbound"`
|
|
|
|
UDPDisableDomainUnmapping bool `json:"udp_disable_domain_unmapping,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type DNSRouteActionOptions struct {
|
|
|
|
Server string `json:"server"`
|
|
|
|
DisableCache bool `json:"disable_cache,omitempty"`
|
|
|
|
RewriteTTL *uint32 `json:"rewrite_ttl,omitempty"`
|
|
|
|
ClientSubnet *AddrPrefix `json:"client_subnet,omitempty"`
|
|
|
|
}
|
|
|
|
|
2024-10-22 21:28:22 +08:00
|
|
|
type _RejectActionOptions struct {
|
|
|
|
Method string `json:"method,omitempty"`
|
2024-11-06 17:23:00 +08:00
|
|
|
NoDrop bool `json:"no_drop,omitempty"`
|
2024-10-21 23:38:34 +08:00
|
|
|
}
|
|
|
|
|
2024-10-22 21:28:22 +08:00
|
|
|
type RejectActionOptions _RejectActionOptions
|
2024-10-21 23:38:34 +08:00
|
|
|
|
2024-10-22 21:28:22 +08:00
|
|
|
func (r *RejectActionOptions) UnmarshalJSON(bytes []byte) error {
|
|
|
|
err := json.Unmarshal(bytes, (*_RejectActionOptions)(r))
|
2024-10-21 23:38:34 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2024-10-22 21:28:22 +08:00
|
|
|
switch r.Method {
|
|
|
|
case "", C.RuleActionRejectMethodDefault:
|
|
|
|
r.Method = C.RuleActionRejectMethodDefault
|
2024-11-06 17:23:00 +08:00
|
|
|
case C.RuleActionRejectMethodDrop:
|
2024-10-21 23:38:34 +08:00
|
|
|
default:
|
2024-10-22 21:28:22 +08:00
|
|
|
return E.New("unknown reject method: " + r.Method)
|
2024-10-21 23:38:34 +08:00
|
|
|
}
|
2024-11-06 17:23:00 +08:00
|
|
|
if r.Method == C.RuleActionRejectMethodDrop && r.NoDrop {
|
|
|
|
return E.New("no_drop is not allowed when method is drop")
|
|
|
|
}
|
2024-10-22 21:28:22 +08:00
|
|
|
return nil
|
2024-10-21 23:38:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
type RouteActionSniff struct {
|
|
|
|
Sniffer Listable[string] `json:"sniffer,omitempty"`
|
|
|
|
Timeout Duration `json:"timeout,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type RouteActionResolve struct {
|
|
|
|
Strategy DomainStrategy `json:"strategy,omitempty"`
|
|
|
|
Server string `json:"server,omitempty"`
|
|
|
|
}
|