package app import ( "context" "errors" "fmt" "os/exec" "strings" "time" ) // --------------------------------------------------------------------- // низкоуровневые helpers // --------------------------------------------------------------------- // EN: Low-level command execution adapters with timeout handling and small // EN: policy-route verification helper used by higher-level handlers. // RU: Низкоуровневые адаптеры запуска команд с таймаутами и вспомогательной // RU: проверкой policy-route, используемой верхнеуровневыми обработчиками. func runCommand(name string, args ...string) (string, string, int, error) { return runCommandTimeout(60*time.Second, name, args...) } // --------------------------------------------------------------------- // policy route check // --------------------------------------------------------------------- func checkPolicyRoute(iface, table string) (bool, error) { stdout, _, exitCode, err := runCommand("ip", "route", "show", "table", table) if exitCode != 0 { if err == nil { err = fmt.Errorf("ip route show exited with %d", exitCode) } return false, err } want := fmt.Sprintf("default dev %s", iface) for _, line := range strings.Split(stdout, "\n") { line = strings.TrimSpace(line) if strings.HasPrefix(line, want) { return true, nil } } return false, nil } // --------------------------------------------------------------------- // command timeout helper // --------------------------------------------------------------------- func runCommandTimeout(timeout time.Duration, name string, args ...string) (string, string, int, error) { ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() cmd := exec.CommandContext(ctx, name, args...) out, err := cmd.CombinedOutput() stdout := string(out) stderr := stdout exitCode := 0 if err != nil { if ee, ok := err.(*exec.ExitError); ok { exitCode = ee.ExitCode() } else if errors.Is(err, context.DeadlineExceeded) { exitCode = -1 err = fmt.Errorf("command timeout: %w", err) } else { exitCode = -1 } } return stdout, stderr, exitCode, err }