table.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // Copyright 2018 Google LLC. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package nftables
  15. import (
  16. "fmt"
  17. "github.com/mdlayher/netlink"
  18. "golang.org/x/sys/unix"
  19. )
  20. var tableHeaderType = netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_NEWTABLE)
  21. // TableFamily specifies the address family for this table.
  22. type TableFamily byte
  23. // Possible TableFamily values.
  24. const (
  25. TableFamilyUnspecified TableFamily = unix.NFPROTO_UNSPEC
  26. TableFamilyINet TableFamily = unix.NFPROTO_INET
  27. TableFamilyIPv4 TableFamily = unix.NFPROTO_IPV4
  28. TableFamilyIPv6 TableFamily = unix.NFPROTO_IPV6
  29. TableFamilyARP TableFamily = unix.NFPROTO_ARP
  30. TableFamilyNetdev TableFamily = unix.NFPROTO_NETDEV
  31. TableFamilyBridge TableFamily = unix.NFPROTO_BRIDGE
  32. )
  33. // A Table contains Chains. See also
  34. // https://wiki.nftables.org/wiki-nftables/index.php/Configuring_tables
  35. type Table struct {
  36. Name string // NFTA_TABLE_NAME
  37. Use uint32 // NFTA_TABLE_USE (Number of chains in table)
  38. Flags uint32 // NFTA_TABLE_FLAGS
  39. Family TableFamily
  40. }
  41. // DelTable deletes a specific table, along with all chains/rules it contains.
  42. func (cc *Conn) DelTable(t *Table) {
  43. cc.mu.Lock()
  44. defer cc.mu.Unlock()
  45. data := cc.marshalAttr([]netlink.Attribute{
  46. {Type: unix.NFTA_TABLE_NAME, Data: []byte(t.Name + "\x00")},
  47. {Type: unix.NFTA_TABLE_FLAGS, Data: []byte{0, 0, 0, 0}},
  48. })
  49. cc.messages = append(cc.messages, netlink.Message{
  50. Header: netlink.Header{
  51. Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_DELTABLE),
  52. Flags: netlink.Request | netlink.Acknowledge,
  53. },
  54. Data: append(extraHeader(uint8(t.Family), 0), data...),
  55. })
  56. }
  57. // AddTable adds the specified Table. See also
  58. // https://wiki.nftables.org/wiki-nftables/index.php/Configuring_tables
  59. func (cc *Conn) AddTable(t *Table) *Table {
  60. cc.mu.Lock()
  61. defer cc.mu.Unlock()
  62. data := cc.marshalAttr([]netlink.Attribute{
  63. {Type: unix.NFTA_TABLE_NAME, Data: []byte(t.Name + "\x00")},
  64. {Type: unix.NFTA_TABLE_FLAGS, Data: []byte{0, 0, 0, 0}},
  65. })
  66. cc.messages = append(cc.messages, netlink.Message{
  67. Header: netlink.Header{
  68. Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_NEWTABLE),
  69. Flags: netlink.Request | netlink.Acknowledge | netlink.Create,
  70. },
  71. Data: append(extraHeader(uint8(t.Family), 0), data...),
  72. })
  73. return t
  74. }
  75. // FlushTable removes all rules in all chains within the specified Table. See also
  76. // https://wiki.nftables.org/wiki-nftables/index.php/Configuring_tables#Flushing_tables
  77. func (cc *Conn) FlushTable(t *Table) {
  78. cc.mu.Lock()
  79. defer cc.mu.Unlock()
  80. data := cc.marshalAttr([]netlink.Attribute{
  81. {Type: unix.NFTA_RULE_TABLE, Data: []byte(t.Name + "\x00")},
  82. })
  83. cc.messages = append(cc.messages, netlink.Message{
  84. Header: netlink.Header{
  85. Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_DELRULE),
  86. Flags: netlink.Request | netlink.Acknowledge,
  87. },
  88. Data: append(extraHeader(uint8(t.Family), 0), data...),
  89. })
  90. }
  91. // ListTables returns currently configured tables in the kernel
  92. func (cc *Conn) ListTables() ([]*Table, error) {
  93. return cc.ListTablesOfFamily(TableFamilyUnspecified)
  94. }
  95. // ListTablesOfFamily returns currently configured tables for the specified table family
  96. // in the kernel. It lists all tables if family is TableFamilyUnspecified.
  97. func (cc *Conn) ListTablesOfFamily(family TableFamily) ([]*Table, error) {
  98. conn, closer, err := cc.netlinkConn()
  99. if err != nil {
  100. return nil, err
  101. }
  102. defer func() { _ = closer() }()
  103. msg := netlink.Message{
  104. Header: netlink.Header{
  105. Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_GETTABLE),
  106. Flags: netlink.Request | netlink.Dump,
  107. },
  108. Data: extraHeader(uint8(family), 0),
  109. }
  110. response, err := conn.Execute(msg)
  111. if err != nil {
  112. return nil, err
  113. }
  114. var tables []*Table
  115. for _, m := range response {
  116. t, err := tableFromMsg(m)
  117. if err != nil {
  118. return nil, err
  119. }
  120. tables = append(tables, t)
  121. }
  122. return tables, nil
  123. }
  124. func tableFromMsg(msg netlink.Message) (*Table, error) {
  125. if got, want := msg.Header.Type, tableHeaderType; got != want {
  126. return nil, fmt.Errorf("unexpected header type: got %v, want %v", got, want)
  127. }
  128. var t Table
  129. t.Family = TableFamily(msg.Data[0])
  130. ad, err := netlink.NewAttributeDecoder(msg.Data[4:])
  131. if err != nil {
  132. return nil, err
  133. }
  134. for ad.Next() {
  135. switch ad.Type() {
  136. case unix.NFTA_TABLE_NAME:
  137. t.Name = ad.String()
  138. case unix.NFTA_TABLE_USE:
  139. t.Use = ad.Uint32()
  140. case unix.NFTA_TABLE_FLAGS:
  141. t.Flags = ad.Uint32()
  142. }
  143. }
  144. return &t, nil
  145. }