MagiTrickle/recoverable-iptables/recoverable-iptables.go
2024-09-06 14:24:55 +03:00

125 lines
2.6 KiB
Go

package recoverableIPTables
import (
"github.com/coreos/go-iptables/iptables"
"reflect"
)
type IPTablesRule struct {
Position int
RuleSpec []string
}
type IPTables struct {
ipt *iptables.IPTables
cache map[string]map[string][]IPTablesRule
}
/*
* Chain
*/
func (r *IPTables) clearChain(table, chain string) {
if r.cache[table] == nil {
r.cache[table] = make(map[string][]IPTablesRule)
}
r.cache[table][chain] = nil
}
func (r *IPTables) delChain(table, chain string) {
if r.cache[table] == nil {
return
}
delete(r.cache[table], chain)
}
/*
* Rule
*/
func (r *IPTables) delRule(table, chain string, rulespec ...string) {
if r.cache[table] == nil {
r.cache[table] = make(map[string][]IPTablesRule)
}
for idx, rule := range r.cache[table][chain] {
if !reflect.DeepEqual(rulespec, rule.RuleSpec) {
continue
}
copy(r.cache[table][chain][idx:], r.cache[table][chain][idx+1:])
r.cache[table][chain] = r.cache[table][chain][:len(r.cache[table][chain])-1]
break
}
}
func (r *IPTables) addRuleUnique(table, chain string, position int, rulespec ...string) {
if r.cache[table] == nil {
r.cache[table] = make(map[string][]IPTablesRule)
}
for _, rule := range r.cache[table][chain] {
if reflect.DeepEqual(rulespec, rule.RuleSpec) {
return
}
}
r.cache[table][chain] = append(r.cache[table][chain], IPTablesRule{
Position: position,
RuleSpec: rulespec,
})
}
/*
* Mappings
*/
func (r *IPTables) ClearChain(table, chain string) error {
err := r.ipt.ClearChain(table, chain)
if err != nil {
return err
}
r.clearChain(table, chain)
return nil
}
func (r *IPTables) ClearAndDeleteChain(table, chain string) error {
err := r.ipt.ClearAndDeleteChain(table, chain)
if err != nil {
return err
}
r.delChain(table, chain)
return nil
}
func (r *IPTables) AppendUnique(table, chain string, rulespec ...string) error {
err := r.ipt.AppendUnique(table, chain, rulespec...)
if err != nil {
return err
}
r.addRuleUnique(table, chain, 0, rulespec...)
return nil
}
func (r *IPTables) InsertUnique(table, chain string, pos int, rulespec ...string) error {
err := r.ipt.InsertUnique(table, chain, pos, rulespec...)
if err != nil {
return err
}
r.addRuleUnique(table, chain, pos, rulespec...)
return nil
}
func (r *IPTables) DeleteIfExists(table, chain string, rulespec ...string) error {
err := r.ipt.DeleteIfExists(table, chain, rulespec...)
if err != nil {
return err
}
r.delRule(table, chain, rulespec...)
return nil
}
func New() (*IPTables, error) {
ipt, err := iptables.New()
return &IPTables{
ipt: ipt,
cache: make(map[string]map[string][]IPTablesRule),
}, err
}