Files
tomswall/internal/config/hosts.go
T
unkinben 8d9a76c751 Add comprehensive nftables compiler with shorewall feature parity
Rewrites the compiler from ~440 to ~1700 lines covering all major shorewall
firewall features: loopback, conntrack fast-path, anti-spoof, DHCP, intra-zone,
blacklist/whitelist, conntrack notrack, tunnels (13 types), rules with sections,
DNAT/redirect, SNAT/masquerade, static NAT, policies with zone exclusions,
MSS clamping, rate limiting, connection limiting, negated addresses, ICMP type
matching, TCP RST reject, user/UID matching, mark match/set, NFQUEUE, NONAT,
and policy-level rate/conn limiting.

Adds full config types for all shorewall subsystems (mangle, accounting, maclist,
netmap, providers, tunnels, conntrack, blrules, proxyarp/ndp, routes, tc, secmarks),
shorewall migration tooling, expanded CLI commands, expression-level diff engine,
and 49 unit tests.
2026-07-01 23:56:44 +10:00

58 lines
1.5 KiB
Go

package config
import "fmt"
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 {
if iface.Interface == h.Interface || iface.PhysicalName() == h.Interface {
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)
}
}
return nil
}