s6-netdev/configuration.go
2024-09-04 12:29:10 +00:00

298 lines
7.9 KiB
Go

package s6netdev
import (
"fmt"
"net"
"strings"
)
func (t *S6SvcTree) NetdevIfaceCreate(iface Iface, iftype *NetdevIfType) *S6Svc {
l := t.CreateIfaceService(iface.Name)
// Defaults to be overridden
l.Up = strings.Join([]string{
NETDEV_EXECLINE_HEADER,
ExeclineDefine("INTERFACE", iface.Name),
fmt.Sprintf("ip link add $INTERFACE type %s", iface.Type.str),
}, "\n")
l.Down = strings.Join([]string{
NETDEV_EXECLINE_HEADER,
ExeclineDefine("INTERFACE", iface.Name),
"ip link del dev $INTERFACE",
}, "\n")
for _, v := range iftype.deps {
// External dummy services, should be ignored at commit
cs := t.S6New(S6SvcName(v), &S6SvcTypes.Oneshot)
l.S6Children(cs)
}
// Overrides
switch iftype {
case &NetdevIfTypes.Phys:
{
l.Up = strings.Join([]string{
NETDEV_EXECLINE_HEADER,
ExeclineDefine("INTERFACE", iface.Name),
"bcnm-waitif 1 $INTERFACE",
}, "\n")
l.Down = ""
}
case &NetdevIfTypes.Vlan:
{
l.Up = strings.Join([]string{
NETDEV_EXECLINE_HEADER,
ExeclineDefine("INTERFACE", iface.Name),
ExeclineDefine("PARENT", iface.Parent.Name),
ExeclineDefine("VLAN", fmt.Sprintf("%d", iface.VlanId)),
fmt.Sprintf("ip link add link $PARENT name $INTERFACE type %s id $VLAN", iface.Type.str),
}, "\n")
l.S6Children(t.CreateIfaceService(iface.Parent.Name))
}
case &NetdevIfTypes.Vrf:
{
l.Up = strings.Join([]string{
NETDEV_EXECLINE_HEADER,
ExeclineDefine("INTERFACE", iface.Name),
ExeclineDefine("TABLE", fmt.Sprintf("%d", iface.Table)),
fmt.Sprintf("ip link add $INTERFACE type %s table $TABLE", iface.Type.str),
}, "\n")
}
}
return l
}
func (t *S6SvcTree) NetdevIfaceIpSysctl(iface Iface, ipv int, p Property) *S6Svc {
svc_name := S6SvcName(fmt.Sprintf("sysctl.net-ipv%d-conf-%s-%s", ipv, iface.Name, p.Key)).Sanitize()
sysctl_path := fmt.Sprintf("net/ipv%d/conf/%s/%s", ipv, iface.Name, p.Key)
l := t.S6New(svc_name, &S6SvcTypes.Oneshot)
l.S6Children(t.S6New("mount.proc", &S6SvcTypes.Oneshot))
if ipv == 6 {
l.S6Children(t.S6New("module.ipv6", &S6SvcTypes.Oneshot))
}
for _, v := range []struct {
prop *string
val string
}{
{&l.Up, p.Value},
{&l.Down, p.Default},
} {
*v.prop = strings.Join([]string{
NETDEV_EXECLINE_HEADER,
ExeclineXDGConfig(),
ExeclineXDGEnvdirConfig(l.Name),
ExeclineExport("SYSCTL", sysctl_path),
// Set default if not exported
ExeclineImportas("VAL", false, v.val),
ExeclineExport("VAL", "$VAL"),
NNDLibExec("sysctl"),
}, "\n")
}
l.S6Children(t.CreateIfaceService(iface.Name))
t.NetdevDependBundleStage(iface.Name, "configure", l)
return l
}
func (t *S6SvcTree) NetdevIfaceProp(iface Iface, p Property) *S6Svc {
svc_name := S6SvcName(fmt.Sprintf("interface.%s.property.%s", iface.Name, p.Key)).Sanitize()
l := t.S6New(svc_name, &S6SvcTypes.Oneshot)
for _, v := range []struct {
prop *string
val string
}{
{&l.Up, p.Value},
{&l.Down, p.Default},
} {
*v.prop = strings.Join([]string{
NETDEV_EXECLINE_HEADER,
ExeclineXDGConfig(),
ExeclineXDGEnvdirConfig(l.Name),
ExeclineDefine("INTERFACE", iface.Name),
ExeclineDefine("PROP", p.Key),
ExeclineImportas("TYPE", false, iface.Type.str),
ExeclineImportas("VAL", false, v.val),
"ip link set dev $INTERFACE type $TYPE $PROP $VAL",
}, "\n")
}
l.S6Children(t.CreateIfaceService(iface.Name))
t.NetdevDependBundleStage(iface.Name, "configure", l)
return l
}
func (t *S6SvcTree) ConfigureIfaceAddr(iface Iface, addr string) *S6Svc {
svc_name := S6SvcName(fmt.Sprintf("interface.%s.ether.addr", iface.Name)).Sanitize()
l := t.S6New(svc_name, &S6SvcTypes.Oneshot)
l.Up = strings.Join([]string{
NETDEV_EXECLINE_HEADER,
ExeclineXDGConfig(),
ExeclineXDGEnvdirConfig(l.Name),
ExeclineDefine("INTERFACE", iface.Name),
ExeclineImportas("ADDRESS", false, addr),
"ip link set $INTERFACE address $ADDRESS",
}, "\n")
l.S6Children(t.CreateIfaceService(iface.Name))
t.NetdevDependBundleStage(iface.Name, "configure", l)
return l
}
func (t *S6SvcTree) NetdevWireguardConfig(iface Iface) *S6Svc {
svc_name := S6SvcName(fmt.Sprintf("interface.%s.wg.config", iface.Name)).Sanitize()
l := t.S6New(svc_name, &S6SvcTypes.Oneshot)
l.Up = strings.Join([]string{
NETDEV_EXECLINE_HEADER,
ExeclineXDGConfig(),
ExeclineXDGEnvdirConfig(l.Name),
ExeclineDefine("INTERFACE", iface.Name),
ExeclineImportas("CONFIG", false, "/etc/wireguard/${INTERFACE}"),
"wg setconf $INTERFACE $CONFIG",
}, "\n")
l.S6Children(t.CreateIfaceService(iface.Name))
t.NetdevDependBundleStage(iface.Name, "configure", l)
return l
}
func (t *S6SvcTree) NetdevIfaceDHCP(iface Iface, ipv int) *S6Svc {
svc_name := S6SvcName(fmt.Sprintf("interface.%s.dhcp", iface.Name)).Sanitize()
l := t.S6New(svc_name, &S6SvcTypes.Longrun)
var daemon = "udhcpc"
if ipv == 6 {
daemon = fmt.Sprintf("%s%d", daemon, ipv)
}
l.Up = strings.Join([]string{
NETDEV_EXECLINE_HEADER,
ExeclineDefine("INTERFACE", iface.Name),
"fdmove -c 2 1",
fmt.Sprintf("%s -i $INTERFACE -f -S", daemon),
}, "\n")
l.ProducerFor = t.S6New("logger.udhcpc", &S6SvcTypes.Longrun)
l.S6Children(t.LinkIfaceService(iface.Name))
t.NetdevDependBundleStage(iface.Name, "ready", l)
return l
}
func (t *S6SvcTree) netdevIfaceAddrTemplate(action, iface string, ipv int, addr net.IP) string {
return strings.Join([]string{
NETDEV_EXECLINE_HEADER,
ExeclineDefine("INTERFACE", iface),
ExeclineDefine("ADDRESS", addr.String()),
ExeclineDefine("FAMILY", fmt.Sprintf("%d", ipv)),
fmt.Sprintf("ip -${FAMILY} address %s $ADDRESS dev $INTERFACE", action),
}, "\n")
}
func (t *S6SvcTree) NetdevIfaceAddr(iface Iface, addr net.IP) *S6Svc {
ipv := NetdevIPAddrVer(addr)
svc_name := S6SvcName(fmt.Sprintf("interface.%s.ip.addr.%d.%s", iface.Name, ipv, addr)).Sanitize()
l := t.S6New(svc_name, &S6SvcTypes.Oneshot)
l.Up = t.netdevIfaceAddrTemplate("add", iface.Name, ipv, addr)
l.Down = t.netdevIfaceAddrTemplate("del", iface.Name, ipv, addr)
l.S6Children(t.LinkIfaceService(iface.Name))
t.NetdevDependBundleStage(iface.Name, "ready", l)
return l
}
func (t *S6SvcTree) netdevRouteTemplate(iface Iface, route Route) (up, down string, name S6SvcName) {
var (
lines []string
svcname = []string{"interface", iface.Name, "route"}
cmd = []string{
"ip",
fmt.Sprintf("-%d", NetdevIPAddrVer(route.Net.IP)), // IP version
"route",
"%s",
}
header = []string{
NETDEV_EXECLINE_HEADER,
ExeclineXDGConfig(),
}
)
if route.Type != "" {
lines = append(lines, ExeclineDefine("TYPE", route.Type))
cmd = append(cmd, "$TYPE")
svcname = append(svcname, route.Type)
}
var r = "default"
if !route.Default {
r = route.Net.String()
}
lines = append(lines, ExeclineDefine("ROUTE", r))
cmd = append(cmd, "$ROUTE")
svcname = append(svcname, r)
if route.Via != nil {
lines = append(lines, ExeclineImportas("VIA", false, route.Via.String()))
cmd = append(cmd, "via", "$VIA")
}
lines = append(lines, ExeclineDefine("DEV", iface.Name))
cmd = append(cmd, "dev", "$DEV")
if route.Metric != 0 {
lines = append(lines, ExeclineImportas("METRIC", false, fmt.Sprintf("%d", route.Metric)))
cmd = append(cmd, "metric", "$METRIC")
}
if route.Vrf != nil && route.Vrf.Type == &NetdevIfTypes.Vrf {
// Parent is VRF
lines = append(lines, ExeclineImportas("VRF", false, route.Vrf.Name))
cmd = append(cmd, "vrf", "$VRF")
}
name = S6SvcName(strings.Join(svcname, "."))
// Merge
header = append(header, ExeclineXDGEnvdirConfig(name))
lines = append(lines, strings.Join(cmd, " "))
full := append(header, lines...)
up = fmt.Sprintf(strings.Join(full, "\n"), "add")
down = fmt.Sprintf(strings.Join(full, "\n"), "del")
return
}
func (t *S6SvcTree) NetdevRoute(iface Iface, route Route) *S6Svc {
up, down, name := t.netdevRouteTemplate(iface, route)
l := t.S6New(name.Sanitize(), &S6SvcTypes.Oneshot)
l.Up = up
l.Down = down
l.S6Children(t.LinkIfaceService(iface.Name))
if route.Vrf != nil {
l.S6Children(t.LinkIfaceService(route.Vrf.Name))
}
t.NetdevDependBundleStage(iface.Name, "ready", l)
return l
}