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

129 lines
4.1 KiB
Go

package config
import "fmt"
// TCDevice defines a traffic-shaped interface with bandwidth limits.
type TCDevice struct {
Interface string `yaml:"interface"`
InBandwidth string `yaml:"in_bandwidth,omitempty"` // ingress rate limit
OutBandwidth string `yaml:"out_bandwidth"` // egress max
Options TCDeviceOptions `yaml:"options,omitempty"`
Comment string `yaml:"comment,omitempty"`
}
type TCDeviceOptions struct {
Classify bool `yaml:"classify,omitempty"`
HTB bool `yaml:"htb,omitempty"`
HFSC bool `yaml:"hfsc,omitempty"`
Linklayer string `yaml:"linklayer,omitempty"` // ethernet, atm, adsl
}
// TCClass defines an HTB/HFSC traffic class with rate guarantees.
type TCClass struct {
Interface string `yaml:"interface"` // format: iface:class or iface:parent:class
Mark int `yaml:"mark,omitempty"` // 1-255 fw mark
Rate string `yaml:"rate"` // minimum guaranteed bandwidth
Ceil string `yaml:"ceil,omitempty"` // max bandwidth
Priority int `yaml:"priority,omitempty"` // scheduling order
Options TCClassOptions `yaml:"options,omitempty"`
Comment string `yaml:"comment,omitempty"`
}
type TCClassOptions struct {
Default bool `yaml:"default,omitempty"` // default class for unclassified traffic
TCPAck bool `yaml:"tcp_ack,omitempty"`
Pfifo bool `yaml:"pfifo,omitempty"`
}
// TCFilter classifies packets into traffic classes.
type TCFilter struct {
Class string `yaml:"class"` // interface:class
Source string `yaml:"source,omitempty"`
Dest string `yaml:"dest,omitempty"`
Proto string `yaml:"proto,omitempty"`
DPort PortSpec `yaml:"dport,omitempty"`
SPort PortSpec `yaml:"sport,omitempty"`
TOS string `yaml:"tos,omitempty"`
Length int `yaml:"length,omitempty"`
Priority int `yaml:"priority,omitempty"` // filter eval order
Comment string `yaml:"comment,omitempty"`
}
// TCInterface defines simple traffic shaping (3-band priority queueing).
type TCInterface struct {
Interface string `yaml:"interface"`
Type string `yaml:"type,omitempty"` // external, internal
InBandwidth string `yaml:"in_bandwidth,omitempty"`
OutBandwidth string `yaml:"out_bandwidth,omitempty"`
Comment string `yaml:"comment,omitempty"`
}
// TCPriority assigns packets to priority bands (1=high, 2=medium, 3=low).
type TCPriority struct {
Band int `yaml:"band"` // 1, 2, or 3
Proto string `yaml:"proto,omitempty"`
DPort PortSpec `yaml:"dport,omitempty"`
SPort PortSpec `yaml:"sport,omitempty"`
Address string `yaml:"address,omitempty"`
Interface string `yaml:"interface,omitempty"`
Helper string `yaml:"helper,omitempty"`
Comment string `yaml:"comment,omitempty"`
}
func (c *Config) validateTCDevices() error {
for i, dev := range c.TCDevices {
if dev.Interface == "" {
return fmt.Errorf("tcdevices[%d]: interface required", i)
}
if dev.OutBandwidth == "" {
return fmt.Errorf("tcdevices[%d]: out_bandwidth required", i)
}
}
return nil
}
func (c *Config) validateTCClasses() error {
for i, cls := range c.TCClasses {
if cls.Interface == "" {
return fmt.Errorf("tcclasses[%d]: interface required", i)
}
if cls.Rate == "" {
return fmt.Errorf("tcclasses[%d]: rate required", i)
}
if cls.Mark != 0 && (cls.Mark < 1 || cls.Mark > 255) {
return fmt.Errorf("tcclasses[%d]: mark must be 1-255", i)
}
}
return nil
}
func (c *Config) validateTCFilters() error {
for i, f := range c.TCFilters {
if f.Class == "" {
return fmt.Errorf("tcfilters[%d]: class required", i)
}
if f.Source == "" && f.Dest == "" {
return fmt.Errorf("tcfilters[%d]: source or dest required", i)
}
}
return nil
}
func (c *Config) validateTCInterfaces() error {
for i, iface := range c.TCInterfaces {
if iface.Interface == "" {
return fmt.Errorf("tcinterfaces[%d]: interface required", i)
}
}
return nil
}
func (c *Config) validateTCPriority() error {
for i, p := range c.TCPriorities {
if p.Band < 1 || p.Band > 3 {
return fmt.Errorf("tcpriority[%d]: band must be 1, 2, or 3", i)
}
}
return nil
}