exthdr.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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. type ExthdrOp uint32
  22. const (
  23. ExthdrOpIpv6 ExthdrOp = unix.NFT_EXTHDR_OP_IPV6
  24. ExthdrOpTcpopt ExthdrOp = unix.NFT_EXTHDR_OP_TCPOPT
  25. )
  26. type Exthdr struct {
  27. DestRegister uint32
  28. Type uint8
  29. Offset uint32
  30. Len uint32
  31. Flags uint32
  32. Op ExthdrOp
  33. SourceRegister uint32
  34. }
  35. func (e *Exthdr) marshal(fam byte) ([]byte, error) {
  36. var attr []netlink.Attribute
  37. // Operations are differentiated by the Op and whether the SourceRegister
  38. // or DestRegister is set. Mixing them results in EOPNOTSUPP.
  39. if e.SourceRegister != 0 {
  40. attr = []netlink.Attribute{
  41. {Type: unix.NFTA_EXTHDR_SREG, Data: binaryutil.BigEndian.PutUint32(e.SourceRegister)}}
  42. } else {
  43. attr = []netlink.Attribute{
  44. {Type: unix.NFTA_EXTHDR_DREG, Data: binaryutil.BigEndian.PutUint32(e.DestRegister)}}
  45. }
  46. attr = append(attr,
  47. netlink.Attribute{Type: unix.NFTA_EXTHDR_TYPE, Data: []byte{e.Type}},
  48. netlink.Attribute{Type: unix.NFTA_EXTHDR_OFFSET, Data: binaryutil.BigEndian.PutUint32(e.Offset)},
  49. netlink.Attribute{Type: unix.NFTA_EXTHDR_LEN, Data: binaryutil.BigEndian.PutUint32(e.Len)},
  50. netlink.Attribute{Type: unix.NFTA_EXTHDR_OP, Data: binaryutil.BigEndian.PutUint32(uint32(e.Op))})
  51. // Flags is only set if DREG is set
  52. if e.DestRegister != 0 {
  53. attr = append(attr,
  54. netlink.Attribute{Type: unix.NFTA_EXTHDR_FLAGS, Data: binaryutil.BigEndian.PutUint32(e.Flags)})
  55. }
  56. data, err := netlink.MarshalAttributes(attr)
  57. if err != nil {
  58. return nil, err
  59. }
  60. return netlink.MarshalAttributes([]netlink.Attribute{
  61. {Type: unix.NFTA_EXPR_NAME, Data: []byte("exthdr\x00")},
  62. {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
  63. })
  64. }
  65. func (e *Exthdr) unmarshal(fam byte, data []byte) error {
  66. ad, err := netlink.NewAttributeDecoder(data)
  67. if err != nil {
  68. return err
  69. }
  70. ad.ByteOrder = binary.BigEndian
  71. for ad.Next() {
  72. switch ad.Type() {
  73. case unix.NFTA_EXTHDR_DREG:
  74. e.DestRegister = ad.Uint32()
  75. case unix.NFTA_EXTHDR_TYPE:
  76. e.Type = ad.Uint8()
  77. case unix.NFTA_EXTHDR_OFFSET:
  78. e.Offset = ad.Uint32()
  79. case unix.NFTA_EXTHDR_LEN:
  80. e.Len = ad.Uint32()
  81. case unix.NFTA_EXTHDR_FLAGS:
  82. e.Flags = ad.Uint32()
  83. case unix.NFTA_EXTHDR_OP:
  84. e.Op = ExthdrOp(ad.Uint32())
  85. case unix.NFTA_EXTHDR_SREG:
  86. e.SourceRegister = ad.Uint32()
  87. }
  88. }
  89. return ad.Err()
  90. }