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"
|
2024-09-04 09:50:56 +03:00
|
|
|
|
|
|
|
"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
|
|
|
|
2024-09-04 09:50:56 +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)
|
|
|
|
}
|
|
|
|
|
2024-09-04 09:50:56 +03:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2024-09-04 09:50:56 +03:00
|
|
|
func GetUsedTables() ([]int, error) {
|
|
|
|
tableMap := map[int]struct{}{
|
2024-08-25 02:55:22 +03:00
|
|
|
0: {},
|
|
|
|
253: {},
|
|
|
|
254: {},
|
|
|
|
255: {},
|
|
|
|
}
|
|
|
|
|
2024-09-04 09:50:56 +03:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2024-09-04 09:50:56 +03:00
|
|
|
for _, route := range routes {
|
|
|
|
tableMap[route.Table] = struct{}{}
|
2024-08-27 03:07:58 +03:00
|
|
|
}
|
|
|
|
|
2024-09-04 09:50:56 +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)
|
|
|
|
}
|
|
|
|
|
2024-09-04 09:50:56 +03:00
|
|
|
for _, rule := range rules {
|
|
|
|
tableMap[rule.Table] = struct{}{}
|
2024-08-25 02:55:22 +03:00
|
|
|
}
|
|
|
|
|
2024-09-04 09:50:56 +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
|
|
|
|
2024-09-04 09:50:56 +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
|
|
|
|
}
|