diff --git a/nl/syscall.go b/nl/syscall.go index f7f7f92..4a01e6e 100644 --- a/nl/syscall.go +++ b/nl/syscall.go @@ -21,6 +21,13 @@ const ( FRA_TABLE /* Extended table id */ FRA_FWMASK /* mask for netfilter mark */ FRA_OIFNAME + FRA_PAD + FRA_L3MDEV /* iif or oif is l3mdev goto its table */ + FRA_UID_RANGE /* UID range */ + FRA_PROTOCOL /* Originator of the rule */ + FRA_IP_PROTO /* ip proto */ + FRA_SPORT_RANGE /* sport */ + FRA_DPORT_RANGE /* dport */ ) // ip rule netlink request types diff --git a/rule.go b/rule.go index 54e1ba3..95f2fac 100644 --- a/rule.go +++ b/rule.go @@ -23,6 +23,8 @@ type Rule struct { SuppressIfgroup int SuppressPrefixlen int Invert bool + Dport *RulePortRange + Sport *RulePortRange } func (r Rule) String() string { @@ -41,3 +43,14 @@ func NewRule() *Rule { Flow: -1, } } + +// NewRulePortRange creates rule sport/dport range. +func NewRulePortRange(start, end uint16) *RulePortRange { + return &RulePortRange{Start: start, End: end} +} + +// RulePortRange represents rule sport/dport range. +type RulePortRange struct { + Start uint16 + End uint16 +} diff --git a/rule_linux.go b/rule_linux.go index 9fa642d..7e07d30 100644 --- a/rule_linux.go +++ b/rule_linux.go @@ -1,6 +1,7 @@ package netlink import ( + "bytes" "fmt" "net" @@ -153,6 +154,16 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error { req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b)) } + if rule.Dport != nil { + b := rule.Dport.toRtAttrData() + req.AddData(nl.NewRtAttr(nl.FRA_DPORT_RANGE, b)) + } + + if rule.Sport != nil { + b := rule.Sport.toRtAttrData() + req.AddData(nl.NewRtAttr(nl.FRA_SPORT_RANGE, b)) + } + _, err := req.Execute(unix.NETLINK_ROUTE, 0) return err } @@ -229,6 +240,10 @@ func (h *Handle) RuleList(family int) ([]Rule, error) { rule.Goto = int(native.Uint32(attrs[j].Value[0:4])) case nl.FRA_PRIORITY: rule.Priority = int(native.Uint32(attrs[j].Value[0:4])) + case nl.FRA_DPORT_RANGE: + rule.Dport = NewRulePortRange(native.Uint16(attrs[j].Value[0:2]), native.Uint16(attrs[j].Value[2:4])) + case nl.FRA_SPORT_RANGE: + rule.Sport = NewRulePortRange(native.Uint16(attrs[j].Value[0:2]), native.Uint16(attrs[j].Value[2:4])) } } res = append(res, *rule) @@ -236,3 +251,10 @@ func (h *Handle) RuleList(family int) ([]Rule, error) { return res, nil } + +func (pr *RulePortRange) toRtAttrData() []byte { + b := [][]byte{make([]byte, 2), make([]byte, 2)} + native.PutUint16(b[0], pr.Start) + native.PutUint16(b[1], pr.End) + return bytes.Join(b, []byte{}) +} diff --git a/rule_test.go b/rule_test.go index 50c6097..630f10f 100644 --- a/rule_test.go +++ b/rule_test.go @@ -30,6 +30,8 @@ func TestRuleAddDel(t *testing.T) { rule.IifName = "lo" rule.Invert = true rule.Tos = 0x10 + rule.Dport = NewRulePortRange(80, 80) + rule.Sport = NewRulePortRange(1000, 1024) if err := RuleAdd(rule); err != nil { t.Fatal(err) }