package nftables import ( "fmt" "github.com/google/nftables" ) type ForeignRule struct { Table string Chain string Handle uint64 Family nftables.TableFamily table *nftables.Table chain *nftables.Chain } func (f ForeignRule) String() string { return fmt.Sprintf("table=%s chain=%s handle=%d", f.Table, f.Chain, f.Handle) } func (e *Engine) FindForeignRules() ([]ForeignRule, error) { tables, err := e.conn.ListTables() if err != nil { return nil, fmt.Errorf("listing tables: %w", err) } var ourTable *nftables.Table for _, t := range tables { if t.Name == e.cfg.Settings.TableName && t.Family == nftables.TableFamilyINet { ourTable = t break } } if ourTable == nil { return nil, nil } compiler := NewCompiler(e.cfg) desired, err := compiler.Compile() if err != nil { return nil, fmt.Errorf("compiling config: %w", err) } desiredTags := make(map[string]bool) for _, rules := range desired.Rules { for _, r := range rules { desiredTags[r.Tag] = true } } var foreign []ForeignRule chains, err := e.conn.ListChainsOfTableFamily(nftables.TableFamilyINet) if err != nil { return nil, fmt.Errorf("listing chains: %w", err) } for _, chain := range chains { if chain.Table.Name != e.cfg.Settings.TableName { continue } rules, err := e.conn.GetRules(ourTable, chain) if err != nil { continue } for _, rule := range rules { tag := string(rule.UserData) if tag == "" || !desiredTags[tag] { foreign = append(foreign, ForeignRule{ Table: ourTable.Name, Chain: chain.Name, Handle: rule.Handle, Family: ourTable.Family, table: ourTable, chain: chain, }) } } } return foreign, nil } func (e *Engine) PurgeForeignRules(foreign []ForeignRule) error { for _, f := range foreign { e.conn.DelRule(&nftables.Rule{ Table: f.table, Chain: f.chain, Handle: f.Handle, }) } return e.conn.Flush() }