MagiTrickle/pkg/ip-helper/ip-helper.go

119 lines
2.2 KiB
Go
Raw Normal View History

2024-08-25 02:55:22 +03:00
package ipHelper
import (
"bytes"
2024-08-27 03:07:58 +03:00
"errors"
2024-08-25 02:55:22 +03:00
"fmt"
"os/exec"
2024-08-27 03:07:58 +03:00
"slices"
"github.com/vishvananda/netlink"
"github.com/vishvananda/netlink/nl"
2024-08-25 02:55:22 +03:00
)
2024-08-27 03:07:58 +03:00
var (
ErrMaxTableSize = errors.New("max table size")
ErrMaxFwMarkSize = errors.New("max fwmark size")
)
func ExecIp(args ...string) ([]byte, error) {
2024-08-25 02:55:22 +03:00
cmd := exec.Command("ip", args...)
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
return nil, err
}
return out.Bytes(), nil
}
2024-08-27 03:07:58 +03:00
func GetUsedFwMarks() ([]uint32, error) {
markMap := make(map[uint32]struct{})
2024-08-25 02:55:22 +03:00
rules, err := netlink.RuleList(nl.FAMILY_ALL)
2024-08-25 02:55:22 +03:00
if err != nil {
return nil, fmt.Errorf("error while getting rules: %w", err)
}
for _, rule := range rules {
markMap[rule.Mark] = struct{}{}
2024-08-25 02:55:22 +03:00
}
2024-08-27 03:07:58 +03:00
marks := make([]uint32, len(markMap))
2024-08-25 02:55:22 +03:00
counter := 0
for mark, _ := range markMap {
marks[counter] = mark
counter++
}
return marks, nil
}
2024-08-30 04:09:28 +03:00
func GetUnusedFwMark(startFrom uint32) (uint32, error) {
2024-08-27 03:07:58 +03:00
usedFwMarks, err := GetUsedFwMarks()
if err != nil {
return 0, fmt.Errorf("error while getting used fwmarks: %w", err)
}
2024-08-30 04:09:28 +03:00
fwmark := startFrom
2024-08-27 03:07:58 +03:00
for slices.Contains(usedFwMarks, fwmark) {
fwmark++
if fwmark == 0xFFFFFFFF {
return 0, ErrMaxFwMarkSize
}
}
return fwmark, nil
}
func GetUsedTables() ([]int, error) {
tableMap := map[int]struct{}{
2024-08-25 02:55:22 +03:00
0: {},
253: {},
254: {},
255: {},
}
routes, err := netlink.RouteListFiltered(nl.FAMILY_ALL, &netlink.Route{}, netlink.RT_FILTER_TABLE)
2024-08-25 02:55:22 +03:00
if err != nil {
return nil, fmt.Errorf("error while getting routes: %w", err)
}
for _, route := range routes {
tableMap[route.Table] = struct{}{}
2024-08-27 03:07:58 +03:00
}
rules, err := netlink.RuleList(nl.FAMILY_ALL)
2024-08-27 03:07:58 +03:00
if err != nil {
return nil, fmt.Errorf("error while getting rules: %w", err)
}
for _, rule := range rules {
tableMap[rule.Table] = struct{}{}
2024-08-25 02:55:22 +03:00
}
tables := make([]int, len(tableMap))
2024-08-25 02:55:22 +03:00
counter := 0
for table, _ := range tableMap {
tables[counter] = table
counter++
}
return tables, nil
}
2024-08-27 03:07:58 +03:00
func GetUnusedTable(startFrom int) (int, error) {
2024-08-27 03:07:58 +03:00
usedTables, err := GetUsedTables()
if err != nil {
return 0, fmt.Errorf("error while getting used tables: %w", err)
}
2024-08-30 04:09:28 +03:00
tableID := startFrom
2024-08-27 03:07:58 +03:00
for slices.Contains(usedTables, tableID) {
tableID++
if tableID > 0x3FF {
return 0, ErrMaxTableSize
}
}
return tableID, nil
}