mirror of
https://github.com/daeuniverse/dae.git
synced 2025-01-03 21:40:36 +07:00
159 lines
5.7 KiB
Go
159 lines
5.7 KiB
Go
/*
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
* Copyright (c) 2022-2024, daeuniverse Organization <dae@v2raya.org>
|
|
*/
|
|
|
|
package routing
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
"net/netip"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/daeuniverse/dae/common"
|
|
"github.com/daeuniverse/dae/common/consts"
|
|
"github.com/daeuniverse/dae/pkg/config_parser"
|
|
"github.com/sirupsen/logrus"
|
|
"golang.org/x/exp/constraints"
|
|
)
|
|
|
|
type FunctionParser func(log *logrus.Logger, f *config_parser.Function, key string, paramValueGroup []string, overrideOutbound *Outbound) (err error)
|
|
|
|
// Preset function parser factories.
|
|
|
|
// PlainParserFactory is for style unity.
|
|
func PlainParserFactory(callback func(f *config_parser.Function, key string, paramValueGroup []string, overrideOutbound *Outbound) (err error)) FunctionParser {
|
|
return func(log *logrus.Logger, f *config_parser.Function, key string, paramValueGroup []string, overrideOutbound *Outbound) (err error) {
|
|
return callback(f, key, paramValueGroup, overrideOutbound)
|
|
}
|
|
}
|
|
|
|
// EmptyKeyPlainParserFactory only accepts function with empty key.
|
|
func EmptyKeyPlainParserFactory(callback func(f *config_parser.Function, values []string, overrideOutbound *Outbound) (err error)) FunctionParser {
|
|
return func(log *logrus.Logger, f *config_parser.Function, key string, paramValueGroup []string, overrideOutbound *Outbound) (err error) {
|
|
if key != "" {
|
|
return fmt.Errorf("this function cannot accept a key")
|
|
}
|
|
return callback(f, paramValueGroup, overrideOutbound)
|
|
}
|
|
}
|
|
|
|
func IpParserFactory(callback func(f *config_parser.Function, cidrs []netip.Prefix, overrideOutbound *Outbound) (err error)) FunctionParser {
|
|
return func(log *logrus.Logger, f *config_parser.Function, key string, paramValueGroup []string, overrideOutbound *Outbound) (err error) {
|
|
cidrs, err := parsePrefixes(paramValueGroup)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return callback(f, cidrs, overrideOutbound)
|
|
}
|
|
}
|
|
|
|
func MacParserFactory(callback func(f *config_parser.Function, macAddrs [][6]byte, overrideOutbound *Outbound) (err error)) FunctionParser {
|
|
return func(log *logrus.Logger, f *config_parser.Function, key string, paramValueGroup []string, overrideOutbound *Outbound) (err error) {
|
|
var macAddrs [][6]byte
|
|
for _, v := range paramValueGroup {
|
|
mac, err := common.ParseMac(v)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
macAddrs = append(macAddrs, mac)
|
|
}
|
|
return callback(f, macAddrs, overrideOutbound)
|
|
}
|
|
}
|
|
|
|
func PortRangeParserFactory(callback func(f *config_parser.Function, portRanges [][2]uint16, overrideOutbound *Outbound) (err error)) FunctionParser {
|
|
return func(log *logrus.Logger, f *config_parser.Function, key string, paramValueGroup []string, overrideOutbound *Outbound) (err error) {
|
|
var portRanges [][2]uint16
|
|
for _, v := range paramValueGroup {
|
|
portRange, err := common.ParsePortRange(v)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
portRanges = append(portRanges, portRange)
|
|
}
|
|
return callback(f, portRanges, overrideOutbound)
|
|
}
|
|
}
|
|
|
|
func L4ProtoParserFactory(callback func(f *config_parser.Function, l4protoType consts.L4ProtoType, overrideOutbound *Outbound) (err error)) FunctionParser {
|
|
return func(log *logrus.Logger, f *config_parser.Function, key string, paramValueGroup []string, overrideOutbound *Outbound) (err error) {
|
|
var l4protoType consts.L4ProtoType
|
|
for _, v := range paramValueGroup {
|
|
switch v {
|
|
case "tcp":
|
|
l4protoType |= consts.L4ProtoType_TCP
|
|
case "udp":
|
|
l4protoType |= consts.L4ProtoType_UDP
|
|
}
|
|
}
|
|
return callback(f, l4protoType, overrideOutbound)
|
|
}
|
|
}
|
|
|
|
func IpVersionParserFactory(callback func(f *config_parser.Function, ipVersion consts.IpVersionType, overrideOutbound *Outbound) (err error)) FunctionParser {
|
|
return func(log *logrus.Logger, f *config_parser.Function, key string, paramValueGroup []string, overrideOutbound *Outbound) (err error) {
|
|
var ipVersion consts.IpVersionType
|
|
for _, v := range paramValueGroup {
|
|
switch v {
|
|
case "4":
|
|
ipVersion |= consts.IpVersion_4
|
|
case "6":
|
|
ipVersion |= consts.IpVersion_6
|
|
}
|
|
}
|
|
return callback(f, ipVersion, overrideOutbound)
|
|
}
|
|
}
|
|
|
|
func ProcessNameParserFactory(callback func(f *config_parser.Function, procNames [][consts.TaskCommLen]byte, overrideOutbound *Outbound) (err error)) FunctionParser {
|
|
return func(log *logrus.Logger, f *config_parser.Function, key string, paramValueGroup []string, overrideOutbound *Outbound) (err error) {
|
|
var procNames [][consts.TaskCommLen]byte
|
|
for _, v := range paramValueGroup {
|
|
if len([]byte(v)) > consts.TaskCommLen {
|
|
log.Infof(`pname routing: trim "%v" to "%v" because it is too long.`, v, string([]byte(v)[:consts.TaskCommLen]))
|
|
}
|
|
procNames = append(procNames, toProcessName(v))
|
|
}
|
|
return callback(f, procNames, overrideOutbound)
|
|
}
|
|
}
|
|
|
|
func parsePrefixes(values []string) (cidrs []netip.Prefix, err error) {
|
|
for _, value := range values {
|
|
toParse := value
|
|
if strings.LastIndexByte(value, '/') == -1 {
|
|
toParse += "/32"
|
|
}
|
|
prefix, err := netip.ParsePrefix(toParse)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("cannot parse %v: %w", value, err)
|
|
}
|
|
cidrs = append(cidrs, prefix)
|
|
}
|
|
return cidrs, nil
|
|
}
|
|
|
|
func toProcessName(processName string) (procName [consts.TaskCommLen]byte) {
|
|
n := []byte(processName)
|
|
copy(procName[:], n)
|
|
return procName
|
|
}
|
|
|
|
func UintParserFactory[T constraints.Unsigned](callback func(f *config_parser.Function, values []T, overrideOutbound *Outbound) (err error)) FunctionParser {
|
|
size := binary.Size(new(T))
|
|
return func(log *logrus.Logger, f *config_parser.Function, key string, paramValueGroup []string, overrideOutbound *Outbound) (err error) {
|
|
var values []T
|
|
for _, v := range paramValueGroup {
|
|
val, err := strconv.ParseUint(v, 0, 8*size)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot parse %v: %w", v, err)
|
|
}
|
|
values = append(values, T(val))
|
|
}
|
|
return callback(f, values, overrideOutbound)
|
|
}
|
|
}
|