mirror of
https://github.com/SagerNet/sing-box.git
synced 2026-04-11 17:47:20 +10:00
Add interface address rule items
This commit is contained in:
@@ -12,6 +12,8 @@ import (
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/domain"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/json/badjson"
|
||||
"github.com/sagernet/sing/common/json/badoption"
|
||||
"github.com/sagernet/sing/common/varbin"
|
||||
|
||||
"go4.org/netipx"
|
||||
@@ -41,6 +43,8 @@ const (
|
||||
ruleItemNetworkType
|
||||
ruleItemNetworkIsExpensive
|
||||
ruleItemNetworkIsConstrained
|
||||
ruleItemNetworkInterfaceAddress
|
||||
ruleItemDefaultInterfaceAddress
|
||||
ruleItemFinal uint8 = 0xFF
|
||||
)
|
||||
|
||||
@@ -230,6 +234,51 @@ func readDefaultRule(reader varbin.Reader, recover bool) (rule option.DefaultHea
|
||||
rule.NetworkIsExpensive = true
|
||||
case ruleItemNetworkIsConstrained:
|
||||
rule.NetworkIsConstrained = true
|
||||
case ruleItemNetworkInterfaceAddress:
|
||||
rule.NetworkInterfaceAddress = new(badjson.TypedMap[option.InterfaceType, badoption.Listable[badoption.Prefixable]])
|
||||
var size uint64
|
||||
size, err = binary.ReadUvarint(reader)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for i := uint64(0); i < size; i++ {
|
||||
var key uint8
|
||||
err = binary.Read(reader, binary.BigEndian, &key)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var value []badoption.Prefixable
|
||||
var prefixCount uint64
|
||||
prefixCount, err = binary.ReadUvarint(reader)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for j := uint64(0); j < prefixCount; j++ {
|
||||
var prefix netip.Prefix
|
||||
prefix, err = readPrefix(reader)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
value = append(value, badoption.Prefixable(prefix))
|
||||
}
|
||||
rule.NetworkInterfaceAddress.Put(option.InterfaceType(key), value)
|
||||
}
|
||||
case ruleItemDefaultInterfaceAddress:
|
||||
var value []badoption.Prefixable
|
||||
var prefixCount uint64
|
||||
prefixCount, err = binary.ReadUvarint(reader)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for j := uint64(0); j < prefixCount; j++ {
|
||||
var prefix netip.Prefix
|
||||
prefix, err = readPrefix(reader)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
value = append(value, badoption.Prefixable(prefix))
|
||||
}
|
||||
rule.DefaultInterfaceAddress = value
|
||||
case ruleItemFinal:
|
||||
err = binary.Read(reader, binary.BigEndian, &rule.Invert)
|
||||
return
|
||||
@@ -346,7 +395,7 @@ func writeDefaultRule(writer varbin.Writer, rule option.DefaultHeadlessRule, gen
|
||||
}
|
||||
if len(rule.NetworkType) > 0 {
|
||||
if generateVersion < C.RuleSetVersion3 {
|
||||
return E.New("network_type rule item is only supported in version 3 or later")
|
||||
return E.New("`network_type` rule item is only supported in version 3 or later")
|
||||
}
|
||||
err = writeRuleItemUint8(writer, ruleItemNetworkType, rule.NetworkType)
|
||||
if err != nil {
|
||||
@@ -354,17 +403,67 @@ func writeDefaultRule(writer varbin.Writer, rule option.DefaultHeadlessRule, gen
|
||||
}
|
||||
}
|
||||
if rule.NetworkIsExpensive {
|
||||
if generateVersion < C.RuleSetVersion3 {
|
||||
return E.New("`network_is_expensive` rule item is only supported in version 3 or later")
|
||||
}
|
||||
err = binary.Write(writer, binary.BigEndian, ruleItemNetworkIsExpensive)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if rule.NetworkIsConstrained {
|
||||
if generateVersion < C.RuleSetVersion3 {
|
||||
return E.New("`network_is_constrained` rule item is only supported in version 3 or later")
|
||||
}
|
||||
err = binary.Write(writer, binary.BigEndian, ruleItemNetworkIsConstrained)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if rule.NetworkInterfaceAddress != nil && rule.NetworkInterfaceAddress.Size() > 0 {
|
||||
if generateVersion < C.RuleSetVersion4 {
|
||||
return E.New("`network_interface_address` rule item is only supported in version 4 or later")
|
||||
}
|
||||
err = writer.WriteByte(ruleItemNetworkInterfaceAddress)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = varbin.WriteUvarint(writer, uint64(rule.NetworkInterfaceAddress.Size()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, entry := range rule.NetworkInterfaceAddress.Entries() {
|
||||
err = binary.Write(writer, binary.BigEndian, uint8(entry.Key.Build()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, rawPrefix := range entry.Value {
|
||||
err = writePrefix(writer, rawPrefix.Build(netip.Prefix{}))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(rule.DefaultInterfaceAddress) > 0 {
|
||||
if generateVersion < C.RuleSetVersion4 {
|
||||
return E.New("`default_interface_address` rule item is only supported in version 4 or later")
|
||||
}
|
||||
err = writer.WriteByte(ruleItemDefaultInterfaceAddress)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = varbin.WriteUvarint(writer, uint64(len(rule.DefaultInterfaceAddress)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, rawPrefix := range rule.DefaultInterfaceAddress {
|
||||
err = writePrefix(writer, rawPrefix.Build(netip.Prefix{}))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(rule.WIFISSID) > 0 {
|
||||
err = writeRuleItemString(writer, ruleItemWIFISSID, rule.WIFISSID)
|
||||
if err != nil {
|
||||
|
||||
33
common/srs/ip_cidr.go
Normal file
33
common/srs/ip_cidr.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package srs
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"net/netip"
|
||||
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
"github.com/sagernet/sing/common/varbin"
|
||||
)
|
||||
|
||||
func readPrefix(reader varbin.Reader) (netip.Prefix, error) {
|
||||
addrSlice, err := varbin.ReadValue[[]byte](reader, binary.BigEndian)
|
||||
if err != nil {
|
||||
return netip.Prefix{}, err
|
||||
}
|
||||
prefixBits, err := varbin.ReadValue[uint8](reader, binary.BigEndian)
|
||||
if err != nil {
|
||||
return netip.Prefix{}, err
|
||||
}
|
||||
return netip.PrefixFrom(M.AddrFromIP(addrSlice), int(prefixBits)), nil
|
||||
}
|
||||
|
||||
func writePrefix(writer varbin.Writer, prefix netip.Prefix) error {
|
||||
err := varbin.Write(writer, binary.BigEndian, prefix.Addr().AsSlice())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = binary.Write(writer, binary.BigEndian, uint8(prefix.Bits()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user