chain_linux.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. package netlink
  2. import (
  3. "errors"
  4. "github.com/vishvananda/netlink/nl"
  5. "golang.org/x/sys/unix"
  6. )
  7. // ChainDel will delete a chain from the system.
  8. func ChainDel(link Link, chain Chain) error {
  9. // Equivalent to: `tc chain del $chain`
  10. return pkgHandle.ChainDel(link, chain)
  11. }
  12. // ChainDel will delete a chain from the system.
  13. // Equivalent to: `tc chain del $chain`
  14. func (h *Handle) ChainDel(link Link, chain Chain) error {
  15. return h.chainModify(unix.RTM_DELCHAIN, 0, link, chain)
  16. }
  17. // ChainAdd will add a chain to the system.
  18. // Equivalent to: `tc chain add`
  19. func ChainAdd(link Link, chain Chain) error {
  20. return pkgHandle.ChainAdd(link, chain)
  21. }
  22. // ChainAdd will add a chain to the system.
  23. // Equivalent to: `tc chain add`
  24. func (h *Handle) ChainAdd(link Link, chain Chain) error {
  25. return h.chainModify(
  26. unix.RTM_NEWCHAIN,
  27. unix.NLM_F_CREATE|unix.NLM_F_EXCL,
  28. link,
  29. chain)
  30. }
  31. func (h *Handle) chainModify(cmd, flags int, link Link, chain Chain) error {
  32. req := h.newNetlinkRequest(cmd, flags|unix.NLM_F_ACK)
  33. index := int32(0)
  34. if link != nil {
  35. base := link.Attrs()
  36. h.ensureIndex(base)
  37. index = int32(base.Index)
  38. }
  39. msg := &nl.TcMsg{
  40. Family: nl.FAMILY_ALL,
  41. Ifindex: index,
  42. Parent: chain.Parent,
  43. }
  44. req.AddData(msg)
  45. req.AddData(nl.NewRtAttr(nl.TCA_CHAIN, nl.Uint32Attr(chain.Chain)))
  46. _, err := req.Execute(unix.NETLINK_ROUTE, 0)
  47. return err
  48. }
  49. // ChainList gets a list of chains in the system.
  50. // Equivalent to: `tc chain list`.
  51. // The list can be filtered by link.
  52. //
  53. // If the returned error is [ErrDumpInterrupted], results may be inconsistent
  54. // or incomplete.
  55. func ChainList(link Link, parent uint32) ([]Chain, error) {
  56. return pkgHandle.ChainList(link, parent)
  57. }
  58. // ChainList gets a list of chains in the system.
  59. // Equivalent to: `tc chain list`.
  60. // The list can be filtered by link.
  61. //
  62. // If the returned error is [ErrDumpInterrupted], results may be inconsistent
  63. // or incomplete.
  64. func (h *Handle) ChainList(link Link, parent uint32) ([]Chain, error) {
  65. req := h.newNetlinkRequest(unix.RTM_GETCHAIN, unix.NLM_F_DUMP)
  66. index := int32(0)
  67. if link != nil {
  68. base := link.Attrs()
  69. h.ensureIndex(base)
  70. index = int32(base.Index)
  71. }
  72. msg := &nl.TcMsg{
  73. Family: nl.FAMILY_ALL,
  74. Ifindex: index,
  75. Parent: parent,
  76. }
  77. req.AddData(msg)
  78. msgs, executeErr := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWCHAIN)
  79. if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) {
  80. return nil, executeErr
  81. }
  82. var res []Chain
  83. for _, m := range msgs {
  84. msg := nl.DeserializeTcMsg(m)
  85. attrs, err := nl.ParseRouteAttr(m[msg.Len():])
  86. if err != nil {
  87. return nil, err
  88. }
  89. // skip chains from other interfaces
  90. if link != nil && msg.Ifindex != index {
  91. continue
  92. }
  93. var chain Chain
  94. for _, attr := range attrs {
  95. switch attr.Attr.Type {
  96. case nl.TCA_CHAIN:
  97. chain.Chain = native.Uint32(attr.Value)
  98. chain.Parent = parent
  99. }
  100. }
  101. res = append(res, chain)
  102. }
  103. return res, executeErr
  104. }