summaryrefslogtreecommitdiff
path: root/internal/network/network.go
blob: 6afcf5e29d8a94106bf4805bffe14752e0bafac4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//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
}