diff --git a/.gitignore b/.gitignore index 0375e81..e69de29 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +0,0 @@ -hosts/ diff --git a/configuration.go b/configuration.go index f3cd7bd..0a184e4 100644 --- a/configuration.go +++ b/configuration.go @@ -3,6 +3,7 @@ package s6netdev import ( "fmt" "net" + "net/netip" "strings" ) @@ -128,7 +129,7 @@ func (t *S6SvcTree) NetdevIfaceProp(iface Iface, p Property) *S6Svc { return l } -func (t *S6SvcTree) ConfigureIfaceAddr(iface Iface, addr string) *S6Svc { +func (t *S6SvcTree) NetdevConfigureIfaceMAC(iface Iface, addr net.HardwareAddr) *S6Svc { svc_name := S6SvcName(fmt.Sprintf("interface.%s.ether.addr", iface.Name)).Sanitize() l := t.S6New(svc_name, &S6SvcTypes.Oneshot) @@ -138,7 +139,7 @@ func (t *S6SvcTree) ConfigureIfaceAddr(iface Iface, addr string) *S6Svc { ExeclineXDGConfig(), ExeclineXDGEnvdirConfig(l.Name), ExeclineDefine("INTERFACE", iface.Name), - ExeclineImportas("ADDRESS", false, addr), + ExeclineImportas("ADDRESS", false, addr.String()), "ip link set $INTERFACE address $ADDRESS", }, "\n") @@ -177,7 +178,7 @@ func (t *S6SvcTree) NetdevIfaceDHCP(iface Iface, ipv int) *S6Svc { if ipv == 6 { daemon = fmt.Sprintf("%s%d", daemon, ipv) } - l.Up = strings.Join([]string{ + l.Run = strings.Join([]string{ NETDEV_EXECLINE_HEADER, ExeclineDefine("INTERFACE", iface.Name), "fdmove -c 2 1", @@ -191,7 +192,7 @@ func (t *S6SvcTree) NetdevIfaceDHCP(iface Iface, ipv int) *S6Svc { return l } -func (t *S6SvcTree) netdevIfaceAddrTemplate(action, iface string, ipv int, addr net.IP) string { +func (t *S6SvcTree) netdevIfaceAddrTemplate(action, iface string, ipv int, addr netip.Prefix) string { return strings.Join([]string{ NETDEV_EXECLINE_HEADER, ExeclineDefine("INTERFACE", iface), @@ -201,8 +202,8 @@ func (t *S6SvcTree) netdevIfaceAddrTemplate(action, iface string, ipv int, addr }, "\n") } -func (t *S6SvcTree) NetdevIfaceAddr(iface Iface, addr net.IP) *S6Svc { - ipv := NetdevIPAddrVer(addr) +func (t *S6SvcTree) NetdevIfaceAddr(iface Iface, addr netip.Prefix) *S6Svc { + ipv := NetdevIPAddrVer(addr.Addr()) svc_name := S6SvcName(fmt.Sprintf("interface.%s.ip.addr.%d.%s", iface.Name, ipv, addr)).Sanitize() l := t.S6New(svc_name, &S6SvcTypes.Oneshot) @@ -223,7 +224,7 @@ func (t *S6SvcTree) netdevRouteTemplate(iface Iface, route Route) (up, down stri cmd = []string{ "ip", - fmt.Sprintf("-%d", NetdevIPAddrVer(route.Net.IP)), // IP version + fmt.Sprintf("-%d", NetdevIPAddrVer(route.Net.Addr())), // IP version "route", "%s", } @@ -247,7 +248,7 @@ func (t *S6SvcTree) netdevRouteTemplate(iface Iface, route Route) (up, down stri cmd = append(cmd, "$ROUTE") svcname = append(svcname, r) - if route.Via != nil { + if route.Via.IsValid() { lines = append(lines, ExeclineImportas("VIA", false, route.Via.String())) cmd = append(cmd, "via", "$VIA") } diff --git a/hosts/generic/main.go b/hosts/generic/main.go new file mode 100644 index 0000000..6bf7034 --- /dev/null +++ b/hosts/generic/main.go @@ -0,0 +1,55 @@ +package main + +import ( + "log" + "net/netip" + "os" + + "git.redxen.eu/caskd/s6-netdev" +) + +func main() { + var ( + err error + l = log.New(os.Stderr, "s6-netdev: ", log.Ltime|log.Lshortfile|log.Lmsgprefix) + ) + t := s6netdev.S6NewTree() + + // Main VRF + main_vrf := s6netdev.Iface{ + Name: "vrf-main", + Type: &s6netdev.NetdevIfTypes.Vrf, + Slaves: []*s6netdev.Iface{ + { + Name: "br-main", + Type: &s6netdev.NetdevIfTypes.Bridge, + Routes: []s6netdev.Route{ + { + Net: netip.MustParsePrefix("fd00::/64"), + }, + }, + Properties: []s6netdev.Property{ + {Key: "stp_state", Value: "1", Default: "0"}, + {Key: "mcast_snooping", Value: "0", Default: "1"}, + }, + Slaves: []*s6netdev.Iface{ + { + Name: "enp1s0", + Type: &s6netdev.NetdevIfTypes.Phys, + }, + }, + }, + }, + } + t.NavServices(main_vrf) + + for _, v := range t.S6Services() { + if s6netdev.NetdevIsDummy(v.Name) { + continue + } + l.Printf("Commiting %s\n", v.Name) + if err = t.S6CommitService(v); err != nil { + l.Fatalf("Failed to commit %s, %s\n", v.Name, err) + } + } +} diff --git a/hosts/thetford-mines.canada/main.go b/hosts/thetford-mines.canada/main.go new file mode 100644 index 0000000..0d77f6a --- /dev/null +++ b/hosts/thetford-mines.canada/main.go @@ -0,0 +1,184 @@ +package main + +import ( + "log" + "net" + "net/netip" + "os" + + "git.redxen.eu/caskd/s6-netdev" +) + +func main() { + var ( + err error + l = log.New(os.Stderr, "s6-netdev: ", log.Ltime|log.Lshortfile|log.Lmsgprefix) + ) + t := s6netdev.S6NewTree() + + // No VRF + phys := s6netdev.Iface{ + Name: "phys", + Type: &s6netdev.NetdevIfTypes.Bridge, + MACAddr: net.HardwareAddr{0x52, 0x54, 0x00, 0x81, 0xcb, 0x62}, + DHCP: s6netdev.DHCP_IP{V4: true}, + Properties: []s6netdev.Property{ + {Key: "stp_state", Value: "1", Default: "0"}, + {Key: "mcast_snooping", Value: "0", Default: "1"}, + }, + Slaves: []*s6netdev.Iface{ + { + Name: "enp12s0", + Type: &s6netdev.NetdevIfTypes.Phys, + }, + }, + } + t.NavServices(phys) + + // DN42 VRF + vrf_dn42 := s6netdev.Iface{ + Name: "vrf-dn42", + Type: &s6netdev.NetdevIfTypes.Vrf, + Table: 20, + Slaves: []*s6netdev.Iface{ + { + Name: "br-dn42", + Type: &s6netdev.NetdevIfTypes.Bridge, + Properties: []s6netdev.Property{ + {Key: "stp_state", Value: "0", Default: "0"}, + {Key: "mcast_snooping", Value: "0", Default: "1"}, + }, + Slaves: []*s6netdev.Iface{ + { + Name: "enp15s0", + Type: &s6netdev.NetdevIfTypes.Phys, + }, + { + Name: "phys.42", + Type: &s6netdev.NetdevIfTypes.Vlan, + VlanId: 42, + Parent: &phys, + }, + }, + }, + }, + } + t.NavServices(vrf_dn42) + + // V6 VRF + vrf_v6 := s6netdev.Iface{ + Name: "vrf-v6", + Type: &s6netdev.NetdevIfTypes.Vrf, + Table: 10, + Slaves: []*s6netdev.Iface{ + { + Name: "vultrbgp", + Type: &s6netdev.NetdevIfTypes.Wireguard, + Addresses: []netip.Prefix{ + netip.MustParsePrefix("fe80::2/64"), + }, + }, + { + Name: "b00b", + Type: &s6netdev.NetdevIfTypes.Bridge, + MACAddr: net.HardwareAddr{0x02, 0x00, 0x00, 0x01, 0xb0, 0x0b}, + Addresses: []netip.Prefix{ + netip.MustParsePrefix("2a04:5b81:2060:b00b::2/64"), + }, + Slaves: []*s6netdev.Iface{ + { + Name: "phys.66", + Type: &s6netdev.NetdevIfTypes.Vlan, + VlanId: 66, + Parent: &phys, + }, + { + Name: "enp9s0", + Type: &s6netdev.NetdevIfTypes.Phys, + }, + }, + Sysctls: s6netdev.Sysctl_IP{ + V6: []s6netdev.Property{ + {Key: "forwarding", Value: "0", Default: "0"}, + {Key: "autoconf", Value: "0", Default: "0"}, + }, + }, + Properties: []s6netdev.Property{ + {Key: "stp_state", Value: "0", Default: "0"}, + {Key: "mcast_snooping", Value: "0", Default: "1"}, + }, + }, + { + Name: "f33d", + Type: &s6netdev.NetdevIfTypes.Bridge, + MACAddr: net.HardwareAddr{0x02, 0x00, 0x00, 0x01, 0xf3, 0x3d}, + Addresses: []netip.Prefix{ + netip.MustParsePrefix("2a04:5b81:2060:f33d::2/64"), + }, + Slaves: []*s6netdev.Iface{ + { + Name: "phys.100", + Type: &s6netdev.NetdevIfTypes.Vlan, + VlanId: 100, + Parent: &phys, + }, + { + Name: "enp14s0", + Type: &s6netdev.NetdevIfTypes.Phys, + }, + }, + Sysctls: s6netdev.Sysctl_IP{ + V6: []s6netdev.Property{ + {Key: "forwarding", Value: "0", Default: "0"}, + {Key: "autoconf", Value: "0", Default: "0"}, + }, + }, + Properties: []s6netdev.Property{ + {Key: "stp_state", Value: "0", Default: "0"}, + {Key: "mcast_snooping", Value: "0", Default: "1"}, + }, + }, + { + Name: "d00d", + Type: &s6netdev.NetdevIfTypes.Bridge, + MACAddr: net.HardwareAddr{0x02, 0x00, 0x00, 0x01, 0xd0, 0x0d}, + Addresses: []netip.Prefix{ + netip.MustParsePrefix("2a04:5b81:2060:d00d::2/64"), + }, + Slaves: []*s6netdev.Iface{ + { + Name: "phys.101", + Type: &s6netdev.NetdevIfTypes.Vlan, + VlanId: 101, + Parent: &phys, + }, + { + Name: "enp13s0", + Type: &s6netdev.NetdevIfTypes.Phys, + }, + }, + Sysctls: s6netdev.Sysctl_IP{ + V6: []s6netdev.Property{ + {Key: "forwarding", Value: "0", Default: "0"}, + {Key: "autoconf", Value: "0", Default: "0"}, + }, + }, + Properties: []s6netdev.Property{ + {Key: "stp_state", Value: "0", Default: "0"}, + {Key: "mcast_snooping", Value: "0", Default: "1"}, + }, + }, + }, + } + t.NavServices(vrf_v6) + + for _, v := range t.S6Services() { + if s6netdev.NetdevIsDummy(v.Name) { + continue + } + l.Printf("Commiting %s\n", v.Name) + if err = t.S6CommitService(v); err != nil { + l.Fatalf("Failed to commit %s, %s\n", v.Name, err) + } + } +} diff --git a/interfaces.go b/interfaces.go index 505f593..973e1ab 100644 --- a/interfaces.go +++ b/interfaces.go @@ -2,136 +2,58 @@ package s6netdev import ( "fmt" - "strings" + "net" + "net/netip" ) -func (t *S6SvcTree) Services(i Iface) (r []*S6Svc) { - r = append(r, t.ConfigureServices(i)...) - r = append(r, t.ReadyServices(i)...) +func (i *Iface) NetdevIfaceAddAddr(addr string) (err error) { + var ( + a netip.Prefix + ) + if a, err = netip.ParsePrefix(addr); err != nil { + err = fmt.Errorf("Failed to parse address %s, %w", addr, err) + } + i.Addresses = append(i.Addresses, a) return } -func (t *S6SvcTree) ConfigureServices(i Iface) (r []*S6Svc) { - svc_create := t.CreateIfaceService(i.Name) - r = append(r, svc_create) - - // Defaults to be overridden - svc_create.Up = strings.Join([]string{ - NETDEV_EXECLINE_HEADER, - ExeclineDefine("INTERFACE", i.Name), - fmt.Sprintf("ip link add $INTERFACE type %s", i.Type.str), - }, "\n") - svc_create.Down = strings.Join([]string{ - NETDEV_EXECLINE_HEADER, - ExeclineDefine("INTERFACE", i.Name), - "ip link del dev $INTERFACE", - }, "\n") - - for _, v := range i.Type.deps { - // External dummy services, should be ignored at commit - cs := t.S6New(S6SvcName(v), &S6SvcTypes.Oneshot) - svc_create.S6Children(cs) - } - - // Overrides - switch i.Type { - case &NetdevIfTypes.Phys: - fallthrough - case &NetdevIfTypes.Loopback: - { - svc_create.Up = strings.Join([]string{ - NETDEV_EXECLINE_HEADER, - ExeclineDefine("INTERFACE", i.Name), - "bcnm-waitif 1 $INTERFACE", - }, "\n") - svc_create.Down = "" +func (i *Iface) NetdevIfaceAddRoute(route, r_type, via string, vrf *Iface, table *RouteTable, metric Metric) (err error) { + var ( + r = Route{ + Type: r_type, + Vrf: vrf, + Table: table, + Metric: metric, } - case &NetdevIfTypes.Vlan: - { - svc_create.Up = strings.Join([]string{ - NETDEV_EXECLINE_HEADER, - ExeclineDefine("INTERFACE", i.Name), - ExeclineDefine("PARENT", i.Parent.Name), - ExeclineDefine("VLAN", fmt.Sprintf("%d", i.VlanId)), - fmt.Sprintf("ip link add link $PARENT name $INTERFACE type %s id $VLAN", i.Type.str), - }, "\n") - svc_create.S6Children(t.CreateIfaceService(i.Parent.Name)) - } - case &NetdevIfTypes.Vrf: - { - // Default if no table defined - if i.Table == 0 { - i.Table = RouteTable(500) - } - svc_create.Up = strings.Join([]string{ - NETDEV_EXECLINE_HEADER, - ExeclineDefine("INTERFACE", i.Name), - ExeclineDefine("TABLE", fmt.Sprintf("%d", i.Table)), - fmt.Sprintf("ip link add $INTERFACE type %s table $TABLE", i.Type.str), - }, "\n") - } - case &NetdevIfTypes.Wireguard: - { - wg_cfg := t.NetdevWireguardConfig(i) - svc_create.S6Children(wg_cfg) - r = append(r, wg_cfg) + ) + + if via != "" { + if r.Via, err = netip.ParseAddr(via); err != nil { + err = fmt.Errorf("Failed to parse via %s, %w", via, err) } } - for _, v := range i.Slaves { - r = append(r, t.NetdevEnslaveInterface(v.Name, i.Name)) - } - - for _, v := range i.Properties { - r = append(r, t.NetdevIfaceProp(i, v)) - } - - if i.DHCP.V4 { - r = append(r, t.NetdevIfaceDHCP(i, 4)) - } - if i.DHCP.V6 { - r = append(r, t.NetdevIfaceDHCP(i, 6)) - } - - for _, v := range i.Sysctls.V4 { - r = append(r, t.NetdevIfaceIpSysctl(i, 4, v)) - } - for _, v := range i.Sysctls.V6 { - r = append(r, t.NetdevIfaceIpSysctl(i, 6, v)) - } - - for _, v := range i.Addresses { - r = append(r, t.NetdevIfaceAddr(i, v)) - } - for _, v := range i.Routes { - r = append(r, t.NetdevRoute(i, v)) - } - - bundle_configure := t.NetdevDependBundleStage(i.Name, "configure", svc_create) - r = append(r, bundle_configure) - r = append(r, svc_create.Children...) - + i.Routes = append(i.Routes, r) return } -func (t *S6SvcTree) ReadyServices(i Iface) (r []*S6Svc) { - svc_link := t.S6New(S6SvcName(fmt.Sprintf("interface.%s.link", i.Name)), &S6SvcTypes.Oneshot) - r = append(r, svc_link) - - svc_link.Up = strings.Join([]string{ - NETDEV_EXECLINE_HEADER, - ExeclineDefine("INTERFACE", i.Name), - "ip link set dev $INTERFACE up", - }, "\n") - svc_link.Down = strings.Join([]string{ - NETDEV_EXECLINE_HEADER, - ExeclineDefine("INTERFACE", i.Name), - "ip link set dev $INTERFACE down", - }, "\n") - svc_link.S6Children(t.CreateIfaceService(i.Name)) - - bundle_ready := t.NetdevDependBundleStage(i.Name, "ready", svc_link) - r = append(r, bundle_ready) - +func (i *Iface) NetdevIfaceMAC(mac string) (err error) { + i.MACAddr, err = net.ParseMAC(mac) return } + +func (i *Iface) NetdevIfaceEnslave(s ...*Iface) { + i.Slaves = append(i.Slaves, s...) +} + +func (i *Iface) NetdevIfaceSysctl(ipv int, key, value, def string) { + l := &i.Sysctls.V4 + if ipv == 6 { + l = &i.Sysctls.V6 + } + *l = append(*l, Property{Key: key, Value: value, Default: def}) +} + +func (i *Iface) NetdevIfaceProperty(key, value, def string) { + i.Properties = append(i.Properties, Property{Key: key, Value: value, Default: def}) +} diff --git a/netdev.go b/misc.go similarity index 88% rename from netdev.go rename to misc.go index 4b49368..6dfdc29 100644 --- a/netdev.go +++ b/misc.go @@ -3,6 +3,7 @@ package s6netdev import ( "fmt" "net" + "net/netip" "strings" ) @@ -42,8 +43,8 @@ func (t *S6SvcTree) NetdevEnslaveInterface(iface, master string) *S6Svc { return l } -func NetdevIPAddrVer(IP net.IP) int { - if IP.To4() == nil { +func NetdevIPAddrVer(IP netip.Addr) int { + if IP.Is6() { return 6 } return 4 @@ -53,3 +54,7 @@ func NetdevIsDummy(s S6SvcName) (r bool) { _, r = dummy_svc_blacklist[s] return } + +func NetdevOnlyMAC(x net.HardwareAddr, _ error) net.HardwareAddr { + return x +} diff --git a/services.go b/services.go index 94aa7b6..be4296c 100644 --- a/services.go +++ b/services.go @@ -2,6 +2,7 @@ package s6netdev import ( "fmt" + "strings" ) func (t *S6SvcTree) CreateIfaceService(iface string) *S6Svc { @@ -11,3 +12,143 @@ func (t *S6SvcTree) CreateIfaceService(iface string) *S6Svc { func (t *S6SvcTree) LinkIfaceService(iface string) *S6Svc { return t.S6New(S6SvcName(fmt.Sprintf("interface.%s.link", iface)), &S6SvcTypes.Oneshot) } + +func (t *S6SvcTree) NavServices(i Iface) (r []*S6Svc) { + r = t.Services(i) + if i.Parent != nil { + r = append(r, t.NavServices(*i.Parent)...) + } + for _, v := range i.Slaves { + r = append(r, t.NavServices(*v)...) + } + return +} + +func (t *S6SvcTree) Services(i Iface) (r []*S6Svc) { + r = append(r, t.ConfigureServices(i)...) + r = append(r, t.ReadyServices(i)...) + return +} + +func (t *S6SvcTree) ConfigureServices(i Iface) (r []*S6Svc) { + svc_create := t.CreateIfaceService(i.Name) + r = append(r, svc_create) + + // Defaults to be overridden + svc_create.Up = strings.Join([]string{ + NETDEV_EXECLINE_HEADER, + ExeclineDefine("INTERFACE", i.Name), + fmt.Sprintf("ip link add $INTERFACE type %s", i.Type.str), + }, "\n") + svc_create.Down = strings.Join([]string{ + NETDEV_EXECLINE_HEADER, + ExeclineDefine("INTERFACE", i.Name), + "ip link del dev $INTERFACE", + }, "\n") + + for _, v := range i.Type.deps { + // External dummy services, should be ignored at commit + cs := t.S6New(S6SvcName(v), &S6SvcTypes.Oneshot) + svc_create.S6Children(cs) + } + + // Overrides + switch i.Type { + case &NetdevIfTypes.Phys: + fallthrough + case &NetdevIfTypes.Loopback: + { + svc_create.Up = strings.Join([]string{ + NETDEV_EXECLINE_HEADER, + ExeclineDefine("INTERFACE", i.Name), + "bcnm-waitif 1 $INTERFACE", + }, "\n") + svc_create.Down = "" + } + case &NetdevIfTypes.Vlan: + { + svc_create.Up = strings.Join([]string{ + NETDEV_EXECLINE_HEADER, + ExeclineDefine("INTERFACE", i.Name), + ExeclineDefine("PARENT", i.Parent.Name), + ExeclineDefine("VLAN", fmt.Sprintf("%d", i.VlanId)), + fmt.Sprintf("ip link add link $PARENT name $INTERFACE type %s id $VLAN", i.Type.str), + }, "\n") + svc_create.S6Children(t.CreateIfaceService(i.Parent.Name)) + } + case &NetdevIfTypes.Vrf: + { + // Default if no table defined + if i.Table == 0 { + i.Table = RouteTable(1924) + } + svc_create.Up = strings.Join([]string{ + NETDEV_EXECLINE_HEADER, + ExeclineDefine("INTERFACE", i.Name), + ExeclineDefine("TABLE", fmt.Sprintf("%d", i.Table)), + fmt.Sprintf("ip link add $INTERFACE type %s table $TABLE", i.Type.str), + }, "\n") + } + } + + for _, v := range i.Slaves { + r = append(r, t.NetdevEnslaveInterface(v.Name, i.Name)) + } + + for _, v := range i.Properties { + r = append(r, t.NetdevIfaceProp(i, v)) + } + + if i.DHCP.V4 { + r = append(r, t.NetdevIfaceDHCP(i, 4)) + } + if i.DHCP.V6 { + r = append(r, t.NetdevIfaceDHCP(i, 6)) + } + + for _, v := range i.Sysctls.V4 { + r = append(r, t.NetdevIfaceIpSysctl(i, 4, v)) + } + for _, v := range i.Sysctls.V6 { + r = append(r, t.NetdevIfaceIpSysctl(i, 6, v)) + } + + for _, v := range i.Addresses { + r = append(r, t.NetdevIfaceAddr(i, v)) + } + for _, v := range i.Routes { + r = append(r, t.NetdevRoute(i, v)) + } + + if i.MACAddr != nil { + r = append(r, t.NetdevConfigureIfaceMAC(i, i.MACAddr)) + } + + bundle_configure := t.NetdevDependBundleStage(i.Name, "configure", svc_create) + r = append(r, bundle_configure) + r = append(r, svc_create.Children...) + + return +} + +func (t *S6SvcTree) ReadyServices(i Iface) (r []*S6Svc) { + svc_link := t.S6New(S6SvcName(fmt.Sprintf("interface.%s.link", i.Name)), &S6SvcTypes.Oneshot) + r = append(r, svc_link) + + svc_link.Up = strings.Join([]string{ + NETDEV_EXECLINE_HEADER, + ExeclineDefine("INTERFACE", i.Name), + "ip link set dev $INTERFACE up", + }, "\n") + svc_link.Down = strings.Join([]string{ + NETDEV_EXECLINE_HEADER, + ExeclineDefine("INTERFACE", i.Name), + "ip link set dev $INTERFACE down", + }, "\n") + svc_link.S6Children(t.netdevCreateBundleStage(i.Name, "configure")) + + bundle_ready := t.NetdevDependBundleStage(i.Name, "ready", svc_link) + r = append(r, bundle_ready) + + return +} diff --git a/types.go b/types.go index 31375de..8cccc7d 100644 --- a/types.go +++ b/types.go @@ -1,6 +1,9 @@ package s6netdev -import "net" +import ( + "net" + "net/netip" +) type ( RouteTable uint16 @@ -13,7 +16,11 @@ type Property struct { } type Sysctl_IP struct { - V4, V6 []Property // Should we start dhcp on this interface? + V4, V6 []Property +} + +type DHCP_IP struct { + V4, V6 bool // Should we start dhcp on this interface? } type Iface struct { @@ -26,14 +33,12 @@ type Iface struct { Table RouteTable // Routing table, for VRF - MACAddr []byte // MAC address of interface (only valid for physical, bridges and VLAN) + MACAddr net.HardwareAddr // MAC address of interface (only valid for physical, bridges and VLAN) - Addresses []net.IP // Addresses to be assigned to interface - Routes []Route // Routes to be assigned to interface + Addresses []netip.Prefix // Addresses to be assigned to interface + Routes []Route // Routes to be assigned to interface - DHCP struct { - V4, V6 bool // Should we start dhcp on this interface? - } + DHCP DHCP_IP // Should we start dhcp on this interface? Properties []Property // List of properties of the interface, valid for many Sysctls Sysctl_IP // Sysctls associated with this interface @@ -43,8 +48,8 @@ type Route struct { Default bool // VRF would be a field but it can be derived from parent Type string // unicast default, can be others - Net net.IPNet - Via *net.IP + Net netip.Prefix + Via netip.Addr Vrf *Iface Table *RouteTable Metric Metric // Should be explicitly initialised to 1024