Files
tomswall/internal/config/hosts.go
T
unkin-agent 190ff72643
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Exclude sub-zone hosts from wildcard parent interfaces
2026-10-09 23:35:32 +11:00

71 lines
1.9 KiB
Go

package config
import (
"fmt"
"net/netip"
"slices"
"strings"
)
type Host struct {
Zone string `yaml:"zone"`
Interface string `yaml:"interface"`
Addresses []string `yaml:"addresses"`
Exclusions []string `yaml:"exclusions,omitempty"`
Dynamic bool `yaml:"dynamic,omitempty"`
Options HostOptions `yaml:"options,omitempty"`
}
type HostOptions struct {
Broadcast bool `yaml:"broadcast,omitempty"`
DestOnly bool `yaml:"destonly,omitempty"`
IPSec bool `yaml:"ipsec,omitempty"`
MSS int `yaml:"mss,omitempty"`
NoSmurfs bool `yaml:"nosmurfs,omitempty"`
RouteBack bool `yaml:"routeback,omitempty"`
TCPFlags bool `yaml:"tcpflags,omitempty"`
}
func (c *Config) validateHosts() error {
fwZone := c.FirewallZone()
for i, h := range c.Hosts {
if h.Zone == "" {
return fmt.Errorf("host[%d]: zone required", i)
}
if h.Zone == fwZone {
return fmt.Errorf("host[%d]: firewall zone must not be listed in hosts", i)
}
if _, ok := c.Zones[h.Zone]; !ok {
return fmt.Errorf("host[%d]: zone %q not defined", i, h.Zone)
}
if h.Interface == "" {
return fmt.Errorf("host[%d]: interface required", i)
}
ifaceFound := false
for _, iface := range c.Interfaces {
prefix, wild := strings.CutSuffix(iface.PhysicalName(), "+")
if iface.Interface == h.Interface || iface.PhysicalName() == h.Interface || (wild && strings.HasPrefix(h.Interface, prefix)) {
ifaceFound = true
break
}
}
if !ifaceFound {
return fmt.Errorf("host[%d]: interface %q not defined in interfaces", i, h.Interface)
}
if !h.Dynamic && len(h.Addresses) == 0 {
return fmt.Errorf("host[%d]: at least one address required (or set dynamic: true)", i)
}
for _, a := range slices.Concat(h.Addresses, h.Exclusions) {
if _, err := netip.ParsePrefix(a); err != nil {
if _, err := netip.ParseAddr(a); err != nil {
return fmt.Errorf("host[%d]: invalid address %q", i, a)
}
}
}
}
return nil
}