mirror of
https://github.com/fosrl/olm.git
synced 2026-02-08 05:56:41 +00:00
283 lines
7.2 KiB
Go
283 lines
7.2 KiB
Go
package network
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"os/exec"
|
|
"runtime"
|
|
"strings"
|
|
|
|
"github.com/fosrl/newt/logger"
|
|
"github.com/vishvananda/netlink"
|
|
)
|
|
|
|
func DarwinAddRoute(destination string, gateway string, interfaceName string) error {
|
|
if runtime.GOOS != "darwin" {
|
|
return nil
|
|
}
|
|
|
|
var cmd *exec.Cmd
|
|
|
|
if gateway != "" {
|
|
// Route with specific gateway
|
|
cmd = exec.Command("route", "-q", "-n", "add", "-inet", destination, "-gateway", gateway)
|
|
} else if interfaceName != "" {
|
|
// Route via interface
|
|
cmd = exec.Command("route", "-q", "-n", "add", "-inet", destination, "-interface", interfaceName)
|
|
} else {
|
|
return fmt.Errorf("either gateway or interface must be specified")
|
|
}
|
|
|
|
logger.Info("Running command: %v", cmd)
|
|
|
|
out, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
return fmt.Errorf("route command failed: %v, output: %s", err, out)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func DarwinRemoveRoute(destination string) error {
|
|
if runtime.GOOS != "darwin" {
|
|
return nil
|
|
}
|
|
|
|
cmd := exec.Command("route", "-q", "-n", "delete", "-inet", destination)
|
|
logger.Info("Running command: %v", cmd)
|
|
|
|
out, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
return fmt.Errorf("route delete command failed: %v, output: %s", err, out)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func LinuxAddRoute(destination string, gateway string, interfaceName string) error {
|
|
if runtime.GOOS != "linux" {
|
|
return nil
|
|
}
|
|
|
|
// Parse destination CIDR
|
|
_, ipNet, err := net.ParseCIDR(destination)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid destination address: %v", err)
|
|
}
|
|
|
|
// Create route
|
|
route := &netlink.Route{
|
|
Dst: ipNet,
|
|
}
|
|
|
|
if gateway != "" {
|
|
// Route with specific gateway
|
|
gw := net.ParseIP(gateway)
|
|
if gw == nil {
|
|
return fmt.Errorf("invalid gateway address: %s", gateway)
|
|
}
|
|
route.Gw = gw
|
|
logger.Info("Adding route to %s via gateway %s", destination, gateway)
|
|
} else if interfaceName != "" {
|
|
// Route via interface
|
|
link, err := netlink.LinkByName(interfaceName)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get interface %s: %v", interfaceName, err)
|
|
}
|
|
route.LinkIndex = link.Attrs().Index
|
|
logger.Info("Adding route to %s via interface %s", destination, interfaceName)
|
|
} else {
|
|
return fmt.Errorf("either gateway or interface must be specified")
|
|
}
|
|
|
|
// Add the route
|
|
if err := netlink.RouteAdd(route); err != nil {
|
|
return fmt.Errorf("failed to add route: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func LinuxRemoveRoute(destination string) error {
|
|
if runtime.GOOS != "linux" {
|
|
return nil
|
|
}
|
|
|
|
// Parse destination CIDR
|
|
_, ipNet, err := net.ParseCIDR(destination)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid destination address: %v", err)
|
|
}
|
|
|
|
// Create route to delete
|
|
route := &netlink.Route{
|
|
Dst: ipNet,
|
|
}
|
|
|
|
logger.Info("Removing route to %s", destination)
|
|
|
|
// Delete the route
|
|
if err := netlink.RouteDel(route); err != nil {
|
|
return fmt.Errorf("failed to delete route: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// addRouteForServerIP adds an OS-specific route for the server IP
|
|
func AddRouteForServerIP(serverIP, interfaceName string) error {
|
|
if err := AddRouteForNetworkConfig(serverIP); err != nil {
|
|
return err
|
|
}
|
|
if interfaceName == "" {
|
|
return nil
|
|
}
|
|
if runtime.GOOS == "darwin" {
|
|
return DarwinAddRoute(serverIP, "", interfaceName)
|
|
}
|
|
// else if runtime.GOOS == "windows" {
|
|
// return WindowsAddRoute(serverIP, "", interfaceName)
|
|
// } else if runtime.GOOS == "linux" {
|
|
// return LinuxAddRoute(serverIP, "", interfaceName)
|
|
// }
|
|
return nil
|
|
}
|
|
|
|
// removeRouteForServerIP removes an OS-specific route for the server IP
|
|
func RemoveRouteForServerIP(serverIP string, interfaceName string) error {
|
|
if err := RemoveRouteForNetworkConfig(serverIP); err != nil {
|
|
return err
|
|
}
|
|
if interfaceName == "" {
|
|
return nil
|
|
}
|
|
if runtime.GOOS == "darwin" {
|
|
return DarwinRemoveRoute(serverIP)
|
|
}
|
|
// else if runtime.GOOS == "windows" {
|
|
// return WindowsRemoveRoute(serverIP)
|
|
// } else if runtime.GOOS == "linux" {
|
|
// return LinuxRemoveRoute(serverIP)
|
|
// }
|
|
return nil
|
|
}
|
|
|
|
func AddRouteForNetworkConfig(destination string) error {
|
|
// Parse the subnet to extract IP and mask
|
|
_, ipNet, err := net.ParseCIDR(destination)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to parse subnet %s: %v", destination, err)
|
|
}
|
|
|
|
// Convert CIDR mask to dotted decimal format (e.g., 255.255.255.0)
|
|
mask := net.IP(ipNet.Mask).String()
|
|
destinationAddress := ipNet.IP.String()
|
|
|
|
AddIPv4IncludedRoute(IPv4Route{DestinationAddress: destinationAddress, SubnetMask: mask})
|
|
|
|
return nil
|
|
}
|
|
|
|
func RemoveRouteForNetworkConfig(destination string) error {
|
|
// Parse the subnet to extract IP and mask
|
|
_, ipNet, err := net.ParseCIDR(destination)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to parse subnet %s: %v", destination, err)
|
|
}
|
|
|
|
// Convert CIDR mask to dotted decimal format (e.g., 255.255.255.0)
|
|
mask := net.IP(ipNet.Mask).String()
|
|
destinationAddress := ipNet.IP.String()
|
|
|
|
RemoveIPv4IncludedRoute(IPv4Route{DestinationAddress: destinationAddress, SubnetMask: mask})
|
|
|
|
return nil
|
|
}
|
|
|
|
// addRoutes adds routes for each subnet in RemoteSubnets
|
|
func AddRoutes(remoteSubnets []string, interfaceName string) error {
|
|
if len(remoteSubnets) == 0 {
|
|
return nil
|
|
}
|
|
|
|
// Add routes for each subnet
|
|
for _, subnet := range remoteSubnets {
|
|
subnet = strings.TrimSpace(subnet)
|
|
if subnet == "" {
|
|
continue
|
|
}
|
|
|
|
if err := AddRouteForNetworkConfig(subnet); err != nil {
|
|
logger.Error("Failed to add network config for subnet %s: %v", subnet, err)
|
|
continue
|
|
}
|
|
|
|
// Add route based on operating system
|
|
if interfaceName == "" {
|
|
continue
|
|
}
|
|
|
|
if runtime.GOOS == "darwin" {
|
|
if err := DarwinAddRoute(subnet, "", interfaceName); err != nil {
|
|
logger.Error("Failed to add Darwin route for subnet %s: %v", subnet, err)
|
|
return err
|
|
}
|
|
} else if runtime.GOOS == "windows" {
|
|
if err := WindowsAddRoute(subnet, "", interfaceName); err != nil {
|
|
logger.Error("Failed to add Windows route for subnet %s: %v", subnet, err)
|
|
return err
|
|
}
|
|
} else if runtime.GOOS == "linux" {
|
|
if err := LinuxAddRoute(subnet, "", interfaceName); err != nil {
|
|
logger.Error("Failed to add Linux route for subnet %s: %v", subnet, err)
|
|
return err
|
|
}
|
|
}
|
|
|
|
logger.Info("Added route for remote subnet: %s", subnet)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// removeRoutesForRemoteSubnets removes routes for each subnet in RemoteSubnets
|
|
func RemoveRoutes(remoteSubnets []string) error {
|
|
if len(remoteSubnets) == 0 {
|
|
return nil
|
|
}
|
|
|
|
// Remove routes for each subnet
|
|
for _, subnet := range remoteSubnets {
|
|
subnet = strings.TrimSpace(subnet)
|
|
if subnet == "" {
|
|
continue
|
|
}
|
|
|
|
if err := RemoveRouteForNetworkConfig(subnet); err != nil {
|
|
logger.Error("Failed to remove network config for subnet %s: %v", subnet, err)
|
|
continue
|
|
}
|
|
|
|
// Remove route based on operating system
|
|
if runtime.GOOS == "darwin" {
|
|
if err := DarwinRemoveRoute(subnet); err != nil {
|
|
logger.Error("Failed to remove Darwin route for subnet %s: %v", subnet, err)
|
|
return err
|
|
}
|
|
} else if runtime.GOOS == "windows" {
|
|
if err := WindowsRemoveRoute(subnet); err != nil {
|
|
logger.Error("Failed to remove Windows route for subnet %s: %v", subnet, err)
|
|
return err
|
|
}
|
|
} else if runtime.GOOS == "linux" {
|
|
if err := LinuxRemoveRoute(subnet); err != nil {
|
|
logger.Error("Failed to remove Linux route for subnet %s: %v", subnet, err)
|
|
return err
|
|
}
|
|
}
|
|
|
|
logger.Info("Removed route for remote subnet: %s", subnet)
|
|
}
|
|
|
|
return nil
|
|
}
|