From b0a2c473e0bc34fe28aa738c677d78b77e7ba2df Mon Sep 17 00:00:00 2001 From: Ryan Whelan <4249368+rwhelan@users.noreply.github.com> Date: Mon, 13 May 2019 08:13:23 -0400 Subject: [PATCH] List tables (#16) list tables function --- table.go | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/table.go b/table.go index 23598a8..e25b566 100644 --- a/table.go +++ b/table.go @@ -15,23 +15,30 @@ package nftables import ( + "fmt" + "github.com/mdlayher/netlink" "golang.org/x/sys/unix" ) +var tableHeaderType = netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_NEWTABLE) + // TableFamily specifies the address family for this table. type TableFamily byte // Possible TableFamily values. const ( - TableFamilyIPv4 TableFamily = unix.AF_INET - TableFamilyIPv6 TableFamily = unix.AF_INET6 + TableFamilyIPv4 TableFamily = unix.AF_INET + TableFamilyIPv6 TableFamily = unix.AF_INET6 + TableFamilyBridge TableFamily = unix.AF_BRIDGE ) // A Table contains Chains. See also // https://wiki.nftables.org/wiki-nftables/index.php/Configuring_tables type Table struct { - Name string + Name string // NFTA_TABLE_NAME + Use uint32 // NFTA_TABLE_USE (Number of chains in table) + Flags uint32 // NFTA_TABLE_FLAGS Family TableFamily } @@ -66,3 +73,65 @@ func (cc *Conn) AddTable(t *Table) *Table { }) return t } + +// ListTables returns currently configured tables in the kernel +func (cc *Conn) ListTables() ([]*Table, error) { + conn, err := cc.dialNetlink() + if err != nil { + return nil, err + } + + defer conn.Close() + + msg := netlink.Message{ + Header: netlink.Header{ + Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_GETTABLE), + Flags: netlink.Request | netlink.Dump, + }, + Data: extraHeader(uint8(unix.AF_UNSPEC), 0), + } + + response, err := conn.Execute(msg) + if err != nil { + return nil, err + } + + var tables []*Table + for _, m := range response { + t, err := tableFromMsg(m) + if err != nil { + return nil, err + } + + tables = append(tables, t) + } + + return tables, nil +} + +func tableFromMsg(msg netlink.Message) (*Table, error) { + if got, want := msg.Header.Type, tableHeaderType; got != want { + return nil, fmt.Errorf("unexpected header type: got %v, want %v", got, want) + } + + var t Table + t.Family = TableFamily(msg.Data[0]) + + ad, err := netlink.NewAttributeDecoder(msg.Data[4:]) + if err != nil { + return nil, err + } + + for ad.Next() { + switch ad.Type() { + case unix.NFTA_TABLE_NAME: + t.Name = ad.String() + case unix.NFTA_TABLE_USE: + t.Use = ad.Uint32() + case unix.NFTA_TABLE_FLAGS: + t.Flags = ad.Uint32() + } + } + + return &t, nil +}