in pkg/iptableswrapper/fake_iptables.go [96:157]
func (f *FakeIPTables) restoreTable(newDump *iptest.IPTablesDump, newTable *iptest.Table, flush iptables.FlushFlag, counters iptables.RestoreCountersFlag) error {
oldTable, err := f.fake.Dump.GetTable(newTable.Name)
if err != nil {
return err
}
backupChains := make([]iptest.Chain, len(oldTable.Chains))
copy(backupChains, oldTable.Chains)
// Update internal state
if flush == iptables.FlushTables {
oldTable.Chains = make([]iptest.Chain, 0, len(newTable.Chains))
}
for _, newChain := range newTable.Chains {
oldChain, _ := f.fake.Dump.GetChain(newTable.Name, newChain.Name)
switch {
case oldChain == nil && newChain.Deleted:
// no-op
case oldChain == nil && !newChain.Deleted:
oldTable.Chains = append(oldTable.Chains, newChain)
case oldChain != nil && newChain.Deleted:
_ = f.DeleteChain(newTable.Name, newChain.Name)
case oldChain != nil && !newChain.Deleted:
// replace old data with new
oldChain.Rules = newChain.Rules
if counters == iptables.RestoreCounters {
oldChain.Packets = newChain.Packets
oldChain.Bytes = newChain.Bytes
}
}
}
// Now check that all old/new jumps are valid
for _, chain := range oldTable.Chains {
for _, rule := range chain.Rules {
if rule.Jump == nil {
continue
}
if f.builtinTargets.Has(rule.Jump.Value) {
continue
}
jumpedChain, _ := f.fake.Dump.GetChain(oldTable.Name, iptables.Chain(rule.Jump.Value))
if jumpedChain == nil {
newChain, _ := newDump.GetChain(oldTable.Name, iptables.Chain(rule.Jump.Value))
if newChain != nil {
// rule is an old rule that jumped to a chain which
// was deleted by newDump.
oldTable.Chains = backupChains
return fmt.Errorf("deleted chain %q is referenced by existing rules", newChain.Name)
} else {
// rule is a new rule that jumped to a chain that was
// neither created nor pre-existing
oldTable.Chains = backupChains
return fmt.Errorf("rule %q jumps to a non-existent chain", rule.Raw)
}
}
}
}
return nil
}