8d9a76c751
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.
129 lines
4.1 KiB
Go
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
|
|
}
|