package network import ( "fmt" "os/exec" "strings" ) // LinkDown sets admin state down without deconfiguring (ip link set down). func LinkDown(name string) error { out, err := exec.Command("ip", "link", "set", name, "down").CombinedOutput() if err != nil { return fmt.Errorf("ip link set down %s: %s", name, strings.TrimSpace(string(out))) } return nil } // LinkUp sets admin state up without re-running ifup (ip link set up). func LinkUp(name string) error { out, err := exec.Command("ip", "link", "set", name, "up").CombinedOutput() if err != nil { return fmt.Errorf("ip link set up %s: %s", name, strings.TrimSpace(string(out))) } return nil } // IfDown brings an interface down via ifdown --force. func IfDown(name string) error { out, err := exec.Command("ifdown", "--force", name).CombinedOutput() if err != nil { return fmt.Errorf("ifdown %s: %s", name, strings.TrimSpace(string(out))) } return nil } // IfUp brings an interface up via ifup --force. func IfUp(name string) error { out, err := exec.Command("ifup", "--force", name).CombinedOutput() if err != nil { return fmt.Errorf("ifup %s: %s", name, strings.TrimSpace(string(out))) } return nil } // IfRestart brings an interface down then up. func IfRestart(name string) error { _ = IfDown(name) return IfUp(name) } // ApplyPending merges pending configs into /etc/network/interfaces, // writes the file, and restarts affected interfaces. // Returns a per-interface error map (nil key = write error). func ApplyPending() map[string]error { errs := map[string]error{} pending := GetAllPending() if len(pending) == 0 { return errs } // Read current file config configs, err := ParseConfig() if err != nil { errs["__parse__"] = err return errs } // Merge for name, cfg := range pending { configs[name] = cfg } // Write file if err := WriteConfig(configs); err != nil { errs["__write__"] = err return errs } // Restart each changed interface for name := range pending { if name == "lo" { ClearPendingConfig(name) continue } // For VLAN interfaces ensure the kernel interface exists before ifup. if IsVLAN(name) { if err := EnsureVLANExists(name); err != nil { errs[name] = err continue } } _ = IfDown(name) if cfg := configs[name]; cfg != nil && cfg.Auto { if err := IfUp(name); err != nil { errs[name] = err continue } } ClearPendingConfig(name) } return errs }