Files
tomswall/internal/config/arprules.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

64 lines
1.6 KiB
Go

package config
import "fmt"
type ArpAction string
const (
ArpAccept ArpAction = "accept"
ArpDrop ArpAction = "drop"
ArpSNAT ArpAction = "snat"
ArpDNAT ArpAction = "dnat"
ArpSMAT ArpAction = "smat"
ArpDMAT ArpAction = "dmat"
)
type ArpRule struct {
// Action to take on matching ARP packets.
Action ArpAction `yaml:"action"`
// ActionAddress is the IP address to rewrite to (required for snat/dnat).
ActionAddress string `yaml:"action_address,omitempty"`
// ActionMAC is the MAC address to rewrite to (required for smat/dmat).
ActionMAC string `yaml:"action_mac,omitempty"`
// Source zone/address spec.
Source string `yaml:"source,omitempty"`
// Dest zone/address spec.
Dest string `yaml:"dest,omitempty"`
// Opcode is the ARP operation code to match (e.g. 1=request, 2=reply).
Opcode int `yaml:"opcode,omitempty"`
Comment string `yaml:"comment,omitempty"`
}
var validArpActions = map[ArpAction]bool{
ArpAccept: true, ArpDrop: true,
ArpSNAT: true, ArpDNAT: true,
ArpSMAT: true, ArpDMAT: true,
}
func (c *Config) validateArpRules() error {
for i, a := range c.ArpRules {
if !validArpActions[a.Action] {
return fmt.Errorf("arprules[%d]: unknown action %q", i, a.Action)
}
if (a.Action == ArpSNAT || a.Action == ArpDNAT) && a.ActionAddress == "" {
return fmt.Errorf("arprules[%d]: action_address required for %s action", i, a.Action)
}
if (a.Action == ArpSMAT || a.Action == ArpDMAT) && a.ActionMAC == "" {
return fmt.Errorf("arprules[%d]: action_mac required for %s action", i, a.Action)
}
if a.Source == "" && a.Dest == "" {
return fmt.Errorf("arprules[%d]: source or dest required", i)
}
}
return nil
}