Files
elmprodvpn/selective-vpn-api/app/routes_cache_helpers_routes.go

96 lines
2.1 KiB
Go

package app
import (
"fmt"
"strings"
"time"
)
func readCurrentRoutesTableLines() ([]string, error) {
out, _, code, err := runCommandTimeout(5*time.Second, "ip", "-4", "route", "show", "table", routesTableName())
if err != nil && code != 0 {
return nil, err
}
lines := make([]string, 0, 32)
for _, raw := range strings.Split(out, "\n") {
ln := strings.TrimSpace(raw)
if ln == "" {
continue
}
lines = append(lines, ln)
}
return lines, nil
}
func detectIfaceFromRoutes(lines []string) string {
for _, ln := range lines {
fields := strings.Fields(ln)
for i := 0; i+1 < len(fields); i++ {
if fields[i] == "dev" {
return strings.TrimSpace(fields[i+1])
}
}
}
return ""
}
func restoreRouteLine(line string) error {
fields := strings.Fields(strings.TrimSpace(line))
if len(fields) == 0 {
return nil
}
args := []string{"-4", "route", "replace"}
args = append(args, fields...)
hasTable := false
for i := 0; i+1 < len(fields); i++ {
if fields[i] == "table" {
hasTable = true
break
}
}
if !hasTable {
args = append(args, "table", routesTableName())
}
_, _, code, err := runCommandTimeout(5*time.Second, "ip", args...)
if err != nil || code != 0 {
if err == nil {
err = fmt.Errorf("exit code %d", code)
}
return err
}
return nil
}
func shouldIgnoreRestoreRouteError(line string, err error) bool {
ln := strings.ToLower(strings.TrimSpace(line))
if strings.Contains(ln, " linkdown") {
return true
}
dev := routeLineDevice(ln)
if dev != "" && !strings.HasPrefix(ln, "default ") && !ifaceExists(dev) {
return true
}
msg := strings.ToLower(strings.TrimSpace(fmt.Sprintf("%v", err)))
if strings.HasPrefix(ln, "default ") {
return false
}
if strings.Contains(msg, "cannot find device") ||
strings.Contains(msg, "no such device") ||
strings.Contains(msg, "network is down") {
return true
}
return false
}
func routeLineDevice(line string) string {
fields := strings.Fields(strings.TrimSpace(line))
for i := 0; i+1 < len(fields); i++ {
if fields[i] == "dev" {
return strings.TrimSpace(fields[i+1])
}
}
return ""
}