diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml old mode 100644 new mode 100755 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9f11b75 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md old mode 100644 new mode 100755 diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 index cb633c7..5853f92 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ [![Build Status](https://github.com/google/nftables/actions/workflows/push.yml/badge.svg)](https://github.com/google/nftables/actions/workflows/push.yml) [![GoDoc](https://godoc.org/github.com/google/nftables?status.svg)](https://godoc.org/github.com/google/nftables) +## 1. Introduction **This is not the correct repository for issues with the Linux nftables project!** This repository contains a third-party Go package to programmatically interact with nftables. Find the official nftables website at @@ -11,14 +12,70 @@ implemented in pure Go, i.e. does not wrap libnftnl. This is not an official Google product. -## Breaking changes +## 2. Breaking changes This package is in very early stages, and only contains enough data types and functions to install very basic nftables rules. It is likely that mistakes with the data types/API will be identified as more functionality is added. -## Contributions +## 3. Contributions Contributions are very welcome! +## 4. Examples + +### 1. Get common data types of Nftables + +#### 1.1. Get table by net family and its name + +```go +conn := nftables.Conn{} // start up a conn + +table, _ := conn.GetTable("nat", nftables.TableFamilyIPv4) +fmt.Println(table.Name) +``` +#### 1.2. Get chain by chain's name + +```go +conn := nftables.Conn{} // start up a conn +chain, _ := conn.GetChain("POSTROUTING") // get chain +fmt.Println(chain.Name) +``` + +#### 1.3. Get set and set's elements by table and set's name + +```go +conn := nftables.Conn{} // start up a conn + +table, _ := conn.GetTable("nat", nftables.TableFamilyIPv4) // get table + + +set, _ := conn.GetSetByName(table, "dest_addrs") // get set +fmt.Println(set.Name) + +eles, _ := conn.GetSetElements(set) +fmt.Println(eles) +``` + +#### 1.4. Get rules by table and chain + +```go + conn := nftables.Conn{} // start up a conn + + table, _ := conn.GetTable("nat", nftables.TableFamilyIPv4) // get table + chain, _ := conn.GetChain("POSTROUTING") // get chain + + rules, _ := conn.GetRule(table, chain) // get rules + for _, rule := range rules { + fmt.Println(rule.Table.Name, rule.Table.Family, rule.Chain.Name, rule.Handle) + // unpack exprs + for _, expr := range rule.Exprs { + fmt.Println(expr) + } + } +``` + +### 2. Insert common data types of Nftables + +**wait for update** \ No newline at end of file diff --git a/binaryutil/binaryutil.go b/binaryutil/binaryutil.go old mode 100644 new mode 100755 diff --git a/chain.go b/chain.go old mode 100644 new mode 100755 index 74caca5..1a4a445 --- a/chain.go +++ b/chain.go @@ -205,6 +205,20 @@ func (cc *Conn) ListChains() ([]*Chain, error) { return chains, nil } +// GetChain gets a chain by name +func (cc *Conn) GetChain(name string) (*Chain, error) { + chains, err := cc.ListChains() + if err != nil { + return nil, err + } + for _, chain := range chains { + if chain.Name == name { + return chain, nil + } + } + return nil, nil +} + func chainFromMsg(msg netlink.Message) (*Chain, error) { chainHeaderType := netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_NEWCHAIN) if got, want := msg.Header.Type, chainHeaderType; got != want { diff --git a/conn.go b/conn.go old mode 100644 new mode 100755 diff --git a/counter.go b/counter.go old mode 100644 new mode 100755 diff --git a/doc.go b/doc.go old mode 100644 new mode 100755 diff --git a/expr/bitwise.go b/expr/bitwise.go old mode 100644 new mode 100755 diff --git a/expr/bitwise_test.go b/expr/bitwise_test.go old mode 100644 new mode 100755 diff --git a/expr/byteorder.go b/expr/byteorder.go old mode 100644 new mode 100755 diff --git a/expr/counter.go b/expr/counter.go old mode 100644 new mode 100755 diff --git a/expr/ct.go b/expr/ct.go old mode 100644 new mode 100755 diff --git a/expr/dup.go b/expr/dup.go old mode 100644 new mode 100755 diff --git a/expr/dynset.go b/expr/dynset.go old mode 100644 new mode 100755 diff --git a/expr/expr.go b/expr/expr.go old mode 100644 new mode 100755 diff --git a/expr/exthdr.go b/expr/exthdr.go old mode 100644 new mode 100755 diff --git a/expr/fib.go b/expr/fib.go old mode 100644 new mode 100755 diff --git a/expr/hash.go b/expr/hash.go old mode 100644 new mode 100755 diff --git a/expr/immediate.go b/expr/immediate.go old mode 100644 new mode 100755 diff --git a/expr/limit.go b/expr/limit.go old mode 100644 new mode 100755 diff --git a/expr/log.go b/expr/log.go old mode 100644 new mode 100755 diff --git a/expr/lookup.go b/expr/lookup.go old mode 100644 new mode 100755 diff --git a/expr/nat.go b/expr/nat.go old mode 100644 new mode 100755 diff --git a/expr/notrack.go b/expr/notrack.go old mode 100644 new mode 100755 diff --git a/expr/numgen.go b/expr/numgen.go old mode 100644 new mode 100755 diff --git a/expr/objref.go b/expr/objref.go old mode 100644 new mode 100755 diff --git a/expr/payload.go b/expr/payload.go old mode 100644 new mode 100755 diff --git a/expr/queue.go b/expr/queue.go old mode 100644 new mode 100755 diff --git a/expr/range.go b/expr/range.go old mode 100644 new mode 100755 diff --git a/expr/redirect.go b/expr/redirect.go old mode 100644 new mode 100755 diff --git a/expr/reject.go b/expr/reject.go old mode 100644 new mode 100755 diff --git a/expr/rt.go b/expr/rt.go old mode 100644 new mode 100755 diff --git a/expr/tproxy.go b/expr/tproxy.go old mode 100644 new mode 100755 diff --git a/expr/verdict.go b/expr/verdict.go old mode 100644 new mode 100755 diff --git a/go.mod b/go.mod old mode 100644 new mode 100755 diff --git a/go.sum b/go.sum old mode 100644 new mode 100755 diff --git a/nftables_test.go b/nftables_test.go old mode 100644 new mode 100755 diff --git a/obj.go b/obj.go old mode 100644 new mode 100755 diff --git a/rule.go b/rule.go old mode 100644 new mode 100755 index ec4ce1f..d55e2d0 --- a/rule.go +++ b/rule.go @@ -84,7 +84,10 @@ func (cc *Conn) GetRule(t *Table, c *Chain) ([]*Rule, error) { if err != nil { return nil, err } - rules = append(rules, r) + + if r.Table.Name == t.Name && r.Table.Family == t.Family && r.Chain.Name == c.Name { + rules = append(rules, r) + } } return rules, nil @@ -293,6 +296,7 @@ func ruleFromMsg(msg netlink.Message) (*Rule, error) { switch ad.Type() { case unix.NFTA_RULE_TABLE: r.Table = &Table{Name: ad.String()} + r.Table.Family = TableFamily(msg.Data[0]) case unix.NFTA_RULE_CHAIN: r.Chain = &Chain{Name: ad.String()} case unix.NFTA_RULE_EXPRESSIONS: diff --git a/set.go b/set.go old mode 100644 new mode 100755 diff --git a/set_test.go b/set_test.go old mode 100644 new mode 100755 diff --git a/table.go b/table.go old mode 100644 new mode 100755 index da0126a..9f8c99c --- a/table.go +++ b/table.go @@ -45,6 +45,23 @@ type Table struct { Family TableFamily } +// GetTable gets a table by name and family +func (cc *Conn) GetTable(name string, family TableFamily) (*Table, error) { + cc.Lock() + defer cc.Unlock() + + tables, err := cc.ListTables() + if err != nil { + return nil, err + } + for _, table := range tables { + if table.Name == name && table.Family == family { + return table, nil + } + } + return nil, nil +} + // DelTable deletes a specific table, along with all chains/rules it contains. func (cc *Conn) DelTable(t *Table) { cc.Lock() diff --git a/tests/get_data_test.go b/tests/get_data_test.go new file mode 100644 index 0000000..919088e --- /dev/null +++ b/tests/get_data_test.go @@ -0,0 +1,52 @@ +package tests + +import ( + "fmt" + "github.com/google/nftables" + "testing" +) + +// Get table by net family and its name +func TestGetTable(t *testing.T) { + conn := nftables.Conn{} // start up a conn + + table, _ := conn.GetTable("nat", nftables.TableFamilyIPv4) + fmt.Println(table.Name) +} + +// Get chain by chain's name +func TestGetChain(t *testing.T) { + conn := nftables.Conn{} // start up a conn + chain, _ := conn.GetChain("POSTROUTING") // get chain + fmt.Println(chain.Name) +} + +// Get set and set's elements by table and set's name +func TestGetSet(t *testing.T) { + conn := nftables.Conn{} // start up a conn + + table, _ := conn.GetTable("nat", nftables.TableFamilyIPv4) // get table + + set, _ := conn.GetSetByName(table, "dest_addrs") // get set + fmt.Println(set.Name) + + eles, _ := conn.GetSetElements(set) + fmt.Println(eles) +} + +// Get rules by table and chain +func TestGetRules(t *testing.T) { + conn := nftables.Conn{} // start up a conn + + table, _ := conn.GetTable("nat", nftables.TableFamilyIPv4) // get table + chain, _ := conn.GetChain("POSTROUTING") // get chain + + rules, _ := conn.GetRule(table, chain) // get rules + for _, rule := range rules { + fmt.Println(rule.Table.Name, rule.Table.Family, rule.Chain.Name, rule.Handle) + // unpack exprs + for _, expr := range rule.Exprs { + fmt.Println(expr) + } + } +} \ No newline at end of file diff --git a/util.go b/util.go old mode 100644 new mode 100755