mirror of
https://github.com/moby/moby.git
synced 2026-07-26 19:32:56 +00:00
Pass context to nftables functions
Signed-off-by: Rob Murray <rob.murray@docker.com>
This commit is contained in:
@@ -81,7 +81,7 @@ func (nft *nftabler) getTable(ipv firewaller.IPVersion) nftables.TableRef {
|
||||
|
||||
func (nft *nftabler) FilterForwardDrop(ctx context.Context, ipv firewaller.IPVersion) error {
|
||||
table := nft.getTable(ipv)
|
||||
if err := table.Chain(forwardChain).SetPolicy("drop"); err != nil {
|
||||
if err := table.Chain(ctx, forwardChain).SetPolicy("drop"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nftApply(ctx, table)
|
||||
@@ -104,7 +104,7 @@ func (nft *nftabler) init(ctx context.Context, family nftables.Family) (nftables
|
||||
// So, packets that aren't related to docker don't need to traverse any per-network filter forward
|
||||
// rules - and packets that are entering or leaving docker networks only need to traverse rules
|
||||
// related to those networks.
|
||||
fwdChain, err := table.BaseChain(forwardChain,
|
||||
fwdChain, err := table.BaseChain(ctx, forwardChain,
|
||||
nftables.BaseChainTypeFilter,
|
||||
nftables.BaseChainHookForward,
|
||||
nftables.BaseChainPriorityFilter)
|
||||
@@ -112,51 +112,51 @@ func (nft *nftabler) init(ctx context.Context, family nftables.Family) (nftables
|
||||
return nftables.TableRef{}, fmt.Errorf("initialising nftables: %w", err)
|
||||
}
|
||||
// Instantiate the verdict maps and add the jumps.
|
||||
_ = table.InterfaceVMap(filtFwdInVMap)
|
||||
if err := fwdChain.AppendRule(initialRuleGroup, "oifname vmap @"+filtFwdInVMap); err != nil {
|
||||
_ = table.InterfaceVMap(ctx, filtFwdInVMap)
|
||||
if err := fwdChain.AppendRule(ctx, initialRuleGroup, "oifname vmap @"+filtFwdInVMap); err != nil {
|
||||
return nftables.TableRef{}, fmt.Errorf("initialising nftables: %w", err)
|
||||
}
|
||||
_ = table.InterfaceVMap(filtFwdOutVMap)
|
||||
if err := fwdChain.AppendRule(initialRuleGroup, "iifname vmap @"+filtFwdOutVMap); err != nil {
|
||||
_ = table.InterfaceVMap(ctx, filtFwdOutVMap)
|
||||
if err := fwdChain.AppendRule(ctx, initialRuleGroup, "iifname vmap @"+filtFwdOutVMap); err != nil {
|
||||
return nftables.TableRef{}, fmt.Errorf("initialising nftables: %w", err)
|
||||
}
|
||||
|
||||
// Set up the NAT postrouting base chain.
|
||||
//
|
||||
// Like the filter-forward chain, its only rules are jumps to network-specific ingress and egress chains.
|
||||
natPostRtChain, err := table.BaseChain(postroutingChain,
|
||||
natPostRtChain, err := table.BaseChain(ctx, postroutingChain,
|
||||
nftables.BaseChainTypeNAT,
|
||||
nftables.BaseChainHookPostrouting,
|
||||
nftables.BaseChainPrioritySrcNAT)
|
||||
if err != nil {
|
||||
return nftables.TableRef{}, err
|
||||
}
|
||||
_ = table.InterfaceVMap(natPostroutingOutVMap)
|
||||
if err := natPostRtChain.AppendRule(initialRuleGroup, "iifname vmap @"+natPostroutingOutVMap); err != nil {
|
||||
_ = table.InterfaceVMap(ctx, natPostroutingOutVMap)
|
||||
if err := natPostRtChain.AppendRule(ctx, initialRuleGroup, "iifname vmap @"+natPostroutingOutVMap); err != nil {
|
||||
return nftables.TableRef{}, fmt.Errorf("initialising nftables: %w", err)
|
||||
}
|
||||
_ = table.InterfaceVMap(natPostroutingInVMap)
|
||||
if err := natPostRtChain.AppendRule(initialRuleGroup, "oifname vmap @"+natPostroutingInVMap); err != nil {
|
||||
_ = table.InterfaceVMap(ctx, natPostroutingInVMap)
|
||||
if err := natPostRtChain.AppendRule(ctx, initialRuleGroup, "oifname vmap @"+natPostroutingInVMap); err != nil {
|
||||
return nftables.TableRef{}, fmt.Errorf("initialising nftables: %w", err)
|
||||
}
|
||||
|
||||
// Instantiate natChain, for the NAT prerouting and output base chains to jump to.
|
||||
_ = table.Chain(natChain)
|
||||
_ = table.Chain(ctx, natChain)
|
||||
|
||||
// Set up the NAT prerouting base chain.
|
||||
natPreRtChain, err := table.BaseChain(preroutingChain,
|
||||
natPreRtChain, err := table.BaseChain(ctx, preroutingChain,
|
||||
nftables.BaseChainTypeNAT,
|
||||
nftables.BaseChainHookPrerouting,
|
||||
nftables.BaseChainPriorityDstNAT)
|
||||
if err != nil {
|
||||
return nftables.TableRef{}, err
|
||||
}
|
||||
if err := natPreRtChain.AppendRule(initialRuleGroup, "fib daddr type local counter jump "+natChain); err != nil {
|
||||
if err := natPreRtChain.AppendRule(ctx, initialRuleGroup, "fib daddr type local counter jump "+natChain); err != nil {
|
||||
return nftables.TableRef{}, fmt.Errorf("initialising nftables: %w", err)
|
||||
}
|
||||
|
||||
// Set up the NAT output base chain
|
||||
natOutputChain, err := table.BaseChain(outputChain,
|
||||
natOutputChain, err := table.BaseChain(ctx, outputChain,
|
||||
nftables.BaseChainTypeNAT,
|
||||
nftables.BaseChainHookOutput,
|
||||
nftables.BaseChainPriorityDstNAT)
|
||||
@@ -172,12 +172,12 @@ func (nft *nftabler) init(ctx context.Context, family nftables.Family) (nftables
|
||||
skipLoopback = "ip6 daddr != ::1 "
|
||||
}
|
||||
}
|
||||
if err := natOutputChain.AppendRule(initialRuleGroup, skipLoopback+"fib daddr type local counter jump "+natChain); err != nil {
|
||||
if err := natOutputChain.AppendRule(ctx, initialRuleGroup, skipLoopback+"fib daddr type local counter jump "+natChain); err != nil {
|
||||
return nftables.TableRef{}, fmt.Errorf("initialising nftables: %w", err)
|
||||
}
|
||||
|
||||
// Set up the raw prerouting base chain
|
||||
if _, err := table.BaseChain(rawPreroutingChain,
|
||||
if _, err := table.BaseChain(ctx, rawPreroutingChain,
|
||||
nftables.BaseChainTypeFilter,
|
||||
nftables.BaseChainHookPrerouting,
|
||||
nftables.BaseChainPriorityRaw); err != nil {
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/docker/docker/libnetwork/internal/nftables"
|
||||
)
|
||||
|
||||
// mirroredWSL2Workaround adds IPv4 NAT rule if docker's host Linux appears to
|
||||
// mirroredWSL2Workaround adds IPv4 NAT rule if docker's host Linux appears to
|
||||
// be a guest running under WSL2 in with mirrored mode networking.
|
||||
// https://learn.microsoft.com/en-us/windows/wsl/networking#mirrored-mode-networking
|
||||
//
|
||||
@@ -44,5 +44,6 @@ func mirroredWSL2Workaround(ctx context.Context, table nftables.TableRef) error
|
||||
if table.Family() != nftables.IPv4 {
|
||||
return nil
|
||||
}
|
||||
return table.Chain(natChain).AppendRule(initialRuleGroup, `iifname "loopback0" ip daddr 127.0.0.0/8 counter return`)
|
||||
return table.Chain(ctx, natChain).AppendRule(ctx,
|
||||
initialRuleGroup, `iifname "loopback0" ip daddr 127.0.0.0/8 counter return`)
|
||||
}
|
||||
|
||||
@@ -408,7 +408,7 @@ type ChainRef struct {
|
||||
// It is an error to create a base chain that already exists.
|
||||
// If the underlying chain already exists, it will be flushed by the
|
||||
// next [TableRef.Apply] before new rules are added.
|
||||
func (t TableRef) BaseChain(name string, chainType BaseChainType, hook BaseChainHook, priority int) (ChainRef, error) {
|
||||
func (t TableRef) BaseChain(ctx context.Context, name string, chainType BaseChainType, hook BaseChainHook, priority int) (ChainRef, error) {
|
||||
if _, ok := t.t.Chains[name]; ok {
|
||||
return ChainRef{}, fmt.Errorf("chain %q already exists", name)
|
||||
}
|
||||
@@ -423,7 +423,7 @@ func (t TableRef) BaseChain(name string, chainType BaseChainType, hook BaseChain
|
||||
ruleGroups: map[RuleGroup][]string{},
|
||||
}
|
||||
t.t.Chains[name] = c
|
||||
log.G(context.TODO()).WithFields(log.Fields{
|
||||
log.G(ctx).WithFields(log.Fields{
|
||||
"family": t.t.Family,
|
||||
"table": t.t.Name,
|
||||
"chain": name,
|
||||
@@ -442,7 +442,7 @@ func (t TableRef) BaseChain(name string, chainType BaseChainType, hook BaseChain
|
||||
//
|
||||
// If a new [ChainRef] is created and the underlying chain already exists, it
|
||||
// will be flushed by the next [TableRef.Apply] before new rules are added.
|
||||
func (t TableRef) Chain(name string) ChainRef {
|
||||
func (t TableRef) Chain(ctx context.Context, name string) ChainRef {
|
||||
c, ok := t.t.Chains[name]
|
||||
if !ok {
|
||||
c = &chain{
|
||||
@@ -453,7 +453,7 @@ func (t TableRef) Chain(name string) ChainRef {
|
||||
}
|
||||
t.t.Chains[name] = c
|
||||
}
|
||||
log.G(context.TODO()).WithFields(log.Fields{
|
||||
log.G(ctx).WithFields(log.Fields{
|
||||
"family": t.t.Family,
|
||||
"table": t.t.Name,
|
||||
"chain": name,
|
||||
@@ -462,14 +462,14 @@ func (t TableRef) Chain(name string) ChainRef {
|
||||
}
|
||||
|
||||
// ChainUpdateFunc is a function that can add rules to a chain, or remove rules from it.
|
||||
type ChainUpdateFunc func(RuleGroup, string, ...interface{}) error
|
||||
type ChainUpdateFunc func(context.Context, RuleGroup, string, ...interface{}) error
|
||||
|
||||
// ChainUpdateFunc returns a [ChainUpdateFunc] to add rules to the named chain if
|
||||
// enable is true, or to remove rules from the chain if enable is false.
|
||||
// (Written as a convenience function to ease migration of iptables functions
|
||||
// originally written with an enable flag.)
|
||||
func (t TableRef) ChainUpdateFunc(name string, enable bool) ChainUpdateFunc {
|
||||
c := t.Chain(name)
|
||||
func (t TableRef) ChainUpdateFunc(ctx context.Context, name string, enable bool) ChainUpdateFunc {
|
||||
c := t.Chain(ctx, name)
|
||||
if enable {
|
||||
return c.AppendRule
|
||||
}
|
||||
@@ -477,14 +477,14 @@ func (t TableRef) ChainUpdateFunc(name string, enable bool) ChainUpdateFunc {
|
||||
}
|
||||
|
||||
// DeleteChain deletes a chain. It is an error to delete a chain that does not exist.
|
||||
func (t TableRef) DeleteChain(name string) error {
|
||||
func (t TableRef) DeleteChain(ctx context.Context, name string) error {
|
||||
if _, ok := t.t.Chains[name]; !ok {
|
||||
return fmt.Errorf("chain %q does not exist", name)
|
||||
}
|
||||
delete(t.t.Chains, name)
|
||||
t.t.DeleteChainCommands = append(t.t.DeleteChainCommands,
|
||||
fmt.Sprintf("delete chain %s %s %s", t.t.Family, t.t.Name, name))
|
||||
log.G(context.TODO()).WithFields(log.Fields{
|
||||
log.G(ctx).WithFields(log.Fields{
|
||||
"family": t.t.Family,
|
||||
"table": t.t.Name,
|
||||
"chain": name,
|
||||
@@ -504,7 +504,7 @@ func (c ChainRef) SetPolicy(policy string) error {
|
||||
}
|
||||
|
||||
// AppendRule appends a rule to a [RuleGroup] in a [ChainRef].
|
||||
func (c ChainRef) AppendRule(group RuleGroup, rule string, args ...interface{}) error {
|
||||
func (c ChainRef) AppendRule(ctx context.Context, group RuleGroup, rule string, args ...interface{}) error {
|
||||
if len(args) > 0 {
|
||||
rule = fmt.Sprintf(rule, args...)
|
||||
}
|
||||
@@ -513,7 +513,7 @@ func (c ChainRef) AppendRule(group RuleGroup, rule string, args ...interface{})
|
||||
}
|
||||
c.c.ruleGroups[group] = append(c.c.ruleGroups[group], rule)
|
||||
c.c.Dirty = true
|
||||
log.G(context.TODO()).WithFields(log.Fields{
|
||||
log.G(ctx).WithFields(log.Fields{
|
||||
"family": c.c.table.Family,
|
||||
"table": c.c.table.Name,
|
||||
"chain": c.c.Name,
|
||||
@@ -523,10 +523,18 @@ func (c ChainRef) AppendRule(group RuleGroup, rule string, args ...interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
// AppendRuleCf calls AppendRule and returns a cleanup function or an error.
|
||||
func (c ChainRef) AppendRuleCf(ctx context.Context, group RuleGroup, rule string, args ...interface{}) (func(context.Context) error, error) {
|
||||
if err := c.AppendRule(ctx, group, rule, args...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return func(ctx context.Context) error { return c.DeleteRule(ctx, group, rule, args...) }, nil
|
||||
}
|
||||
|
||||
// DeleteRule deletes a rule from a [RuleGroup] in a [ChainRef]. It is an error
|
||||
// to delete from a group that does not exist, or to delete a rule that does not
|
||||
// exist.
|
||||
func (c ChainRef) DeleteRule(group RuleGroup, rule string, args ...interface{}) error {
|
||||
func (c ChainRef) DeleteRule(ctx context.Context, group RuleGroup, rule string, args ...interface{}) error {
|
||||
if len(args) > 0 {
|
||||
rule = fmt.Sprintf(rule, args...)
|
||||
}
|
||||
@@ -540,7 +548,7 @@ func (c ChainRef) DeleteRule(group RuleGroup, rule string, args ...interface{})
|
||||
return fmt.Errorf("rule %q does not exist", rule)
|
||||
}
|
||||
c.c.Dirty = true
|
||||
log.G(context.TODO()).WithFields(log.Fields{
|
||||
log.G(ctx).WithFields(log.Fields{
|
||||
"family": c.c.table.Family,
|
||||
"table": c.c.table.Name,
|
||||
"chain": c.c.Name,
|
||||
@@ -578,7 +586,7 @@ type VMapRef struct {
|
||||
//
|
||||
// If a [VMapRef] is created and the underlying map already exists, it will be flushed
|
||||
// by the next [TableRef.Apply] before new elements are added.
|
||||
func (t TableRef) InterfaceVMap(name string) VMapRef {
|
||||
func (t TableRef) InterfaceVMap(ctx context.Context, name string) VMapRef {
|
||||
if vmap, ok := t.t.VMaps[name]; ok {
|
||||
return VMapRef{vmap}
|
||||
}
|
||||
@@ -592,7 +600,7 @@ func (t TableRef) InterfaceVMap(name string) VMapRef {
|
||||
Dirty: true,
|
||||
}
|
||||
t.t.VMaps[name] = vmap
|
||||
log.G(context.TODO()).WithFields(log.Fields{
|
||||
log.G(ctx).WithFields(log.Fields{
|
||||
"family": t.t.Family,
|
||||
"table": t.t.Name,
|
||||
"vmap": name,
|
||||
@@ -602,13 +610,13 @@ func (t TableRef) InterfaceVMap(name string) VMapRef {
|
||||
|
||||
// AddElement adds an element to a verdict map. The caller must ensure the key has
|
||||
// the correct type. It is an error to add a key that already exists.
|
||||
func (v VMapRef) AddElement(key string, verdict string) error {
|
||||
func (v VMapRef) AddElement(ctx context.Context, key string, verdict string) error {
|
||||
if _, ok := v.v.Elements[key]; ok {
|
||||
return fmt.Errorf("verdict map already contains element %q", key)
|
||||
}
|
||||
v.v.Elements[key] = verdict
|
||||
v.v.AddedElements[key] = verdict
|
||||
log.G(context.TODO()).WithFields(log.Fields{
|
||||
log.G(ctx).WithFields(log.Fields{
|
||||
"family": v.v.table.Family,
|
||||
"table": v.v.table.Name,
|
||||
"vmap": v.v.Name,
|
||||
@@ -618,15 +626,23 @@ func (v VMapRef) AddElement(key string, verdict string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddElementCf calls AddElement and returns a cleanup function or an error.
|
||||
func (v VMapRef) AddElementCf(ctx context.Context, key string, verdict string) (func(context.Context) error, error) {
|
||||
if err := v.AddElement(ctx, key, verdict); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return func(ctx context.Context) error { return v.DeleteElement(ctx, key) }, nil
|
||||
}
|
||||
|
||||
// DeleteElement deletes an element from a verdict map. It is an error to delete
|
||||
// an element that does not exist.
|
||||
func (v VMapRef) DeleteElement(key string) error {
|
||||
func (v VMapRef) DeleteElement(ctx context.Context, key string) error {
|
||||
if _, ok := v.v.Elements[key]; !ok {
|
||||
return fmt.Errorf("verdict map does not contain element %q", key)
|
||||
}
|
||||
delete(v.v.Elements, key)
|
||||
v.v.DeletedElements[key] = struct{}{}
|
||||
log.G(context.TODO()).WithFields(log.Fields{
|
||||
log.G(ctx).WithFields(log.Fields{
|
||||
"family": v.v.table.Family,
|
||||
"table": v.v.table.Name,
|
||||
"vmap": v.v.Name,
|
||||
@@ -666,7 +682,7 @@ type SetRef struct {
|
||||
// change if we need an "inet" table.)
|
||||
//
|
||||
// See https://wiki.nftables.org/wiki-nftables/index.php/Sets#Named_sets
|
||||
func (t TableRef) PrefixSet(name string) SetRef {
|
||||
func (t TableRef) PrefixSet(ctx context.Context, name string) SetRef {
|
||||
if s, ok := t.t.Sets[name]; ok {
|
||||
return SetRef{s}
|
||||
}
|
||||
@@ -684,7 +700,7 @@ func (t TableRef) PrefixSet(name string) SetRef {
|
||||
s.ElementType = nftTypeIPv6Addr
|
||||
}
|
||||
t.t.Sets[name] = s
|
||||
log.G(context.TODO()).WithFields(log.Fields{
|
||||
log.G(ctx).WithFields(log.Fields{
|
||||
"family": t.t.Family,
|
||||
"table": t.t.Name,
|
||||
"set": name,
|
||||
@@ -695,13 +711,13 @@ func (t TableRef) PrefixSet(name string) SetRef {
|
||||
// AddElement adds an element to a set. It is the caller's responsibility to make sure
|
||||
// the element has the correct type. It is an error to add an element that is already
|
||||
// in the set.
|
||||
func (s SetRef) AddElement(element string) error {
|
||||
func (s SetRef) AddElement(ctx context.Context, element string) error {
|
||||
if _, ok := s.s.Elements[element]; ok {
|
||||
return fmt.Errorf("set already contains element %q", element)
|
||||
}
|
||||
s.s.Elements[element] = struct{}{}
|
||||
s.s.AddedElements[element] = struct{}{}
|
||||
log.G(context.TODO()).WithFields(log.Fields{
|
||||
log.G(ctx).WithFields(log.Fields{
|
||||
"family": s.s.table.Family,
|
||||
"table": s.s.table.Name,
|
||||
"set": s.s.Name,
|
||||
@@ -712,13 +728,13 @@ func (s SetRef) AddElement(element string) error {
|
||||
|
||||
// DeleteElement deletes an element from the set. It is an error to delete an
|
||||
// element that is not in the set.
|
||||
func (s SetRef) DeleteElement(element string) error {
|
||||
func (s SetRef) DeleteElement(ctx context.Context, element string) error {
|
||||
if _, ok := s.s.Elements[element]; !ok {
|
||||
return fmt.Errorf("set does not contain element %q", element)
|
||||
}
|
||||
delete(s.s.Elements, element)
|
||||
s.s.DeletedElements[element] = struct{}{}
|
||||
log.G(context.TODO()).WithFields(log.Fields{
|
||||
log.G(ctx).WithFields(log.Fields{
|
||||
"family": s.s.table.Family,
|
||||
"table": s.s.table.Name,
|
||||
"set": s.s.Name,
|
||||
|
||||
@@ -58,6 +58,7 @@ func TestTable(t *testing.T) {
|
||||
|
||||
func TestChain(t *testing.T) {
|
||||
defer testSetup(t)()
|
||||
ctx := context.Background()
|
||||
|
||||
// Create a table.
|
||||
tbl, err := NewTable(IPv4, "this_is_a_table")
|
||||
@@ -65,68 +66,68 @@ func TestChain(t *testing.T) {
|
||||
|
||||
// Create a base chain.
|
||||
const bcName = "this_is_a_base_chain"
|
||||
bc1, err := tbl.BaseChain(bcName, BaseChainTypeFilter, BaseChainHookForward, BaseChainPriorityFilter+10)
|
||||
bc1, err := tbl.BaseChain(ctx, bcName, BaseChainTypeFilter, BaseChainHookForward, BaseChainPriorityFilter+10)
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Check that it's an error to add a new base chain with the same name.
|
||||
_, err = tbl.BaseChain(bcName, BaseChainTypeNAT, BaseChainHookPrerouting, BaseChainPriorityDstNAT)
|
||||
_, err = tbl.BaseChain(ctx, bcName, BaseChainTypeNAT, BaseChainHookPrerouting, BaseChainPriorityDstNAT)
|
||||
assert.Check(t, is.ErrorContains(err, "already exists"))
|
||||
|
||||
// Add a rule.
|
||||
err = bc1.AppendRule(0, "counter")
|
||||
err = bc1.AppendRule(ctx, 0, "counter")
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Add a regular chain.
|
||||
const regularChainName = "this_is_a_regular_chain"
|
||||
_ = tbl.Chain(regularChainName)
|
||||
_ = tbl.Chain(ctx, regularChainName)
|
||||
|
||||
// Add a rule to the regular chain, use string formatting and a func retrieved
|
||||
// from the table.
|
||||
f := tbl.ChainUpdateFunc(regularChainName, true)
|
||||
err = f(0, "counter %s", "accept")
|
||||
f := tbl.ChainUpdateFunc(ctx, regularChainName, true)
|
||||
err = f(ctx, 0, "counter %s", "accept")
|
||||
assert.Check(t, err)
|
||||
|
||||
// Fetch the base chain by name.
|
||||
bc1 = tbl.Chain(bcName)
|
||||
bc1 = tbl.Chain(ctx, bcName)
|
||||
|
||||
// Add another rule to the base chain, using the newly-retrieved handle.
|
||||
err = bc1.AppendRule(0, "jump %s", regularChainName)
|
||||
err = bc1.AppendRule(ctx, 0, "jump %s", regularChainName)
|
||||
assert.Check(t, err)
|
||||
|
||||
// Update nftables and check what happened.
|
||||
applyAndCheck(t, tbl, t.Name()+"_created.golden")
|
||||
|
||||
// Delete a rule from the base chain.
|
||||
f = tbl.ChainUpdateFunc(bcName, false)
|
||||
err = f(0, "counter")
|
||||
f = tbl.ChainUpdateFunc(ctx, bcName, false)
|
||||
err = f(ctx, 0, "counter")
|
||||
assert.Check(t, err)
|
||||
|
||||
// Check it's an error to delete that rule again. This time, call the delete
|
||||
// function directly on a newly retrieved handle.
|
||||
err = tbl.Chain(bcName).DeleteRule(0, "counter")
|
||||
err = tbl.Chain(ctx, bcName).DeleteRule(ctx, 0, "counter")
|
||||
assert.Check(t, is.ErrorContains(err, "does not exist"))
|
||||
|
||||
// Update the base chain's policy.
|
||||
err = tbl.Chain(bcName).SetPolicy("drop")
|
||||
err = tbl.Chain(ctx, bcName).SetPolicy("drop")
|
||||
assert.Check(t, err)
|
||||
|
||||
// Check it's an error to set a policy on a regular chain.
|
||||
err = tbl.Chain(regularChainName).SetPolicy("drop")
|
||||
err = tbl.Chain(ctx, regularChainName).SetPolicy("drop")
|
||||
assert.Check(t, is.ErrorContains(err, "not a base chain"))
|
||||
|
||||
// Update nftables and check what happened.
|
||||
applyAndCheck(t, tbl, t.Name()+"_modified.golden")
|
||||
|
||||
// Delete the base chain.
|
||||
err = tbl.DeleteChain(bcName)
|
||||
err = tbl.DeleteChain(ctx, bcName)
|
||||
assert.Check(t, err)
|
||||
|
||||
// Delete the regular chain.
|
||||
err = tbl.DeleteChain(regularChainName)
|
||||
err = tbl.DeleteChain(ctx, regularChainName)
|
||||
assert.Check(t, err)
|
||||
|
||||
// Check that it's an error to delete it again.
|
||||
err = tbl.DeleteChain(regularChainName)
|
||||
err = tbl.DeleteChain(ctx, regularChainName)
|
||||
assert.Check(t, is.ErrorContains(err, "does not exist"))
|
||||
|
||||
// Update nftables and check what happened.
|
||||
@@ -135,19 +136,20 @@ func TestChain(t *testing.T) {
|
||||
|
||||
func TestChainRuleGroups(t *testing.T) {
|
||||
defer testSetup(t)()
|
||||
ctx := context.Background()
|
||||
|
||||
tbl, err := NewTable(IPv4, "testtable")
|
||||
assert.NilError(t, err)
|
||||
c := tbl.Chain("testchain")
|
||||
err = c.AppendRule(100, "hello100")
|
||||
c := tbl.Chain(ctx, "testchain")
|
||||
err = c.AppendRule(ctx, 100, "hello100")
|
||||
assert.Check(t, err)
|
||||
err = c.AppendRule(200, "hello200")
|
||||
err = c.AppendRule(ctx, 200, "hello200")
|
||||
assert.Check(t, err)
|
||||
err = c.AppendRule(100, "hello101")
|
||||
err = c.AppendRule(ctx, 100, "hello101")
|
||||
assert.Check(t, err)
|
||||
err = c.AppendRule(200, "hello201")
|
||||
err = c.AppendRule(ctx, 200, "hello201")
|
||||
assert.Check(t, err)
|
||||
err = c.AppendRule(100, "hello102")
|
||||
err = c.AppendRule(ctx, 100, "hello102")
|
||||
assert.Check(t, err)
|
||||
|
||||
assert.Check(t, is.DeepEqual(c.c.Rules(), []string{
|
||||
@@ -158,6 +160,7 @@ func TestChainRuleGroups(t *testing.T) {
|
||||
|
||||
func TestVMap(t *testing.T) {
|
||||
defer testSetup(t)()
|
||||
ctx := context.Background()
|
||||
|
||||
// Create a table.
|
||||
tbl, err := NewTable(IPv6, "this_is_a_table")
|
||||
@@ -165,32 +168,32 @@ func TestVMap(t *testing.T) {
|
||||
|
||||
// Create a verdict map.
|
||||
const mapName = "this_is_a_vmap"
|
||||
m := tbl.InterfaceVMap(mapName)
|
||||
m := tbl.InterfaceVMap(ctx, mapName)
|
||||
|
||||
// Add an element.
|
||||
err = m.AddElement("eth0", "return")
|
||||
err = m.AddElement(ctx, "eth0", "return")
|
||||
assert.Check(t, err)
|
||||
|
||||
// Check that it's an error to add the element again.
|
||||
err = m.AddElement("eth0", "return")
|
||||
err = m.AddElement(ctx, "eth0", "return")
|
||||
assert.Check(t, is.ErrorContains(err, "already contains element"))
|
||||
|
||||
// Fetch the existing vmap.
|
||||
m = tbl.InterfaceVMap(mapName)
|
||||
m = tbl.InterfaceVMap(ctx, mapName)
|
||||
|
||||
// Add another element.
|
||||
err = m.AddElement("eth1", "drop")
|
||||
err = m.AddElement(ctx, "eth1", "drop")
|
||||
assert.Check(t, err)
|
||||
|
||||
// Update nftables and check what happened.
|
||||
applyAndCheck(t, tbl, t.Name()+"_created.golden")
|
||||
|
||||
// Delete an element.
|
||||
err = m.DeleteElement("eth1")
|
||||
err = m.DeleteElement(ctx, "eth1")
|
||||
assert.Check(t, err)
|
||||
|
||||
// Check it's an error to delete it again.
|
||||
err = m.DeleteElement("eth1")
|
||||
err = m.DeleteElement(ctx, "eth1")
|
||||
assert.Check(t, is.ErrorContains(err, "does not contain element"))
|
||||
|
||||
// Update nftables and check what happened.
|
||||
@@ -199,6 +202,7 @@ func TestVMap(t *testing.T) {
|
||||
|
||||
func TestSet(t *testing.T) {
|
||||
defer testSetup(t)()
|
||||
ctx := context.Background()
|
||||
|
||||
// Create v4 and v6 tables.
|
||||
tbl4, err := NewTable(IPv4, "table4")
|
||||
@@ -207,19 +211,19 @@ func TestSet(t *testing.T) {
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Create a set in each table.
|
||||
s4 := tbl4.PrefixSet("set4")
|
||||
s6 := tbl6.PrefixSet("set6")
|
||||
s4 := tbl4.PrefixSet(ctx, "set4")
|
||||
s6 := tbl6.PrefixSet(ctx, "set6")
|
||||
|
||||
// Add elements to each set.
|
||||
err = s4.AddElement("192.0.2.1/24")
|
||||
err = s4.AddElement(ctx, "192.0.2.1/24")
|
||||
assert.Check(t, err)
|
||||
err = s6.AddElement("2001:db8::1/64")
|
||||
err = s6.AddElement(ctx, "2001:db8::1/64")
|
||||
assert.Check(t, err)
|
||||
|
||||
// Check it's an error to add those elements again.
|
||||
err = s4.AddElement("192.0.2.1/24")
|
||||
err = s4.AddElement(ctx, "192.0.2.1/24")
|
||||
assert.Check(t, is.ErrorContains(err, "already contains element"))
|
||||
err = s6.AddElement("2001:db8::1/64")
|
||||
err = s6.AddElement(ctx, "2001:db8::1/64")
|
||||
assert.Check(t, is.ErrorContains(err, "already contains element"))
|
||||
|
||||
// Update nftables and check what happened.
|
||||
@@ -227,15 +231,15 @@ func TestSet(t *testing.T) {
|
||||
applyAndCheck(t, tbl6, t.Name()+"_created46.golden")
|
||||
|
||||
// Delete elements.
|
||||
err = s4.DeleteElement("192.0.2.1/24")
|
||||
err = s4.DeleteElement(ctx, "192.0.2.1/24")
|
||||
assert.Check(t, err)
|
||||
err = s6.DeleteElement("2001:db8::1/64")
|
||||
err = s6.DeleteElement(ctx, "2001:db8::1/64")
|
||||
assert.Check(t, err)
|
||||
|
||||
// Check it's an error to delete those elements again.
|
||||
err = s4.DeleteElement("192.0.2.1/24")
|
||||
err = s4.DeleteElement(ctx, "192.0.2.1/24")
|
||||
assert.Check(t, is.ErrorContains(err, "does not contain element"))
|
||||
err = s6.DeleteElement("2001:db8::1/64")
|
||||
err = s6.DeleteElement(ctx, "2001:db8::1/64")
|
||||
assert.Check(t, is.ErrorContains(err, "does not contain element"))
|
||||
|
||||
// Update nftables and check what happened.
|
||||
@@ -245,21 +249,22 @@ func TestSet(t *testing.T) {
|
||||
|
||||
func TestReload(t *testing.T) {
|
||||
defer testSetup(t)()
|
||||
ctx := context.Background()
|
||||
|
||||
// Create a table with some stuff in it.
|
||||
const tableName = "this_is_a_table"
|
||||
tbl, err := NewTable(IPv4, tableName)
|
||||
assert.NilError(t, err)
|
||||
bc, err := tbl.BaseChain("a_base_chain", BaseChainTypeFilter, BaseChainHookForward, BaseChainPriorityFilter)
|
||||
bc, err := tbl.BaseChain(ctx, "a_base_chain", BaseChainTypeFilter, BaseChainHookForward, BaseChainPriorityFilter)
|
||||
assert.NilError(t, err)
|
||||
err = bc.AppendRule(0, "counter")
|
||||
err = bc.AppendRule(ctx, 0, "counter")
|
||||
assert.NilError(t, err)
|
||||
m := tbl.InterfaceVMap("this_is_a_vmap")
|
||||
err = m.AddElement("eth0", "return")
|
||||
m := tbl.InterfaceVMap(ctx, "this_is_a_vmap")
|
||||
err = m.AddElement(ctx, "eth0", "return")
|
||||
assert.Check(t, err)
|
||||
err = m.AddElement("eth1", "return")
|
||||
err = m.AddElement(ctx, "eth1", "return")
|
||||
assert.Check(t, err)
|
||||
err = tbl.PrefixSet("set4").AddElement("192.0.2.0/24")
|
||||
err = tbl.PrefixSet(ctx, "set4").AddElement(ctx, "192.0.2.0/24")
|
||||
assert.Check(t, err)
|
||||
applyAndCheck(t, tbl, t.Name()+"_created.golden")
|
||||
|
||||
@@ -284,7 +289,7 @@ func TestReload(t *testing.T) {
|
||||
|
||||
// Check implicit/recovery reload - only deleting something that's gone missing
|
||||
// from a vmap/set will trigger this.
|
||||
err = m.DeleteElement("eth1")
|
||||
err = m.DeleteElement(ctx, "eth1")
|
||||
assert.Check(t, err)
|
||||
applyAndCheck(t, tbl, t.Name()+"_recovered.golden")
|
||||
}
|
||||
|
||||
@@ -98,25 +98,25 @@ func (r *Resolver) setupNftablesNAT(ctx context.Context, laddr, ltcpaddr, resolv
|
||||
return err
|
||||
}
|
||||
|
||||
dnatChain, err := table.BaseChain("dns-dnat", nftables.BaseChainTypeNAT, nftables.BaseChainHookOutput, nftables.BaseChainPriorityDstNAT)
|
||||
dnatChain, err := table.BaseChain(ctx, "dns-dnat", nftables.BaseChainTypeNAT, nftables.BaseChainHookOutput, nftables.BaseChainPriorityDstNAT)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := dnatChain.AppendRule(0, "ip daddr %s udp dport %s counter dnat to %s", resolverIP, dnsPort, laddr); err != nil {
|
||||
if err := dnatChain.AppendRule(ctx, 0, "ip daddr %s udp dport %s counter dnat to %s", resolverIP, dnsPort, laddr); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := dnatChain.AppendRule(0, "ip daddr %s tcp dport %s counter dnat to %s", resolverIP, dnsPort, ltcpaddr); err != nil {
|
||||
if err := dnatChain.AppendRule(ctx, 0, "ip daddr %s tcp dport %s counter dnat to %s", resolverIP, dnsPort, ltcpaddr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
snatChain, err := table.BaseChain("dns-snat", nftables.BaseChainTypeNAT, nftables.BaseChainHookPostrouting, nftables.BaseChainPrioritySrcNAT)
|
||||
snatChain, err := table.BaseChain(ctx, "dns-snat", nftables.BaseChainTypeNAT, nftables.BaseChainHookPostrouting, nftables.BaseChainPrioritySrcNAT)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := snatChain.AppendRule(0, "ip saddr %s udp sport %s counter snat to :%s", resolverIP, ipPort, dnsPort); err != nil {
|
||||
if err := snatChain.AppendRule(ctx, 0, "ip saddr %s udp sport %s counter snat to :%s", resolverIP, ipPort, dnsPort); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := snatChain.AppendRule(0, "ip saddr %s tcp sport %s counter snat to :%s", resolverIP, tcpPort, dnsPort); err != nil {
|
||||
if err := snatChain.AppendRule(ctx, 0, "ip saddr %s tcp sport %s counter snat to :%s", resolverIP, tcpPort, dnsPort); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user