From c335a7cce6730d6a289d92818d0a57038aa39cf6 Mon Sep 17 00:00:00 2001 From: Vladimir Avtsenov Date: Wed, 4 Sep 2024 09:50:56 +0300 Subject: [PATCH] using netlink instead exec in ip-helper --- group.go | 2 +- pkg/ip-helper/ip-helper.go | 113 ++++++------------------------------- 2 files changed, 17 insertions(+), 98 deletions(-) diff --git a/group.go b/group.go index 34fcfd2..63c9f9f 100644 --- a/group.go +++ b/group.go @@ -16,7 +16,7 @@ import ( type GroupOptions struct { Enabled bool FWMark uint32 - Table uint16 + Table int } type Group struct { diff --git a/pkg/ip-helper/ip-helper.go b/pkg/ip-helper/ip-helper.go index 352a22d..0740474 100644 --- a/pkg/ip-helper/ip-helper.go +++ b/pkg/ip-helper/ip-helper.go @@ -1,16 +1,14 @@ package ipHelper import ( - "bufio" "bytes" "errors" "fmt" - "os" "os/exec" - "regexp" "slices" - "strconv" - "strings" + + "github.com/vishvananda/netlink" + "github.com/vishvananda/netlink/nl" ) var ( @@ -32,23 +30,13 @@ func ExecIp(args ...string) ([]byte, error) { func GetUsedFwMarks() ([]uint32, error) { markMap := make(map[uint32]struct{}) - out, err := ExecIp("rule", "show") + rules, err := netlink.RuleList(nl.FAMILY_ALL) if err != nil { return nil, fmt.Errorf("error while getting rules: %w", err) } - re := regexp.MustCompile(`fwmark\s+0x([0-9a-fA-F]+)`) - for _, line := range strings.Split(string(out), "\n") { - match := re.FindStringSubmatch(line) - if len(match) < 2 { - continue - } - - hexStr := match[1] - hexValue, err := strconv.ParseInt(hexStr, 16, 64) - if err == nil { - markMap[uint32(hexValue)] = struct{}{} - } + for _, rule := range rules { + markMap[rule.Mark] = struct{}{} } marks := make([]uint32, len(markMap)) @@ -77,102 +65,33 @@ func GetUnusedFwMark(startFrom uint32) (uint32, error) { return fwmark, nil } -func GetTableAliases() (map[string]uint16, error) { - tables := map[string]uint16{ - "unspec": 0, - "default": 253, - "main": 254, - "local": 255, - } - - file, err := os.Open("/opt/etc/iproute2/rt_tables") - if err != nil { - if os.IsNotExist(err) { - return tables, nil - } - return nil, err - } - defer file.Close() - - scanner := bufio.NewScanner(file) - for scanner.Scan() { - line := scanner.Text() - if strings.HasPrefix(line, "#") || len(strings.TrimSpace(line)) == 0 { - continue - } - - parts := strings.Fields(line) - if len(parts) >= 2 { - tableID, err := strconv.Atoi(parts[0]) - if err == nil { - tables[parts[1]] = uint16(tableID) - } - } - } - - if err := scanner.Err(); err != nil { - return nil, err - } - - return tables, nil -} - -func GetUsedTables() ([]uint16, error) { - tableMap := map[uint16]struct{}{ +func GetUsedTables() ([]int, error) { + tableMap := map[int]struct{}{ 0: {}, 253: {}, 254: {}, 255: {}, } - tableAliases, err := GetTableAliases() - if err != nil { - return nil, fmt.Errorf("error while getting table aliases: %w", err) - } - - out, err := ExecIp("route", "show", "table", "all") + routes, err := netlink.RouteListFiltered(nl.FAMILY_ALL, &netlink.Route{}, netlink.RT_FILTER_TABLE) if err != nil { return nil, fmt.Errorf("error while getting routes: %w", err) } - for _, line := range strings.Split(string(out), "\n") { - if strings.Contains(line, "table") { - parts := strings.Fields(line) - for i, part := range parts { - if part == "table" && i+1 < len(parts) { - tableNum, ok := tableAliases[parts[i+1]] - if !ok { - tableNumInt, _ := strconv.Atoi(parts[i+1]) - tableNum = uint16(tableNumInt) - } - tableMap[tableNum] = struct{}{} - } - } - } + for _, route := range routes { + tableMap[route.Table] = struct{}{} } - out, err = ExecIp("rule", "show") + rules, err := netlink.RuleList(nl.FAMILY_ALL) if err != nil { return nil, fmt.Errorf("error while getting rules: %w", err) } - for _, line := range strings.Split(string(out), "\n") { - if strings.Contains(line, "lookup") { - parts := strings.Fields(line) - for i, part := range parts { - if part == "lookup" && i+1 < len(parts) { - tableNum, ok := tableAliases[parts[i+1]] - if !ok { - tableNumInt, _ := strconv.Atoi(parts[i+1]) - tableNum = uint16(tableNumInt) - } - tableMap[tableNum] = struct{}{} - } - } - } + for _, rule := range rules { + tableMap[rule.Table] = struct{}{} } - tables := make([]uint16, len(tableMap)) + tables := make([]int, len(tableMap)) counter := 0 for table, _ := range tableMap { tables[counter] = table @@ -182,7 +101,7 @@ func GetUsedTables() ([]uint16, error) { return tables, nil } -func GetUnusedTable(startFrom uint16) (uint16, error) { +func GetUnusedTable(startFrom int) (int, error) { usedTables, err := GetUsedTables() if err != nil { return 0, fmt.Errorf("error while getting used tables: %w", err)