//go:build linux package network import ( "fmt" "net" "strings" "github.com/vishvananda/netlink" ) // InterfaceInfo contains basic information about a network interface. type InterfaceInfo struct { Name string Index int } // ListInterfaces returns a list of all network interfaces present in the current namespace. func ListInterfaces() ([]InterfaceInfo, error) { links, err := netlink.LinkList() if err != nil { return nil, fmt.Errorf("failed to list interfaces: %w", err) } var interfaces []InterfaceInfo for _, link := range links { interfaces = append(interfaces, InterfaceInfo{ Name: link.Attrs().Name, Index: link.Attrs().Index, }) } return interfaces, nil } // ConfigureInterface sets the MTU, brings the interface up, assigns an IP address, // and configures the default route. func ConfigureInterface(name, address string, mtu int) error { link, err := netlink.LinkByName(name) if err != nil { return fmt.Errorf("failed to find link %s: %w", name, err) } if err := netlink.LinkSetMTU(link, mtu); err != nil { return fmt.Errorf("failed to set MTU %d on link %s: %w", mtu, name, err) } if err := netlink.LinkSetUp(link); err != nil { return fmt.Errorf("failed to bring up link %s: %w", name, err) } addr, err := netlink.ParseAddr(address) if err != nil { return fmt.Errorf("invalid IP address %s: %w", address, err) } if err := netlink.AddrAdd(link, addr); err != nil { if !strings.Contains(err.Error(), "file exists") { return fmt.Errorf("failed to add address %s to link %s: %w", address, name, err) } } var dst *net.IPNet if addr.IP.To4() != nil { _, dst, _ = net.ParseCIDR("0.0.0.0/0") } else { _, dst, _ = net.ParseCIDR("::/0") } route := &netlink.Route{ Scope: netlink.SCOPE_UNIVERSE, LinkIndex: link.Attrs().Index, Dst: dst, } if err := netlink.RouteAdd(route); err != nil { if err := netlink.RouteReplace(route); err != nil { return fmt.Errorf("failed to configure default route via %s: %w", name, err) } } return nil }