quota.go 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  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 expr
  15. import (
  16. "encoding/binary"
  17. "github.com/google/nftables/binaryutil"
  18. "github.com/mdlayher/netlink"
  19. "golang.org/x/sys/unix"
  20. )
  21. // Quota defines a threshold against a number of bytes.
  22. type Quota struct {
  23. Bytes uint64
  24. Consumed uint64
  25. Over bool
  26. }
  27. func (q *Quota) marshal(fam byte) ([]byte, error) {
  28. attrs := []netlink.Attribute{
  29. {Type: unix.NFTA_QUOTA_BYTES, Data: binaryutil.BigEndian.PutUint64(q.Bytes)},
  30. {Type: unix.NFTA_QUOTA_CONSUMED, Data: binaryutil.BigEndian.PutUint64(q.Consumed)},
  31. }
  32. flags := uint32(0)
  33. if q.Over {
  34. flags = unix.NFT_QUOTA_F_INV
  35. }
  36. attrs = append(attrs, netlink.Attribute{
  37. Type: unix.NFTA_QUOTA_FLAGS,
  38. Data: binaryutil.BigEndian.PutUint32(flags),
  39. })
  40. data, err := netlink.MarshalAttributes(attrs)
  41. if err != nil {
  42. return nil, err
  43. }
  44. return netlink.MarshalAttributes([]netlink.Attribute{
  45. {Type: unix.NFTA_EXPR_NAME, Data: []byte("quota\x00")},
  46. {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
  47. })
  48. }
  49. func (q *Quota) unmarshal(fam byte, data []byte) error {
  50. ad, err := netlink.NewAttributeDecoder(data)
  51. if err != nil {
  52. return err
  53. }
  54. ad.ByteOrder = binary.BigEndian
  55. for ad.Next() {
  56. switch ad.Type() {
  57. case unix.NFTA_QUOTA_BYTES:
  58. q.Bytes = ad.Uint64()
  59. case unix.NFTA_QUOTA_CONSUMED:
  60. q.Consumed = ad.Uint64()
  61. case unix.NFTA_QUOTA_FLAGS:
  62. q.Over = (ad.Uint32() & unix.NFT_QUOTA_F_INV) == 1
  63. }
  64. }
  65. return ad.Err()
  66. }