Update dependencies
This commit is contained in:
23
vendor/github.com/google/nftables/CONTRIBUTING.md
generated
vendored
Normal file
23
vendor/github.com/google/nftables/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
# How to Contribute
|
||||
|
||||
We'd love to accept your patches and contributions to this project. There are
|
||||
just a few small guidelines you need to follow.
|
||||
|
||||
## Contributor License Agreement
|
||||
|
||||
Contributions to this project must be accompanied by a Contributor License
|
||||
Agreement. You (or your employer) retain the copyright to your contribution,
|
||||
this simply gives us permission to use and redistribute your contributions as
|
||||
part of the project. Head over to <https://cla.developers.google.com/> to see
|
||||
your current agreements on file or to sign a new one.
|
||||
|
||||
You generally only need to submit a CLA once, so if you've already submitted one
|
||||
(even if it was for a different project), you probably don't need to do it
|
||||
again.
|
||||
|
||||
## Code reviews
|
||||
|
||||
All submissions, including submissions by project members, require review. We
|
||||
use GitHub pull requests for this purpose. Consult
|
||||
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
|
||||
information on using pull requests.
|
||||
202
vendor/github.com/google/nftables/LICENSE
generated
vendored
Normal file
202
vendor/github.com/google/nftables/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
24
vendor/github.com/google/nftables/README.md
generated
vendored
Normal file
24
vendor/github.com/google/nftables/README.md
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
[](https://github.com/google/nftables/actions/workflows/push.yml)
|
||||
[](https://godoc.org/github.com/google/nftables)
|
||||
|
||||
**This is not the correct repository for issues with the Linux nftables
|
||||
project!** This repository contains a third-party Go package to programmatically
|
||||
interact with nftables. Find the official nftables website at
|
||||
https://wiki.nftables.org/
|
||||
|
||||
This package manipulates Linux nftables (the iptables successor). It is
|
||||
implemented in pure Go, i.e. does not wrap libnftnl.
|
||||
|
||||
This is not an official Google product.
|
||||
|
||||
## Breaking changes
|
||||
|
||||
This package is in very early stages, and only contains enough data types and
|
||||
functions to install very basic nftables rules. It is likely that mistakes with
|
||||
the data types/API will be identified as more functionality is added.
|
||||
|
||||
## Contributions
|
||||
|
||||
Contributions are very welcome!
|
||||
|
||||
|
||||
300
vendor/github.com/google/nftables/alignedbuff/alignedbuff.go
generated
vendored
Normal file
300
vendor/github.com/google/nftables/alignedbuff/alignedbuff.go
generated
vendored
Normal file
@@ -0,0 +1,300 @@
|
||||
// Package alignedbuff implements encoding and decoding aligned data elements
|
||||
// to/from buffers in native endianess.
|
||||
//
|
||||
// # Note
|
||||
//
|
||||
// The alignment/padding as implemented in this package must match that of
|
||||
// kernel's and user space C implementations for a particular architecture (bit
|
||||
// size). Please see also the "dummy structure" _xt_align
|
||||
// (https://elixir.bootlin.com/linux/v5.17.7/source/include/uapi/linux/netfilter/x_tables.h#L93)
|
||||
// as well as the associated XT_ALIGN C preprocessor macro.
|
||||
//
|
||||
// In particular, we rely on the Go compiler to follow the same architecture
|
||||
// alignments as the C compiler(s) on Linux.
|
||||
package alignedbuff
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"unsafe"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
)
|
||||
|
||||
// ErrEOF signals trying to read beyond the available payload information.
|
||||
var ErrEOF = errors.New("not enough data left")
|
||||
|
||||
// AlignedBuff implements marshalling and unmarshalling information in
|
||||
// platform/architecture native endianess and data type alignment. It
|
||||
// additionally covers some of the nftables-xtables translation-specific
|
||||
// idiosyncracies to the extend needed in order to properly marshal and
|
||||
// unmarshal Match and Target expressions, and their Info payload in particular.
|
||||
type AlignedBuff struct {
|
||||
data []byte
|
||||
pos int
|
||||
}
|
||||
|
||||
// New returns a new AlignedBuff for marshalling aligned data in native
|
||||
// endianess.
|
||||
func New() AlignedBuff {
|
||||
return AlignedBuff{}
|
||||
}
|
||||
|
||||
// NewWithData returns a new AlignedBuff for unmarshalling the passed data in
|
||||
// native endianess.
|
||||
func NewWithData(data []byte) AlignedBuff {
|
||||
return AlignedBuff{data: data}
|
||||
}
|
||||
|
||||
// Data returns the properly padded info payload data written before by calling
|
||||
// the various Uint8, Uint16, ... marshalling functions.
|
||||
func (a *AlignedBuff) Data() []byte {
|
||||
// The Linux kernel expects payloads to be padded to the next uint64
|
||||
// alignment.
|
||||
a.alignWrite(uint64AlignMask)
|
||||
return a.data
|
||||
}
|
||||
|
||||
// BytesAligned32 unmarshals the given amount of bytes starting with the native
|
||||
// alignment for uint32 data types. It returns ErrEOF when trying to read beyond
|
||||
// the payload.
|
||||
//
|
||||
// BytesAligned32 is used to unmarshal IP addresses for different IP versions,
|
||||
// which are always aligned the same way as the native alignment for uint32.
|
||||
func (a *AlignedBuff) BytesAligned32(size int) ([]byte, error) {
|
||||
if err := a.alignCheckedRead(uint32AlignMask); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if a.pos > len(a.data)-size {
|
||||
return nil, ErrEOF
|
||||
}
|
||||
data := a.data[a.pos : a.pos+size]
|
||||
a.pos += size
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// Uint8 unmarshals an uint8 in native endianess and alignment. It returns
|
||||
// ErrEOF when trying to read beyond the payload.
|
||||
func (a *AlignedBuff) Uint8() (uint8, error) {
|
||||
if a.pos >= len(a.data) {
|
||||
return 0, ErrEOF
|
||||
}
|
||||
v := a.data[a.pos]
|
||||
a.pos++
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// Uint16 unmarshals an uint16 in native endianess and alignment. It returns
|
||||
// ErrEOF when trying to read beyond the payload.
|
||||
func (a *AlignedBuff) Uint16() (uint16, error) {
|
||||
if err := a.alignCheckedRead(uint16AlignMask); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
v := binaryutil.NativeEndian.Uint16(a.data[a.pos : a.pos+2])
|
||||
a.pos += 2
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// Uint16BE unmarshals an uint16 in "network" (=big endian) endianess and native
|
||||
// uint16 alignment. It returns ErrEOF when trying to read beyond the payload.
|
||||
func (a *AlignedBuff) Uint16BE() (uint16, error) {
|
||||
if err := a.alignCheckedRead(uint16AlignMask); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
v := binaryutil.BigEndian.Uint16(a.data[a.pos : a.pos+2])
|
||||
a.pos += 2
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// Uint32 unmarshals an uint32 in native endianess and alignment. It returns
|
||||
// ErrEOF when trying to read beyond the payload.
|
||||
func (a *AlignedBuff) Uint32() (uint32, error) {
|
||||
if err := a.alignCheckedRead(uint32AlignMask); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
v := binaryutil.NativeEndian.Uint32(a.data[a.pos : a.pos+4])
|
||||
a.pos += 4
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// Uint64 unmarshals an uint64 in native endianess and alignment. It returns
|
||||
// ErrEOF when trying to read beyond the payload.
|
||||
func (a *AlignedBuff) Uint64() (uint64, error) {
|
||||
if err := a.alignCheckedRead(uint64AlignMask); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
v := binaryutil.NativeEndian.Uint64(a.data[a.pos : a.pos+8])
|
||||
a.pos += 8
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// Int32 unmarshals an int32 in native endianess and alignment. It returns
|
||||
// ErrEOF when trying to read beyond the payload.
|
||||
func (a *AlignedBuff) Int32() (int32, error) {
|
||||
if err := a.alignCheckedRead(int32AlignMask); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
v := binaryutil.Int32(a.data[a.pos : a.pos+4])
|
||||
a.pos += 4
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// String unmarshals a null terminated string
|
||||
func (a *AlignedBuff) String() (string, error) {
|
||||
len := 0
|
||||
for {
|
||||
if a.data[a.pos+len] == 0x00 {
|
||||
break
|
||||
}
|
||||
len++
|
||||
}
|
||||
|
||||
v := binaryutil.String(a.data[a.pos : a.pos+len])
|
||||
a.pos += len
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// StringWithLength unmarshals a string of a given length (for non-null
|
||||
// terminated strings)
|
||||
func (a *AlignedBuff) StringWithLength(len int) (string, error) {
|
||||
v := binaryutil.String(a.data[a.pos : a.pos+len])
|
||||
a.pos += len
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// Uint unmarshals an uint in native endianess and alignment for the C "unsigned
|
||||
// int" type. It returns ErrEOF when trying to read beyond the payload. Please
|
||||
// note that on 64bit platforms, the size and alignment of C's and Go's unsigned
|
||||
// integer data types differ, so we encapsulate this difference here.
|
||||
func (a *AlignedBuff) Uint() (uint, error) {
|
||||
switch uintSize {
|
||||
case 2:
|
||||
v, err := a.Uint16()
|
||||
return uint(v), err
|
||||
case 4:
|
||||
v, err := a.Uint32()
|
||||
return uint(v), err
|
||||
case 8:
|
||||
v, err := a.Uint64()
|
||||
return uint(v), err
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported uint size %d", uintSize))
|
||||
}
|
||||
}
|
||||
|
||||
// PutBytesAligned32 marshals the given bytes starting with the native alignment
|
||||
// for uint32 data types. It additionaly adds padding to reach the specified
|
||||
// size.
|
||||
//
|
||||
// PutBytesAligned32 is used to marshal IP addresses for different IP versions,
|
||||
// which are always aligned the same way as the native alignment for uint32.
|
||||
func (a *AlignedBuff) PutBytesAligned32(data []byte, size int) {
|
||||
a.alignWrite(uint32AlignMask)
|
||||
a.data = append(a.data, data...)
|
||||
a.pos += len(data)
|
||||
if len(data) < size {
|
||||
padding := size - len(data)
|
||||
a.data = append(a.data, bytes.Repeat([]byte{0}, padding)...)
|
||||
a.pos += padding
|
||||
}
|
||||
}
|
||||
|
||||
// PutUint8 marshals an uint8 in native endianess and alignment.
|
||||
func (a *AlignedBuff) PutUint8(v uint8) {
|
||||
a.data = append(a.data, v)
|
||||
a.pos++
|
||||
}
|
||||
|
||||
// PutUint16 marshals an uint16 in native endianess and alignment.
|
||||
func (a *AlignedBuff) PutUint16(v uint16) {
|
||||
a.alignWrite(uint16AlignMask)
|
||||
a.data = append(a.data, binaryutil.NativeEndian.PutUint16(v)...)
|
||||
a.pos += 2
|
||||
}
|
||||
|
||||
// PutUint16BE marshals an uint16 in "network" (=big endian) endianess and
|
||||
// native uint16 alignment.
|
||||
func (a *AlignedBuff) PutUint16BE(v uint16) {
|
||||
a.alignWrite(uint16AlignMask)
|
||||
a.data = append(a.data, binaryutil.BigEndian.PutUint16(v)...)
|
||||
a.pos += 2
|
||||
}
|
||||
|
||||
// PutUint32 marshals an uint32 in native endianess and alignment.
|
||||
func (a *AlignedBuff) PutUint32(v uint32) {
|
||||
a.alignWrite(uint32AlignMask)
|
||||
a.data = append(a.data, binaryutil.NativeEndian.PutUint32(v)...)
|
||||
a.pos += 4
|
||||
}
|
||||
|
||||
// PutUint64 marshals an uint64 in native endianess and alignment.
|
||||
func (a *AlignedBuff) PutUint64(v uint64) {
|
||||
a.alignWrite(uint64AlignMask)
|
||||
a.data = append(a.data, binaryutil.NativeEndian.PutUint64(v)...)
|
||||
a.pos += 8
|
||||
}
|
||||
|
||||
// PutInt32 marshals an int32 in native endianess and alignment.
|
||||
func (a *AlignedBuff) PutInt32(v int32) {
|
||||
a.alignWrite(int32AlignMask)
|
||||
a.data = append(a.data, binaryutil.PutInt32(v)...)
|
||||
a.pos += 4
|
||||
}
|
||||
|
||||
// PutString marshals a string.
|
||||
func (a *AlignedBuff) PutString(v string) {
|
||||
a.data = append(a.data, binaryutil.PutString(v)...)
|
||||
a.pos += len(v)
|
||||
}
|
||||
|
||||
// PutUint marshals an uint in native endianess and alignment for the C
|
||||
// "unsigned int" type. Please note that on 64bit platforms, the size and
|
||||
// alignment of C's and Go's unsigned integer data types differ, so we
|
||||
// encapsulate this difference here.
|
||||
func (a *AlignedBuff) PutUint(v uint) {
|
||||
switch uintSize {
|
||||
case 2:
|
||||
a.PutUint16(uint16(v))
|
||||
case 4:
|
||||
a.PutUint32(uint32(v))
|
||||
case 8:
|
||||
a.PutUint64(uint64(v))
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported uint size %d", uintSize))
|
||||
}
|
||||
}
|
||||
|
||||
// alignCheckedRead aligns the (read) position if necessary and suitable
|
||||
// according to the specified alignment mask. alignCheckedRead returns an error
|
||||
// if after any necessary alignment there isn't enough data left to be read into
|
||||
// a value of the size corresponding to the specified alignment mask.
|
||||
func (a *AlignedBuff) alignCheckedRead(m int) error {
|
||||
a.pos = (a.pos + m) & ^m
|
||||
if a.pos > len(a.data)-(m+1) {
|
||||
return ErrEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// alignWrite aligns the (write) position if necessary and suitable according to
|
||||
// the specified alignment mask. It doubles as final payload padding helpmate in
|
||||
// order to keep the kernel happy.
|
||||
func (a *AlignedBuff) alignWrite(m int) {
|
||||
pos := (a.pos + m) & ^m
|
||||
if pos != a.pos {
|
||||
a.data = append(a.data, padding[:pos-a.pos]...)
|
||||
a.pos = pos
|
||||
}
|
||||
}
|
||||
|
||||
// This is ... ugly.
|
||||
var uint16AlignMask = int(unsafe.Alignof(uint16(0)) - 1)
|
||||
var uint32AlignMask = int(unsafe.Alignof(uint32(0)) - 1)
|
||||
var uint64AlignMask = int(unsafe.Alignof(uint64(0)) - 1)
|
||||
var padding = bytes.Repeat([]byte{0}, uint64AlignMask)
|
||||
|
||||
var int32AlignMask = int(unsafe.Alignof(int32(0)) - 1)
|
||||
|
||||
// And this even worse.
|
||||
var uintSize = unsafe.Sizeof(uint32(0))
|
||||
125
vendor/github.com/google/nftables/binaryutil/binaryutil.go
generated
vendored
Normal file
125
vendor/github.com/google/nftables/binaryutil/binaryutil.go
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package binaryutil contains convenience wrappers around encoding/binary.
|
||||
package binaryutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// ByteOrder is like binary.ByteOrder, but allocates memory and returns byte
|
||||
// slices, for convenience.
|
||||
type ByteOrder interface {
|
||||
PutUint16(v uint16) []byte
|
||||
PutUint32(v uint32) []byte
|
||||
PutUint64(v uint64) []byte
|
||||
Uint16(b []byte) uint16
|
||||
Uint32(b []byte) uint32
|
||||
Uint64(b []byte) uint64
|
||||
}
|
||||
|
||||
// NativeEndian is either little endian or big endian, depending on the native
|
||||
// endian-ness, and allocates memory and returns byte slices, for convenience.
|
||||
var NativeEndian ByteOrder = &nativeEndian{}
|
||||
|
||||
type nativeEndian struct{}
|
||||
|
||||
func (nativeEndian) PutUint16(v uint16) []byte {
|
||||
buf := make([]byte, 2)
|
||||
*(*uint16)(unsafe.Pointer(&buf[0])) = v
|
||||
return buf
|
||||
}
|
||||
|
||||
func (nativeEndian) PutUint32(v uint32) []byte {
|
||||
buf := make([]byte, 4)
|
||||
*(*uint32)(unsafe.Pointer(&buf[0])) = v
|
||||
return buf
|
||||
}
|
||||
|
||||
func (nativeEndian) PutUint64(v uint64) []byte {
|
||||
buf := make([]byte, 8)
|
||||
*(*uint64)(unsafe.Pointer(&buf[0])) = v
|
||||
return buf
|
||||
}
|
||||
|
||||
func (nativeEndian) Uint16(b []byte) uint16 {
|
||||
return *(*uint16)(unsafe.Pointer(&b[0]))
|
||||
}
|
||||
|
||||
func (nativeEndian) Uint32(b []byte) uint32 {
|
||||
return *(*uint32)(unsafe.Pointer(&b[0]))
|
||||
}
|
||||
|
||||
func (nativeEndian) Uint64(b []byte) uint64 {
|
||||
return *(*uint64)(unsafe.Pointer(&b[0]))
|
||||
}
|
||||
|
||||
// BigEndian is like binary.BigEndian, but allocates memory and returns byte
|
||||
// slices, for convenience.
|
||||
var BigEndian ByteOrder = &bigEndian{}
|
||||
|
||||
type bigEndian struct{}
|
||||
|
||||
func (bigEndian) PutUint16(v uint16) []byte {
|
||||
buf := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(buf, v)
|
||||
return buf
|
||||
}
|
||||
|
||||
func (bigEndian) PutUint32(v uint32) []byte {
|
||||
buf := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(buf, v)
|
||||
return buf
|
||||
}
|
||||
|
||||
func (bigEndian) PutUint64(v uint64) []byte {
|
||||
buf := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(buf, v)
|
||||
return buf
|
||||
}
|
||||
|
||||
func (bigEndian) Uint16(b []byte) uint16 {
|
||||
return binary.BigEndian.Uint16(b)
|
||||
}
|
||||
|
||||
func (bigEndian) Uint32(b []byte) uint32 {
|
||||
return binary.BigEndian.Uint32(b)
|
||||
}
|
||||
|
||||
func (bigEndian) Uint64(b []byte) uint64 {
|
||||
return binary.BigEndian.Uint64(b)
|
||||
}
|
||||
|
||||
// For dealing with types not supported by the encoding/binary interface
|
||||
|
||||
func PutInt32(v int32) []byte {
|
||||
buf := make([]byte, 4)
|
||||
*(*int32)(unsafe.Pointer(&buf[0])) = v
|
||||
return buf
|
||||
}
|
||||
|
||||
func Int32(b []byte) int32 {
|
||||
return *(*int32)(unsafe.Pointer(&b[0]))
|
||||
}
|
||||
|
||||
func PutString(s string) []byte {
|
||||
return []byte(s)
|
||||
}
|
||||
|
||||
func String(b []byte) string {
|
||||
return string(bytes.TrimRight(b, "\x00"))
|
||||
}
|
||||
328
vendor/github.com/google/nftables/chain.go
generated
vendored
Normal file
328
vendor/github.com/google/nftables/chain.go
generated
vendored
Normal file
@@ -0,0 +1,328 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nftables
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// ChainHook specifies at which step in packet processing the Chain should be
|
||||
// executed. See also
|
||||
// https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains#Base_chain_hooks
|
||||
type ChainHook uint32
|
||||
|
||||
// Possible ChainHook values.
|
||||
var (
|
||||
ChainHookPrerouting *ChainHook = ChainHookRef(unix.NF_INET_PRE_ROUTING)
|
||||
ChainHookInput *ChainHook = ChainHookRef(unix.NF_INET_LOCAL_IN)
|
||||
ChainHookForward *ChainHook = ChainHookRef(unix.NF_INET_FORWARD)
|
||||
ChainHookOutput *ChainHook = ChainHookRef(unix.NF_INET_LOCAL_OUT)
|
||||
ChainHookPostrouting *ChainHook = ChainHookRef(unix.NF_INET_POST_ROUTING)
|
||||
ChainHookIngress *ChainHook = ChainHookRef(unix.NF_NETDEV_INGRESS)
|
||||
ChainHookEgress *ChainHook = ChainHookRef(unix.NF_NETDEV_EGRESS)
|
||||
)
|
||||
|
||||
// ChainHookRef returns a pointer to a ChainHookRef value.
|
||||
func ChainHookRef(h ChainHook) *ChainHook {
|
||||
return &h
|
||||
}
|
||||
|
||||
// ChainPriority orders the chain relative to Netfilter internal operations. See
|
||||
// also
|
||||
// https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains#Base_chain_priority
|
||||
type ChainPriority int32
|
||||
|
||||
// Possible ChainPriority values.
|
||||
var ( // from /usr/include/linux/netfilter_ipv4.h
|
||||
ChainPriorityFirst *ChainPriority = ChainPriorityRef(math.MinInt32)
|
||||
ChainPriorityConntrackDefrag *ChainPriority = ChainPriorityRef(-400)
|
||||
ChainPriorityRaw *ChainPriority = ChainPriorityRef(-300)
|
||||
ChainPrioritySELinuxFirst *ChainPriority = ChainPriorityRef(-225)
|
||||
ChainPriorityConntrack *ChainPriority = ChainPriorityRef(-200)
|
||||
ChainPriorityMangle *ChainPriority = ChainPriorityRef(-150)
|
||||
ChainPriorityNATDest *ChainPriority = ChainPriorityRef(-100)
|
||||
ChainPriorityFilter *ChainPriority = ChainPriorityRef(0)
|
||||
ChainPrioritySecurity *ChainPriority = ChainPriorityRef(50)
|
||||
ChainPriorityNATSource *ChainPriority = ChainPriorityRef(100)
|
||||
ChainPrioritySELinuxLast *ChainPriority = ChainPriorityRef(225)
|
||||
ChainPriorityConntrackHelper *ChainPriority = ChainPriorityRef(300)
|
||||
ChainPriorityConntrackConfirm *ChainPriority = ChainPriorityRef(math.MaxInt32)
|
||||
ChainPriorityLast *ChainPriority = ChainPriorityRef(math.MaxInt32)
|
||||
)
|
||||
|
||||
// ChainPriorityRef returns a pointer to a ChainPriority value.
|
||||
func ChainPriorityRef(p ChainPriority) *ChainPriority {
|
||||
return &p
|
||||
}
|
||||
|
||||
// ChainType defines what this chain will be used for. See also
|
||||
// https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains#Base_chain_types
|
||||
type ChainType string
|
||||
|
||||
// Possible ChainType values.
|
||||
const (
|
||||
ChainTypeFilter ChainType = "filter"
|
||||
ChainTypeRoute ChainType = "route"
|
||||
ChainTypeNAT ChainType = "nat"
|
||||
)
|
||||
|
||||
// ChainPolicy defines what this chain default policy will be.
|
||||
type ChainPolicy uint32
|
||||
|
||||
// Possible ChainPolicy values.
|
||||
const (
|
||||
ChainPolicyDrop ChainPolicy = iota
|
||||
ChainPolicyAccept
|
||||
)
|
||||
|
||||
// A Chain contains Rules. See also
|
||||
// https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains
|
||||
type Chain struct {
|
||||
Name string
|
||||
Table *Table
|
||||
Hooknum *ChainHook
|
||||
Priority *ChainPriority
|
||||
Type ChainType
|
||||
Policy *ChainPolicy
|
||||
Device string
|
||||
}
|
||||
|
||||
// AddChain adds the specified Chain. See also
|
||||
// https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains#Adding_base_chains
|
||||
func (cc *Conn) AddChain(c *Chain) *Chain {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
data := cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NFTA_CHAIN_TABLE, Data: []byte(c.Table.Name + "\x00")},
|
||||
{Type: unix.NFTA_CHAIN_NAME, Data: []byte(c.Name + "\x00")},
|
||||
})
|
||||
|
||||
if c.Hooknum != nil && c.Priority != nil {
|
||||
hookAttr := []netlink.Attribute{
|
||||
{Type: unix.NFTA_HOOK_HOOKNUM, Data: binaryutil.BigEndian.PutUint32(uint32(*c.Hooknum))},
|
||||
{Type: unix.NFTA_HOOK_PRIORITY, Data: binaryutil.BigEndian.PutUint32(uint32(*c.Priority))},
|
||||
}
|
||||
|
||||
if c.Device != "" {
|
||||
hookAttr = append(hookAttr, netlink.Attribute{Type: unix.NFTA_HOOK_DEV, Data: []byte(c.Device + "\x00")})
|
||||
}
|
||||
|
||||
data = append(data, cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_CHAIN_HOOK, Data: cc.marshalAttr(hookAttr)},
|
||||
})...)
|
||||
}
|
||||
|
||||
if c.Policy != nil {
|
||||
data = append(data, cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NFTA_CHAIN_POLICY, Data: binaryutil.BigEndian.PutUint32(uint32(*c.Policy))},
|
||||
})...)
|
||||
}
|
||||
if c.Type != "" {
|
||||
data = append(data, cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NFTA_CHAIN_TYPE, Data: []byte(c.Type + "\x00")},
|
||||
})...)
|
||||
}
|
||||
cc.messages = append(cc.messages, netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_NEWCHAIN),
|
||||
Flags: netlink.Request | netlink.Acknowledge | netlink.Create,
|
||||
},
|
||||
Data: append(extraHeader(uint8(c.Table.Family), 0), data...),
|
||||
})
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// DelChain deletes the specified Chain. See also
|
||||
// https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains#Deleting_chains
|
||||
func (cc *Conn) DelChain(c *Chain) {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
data := cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NFTA_CHAIN_TABLE, Data: []byte(c.Table.Name + "\x00")},
|
||||
{Type: unix.NFTA_CHAIN_NAME, Data: []byte(c.Name + "\x00")},
|
||||
})
|
||||
|
||||
cc.messages = append(cc.messages, netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_DELCHAIN),
|
||||
Flags: netlink.Request | netlink.Acknowledge,
|
||||
},
|
||||
Data: append(extraHeader(uint8(c.Table.Family), 0), data...),
|
||||
})
|
||||
}
|
||||
|
||||
// FlushChain removes all rules within the specified Chain. See also
|
||||
// https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains#Flushing_chain
|
||||
func (cc *Conn) FlushChain(c *Chain) {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
data := cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NFTA_RULE_TABLE, Data: []byte(c.Table.Name + "\x00")},
|
||||
{Type: unix.NFTA_RULE_CHAIN, Data: []byte(c.Name + "\x00")},
|
||||
})
|
||||
cc.messages = append(cc.messages, netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_DELRULE),
|
||||
Flags: netlink.Request | netlink.Acknowledge,
|
||||
},
|
||||
Data: append(extraHeader(uint8(c.Table.Family), 0), data...),
|
||||
})
|
||||
}
|
||||
|
||||
// ListChains returns currently configured chains in the kernel
|
||||
func (cc *Conn) ListChains() ([]*Chain, error) {
|
||||
return cc.ListChainsOfTableFamily(TableFamilyUnspecified)
|
||||
}
|
||||
|
||||
// ListChain returns a single chain configured in the specified table
|
||||
func (cc *Conn) ListChain(table *Table, chain string) (*Chain, error) {
|
||||
conn, closer, err := cc.netlinkConn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = closer() }()
|
||||
|
||||
attrs := []netlink.Attribute{
|
||||
{Type: unix.NFTA_TABLE_NAME, Data: []byte(table.Name + "\x00")},
|
||||
{Type: unix.NFTA_CHAIN_NAME, Data: []byte(chain + "\x00")},
|
||||
}
|
||||
msg := netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_GETCHAIN),
|
||||
Flags: netlink.Request,
|
||||
},
|
||||
Data: append(extraHeader(uint8(table.Family), 0), cc.marshalAttr(attrs)...),
|
||||
}
|
||||
|
||||
response, err := conn.Execute(msg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("conn.Execute failed: %v", err)
|
||||
}
|
||||
|
||||
if got, want := len(response), 1; got != want {
|
||||
return nil, fmt.Errorf("expected %d response message for chain, got %d", want, got)
|
||||
}
|
||||
|
||||
ch, err := chainFromMsg(response[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
// ListChainsOfTableFamily returns currently configured chains for the specified
|
||||
// family in the kernel. It lists all chains ins all tables if family is
|
||||
// TableFamilyUnspecified.
|
||||
func (cc *Conn) ListChainsOfTableFamily(family TableFamily) ([]*Chain, error) {
|
||||
conn, closer, err := cc.netlinkConn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = closer() }()
|
||||
|
||||
msg := netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_GETCHAIN),
|
||||
Flags: netlink.Request | netlink.Dump,
|
||||
},
|
||||
Data: extraHeader(uint8(family), 0),
|
||||
}
|
||||
|
||||
response, err := conn.Execute(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var chains []*Chain
|
||||
for _, m := range response {
|
||||
c, err := chainFromMsg(m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
chains = append(chains, c)
|
||||
}
|
||||
|
||||
return chains, nil
|
||||
}
|
||||
|
||||
func chainFromMsg(msg netlink.Message) (*Chain, error) {
|
||||
newChainHeaderType := netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_NEWCHAIN)
|
||||
delChainHeaderType := netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_DELCHAIN)
|
||||
if got, want1, want2 := msg.Header.Type, newChainHeaderType, delChainHeaderType; got != want1 && got != want2 {
|
||||
return nil, fmt.Errorf("unexpected header type: got %v, want %v or %v", got, want1, want2)
|
||||
}
|
||||
|
||||
var c Chain
|
||||
|
||||
ad, err := netlink.NewAttributeDecoder(msg.Data[4:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_CHAIN_NAME:
|
||||
c.Name = ad.String()
|
||||
case unix.NFTA_TABLE_NAME:
|
||||
c.Table = &Table{Name: ad.String()}
|
||||
// msg[0] carries TableFamily byte indicating whether it is IPv4, IPv6 or something else
|
||||
c.Table.Family = TableFamily(msg.Data[0])
|
||||
case unix.NFTA_CHAIN_TYPE:
|
||||
c.Type = ChainType(ad.String())
|
||||
case unix.NFTA_CHAIN_POLICY:
|
||||
policy := ChainPolicy(binaryutil.BigEndian.Uint32(ad.Bytes()))
|
||||
c.Policy = &policy
|
||||
case unix.NFTA_CHAIN_HOOK:
|
||||
ad.Do(func(b []byte) error {
|
||||
c.Hooknum, c.Priority, err = hookFromMsg(b)
|
||||
return err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
func hookFromMsg(b []byte) (*ChainHook, *ChainPriority, error) {
|
||||
ad, err := netlink.NewAttributeDecoder(b)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
|
||||
var hooknum ChainHook
|
||||
var prio ChainPriority
|
||||
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_HOOK_HOOKNUM:
|
||||
hooknum = ChainHook(ad.Uint32())
|
||||
case unix.NFTA_HOOK_PRIORITY:
|
||||
prio = ChainPriority(ad.Uint32())
|
||||
}
|
||||
}
|
||||
|
||||
return &hooknum, &prio, nil
|
||||
}
|
||||
89
vendor/github.com/google/nftables/compat_policy.go
generated
vendored
Normal file
89
vendor/github.com/google/nftables/compat_policy.go
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
package nftables
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/nftables/expr"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const nft_RULE_COMPAT_F_INV uint32 = (1 << 1)
|
||||
const nft_RULE_COMPAT_F_MASK uint32 = nft_RULE_COMPAT_F_INV
|
||||
|
||||
// Used by xt match or target like xt_tcpudp to set compat policy between xtables and nftables
|
||||
// https://elixir.bootlin.com/linux/v5.12/source/net/netfilter/nft_compat.c#L187
|
||||
type compatPolicy struct {
|
||||
Proto uint32
|
||||
Flag uint32
|
||||
}
|
||||
|
||||
var xtMatchCompatMap map[string]*compatPolicy = map[string]*compatPolicy{
|
||||
"tcp": {
|
||||
Proto: unix.IPPROTO_TCP,
|
||||
},
|
||||
"udp": {
|
||||
Proto: unix.IPPROTO_UDP,
|
||||
},
|
||||
"udplite": {
|
||||
Proto: unix.IPPROTO_UDPLITE,
|
||||
},
|
||||
"tcpmss": {
|
||||
Proto: unix.IPPROTO_TCP,
|
||||
},
|
||||
"sctp": {
|
||||
Proto: unix.IPPROTO_SCTP,
|
||||
},
|
||||
"osf": {
|
||||
Proto: unix.IPPROTO_TCP,
|
||||
},
|
||||
"ipcomp": {
|
||||
Proto: unix.IPPROTO_COMP,
|
||||
},
|
||||
"esp": {
|
||||
Proto: unix.IPPROTO_ESP,
|
||||
},
|
||||
}
|
||||
|
||||
var xtTargetCompatMap map[string]*compatPolicy = map[string]*compatPolicy{
|
||||
"TCPOPTSTRIP": {
|
||||
Proto: unix.IPPROTO_TCP,
|
||||
},
|
||||
"TCPMSS": {
|
||||
Proto: unix.IPPROTO_TCP,
|
||||
},
|
||||
}
|
||||
|
||||
func getCompatPolicy(exprs []expr.Any) (*compatPolicy, error) {
|
||||
var exprItem expr.Any
|
||||
var compat *compatPolicy
|
||||
|
||||
for _, iter := range exprs {
|
||||
var tmpExprItem expr.Any
|
||||
var tmpCompat *compatPolicy
|
||||
switch item := iter.(type) {
|
||||
case *expr.Match:
|
||||
if compat, ok := xtMatchCompatMap[item.Name]; ok {
|
||||
tmpCompat = compat
|
||||
tmpExprItem = item
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
case *expr.Target:
|
||||
if compat, ok := xtTargetCompatMap[item.Name]; ok {
|
||||
tmpCompat = compat
|
||||
tmpExprItem = item
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
if compat == nil {
|
||||
compat = tmpCompat
|
||||
exprItem = tmpExprItem
|
||||
} else if *compat != *tmpCompat {
|
||||
return nil, fmt.Errorf("%#v and %#v has conflict compat policy %#v vs %#v", exprItem, tmpExprItem, compat, tmpCompat)
|
||||
}
|
||||
}
|
||||
return compat, nil
|
||||
}
|
||||
341
vendor/github.com/google/nftables/conn.go
generated
vendored
Normal file
341
vendor/github.com/google/nftables/conn.go
generated
vendored
Normal file
@@ -0,0 +1,341 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nftables
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/google/nftables/expr"
|
||||
"github.com/mdlayher/netlink"
|
||||
"github.com/mdlayher/netlink/nltest"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// A Conn represents a netlink connection of the nftables family.
|
||||
//
|
||||
// All methods return their input, so that variables can be defined from string
|
||||
// literals when desired.
|
||||
//
|
||||
// Commands are buffered. Flush sends all buffered commands in a single batch.
|
||||
type Conn struct {
|
||||
TestDial nltest.Func // for testing only; passed to nltest.Dial
|
||||
NetNS int // fd referencing the network namespace netlink will interact with.
|
||||
|
||||
lasting bool // establish a lasting connection to be used across multiple netlink operations.
|
||||
mu sync.Mutex // protects the following state
|
||||
messages []netlink.Message
|
||||
err error
|
||||
nlconn *netlink.Conn // netlink socket using NETLINK_NETFILTER protocol.
|
||||
}
|
||||
|
||||
// ConnOption is an option to change the behavior of the nftables Conn returned by Open.
|
||||
type ConnOption func(*Conn)
|
||||
|
||||
// New returns a netlink connection for querying and modifying nftables. Some
|
||||
// aspects of the new netlink connection can be configured using the options
|
||||
// WithNetNSFd, WithTestDial, and AsLasting.
|
||||
//
|
||||
// A lasting netlink connection should be closed by calling CloseLasting() to
|
||||
// close the underlying lasting netlink connection, cancelling all pending
|
||||
// operations using this connection.
|
||||
func New(opts ...ConnOption) (*Conn, error) {
|
||||
cc := &Conn{}
|
||||
for _, opt := range opts {
|
||||
opt(cc)
|
||||
}
|
||||
|
||||
if !cc.lasting {
|
||||
return cc, nil
|
||||
}
|
||||
|
||||
nlconn, err := cc.dialNetlink()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cc.nlconn = nlconn
|
||||
return cc, nil
|
||||
}
|
||||
|
||||
// AsLasting creates the new netlink connection as a lasting connection that is
|
||||
// reused across multiple netlink operations, instead of opening and closing the
|
||||
// underlying netlink connection only for the duration of a single netlink
|
||||
// operation.
|
||||
func AsLasting() ConnOption {
|
||||
return func(cc *Conn) {
|
||||
// We cannot create the underlying connection yet, as we are called
|
||||
// anywhere in the option processing chain and there might be later
|
||||
// options still modifying connection behavior.
|
||||
cc.lasting = true
|
||||
}
|
||||
}
|
||||
|
||||
// WithNetNSFd sets the network namespace to create a new netlink connection to:
|
||||
// the fd must reference a network namespace.
|
||||
func WithNetNSFd(fd int) ConnOption {
|
||||
return func(cc *Conn) {
|
||||
cc.NetNS = fd
|
||||
}
|
||||
}
|
||||
|
||||
// WithTestDial sets the specified nltest.Func when creating a new netlink
|
||||
// connection.
|
||||
func WithTestDial(f nltest.Func) ConnOption {
|
||||
return func(cc *Conn) {
|
||||
cc.TestDial = f
|
||||
}
|
||||
}
|
||||
|
||||
// netlinkCloser is returned by netlinkConn(UnderLock) and must be called after
|
||||
// being done with the returned netlink connection in order to properly close
|
||||
// this connection, if necessary.
|
||||
type netlinkCloser func() error
|
||||
|
||||
// netlinkConn returns a netlink connection together with a netlinkCloser that
|
||||
// later must be called by the caller when it doesn't need the returned netlink
|
||||
// connection anymore. The netlinkCloser will close the netlink connection when
|
||||
// necessary. If New has been told to create a lasting connection, then this
|
||||
// lasting netlink connection will be returned, otherwise a new "transient"
|
||||
// netlink connection will be opened and returned instead. netlinkConn must not
|
||||
// be called while the Conn.mu lock is currently helt (this will cause a
|
||||
// deadlock). Use netlinkConnUnderLock instead in such situations.
|
||||
func (cc *Conn) netlinkConn() (*netlink.Conn, netlinkCloser, error) {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
return cc.netlinkConnUnderLock()
|
||||
}
|
||||
|
||||
// netlinkConnUnderLock works like netlinkConn but must be called while holding
|
||||
// the Conn.mu lock.
|
||||
func (cc *Conn) netlinkConnUnderLock() (*netlink.Conn, netlinkCloser, error) {
|
||||
if cc.nlconn != nil {
|
||||
return cc.nlconn, func() error { return nil }, nil
|
||||
}
|
||||
nlconn, err := cc.dialNetlink()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return nlconn, func() error { return nlconn.Close() }, nil
|
||||
}
|
||||
|
||||
func receiveAckAware(nlconn *netlink.Conn, sentMsgFlags netlink.HeaderFlags) ([]netlink.Message, error) {
|
||||
if nlconn == nil {
|
||||
return nil, errors.New("netlink conn is not initialized")
|
||||
}
|
||||
|
||||
// first receive will be the message that we expect
|
||||
reply, err := nlconn.Receive()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if (sentMsgFlags & netlink.Acknowledge) == 0 {
|
||||
// we did not request an ack
|
||||
return reply, nil
|
||||
}
|
||||
|
||||
if (sentMsgFlags & netlink.Dump) == netlink.Dump {
|
||||
// sent message has Dump flag set, there will be no acks
|
||||
// https://github.com/torvalds/linux/blob/7e062cda7d90543ac8c7700fc7c5527d0c0f22ad/net/netlink/af_netlink.c#L2387-L2390
|
||||
return reply, nil
|
||||
}
|
||||
|
||||
if len(reply) != 0 {
|
||||
last := reply[len(reply)-1]
|
||||
for re := last.Header.Type; (re&netlink.Overrun) == netlink.Overrun && (re&netlink.Done) != netlink.Done; re = last.Header.Type {
|
||||
// we are not finished, the message is overrun
|
||||
r, err := nlconn.Receive()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reply = append(reply, r...)
|
||||
last = reply[len(reply)-1]
|
||||
}
|
||||
|
||||
if last.Header.Type == netlink.Error && binaryutil.BigEndian.Uint32(last.Data[:4]) == 0 {
|
||||
// we have already collected an ack
|
||||
return reply, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Now we expect an ack
|
||||
ack, err := nlconn.Receive()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(ack) == 0 {
|
||||
// received an empty ack?
|
||||
return reply, nil
|
||||
}
|
||||
|
||||
msg := ack[0]
|
||||
if msg.Header.Type != netlink.Error {
|
||||
// acks should be delivered as NLMSG_ERROR
|
||||
return nil, fmt.Errorf("expected header %v, but got %v", netlink.Error, msg.Header.Type)
|
||||
}
|
||||
|
||||
if binaryutil.BigEndian.Uint32(msg.Data[:4]) != 0 {
|
||||
// if errno field is not set to 0 (success), this is an error
|
||||
return nil, fmt.Errorf("error delivered in message: %v", msg.Data)
|
||||
}
|
||||
|
||||
return reply, nil
|
||||
}
|
||||
|
||||
// CloseLasting closes the lasting netlink connection that has been opened using
|
||||
// AsLasting option when creating this connection. If either no lasting netlink
|
||||
// connection has been opened or the lasting connection is already in the
|
||||
// process of closing or has been closed, CloseLasting will immediately return
|
||||
// without any error.
|
||||
//
|
||||
// CloseLasting will terminate all pending netlink operations using the lasting
|
||||
// connection.
|
||||
//
|
||||
// After closing a lasting connection, the connection will revert to using
|
||||
// on-demand transient netlink connections when calling further netlink
|
||||
// operations (such as GetTables).
|
||||
func (cc *Conn) CloseLasting() error {
|
||||
// Don't acquire the lock for the whole duration of the CloseLasting
|
||||
// operation, but instead only so long as to make sure to only run the
|
||||
// netlink socket close on the first time with a lasting netlink socket. As
|
||||
// there is only the New() constructor, but no Open() method, it's
|
||||
// impossible to reopen a lasting connection.
|
||||
cc.mu.Lock()
|
||||
nlconn := cc.nlconn
|
||||
cc.nlconn = nil
|
||||
cc.mu.Unlock()
|
||||
if nlconn != nil {
|
||||
return nlconn.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Flush sends all buffered commands in a single batch to nftables.
|
||||
func (cc *Conn) Flush() error {
|
||||
cc.mu.Lock()
|
||||
defer func() {
|
||||
cc.messages = nil
|
||||
cc.mu.Unlock()
|
||||
}()
|
||||
if len(cc.messages) == 0 {
|
||||
// Messages were already programmed, returning nil
|
||||
return nil
|
||||
}
|
||||
if cc.err != nil {
|
||||
return cc.err // serialization error
|
||||
}
|
||||
conn, closer, err := cc.netlinkConnUnderLock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { _ = closer() }()
|
||||
|
||||
if _, err := conn.SendMessages(batch(cc.messages)); err != nil {
|
||||
return fmt.Errorf("SendMessages: %w", err)
|
||||
}
|
||||
|
||||
var errs error
|
||||
// Fetch the requested acknowledgement for each message we sent.
|
||||
for _, msg := range cc.messages {
|
||||
if _, err := receiveAckAware(conn, msg.Header.Flags); err != nil {
|
||||
if errors.Is(err, os.ErrPermission) {
|
||||
// Kernel will only send one permission error to user space.
|
||||
return err
|
||||
}
|
||||
errs = errors.Join(errs, err)
|
||||
}
|
||||
}
|
||||
|
||||
if errs != nil {
|
||||
return fmt.Errorf("conn.Receive: %w", errs)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FlushRuleset flushes the entire ruleset. See also
|
||||
// https://wiki.nftables.org/wiki-nftables/index.php/Operations_at_ruleset_level
|
||||
func (cc *Conn) FlushRuleset() {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
cc.messages = append(cc.messages, netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_DELTABLE),
|
||||
Flags: netlink.Request | netlink.Acknowledge | netlink.Create,
|
||||
},
|
||||
Data: extraHeader(0, 0),
|
||||
})
|
||||
}
|
||||
|
||||
func (cc *Conn) dialNetlink() (*netlink.Conn, error) {
|
||||
if cc.TestDial != nil {
|
||||
return nltest.Dial(cc.TestDial), nil
|
||||
}
|
||||
|
||||
return netlink.Dial(unix.NETLINK_NETFILTER, &netlink.Config{NetNS: cc.NetNS})
|
||||
}
|
||||
|
||||
func (cc *Conn) setErr(err error) {
|
||||
if cc.err != nil {
|
||||
return
|
||||
}
|
||||
cc.err = err
|
||||
}
|
||||
|
||||
func (cc *Conn) marshalAttr(attrs []netlink.Attribute) []byte {
|
||||
b, err := netlink.MarshalAttributes(attrs)
|
||||
if err != nil {
|
||||
cc.setErr(err)
|
||||
return nil
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (cc *Conn) marshalExpr(fam byte, e expr.Any) []byte {
|
||||
b, err := expr.Marshal(fam, e)
|
||||
if err != nil {
|
||||
cc.setErr(err)
|
||||
return nil
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func batch(messages []netlink.Message) []netlink.Message {
|
||||
batch := []netlink.Message{
|
||||
{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType(unix.NFNL_MSG_BATCH_BEGIN),
|
||||
Flags: netlink.Request,
|
||||
},
|
||||
Data: extraHeader(0, unix.NFNL_SUBSYS_NFTABLES),
|
||||
},
|
||||
}
|
||||
|
||||
batch = append(batch, messages...)
|
||||
|
||||
batch = append(batch, netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType(unix.NFNL_MSG_BATCH_END),
|
||||
Flags: netlink.Request,
|
||||
},
|
||||
Data: extraHeader(0, unix.NFNL_SUBSYS_NFTABLES),
|
||||
})
|
||||
|
||||
return batch
|
||||
}
|
||||
69
vendor/github.com/google/nftables/counter.go
generated
vendored
Normal file
69
vendor/github.com/google/nftables/counter.go
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nftables
|
||||
|
||||
import (
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// CounterObj implements Obj.
|
||||
type CounterObj struct {
|
||||
Table *Table
|
||||
Name string // e.g. “fwded”
|
||||
|
||||
Bytes uint64
|
||||
Packets uint64
|
||||
}
|
||||
|
||||
func (c *CounterObj) unmarshal(ad *netlink.AttributeDecoder) error {
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_COUNTER_BYTES:
|
||||
c.Bytes = ad.Uint64()
|
||||
case unix.NFTA_COUNTER_PACKETS:
|
||||
c.Packets = ad.Uint64()
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
|
||||
func (c *CounterObj) table() *Table {
|
||||
return c.Table
|
||||
}
|
||||
|
||||
func (c *CounterObj) family() TableFamily {
|
||||
return c.Table.Family
|
||||
}
|
||||
|
||||
func (c *CounterObj) marshal(data bool) ([]byte, error) {
|
||||
obj, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_COUNTER_BYTES, Data: binaryutil.BigEndian.PutUint64(c.Bytes)},
|
||||
{Type: unix.NFTA_COUNTER_PACKETS, Data: binaryutil.BigEndian.PutUint64(c.Packets)},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
attrs := []netlink.Attribute{
|
||||
{Type: unix.NFTA_OBJ_TABLE, Data: []byte(c.Table.Name + "\x00")},
|
||||
{Type: unix.NFTA_OBJ_NAME, Data: []byte(c.Name + "\x00")},
|
||||
{Type: unix.NFTA_OBJ_TYPE, Data: binaryutil.BigEndian.PutUint32(unix.NFT_OBJECT_COUNTER)},
|
||||
}
|
||||
if data {
|
||||
attrs = append(attrs, netlink.Attribute{Type: unix.NLA_F_NESTED | unix.NFTA_OBJ_DATA, Data: obj})
|
||||
}
|
||||
return netlink.MarshalAttributes(attrs)
|
||||
}
|
||||
16
vendor/github.com/google/nftables/doc.go
generated
vendored
Normal file
16
vendor/github.com/google/nftables/doc.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package nftables manipulates Linux nftables (the iptables successor).
|
||||
package nftables
|
||||
102
vendor/github.com/google/nftables/expr/bitwise.go
generated
vendored
Normal file
102
vendor/github.com/google/nftables/expr/bitwise.go
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type Bitwise struct {
|
||||
SourceRegister uint32
|
||||
DestRegister uint32
|
||||
Len uint32
|
||||
Mask []byte
|
||||
Xor []byte
|
||||
}
|
||||
|
||||
func (e *Bitwise) marshal(fam byte) ([]byte, error) {
|
||||
mask, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_DATA_VALUE, Data: e.Mask},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
xor, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_DATA_VALUE, Data: e.Xor},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_BITWISE_SREG, Data: binaryutil.BigEndian.PutUint32(e.SourceRegister)},
|
||||
{Type: unix.NFTA_BITWISE_DREG, Data: binaryutil.BigEndian.PutUint32(e.DestRegister)},
|
||||
{Type: unix.NFTA_BITWISE_LEN, Data: binaryutil.BigEndian.PutUint32(e.Len)},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_BITWISE_MASK, Data: mask},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_BITWISE_XOR, Data: xor},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("bitwise\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Bitwise) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_BITWISE_SREG:
|
||||
e.SourceRegister = ad.Uint32()
|
||||
case unix.NFTA_BITWISE_DREG:
|
||||
e.DestRegister = ad.Uint32()
|
||||
case unix.NFTA_BITWISE_LEN:
|
||||
e.Len = ad.Uint32()
|
||||
case unix.NFTA_BITWISE_MASK:
|
||||
// Since NFTA_BITWISE_MASK is nested, it requires additional decoding
|
||||
ad.Nested(func(nad *netlink.AttributeDecoder) error {
|
||||
for nad.Next() {
|
||||
switch nad.Type() {
|
||||
case unix.NFTA_DATA_VALUE:
|
||||
e.Mask = nad.Bytes()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
case unix.NFTA_BITWISE_XOR:
|
||||
// Since NFTA_BITWISE_XOR is nested, it requires additional decoding
|
||||
ad.Nested(func(nad *netlink.AttributeDecoder) error {
|
||||
for nad.Next() {
|
||||
switch nad.Type() {
|
||||
case unix.NFTA_DATA_VALUE:
|
||||
e.Xor = nad.Bytes()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
59
vendor/github.com/google/nftables/expr/byteorder.go
generated
vendored
Normal file
59
vendor/github.com/google/nftables/expr/byteorder.go
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type ByteorderOp uint32
|
||||
|
||||
const (
|
||||
ByteorderNtoh ByteorderOp = unix.NFT_BYTEORDER_NTOH
|
||||
ByteorderHton ByteorderOp = unix.NFT_BYTEORDER_HTON
|
||||
)
|
||||
|
||||
type Byteorder struct {
|
||||
SourceRegister uint32
|
||||
DestRegister uint32
|
||||
Op ByteorderOp
|
||||
Len uint32
|
||||
Size uint32
|
||||
}
|
||||
|
||||
func (e *Byteorder) marshal(fam byte) ([]byte, error) {
|
||||
data, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_BYTEORDER_SREG, Data: binaryutil.BigEndian.PutUint32(e.SourceRegister)},
|
||||
{Type: unix.NFTA_BYTEORDER_DREG, Data: binaryutil.BigEndian.PutUint32(e.DestRegister)},
|
||||
{Type: unix.NFTA_BYTEORDER_OP, Data: binaryutil.BigEndian.PutUint32(uint32(e.Op))},
|
||||
{Type: unix.NFTA_BYTEORDER_LEN, Data: binaryutil.BigEndian.PutUint32(e.Len)},
|
||||
{Type: unix.NFTA_BYTEORDER_SIZE, Data: binaryutil.BigEndian.PutUint32(e.Size)},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("byteorder\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Byteorder) unmarshal(fam byte, data []byte) error {
|
||||
return fmt.Errorf("not yet implemented")
|
||||
}
|
||||
70
vendor/github.com/google/nftables/expr/connlimit.go
generated
vendored
Normal file
70
vendor/github.com/google/nftables/expr/connlimit.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright 2019 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
// Per https://git.netfilter.org/libnftnl/tree/include/linux/netfilter/nf_tables.h?id=84d12cfacf8ddd857a09435f3d982ab6250d250c#n1167
|
||||
NFTA_CONNLIMIT_UNSPEC = iota
|
||||
NFTA_CONNLIMIT_COUNT
|
||||
NFTA_CONNLIMIT_FLAGS
|
||||
NFT_CONNLIMIT_F_INV = 1
|
||||
)
|
||||
|
||||
// Per https://git.netfilter.org/libnftnl/tree/src/expr/connlimit.c?id=84d12cfacf8ddd857a09435f3d982ab6250d250c
|
||||
type Connlimit struct {
|
||||
Count uint32
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
func (e *Connlimit) marshal(fam byte) ([]byte, error) {
|
||||
data, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: NFTA_CONNLIMIT_COUNT, Data: binaryutil.BigEndian.PutUint32(e.Count)},
|
||||
{Type: NFTA_CONNLIMIT_FLAGS, Data: binaryutil.BigEndian.PutUint32(e.Flags)},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("connlimit\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Connlimit) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case NFTA_CONNLIMIT_COUNT:
|
||||
e.Count = binaryutil.BigEndian.Uint32(ad.Bytes())
|
||||
case NFTA_CONNLIMIT_FLAGS:
|
||||
e.Flags = binaryutil.BigEndian.Uint32(ad.Bytes())
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
60
vendor/github.com/google/nftables/expr/counter.go
generated
vendored
Normal file
60
vendor/github.com/google/nftables/expr/counter.go
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type Counter struct {
|
||||
Bytes uint64
|
||||
Packets uint64
|
||||
}
|
||||
|
||||
func (e *Counter) marshal(fam byte) ([]byte, error) {
|
||||
data, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_COUNTER_BYTES, Data: binaryutil.BigEndian.PutUint64(e.Bytes)},
|
||||
{Type: unix.NFTA_COUNTER_PACKETS, Data: binaryutil.BigEndian.PutUint64(e.Packets)},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("counter\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Counter) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_COUNTER_BYTES:
|
||||
e.Bytes = ad.Uint64()
|
||||
case unix.NFTA_COUNTER_PACKETS:
|
||||
e.Packets = ad.Uint64()
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
115
vendor/github.com/google/nftables/expr/ct.go
generated
vendored
Normal file
115
vendor/github.com/google/nftables/expr/ct.go
generated
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// CtKey specifies which piece of conntrack information should be loaded. See
|
||||
// also https://wiki.nftables.org/wiki-nftables/index.php/Matching_connection_tracking_stateful_metainformation
|
||||
type CtKey uint32
|
||||
|
||||
// Possible CtKey values.
|
||||
const (
|
||||
CtKeySTATE CtKey = unix.NFT_CT_STATE
|
||||
CtKeyDIRECTION CtKey = unix.NFT_CT_DIRECTION
|
||||
CtKeySTATUS CtKey = unix.NFT_CT_STATUS
|
||||
CtKeyMARK CtKey = unix.NFT_CT_MARK
|
||||
CtKeySECMARK CtKey = unix.NFT_CT_SECMARK
|
||||
CtKeyEXPIRATION CtKey = unix.NFT_CT_EXPIRATION
|
||||
CtKeyHELPER CtKey = unix.NFT_CT_HELPER
|
||||
CtKeyL3PROTOCOL CtKey = unix.NFT_CT_L3PROTOCOL
|
||||
CtKeySRC CtKey = unix.NFT_CT_SRC
|
||||
CtKeyDST CtKey = unix.NFT_CT_DST
|
||||
CtKeyPROTOCOL CtKey = unix.NFT_CT_PROTOCOL
|
||||
CtKeyPROTOSRC CtKey = unix.NFT_CT_PROTO_SRC
|
||||
CtKeyPROTODST CtKey = unix.NFT_CT_PROTO_DST
|
||||
CtKeyLABELS CtKey = unix.NFT_CT_LABELS
|
||||
CtKeyPKTS CtKey = unix.NFT_CT_PKTS
|
||||
CtKeyBYTES CtKey = unix.NFT_CT_BYTES
|
||||
CtKeyAVGPKT CtKey = unix.NFT_CT_AVGPKT
|
||||
CtKeyZONE CtKey = unix.NFT_CT_ZONE
|
||||
CtKeyEVENTMASK CtKey = unix.NFT_CT_EVENTMASK
|
||||
|
||||
// https://sources.debian.org/src//nftables/0.9.8-3/src/ct.c/?hl=39#L39
|
||||
CtStateBitINVALID uint32 = 1
|
||||
CtStateBitESTABLISHED uint32 = 2
|
||||
CtStateBitRELATED uint32 = 4
|
||||
CtStateBitNEW uint32 = 8
|
||||
CtStateBitUNTRACKED uint32 = 64
|
||||
)
|
||||
|
||||
// Ct defines type for NFT connection tracking
|
||||
type Ct struct {
|
||||
Register uint32
|
||||
SourceRegister bool
|
||||
Key CtKey
|
||||
}
|
||||
|
||||
func (e *Ct) marshal(fam byte) ([]byte, error) {
|
||||
regData := []byte{}
|
||||
exprData, err := netlink.MarshalAttributes(
|
||||
[]netlink.Attribute{
|
||||
{Type: unix.NFTA_CT_KEY, Data: binaryutil.BigEndian.PutUint32(uint32(e.Key))},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if e.SourceRegister {
|
||||
regData, err = netlink.MarshalAttributes(
|
||||
[]netlink.Attribute{
|
||||
{Type: unix.NFTA_CT_SREG, Data: binaryutil.BigEndian.PutUint32(e.Register)},
|
||||
},
|
||||
)
|
||||
} else {
|
||||
regData, err = netlink.MarshalAttributes(
|
||||
[]netlink.Attribute{
|
||||
{Type: unix.NFTA_CT_DREG, Data: binaryutil.BigEndian.PutUint32(e.Register)},
|
||||
},
|
||||
)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
exprData = append(exprData, regData...)
|
||||
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("ct\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: exprData},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Ct) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_CT_KEY:
|
||||
e.Key = CtKey(ad.Uint32())
|
||||
case unix.NFTA_CT_DREG:
|
||||
e.Register = ad.Uint32()
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
67
vendor/github.com/google/nftables/expr/dup.go
generated
vendored
Normal file
67
vendor/github.com/google/nftables/expr/dup.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type Dup struct {
|
||||
RegAddr uint32
|
||||
RegDev uint32
|
||||
IsRegDevSet bool
|
||||
}
|
||||
|
||||
func (e *Dup) marshal(fam byte) ([]byte, error) {
|
||||
attrs := []netlink.Attribute{
|
||||
{Type: unix.NFTA_DUP_SREG_ADDR, Data: binaryutil.BigEndian.PutUint32(e.RegAddr)},
|
||||
}
|
||||
|
||||
if e.IsRegDevSet {
|
||||
attrs = append(attrs, netlink.Attribute{Type: unix.NFTA_DUP_SREG_DEV, Data: binaryutil.BigEndian.PutUint32(e.RegDev)})
|
||||
}
|
||||
|
||||
data, err := netlink.MarshalAttributes(attrs)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("dup\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Dup) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_DUP_SREG_ADDR:
|
||||
e.RegAddr = ad.Uint32()
|
||||
case unix.NFTA_DUP_SREG_DEV:
|
||||
e.RegDev = ad.Uint32()
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
149
vendor/github.com/google/nftables/expr/dynset.go
generated
vendored
Normal file
149
vendor/github.com/google/nftables/expr/dynset.go
generated
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"time"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/google/nftables/internal/parseexprfunc"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// Not yet supported by unix package
|
||||
// https://cs.opensource.google/go/x/sys/+/c6bc011c:unix/ztypes_linux.go;l=2027-2036
|
||||
const (
|
||||
NFTA_DYNSET_EXPRESSIONS = 0xa
|
||||
NFT_DYNSET_F_EXPR = (1 << 1)
|
||||
)
|
||||
|
||||
// Dynset represent a rule dynamically adding or updating a set or a map based on an incoming packet.
|
||||
type Dynset struct {
|
||||
SrcRegKey uint32
|
||||
SrcRegData uint32
|
||||
SetID uint32
|
||||
SetName string
|
||||
Operation uint32
|
||||
Timeout time.Duration
|
||||
Invert bool
|
||||
Exprs []Any
|
||||
}
|
||||
|
||||
func (e *Dynset) marshal(fam byte) ([]byte, error) {
|
||||
// See: https://git.netfilter.org/libnftnl/tree/src/expr/dynset.c
|
||||
var opAttrs []netlink.Attribute
|
||||
opAttrs = append(opAttrs, netlink.Attribute{Type: unix.NFTA_DYNSET_SREG_KEY, Data: binaryutil.BigEndian.PutUint32(e.SrcRegKey)})
|
||||
if e.SrcRegData != 0 {
|
||||
opAttrs = append(opAttrs, netlink.Attribute{Type: unix.NFTA_DYNSET_SREG_DATA, Data: binaryutil.BigEndian.PutUint32(e.SrcRegData)})
|
||||
}
|
||||
opAttrs = append(opAttrs, netlink.Attribute{Type: unix.NFTA_DYNSET_OP, Data: binaryutil.BigEndian.PutUint32(e.Operation)})
|
||||
if e.Timeout != 0 {
|
||||
opAttrs = append(opAttrs, netlink.Attribute{Type: unix.NFTA_DYNSET_TIMEOUT, Data: binaryutil.BigEndian.PutUint64(uint64(e.Timeout.Milliseconds()))})
|
||||
}
|
||||
var flags uint32
|
||||
if e.Invert {
|
||||
flags |= unix.NFT_DYNSET_F_INV
|
||||
}
|
||||
|
||||
opAttrs = append(opAttrs,
|
||||
netlink.Attribute{Type: unix.NFTA_DYNSET_SET_NAME, Data: []byte(e.SetName + "\x00")},
|
||||
netlink.Attribute{Type: unix.NFTA_DYNSET_SET_ID, Data: binaryutil.BigEndian.PutUint32(e.SetID)})
|
||||
|
||||
// Per https://git.netfilter.org/libnftnl/tree/src/expr/dynset.c?id=84d12cfacf8ddd857a09435f3d982ab6250d250c#n170
|
||||
if len(e.Exprs) > 0 {
|
||||
flags |= NFT_DYNSET_F_EXPR
|
||||
switch len(e.Exprs) {
|
||||
case 1:
|
||||
exprData, err := Marshal(fam, e.Exprs[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opAttrs = append(opAttrs, netlink.Attribute{Type: unix.NFTA_DYNSET_EXPR, Data: exprData})
|
||||
default:
|
||||
var elemAttrs []netlink.Attribute
|
||||
for _, ex := range e.Exprs {
|
||||
exprData, err := Marshal(fam, ex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
elemAttrs = append(elemAttrs, netlink.Attribute{Type: unix.NFTA_LIST_ELEM, Data: exprData})
|
||||
}
|
||||
elemData, err := netlink.MarshalAttributes(elemAttrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opAttrs = append(opAttrs, netlink.Attribute{Type: NFTA_DYNSET_EXPRESSIONS, Data: elemData})
|
||||
}
|
||||
}
|
||||
opAttrs = append(opAttrs, netlink.Attribute{Type: unix.NFTA_DYNSET_FLAGS, Data: binaryutil.BigEndian.PutUint32(flags)})
|
||||
|
||||
opData, err := netlink.MarshalAttributes(opAttrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("dynset\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: opData},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Dynset) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_DYNSET_SET_NAME:
|
||||
e.SetName = ad.String()
|
||||
case unix.NFTA_DYNSET_SET_ID:
|
||||
e.SetID = ad.Uint32()
|
||||
case unix.NFTA_DYNSET_SREG_KEY:
|
||||
e.SrcRegKey = ad.Uint32()
|
||||
case unix.NFTA_DYNSET_SREG_DATA:
|
||||
e.SrcRegData = ad.Uint32()
|
||||
case unix.NFTA_DYNSET_OP:
|
||||
e.Operation = ad.Uint32()
|
||||
case unix.NFTA_DYNSET_TIMEOUT:
|
||||
e.Timeout = time.Duration(time.Millisecond * time.Duration(ad.Uint64()))
|
||||
case unix.NFTA_DYNSET_FLAGS:
|
||||
e.Invert = (ad.Uint32() & unix.NFT_DYNSET_F_INV) != 0
|
||||
case unix.NFTA_DYNSET_EXPR:
|
||||
exprs, err := parseexprfunc.ParseExprBytesFunc(fam, ad, ad.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
e.setInterfaceExprs(exprs)
|
||||
case NFTA_DYNSET_EXPRESSIONS:
|
||||
exprs, err := parseexprfunc.ParseExprMsgFunc(fam, ad.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
e.setInterfaceExprs(exprs)
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
|
||||
func (e *Dynset) setInterfaceExprs(exprs []interface{}) {
|
||||
e.Exprs = make([]Any, len(exprs))
|
||||
for i := range exprs {
|
||||
e.Exprs[i] = exprs[i].(Any)
|
||||
}
|
||||
}
|
||||
430
vendor/github.com/google/nftables/expr/expr.go
generated
vendored
Normal file
430
vendor/github.com/google/nftables/expr/expr.go
generated
vendored
Normal file
@@ -0,0 +1,430 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package expr provides nftables rule expressions.
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/google/nftables/internal/parseexprfunc"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func init() {
|
||||
parseexprfunc.ParseExprBytesFunc = func(fam byte, ad *netlink.AttributeDecoder, b []byte) ([]interface{}, error) {
|
||||
exprs, err := exprsFromBytes(fam, ad, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := make([]interface{}, len(exprs))
|
||||
for idx, expr := range exprs {
|
||||
result[idx] = expr
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
parseexprfunc.ParseExprMsgFunc = func(fam byte, b []byte) ([]interface{}, error) {
|
||||
ad, err := netlink.NewAttributeDecoder(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
var exprs []interface{}
|
||||
for ad.Next() {
|
||||
e, err := parseexprfunc.ParseExprBytesFunc(fam, ad, b)
|
||||
if err != nil {
|
||||
return e, err
|
||||
}
|
||||
exprs = append(exprs, e...)
|
||||
}
|
||||
return exprs, ad.Err()
|
||||
}
|
||||
}
|
||||
|
||||
// Marshal serializes the specified expression into a byte slice.
|
||||
func Marshal(fam byte, e Any) ([]byte, error) {
|
||||
return e.marshal(fam)
|
||||
}
|
||||
|
||||
// Unmarshal fills an expression from the specified byte slice.
|
||||
func Unmarshal(fam byte, data []byte, e Any) error {
|
||||
return e.unmarshal(fam, data)
|
||||
}
|
||||
|
||||
// exprsFromBytes parses nested raw expressions bytes
|
||||
// to construct nftables expressions
|
||||
func exprsFromBytes(fam byte, ad *netlink.AttributeDecoder, b []byte) ([]Any, error) {
|
||||
var exprs []Any
|
||||
ad.Do(func(b []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
var name string
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_EXPR_NAME:
|
||||
name = ad.String()
|
||||
if name == "notrack" {
|
||||
e := &Notrack{}
|
||||
exprs = append(exprs, e)
|
||||
}
|
||||
case unix.NFTA_EXPR_DATA:
|
||||
var e Any
|
||||
switch name {
|
||||
case "ct":
|
||||
e = &Ct{}
|
||||
case "range":
|
||||
e = &Range{}
|
||||
case "meta":
|
||||
e = &Meta{}
|
||||
case "cmp":
|
||||
e = &Cmp{}
|
||||
case "counter":
|
||||
e = &Counter{}
|
||||
case "objref":
|
||||
e = &Objref{}
|
||||
case "payload":
|
||||
e = &Payload{}
|
||||
case "lookup":
|
||||
e = &Lookup{}
|
||||
case "immediate":
|
||||
e = &Immediate{}
|
||||
case "bitwise":
|
||||
e = &Bitwise{}
|
||||
case "redir":
|
||||
e = &Redir{}
|
||||
case "nat":
|
||||
e = &NAT{}
|
||||
case "limit":
|
||||
e = &Limit{}
|
||||
case "quota":
|
||||
e = &Quota{}
|
||||
case "dynset":
|
||||
e = &Dynset{}
|
||||
case "log":
|
||||
e = &Log{}
|
||||
case "exthdr":
|
||||
e = &Exthdr{}
|
||||
case "match":
|
||||
e = &Match{}
|
||||
case "target":
|
||||
e = &Target{}
|
||||
case "connlimit":
|
||||
e = &Connlimit{}
|
||||
case "queue":
|
||||
e = &Queue{}
|
||||
case "flow_offload":
|
||||
e = &FlowOffload{}
|
||||
case "reject":
|
||||
e = &Reject{}
|
||||
case "masq":
|
||||
e = &Masq{}
|
||||
case "hash":
|
||||
e = &Hash{}
|
||||
}
|
||||
if e == nil {
|
||||
// TODO: introduce an opaque expression type so that users know
|
||||
// something is here.
|
||||
continue // unsupported expression type
|
||||
}
|
||||
|
||||
ad.Do(func(b []byte) error {
|
||||
if err := Unmarshal(fam, b, e); err != nil {
|
||||
return err
|
||||
}
|
||||
// Verdict expressions are a special-case of immediate expressions, so
|
||||
// if the expression is an immediate writing nothing into the verdict
|
||||
// register (invalid), re-parse it as a verdict expression.
|
||||
if imm, isImmediate := e.(*Immediate); isImmediate && imm.Register == unix.NFT_REG_VERDICT && len(imm.Data) == 0 {
|
||||
e = &Verdict{}
|
||||
if err := Unmarshal(fam, b, e); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
exprs = append(exprs, e)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
})
|
||||
return exprs, ad.Err()
|
||||
}
|
||||
|
||||
// Any is an interface implemented by any expression type.
|
||||
type Any interface {
|
||||
marshal(fam byte) ([]byte, error)
|
||||
unmarshal(fam byte, data []byte) error
|
||||
}
|
||||
|
||||
// MetaKey specifies which piece of meta information should be loaded. See also
|
||||
// https://wiki.nftables.org/wiki-nftables/index.php/Matching_packet_metainformation
|
||||
type MetaKey uint32
|
||||
|
||||
// Possible MetaKey values.
|
||||
const (
|
||||
MetaKeyLEN MetaKey = unix.NFT_META_LEN
|
||||
MetaKeyPROTOCOL MetaKey = unix.NFT_META_PROTOCOL
|
||||
MetaKeyPRIORITY MetaKey = unix.NFT_META_PRIORITY
|
||||
MetaKeyMARK MetaKey = unix.NFT_META_MARK
|
||||
MetaKeyIIF MetaKey = unix.NFT_META_IIF
|
||||
MetaKeyOIF MetaKey = unix.NFT_META_OIF
|
||||
MetaKeyIIFNAME MetaKey = unix.NFT_META_IIFNAME
|
||||
MetaKeyOIFNAME MetaKey = unix.NFT_META_OIFNAME
|
||||
MetaKeyIIFTYPE MetaKey = unix.NFT_META_IIFTYPE
|
||||
MetaKeyOIFTYPE MetaKey = unix.NFT_META_OIFTYPE
|
||||
MetaKeySKUID MetaKey = unix.NFT_META_SKUID
|
||||
MetaKeySKGID MetaKey = unix.NFT_META_SKGID
|
||||
MetaKeyNFTRACE MetaKey = unix.NFT_META_NFTRACE
|
||||
MetaKeyRTCLASSID MetaKey = unix.NFT_META_RTCLASSID
|
||||
MetaKeySECMARK MetaKey = unix.NFT_META_SECMARK
|
||||
MetaKeyNFPROTO MetaKey = unix.NFT_META_NFPROTO
|
||||
MetaKeyL4PROTO MetaKey = unix.NFT_META_L4PROTO
|
||||
MetaKeyBRIIIFNAME MetaKey = unix.NFT_META_BRI_IIFNAME
|
||||
MetaKeyBRIOIFNAME MetaKey = unix.NFT_META_BRI_OIFNAME
|
||||
MetaKeyPKTTYPE MetaKey = unix.NFT_META_PKTTYPE
|
||||
MetaKeyCPU MetaKey = unix.NFT_META_CPU
|
||||
MetaKeyIIFGROUP MetaKey = unix.NFT_META_IIFGROUP
|
||||
MetaKeyOIFGROUP MetaKey = unix.NFT_META_OIFGROUP
|
||||
MetaKeyCGROUP MetaKey = unix.NFT_META_CGROUP
|
||||
MetaKeyPRANDOM MetaKey = unix.NFT_META_PRANDOM
|
||||
)
|
||||
|
||||
// Meta loads packet meta information for later comparisons. See also
|
||||
// https://wiki.nftables.org/wiki-nftables/index.php/Matching_packet_metainformation
|
||||
type Meta struct {
|
||||
Key MetaKey
|
||||
SourceRegister bool
|
||||
Register uint32
|
||||
}
|
||||
|
||||
func (e *Meta) marshal(fam byte) ([]byte, error) {
|
||||
regData := []byte{}
|
||||
exprData, err := netlink.MarshalAttributes(
|
||||
[]netlink.Attribute{
|
||||
{Type: unix.NFTA_META_KEY, Data: binaryutil.BigEndian.PutUint32(uint32(e.Key))},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if e.SourceRegister {
|
||||
regData, err = netlink.MarshalAttributes(
|
||||
[]netlink.Attribute{
|
||||
{Type: unix.NFTA_META_SREG, Data: binaryutil.BigEndian.PutUint32(e.Register)},
|
||||
},
|
||||
)
|
||||
} else {
|
||||
regData, err = netlink.MarshalAttributes(
|
||||
[]netlink.Attribute{
|
||||
{Type: unix.NFTA_META_DREG, Data: binaryutil.BigEndian.PutUint32(e.Register)},
|
||||
},
|
||||
)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
exprData = append(exprData, regData...)
|
||||
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("meta\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: exprData},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Meta) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_META_SREG:
|
||||
e.Register = ad.Uint32()
|
||||
e.SourceRegister = true
|
||||
case unix.NFTA_META_DREG:
|
||||
e.Register = ad.Uint32()
|
||||
case unix.NFTA_META_KEY:
|
||||
e.Key = MetaKey(ad.Uint32())
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
|
||||
// Masq (Masquerade) is a special case of SNAT, where the source address is
|
||||
// automagically set to the address of the output interface. See also
|
||||
// https://wiki.nftables.org/wiki-nftables/index.php/Performing_Network_Address_Translation_(NAT)#Masquerading
|
||||
type Masq struct {
|
||||
Random bool
|
||||
FullyRandom bool
|
||||
Persistent bool
|
||||
ToPorts bool
|
||||
RegProtoMin uint32
|
||||
RegProtoMax uint32
|
||||
}
|
||||
|
||||
const (
|
||||
// NF_NAT_RANGE_PROTO_RANDOM defines flag for a random masquerade
|
||||
NF_NAT_RANGE_PROTO_RANDOM = unix.NF_NAT_RANGE_PROTO_RANDOM
|
||||
// NF_NAT_RANGE_PROTO_RANDOM_FULLY defines flag for a fully random masquerade
|
||||
NF_NAT_RANGE_PROTO_RANDOM_FULLY = unix.NF_NAT_RANGE_PROTO_RANDOM_FULLY
|
||||
// NF_NAT_RANGE_PERSISTENT defines flag for a persistent masquerade
|
||||
NF_NAT_RANGE_PERSISTENT = unix.NF_NAT_RANGE_PERSISTENT
|
||||
// NF_NAT_RANGE_PREFIX defines flag for a prefix masquerade
|
||||
NF_NAT_RANGE_PREFIX = unix.NF_NAT_RANGE_NETMAP
|
||||
)
|
||||
|
||||
func (e *Masq) marshal(fam byte) ([]byte, error) {
|
||||
msgData := []byte{}
|
||||
if !e.ToPorts {
|
||||
flags := uint32(0)
|
||||
if e.Random {
|
||||
flags |= NF_NAT_RANGE_PROTO_RANDOM
|
||||
}
|
||||
if e.FullyRandom {
|
||||
flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY
|
||||
}
|
||||
if e.Persistent {
|
||||
flags |= NF_NAT_RANGE_PERSISTENT
|
||||
}
|
||||
if flags != 0 {
|
||||
flagsData, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_MASQ_FLAGS, Data: binaryutil.BigEndian.PutUint32(flags)}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msgData = append(msgData, flagsData...)
|
||||
}
|
||||
} else {
|
||||
regsData, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_MASQ_REG_PROTO_MIN, Data: binaryutil.BigEndian.PutUint32(e.RegProtoMin)}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msgData = append(msgData, regsData...)
|
||||
if e.RegProtoMax != 0 {
|
||||
regsData, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_MASQ_REG_PROTO_MAX, Data: binaryutil.BigEndian.PutUint32(e.RegProtoMax)}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msgData = append(msgData, regsData...)
|
||||
}
|
||||
}
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("masq\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: msgData},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Masq) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_MASQ_REG_PROTO_MIN:
|
||||
e.ToPorts = true
|
||||
e.RegProtoMin = ad.Uint32()
|
||||
case unix.NFTA_MASQ_REG_PROTO_MAX:
|
||||
e.RegProtoMax = ad.Uint32()
|
||||
case unix.NFTA_MASQ_FLAGS:
|
||||
flags := ad.Uint32()
|
||||
e.Persistent = (flags & NF_NAT_RANGE_PERSISTENT) != 0
|
||||
e.Random = (flags & NF_NAT_RANGE_PROTO_RANDOM) != 0
|
||||
e.FullyRandom = (flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) != 0
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
|
||||
// CmpOp specifies which type of comparison should be performed.
|
||||
type CmpOp uint32
|
||||
|
||||
// Possible CmpOp values.
|
||||
const (
|
||||
CmpOpEq CmpOp = unix.NFT_CMP_EQ
|
||||
CmpOpNeq CmpOp = unix.NFT_CMP_NEQ
|
||||
CmpOpLt CmpOp = unix.NFT_CMP_LT
|
||||
CmpOpLte CmpOp = unix.NFT_CMP_LTE
|
||||
CmpOpGt CmpOp = unix.NFT_CMP_GT
|
||||
CmpOpGte CmpOp = unix.NFT_CMP_GTE
|
||||
)
|
||||
|
||||
// Cmp compares a register with the specified data.
|
||||
type Cmp struct {
|
||||
Op CmpOp
|
||||
Register uint32
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func (e *Cmp) marshal(fam byte) ([]byte, error) {
|
||||
cmpData, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_DATA_VALUE, Data: e.Data},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
exprData, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_CMP_SREG, Data: binaryutil.BigEndian.PutUint32(e.Register)},
|
||||
{Type: unix.NFTA_CMP_OP, Data: binaryutil.BigEndian.PutUint32(uint32(e.Op))},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_CMP_DATA, Data: cmpData},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("cmp\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: exprData},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Cmp) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_CMP_SREG:
|
||||
e.Register = ad.Uint32()
|
||||
case unix.NFTA_CMP_OP:
|
||||
e.Op = CmpOp(ad.Uint32())
|
||||
case unix.NFTA_CMP_DATA:
|
||||
ad.Do(func(b []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
if ad.Next() && ad.Type() == unix.NFTA_DATA_VALUE {
|
||||
ad.Do(func(b []byte) error {
|
||||
e.Data = b
|
||||
return nil
|
||||
})
|
||||
}
|
||||
return ad.Err()
|
||||
})
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
102
vendor/github.com/google/nftables/expr/exthdr.go
generated
vendored
Normal file
102
vendor/github.com/google/nftables/expr/exthdr.go
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type ExthdrOp uint32
|
||||
|
||||
const (
|
||||
ExthdrOpIpv6 ExthdrOp = unix.NFT_EXTHDR_OP_IPV6
|
||||
ExthdrOpTcpopt ExthdrOp = unix.NFT_EXTHDR_OP_TCPOPT
|
||||
)
|
||||
|
||||
type Exthdr struct {
|
||||
DestRegister uint32
|
||||
Type uint8
|
||||
Offset uint32
|
||||
Len uint32
|
||||
Flags uint32
|
||||
Op ExthdrOp
|
||||
SourceRegister uint32
|
||||
}
|
||||
|
||||
func (e *Exthdr) marshal(fam byte) ([]byte, error) {
|
||||
var attr []netlink.Attribute
|
||||
|
||||
// Operations are differentiated by the Op and whether the SourceRegister
|
||||
// or DestRegister is set. Mixing them results in EOPNOTSUPP.
|
||||
if e.SourceRegister != 0 {
|
||||
attr = []netlink.Attribute{
|
||||
{Type: unix.NFTA_EXTHDR_SREG, Data: binaryutil.BigEndian.PutUint32(e.SourceRegister)}}
|
||||
} else {
|
||||
attr = []netlink.Attribute{
|
||||
{Type: unix.NFTA_EXTHDR_DREG, Data: binaryutil.BigEndian.PutUint32(e.DestRegister)}}
|
||||
}
|
||||
|
||||
attr = append(attr,
|
||||
netlink.Attribute{Type: unix.NFTA_EXTHDR_TYPE, Data: []byte{e.Type}},
|
||||
netlink.Attribute{Type: unix.NFTA_EXTHDR_OFFSET, Data: binaryutil.BigEndian.PutUint32(e.Offset)},
|
||||
netlink.Attribute{Type: unix.NFTA_EXTHDR_LEN, Data: binaryutil.BigEndian.PutUint32(e.Len)},
|
||||
netlink.Attribute{Type: unix.NFTA_EXTHDR_OP, Data: binaryutil.BigEndian.PutUint32(uint32(e.Op))})
|
||||
|
||||
// Flags is only set if DREG is set
|
||||
if e.DestRegister != 0 {
|
||||
attr = append(attr,
|
||||
netlink.Attribute{Type: unix.NFTA_EXTHDR_FLAGS, Data: binaryutil.BigEndian.PutUint32(e.Flags)})
|
||||
}
|
||||
|
||||
data, err := netlink.MarshalAttributes(attr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("exthdr\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Exthdr) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_EXTHDR_DREG:
|
||||
e.DestRegister = ad.Uint32()
|
||||
case unix.NFTA_EXTHDR_TYPE:
|
||||
e.Type = ad.Uint8()
|
||||
case unix.NFTA_EXTHDR_OFFSET:
|
||||
e.Offset = ad.Uint32()
|
||||
case unix.NFTA_EXTHDR_LEN:
|
||||
e.Len = ad.Uint32()
|
||||
case unix.NFTA_EXTHDR_FLAGS:
|
||||
e.Flags = ad.Uint32()
|
||||
case unix.NFTA_EXTHDR_OP:
|
||||
e.Op = ExthdrOp(ad.Uint32())
|
||||
case unix.NFTA_EXTHDR_SREG:
|
||||
e.SourceRegister = ad.Uint32()
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
128
vendor/github.com/google/nftables/expr/fib.go
generated
vendored
Normal file
128
vendor/github.com/google/nftables/expr/fib.go
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// Fib defines fib expression structure
|
||||
type Fib struct {
|
||||
Register uint32
|
||||
ResultOIF bool
|
||||
ResultOIFNAME bool
|
||||
ResultADDRTYPE bool
|
||||
FlagSADDR bool
|
||||
FlagDADDR bool
|
||||
FlagMARK bool
|
||||
FlagIIF bool
|
||||
FlagOIF bool
|
||||
FlagPRESENT bool
|
||||
}
|
||||
|
||||
func (e *Fib) marshal(fam byte) ([]byte, error) {
|
||||
data := []byte{}
|
||||
reg, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_FIB_DREG, Data: binaryutil.BigEndian.PutUint32(e.Register)},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data = append(data, reg...)
|
||||
flags := uint32(0)
|
||||
if e.FlagSADDR {
|
||||
flags |= unix.NFTA_FIB_F_SADDR
|
||||
}
|
||||
if e.FlagDADDR {
|
||||
flags |= unix.NFTA_FIB_F_DADDR
|
||||
}
|
||||
if e.FlagMARK {
|
||||
flags |= unix.NFTA_FIB_F_MARK
|
||||
}
|
||||
if e.FlagIIF {
|
||||
flags |= unix.NFTA_FIB_F_IIF
|
||||
}
|
||||
if e.FlagOIF {
|
||||
flags |= unix.NFTA_FIB_F_OIF
|
||||
}
|
||||
if e.FlagPRESENT {
|
||||
flags |= unix.NFTA_FIB_F_PRESENT
|
||||
}
|
||||
if flags != 0 {
|
||||
flg, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_FIB_FLAGS, Data: binaryutil.BigEndian.PutUint32(flags)},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data = append(data, flg...)
|
||||
}
|
||||
results := uint32(0)
|
||||
if e.ResultOIF {
|
||||
results |= unix.NFT_FIB_RESULT_OIF
|
||||
}
|
||||
if e.ResultOIFNAME {
|
||||
results |= unix.NFT_FIB_RESULT_OIFNAME
|
||||
}
|
||||
if e.ResultADDRTYPE {
|
||||
results |= unix.NFT_FIB_RESULT_ADDRTYPE
|
||||
}
|
||||
if results != 0 {
|
||||
rslt, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_FIB_RESULT, Data: binaryutil.BigEndian.PutUint32(results)},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data = append(data, rslt...)
|
||||
}
|
||||
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("fib\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Fib) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_FIB_DREG:
|
||||
e.Register = ad.Uint32()
|
||||
case unix.NFTA_FIB_RESULT:
|
||||
result := ad.Uint32()
|
||||
e.ResultOIF = (result & unix.NFT_FIB_RESULT_OIF) == 1
|
||||
e.ResultOIFNAME = (result & unix.NFT_FIB_RESULT_OIFNAME) == 1
|
||||
e.ResultADDRTYPE = (result & unix.NFT_FIB_RESULT_ADDRTYPE) == 1
|
||||
case unix.NFTA_FIB_FLAGS:
|
||||
flags := ad.Uint32()
|
||||
e.FlagSADDR = (flags & unix.NFTA_FIB_F_SADDR) == 1
|
||||
e.FlagDADDR = (flags & unix.NFTA_FIB_F_DADDR) == 1
|
||||
e.FlagMARK = (flags & unix.NFTA_FIB_F_MARK) == 1
|
||||
e.FlagIIF = (flags & unix.NFTA_FIB_F_IIF) == 1
|
||||
e.FlagOIF = (flags & unix.NFTA_FIB_F_OIF) == 1
|
||||
e.FlagPRESENT = (flags & unix.NFTA_FIB_F_PRESENT) == 1
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
59
vendor/github.com/google/nftables/expr/flow_offload.go
generated
vendored
Normal file
59
vendor/github.com/google/nftables/expr/flow_offload.go
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const NFTNL_EXPR_FLOW_TABLE_NAME = 1
|
||||
|
||||
type FlowOffload struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (e *FlowOffload) marshal(fam byte) ([]byte, error) {
|
||||
data, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: NFTNL_EXPR_FLOW_TABLE_NAME, Data: []byte(e.Name)},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("flow_offload\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *FlowOffload) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case NFTNL_EXPR_FLOW_TABLE_NAME:
|
||||
e.Name = ad.String()
|
||||
}
|
||||
}
|
||||
|
||||
return ad.Err()
|
||||
}
|
||||
94
vendor/github.com/google/nftables/expr/hash.go
generated
vendored
Normal file
94
vendor/github.com/google/nftables/expr/hash.go
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type HashType uint32
|
||||
|
||||
const (
|
||||
HashTypeJenkins HashType = unix.NFT_HASH_JENKINS
|
||||
HashTypeSym HashType = unix.NFT_HASH_SYM
|
||||
)
|
||||
|
||||
// Hash defines type for nftables internal hashing functions
|
||||
type Hash struct {
|
||||
SourceRegister uint32
|
||||
DestRegister uint32
|
||||
Length uint32
|
||||
Modulus uint32
|
||||
Seed uint32
|
||||
Offset uint32
|
||||
Type HashType
|
||||
}
|
||||
|
||||
func (e *Hash) marshal(fam byte) ([]byte, error) {
|
||||
hashAttrs := []netlink.Attribute{
|
||||
{Type: unix.NFTA_HASH_SREG, Data: binaryutil.BigEndian.PutUint32(uint32(e.SourceRegister))},
|
||||
{Type: unix.NFTA_HASH_DREG, Data: binaryutil.BigEndian.PutUint32(uint32(e.DestRegister))},
|
||||
{Type: unix.NFTA_HASH_LEN, Data: binaryutil.BigEndian.PutUint32(uint32(e.Length))},
|
||||
{Type: unix.NFTA_HASH_MODULUS, Data: binaryutil.BigEndian.PutUint32(uint32(e.Modulus))},
|
||||
}
|
||||
if e.Seed != 0 {
|
||||
hashAttrs = append(hashAttrs, netlink.Attribute{
|
||||
Type: unix.NFTA_HASH_SEED, Data: binaryutil.BigEndian.PutUint32(uint32(e.Seed)),
|
||||
})
|
||||
}
|
||||
hashAttrs = append(hashAttrs, []netlink.Attribute{
|
||||
{Type: unix.NFTA_HASH_OFFSET, Data: binaryutil.BigEndian.PutUint32(uint32(e.Offset))},
|
||||
{Type: unix.NFTA_HASH_TYPE, Data: binaryutil.BigEndian.PutUint32(uint32(e.Type))},
|
||||
}...)
|
||||
data, err := netlink.MarshalAttributes(hashAttrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("hash\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Hash) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_HASH_SREG:
|
||||
e.SourceRegister = ad.Uint32()
|
||||
case unix.NFTA_HASH_DREG:
|
||||
e.DestRegister = ad.Uint32()
|
||||
case unix.NFTA_HASH_LEN:
|
||||
e.Length = ad.Uint32()
|
||||
case unix.NFTA_HASH_MODULUS:
|
||||
e.Modulus = ad.Uint32()
|
||||
case unix.NFTA_HASH_SEED:
|
||||
e.Seed = ad.Uint32()
|
||||
case unix.NFTA_HASH_OFFSET:
|
||||
e.Offset = ad.Uint32()
|
||||
case unix.NFTA_HASH_TYPE:
|
||||
e.Type = HashType(ad.Uint32())
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
79
vendor/github.com/google/nftables/expr/immediate.go
generated
vendored
Normal file
79
vendor/github.com/google/nftables/expr/immediate.go
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type Immediate struct {
|
||||
Register uint32
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func (e *Immediate) marshal(fam byte) ([]byte, error) {
|
||||
immData, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_DATA_VALUE, Data: e.Data},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_IMMEDIATE_DREG, Data: binaryutil.BigEndian.PutUint32(e.Register)},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_IMMEDIATE_DATA, Data: immData},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("immediate\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Immediate) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_IMMEDIATE_DREG:
|
||||
e.Register = ad.Uint32()
|
||||
case unix.NFTA_IMMEDIATE_DATA:
|
||||
nestedAD, err := netlink.NewAttributeDecoder(ad.Bytes())
|
||||
if err != nil {
|
||||
return fmt.Errorf("nested NewAttributeDecoder() failed: %v", err)
|
||||
}
|
||||
for nestedAD.Next() {
|
||||
switch nestedAD.Type() {
|
||||
case unix.NFTA_DATA_VALUE:
|
||||
e.Data = nestedAD.Bytes()
|
||||
}
|
||||
}
|
||||
if nestedAD.Err() != nil {
|
||||
return fmt.Errorf("decoding immediate: %v", nestedAD.Err())
|
||||
}
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
128
vendor/github.com/google/nftables/expr/limit.go
generated
vendored
Normal file
128
vendor/github.com/google/nftables/expr/limit.go
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// LimitType represents the type of the limit expression.
|
||||
type LimitType uint32
|
||||
|
||||
// Imported from the nft_limit_type enum in netfilter/nf_tables.h.
|
||||
const (
|
||||
LimitTypePkts LimitType = unix.NFT_LIMIT_PKTS
|
||||
LimitTypePktBytes LimitType = unix.NFT_LIMIT_PKT_BYTES
|
||||
)
|
||||
|
||||
// LimitTime represents the limit unit.
|
||||
type LimitTime uint64
|
||||
|
||||
// Possible limit unit values.
|
||||
const (
|
||||
LimitTimeSecond LimitTime = 1
|
||||
LimitTimeMinute LimitTime = 60
|
||||
LimitTimeHour LimitTime = 60 * 60
|
||||
LimitTimeDay LimitTime = 60 * 60 * 24
|
||||
LimitTimeWeek LimitTime = 60 * 60 * 24 * 7
|
||||
)
|
||||
|
||||
func limitTime(value uint64) (LimitTime, error) {
|
||||
switch LimitTime(value) {
|
||||
case LimitTimeSecond:
|
||||
return LimitTimeSecond, nil
|
||||
case LimitTimeMinute:
|
||||
return LimitTimeMinute, nil
|
||||
case LimitTimeHour:
|
||||
return LimitTimeHour, nil
|
||||
case LimitTimeDay:
|
||||
return LimitTimeDay, nil
|
||||
case LimitTimeWeek:
|
||||
return LimitTimeWeek, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("expr: invalid limit unit value %d", value)
|
||||
}
|
||||
}
|
||||
|
||||
// Limit represents a rate limit expression.
|
||||
type Limit struct {
|
||||
Type LimitType
|
||||
Rate uint64
|
||||
Over bool
|
||||
Unit LimitTime
|
||||
Burst uint32
|
||||
}
|
||||
|
||||
func (l *Limit) marshal(fam byte) ([]byte, error) {
|
||||
var flags uint32
|
||||
if l.Over {
|
||||
flags = unix.NFT_LIMIT_F_INV
|
||||
}
|
||||
attrs := []netlink.Attribute{
|
||||
{Type: unix.NFTA_LIMIT_RATE, Data: binaryutil.BigEndian.PutUint64(l.Rate)},
|
||||
{Type: unix.NFTA_LIMIT_UNIT, Data: binaryutil.BigEndian.PutUint64(uint64(l.Unit))},
|
||||
{Type: unix.NFTA_LIMIT_BURST, Data: binaryutil.BigEndian.PutUint32(l.Burst)},
|
||||
{Type: unix.NFTA_LIMIT_TYPE, Data: binaryutil.BigEndian.PutUint32(uint32(l.Type))},
|
||||
{Type: unix.NFTA_LIMIT_FLAGS, Data: binaryutil.BigEndian.PutUint32(flags)},
|
||||
}
|
||||
|
||||
data, err := netlink.MarshalAttributes(attrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("limit\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (l *Limit) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_LIMIT_RATE:
|
||||
l.Rate = ad.Uint64()
|
||||
case unix.NFTA_LIMIT_UNIT:
|
||||
l.Unit, err = limitTime(ad.Uint64())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case unix.NFTA_LIMIT_BURST:
|
||||
l.Burst = ad.Uint32()
|
||||
case unix.NFTA_LIMIT_TYPE:
|
||||
l.Type = LimitType(ad.Uint32())
|
||||
if l.Type != LimitTypePkts && l.Type != LimitTypePktBytes {
|
||||
return fmt.Errorf("expr: invalid limit type %d", l.Type)
|
||||
}
|
||||
case unix.NFTA_LIMIT_FLAGS:
|
||||
l.Over = (ad.Uint32() & unix.NFT_LIMIT_F_INV) == 1
|
||||
default:
|
||||
return errors.New("expr: unhandled limit netlink attribute")
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
150
vendor/github.com/google/nftables/expr/log.go
generated
vendored
Normal file
150
vendor/github.com/google/nftables/expr/log.go
generated
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
// Copyright 2019 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type LogLevel uint32
|
||||
|
||||
const (
|
||||
// See https://git.netfilter.org/nftables/tree/include/linux/netfilter/nf_tables.h?id=5b364657a35f4e4cd5d220ba2a45303d729c8eca#n1226
|
||||
LogLevelEmerg LogLevel = iota
|
||||
LogLevelAlert
|
||||
LogLevelCrit
|
||||
LogLevelErr
|
||||
LogLevelWarning
|
||||
LogLevelNotice
|
||||
LogLevelInfo
|
||||
LogLevelDebug
|
||||
LogLevelAudit
|
||||
)
|
||||
|
||||
type LogFlags uint32
|
||||
|
||||
const (
|
||||
// See https://git.netfilter.org/nftables/tree/include/linux/netfilter/nf_log.h?id=5b364657a35f4e4cd5d220ba2a45303d729c8eca
|
||||
LogFlagsTCPSeq LogFlags = 0x01 << iota
|
||||
LogFlagsTCPOpt
|
||||
LogFlagsIPOpt
|
||||
LogFlagsUID
|
||||
LogFlagsNFLog
|
||||
LogFlagsMACDecode
|
||||
LogFlagsMask LogFlags = 0x2f
|
||||
)
|
||||
|
||||
// Log defines type for NFT logging
|
||||
// See https://git.netfilter.org/libnftnl/tree/src/expr/log.c?id=09456c720e9c00eecc08e41ac6b7c291b3821ee5#n25
|
||||
type Log struct {
|
||||
Level LogLevel
|
||||
// Refers to log flags (flags all, flags ip options, ...)
|
||||
Flags LogFlags
|
||||
// Equivalent to expression flags.
|
||||
// Indicates that an option is set by setting a bit
|
||||
// on index referred by the NFTA_LOG_* value.
|
||||
// See https://cs.opensource.google/go/x/sys/+/3681064d:unix/ztypes_linux.go;l=2126;drc=3681064d51587c1db0324b3d5c23c2ddbcff6e8f
|
||||
Key uint32
|
||||
Snaplen uint32
|
||||
Group uint16
|
||||
QThreshold uint16
|
||||
// Log prefix string content
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func (e *Log) marshal(fam byte) ([]byte, error) {
|
||||
// Per https://git.netfilter.org/libnftnl/tree/src/expr/log.c?id=09456c720e9c00eecc08e41ac6b7c291b3821ee5#n129
|
||||
attrs := make([]netlink.Attribute, 0)
|
||||
if e.Key&(1<<unix.NFTA_LOG_GROUP) != 0 {
|
||||
attrs = append(attrs, netlink.Attribute{
|
||||
Type: unix.NFTA_LOG_GROUP,
|
||||
Data: binaryutil.BigEndian.PutUint16(e.Group),
|
||||
})
|
||||
}
|
||||
if e.Key&(1<<unix.NFTA_LOG_PREFIX) != 0 {
|
||||
prefix := append(e.Data, '\x00')
|
||||
attrs = append(attrs, netlink.Attribute{
|
||||
Type: unix.NFTA_LOG_PREFIX,
|
||||
Data: prefix,
|
||||
})
|
||||
}
|
||||
if e.Key&(1<<unix.NFTA_LOG_SNAPLEN) != 0 {
|
||||
attrs = append(attrs, netlink.Attribute{
|
||||
Type: unix.NFTA_LOG_SNAPLEN,
|
||||
Data: binaryutil.BigEndian.PutUint32(e.Snaplen),
|
||||
})
|
||||
}
|
||||
if e.Key&(1<<unix.NFTA_LOG_QTHRESHOLD) != 0 {
|
||||
attrs = append(attrs, netlink.Attribute{
|
||||
Type: unix.NFTA_LOG_QTHRESHOLD,
|
||||
Data: binaryutil.BigEndian.PutUint16(e.QThreshold),
|
||||
})
|
||||
}
|
||||
if e.Key&(1<<unix.NFTA_LOG_LEVEL) != 0 {
|
||||
attrs = append(attrs, netlink.Attribute{
|
||||
Type: unix.NFTA_LOG_LEVEL,
|
||||
Data: binaryutil.BigEndian.PutUint32(uint32(e.Level)),
|
||||
})
|
||||
}
|
||||
if e.Key&(1<<unix.NFTA_LOG_FLAGS) != 0 {
|
||||
attrs = append(attrs, netlink.Attribute{
|
||||
Type: unix.NFTA_LOG_FLAGS,
|
||||
Data: binaryutil.BigEndian.PutUint32(uint32(e.Flags)),
|
||||
})
|
||||
}
|
||||
|
||||
data, err := netlink.MarshalAttributes(attrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("log\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Log) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
e.Key |= 1 << uint32(ad.Type())
|
||||
data := ad.Bytes()
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_LOG_GROUP:
|
||||
e.Group = binaryutil.BigEndian.Uint16(data)
|
||||
case unix.NFTA_LOG_PREFIX:
|
||||
// Getting rid of \x00 at the end of string
|
||||
e.Data = data[:len(data)-1]
|
||||
case unix.NFTA_LOG_SNAPLEN:
|
||||
e.Snaplen = binaryutil.BigEndian.Uint32(data)
|
||||
case unix.NFTA_LOG_QTHRESHOLD:
|
||||
e.QThreshold = binaryutil.BigEndian.Uint16(data)
|
||||
case unix.NFTA_LOG_LEVEL:
|
||||
e.Level = LogLevel(binaryutil.BigEndian.Uint32(data))
|
||||
case unix.NFTA_LOG_FLAGS:
|
||||
e.Flags = LogFlags(binaryutil.BigEndian.Uint32(data))
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
85
vendor/github.com/google/nftables/expr/lookup.go
generated
vendored
Normal file
85
vendor/github.com/google/nftables/expr/lookup.go
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// Lookup represents a match against the contents of a set.
|
||||
type Lookup struct {
|
||||
SourceRegister uint32
|
||||
DestRegister uint32
|
||||
IsDestRegSet bool
|
||||
|
||||
SetID uint32
|
||||
SetName string
|
||||
Invert bool
|
||||
}
|
||||
|
||||
func (e *Lookup) marshal(fam byte) ([]byte, error) {
|
||||
// See: https://git.netfilter.org/libnftnl/tree/src/expr/lookup.c?id=6dc1c3d8bb64077da7f3f28c7368fb087d10a492#n115
|
||||
var opAttrs []netlink.Attribute
|
||||
if e.SourceRegister != 0 {
|
||||
opAttrs = append(opAttrs, netlink.Attribute{Type: unix.NFTA_LOOKUP_SREG, Data: binaryutil.BigEndian.PutUint32(e.SourceRegister)})
|
||||
}
|
||||
if e.IsDestRegSet {
|
||||
opAttrs = append(opAttrs, netlink.Attribute{Type: unix.NFTA_LOOKUP_DREG, Data: binaryutil.BigEndian.PutUint32(e.DestRegister)})
|
||||
}
|
||||
if e.Invert {
|
||||
opAttrs = append(opAttrs, netlink.Attribute{Type: unix.NFTA_LOOKUP_FLAGS, Data: binaryutil.BigEndian.PutUint32(unix.NFT_LOOKUP_F_INV)})
|
||||
}
|
||||
opAttrs = append(opAttrs,
|
||||
netlink.Attribute{Type: unix.NFTA_LOOKUP_SET, Data: []byte(e.SetName + "\x00")},
|
||||
netlink.Attribute{Type: unix.NFTA_LOOKUP_SET_ID, Data: binaryutil.BigEndian.PutUint32(e.SetID)},
|
||||
)
|
||||
opData, err := netlink.MarshalAttributes(opAttrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("lookup\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: opData},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Lookup) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_LOOKUP_SET:
|
||||
e.SetName = ad.String()
|
||||
case unix.NFTA_LOOKUP_SET_ID:
|
||||
e.SetID = ad.Uint32()
|
||||
case unix.NFTA_LOOKUP_SREG:
|
||||
e.SourceRegister = ad.Uint32()
|
||||
case unix.NFTA_LOOKUP_DREG:
|
||||
e.DestRegister = ad.Uint32()
|
||||
e.IsDestRegSet = true
|
||||
case unix.NFTA_LOOKUP_FLAGS:
|
||||
e.Invert = (ad.Uint32() & unix.NFT_LOOKUP_F_INV) != 0
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
75
vendor/github.com/google/nftables/expr/match.go
generated
vendored
Normal file
75
vendor/github.com/google/nftables/expr/match.go
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
package expr
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/google/nftables/xt"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// See https://git.netfilter.org/libnftnl/tree/src/expr/match.c?id=09456c720e9c00eecc08e41ac6b7c291b3821ee5#n30
|
||||
type Match struct {
|
||||
Name string
|
||||
Rev uint32
|
||||
Info xt.InfoAny
|
||||
}
|
||||
|
||||
func (e *Match) marshal(fam byte) ([]byte, error) {
|
||||
// Per https://git.netfilter.org/libnftnl/tree/src/expr/match.c?id=09456c720e9c00eecc08e41ac6b7c291b3821ee5#n38
|
||||
name := e.Name
|
||||
// limit the extension name as (some) user-space tools do and leave room for
|
||||
// trailing \x00
|
||||
if len(name) >= /* sic! */ XTablesExtensionNameMaxLen {
|
||||
name = name[:XTablesExtensionNameMaxLen-1] // leave room for trailing \x00.
|
||||
}
|
||||
// Marshalling assumes that the correct Info type for the particular table
|
||||
// family and Match revision has been set.
|
||||
info, err := xt.Marshal(xt.TableFamily(fam), e.Rev, e.Info)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
attrs := []netlink.Attribute{
|
||||
{Type: unix.NFTA_MATCH_NAME, Data: []byte(name + "\x00")},
|
||||
{Type: unix.NFTA_MATCH_REV, Data: binaryutil.BigEndian.PutUint32(e.Rev)},
|
||||
{Type: unix.NFTA_MATCH_INFO, Data: info},
|
||||
}
|
||||
data, err := netlink.MarshalAttributes(attrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("match\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Match) unmarshal(fam byte, data []byte) error {
|
||||
// Per https://git.netfilter.org/libnftnl/tree/src/expr/match.c?id=09456c720e9c00eecc08e41ac6b7c291b3821ee5#n65
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var info []byte
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_MATCH_NAME:
|
||||
// We are forgiving here, accepting any length and even missing terminating \x00.
|
||||
e.Name = string(bytes.TrimRight(ad.Bytes(), "\x00"))
|
||||
case unix.NFTA_MATCH_REV:
|
||||
e.Rev = ad.Uint32()
|
||||
case unix.NFTA_MATCH_INFO:
|
||||
info = ad.Bytes()
|
||||
}
|
||||
}
|
||||
if err = ad.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
e.Info, err = xt.Unmarshal(e.Name, xt.TableFamily(fam), e.Rev, info)
|
||||
return err
|
||||
}
|
||||
132
vendor/github.com/google/nftables/expr/nat.go
generated
vendored
Normal file
132
vendor/github.com/google/nftables/expr/nat.go
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type NATType uint32
|
||||
|
||||
// Possible NATType values.
|
||||
const (
|
||||
NATTypeSourceNAT NATType = unix.NFT_NAT_SNAT
|
||||
NATTypeDestNAT NATType = unix.NFT_NAT_DNAT
|
||||
)
|
||||
|
||||
type NAT struct {
|
||||
Type NATType
|
||||
Family uint32 // TODO: typed const
|
||||
RegAddrMin uint32
|
||||
RegAddrMax uint32
|
||||
RegProtoMin uint32
|
||||
RegProtoMax uint32
|
||||
Random bool
|
||||
FullyRandom bool
|
||||
Persistent bool
|
||||
Prefix bool
|
||||
}
|
||||
|
||||
// |00048|N-|00001| |len |flags| type|
|
||||
// |00008|--|00001| |len |flags| type|
|
||||
// | 6e 61 74 00 | | data | n a t
|
||||
// |00036|N-|00002| |len |flags| type|
|
||||
// |00008|--|00001| |len |flags| type| NFTA_NAT_TYPE
|
||||
// | 00 00 00 01 | | data | NFT_NAT_DNAT
|
||||
// |00008|--|00002| |len |flags| type| NFTA_NAT_FAMILY
|
||||
// | 00 00 00 02 | | data | NFPROTO_IPV4
|
||||
// |00008|--|00003| |len |flags| type| NFTA_NAT_REG_ADDR_MIN
|
||||
// | 00 00 00 01 | | data | reg 1
|
||||
// |00008|--|00005| |len |flags| type| NFTA_NAT_REG_PROTO_MIN
|
||||
// | 00 00 00 02 | | data | reg 2
|
||||
|
||||
func (e *NAT) marshal(fam byte) ([]byte, error) {
|
||||
attrs := []netlink.Attribute{
|
||||
{Type: unix.NFTA_NAT_TYPE, Data: binaryutil.BigEndian.PutUint32(uint32(e.Type))},
|
||||
{Type: unix.NFTA_NAT_FAMILY, Data: binaryutil.BigEndian.PutUint32(e.Family)},
|
||||
}
|
||||
if e.RegAddrMin != 0 {
|
||||
attrs = append(attrs, netlink.Attribute{Type: unix.NFTA_NAT_REG_ADDR_MIN, Data: binaryutil.BigEndian.PutUint32(e.RegAddrMin)})
|
||||
if e.RegAddrMax != 0 {
|
||||
attrs = append(attrs, netlink.Attribute{Type: unix.NFTA_NAT_REG_ADDR_MAX, Data: binaryutil.BigEndian.PutUint32(e.RegAddrMax)})
|
||||
}
|
||||
}
|
||||
if e.RegProtoMin != 0 {
|
||||
attrs = append(attrs, netlink.Attribute{Type: unix.NFTA_NAT_REG_PROTO_MIN, Data: binaryutil.BigEndian.PutUint32(e.RegProtoMin)})
|
||||
if e.RegProtoMax != 0 {
|
||||
attrs = append(attrs, netlink.Attribute{Type: unix.NFTA_NAT_REG_PROTO_MAX, Data: binaryutil.BigEndian.PutUint32(e.RegProtoMax)})
|
||||
}
|
||||
}
|
||||
flags := uint32(0)
|
||||
if e.Random {
|
||||
flags |= NF_NAT_RANGE_PROTO_RANDOM
|
||||
}
|
||||
if e.FullyRandom {
|
||||
flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY
|
||||
}
|
||||
if e.Persistent {
|
||||
flags |= NF_NAT_RANGE_PERSISTENT
|
||||
}
|
||||
if e.Prefix {
|
||||
flags |= NF_NAT_RANGE_PREFIX
|
||||
}
|
||||
if flags != 0 {
|
||||
attrs = append(attrs, netlink.Attribute{Type: unix.NFTA_NAT_FLAGS, Data: binaryutil.BigEndian.PutUint32(flags)})
|
||||
}
|
||||
|
||||
data, err := netlink.MarshalAttributes(attrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("nat\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *NAT) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_NAT_TYPE:
|
||||
e.Type = NATType(ad.Uint32())
|
||||
case unix.NFTA_NAT_FAMILY:
|
||||
e.Family = ad.Uint32()
|
||||
case unix.NFTA_NAT_REG_ADDR_MIN:
|
||||
e.RegAddrMin = ad.Uint32()
|
||||
case unix.NFTA_NAT_REG_ADDR_MAX:
|
||||
e.RegAddrMax = ad.Uint32()
|
||||
case unix.NFTA_NAT_REG_PROTO_MIN:
|
||||
e.RegProtoMin = ad.Uint32()
|
||||
case unix.NFTA_NAT_REG_PROTO_MAX:
|
||||
e.RegProtoMax = ad.Uint32()
|
||||
case unix.NFTA_NAT_FLAGS:
|
||||
flags := ad.Uint32()
|
||||
e.Persistent = (flags & NF_NAT_RANGE_PERSISTENT) != 0
|
||||
e.Random = (flags & NF_NAT_RANGE_PROTO_RANDOM) != 0
|
||||
e.FullyRandom = (flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) != 0
|
||||
e.Prefix = (flags & NF_NAT_RANGE_PREFIX) != 0
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
38
vendor/github.com/google/nftables/expr/notrack.go
generated
vendored
Normal file
38
vendor/github.com/google/nftables/expr/notrack.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright 2019 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type Notrack struct{}
|
||||
|
||||
func (e *Notrack) marshal(fam byte) ([]byte, error) {
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("notrack\x00")},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Notrack) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ad.Err()
|
||||
}
|
||||
78
vendor/github.com/google/nftables/expr/numgen.go
generated
vendored
Normal file
78
vendor/github.com/google/nftables/expr/numgen.go
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// Numgen defines Numgen expression structure
|
||||
type Numgen struct {
|
||||
Register uint32
|
||||
Modulus uint32
|
||||
Type uint32
|
||||
Offset uint32
|
||||
}
|
||||
|
||||
func (e *Numgen) marshal(fam byte) ([]byte, error) {
|
||||
// Currently only two types are supported, failing if Type is not of two known types
|
||||
switch e.Type {
|
||||
case unix.NFT_NG_INCREMENTAL:
|
||||
case unix.NFT_NG_RANDOM:
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported numgen type %d", e.Type)
|
||||
}
|
||||
|
||||
data, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_NG_DREG, Data: binaryutil.BigEndian.PutUint32(e.Register)},
|
||||
{Type: unix.NFTA_NG_MODULUS, Data: binaryutil.BigEndian.PutUint32(e.Modulus)},
|
||||
{Type: unix.NFTA_NG_TYPE, Data: binaryutil.BigEndian.PutUint32(e.Type)},
|
||||
{Type: unix.NFTA_NG_OFFSET, Data: binaryutil.BigEndian.PutUint32(e.Offset)},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("numgen\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Numgen) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_NG_DREG:
|
||||
e.Register = ad.Uint32()
|
||||
case unix.NFTA_NG_MODULUS:
|
||||
e.Modulus = ad.Uint32()
|
||||
case unix.NFTA_NG_TYPE:
|
||||
e.Type = ad.Uint32()
|
||||
case unix.NFTA_NG_OFFSET:
|
||||
e.Offset = ad.Uint32()
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
60
vendor/github.com/google/nftables/expr/objref.go
generated
vendored
Normal file
60
vendor/github.com/google/nftables/expr/objref.go
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type Objref struct {
|
||||
Type int // TODO: enum
|
||||
Name string
|
||||
}
|
||||
|
||||
func (e *Objref) marshal(fam byte) ([]byte, error) {
|
||||
data, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_OBJREF_IMM_TYPE, Data: binaryutil.BigEndian.PutUint32(uint32(e.Type))},
|
||||
{Type: unix.NFTA_OBJREF_IMM_NAME, Data: []byte(e.Name)}, // NOT \x00-terminated?!
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("objref\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Objref) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_OBJREF_IMM_TYPE:
|
||||
e.Type = int(ad.Uint32())
|
||||
case unix.NFTA_OBJREF_IMM_NAME:
|
||||
e.Name = ad.String()
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
131
vendor/github.com/google/nftables/expr/payload.go
generated
vendored
Normal file
131
vendor/github.com/google/nftables/expr/payload.go
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type PayloadBase uint32
|
||||
type PayloadCsumType uint32
|
||||
type PayloadOperationType uint32
|
||||
|
||||
// Possible PayloadBase values.
|
||||
const (
|
||||
PayloadBaseLLHeader PayloadBase = unix.NFT_PAYLOAD_LL_HEADER
|
||||
PayloadBaseNetworkHeader PayloadBase = unix.NFT_PAYLOAD_NETWORK_HEADER
|
||||
PayloadBaseTransportHeader PayloadBase = unix.NFT_PAYLOAD_TRANSPORT_HEADER
|
||||
)
|
||||
|
||||
// Possible PayloadCsumType values.
|
||||
const (
|
||||
CsumTypeNone PayloadCsumType = unix.NFT_PAYLOAD_CSUM_NONE
|
||||
CsumTypeInet PayloadCsumType = unix.NFT_PAYLOAD_CSUM_INET
|
||||
)
|
||||
|
||||
// Possible PayloadOperationType values.
|
||||
const (
|
||||
PayloadLoad PayloadOperationType = iota
|
||||
PayloadWrite
|
||||
)
|
||||
|
||||
type Payload struct {
|
||||
OperationType PayloadOperationType
|
||||
DestRegister uint32
|
||||
SourceRegister uint32
|
||||
Base PayloadBase
|
||||
Offset uint32
|
||||
Len uint32
|
||||
CsumType PayloadCsumType
|
||||
CsumOffset uint32
|
||||
CsumFlags uint32
|
||||
}
|
||||
|
||||
func (e *Payload) marshal(fam byte) ([]byte, error) {
|
||||
|
||||
var attrs []netlink.Attribute
|
||||
|
||||
if e.OperationType == PayloadWrite {
|
||||
attrs = []netlink.Attribute{
|
||||
{Type: unix.NFTA_PAYLOAD_SREG, Data: binaryutil.BigEndian.PutUint32(e.SourceRegister)},
|
||||
}
|
||||
} else {
|
||||
attrs = []netlink.Attribute{
|
||||
{Type: unix.NFTA_PAYLOAD_DREG, Data: binaryutil.BigEndian.PutUint32(e.DestRegister)},
|
||||
}
|
||||
}
|
||||
|
||||
attrs = append(attrs,
|
||||
netlink.Attribute{Type: unix.NFTA_PAYLOAD_BASE, Data: binaryutil.BigEndian.PutUint32(uint32(e.Base))},
|
||||
netlink.Attribute{Type: unix.NFTA_PAYLOAD_OFFSET, Data: binaryutil.BigEndian.PutUint32(e.Offset)},
|
||||
netlink.Attribute{Type: unix.NFTA_PAYLOAD_LEN, Data: binaryutil.BigEndian.PutUint32(e.Len)},
|
||||
)
|
||||
|
||||
if e.CsumType > 0 {
|
||||
attrs = append(attrs,
|
||||
netlink.Attribute{Type: unix.NFTA_PAYLOAD_CSUM_TYPE, Data: binaryutil.BigEndian.PutUint32(uint32(e.CsumType))},
|
||||
netlink.Attribute{Type: unix.NFTA_PAYLOAD_CSUM_OFFSET, Data: binaryutil.BigEndian.PutUint32(uint32(e.CsumOffset))},
|
||||
)
|
||||
if e.CsumFlags > 0 {
|
||||
attrs = append(attrs,
|
||||
netlink.Attribute{Type: unix.NFTA_PAYLOAD_CSUM_FLAGS, Data: binaryutil.BigEndian.PutUint32(e.CsumFlags)},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data, err := netlink.MarshalAttributes(attrs)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("payload\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Payload) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_PAYLOAD_DREG:
|
||||
e.DestRegister = ad.Uint32()
|
||||
case unix.NFTA_PAYLOAD_SREG:
|
||||
e.SourceRegister = ad.Uint32()
|
||||
e.OperationType = PayloadWrite
|
||||
case unix.NFTA_PAYLOAD_BASE:
|
||||
e.Base = PayloadBase(ad.Uint32())
|
||||
case unix.NFTA_PAYLOAD_OFFSET:
|
||||
e.Offset = ad.Uint32()
|
||||
case unix.NFTA_PAYLOAD_LEN:
|
||||
e.Len = ad.Uint32()
|
||||
case unix.NFTA_PAYLOAD_CSUM_TYPE:
|
||||
e.CsumType = PayloadCsumType(ad.Uint32())
|
||||
case unix.NFTA_PAYLOAD_CSUM_OFFSET:
|
||||
e.CsumOffset = ad.Uint32()
|
||||
case unix.NFTA_PAYLOAD_CSUM_FLAGS:
|
||||
e.CsumFlags = ad.Uint32()
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
81
vendor/github.com/google/nftables/expr/queue.go
generated
vendored
Normal file
81
vendor/github.com/google/nftables/expr/queue.go
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type QueueAttribute uint16
|
||||
|
||||
type QueueFlag uint16
|
||||
|
||||
// Possible QueueAttribute values
|
||||
const (
|
||||
QueueNum QueueAttribute = unix.NFTA_QUEUE_NUM
|
||||
QueueTotal QueueAttribute = unix.NFTA_QUEUE_TOTAL
|
||||
QueueFlags QueueAttribute = unix.NFTA_QUEUE_FLAGS
|
||||
|
||||
QueueFlagBypass QueueFlag = unix.NFT_QUEUE_FLAG_BYPASS
|
||||
QueueFlagFanout QueueFlag = unix.NFT_QUEUE_FLAG_CPU_FANOUT
|
||||
QueueFlagMask QueueFlag = unix.NFT_QUEUE_FLAG_MASK
|
||||
)
|
||||
|
||||
type Queue struct {
|
||||
Num uint16
|
||||
Total uint16
|
||||
Flag QueueFlag
|
||||
}
|
||||
|
||||
func (e *Queue) marshal(fam byte) ([]byte, error) {
|
||||
if e.Total == 0 {
|
||||
e.Total = 1 // The total default value is 1
|
||||
}
|
||||
data, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_QUEUE_NUM, Data: binaryutil.BigEndian.PutUint16(e.Num)},
|
||||
{Type: unix.NFTA_QUEUE_TOTAL, Data: binaryutil.BigEndian.PutUint16(e.Total)},
|
||||
{Type: unix.NFTA_QUEUE_FLAGS, Data: binaryutil.BigEndian.PutUint16(uint16(e.Flag))},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("queue\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Queue) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_QUEUE_NUM:
|
||||
e.Num = ad.Uint16()
|
||||
case unix.NFTA_QUEUE_TOTAL:
|
||||
e.Total = ad.Uint16()
|
||||
case unix.NFTA_QUEUE_FLAGS:
|
||||
e.Flag = QueueFlag(ad.Uint16())
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
76
vendor/github.com/google/nftables/expr/quota.go
generated
vendored
Normal file
76
vendor/github.com/google/nftables/expr/quota.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// Quota defines a threshold against a number of bytes.
|
||||
type Quota struct {
|
||||
Bytes uint64
|
||||
Consumed uint64
|
||||
Over bool
|
||||
}
|
||||
|
||||
func (q *Quota) marshal(fam byte) ([]byte, error) {
|
||||
attrs := []netlink.Attribute{
|
||||
{Type: unix.NFTA_QUOTA_BYTES, Data: binaryutil.BigEndian.PutUint64(q.Bytes)},
|
||||
{Type: unix.NFTA_QUOTA_CONSUMED, Data: binaryutil.BigEndian.PutUint64(q.Consumed)},
|
||||
}
|
||||
|
||||
flags := uint32(0)
|
||||
if q.Over {
|
||||
flags = unix.NFT_QUOTA_F_INV
|
||||
}
|
||||
attrs = append(attrs, netlink.Attribute{
|
||||
Type: unix.NFTA_QUOTA_FLAGS,
|
||||
Data: binaryutil.BigEndian.PutUint32(flags),
|
||||
})
|
||||
|
||||
data, err := netlink.MarshalAttributes(attrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("quota\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (q *Quota) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_QUOTA_BYTES:
|
||||
q.Bytes = ad.Uint64()
|
||||
case unix.NFTA_QUOTA_CONSUMED:
|
||||
q.Consumed = ad.Uint64()
|
||||
case unix.NFTA_QUOTA_FLAGS:
|
||||
q.Over = (ad.Uint32() & unix.NFT_QUOTA_F_INV) == 1
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
124
vendor/github.com/google/nftables/expr/range.go
generated
vendored
Normal file
124
vendor/github.com/google/nftables/expr/range.go
generated
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
// Copyright 2019 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// Range implements range expression
|
||||
type Range struct {
|
||||
Op CmpOp
|
||||
Register uint32
|
||||
FromData []byte
|
||||
ToData []byte
|
||||
}
|
||||
|
||||
func (e *Range) marshal(fam byte) ([]byte, error) {
|
||||
var attrs []netlink.Attribute
|
||||
var err error
|
||||
var rangeFromData, rangeToData []byte
|
||||
|
||||
if e.Register > 0 {
|
||||
attrs = append(attrs, netlink.Attribute{Type: unix.NFTA_RANGE_SREG, Data: binaryutil.BigEndian.PutUint32(e.Register)})
|
||||
}
|
||||
attrs = append(attrs, netlink.Attribute{Type: unix.NFTA_RANGE_OP, Data: binaryutil.BigEndian.PutUint32(uint32(e.Op))})
|
||||
if len(e.FromData) > 0 {
|
||||
rangeFromData, err = nestedAttr(e.FromData, unix.NFTA_RANGE_FROM_DATA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if len(e.ToData) > 0 {
|
||||
rangeToData, err = nestedAttr(e.ToData, unix.NFTA_RANGE_TO_DATA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
data, err := netlink.MarshalAttributes(attrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data = append(data, rangeFromData...)
|
||||
data = append(data, rangeToData...)
|
||||
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("range\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Range) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_RANGE_OP:
|
||||
e.Op = CmpOp(ad.Uint32())
|
||||
case unix.NFTA_RANGE_SREG:
|
||||
e.Register = ad.Uint32()
|
||||
case unix.NFTA_RANGE_FROM_DATA:
|
||||
ad.Do(func(b []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
if ad.Next() && ad.Type() == unix.NFTA_DATA_VALUE {
|
||||
ad.Do(func(b []byte) error {
|
||||
e.FromData = b
|
||||
return nil
|
||||
})
|
||||
}
|
||||
return ad.Err()
|
||||
})
|
||||
case unix.NFTA_RANGE_TO_DATA:
|
||||
ad.Do(func(b []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
if ad.Next() && ad.Type() == unix.NFTA_DATA_VALUE {
|
||||
ad.Do(func(b []byte) error {
|
||||
e.ToData = b
|
||||
return nil
|
||||
})
|
||||
}
|
||||
return ad.Err()
|
||||
})
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
|
||||
func nestedAttr(data []byte, attrType uint16) ([]byte, error) {
|
||||
ae := netlink.NewAttributeEncoder()
|
||||
ae.Do(unix.NLA_F_NESTED|attrType, func() ([]byte, error) {
|
||||
nae := netlink.NewAttributeEncoder()
|
||||
nae.ByteOrder = binary.BigEndian
|
||||
nae.Bytes(unix.NFTA_DATA_VALUE, data)
|
||||
|
||||
return nae.Encode()
|
||||
})
|
||||
return ae.Encode()
|
||||
}
|
||||
71
vendor/github.com/google/nftables/expr/redirect.go
generated
vendored
Normal file
71
vendor/github.com/google/nftables/expr/redirect.go
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type Redir struct {
|
||||
RegisterProtoMin uint32
|
||||
RegisterProtoMax uint32
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
func (e *Redir) marshal(fam byte) ([]byte, error) {
|
||||
var attrs []netlink.Attribute
|
||||
if e.RegisterProtoMin > 0 {
|
||||
attrs = append(attrs, netlink.Attribute{Type: unix.NFTA_REDIR_REG_PROTO_MIN, Data: binaryutil.BigEndian.PutUint32(e.RegisterProtoMin)})
|
||||
}
|
||||
if e.RegisterProtoMax > 0 {
|
||||
attrs = append(attrs, netlink.Attribute{Type: unix.NFTA_REDIR_REG_PROTO_MAX, Data: binaryutil.BigEndian.PutUint32(e.RegisterProtoMax)})
|
||||
}
|
||||
if e.Flags > 0 {
|
||||
attrs = append(attrs, netlink.Attribute{Type: unix.NFTA_REDIR_FLAGS, Data: binaryutil.BigEndian.PutUint32(e.Flags)})
|
||||
}
|
||||
|
||||
data, err := netlink.MarshalAttributes(attrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("redir\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Redir) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_REDIR_REG_PROTO_MIN:
|
||||
e.RegisterProtoMin = ad.Uint32()
|
||||
case unix.NFTA_REDIR_REG_PROTO_MAX:
|
||||
e.RegisterProtoMax = ad.Uint32()
|
||||
case unix.NFTA_REDIR_FLAGS:
|
||||
e.Flags = ad.Uint32()
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
59
vendor/github.com/google/nftables/expr/reject.go
generated
vendored
Normal file
59
vendor/github.com/google/nftables/expr/reject.go
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type Reject struct {
|
||||
Type uint32
|
||||
Code uint8
|
||||
}
|
||||
|
||||
func (e *Reject) marshal(fam byte) ([]byte, error) {
|
||||
data, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_REJECT_TYPE, Data: binaryutil.BigEndian.PutUint32(e.Type)},
|
||||
{Type: unix.NFTA_REJECT_ICMP_CODE, Data: []byte{e.Code}},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("reject\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Reject) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_REJECT_TYPE:
|
||||
e.Type = ad.Uint32()
|
||||
case unix.NFTA_REJECT_ICMP_CODE:
|
||||
e.Code = ad.Uint8()
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
55
vendor/github.com/google/nftables/expr/rt.go
generated
vendored
Normal file
55
vendor/github.com/google/nftables/expr/rt.go
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type RtKey uint32
|
||||
|
||||
const (
|
||||
RtClassid RtKey = unix.NFT_RT_CLASSID
|
||||
RtNexthop4 RtKey = unix.NFT_RT_NEXTHOP4
|
||||
RtNexthop6 RtKey = unix.NFT_RT_NEXTHOP6
|
||||
RtTCPMSS RtKey = unix.NFT_RT_TCPMSS
|
||||
)
|
||||
|
||||
type Rt struct {
|
||||
Register uint32
|
||||
Key RtKey
|
||||
}
|
||||
|
||||
func (e *Rt) marshal(fam byte) ([]byte, error) {
|
||||
data, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_RT_KEY, Data: binaryutil.BigEndian.PutUint32(uint32(e.Key))},
|
||||
{Type: unix.NFTA_RT_DREG, Data: binaryutil.BigEndian.PutUint32(e.Register)},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("rt\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Rt) unmarshal(fam byte, data []byte) error {
|
||||
return fmt.Errorf("not yet implemented")
|
||||
}
|
||||
89
vendor/github.com/google/nftables/expr/socket.go
generated
vendored
Normal file
89
vendor/github.com/google/nftables/expr/socket.go
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
// Copyright 2023 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
)
|
||||
|
||||
type Socket struct {
|
||||
Key SocketKey
|
||||
Level uint32
|
||||
Register uint32
|
||||
}
|
||||
|
||||
type SocketKey uint32
|
||||
|
||||
const (
|
||||
// TODO, Once the constants below are available in golang.org/x/sys/unix, switch to use those.
|
||||
NFTA_SOCKET_KEY = 1
|
||||
NFTA_SOCKET_DREG = 2
|
||||
NFTA_SOCKET_LEVEL = 3
|
||||
|
||||
NFT_SOCKET_TRANSPARENT = 0
|
||||
NFT_SOCKET_MARK = 1
|
||||
NFT_SOCKET_WILDCARD = 2
|
||||
NFT_SOCKET_CGROUPV2 = 3
|
||||
|
||||
SocketKeyTransparent SocketKey = NFT_SOCKET_TRANSPARENT
|
||||
SocketKeyMark SocketKey = NFT_SOCKET_MARK
|
||||
SocketKeyWildcard SocketKey = NFT_SOCKET_WILDCARD
|
||||
SocketKeyCgroupv2 SocketKey = NFT_SOCKET_CGROUPV2
|
||||
)
|
||||
|
||||
func (e *Socket) marshal(fam byte) ([]byte, error) {
|
||||
// NOTE: Socket.Level is only used when Socket.Key == SocketKeyCgroupv2. But `nft` always encoding it. Check link below:
|
||||
// http://git.netfilter.org/nftables/tree/src/netlink_linearize.c?id=0583bac241ea18c9d7f61cb20ca04faa1e043b78#n319
|
||||
exprData, err := netlink.MarshalAttributes(
|
||||
[]netlink.Attribute{
|
||||
{Type: NFTA_SOCKET_DREG, Data: binaryutil.BigEndian.PutUint32(e.Register)},
|
||||
{Type: NFTA_SOCKET_KEY, Data: binaryutil.BigEndian.PutUint32(uint32(e.Key))},
|
||||
{Type: NFTA_SOCKET_LEVEL, Data: binaryutil.BigEndian.PutUint32(uint32(e.Level))},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("socket\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: exprData},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Socket) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case NFTA_SOCKET_DREG:
|
||||
e.Register = ad.Uint32()
|
||||
case NFTA_SOCKET_KEY:
|
||||
e.Key = SocketKey(ad.Uint32())
|
||||
case NFTA_SOCKET_LEVEL:
|
||||
e.Level = ad.Uint32()
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
79
vendor/github.com/google/nftables/expr/target.go
generated
vendored
Normal file
79
vendor/github.com/google/nftables/expr/target.go
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
package expr
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/google/nftables/xt"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// See https://git.netfilter.org/libnftnl/tree/src/expr/target.c?id=09456c720e9c00eecc08e41ac6b7c291b3821ee5#n28
|
||||
const XTablesExtensionNameMaxLen = 29
|
||||
|
||||
// See https://git.netfilter.org/libnftnl/tree/src/expr/target.c?id=09456c720e9c00eecc08e41ac6b7c291b3821ee5#n30
|
||||
type Target struct {
|
||||
Name string
|
||||
Rev uint32
|
||||
Info xt.InfoAny
|
||||
}
|
||||
|
||||
func (e *Target) marshal(fam byte) ([]byte, error) {
|
||||
// Per https://git.netfilter.org/libnftnl/tree/src/expr/target.c?id=09456c720e9c00eecc08e41ac6b7c291b3821ee5#n38
|
||||
name := e.Name
|
||||
// limit the extension name as (some) user-space tools do and leave room for
|
||||
// trailing \x00
|
||||
if len(name) >= /* sic! */ XTablesExtensionNameMaxLen {
|
||||
name = name[:XTablesExtensionNameMaxLen-1] // leave room for trailing \x00.
|
||||
}
|
||||
// Marshalling assumes that the correct Info type for the particular table
|
||||
// family and Match revision has been set.
|
||||
info, err := xt.Marshal(xt.TableFamily(fam), e.Rev, e.Info)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
attrs := []netlink.Attribute{
|
||||
{Type: unix.NFTA_TARGET_NAME, Data: []byte(name + "\x00")},
|
||||
{Type: unix.NFTA_TARGET_REV, Data: binaryutil.BigEndian.PutUint32(e.Rev)},
|
||||
{Type: unix.NFTA_TARGET_INFO, Data: info},
|
||||
}
|
||||
|
||||
data, err := netlink.MarshalAttributes(attrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("target\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Target) unmarshal(fam byte, data []byte) error {
|
||||
// Per https://git.netfilter.org/libnftnl/tree/src/expr/target.c?id=09456c720e9c00eecc08e41ac6b7c291b3821ee5#n65
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var info []byte
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_TARGET_NAME:
|
||||
// We are forgiving here, accepting any length and even missing terminating \x00.
|
||||
e.Name = string(bytes.TrimRight(ad.Bytes(), "\x00"))
|
||||
case unix.NFTA_TARGET_REV:
|
||||
e.Rev = ad.Uint32()
|
||||
case unix.NFTA_TARGET_INFO:
|
||||
info = ad.Bytes()
|
||||
}
|
||||
}
|
||||
if err = ad.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
e.Info, err = xt.Unmarshal(e.Name, xt.TableFamily(fam), e.Rev, info)
|
||||
return err
|
||||
}
|
||||
82
vendor/github.com/google/nftables/expr/tproxy.go
generated
vendored
Normal file
82
vendor/github.com/google/nftables/expr/tproxy.go
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
// NFTA_TPROXY_FAMILY defines attribute for a table family
|
||||
NFTA_TPROXY_FAMILY = 0x01
|
||||
// NFTA_TPROXY_REG_ADDR defines attribute for a register carrying redirection address value
|
||||
NFTA_TPROXY_REG_ADDR = 0x02
|
||||
// NFTA_TPROXY_REG_PORT defines attribute for a register carrying redirection port value
|
||||
NFTA_TPROXY_REG_PORT = 0x03
|
||||
)
|
||||
|
||||
// TProxy defines struct with parameters for the transparent proxy
|
||||
type TProxy struct {
|
||||
Family byte
|
||||
TableFamily byte
|
||||
RegAddr uint32
|
||||
RegPort uint32
|
||||
}
|
||||
|
||||
func (e *TProxy) marshal(fam byte) ([]byte, error) {
|
||||
attrs := []netlink.Attribute{
|
||||
{Type: NFTA_TPROXY_FAMILY, Data: binaryutil.BigEndian.PutUint32(uint32(e.Family))},
|
||||
{Type: NFTA_TPROXY_REG_PORT, Data: binaryutil.BigEndian.PutUint32(e.RegPort)},
|
||||
}
|
||||
|
||||
if e.RegAddr != 0 {
|
||||
attrs = append(attrs, netlink.Attribute{
|
||||
Type: NFTA_TPROXY_REG_ADDR,
|
||||
Data: binaryutil.BigEndian.PutUint32(e.RegAddr),
|
||||
})
|
||||
}
|
||||
|
||||
data, err := netlink.MarshalAttributes(attrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("tproxy\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *TProxy) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case NFTA_TPROXY_FAMILY:
|
||||
e.Family = ad.Uint8()
|
||||
case NFTA_TPROXY_REG_PORT:
|
||||
e.RegPort = ad.Uint32()
|
||||
case NFTA_TPROXY_REG_ADDR:
|
||||
e.RegAddr = ad.Uint32()
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
128
vendor/github.com/google/nftables/expr/verdict.go
generated
vendored
Normal file
128
vendor/github.com/google/nftables/expr/verdict.go
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expr
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// This code assembles the verdict structure, as expected by the
|
||||
// nftables netlink API.
|
||||
// For further information, consult:
|
||||
// - netfilter.h (Linux kernel)
|
||||
// - net/netfilter/nf_tables_api.c (Linux kernel)
|
||||
// - src/expr/data_reg.c (linbnftnl)
|
||||
|
||||
type Verdict struct {
|
||||
Kind VerdictKind
|
||||
Chain string
|
||||
}
|
||||
|
||||
type VerdictKind int64
|
||||
|
||||
// Verdicts, as per netfilter.h and netfilter/nf_tables.h.
|
||||
const (
|
||||
VerdictReturn VerdictKind = iota - 5
|
||||
VerdictGoto
|
||||
VerdictJump
|
||||
VerdictBreak
|
||||
VerdictContinue
|
||||
VerdictDrop
|
||||
VerdictAccept
|
||||
VerdictStolen
|
||||
VerdictQueue
|
||||
VerdictRepeat
|
||||
VerdictStop
|
||||
)
|
||||
|
||||
func (e *Verdict) marshal(fam byte) ([]byte, error) {
|
||||
// A verdict is a tree of netlink attributes structured as follows:
|
||||
// NFTA_LIST_ELEM | NLA_F_NESTED {
|
||||
// NFTA_EXPR_NAME { "immediate\x00" }
|
||||
// NFTA_EXPR_DATA | NLA_F_NESTED {
|
||||
// NFTA_IMMEDIATE_DREG { NFT_REG_VERDICT }
|
||||
// NFTA_IMMEDIATE_DATA | NLA_F_NESTED {
|
||||
// the verdict code
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
attrs := []netlink.Attribute{
|
||||
{Type: unix.NFTA_VERDICT_CODE, Data: binaryutil.BigEndian.PutUint32(uint32(e.Kind))},
|
||||
}
|
||||
if e.Chain != "" {
|
||||
attrs = append(attrs, netlink.Attribute{Type: unix.NFTA_VERDICT_CHAIN, Data: []byte(e.Chain + "\x00")})
|
||||
}
|
||||
codeData, err := netlink.MarshalAttributes(attrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
immData, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_DATA_VERDICT, Data: codeData},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_IMMEDIATE_DREG, Data: binaryutil.BigEndian.PutUint32(unix.NFT_REG_VERDICT)},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_IMMEDIATE_DATA, Data: immData},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_EXPR_NAME, Data: []byte("immediate\x00")},
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: data},
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Verdict) unmarshal(fam byte, data []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_IMMEDIATE_DATA:
|
||||
nestedAD, err := netlink.NewAttributeDecoder(ad.Bytes())
|
||||
if err != nil {
|
||||
return fmt.Errorf("nested NewAttributeDecoder() failed: %v", err)
|
||||
}
|
||||
for nestedAD.Next() {
|
||||
switch nestedAD.Type() {
|
||||
case unix.NFTA_DATA_VERDICT:
|
||||
e.Kind = VerdictKind(int32(binaryutil.BigEndian.Uint32(nestedAD.Bytes()[4:8])))
|
||||
if len(nestedAD.Bytes()) > 12 {
|
||||
e.Chain = string(bytes.Trim(nestedAD.Bytes()[12:], "\x00"))
|
||||
}
|
||||
}
|
||||
}
|
||||
if nestedAD.Err() != nil {
|
||||
return fmt.Errorf("decoding immediate: %v", nestedAD.Err())
|
||||
}
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
306
vendor/github.com/google/nftables/flowtable.go
generated
vendored
Normal file
306
vendor/github.com/google/nftables/flowtable.go
generated
vendored
Normal file
@@ -0,0 +1,306 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nftables
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
// not in ztypes_linux.go, added here
|
||||
// https://cs.opensource.google/go/x/sys/+/c6bc011c:unix/ztypes_linux.go;l=1870-1892
|
||||
NFT_MSG_NEWFLOWTABLE = 0x16
|
||||
NFT_MSG_GETFLOWTABLE = 0x17
|
||||
NFT_MSG_DELFLOWTABLE = 0x18
|
||||
)
|
||||
|
||||
const (
|
||||
// not in ztypes_linux.go, added here
|
||||
// https://git.netfilter.org/libnftnl/tree/include/linux/netfilter/nf_tables.h?id=84d12cfacf8ddd857a09435f3d982ab6250d250c#n1634
|
||||
_ = iota
|
||||
NFTA_FLOWTABLE_TABLE
|
||||
NFTA_FLOWTABLE_NAME
|
||||
NFTA_FLOWTABLE_HOOK
|
||||
NFTA_FLOWTABLE_USE
|
||||
NFTA_FLOWTABLE_HANDLE
|
||||
NFTA_FLOWTABLE_PAD
|
||||
NFTA_FLOWTABLE_FLAGS
|
||||
)
|
||||
|
||||
const (
|
||||
// not in ztypes_linux.go, added here
|
||||
// https://git.netfilter.org/libnftnl/tree/include/linux/netfilter/nf_tables.h?id=84d12cfacf8ddd857a09435f3d982ab6250d250c#n1657
|
||||
_ = iota
|
||||
NFTA_FLOWTABLE_HOOK_NUM
|
||||
NFTA_FLOWTABLE_PRIORITY
|
||||
NFTA_FLOWTABLE_DEVS
|
||||
)
|
||||
|
||||
const (
|
||||
// not in ztypes_linux.go, added here, used for flowtable device name specification
|
||||
// https://git.netfilter.org/libnftnl/tree/include/linux/netfilter/nf_tables.h?id=84d12cfacf8ddd857a09435f3d982ab6250d250c#n1709
|
||||
NFTA_DEVICE_NAME = 1
|
||||
)
|
||||
|
||||
type FlowtableFlags uint32
|
||||
|
||||
const (
|
||||
_ FlowtableFlags = iota
|
||||
FlowtableFlagsHWOffload
|
||||
FlowtableFlagsCounter
|
||||
FlowtableFlagsMask = (FlowtableFlagsHWOffload | FlowtableFlagsCounter)
|
||||
)
|
||||
|
||||
type FlowtableHook uint32
|
||||
|
||||
func FlowtableHookRef(h FlowtableHook) *FlowtableHook {
|
||||
return &h
|
||||
}
|
||||
|
||||
var (
|
||||
// Only ingress is supported
|
||||
// https://github.com/torvalds/linux/blob/b72018ab8236c3ae427068adeb94bdd3f20454ec/net/netfilter/nf_tables_api.c#L7378-L7379
|
||||
FlowtableHookIngress *FlowtableHook = FlowtableHookRef(unix.NF_NETDEV_INGRESS)
|
||||
)
|
||||
|
||||
type FlowtablePriority int32
|
||||
|
||||
func FlowtablePriorityRef(p FlowtablePriority) *FlowtablePriority {
|
||||
return &p
|
||||
}
|
||||
|
||||
var (
|
||||
// As per man page:
|
||||
// The priority can be a signed integer or filter which stands for 0. Addition and subtraction can be used to set relative priority, e.g. filter + 5 equals to 5.
|
||||
// https://git.netfilter.org/nftables/tree/doc/nft.txt?id=8c600a843b7c0c1cc275ecc0603bd1fc57773e98#n712
|
||||
FlowtablePriorityFilter *FlowtablePriority = FlowtablePriorityRef(0)
|
||||
)
|
||||
|
||||
type Flowtable struct {
|
||||
Table *Table
|
||||
Name string
|
||||
Hooknum *FlowtableHook
|
||||
Priority *FlowtablePriority
|
||||
Devices []string
|
||||
Use uint32
|
||||
// Bitmask flags, can be HW_OFFLOAD or COUNTER
|
||||
// https://git.netfilter.org/libnftnl/tree/include/linux/netfilter/nf_tables.h?id=84d12cfacf8ddd857a09435f3d982ab6250d250c#n1621
|
||||
Flags FlowtableFlags
|
||||
Handle uint64
|
||||
}
|
||||
|
||||
func (cc *Conn) AddFlowtable(f *Flowtable) *Flowtable {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
|
||||
data := cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: NFTA_FLOWTABLE_TABLE, Data: []byte(f.Table.Name)},
|
||||
{Type: NFTA_FLOWTABLE_NAME, Data: []byte(f.Name)},
|
||||
{Type: NFTA_FLOWTABLE_FLAGS, Data: binaryutil.BigEndian.PutUint32(uint32(f.Flags))},
|
||||
})
|
||||
|
||||
if f.Hooknum == nil {
|
||||
f.Hooknum = FlowtableHookIngress
|
||||
}
|
||||
|
||||
if f.Priority == nil {
|
||||
f.Priority = FlowtablePriorityFilter
|
||||
}
|
||||
|
||||
hookAttr := []netlink.Attribute{
|
||||
{Type: NFTA_FLOWTABLE_HOOK_NUM, Data: binaryutil.BigEndian.PutUint32(uint32(*f.Hooknum))},
|
||||
{Type: NFTA_FLOWTABLE_PRIORITY, Data: binaryutil.BigEndian.PutUint32(uint32(*f.Priority))},
|
||||
}
|
||||
if len(f.Devices) > 0 {
|
||||
devs := make([]netlink.Attribute, len(f.Devices))
|
||||
for i, d := range f.Devices {
|
||||
devs[i] = netlink.Attribute{Type: NFTA_DEVICE_NAME, Data: []byte(d)}
|
||||
}
|
||||
hookAttr = append(hookAttr, netlink.Attribute{
|
||||
Type: unix.NLA_F_NESTED | NFTA_FLOWTABLE_DEVS,
|
||||
Data: cc.marshalAttr(devs),
|
||||
})
|
||||
}
|
||||
data = append(data, cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NLA_F_NESTED | NFTA_FLOWTABLE_HOOK, Data: cc.marshalAttr(hookAttr)},
|
||||
})...)
|
||||
|
||||
cc.messages = append(cc.messages, netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWFLOWTABLE),
|
||||
Flags: netlink.Request | netlink.Acknowledge | netlink.Create,
|
||||
},
|
||||
Data: append(extraHeader(uint8(f.Table.Family), 0), data...),
|
||||
})
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
func (cc *Conn) DelFlowtable(f *Flowtable) {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
|
||||
data := cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: NFTA_FLOWTABLE_TABLE, Data: []byte(f.Table.Name)},
|
||||
{Type: NFTA_FLOWTABLE_NAME, Data: []byte(f.Name)},
|
||||
})
|
||||
|
||||
cc.messages = append(cc.messages, netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_DELFLOWTABLE),
|
||||
Flags: netlink.Request | netlink.Acknowledge,
|
||||
},
|
||||
Data: append(extraHeader(uint8(f.Table.Family), 0), data...),
|
||||
})
|
||||
}
|
||||
|
||||
func (cc *Conn) ListFlowtables(t *Table) ([]*Flowtable, error) {
|
||||
reply, err := cc.getFlowtables(t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var fts []*Flowtable
|
||||
for _, msg := range reply {
|
||||
f, err := ftsFromMsg(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f.Table = t
|
||||
fts = append(fts, f)
|
||||
}
|
||||
|
||||
return fts, nil
|
||||
}
|
||||
|
||||
func (cc *Conn) getFlowtables(t *Table) ([]netlink.Message, error) {
|
||||
conn, closer, err := cc.netlinkConn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = closer() }()
|
||||
|
||||
attrs := []netlink.Attribute{
|
||||
{Type: NFTA_FLOWTABLE_TABLE, Data: []byte(t.Name + "\x00")},
|
||||
}
|
||||
data, err := netlink.MarshalAttributes(attrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
message := netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_GETFLOWTABLE),
|
||||
Flags: netlink.Request | netlink.Acknowledge | netlink.Dump,
|
||||
},
|
||||
Data: append(extraHeader(uint8(t.Family), 0), data...),
|
||||
}
|
||||
|
||||
if _, err := conn.SendMessages([]netlink.Message{message}); err != nil {
|
||||
return nil, fmt.Errorf("SendMessages: %v", err)
|
||||
}
|
||||
|
||||
reply, err := receiveAckAware(conn, message.Header.Flags)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Receive: %v", err)
|
||||
}
|
||||
|
||||
return reply, nil
|
||||
}
|
||||
|
||||
func ftsFromMsg(msg netlink.Message) (*Flowtable, error) {
|
||||
flowHeaderType := netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWFLOWTABLE)
|
||||
if got, want := msg.Header.Type, flowHeaderType; got != want {
|
||||
return nil, fmt.Errorf("unexpected header type: got %v, want %v", got, want)
|
||||
}
|
||||
ad, err := netlink.NewAttributeDecoder(msg.Data[4:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
|
||||
var ft Flowtable
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case NFTA_FLOWTABLE_NAME:
|
||||
ft.Name = ad.String()
|
||||
case NFTA_FLOWTABLE_USE:
|
||||
ft.Use = ad.Uint32()
|
||||
case NFTA_FLOWTABLE_HANDLE:
|
||||
ft.Handle = ad.Uint64()
|
||||
case NFTA_FLOWTABLE_FLAGS:
|
||||
ft.Flags = FlowtableFlags(ad.Uint32())
|
||||
case NFTA_FLOWTABLE_HOOK:
|
||||
ad.Do(func(b []byte) error {
|
||||
ft.Hooknum, ft.Priority, ft.Devices, err = ftsHookFromMsg(b)
|
||||
return err
|
||||
})
|
||||
}
|
||||
}
|
||||
return &ft, nil
|
||||
}
|
||||
|
||||
func ftsHookFromMsg(b []byte) (*FlowtableHook, *FlowtablePriority, []string, error) {
|
||||
ad, err := netlink.NewAttributeDecoder(b)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
|
||||
var hooknum FlowtableHook
|
||||
var prio FlowtablePriority
|
||||
var devices []string
|
||||
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case NFTA_FLOWTABLE_HOOK_NUM:
|
||||
hooknum = FlowtableHook(ad.Uint32())
|
||||
case NFTA_FLOWTABLE_PRIORITY:
|
||||
prio = FlowtablePriority(ad.Uint32())
|
||||
case NFTA_FLOWTABLE_DEVS:
|
||||
ad.Do(func(b []byte) error {
|
||||
devices, err = devsFromMsg(b)
|
||||
return err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return &hooknum, &prio, devices, nil
|
||||
}
|
||||
|
||||
func devsFromMsg(b []byte) ([]string, error) {
|
||||
ad, err := netlink.NewAttributeDecoder(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
|
||||
devs := make([]string, 0)
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case NFTA_DEVICE_NAME:
|
||||
devs = append(devs, ad.String())
|
||||
}
|
||||
}
|
||||
|
||||
return devs, nil
|
||||
}
|
||||
10
vendor/github.com/google/nftables/internal/parseexprfunc/parseexprfunc.go
generated
vendored
Normal file
10
vendor/github.com/google/nftables/internal/parseexprfunc/parseexprfunc.go
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
package parseexprfunc
|
||||
|
||||
import (
|
||||
"github.com/mdlayher/netlink"
|
||||
)
|
||||
|
||||
var (
|
||||
ParseExprBytesFunc func(fam byte, ad *netlink.AttributeDecoder, b []byte) ([]interface{}, error)
|
||||
ParseExprMsgFunc func(fam byte, b []byte) ([]interface{}, error)
|
||||
)
|
||||
319
vendor/github.com/google/nftables/monitor.go
generated
vendored
Normal file
319
vendor/github.com/google/nftables/monitor.go
generated
vendored
Normal file
@@ -0,0 +1,319 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nftables
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type MonitorAction uint8
|
||||
|
||||
// Possible MonitorAction values.
|
||||
const (
|
||||
MonitorActionNew MonitorAction = 1 << iota
|
||||
MonitorActionDel
|
||||
MonitorActionMask MonitorAction = (1 << iota) - 1
|
||||
MonitorActionAny MonitorAction = MonitorActionMask
|
||||
)
|
||||
|
||||
type MonitorObject uint32
|
||||
|
||||
// Possible MonitorObject values.
|
||||
const (
|
||||
MonitorObjectTables MonitorObject = 1 << iota
|
||||
MonitorObjectChains
|
||||
MonitorObjectSets
|
||||
MonitorObjectRules
|
||||
MonitorObjectElements
|
||||
MonitorObjectRuleset
|
||||
MonitorObjectMask MonitorObject = (1 << iota) - 1
|
||||
MonitorObjectAny MonitorObject = MonitorObjectMask
|
||||
)
|
||||
|
||||
var (
|
||||
monitorFlags = map[MonitorAction]map[MonitorObject]uint32{
|
||||
MonitorActionAny: {
|
||||
MonitorObjectAny: 0xffffffff,
|
||||
MonitorObjectTables: 1<<unix.NFT_MSG_NEWTABLE | 1<<unix.NFT_MSG_DELTABLE,
|
||||
MonitorObjectChains: 1<<unix.NFT_MSG_NEWCHAIN | 1<<unix.NFT_MSG_DELCHAIN,
|
||||
MonitorObjectRules: 1<<unix.NFT_MSG_NEWRULE | 1<<unix.NFT_MSG_DELRULE,
|
||||
MonitorObjectSets: 1<<unix.NFT_MSG_NEWSET | 1<<unix.NFT_MSG_DELSET,
|
||||
MonitorObjectElements: 1<<unix.NFT_MSG_NEWSETELEM | 1<<unix.NFT_MSG_DELSETELEM,
|
||||
MonitorObjectRuleset: 1<<unix.NFT_MSG_NEWTABLE | 1<<unix.NFT_MSG_DELTABLE |
|
||||
1<<unix.NFT_MSG_NEWCHAIN | 1<<unix.NFT_MSG_DELCHAIN |
|
||||
1<<unix.NFT_MSG_NEWRULE | 1<<unix.NFT_MSG_DELRULE |
|
||||
1<<unix.NFT_MSG_NEWSET | 1<<unix.NFT_MSG_DELSET |
|
||||
1<<unix.NFT_MSG_NEWSETELEM | 1<<unix.NFT_MSG_DELSETELEM |
|
||||
1<<unix.NFT_MSG_NEWOBJ | 1<<unix.NFT_MSG_DELOBJ,
|
||||
},
|
||||
MonitorActionNew: {
|
||||
MonitorObjectAny: 1<<unix.NFT_MSG_NEWTABLE |
|
||||
1<<unix.NFT_MSG_NEWCHAIN |
|
||||
1<<unix.NFT_MSG_NEWRULE |
|
||||
1<<unix.NFT_MSG_NEWSET |
|
||||
1<<unix.NFT_MSG_NEWSETELEM,
|
||||
MonitorObjectTables: 1 << unix.NFT_MSG_NEWTABLE,
|
||||
MonitorObjectChains: 1 << unix.NFT_MSG_NEWCHAIN,
|
||||
MonitorObjectRules: 1 << unix.NFT_MSG_NEWRULE,
|
||||
MonitorObjectSets: 1 << unix.NFT_MSG_NEWSET,
|
||||
MonitorObjectRuleset: 1<<unix.NFT_MSG_NEWTABLE |
|
||||
1<<unix.NFT_MSG_NEWCHAIN |
|
||||
1<<unix.NFT_MSG_NEWRULE |
|
||||
1<<unix.NFT_MSG_NEWSET |
|
||||
1<<unix.NFT_MSG_NEWSETELEM |
|
||||
1<<unix.NFT_MSG_NEWOBJ,
|
||||
},
|
||||
MonitorActionDel: {
|
||||
MonitorObjectAny: 1<<unix.NFT_MSG_DELTABLE |
|
||||
1<<unix.NFT_MSG_DELCHAIN |
|
||||
1<<unix.NFT_MSG_DELRULE |
|
||||
1<<unix.NFT_MSG_DELSET |
|
||||
1<<unix.NFT_MSG_DELSETELEM |
|
||||
1<<unix.NFT_MSG_DELOBJ,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
type MonitorEventType int
|
||||
|
||||
const (
|
||||
MonitorEventTypeNewTable MonitorEventType = unix.NFT_MSG_NEWTABLE
|
||||
MonitorEventTypeDelTable MonitorEventType = unix.NFT_MSG_DELTABLE
|
||||
MonitorEventTypeNewChain MonitorEventType = unix.NFT_MSG_NEWCHAIN
|
||||
MonitorEventTypeDelChain MonitorEventType = unix.NFT_MSG_DELCHAIN
|
||||
MonitorEventTypeNewRule MonitorEventType = unix.NFT_MSG_NEWRULE
|
||||
MonitorEventTypeDelRule MonitorEventType = unix.NFT_MSG_DELRULE
|
||||
MonitorEventTypeNewSet MonitorEventType = unix.NFT_MSG_NEWSET
|
||||
MonitorEventTypeDelSet MonitorEventType = unix.NFT_MSG_DELSET
|
||||
MonitorEventTypeNewSetElem MonitorEventType = unix.NFT_MSG_NEWSETELEM
|
||||
MonitorEventTypeDelSetElem MonitorEventType = unix.NFT_MSG_DELSETELEM
|
||||
MonitorEventTypeNewObj MonitorEventType = unix.NFT_MSG_NEWOBJ
|
||||
MonitorEventTypeDelObj MonitorEventType = unix.NFT_MSG_DELOBJ
|
||||
MonitorEventTypeOOB MonitorEventType = math.MaxInt // out of band event
|
||||
)
|
||||
|
||||
// A MonitorEvent represents a single change received via a [Monitor].
|
||||
//
|
||||
// Depending on the Type, the Data field can be type-asserted to the specific
|
||||
// data type for this event, e.g. when Type is
|
||||
// nftables.MonitorEventTypeNewTable, you can access the corresponding table
|
||||
// details via Data.(*nftables.Table).
|
||||
type MonitorEvent struct {
|
||||
Type MonitorEventType
|
||||
Data any
|
||||
Error error
|
||||
}
|
||||
|
||||
const (
|
||||
monitorOK = iota
|
||||
monitorClosed
|
||||
)
|
||||
|
||||
// A Monitor is an event-based nftables monitor that will receive one event per
|
||||
// new (or deleted) table, chain, rule, set, etc., depending on the monitor
|
||||
// configuration.
|
||||
type Monitor struct {
|
||||
action MonitorAction
|
||||
object MonitorObject
|
||||
monitorFlags uint32
|
||||
|
||||
conn *netlink.Conn
|
||||
closer netlinkCloser
|
||||
|
||||
// mu covers eventCh and status
|
||||
mu sync.Mutex
|
||||
eventCh chan *MonitorEvent
|
||||
status int
|
||||
}
|
||||
|
||||
type MonitorOption func(*Monitor)
|
||||
|
||||
func WithMonitorEventBuffer(size int) MonitorOption {
|
||||
return func(monitor *Monitor) {
|
||||
monitor.eventCh = make(chan *MonitorEvent, size)
|
||||
}
|
||||
}
|
||||
|
||||
// WithMonitorAction to set monitor actions like new, del or any.
|
||||
func WithMonitorAction(action MonitorAction) MonitorOption {
|
||||
return func(monitor *Monitor) {
|
||||
monitor.action = action
|
||||
}
|
||||
}
|
||||
|
||||
// WithMonitorObject to set monitor objects.
|
||||
func WithMonitorObject(object MonitorObject) MonitorOption {
|
||||
return func(monitor *Monitor) {
|
||||
monitor.object = object
|
||||
}
|
||||
}
|
||||
|
||||
// NewMonitor returns a Monitor with options to be started.
|
||||
//
|
||||
// Note that NewMonitor only prepares a Monitor. To install the monitor, call
|
||||
// [Conn.AddMonitor].
|
||||
func NewMonitor(opts ...MonitorOption) *Monitor {
|
||||
monitor := &Monitor{
|
||||
status: monitorOK,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(monitor)
|
||||
}
|
||||
if monitor.eventCh == nil {
|
||||
monitor.eventCh = make(chan *MonitorEvent)
|
||||
}
|
||||
objects, ok := monitorFlags[monitor.action]
|
||||
if !ok {
|
||||
objects = monitorFlags[MonitorActionAny]
|
||||
}
|
||||
flags, ok := objects[monitor.object]
|
||||
if !ok {
|
||||
flags = objects[MonitorObjectAny]
|
||||
}
|
||||
monitor.monitorFlags = flags
|
||||
return monitor
|
||||
}
|
||||
|
||||
func (monitor *Monitor) monitor() {
|
||||
for {
|
||||
msgs, err := monitor.conn.Receive()
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "use of closed file") {
|
||||
// ignore the error that be closed
|
||||
break
|
||||
} else {
|
||||
// any other errors will be send to user, and then to close eventCh
|
||||
event := &MonitorEvent{
|
||||
Type: MonitorEventTypeOOB,
|
||||
Data: nil,
|
||||
Error: err,
|
||||
}
|
||||
monitor.eventCh <- event
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, msg := range msgs {
|
||||
if msg.Header.Type&0xff00>>8 != netlink.HeaderType(unix.NFNL_SUBSYS_NFTABLES) {
|
||||
continue
|
||||
}
|
||||
msgType := msg.Header.Type & 0x00ff
|
||||
if monitor.monitorFlags&1<<msgType == 0 {
|
||||
continue
|
||||
}
|
||||
switch msgType {
|
||||
case unix.NFT_MSG_NEWTABLE, unix.NFT_MSG_DELTABLE:
|
||||
table, err := tableFromMsg(msg)
|
||||
event := &MonitorEvent{
|
||||
Type: MonitorEventType(msgType),
|
||||
Data: table,
|
||||
Error: err,
|
||||
}
|
||||
monitor.eventCh <- event
|
||||
case unix.NFT_MSG_NEWCHAIN, unix.NFT_MSG_DELCHAIN:
|
||||
chain, err := chainFromMsg(msg)
|
||||
event := &MonitorEvent{
|
||||
Type: MonitorEventType(msgType),
|
||||
Data: chain,
|
||||
Error: err,
|
||||
}
|
||||
monitor.eventCh <- event
|
||||
case unix.NFT_MSG_NEWRULE, unix.NFT_MSG_DELRULE:
|
||||
rule, err := parseRuleFromMsg(msg)
|
||||
event := &MonitorEvent{
|
||||
Type: MonitorEventType(msgType),
|
||||
Data: rule,
|
||||
Error: err,
|
||||
}
|
||||
monitor.eventCh <- event
|
||||
case unix.NFT_MSG_NEWSET, unix.NFT_MSG_DELSET:
|
||||
set, err := setsFromMsg(msg)
|
||||
event := &MonitorEvent{
|
||||
Type: MonitorEventType(msgType),
|
||||
Data: set,
|
||||
Error: err,
|
||||
}
|
||||
monitor.eventCh <- event
|
||||
case unix.NFT_MSG_NEWSETELEM, unix.NFT_MSG_DELSETELEM:
|
||||
elems, err := elementsFromMsg(uint8(TableFamilyUnspecified), msg)
|
||||
event := &MonitorEvent{
|
||||
Type: MonitorEventType(msgType),
|
||||
Data: elems,
|
||||
Error: err,
|
||||
}
|
||||
monitor.eventCh <- event
|
||||
case unix.NFT_MSG_NEWOBJ, unix.NFT_MSG_DELOBJ:
|
||||
obj, err := objFromMsg(msg)
|
||||
event := &MonitorEvent{
|
||||
Type: MonitorEventType(msgType),
|
||||
Data: obj,
|
||||
Error: err,
|
||||
}
|
||||
monitor.eventCh <- event
|
||||
}
|
||||
}
|
||||
}
|
||||
monitor.mu.Lock()
|
||||
defer monitor.mu.Unlock()
|
||||
|
||||
if monitor.status != monitorClosed {
|
||||
monitor.status = monitorClosed
|
||||
}
|
||||
close(monitor.eventCh)
|
||||
}
|
||||
|
||||
func (monitor *Monitor) Close() error {
|
||||
monitor.mu.Lock()
|
||||
defer monitor.mu.Unlock()
|
||||
|
||||
if monitor.status != monitorClosed {
|
||||
monitor.status = monitorClosed
|
||||
return monitor.closer()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddMonitor to perform the monitor immediately. The channel will be closed after
|
||||
// calling Close on Monitor or encountering a netlink conn error while Receive.
|
||||
// Caller may receive a MonitorEventTypeOOB event which contains an error we didn't
|
||||
// handle, for now.
|
||||
func (cc *Conn) AddMonitor(monitor *Monitor) (chan *MonitorEvent, error) {
|
||||
conn, closer, err := cc.netlinkConn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
monitor.conn = conn
|
||||
monitor.closer = closer
|
||||
|
||||
if monitor.monitorFlags != 0 {
|
||||
if err = conn.JoinGroup(uint32(unix.NFNLGRP_NFTABLES)); err != nil {
|
||||
monitor.closer()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
go monitor.monitor()
|
||||
return monitor.eventCh, nil
|
||||
}
|
||||
|
||||
func parseRuleFromMsg(msg netlink.Message) (*Rule, error) {
|
||||
genmsg := &NFGenMsg{}
|
||||
genmsg.Decode(msg.Data[:4])
|
||||
return ruleFromMsg(TableFamily(genmsg.NFGenFamily), msg)
|
||||
}
|
||||
241
vendor/github.com/google/nftables/obj.go
generated
vendored
Normal file
241
vendor/github.com/google/nftables/obj.go
generated
vendored
Normal file
@@ -0,0 +1,241 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nftables
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
var (
|
||||
newObjHeaderType = netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_NEWOBJ)
|
||||
delObjHeaderType = netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_DELOBJ)
|
||||
)
|
||||
|
||||
// Obj represents a netfilter stateful object. See also
|
||||
// https://wiki.nftables.org/wiki-nftables/index.php/Stateful_objects
|
||||
type Obj interface {
|
||||
table() *Table
|
||||
family() TableFamily
|
||||
unmarshal(*netlink.AttributeDecoder) error
|
||||
marshal(data bool) ([]byte, error)
|
||||
}
|
||||
|
||||
// AddObject adds the specified Obj. Alias of AddObj.
|
||||
func (cc *Conn) AddObject(o Obj) Obj {
|
||||
return cc.AddObj(o)
|
||||
}
|
||||
|
||||
// AddObj adds the specified Obj. See also
|
||||
// https://wiki.nftables.org/wiki-nftables/index.php/Stateful_objects
|
||||
func (cc *Conn) AddObj(o Obj) Obj {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
data, err := o.marshal(true)
|
||||
if err != nil {
|
||||
cc.setErr(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
cc.messages = append(cc.messages, netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_NEWOBJ),
|
||||
Flags: netlink.Request | netlink.Acknowledge | netlink.Create,
|
||||
},
|
||||
Data: append(extraHeader(uint8(o.family()), 0), data...),
|
||||
})
|
||||
return o
|
||||
}
|
||||
|
||||
// DeleteObject deletes the specified Obj
|
||||
func (cc *Conn) DeleteObject(o Obj) {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
data, err := o.marshal(false)
|
||||
if err != nil {
|
||||
cc.setErr(err)
|
||||
return
|
||||
}
|
||||
|
||||
data = append(data, cc.marshalAttr([]netlink.Attribute{{Type: unix.NLA_F_NESTED | unix.NFTA_OBJ_DATA}})...)
|
||||
|
||||
cc.messages = append(cc.messages, netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_DELOBJ),
|
||||
Flags: netlink.Request | netlink.Acknowledge,
|
||||
},
|
||||
Data: append(extraHeader(uint8(o.family()), 0), data...),
|
||||
})
|
||||
}
|
||||
|
||||
// GetObj is a legacy method that return all Obj that belongs
|
||||
// to the same table as the given one
|
||||
func (cc *Conn) GetObj(o Obj) ([]Obj, error) {
|
||||
return cc.getObj(nil, o.table(), unix.NFT_MSG_GETOBJ)
|
||||
}
|
||||
|
||||
// GetObjReset is a legacy method that reset all Obj that belongs
|
||||
// the same table as the given one
|
||||
func (cc *Conn) GetObjReset(o Obj) ([]Obj, error) {
|
||||
return cc.getObj(nil, o.table(), unix.NFT_MSG_GETOBJ_RESET)
|
||||
}
|
||||
|
||||
// GetObject gets the specified Object
|
||||
func (cc *Conn) GetObject(o Obj) (Obj, error) {
|
||||
objs, err := cc.getObj(o, o.table(), unix.NFT_MSG_GETOBJ)
|
||||
|
||||
if len(objs) == 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return objs[0], err
|
||||
}
|
||||
|
||||
// GetObjects get all the Obj that belongs to the given table
|
||||
func (cc *Conn) GetObjects(t *Table) ([]Obj, error) {
|
||||
return cc.getObj(nil, t, unix.NFT_MSG_GETOBJ)
|
||||
}
|
||||
|
||||
// ResetObject reset the given Obj
|
||||
func (cc *Conn) ResetObject(o Obj) (Obj, error) {
|
||||
objs, err := cc.getObj(o, o.table(), unix.NFT_MSG_GETOBJ_RESET)
|
||||
|
||||
if len(objs) == 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return objs[0], err
|
||||
}
|
||||
|
||||
// ResetObjects reset all the Obj that belongs to the given table
|
||||
func (cc *Conn) ResetObjects(t *Table) ([]Obj, error) {
|
||||
return cc.getObj(nil, t, unix.NFT_MSG_GETOBJ_RESET)
|
||||
}
|
||||
|
||||
func objFromMsg(msg netlink.Message) (Obj, error) {
|
||||
if got, want1, want2 := msg.Header.Type, newObjHeaderType, delObjHeaderType; got != want1 && got != want2 {
|
||||
return nil, fmt.Errorf("unexpected header type: got %v, want %v or %v", got, want1, want2)
|
||||
}
|
||||
ad, err := netlink.NewAttributeDecoder(msg.Data[4:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
var (
|
||||
table *Table
|
||||
name string
|
||||
objectType uint32
|
||||
)
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_OBJ_TABLE:
|
||||
table = &Table{Name: ad.String(), Family: TableFamily(msg.Data[0])}
|
||||
case unix.NFTA_OBJ_NAME:
|
||||
name = ad.String()
|
||||
case unix.NFTA_OBJ_TYPE:
|
||||
objectType = ad.Uint32()
|
||||
case unix.NFTA_OBJ_DATA:
|
||||
switch objectType {
|
||||
case unix.NFT_OBJECT_COUNTER:
|
||||
o := CounterObj{
|
||||
Table: table,
|
||||
Name: name,
|
||||
}
|
||||
|
||||
ad.Do(func(b []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
return o.unmarshal(ad)
|
||||
})
|
||||
return &o, ad.Err()
|
||||
case NFT_OBJECT_QUOTA:
|
||||
o := QuotaObj{
|
||||
Table: table,
|
||||
Name: name,
|
||||
}
|
||||
|
||||
ad.Do(func(b []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
return o.unmarshal(ad)
|
||||
})
|
||||
return &o, ad.Err()
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := ad.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, fmt.Errorf("malformed stateful object")
|
||||
}
|
||||
|
||||
func (cc *Conn) getObj(o Obj, t *Table, msgType uint16) ([]Obj, error) {
|
||||
conn, closer, err := cc.netlinkConn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = closer() }()
|
||||
|
||||
var data []byte
|
||||
var flags netlink.HeaderFlags
|
||||
|
||||
if o != nil {
|
||||
data, err = o.marshal(false)
|
||||
} else {
|
||||
flags = netlink.Dump
|
||||
data, err = netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_RULE_TABLE, Data: []byte(t.Name + "\x00")},
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
message := netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | msgType),
|
||||
Flags: netlink.Request | netlink.Acknowledge | flags,
|
||||
},
|
||||
Data: append(extraHeader(uint8(t.Family), 0), data...),
|
||||
}
|
||||
|
||||
if _, err := conn.SendMessages([]netlink.Message{message}); err != nil {
|
||||
return nil, fmt.Errorf("SendMessages: %v", err)
|
||||
}
|
||||
|
||||
reply, err := receiveAckAware(conn, message.Header.Flags)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Receive: %v", err)
|
||||
}
|
||||
var objs []Obj
|
||||
for _, msg := range reply {
|
||||
o, err := objFromMsg(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
objs = append(objs, o)
|
||||
}
|
||||
|
||||
return objs, nil
|
||||
}
|
||||
80
vendor/github.com/google/nftables/quota.go
generated
vendored
Normal file
80
vendor/github.com/google/nftables/quota.go
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
// Copyright 2023 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nftables
|
||||
|
||||
import (
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
NFTA_OBJ_USERDATA = 8
|
||||
NFT_OBJECT_QUOTA = 2
|
||||
)
|
||||
|
||||
type QuotaObj struct {
|
||||
Table *Table
|
||||
Name string
|
||||
Bytes uint64
|
||||
Consumed uint64
|
||||
Over bool
|
||||
}
|
||||
|
||||
func (q *QuotaObj) unmarshal(ad *netlink.AttributeDecoder) error {
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_QUOTA_BYTES:
|
||||
q.Bytes = ad.Uint64()
|
||||
case unix.NFTA_QUOTA_CONSUMED:
|
||||
q.Consumed = ad.Uint64()
|
||||
case unix.NFTA_QUOTA_FLAGS:
|
||||
q.Over = (ad.Uint32() & unix.NFT_QUOTA_F_INV) == 1
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (q *QuotaObj) marshal(data bool) ([]byte, error) {
|
||||
flags := uint32(0)
|
||||
if q.Over {
|
||||
flags = unix.NFT_QUOTA_F_INV
|
||||
}
|
||||
obj, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_QUOTA_BYTES, Data: binaryutil.BigEndian.PutUint64(q.Bytes)},
|
||||
{Type: unix.NFTA_QUOTA_CONSUMED, Data: binaryutil.BigEndian.PutUint64(q.Consumed)},
|
||||
{Type: unix.NFTA_QUOTA_FLAGS, Data: binaryutil.BigEndian.PutUint32(flags)},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
attrs := []netlink.Attribute{
|
||||
{Type: unix.NFTA_OBJ_TABLE, Data: []byte(q.Table.Name + "\x00")},
|
||||
{Type: unix.NFTA_OBJ_NAME, Data: []byte(q.Name + "\x00")},
|
||||
{Type: unix.NFTA_OBJ_TYPE, Data: binaryutil.BigEndian.PutUint32(NFT_OBJECT_QUOTA)},
|
||||
}
|
||||
if data {
|
||||
attrs = append(attrs, netlink.Attribute{Type: unix.NLA_F_NESTED | unix.NFTA_OBJ_DATA, Data: obj})
|
||||
}
|
||||
return netlink.MarshalAttributes(attrs)
|
||||
}
|
||||
|
||||
func (q *QuotaObj) table() *Table {
|
||||
return q.Table
|
||||
}
|
||||
|
||||
func (q *QuotaObj) family() TableFamily {
|
||||
return q.Table.Family
|
||||
}
|
||||
270
vendor/github.com/google/nftables/rule.go
generated
vendored
Normal file
270
vendor/github.com/google/nftables/rule.go
generated
vendored
Normal file
@@ -0,0 +1,270 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nftables
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/google/nftables/expr"
|
||||
"github.com/google/nftables/internal/parseexprfunc"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
var (
|
||||
newRuleHeaderType = netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_NEWRULE)
|
||||
delRuleHeaderType = netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_DELRULE)
|
||||
)
|
||||
|
||||
type ruleOperation uint32
|
||||
|
||||
// Possible PayloadOperationType values.
|
||||
const (
|
||||
operationAdd ruleOperation = iota
|
||||
operationInsert
|
||||
operationReplace
|
||||
)
|
||||
|
||||
// A Rule does something with a packet. See also
|
||||
// https://wiki.nftables.org/wiki-nftables/index.php/Simple_rule_management
|
||||
type Rule struct {
|
||||
Table *Table
|
||||
Chain *Chain
|
||||
Position uint64
|
||||
Handle uint64
|
||||
// The list of possible flags are specified by nftnl_rule_attr, see
|
||||
// https://git.netfilter.org/libnftnl/tree/include/libnftnl/rule.h#n21
|
||||
// Current nftables go implementation supports only
|
||||
// NFTNL_RULE_POSITION flag for setting rule at position 0
|
||||
Flags uint32
|
||||
Exprs []expr.Any
|
||||
UserData []byte
|
||||
}
|
||||
|
||||
// GetRule returns the rules in the specified table and chain.
|
||||
//
|
||||
// Deprecated: use GetRules instead.
|
||||
func (cc *Conn) GetRule(t *Table, c *Chain) ([]*Rule, error) {
|
||||
return cc.GetRules(t, c)
|
||||
}
|
||||
|
||||
// GetRules returns the rules in the specified table and chain.
|
||||
func (cc *Conn) GetRules(t *Table, c *Chain) ([]*Rule, error) {
|
||||
conn, closer, err := cc.netlinkConn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = closer() }()
|
||||
|
||||
data, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_RULE_TABLE, Data: []byte(t.Name + "\x00")},
|
||||
{Type: unix.NFTA_RULE_CHAIN, Data: []byte(c.Name + "\x00")},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
message := netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_GETRULE),
|
||||
Flags: netlink.Request | netlink.Acknowledge | netlink.Dump | unix.NLM_F_ECHO,
|
||||
},
|
||||
Data: append(extraHeader(uint8(t.Family), 0), data...),
|
||||
}
|
||||
|
||||
if _, err := conn.SendMessages([]netlink.Message{message}); err != nil {
|
||||
return nil, fmt.Errorf("SendMessages: %v", err)
|
||||
}
|
||||
|
||||
reply, err := receiveAckAware(conn, message.Header.Flags)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Receive: %v", err)
|
||||
}
|
||||
var rules []*Rule
|
||||
for _, msg := range reply {
|
||||
r, err := ruleFromMsg(t.Family, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rules = append(rules, r)
|
||||
}
|
||||
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
// AddRule adds the specified Rule
|
||||
func (cc *Conn) newRule(r *Rule, op ruleOperation) *Rule {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
exprAttrs := make([]netlink.Attribute, len(r.Exprs))
|
||||
for idx, expr := range r.Exprs {
|
||||
exprAttrs[idx] = netlink.Attribute{
|
||||
Type: unix.NLA_F_NESTED | unix.NFTA_LIST_ELEM,
|
||||
Data: cc.marshalExpr(byte(r.Table.Family), expr),
|
||||
}
|
||||
}
|
||||
|
||||
data := cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NFTA_RULE_TABLE, Data: []byte(r.Table.Name + "\x00")},
|
||||
{Type: unix.NFTA_RULE_CHAIN, Data: []byte(r.Chain.Name + "\x00")},
|
||||
})
|
||||
|
||||
if r.Handle != 0 {
|
||||
data = append(data, cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NFTA_RULE_HANDLE, Data: binaryutil.BigEndian.PutUint64(r.Handle)},
|
||||
})...)
|
||||
}
|
||||
|
||||
data = append(data, cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_RULE_EXPRESSIONS, Data: cc.marshalAttr(exprAttrs)},
|
||||
})...)
|
||||
|
||||
if compatPolicy, err := getCompatPolicy(r.Exprs); err != nil {
|
||||
cc.setErr(err)
|
||||
} else if compatPolicy != nil {
|
||||
data = append(data, cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NLA_F_NESTED | unix.NFTA_RULE_COMPAT, Data: cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NFTA_RULE_COMPAT_PROTO, Data: binaryutil.BigEndian.PutUint32(compatPolicy.Proto)},
|
||||
{Type: unix.NFTA_RULE_COMPAT_FLAGS, Data: binaryutil.BigEndian.PutUint32(compatPolicy.Flag & nft_RULE_COMPAT_F_MASK)},
|
||||
})},
|
||||
})...)
|
||||
}
|
||||
|
||||
msgData := []byte{}
|
||||
|
||||
msgData = append(msgData, data...)
|
||||
var flags netlink.HeaderFlags
|
||||
if r.UserData != nil {
|
||||
msgData = append(msgData, cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NFTA_RULE_USERDATA, Data: r.UserData},
|
||||
})...)
|
||||
}
|
||||
|
||||
switch op {
|
||||
case operationAdd:
|
||||
flags = netlink.Request | netlink.Acknowledge | netlink.Create | unix.NLM_F_ECHO | unix.NLM_F_APPEND
|
||||
case operationInsert:
|
||||
flags = netlink.Request | netlink.Acknowledge | netlink.Create | unix.NLM_F_ECHO
|
||||
case operationReplace:
|
||||
flags = netlink.Request | netlink.Acknowledge | netlink.Replace | unix.NLM_F_ECHO | unix.NLM_F_REPLACE
|
||||
}
|
||||
|
||||
if r.Position != 0 || (r.Flags&(1<<unix.NFTA_RULE_POSITION)) != 0 {
|
||||
msgData = append(msgData, cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NFTA_RULE_POSITION, Data: binaryutil.BigEndian.PutUint64(r.Position)},
|
||||
})...)
|
||||
}
|
||||
|
||||
cc.messages = append(cc.messages, netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: newRuleHeaderType,
|
||||
Flags: flags,
|
||||
},
|
||||
Data: append(extraHeader(uint8(r.Table.Family), 0), msgData...),
|
||||
})
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (cc *Conn) ReplaceRule(r *Rule) *Rule {
|
||||
return cc.newRule(r, operationReplace)
|
||||
}
|
||||
|
||||
func (cc *Conn) AddRule(r *Rule) *Rule {
|
||||
if r.Handle != 0 {
|
||||
return cc.newRule(r, operationReplace)
|
||||
}
|
||||
|
||||
return cc.newRule(r, operationAdd)
|
||||
}
|
||||
|
||||
func (cc *Conn) InsertRule(r *Rule) *Rule {
|
||||
if r.Handle != 0 {
|
||||
return cc.newRule(r, operationReplace)
|
||||
}
|
||||
|
||||
return cc.newRule(r, operationInsert)
|
||||
}
|
||||
|
||||
// DelRule deletes the specified Rule, rule's handle cannot be 0
|
||||
func (cc *Conn) DelRule(r *Rule) error {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
data := cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NFTA_RULE_TABLE, Data: []byte(r.Table.Name + "\x00")},
|
||||
{Type: unix.NFTA_RULE_CHAIN, Data: []byte(r.Chain.Name + "\x00")},
|
||||
})
|
||||
if r.Handle == 0 {
|
||||
return fmt.Errorf("rule's handle cannot be 0")
|
||||
}
|
||||
data = append(data, cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NFTA_RULE_HANDLE, Data: binaryutil.BigEndian.PutUint64(r.Handle)},
|
||||
})...)
|
||||
flags := netlink.Request | netlink.Acknowledge
|
||||
|
||||
cc.messages = append(cc.messages, netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: delRuleHeaderType,
|
||||
Flags: flags,
|
||||
},
|
||||
Data: append(extraHeader(uint8(r.Table.Family), 0), data...),
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ruleFromMsg(fam TableFamily, msg netlink.Message) (*Rule, error) {
|
||||
if got, want1, want2 := msg.Header.Type, newRuleHeaderType, delRuleHeaderType; got != want1 && got != want2 {
|
||||
return nil, fmt.Errorf("unexpected header type: got %v, want %v or %v", msg.Header.Type, want1, want2)
|
||||
}
|
||||
ad, err := netlink.NewAttributeDecoder(msg.Data[4:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
var r Rule
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_RULE_TABLE:
|
||||
r.Table = &Table{
|
||||
Name: ad.String(),
|
||||
Family: fam,
|
||||
}
|
||||
case unix.NFTA_RULE_CHAIN:
|
||||
r.Chain = &Chain{Name: ad.String()}
|
||||
case unix.NFTA_RULE_EXPRESSIONS:
|
||||
ad.Do(func(b []byte) error {
|
||||
exprs, err := parseexprfunc.ParseExprMsgFunc(byte(fam), b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Exprs = make([]expr.Any, len(exprs))
|
||||
for i := range exprs {
|
||||
r.Exprs[i] = exprs[i].(expr.Any)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
case unix.NFTA_RULE_POSITION:
|
||||
r.Position = ad.Uint64()
|
||||
case unix.NFTA_RULE_HANDLE:
|
||||
r.Handle = ad.Uint64()
|
||||
case unix.NFTA_RULE_USERDATA:
|
||||
r.UserData = ad.Bytes()
|
||||
}
|
||||
}
|
||||
return &r, ad.Err()
|
||||
}
|
||||
937
vendor/github.com/google/nftables/set.go
generated
vendored
Normal file
937
vendor/github.com/google/nftables/set.go
generated
vendored
Normal file
@@ -0,0 +1,937 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nftables
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/nftables/expr"
|
||||
"github.com/google/nftables/internal/parseexprfunc"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// SetConcatTypeBits defines concatination bits, originally defined in
|
||||
// https://git.netfilter.org/iptables/tree/iptables/nft.c?id=26753888720d8e7eb422ae4311348347f5a05cb4#n1002
|
||||
const (
|
||||
SetConcatTypeBits = 6
|
||||
SetConcatTypeMask = (1 << SetConcatTypeBits) - 1
|
||||
// below consts added because not found in go unix package
|
||||
// https://git.netfilter.org/nftables/tree/include/linux/netfilter/nf_tables.h?id=d1289bff58e1878c3162f574c603da993e29b113#n306
|
||||
NFT_SET_CONCAT = 0x80
|
||||
// https://git.netfilter.org/nftables/tree/include/linux/netfilter/nf_tables.h?id=d1289bff58e1878c3162f574c603da993e29b113#n330
|
||||
NFTA_SET_DESC_CONCAT = 2
|
||||
// https://git.netfilter.org/nftables/tree/include/linux/netfilter/nf_tables.h?id=d1289bff58e1878c3162f574c603da993e29b113#n428
|
||||
NFTA_SET_ELEM_KEY_END = 10
|
||||
// https://git.netfilter.org/nftables/tree/include/linux/netfilter/nf_tables.h?id=d1289bff58e1878c3162f574c603da993e29b113#n429
|
||||
NFTA_SET_ELEM_EXPRESSIONS = 0x11
|
||||
)
|
||||
|
||||
var allocSetID uint32
|
||||
|
||||
// SetDatatype represents a datatype declared by nft.
|
||||
type SetDatatype struct {
|
||||
Name string
|
||||
Bytes uint32
|
||||
|
||||
// nftMagic represents the magic value that nft uses for
|
||||
// certain types (ie: IP addresses). We populate SET_KEY_TYPE
|
||||
// identically, so `nft list ...` commands produce correct output.
|
||||
nftMagic uint32
|
||||
}
|
||||
|
||||
// GetNFTMagic returns a custom datatype based on user's parameters
|
||||
func (s *SetDatatype) GetNFTMagic() uint32 {
|
||||
return s.nftMagic
|
||||
}
|
||||
|
||||
// SetNFTMagic returns a custom datatype based on user's parameters
|
||||
func (s *SetDatatype) SetNFTMagic(nftMagic uint32) {
|
||||
s.nftMagic = nftMagic
|
||||
}
|
||||
|
||||
// NFT datatypes. See: https://git.netfilter.org/nftables/tree/include/datatype.h
|
||||
var (
|
||||
TypeInvalid = SetDatatype{Name: "invalid", nftMagic: 0}
|
||||
TypeVerdict = SetDatatype{Name: "verdict", Bytes: 0, nftMagic: 1}
|
||||
TypeNFProto = SetDatatype{Name: "nf_proto", Bytes: 1, nftMagic: 2}
|
||||
TypeBitmask = SetDatatype{Name: "bitmask", Bytes: 0, nftMagic: 3}
|
||||
TypeInteger = SetDatatype{Name: "integer", Bytes: 4, nftMagic: 4}
|
||||
TypeString = SetDatatype{Name: "string", Bytes: 0, nftMagic: 5}
|
||||
TypeLLAddr = SetDatatype{Name: "ll_addr", Bytes: 0, nftMagic: 6}
|
||||
TypeIPAddr = SetDatatype{Name: "ipv4_addr", Bytes: 4, nftMagic: 7}
|
||||
TypeIP6Addr = SetDatatype{Name: "ipv6_addr", Bytes: 16, nftMagic: 8}
|
||||
TypeEtherAddr = SetDatatype{Name: "ether_addr", Bytes: 6, nftMagic: 9}
|
||||
TypeEtherType = SetDatatype{Name: "ether_type", Bytes: 2, nftMagic: 10}
|
||||
TypeARPOp = SetDatatype{Name: "arp_op", Bytes: 2, nftMagic: 11}
|
||||
TypeInetProto = SetDatatype{Name: "inet_proto", Bytes: 1, nftMagic: 12}
|
||||
TypeInetService = SetDatatype{Name: "inet_service", Bytes: 2, nftMagic: 13}
|
||||
TypeICMPType = SetDatatype{Name: "icmp_type", Bytes: 1, nftMagic: 14}
|
||||
TypeTCPFlag = SetDatatype{Name: "tcp_flag", Bytes: 1, nftMagic: 15}
|
||||
TypeDCCPPktType = SetDatatype{Name: "dccp_pkttype", Bytes: 1, nftMagic: 16}
|
||||
TypeMHType = SetDatatype{Name: "mh_type", Bytes: 1, nftMagic: 17}
|
||||
TypeTime = SetDatatype{Name: "time", Bytes: 8, nftMagic: 18}
|
||||
TypeMark = SetDatatype{Name: "mark", Bytes: 4, nftMagic: 19}
|
||||
TypeIFIndex = SetDatatype{Name: "iface_index", Bytes: 4, nftMagic: 20}
|
||||
TypeARPHRD = SetDatatype{Name: "iface_type", Bytes: 2, nftMagic: 21}
|
||||
TypeRealm = SetDatatype{Name: "realm", Bytes: 4, nftMagic: 22}
|
||||
TypeClassID = SetDatatype{Name: "classid", Bytes: 4, nftMagic: 23}
|
||||
TypeUID = SetDatatype{Name: "uid", Bytes: sizeOfUIDT, nftMagic: 24}
|
||||
TypeGID = SetDatatype{Name: "gid", Bytes: sizeOfGIDT, nftMagic: 25}
|
||||
TypeCTState = SetDatatype{Name: "ct_state", Bytes: 4, nftMagic: 26}
|
||||
TypeCTDir = SetDatatype{Name: "ct_dir", Bytes: 1, nftMagic: 27}
|
||||
TypeCTStatus = SetDatatype{Name: "ct_status", Bytes: 4, nftMagic: 28}
|
||||
TypeICMP6Type = SetDatatype{Name: "icmpv6_type", Bytes: 1, nftMagic: 29}
|
||||
TypeCTLabel = SetDatatype{Name: "ct_label", Bytes: ctLabelBitSize / 8, nftMagic: 30}
|
||||
TypePktType = SetDatatype{Name: "pkt_type", Bytes: 1, nftMagic: 31}
|
||||
TypeICMPCode = SetDatatype{Name: "icmp_code", Bytes: 1, nftMagic: 32}
|
||||
TypeICMPV6Code = SetDatatype{Name: "icmpv6_code", Bytes: 1, nftMagic: 33}
|
||||
TypeICMPXCode = SetDatatype{Name: "icmpx_code", Bytes: 1, nftMagic: 34}
|
||||
TypeDevGroup = SetDatatype{Name: "devgroup", Bytes: 4, nftMagic: 35}
|
||||
TypeDSCP = SetDatatype{Name: "dscp", Bytes: 1, nftMagic: 36}
|
||||
TypeECN = SetDatatype{Name: "ecn", Bytes: 1, nftMagic: 37}
|
||||
TypeFIBAddr = SetDatatype{Name: "fib_addrtype", Bytes: 4, nftMagic: 38}
|
||||
TypeBoolean = SetDatatype{Name: "boolean", Bytes: 1, nftMagic: 39}
|
||||
TypeCTEventBit = SetDatatype{Name: "ct_event", Bytes: 4, nftMagic: 40}
|
||||
TypeIFName = SetDatatype{Name: "ifname", Bytes: ifNameSize, nftMagic: 41}
|
||||
TypeIGMPType = SetDatatype{Name: "igmp_type", Bytes: 1, nftMagic: 42}
|
||||
TypeTimeDate = SetDatatype{Name: "time", Bytes: 8, nftMagic: 43}
|
||||
TypeTimeHour = SetDatatype{Name: "hour", Bytes: 4, nftMagic: 44}
|
||||
TypeTimeDay = SetDatatype{Name: "day", Bytes: 1, nftMagic: 45}
|
||||
TypeCGroupV2 = SetDatatype{Name: "cgroupsv2", Bytes: 8, nftMagic: 46}
|
||||
|
||||
nftDatatypes = []SetDatatype{
|
||||
TypeVerdict,
|
||||
TypeNFProto,
|
||||
TypeBitmask,
|
||||
TypeInteger,
|
||||
TypeString,
|
||||
TypeLLAddr,
|
||||
TypeIPAddr,
|
||||
TypeIP6Addr,
|
||||
TypeEtherAddr,
|
||||
TypeEtherType,
|
||||
TypeARPOp,
|
||||
TypeInetProto,
|
||||
TypeInetService,
|
||||
TypeICMPType,
|
||||
TypeTCPFlag,
|
||||
TypeDCCPPktType,
|
||||
TypeMHType,
|
||||
TypeTime,
|
||||
TypeMark,
|
||||
TypeIFIndex,
|
||||
TypeARPHRD,
|
||||
TypeRealm,
|
||||
TypeClassID,
|
||||
TypeUID,
|
||||
TypeGID,
|
||||
TypeCTState,
|
||||
TypeCTDir,
|
||||
TypeCTStatus,
|
||||
TypeICMP6Type,
|
||||
TypeCTLabel,
|
||||
TypePktType,
|
||||
TypeICMPCode,
|
||||
TypeICMPV6Code,
|
||||
TypeICMPXCode,
|
||||
TypeDevGroup,
|
||||
TypeDSCP,
|
||||
TypeECN,
|
||||
TypeFIBAddr,
|
||||
TypeBoolean,
|
||||
TypeCTEventBit,
|
||||
TypeIFName,
|
||||
TypeIGMPType,
|
||||
TypeTimeDate,
|
||||
TypeTimeHour,
|
||||
TypeTimeDay,
|
||||
TypeCGroupV2,
|
||||
}
|
||||
|
||||
// ctLabelBitSize is defined in https://git.netfilter.org/nftables/tree/src/ct.c.
|
||||
ctLabelBitSize uint32 = 128
|
||||
|
||||
// ifNameSize is called IFNAMSIZ in linux/if.h.
|
||||
ifNameSize uint32 = 16
|
||||
|
||||
// bits/typesizes.h
|
||||
sizeOfUIDT uint32 = 4
|
||||
sizeOfGIDT uint32 = 4
|
||||
)
|
||||
|
||||
var nftDatatypesByName map[string]SetDatatype
|
||||
var nftDatatypesByMagic map[uint32]SetDatatype
|
||||
|
||||
// Create maps for efficient datatype lookup.
|
||||
func init() {
|
||||
nftDatatypesByName = make(map[string]SetDatatype, len(nftDatatypes))
|
||||
nftDatatypesByMagic = make(map[uint32]SetDatatype, len(nftDatatypes))
|
||||
for _, dt := range nftDatatypes {
|
||||
nftDatatypesByName[dt.Name] = dt
|
||||
nftDatatypesByMagic[dt.nftMagic] = dt
|
||||
}
|
||||
}
|
||||
|
||||
// ErrTooManyTypes is the error returned by ConcatSetType, if nftMagic would overflow.
|
||||
var ErrTooManyTypes = errors.New("too many types to concat")
|
||||
|
||||
// MustConcatSetType does the same as ConcatSetType, but panics instead of an
|
||||
// error. It simplifies safe initialization of global variables.
|
||||
func MustConcatSetType(types ...SetDatatype) SetDatatype {
|
||||
t, err := ConcatSetType(types...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// ConcatSetType constructs a new SetDatatype which consists of a concatenation
|
||||
// of the passed types. It returns ErrTooManyTypes, if nftMagic would overflow
|
||||
// (more than 5 types).
|
||||
func ConcatSetType(types ...SetDatatype) (SetDatatype, error) {
|
||||
if len(types) > 32/SetConcatTypeBits {
|
||||
return SetDatatype{}, ErrTooManyTypes
|
||||
}
|
||||
|
||||
var magic, bytes uint32
|
||||
names := make([]string, len(types))
|
||||
for i, t := range types {
|
||||
bytes += t.Bytes
|
||||
// concatenated types pad the length to multiples of the register size (4 bytes)
|
||||
// see https://git.netfilter.org/nftables/tree/src/datatype.c?id=488356b895024d0944b20feb1f930558726e0877#n1162
|
||||
if t.Bytes%4 != 0 {
|
||||
bytes += 4 - (t.Bytes % 4)
|
||||
}
|
||||
names[i] = t.Name
|
||||
|
||||
magic <<= SetConcatTypeBits
|
||||
magic |= t.nftMagic & SetConcatTypeMask
|
||||
}
|
||||
return SetDatatype{Name: strings.Join(names, " . "), Bytes: bytes, nftMagic: magic}, nil
|
||||
}
|
||||
|
||||
// ConcatSetTypeElements uses the ConcatSetType name to calculate and return
|
||||
// a list of base types which were used to construct the concatenated type
|
||||
func ConcatSetTypeElements(t SetDatatype) []SetDatatype {
|
||||
names := strings.Split(t.Name, " . ")
|
||||
types := make([]SetDatatype, len(names))
|
||||
for i, n := range names {
|
||||
types[i] = nftDatatypesByName[n]
|
||||
}
|
||||
return types
|
||||
}
|
||||
|
||||
// Set represents an nftables set. Anonymous sets are only valid within the
|
||||
// context of a single batch.
|
||||
type Set struct {
|
||||
Table *Table
|
||||
ID uint32
|
||||
Name string
|
||||
Anonymous bool
|
||||
Constant bool
|
||||
Interval bool
|
||||
IsMap bool
|
||||
HasTimeout bool
|
||||
Counter bool
|
||||
// Can be updated per evaluation path, per `nft list ruleset`
|
||||
// indicates that set contains "flags dynamic"
|
||||
// https://git.netfilter.org/libnftnl/tree/include/linux/netfilter/nf_tables.h?id=84d12cfacf8ddd857a09435f3d982ab6250d250c#n298
|
||||
Dynamic bool
|
||||
// Indicates that the set contains a concatenation
|
||||
// https://git.netfilter.org/nftables/tree/include/linux/netfilter/nf_tables.h?id=d1289bff58e1878c3162f574c603da993e29b113#n306
|
||||
Concatenation bool
|
||||
Timeout time.Duration
|
||||
KeyType SetDatatype
|
||||
DataType SetDatatype
|
||||
// Either host (binaryutil.NativeEndian) or big (binaryutil.BigEndian) endian as per
|
||||
// https://git.netfilter.org/nftables/tree/include/datatype.h?id=d486c9e626405e829221b82d7355558005b26d8a#n109
|
||||
KeyByteOrder binaryutil.ByteOrder
|
||||
}
|
||||
|
||||
// SetElement represents a data point within a set.
|
||||
type SetElement struct {
|
||||
Key []byte
|
||||
Val []byte
|
||||
// Field used for definition of ending interval value in concatenated types
|
||||
// https://git.netfilter.org/libnftnl/tree/include/set_elem.h?id=e2514c0eff4da7e8e0aabd410f7b7d0b7564c880#n11
|
||||
KeyEnd []byte
|
||||
IntervalEnd bool
|
||||
// To support vmap, a caller must be able to pass Verdict type of data.
|
||||
// If IsMap is true and VerdictData is not nil, then Val of SetElement will be ignored
|
||||
// and VerdictData will be wrapped into Attribute data.
|
||||
VerdictData *expr.Verdict
|
||||
// To support aging of set elements
|
||||
Timeout time.Duration
|
||||
|
||||
// Life left of the "timeout" elements
|
||||
Expires time.Duration
|
||||
|
||||
Counter *expr.Counter
|
||||
}
|
||||
|
||||
func (s *SetElement) decode(fam byte) func(b []byte) error {
|
||||
return func(b []byte) error {
|
||||
ad, err := netlink.NewAttributeDecoder(b)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create nested attribute decoder: %v", err)
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_SET_ELEM_KEY:
|
||||
s.Key, err = decodeElement(ad.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case NFTA_SET_ELEM_KEY_END:
|
||||
s.KeyEnd, err = decodeElement(ad.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case unix.NFTA_SET_ELEM_DATA:
|
||||
s.Val, err = decodeElement(ad.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case unix.NFTA_SET_ELEM_FLAGS:
|
||||
flags := ad.Uint32()
|
||||
s.IntervalEnd = (flags & unix.NFT_SET_ELEM_INTERVAL_END) != 0
|
||||
case unix.NFTA_SET_ELEM_TIMEOUT:
|
||||
s.Timeout = time.Millisecond * time.Duration(ad.Uint64())
|
||||
case unix.NFTA_SET_ELEM_EXPIRATION:
|
||||
s.Expires = time.Millisecond * time.Duration(ad.Uint64())
|
||||
case unix.NFTA_SET_ELEM_EXPR:
|
||||
elems, err := parseexprfunc.ParseExprBytesFunc(fam, ad, ad.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, elem := range elems {
|
||||
switch item := elem.(type) {
|
||||
case *expr.Counter:
|
||||
s.Counter = item
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ad.Err()
|
||||
}
|
||||
}
|
||||
|
||||
func decodeElement(d []byte) ([]byte, error) {
|
||||
ad, err := netlink.NewAttributeDecoder(d)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create nested attribute decoder: %v", err)
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
var b []byte
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_SET_ELEM_KEY:
|
||||
fallthrough
|
||||
case unix.NFTA_SET_ELEM_DATA:
|
||||
b = ad.Bytes()
|
||||
}
|
||||
}
|
||||
if err := ad.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// SetAddElements applies data points to an nftables set.
|
||||
func (cc *Conn) SetAddElements(s *Set, vals []SetElement) error {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
if s.Anonymous {
|
||||
return errors.New("anonymous sets cannot be updated")
|
||||
}
|
||||
|
||||
elements, err := s.makeElemList(vals, s.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cc.messages = append(cc.messages, netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_NEWSETELEM),
|
||||
Flags: netlink.Request | netlink.Acknowledge | netlink.Create,
|
||||
},
|
||||
Data: append(extraHeader(uint8(s.Table.Family), 0), cc.marshalAttr(elements)...),
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Set) makeElemList(vals []SetElement, id uint32) ([]netlink.Attribute, error) {
|
||||
var elements []netlink.Attribute
|
||||
|
||||
for i, v := range vals {
|
||||
item := make([]netlink.Attribute, 0)
|
||||
var flags uint32
|
||||
if v.IntervalEnd {
|
||||
flags |= unix.NFT_SET_ELEM_INTERVAL_END
|
||||
item = append(item, netlink.Attribute{Type: unix.NFTA_SET_ELEM_FLAGS | unix.NLA_F_NESTED, Data: binaryutil.BigEndian.PutUint32(flags)})
|
||||
}
|
||||
|
||||
encodedKey, err := netlink.MarshalAttributes([]netlink.Attribute{{Type: unix.NFTA_DATA_VALUE, Data: v.Key}})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("marshal key %d: %v", i, err)
|
||||
}
|
||||
|
||||
item = append(item, netlink.Attribute{Type: unix.NFTA_SET_ELEM_KEY | unix.NLA_F_NESTED, Data: encodedKey})
|
||||
if len(v.KeyEnd) > 0 {
|
||||
encodedKeyEnd, err := netlink.MarshalAttributes([]netlink.Attribute{{Type: unix.NFTA_DATA_VALUE, Data: v.KeyEnd}})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("marshal key end %d: %v", i, err)
|
||||
}
|
||||
item = append(item, netlink.Attribute{Type: NFTA_SET_ELEM_KEY_END | unix.NLA_F_NESTED, Data: encodedKeyEnd})
|
||||
}
|
||||
if s.HasTimeout && v.Timeout != 0 {
|
||||
// Set has Timeout flag set, which means an individual element can specify its own timeout.
|
||||
item = append(item, netlink.Attribute{Type: unix.NFTA_SET_ELEM_TIMEOUT, Data: binaryutil.BigEndian.PutUint64(uint64(v.Timeout.Milliseconds()))})
|
||||
}
|
||||
// The following switch statement deal with 3 different types of elements.
|
||||
// 1. v is an element of vmap
|
||||
// 2. v is an element of a regular map
|
||||
// 3. v is an element of a regular set (default)
|
||||
switch {
|
||||
case v.VerdictData != nil:
|
||||
// Since VerdictData is not nil, v is vmap element, need to add to the attributes
|
||||
encodedVal := []byte{}
|
||||
encodedKind, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_DATA_VALUE, Data: binaryutil.BigEndian.PutUint32(uint32(v.VerdictData.Kind))},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("marshal item %d: %v", i, err)
|
||||
}
|
||||
encodedVal = append(encodedVal, encodedKind...)
|
||||
if len(v.VerdictData.Chain) != 0 {
|
||||
encodedChain, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_SET_ELEM_DATA, Data: []byte(v.VerdictData.Chain + "\x00")},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("marshal item %d: %v", i, err)
|
||||
}
|
||||
encodedVal = append(encodedVal, encodedChain...)
|
||||
}
|
||||
encodedVerdict, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_SET_ELEM_DATA | unix.NLA_F_NESTED, Data: encodedVal}})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("marshal item %d: %v", i, err)
|
||||
}
|
||||
item = append(item, netlink.Attribute{Type: unix.NFTA_SET_ELEM_DATA | unix.NLA_F_NESTED, Data: encodedVerdict})
|
||||
case len(v.Val) > 0:
|
||||
// Since v.Val's length is not 0 then, v is a regular map element, need to add to the attributes
|
||||
encodedVal, err := netlink.MarshalAttributes([]netlink.Attribute{{Type: unix.NFTA_DATA_VALUE, Data: v.Val}})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("marshal item %d: %v", i, err)
|
||||
}
|
||||
|
||||
item = append(item, netlink.Attribute{Type: unix.NFTA_SET_ELEM_DATA | unix.NLA_F_NESTED, Data: encodedVal})
|
||||
default:
|
||||
// If niether of previous cases matche, it means 'e' is an element of a regular Set, no need to add to the attributes
|
||||
}
|
||||
|
||||
encodedItem, err := netlink.MarshalAttributes(item)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("marshal item %d: %v", i, err)
|
||||
}
|
||||
elements = append(elements, netlink.Attribute{Type: uint16(i+1) | unix.NLA_F_NESTED, Data: encodedItem})
|
||||
}
|
||||
|
||||
encodedElem, err := netlink.MarshalAttributes(elements)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("marshal elements: %v", err)
|
||||
}
|
||||
|
||||
return []netlink.Attribute{
|
||||
{Type: unix.NFTA_SET_NAME, Data: []byte(s.Name + "\x00")},
|
||||
{Type: unix.NFTA_LOOKUP_SET_ID, Data: binaryutil.BigEndian.PutUint32(id)},
|
||||
{Type: unix.NFTA_SET_TABLE, Data: []byte(s.Table.Name + "\x00")},
|
||||
{Type: unix.NFTA_SET_ELEM_LIST_ELEMENTS | unix.NLA_F_NESTED, Data: encodedElem},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// AddSet adds the specified Set.
|
||||
func (cc *Conn) AddSet(s *Set, vals []SetElement) error {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
// Based on nft implementation & linux source.
|
||||
// Link: https://github.com/torvalds/linux/blob/49a57857aeea06ca831043acbb0fa5e0f50602fd/net/netfilter/nf_tables_api.c#L3395
|
||||
// Another reference: https://git.netfilter.org/nftables/tree/src
|
||||
|
||||
if s.Anonymous && !s.Constant {
|
||||
return errors.New("anonymous structs must be constant")
|
||||
}
|
||||
|
||||
if s.ID == 0 {
|
||||
allocSetID++
|
||||
s.ID = allocSetID
|
||||
if s.Anonymous {
|
||||
s.Name = "__set%d"
|
||||
if s.IsMap {
|
||||
s.Name = "__map%d"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var flags uint32
|
||||
if s.Anonymous {
|
||||
flags |= unix.NFT_SET_ANONYMOUS
|
||||
}
|
||||
if s.Constant {
|
||||
flags |= unix.NFT_SET_CONSTANT
|
||||
}
|
||||
if s.Interval {
|
||||
flags |= unix.NFT_SET_INTERVAL
|
||||
}
|
||||
if s.IsMap {
|
||||
flags |= unix.NFT_SET_MAP
|
||||
}
|
||||
if s.HasTimeout {
|
||||
flags |= unix.NFT_SET_TIMEOUT
|
||||
}
|
||||
if s.Dynamic {
|
||||
flags |= unix.NFT_SET_EVAL
|
||||
}
|
||||
if s.Concatenation {
|
||||
flags |= NFT_SET_CONCAT
|
||||
}
|
||||
tableInfo := []netlink.Attribute{
|
||||
{Type: unix.NFTA_SET_TABLE, Data: []byte(s.Table.Name + "\x00")},
|
||||
{Type: unix.NFTA_SET_NAME, Data: []byte(s.Name + "\x00")},
|
||||
{Type: unix.NFTA_SET_FLAGS, Data: binaryutil.BigEndian.PutUint32(flags)},
|
||||
{Type: unix.NFTA_SET_KEY_TYPE, Data: binaryutil.BigEndian.PutUint32(s.KeyType.nftMagic)},
|
||||
{Type: unix.NFTA_SET_KEY_LEN, Data: binaryutil.BigEndian.PutUint32(s.KeyType.Bytes)},
|
||||
{Type: unix.NFTA_SET_ID, Data: binaryutil.BigEndian.PutUint32(s.ID)},
|
||||
}
|
||||
if s.IsMap {
|
||||
// Check if it is vmap case
|
||||
if s.DataType.nftMagic == 1 {
|
||||
// For Verdict data type, the expected magic is 0xfffff0
|
||||
tableInfo = append(tableInfo, netlink.Attribute{Type: unix.NFTA_SET_DATA_TYPE, Data: binaryutil.BigEndian.PutUint32(uint32(unix.NFT_DATA_VERDICT))},
|
||||
netlink.Attribute{Type: unix.NFTA_SET_DATA_LEN, Data: binaryutil.BigEndian.PutUint32(s.DataType.Bytes)})
|
||||
} else {
|
||||
tableInfo = append(tableInfo, netlink.Attribute{Type: unix.NFTA_SET_DATA_TYPE, Data: binaryutil.BigEndian.PutUint32(s.DataType.nftMagic)},
|
||||
netlink.Attribute{Type: unix.NFTA_SET_DATA_LEN, Data: binaryutil.BigEndian.PutUint32(s.DataType.Bytes)})
|
||||
}
|
||||
}
|
||||
if s.HasTimeout && s.Timeout != 0 {
|
||||
// If Set's global timeout is specified, add it to set's attributes
|
||||
tableInfo = append(tableInfo, netlink.Attribute{Type: unix.NFTA_SET_TIMEOUT, Data: binaryutil.BigEndian.PutUint64(uint64(s.Timeout.Milliseconds()))})
|
||||
}
|
||||
if s.Constant {
|
||||
// nft cli tool adds the number of elements to set/map's descriptor
|
||||
// It make sense to do only if a set or map are constant, otherwise skip NFTA_SET_DESC attribute
|
||||
numberOfElements, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_DATA_VALUE, Data: binaryutil.BigEndian.PutUint32(uint32(len(vals)))},
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("fail to marshal number of elements %d: %v", len(vals), err)
|
||||
}
|
||||
tableInfo = append(tableInfo, netlink.Attribute{Type: unix.NLA_F_NESTED | unix.NFTA_SET_DESC, Data: numberOfElements})
|
||||
}
|
||||
if s.Concatenation {
|
||||
// Length of concatenated types is a must, otherwise segfaults when executing nft list ruleset
|
||||
var concatDefinition []byte
|
||||
elements := ConcatSetTypeElements(s.KeyType)
|
||||
for i, v := range elements {
|
||||
// Marshal base type size value
|
||||
valData, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_DATA_VALUE, Data: binaryutil.BigEndian.PutUint32(v.Bytes)},
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("fail to marshal element key size %d: %v", i, err)
|
||||
}
|
||||
// Marshal base type size description
|
||||
descSize, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_SET_DESC_SIZE, Data: valData},
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("fail to marshal base type size description: %w", err)
|
||||
}
|
||||
concatDefinition = append(concatDefinition, descSize...)
|
||||
}
|
||||
// Marshal all base type descriptions into concatenation size description
|
||||
concatBytes, err := netlink.MarshalAttributes([]netlink.Attribute{{Type: unix.NLA_F_NESTED | NFTA_SET_DESC_CONCAT, Data: concatDefinition}})
|
||||
if err != nil {
|
||||
return fmt.Errorf("fail to marshal concat definition %v", err)
|
||||
}
|
||||
// Marshal concat size description as set description
|
||||
tableInfo = append(tableInfo, netlink.Attribute{Type: unix.NLA_F_NESTED | unix.NFTA_SET_DESC, Data: concatBytes})
|
||||
}
|
||||
if s.Anonymous || s.Constant || s.Interval || s.KeyByteOrder == binaryutil.BigEndian {
|
||||
tableInfo = append(tableInfo,
|
||||
// Semantically useless - kept for binary compatability with nft
|
||||
netlink.Attribute{Type: unix.NFTA_SET_USERDATA, Data: []byte("\x00\x04\x02\x00\x00\x00")})
|
||||
} else if s.KeyByteOrder == binaryutil.NativeEndian {
|
||||
// Per https://git.netfilter.org/nftables/tree/src/mnl.c?id=187c6d01d35722618c2711bbc49262c286472c8f#n1165
|
||||
tableInfo = append(tableInfo,
|
||||
netlink.Attribute{Type: unix.NFTA_SET_USERDATA, Data: []byte("\x00\x04\x01\x00\x00\x00")})
|
||||
}
|
||||
if s.Counter {
|
||||
data, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_LIST_ELEM, Data: []byte("counter\x00")},
|
||||
{Type: unix.NFTA_SET_ELEM_PAD | unix.NFTA_SET_ELEM_DATA, Data: []byte{}},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tableInfo = append(tableInfo, netlink.Attribute{Type: unix.NLA_F_NESTED | NFTA_SET_ELEM_EXPRESSIONS, Data: data})
|
||||
}
|
||||
|
||||
cc.messages = append(cc.messages, netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_NEWSET),
|
||||
Flags: netlink.Request | netlink.Acknowledge | netlink.Create,
|
||||
},
|
||||
Data: append(extraHeader(uint8(s.Table.Family), 0), cc.marshalAttr(tableInfo)...),
|
||||
})
|
||||
|
||||
// Set the values of the set if initial values were provided.
|
||||
if len(vals) > 0 {
|
||||
hdrType := unix.NFT_MSG_NEWSETELEM
|
||||
elements, err := s.makeElemList(vals, s.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cc.messages = append(cc.messages, netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | hdrType),
|
||||
Flags: netlink.Request | netlink.Acknowledge | netlink.Create,
|
||||
},
|
||||
Data: append(extraHeader(uint8(s.Table.Family), 0), cc.marshalAttr(elements)...),
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelSet deletes a specific set, along with all elements it contains.
|
||||
func (cc *Conn) DelSet(s *Set) {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
data := cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NFTA_SET_TABLE, Data: []byte(s.Table.Name + "\x00")},
|
||||
{Type: unix.NFTA_SET_NAME, Data: []byte(s.Name + "\x00")},
|
||||
})
|
||||
cc.messages = append(cc.messages, netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_DELSET),
|
||||
Flags: netlink.Request | netlink.Acknowledge,
|
||||
},
|
||||
Data: append(extraHeader(uint8(s.Table.Family), 0), data...),
|
||||
})
|
||||
}
|
||||
|
||||
// SetDeleteElements deletes data points from an nftables set.
|
||||
func (cc *Conn) SetDeleteElements(s *Set, vals []SetElement) error {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
if s.Anonymous {
|
||||
return errors.New("anonymous sets cannot be updated")
|
||||
}
|
||||
|
||||
elements, err := s.makeElemList(vals, s.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cc.messages = append(cc.messages, netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_DELSETELEM),
|
||||
Flags: netlink.Request | netlink.Acknowledge | netlink.Create,
|
||||
},
|
||||
Data: append(extraHeader(uint8(s.Table.Family), 0), cc.marshalAttr(elements)...),
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FlushSet deletes all data points from an nftables set.
|
||||
func (cc *Conn) FlushSet(s *Set) {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
data := cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NFTA_SET_TABLE, Data: []byte(s.Table.Name + "\x00")},
|
||||
{Type: unix.NFTA_SET_NAME, Data: []byte(s.Name + "\x00")},
|
||||
})
|
||||
cc.messages = append(cc.messages, netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_DELSETELEM),
|
||||
Flags: netlink.Request | netlink.Acknowledge,
|
||||
},
|
||||
Data: append(extraHeader(uint8(s.Table.Family), 0), data...),
|
||||
})
|
||||
}
|
||||
|
||||
var (
|
||||
newSetHeaderType = netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_NEWSET)
|
||||
delSetHeaderType = netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_DELSET)
|
||||
)
|
||||
|
||||
func setsFromMsg(msg netlink.Message) (*Set, error) {
|
||||
if got, want1, want2 := msg.Header.Type, newSetHeaderType, delSetHeaderType; got != want1 && got != want2 {
|
||||
return nil, fmt.Errorf("unexpected header type: got %v, want %v or %v", got, want1, want2)
|
||||
}
|
||||
ad, err := netlink.NewAttributeDecoder(msg.Data[4:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
|
||||
var set Set
|
||||
for ad.Next() {
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_SET_NAME:
|
||||
set.Name = ad.String()
|
||||
case unix.NFTA_SET_ID:
|
||||
set.ID = binary.BigEndian.Uint32(ad.Bytes())
|
||||
case unix.NFTA_SET_TIMEOUT:
|
||||
set.Timeout = time.Duration(time.Millisecond * time.Duration(binary.BigEndian.Uint64(ad.Bytes())))
|
||||
set.HasTimeout = true
|
||||
case unix.NFTA_SET_FLAGS:
|
||||
flags := ad.Uint32()
|
||||
set.Constant = (flags & unix.NFT_SET_CONSTANT) != 0
|
||||
set.Anonymous = (flags & unix.NFT_SET_ANONYMOUS) != 0
|
||||
set.Interval = (flags & unix.NFT_SET_INTERVAL) != 0
|
||||
set.IsMap = (flags & unix.NFT_SET_MAP) != 0
|
||||
set.HasTimeout = (flags & unix.NFT_SET_TIMEOUT) != 0
|
||||
set.Concatenation = (flags & NFT_SET_CONCAT) != 0
|
||||
case unix.NFTA_SET_KEY_TYPE:
|
||||
nftMagic := ad.Uint32()
|
||||
dt, err := parseSetDatatype(nftMagic)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not determine data type: %w", err)
|
||||
}
|
||||
set.KeyType = dt
|
||||
case unix.NFTA_SET_KEY_LEN:
|
||||
set.KeyType.Bytes = binary.BigEndian.Uint32(ad.Bytes())
|
||||
case unix.NFTA_SET_DATA_TYPE:
|
||||
nftMagic := ad.Uint32()
|
||||
// Special case for the data type verdict, in the message it is stored as 0xffffff00 but it is defined as 1
|
||||
if nftMagic == 0xffffff00 {
|
||||
set.KeyType = TypeVerdict
|
||||
break
|
||||
}
|
||||
dt, err := parseSetDatatype(nftMagic)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not determine data type: %w", err)
|
||||
}
|
||||
set.DataType = dt
|
||||
case unix.NFTA_SET_DATA_LEN:
|
||||
set.DataType.Bytes = binary.BigEndian.Uint32(ad.Bytes())
|
||||
}
|
||||
}
|
||||
return &set, nil
|
||||
}
|
||||
|
||||
func parseSetDatatype(magic uint32) (SetDatatype, error) {
|
||||
types := make([]SetDatatype, 0, 32/SetConcatTypeBits)
|
||||
for magic != 0 {
|
||||
t := magic & SetConcatTypeMask
|
||||
magic = magic >> SetConcatTypeBits
|
||||
dt, ok := nftDatatypesByMagic[t]
|
||||
if !ok {
|
||||
return TypeInvalid, fmt.Errorf("could not determine data type %+v", dt)
|
||||
}
|
||||
// Because we start with the last type, we insert the later types at the front.
|
||||
types = append([]SetDatatype{dt}, types...)
|
||||
}
|
||||
|
||||
dt, err := ConcatSetType(types...)
|
||||
if err != nil {
|
||||
return TypeInvalid, fmt.Errorf("could not create data type: %w", err)
|
||||
}
|
||||
return dt, nil
|
||||
}
|
||||
|
||||
var (
|
||||
newElemHeaderType = netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_NEWSETELEM)
|
||||
delElemHeaderType = netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_DELSETELEM)
|
||||
)
|
||||
|
||||
func elementsFromMsg(fam byte, msg netlink.Message) ([]SetElement, error) {
|
||||
if got, want1, want2 := msg.Header.Type, newElemHeaderType, delElemHeaderType; got != want1 && got != want2 {
|
||||
return nil, fmt.Errorf("unexpected header type: got %v, want %v or %v", got, want1, want2)
|
||||
}
|
||||
ad, err := netlink.NewAttributeDecoder(msg.Data[4:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
|
||||
var elements []SetElement
|
||||
for ad.Next() {
|
||||
b := ad.Bytes()
|
||||
if ad.Type() == unix.NFTA_SET_ELEM_LIST_ELEMENTS {
|
||||
ad, err := netlink.NewAttributeDecoder(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ad.ByteOrder = binary.BigEndian
|
||||
|
||||
for ad.Next() {
|
||||
var elem SetElement
|
||||
switch ad.Type() {
|
||||
case unix.NFTA_LIST_ELEM:
|
||||
ad.Do(elem.decode(fam))
|
||||
}
|
||||
elements = append(elements, elem)
|
||||
}
|
||||
}
|
||||
}
|
||||
return elements, nil
|
||||
}
|
||||
|
||||
// GetSets returns the sets in the specified table.
|
||||
func (cc *Conn) GetSets(t *Table) ([]*Set, error) {
|
||||
conn, closer, err := cc.netlinkConn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = closer() }()
|
||||
|
||||
data, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_SET_TABLE, Data: []byte(t.Name + "\x00")},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
message := netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_GETSET),
|
||||
Flags: netlink.Request | netlink.Acknowledge | netlink.Dump,
|
||||
},
|
||||
Data: append(extraHeader(uint8(t.Family), 0), data...),
|
||||
}
|
||||
|
||||
if _, err := conn.SendMessages([]netlink.Message{message}); err != nil {
|
||||
return nil, fmt.Errorf("SendMessages: %v", err)
|
||||
}
|
||||
|
||||
reply, err := receiveAckAware(conn, message.Header.Flags)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Receive: %v", err)
|
||||
}
|
||||
var sets []*Set
|
||||
for _, msg := range reply {
|
||||
s, err := setsFromMsg(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.Table = &Table{Name: t.Name, Use: t.Use, Flags: t.Flags, Family: t.Family}
|
||||
sets = append(sets, s)
|
||||
}
|
||||
|
||||
return sets, nil
|
||||
}
|
||||
|
||||
// GetSetByName returns the set in the specified table if matching name is found.
|
||||
func (cc *Conn) GetSetByName(t *Table, name string) (*Set, error) {
|
||||
conn, closer, err := cc.netlinkConn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = closer() }()
|
||||
|
||||
data, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_SET_TABLE, Data: []byte(t.Name + "\x00")},
|
||||
{Type: unix.NFTA_SET_NAME, Data: []byte(name + "\x00")},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
message := netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_GETSET),
|
||||
Flags: netlink.Request | netlink.Acknowledge,
|
||||
},
|
||||
Data: append(extraHeader(uint8(t.Family), 0), data...),
|
||||
}
|
||||
|
||||
if _, err := conn.SendMessages([]netlink.Message{message}); err != nil {
|
||||
return nil, fmt.Errorf("SendMessages: %w", err)
|
||||
}
|
||||
|
||||
reply, err := receiveAckAware(conn, message.Header.Flags)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Receive: %w", err)
|
||||
}
|
||||
|
||||
if len(reply) != 1 {
|
||||
return nil, fmt.Errorf("Receive: expected to receive 1 message but got %d", len(reply))
|
||||
}
|
||||
rs, err := setsFromMsg(reply[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rs.Table = &Table{Name: t.Name, Use: t.Use, Flags: t.Flags, Family: t.Family}
|
||||
|
||||
return rs, nil
|
||||
}
|
||||
|
||||
// GetSetElements returns the elements in the specified set.
|
||||
func (cc *Conn) GetSetElements(s *Set) ([]SetElement, error) {
|
||||
conn, closer, err := cc.netlinkConn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = closer() }()
|
||||
|
||||
data, err := netlink.MarshalAttributes([]netlink.Attribute{
|
||||
{Type: unix.NFTA_SET_TABLE, Data: []byte(s.Table.Name + "\x00")},
|
||||
{Type: unix.NFTA_SET_NAME, Data: []byte(s.Name + "\x00")},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
message := netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_GETSETELEM),
|
||||
Flags: netlink.Request | netlink.Acknowledge | netlink.Dump,
|
||||
},
|
||||
Data: append(extraHeader(uint8(s.Table.Family), 0), data...),
|
||||
}
|
||||
|
||||
if _, err := conn.SendMessages([]netlink.Message{message}); err != nil {
|
||||
return nil, fmt.Errorf("SendMessages: %v", err)
|
||||
}
|
||||
|
||||
reply, err := receiveAckAware(conn, message.Header.Flags)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Receive: %v", err)
|
||||
}
|
||||
var elems []SetElement
|
||||
for _, msg := range reply {
|
||||
s, err := elementsFromMsg(uint8(s.Table.Family), msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
elems = append(elems, s...)
|
||||
}
|
||||
|
||||
return elems, nil
|
||||
}
|
||||
212
vendor/github.com/google/nftables/table.go
generated
vendored
Normal file
212
vendor/github.com/google/nftables/table.go
generated
vendored
Normal file
@@ -0,0 +1,212 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nftables
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/mdlayher/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
var (
|
||||
newTableHeaderType = netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_NEWTABLE)
|
||||
delTableHeaderType = netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_DELTABLE)
|
||||
)
|
||||
|
||||
// TableFamily specifies the address family for this table.
|
||||
type TableFamily byte
|
||||
|
||||
// Possible TableFamily values.
|
||||
const (
|
||||
TableFamilyUnspecified TableFamily = unix.NFPROTO_UNSPEC
|
||||
TableFamilyINet TableFamily = unix.NFPROTO_INET
|
||||
TableFamilyIPv4 TableFamily = unix.NFPROTO_IPV4
|
||||
TableFamilyIPv6 TableFamily = unix.NFPROTO_IPV6
|
||||
TableFamilyARP TableFamily = unix.NFPROTO_ARP
|
||||
TableFamilyNetdev TableFamily = unix.NFPROTO_NETDEV
|
||||
TableFamilyBridge TableFamily = unix.NFPROTO_BRIDGE
|
||||
)
|
||||
|
||||
// A Table contains Chains. See also
|
||||
// https://wiki.nftables.org/wiki-nftables/index.php/Configuring_tables
|
||||
type Table struct {
|
||||
Name string // NFTA_TABLE_NAME
|
||||
Use uint32 // NFTA_TABLE_USE (Number of chains in table)
|
||||
Flags uint32 // NFTA_TABLE_FLAGS
|
||||
Family TableFamily
|
||||
}
|
||||
|
||||
// DelTable deletes a specific table, along with all chains/rules it contains.
|
||||
func (cc *Conn) DelTable(t *Table) {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
data := cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NFTA_TABLE_NAME, Data: []byte(t.Name + "\x00")},
|
||||
{Type: unix.NFTA_TABLE_FLAGS, Data: []byte{0, 0, 0, 0}},
|
||||
})
|
||||
cc.messages = append(cc.messages, netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_DELTABLE),
|
||||
Flags: netlink.Request | netlink.Acknowledge,
|
||||
},
|
||||
Data: append(extraHeader(uint8(t.Family), 0), data...),
|
||||
})
|
||||
}
|
||||
|
||||
func (cc *Conn) addTable(t *Table, flag netlink.HeaderFlags) *Table {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
data := cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NFTA_TABLE_NAME, Data: []byte(t.Name + "\x00")},
|
||||
{Type: unix.NFTA_TABLE_FLAGS, Data: []byte{0, 0, 0, 0}},
|
||||
})
|
||||
cc.messages = append(cc.messages, netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_NEWTABLE),
|
||||
Flags: netlink.Request | netlink.Acknowledge | flag,
|
||||
},
|
||||
Data: append(extraHeader(uint8(t.Family), 0), data...),
|
||||
})
|
||||
return t
|
||||
}
|
||||
|
||||
// AddTable adds the specified Table, just like `nft add table ...`.
|
||||
// See also https://wiki.nftables.org/wiki-nftables/index.php/Configuring_tables
|
||||
func (cc *Conn) AddTable(t *Table) *Table {
|
||||
return cc.addTable(t, netlink.Create)
|
||||
}
|
||||
|
||||
// CreateTable create the specified Table if it do not existed.
|
||||
// just like `nft create table ...`.
|
||||
func (cc *Conn) CreateTable(t *Table) *Table {
|
||||
return cc.addTable(t, netlink.Excl)
|
||||
}
|
||||
|
||||
// FlushTable removes all rules in all chains within the specified Table. See also
|
||||
// https://wiki.nftables.org/wiki-nftables/index.php/Configuring_tables#Flushing_tables
|
||||
func (cc *Conn) FlushTable(t *Table) {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
data := cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NFTA_RULE_TABLE, Data: []byte(t.Name + "\x00")},
|
||||
})
|
||||
cc.messages = append(cc.messages, netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_DELRULE),
|
||||
Flags: netlink.Request | netlink.Acknowledge,
|
||||
},
|
||||
Data: append(extraHeader(uint8(t.Family), 0), data...),
|
||||
})
|
||||
}
|
||||
|
||||
// ListTable returns table found for the specified name. Searches for
|
||||
// the table under IPv4 family. As per nft man page: "When no address
|
||||
// family is specified, ip is used by default."
|
||||
func (cc *Conn) ListTable(name string) (*Table, error) {
|
||||
return cc.ListTableOfFamily(name, TableFamilyIPv4)
|
||||
}
|
||||
|
||||
// ListTableOfFamily returns table found for the specified name and table family
|
||||
func (cc *Conn) ListTableOfFamily(name string, family TableFamily) (*Table, error) {
|
||||
t, err := cc.listTablesOfNameAndFamily(name, family)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if got, want := len(t), 1; got != want {
|
||||
return nil, fmt.Errorf("expected table count %d, got %d", want, got)
|
||||
}
|
||||
return t[0], nil
|
||||
}
|
||||
|
||||
// ListTables returns currently configured tables in the kernel
|
||||
func (cc *Conn) ListTables() ([]*Table, error) {
|
||||
return cc.ListTablesOfFamily(TableFamilyUnspecified)
|
||||
}
|
||||
|
||||
// ListTablesOfFamily returns currently configured tables for the specified table family
|
||||
// in the kernel. It lists all tables if family is TableFamilyUnspecified.
|
||||
func (cc *Conn) ListTablesOfFamily(family TableFamily) ([]*Table, error) {
|
||||
return cc.listTablesOfNameAndFamily("", family)
|
||||
}
|
||||
|
||||
func (cc *Conn) listTablesOfNameAndFamily(name string, family TableFamily) ([]*Table, error) {
|
||||
conn, closer, err := cc.netlinkConn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = closer() }()
|
||||
|
||||
data := extraHeader(uint8(family), 0)
|
||||
flags := netlink.Request | netlink.Dump
|
||||
if name != "" {
|
||||
data = append(data, cc.marshalAttr([]netlink.Attribute{
|
||||
{Type: unix.NFTA_TABLE_NAME, Data: []byte(name + "\x00")},
|
||||
})...)
|
||||
flags = netlink.Request
|
||||
}
|
||||
|
||||
msg := netlink.Message{
|
||||
Header: netlink.Header{
|
||||
Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_GETTABLE),
|
||||
Flags: flags,
|
||||
},
|
||||
Data: data,
|
||||
}
|
||||
|
||||
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, want1, want2 := msg.Header.Type, newTableHeaderType, delTableHeaderType; got != want1 && got != want2 {
|
||||
return nil, fmt.Errorf("unexpected header type: got %v, want %v or %v", got, want1, want2)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
89
vendor/github.com/google/nftables/util.go
generated
vendored
Normal file
89
vendor/github.com/google/nftables/util.go
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nftables
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"net"
|
||||
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func extraHeader(family uint8, resID uint16) []byte {
|
||||
return append([]byte{
|
||||
family,
|
||||
unix.NFNETLINK_V0,
|
||||
}, binaryutil.BigEndian.PutUint16(resID)...)
|
||||
}
|
||||
|
||||
// General form of address family dependent message, see
|
||||
// https://git.netfilter.org/libnftnl/tree/include/linux/netfilter/nfnetlink.h#29
|
||||
type NFGenMsg struct {
|
||||
NFGenFamily uint8
|
||||
Version uint8
|
||||
ResourceID uint16
|
||||
}
|
||||
|
||||
func (genmsg *NFGenMsg) Decode(b []byte) {
|
||||
if len(b) < 16 {
|
||||
return
|
||||
}
|
||||
genmsg.NFGenFamily = b[0]
|
||||
genmsg.Version = b[1]
|
||||
genmsg.ResourceID = binary.BigEndian.Uint16(b[2:])
|
||||
}
|
||||
|
||||
// NetFirstAndLastIP takes the beginning address of an entire network in CIDR
|
||||
// notation (e.g. 192.168.1.0/24) and returns the first and last IP addresses
|
||||
// within the network (e.g. first 192.168.1.0, last 192.168.1.255).
|
||||
//
|
||||
// Note that these are the first and last IP addresses, not the first and last
|
||||
// *usable* IP addresses (which would be 192.168.1.1 and 192.168.1.254,
|
||||
// respectively, for 192.168.1.0/24).
|
||||
func NetFirstAndLastIP(networkCIDR string) (first, last net.IP, err error) {
|
||||
_, subnet, err := net.ParseCIDR(networkCIDR)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
first = make(net.IP, len(subnet.IP))
|
||||
last = make(net.IP, len(subnet.IP))
|
||||
|
||||
switch len(subnet.IP) {
|
||||
case net.IPv4len:
|
||||
mask := binary.BigEndian.Uint32(subnet.Mask)
|
||||
ip := binary.BigEndian.Uint32(subnet.IP)
|
||||
// To achieve the first IP address, we need to AND the IP with the mask.
|
||||
// The AND operation will set all bits in the host part to 0.
|
||||
binary.BigEndian.PutUint32(first, ip&mask)
|
||||
// To achieve the last IP address, we need to OR the IP network with the inverted mask.
|
||||
// The AND between the IP and the mask will set all bits in the host part to 0, keeping the network part.
|
||||
// The XOR between the mask and 0xffffffff will set all bits in the host part to 1, and the network part to 0.
|
||||
// The OR operation will keep the host part unchanged, and sets the host part to all 1.
|
||||
binary.BigEndian.PutUint32(last, (ip&mask)|(mask^0xffffffff))
|
||||
case net.IPv6len:
|
||||
mask1 := binary.BigEndian.Uint64(subnet.Mask[:8])
|
||||
mask2 := binary.BigEndian.Uint64(subnet.Mask[8:])
|
||||
ip1 := binary.BigEndian.Uint64(subnet.IP[:8])
|
||||
ip2 := binary.BigEndian.Uint64(subnet.IP[8:])
|
||||
binary.BigEndian.PutUint64(first[:8], ip1&mask1)
|
||||
binary.BigEndian.PutUint64(first[8:], ip2&mask2)
|
||||
binary.BigEndian.PutUint64(last[:8], (ip1&mask1)|(mask1^0xffffffffffffffff))
|
||||
binary.BigEndian.PutUint64(last[8:], (ip2&mask2)|(mask2^0xffffffffffffffff))
|
||||
}
|
||||
|
||||
return first, last, nil
|
||||
}
|
||||
94
vendor/github.com/google/nftables/xt/info.go
generated
vendored
Normal file
94
vendor/github.com/google/nftables/xt/info.go
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
package xt
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// TableFamily specifies the address family of the table Match or Target Info
|
||||
// data is contained in. On purpose, we don't import the expr package here in
|
||||
// order to keep the option open to import this package instead into expr.
|
||||
type TableFamily byte
|
||||
|
||||
// InfoAny is a (un)marshaling implemented by any info type.
|
||||
type InfoAny interface {
|
||||
marshal(fam TableFamily, rev uint32) ([]byte, error)
|
||||
unmarshal(fam TableFamily, rev uint32, data []byte) error
|
||||
}
|
||||
|
||||
// Marshal a Match or Target Info type into its binary representation.
|
||||
func Marshal(fam TableFamily, rev uint32, info InfoAny) ([]byte, error) {
|
||||
return info.marshal(fam, rev)
|
||||
}
|
||||
|
||||
// Unmarshal Info binary payload into its corresponding dedicated type as
|
||||
// indicated by the name argument. In several cases, unmarshalling depends on
|
||||
// the specific table family the Target or Match expression with the info
|
||||
// payload belongs to, as well as the specific info structure revision.
|
||||
func Unmarshal(name string, fam TableFamily, rev uint32, data []byte) (InfoAny, error) {
|
||||
var i InfoAny
|
||||
switch name {
|
||||
case "addrtype":
|
||||
switch rev {
|
||||
case 0:
|
||||
i = &AddrType{}
|
||||
case 1:
|
||||
i = &AddrTypeV1{}
|
||||
}
|
||||
case "conntrack":
|
||||
switch rev {
|
||||
case 1:
|
||||
i = &ConntrackMtinfo1{}
|
||||
case 2:
|
||||
i = &ConntrackMtinfo2{}
|
||||
case 3:
|
||||
i = &ConntrackMtinfo3{}
|
||||
}
|
||||
case "tcp":
|
||||
i = &Tcp{}
|
||||
case "udp":
|
||||
i = &Udp{}
|
||||
case "SNAT":
|
||||
if fam == unix.NFPROTO_IPV4 {
|
||||
i = &NatIPv4MultiRangeCompat{}
|
||||
}
|
||||
case "DNAT":
|
||||
switch fam {
|
||||
case unix.NFPROTO_IPV4:
|
||||
if rev == 0 {
|
||||
i = &NatIPv4MultiRangeCompat{}
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
case unix.NFPROTO_IPV6:
|
||||
switch rev {
|
||||
case 1:
|
||||
i = &NatRange{}
|
||||
case 2:
|
||||
i = &NatRange2{}
|
||||
}
|
||||
}
|
||||
case "MASQUERADE":
|
||||
switch fam {
|
||||
case unix.NFPROTO_IPV4:
|
||||
i = &NatIPv4MultiRangeCompat{}
|
||||
}
|
||||
case "REDIRECT":
|
||||
switch fam {
|
||||
case unix.NFPROTO_IPV4:
|
||||
if rev == 0 {
|
||||
i = &NatIPv4MultiRangeCompat{}
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
case unix.NFPROTO_IPV6:
|
||||
i = &NatRange{}
|
||||
}
|
||||
}
|
||||
if i == nil {
|
||||
i = &Unknown{}
|
||||
}
|
||||
if err := i.unmarshal(fam, rev, data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
89
vendor/github.com/google/nftables/xt/match_addrtype.go
generated
vendored
Normal file
89
vendor/github.com/google/nftables/xt/match_addrtype.go
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
package xt
|
||||
|
||||
import (
|
||||
"github.com/google/nftables/alignedbuff"
|
||||
)
|
||||
|
||||
// Rev. 0, see https://elixir.bootlin.com/linux/v5.17.7/source/include/uapi/linux/netfilter/xt_addrtype.h#L38
|
||||
type AddrType struct {
|
||||
Source uint16
|
||||
Dest uint16
|
||||
InvertSource bool
|
||||
InvertDest bool
|
||||
}
|
||||
|
||||
type AddrTypeFlags uint32
|
||||
|
||||
const (
|
||||
AddrTypeUnspec AddrTypeFlags = 1 << iota
|
||||
AddrTypeUnicast
|
||||
AddrTypeLocal
|
||||
AddrTypeBroadcast
|
||||
AddrTypeAnycast
|
||||
AddrTypeMulticast
|
||||
AddrTypeBlackhole
|
||||
AddrTypeUnreachable
|
||||
AddrTypeProhibit
|
||||
AddrTypeThrow
|
||||
AddrTypeNat
|
||||
AddrTypeXresolve
|
||||
)
|
||||
|
||||
// See https://elixir.bootlin.com/linux/v5.17.7/source/include/uapi/linux/netfilter/xt_addrtype.h#L31
|
||||
type AddrTypeV1 struct {
|
||||
Source uint16
|
||||
Dest uint16
|
||||
Flags AddrTypeFlags
|
||||
}
|
||||
|
||||
func (x *AddrType) marshal(fam TableFamily, rev uint32) ([]byte, error) {
|
||||
ab := alignedbuff.New()
|
||||
ab.PutUint16(x.Source)
|
||||
ab.PutUint16(x.Dest)
|
||||
putBool32(&ab, x.InvertSource)
|
||||
putBool32(&ab, x.InvertDest)
|
||||
return ab.Data(), nil
|
||||
}
|
||||
|
||||
func (x *AddrType) unmarshal(fam TableFamily, rev uint32, data []byte) error {
|
||||
ab := alignedbuff.NewWithData(data)
|
||||
var err error
|
||||
if x.Source, err = ab.Uint16(); err != nil {
|
||||
return nil
|
||||
}
|
||||
if x.Dest, err = ab.Uint16(); err != nil {
|
||||
return nil
|
||||
}
|
||||
if x.InvertSource, err = bool32(&ab); err != nil {
|
||||
return nil
|
||||
}
|
||||
if x.InvertDest, err = bool32(&ab); err != nil {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *AddrTypeV1) marshal(fam TableFamily, rev uint32) ([]byte, error) {
|
||||
ab := alignedbuff.New()
|
||||
ab.PutUint16(x.Source)
|
||||
ab.PutUint16(x.Dest)
|
||||
ab.PutUint32(uint32(x.Flags))
|
||||
return ab.Data(), nil
|
||||
}
|
||||
|
||||
func (x *AddrTypeV1) unmarshal(fam TableFamily, rev uint32, data []byte) error {
|
||||
ab := alignedbuff.NewWithData(data)
|
||||
var err error
|
||||
if x.Source, err = ab.Uint16(); err != nil {
|
||||
return nil
|
||||
}
|
||||
if x.Dest, err = ab.Uint16(); err != nil {
|
||||
return nil
|
||||
}
|
||||
var flags uint32
|
||||
if flags, err = ab.Uint32(); err != nil {
|
||||
return nil
|
||||
}
|
||||
x.Flags = AddrTypeFlags(flags)
|
||||
return nil
|
||||
}
|
||||
260
vendor/github.com/google/nftables/xt/match_conntrack.go
generated
vendored
Normal file
260
vendor/github.com/google/nftables/xt/match_conntrack.go
generated
vendored
Normal file
@@ -0,0 +1,260 @@
|
||||
package xt
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/google/nftables/alignedbuff"
|
||||
)
|
||||
|
||||
type ConntrackFlags uint16
|
||||
|
||||
const (
|
||||
ConntrackState ConntrackFlags = 1 << iota
|
||||
ConntrackProto
|
||||
ConntrackOrigSrc
|
||||
ConntrackOrigDst
|
||||
ConntrackReplSrc
|
||||
ConntrackReplDst
|
||||
ConntrackStatus
|
||||
ConntrackExpires
|
||||
ConntrackOrigSrcPort
|
||||
ConntrackOrigDstPort
|
||||
ConntrackReplSrcPort
|
||||
ConntrackReplDstPrt
|
||||
ConntrackDirection
|
||||
ConntrackStateAlias
|
||||
)
|
||||
|
||||
type ConntrackMtinfoBase struct {
|
||||
OrigSrcAddr net.IP
|
||||
OrigSrcMask net.IPMask
|
||||
OrigDstAddr net.IP
|
||||
OrigDstMask net.IPMask
|
||||
ReplSrcAddr net.IP
|
||||
ReplSrcMask net.IPMask
|
||||
ReplDstAddr net.IP
|
||||
ReplDstMask net.IPMask
|
||||
ExpiresMin uint32
|
||||
ExpiresMax uint32
|
||||
L4Proto uint16
|
||||
OrigSrcPort uint16
|
||||
OrigDstPort uint16
|
||||
ReplSrcPort uint16
|
||||
ReplDstPort uint16
|
||||
MatchFlags uint16
|
||||
InvertFlags uint16
|
||||
}
|
||||
|
||||
// See https://elixir.bootlin.com/linux/v5.17.7/source/include/uapi/linux/netfilter/xt_conntrack.h#L38
|
||||
type ConntrackMtinfo1 struct {
|
||||
ConntrackMtinfoBase
|
||||
StateMask uint8
|
||||
StatusMask uint8
|
||||
}
|
||||
|
||||
// See https://elixir.bootlin.com/linux/v5.17.7/source/include/uapi/linux/netfilter/xt_conntrack.h#L51
|
||||
type ConntrackMtinfo2 struct {
|
||||
ConntrackMtinfoBase
|
||||
StateMask uint16
|
||||
StatusMask uint16
|
||||
}
|
||||
|
||||
// See https://elixir.bootlin.com/linux/v5.17.7/source/include/uapi/linux/netfilter/xt_conntrack.h#L64
|
||||
type ConntrackMtinfo3 struct {
|
||||
ConntrackMtinfo2
|
||||
OrigSrcPortHigh uint16
|
||||
OrigDstPortHigh uint16
|
||||
ReplSrcPortHigh uint16
|
||||
ReplDstPortHigh uint16
|
||||
}
|
||||
|
||||
func (x *ConntrackMtinfoBase) marshalAB(fam TableFamily, rev uint32, ab *alignedbuff.AlignedBuff) error {
|
||||
if err := putIPv46(ab, fam, x.OrigSrcAddr); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := putIPv46Mask(ab, fam, x.OrigSrcMask); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := putIPv46(ab, fam, x.OrigDstAddr); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := putIPv46Mask(ab, fam, x.OrigDstMask); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := putIPv46(ab, fam, x.ReplSrcAddr); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := putIPv46Mask(ab, fam, x.ReplSrcMask); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := putIPv46(ab, fam, x.ReplDstAddr); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := putIPv46Mask(ab, fam, x.ReplDstMask); err != nil {
|
||||
return err
|
||||
}
|
||||
ab.PutUint32(x.ExpiresMin)
|
||||
ab.PutUint32(x.ExpiresMax)
|
||||
ab.PutUint16(x.L4Proto)
|
||||
ab.PutUint16(x.OrigSrcPort)
|
||||
ab.PutUint16(x.OrigDstPort)
|
||||
ab.PutUint16(x.ReplSrcPort)
|
||||
ab.PutUint16(x.ReplDstPort)
|
||||
ab.PutUint16(x.MatchFlags)
|
||||
ab.PutUint16(x.InvertFlags)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ConntrackMtinfoBase) unmarshalAB(fam TableFamily, rev uint32, ab *alignedbuff.AlignedBuff) error {
|
||||
var err error
|
||||
if x.OrigSrcAddr, err = iPv46(ab, fam); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.OrigSrcMask, err = iPv46Mask(ab, fam); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.OrigDstAddr, err = iPv46(ab, fam); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.OrigDstMask, err = iPv46Mask(ab, fam); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.ReplSrcAddr, err = iPv46(ab, fam); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.ReplSrcMask, err = iPv46Mask(ab, fam); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.ReplDstAddr, err = iPv46(ab, fam); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.ReplDstMask, err = iPv46Mask(ab, fam); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.ExpiresMin, err = ab.Uint32(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.ExpiresMax, err = ab.Uint32(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.L4Proto, err = ab.Uint16(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.OrigSrcPort, err = ab.Uint16(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.OrigDstPort, err = ab.Uint16(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.ReplSrcPort, err = ab.Uint16(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.ReplDstPort, err = ab.Uint16(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.MatchFlags, err = ab.Uint16(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.InvertFlags, err = ab.Uint16(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ConntrackMtinfo1) marshal(fam TableFamily, rev uint32) ([]byte, error) {
|
||||
ab := alignedbuff.New()
|
||||
if err := x.ConntrackMtinfoBase.marshalAB(fam, rev, &ab); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ab.PutUint8(x.StateMask)
|
||||
ab.PutUint8(x.StatusMask)
|
||||
return ab.Data(), nil
|
||||
}
|
||||
|
||||
func (x *ConntrackMtinfo1) unmarshal(fam TableFamily, rev uint32, data []byte) error {
|
||||
ab := alignedbuff.NewWithData(data)
|
||||
var err error
|
||||
if err = x.ConntrackMtinfoBase.unmarshalAB(fam, rev, &ab); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.StateMask, err = ab.Uint8(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.StatusMask, err = ab.Uint8(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ConntrackMtinfo2) marshalAB(fam TableFamily, rev uint32, ab *alignedbuff.AlignedBuff) error {
|
||||
if err := x.ConntrackMtinfoBase.marshalAB(fam, rev, ab); err != nil {
|
||||
return err
|
||||
}
|
||||
ab.PutUint16(x.StateMask)
|
||||
ab.PutUint16(x.StatusMask)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ConntrackMtinfo2) marshal(fam TableFamily, rev uint32) ([]byte, error) {
|
||||
ab := alignedbuff.New()
|
||||
if err := x.marshalAB(fam, rev, &ab); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ab.Data(), nil
|
||||
}
|
||||
|
||||
func (x *ConntrackMtinfo2) unmarshalAB(fam TableFamily, rev uint32, ab *alignedbuff.AlignedBuff) error {
|
||||
var err error
|
||||
if err = x.ConntrackMtinfoBase.unmarshalAB(fam, rev, ab); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.StateMask, err = ab.Uint16(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.StatusMask, err = ab.Uint16(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ConntrackMtinfo2) unmarshal(fam TableFamily, rev uint32, data []byte) error {
|
||||
ab := alignedbuff.NewWithData(data)
|
||||
var err error
|
||||
if err = x.unmarshalAB(fam, rev, &ab); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ConntrackMtinfo3) marshal(fam TableFamily, rev uint32) ([]byte, error) {
|
||||
ab := alignedbuff.New()
|
||||
if err := x.ConntrackMtinfo2.marshalAB(fam, rev, &ab); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ab.PutUint16(x.OrigSrcPortHigh)
|
||||
ab.PutUint16(x.OrigDstPortHigh)
|
||||
ab.PutUint16(x.ReplSrcPortHigh)
|
||||
ab.PutUint16(x.ReplDstPortHigh)
|
||||
return ab.Data(), nil
|
||||
}
|
||||
|
||||
func (x *ConntrackMtinfo3) unmarshal(fam TableFamily, rev uint32, data []byte) error {
|
||||
ab := alignedbuff.NewWithData(data)
|
||||
var err error
|
||||
if err = x.ConntrackMtinfo2.unmarshalAB(fam, rev, &ab); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.OrigSrcPortHigh, err = ab.Uint16(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.OrigDstPortHigh, err = ab.Uint16(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.ReplSrcPortHigh, err = ab.Uint16(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.ReplDstPortHigh, err = ab.Uint16(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
74
vendor/github.com/google/nftables/xt/match_tcp.go
generated
vendored
Normal file
74
vendor/github.com/google/nftables/xt/match_tcp.go
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
package xt
|
||||
|
||||
import (
|
||||
"github.com/google/nftables/alignedbuff"
|
||||
)
|
||||
|
||||
// Tcp is the Match.Info payload for the tcp xtables extension
|
||||
// (https://wiki.nftables.org/wiki-nftables/index.php/Supported_features_compared_to_xtables#tcp).
|
||||
//
|
||||
// See
|
||||
// https://elixir.bootlin.com/linux/v5.17.7/source/include/uapi/linux/netfilter/xt_tcpudp.h#L8
|
||||
type Tcp struct {
|
||||
SrcPorts [2]uint16 // min, max source port range
|
||||
DstPorts [2]uint16 // min, max destination port range
|
||||
Option uint8 // TCP option if non-zero
|
||||
FlagsMask uint8 // TCP flags mask
|
||||
FlagsCmp uint8 // TCP flags compare
|
||||
InvFlags TcpInvFlagset // Inverse flags
|
||||
}
|
||||
|
||||
type TcpInvFlagset uint8
|
||||
|
||||
const (
|
||||
TcpInvSrcPorts TcpInvFlagset = 1 << iota
|
||||
TcpInvDestPorts
|
||||
TcpInvFlags
|
||||
TcpInvOption
|
||||
TcpInvMask TcpInvFlagset = (1 << iota) - 1
|
||||
)
|
||||
|
||||
func (x *Tcp) marshal(fam TableFamily, rev uint32) ([]byte, error) {
|
||||
ab := alignedbuff.New()
|
||||
ab.PutUint16(x.SrcPorts[0])
|
||||
ab.PutUint16(x.SrcPorts[1])
|
||||
ab.PutUint16(x.DstPorts[0])
|
||||
ab.PutUint16(x.DstPorts[1])
|
||||
ab.PutUint8(x.Option)
|
||||
ab.PutUint8(x.FlagsMask)
|
||||
ab.PutUint8(x.FlagsCmp)
|
||||
ab.PutUint8(byte(x.InvFlags))
|
||||
return ab.Data(), nil
|
||||
}
|
||||
|
||||
func (x *Tcp) unmarshal(fam TableFamily, rev uint32, data []byte) error {
|
||||
ab := alignedbuff.NewWithData(data)
|
||||
var err error
|
||||
if x.SrcPorts[0], err = ab.Uint16(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.SrcPorts[1], err = ab.Uint16(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.DstPorts[0], err = ab.Uint16(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.DstPorts[1], err = ab.Uint16(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.Option, err = ab.Uint8(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.FlagsMask, err = ab.Uint8(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.FlagsCmp, err = ab.Uint8(); err != nil {
|
||||
return err
|
||||
}
|
||||
var invFlags uint8
|
||||
if invFlags, err = ab.Uint8(); err != nil {
|
||||
return err
|
||||
}
|
||||
x.InvFlags = TcpInvFlagset(invFlags)
|
||||
return nil
|
||||
}
|
||||
57
vendor/github.com/google/nftables/xt/match_udp.go
generated
vendored
Normal file
57
vendor/github.com/google/nftables/xt/match_udp.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
package xt
|
||||
|
||||
import (
|
||||
"github.com/google/nftables/alignedbuff"
|
||||
)
|
||||
|
||||
// Tcp is the Match.Info payload for the tcp xtables extension
|
||||
// (https://wiki.nftables.org/wiki-nftables/index.php/Supported_features_compared_to_xtables#tcp).
|
||||
//
|
||||
// See
|
||||
// https://elixir.bootlin.com/linux/v5.17.7/source/include/uapi/linux/netfilter/xt_tcpudp.h#L25
|
||||
type Udp struct {
|
||||
SrcPorts [2]uint16 // min, max source port range
|
||||
DstPorts [2]uint16 // min, max destination port range
|
||||
InvFlags UdpInvFlagset // Inverse flags
|
||||
}
|
||||
|
||||
type UdpInvFlagset uint8
|
||||
|
||||
const (
|
||||
UdpInvSrcPorts UdpInvFlagset = 1 << iota
|
||||
UdpInvDestPorts
|
||||
UdpInvMask UdpInvFlagset = (1 << iota) - 1
|
||||
)
|
||||
|
||||
func (x *Udp) marshal(fam TableFamily, rev uint32) ([]byte, error) {
|
||||
ab := alignedbuff.New()
|
||||
ab.PutUint16(x.SrcPorts[0])
|
||||
ab.PutUint16(x.SrcPorts[1])
|
||||
ab.PutUint16(x.DstPorts[0])
|
||||
ab.PutUint16(x.DstPorts[1])
|
||||
ab.PutUint8(byte(x.InvFlags))
|
||||
return ab.Data(), nil
|
||||
}
|
||||
|
||||
func (x *Udp) unmarshal(fam TableFamily, rev uint32, data []byte) error {
|
||||
ab := alignedbuff.NewWithData(data)
|
||||
var err error
|
||||
if x.SrcPorts[0], err = ab.Uint16(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.SrcPorts[1], err = ab.Uint16(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.DstPorts[0], err = ab.Uint16(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.DstPorts[1], err = ab.Uint16(); err != nil {
|
||||
return err
|
||||
}
|
||||
var invFlags uint8
|
||||
if invFlags, err = ab.Uint8(); err != nil {
|
||||
return err
|
||||
}
|
||||
x.InvFlags = UdpInvFlagset(invFlags)
|
||||
return nil
|
||||
}
|
||||
106
vendor/github.com/google/nftables/xt/target_dnat.go
generated
vendored
Normal file
106
vendor/github.com/google/nftables/xt/target_dnat.go
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
package xt
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/google/nftables/alignedbuff"
|
||||
)
|
||||
|
||||
type NatRangeFlags uint
|
||||
|
||||
// See: https://elixir.bootlin.com/linux/v5.17.7/source/include/uapi/linux/netfilter/nf_nat.h#L8
|
||||
const (
|
||||
NatRangeMapIPs NatRangeFlags = (1 << iota)
|
||||
NatRangeProtoSpecified
|
||||
NatRangeProtoRandom
|
||||
NatRangePersistent
|
||||
NatRangeProtoRandomFully
|
||||
NatRangeProtoOffset
|
||||
NatRangeNetmap
|
||||
|
||||
NatRangeMask NatRangeFlags = (1 << iota) - 1
|
||||
|
||||
NatRangeProtoRandomAll = NatRangeProtoRandom | NatRangeProtoRandomFully
|
||||
)
|
||||
|
||||
// see: https://elixir.bootlin.com/linux/v5.17.7/source/include/uapi/linux/netfilter/nf_nat.h#L38
|
||||
type NatRange struct {
|
||||
Flags uint // sic! platform/arch/compiler-dependent uint size
|
||||
MinIP net.IP // always taking up space for an IPv6 address
|
||||
MaxIP net.IP // dito
|
||||
MinPort uint16
|
||||
MaxPort uint16
|
||||
}
|
||||
|
||||
// see: https://elixir.bootlin.com/linux/v5.17.7/source/include/uapi/linux/netfilter/nf_nat.h#L46
|
||||
type NatRange2 struct {
|
||||
NatRange
|
||||
BasePort uint16
|
||||
}
|
||||
|
||||
func (x *NatRange) marshal(fam TableFamily, rev uint32) ([]byte, error) {
|
||||
ab := alignedbuff.New()
|
||||
if err := x.marshalAB(fam, rev, &ab); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ab.Data(), nil
|
||||
}
|
||||
|
||||
func (x *NatRange) marshalAB(fam TableFamily, rev uint32, ab *alignedbuff.AlignedBuff) error {
|
||||
ab.PutUint(x.Flags)
|
||||
if err := putIPv46(ab, fam, x.MinIP); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := putIPv46(ab, fam, x.MaxIP); err != nil {
|
||||
return err
|
||||
}
|
||||
ab.PutUint16BE(x.MinPort)
|
||||
ab.PutUint16BE(x.MaxPort)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NatRange) unmarshal(fam TableFamily, rev uint32, data []byte) error {
|
||||
ab := alignedbuff.NewWithData(data)
|
||||
return x.unmarshalAB(fam, rev, &ab)
|
||||
}
|
||||
|
||||
func (x *NatRange) unmarshalAB(fam TableFamily, rev uint32, ab *alignedbuff.AlignedBuff) error {
|
||||
var err error
|
||||
if x.Flags, err = ab.Uint(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.MinIP, err = iPv46(ab, fam); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.MaxIP, err = iPv46(ab, fam); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.MinPort, err = ab.Uint16BE(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.MaxPort, err = ab.Uint16BE(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NatRange2) marshal(fam TableFamily, rev uint32) ([]byte, error) {
|
||||
ab := alignedbuff.New()
|
||||
if err := x.NatRange.marshalAB(fam, rev, &ab); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ab.PutUint16BE(x.BasePort)
|
||||
return ab.Data(), nil
|
||||
}
|
||||
|
||||
func (x *NatRange2) unmarshal(fam TableFamily, rev uint32, data []byte) error {
|
||||
ab := alignedbuff.NewWithData(data)
|
||||
var err error
|
||||
if err = x.NatRange.unmarshalAB(fam, rev, &ab); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.BasePort, err = ab.Uint16BE(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
86
vendor/github.com/google/nftables/xt/target_masquerade_ip.go
generated
vendored
Normal file
86
vendor/github.com/google/nftables/xt/target_masquerade_ip.go
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
package xt
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
|
||||
"github.com/google/nftables/alignedbuff"
|
||||
)
|
||||
|
||||
// See https://elixir.bootlin.com/linux/v5.17.7/source/include/uapi/linux/netfilter/nf_nat.h#L25
|
||||
type NatIPv4Range struct {
|
||||
Flags uint // sic!
|
||||
MinIP net.IP
|
||||
MaxIP net.IP
|
||||
MinPort uint16
|
||||
MaxPort uint16
|
||||
}
|
||||
|
||||
// NatIPv4MultiRangeCompat despite being a slice of NAT IPv4 ranges is currently allowed to
|
||||
// only hold exactly one element.
|
||||
//
|
||||
// See https://elixir.bootlin.com/linux/v5.17.7/source/include/uapi/linux/netfilter/nf_nat.h#L33
|
||||
type NatIPv4MultiRangeCompat []NatIPv4Range
|
||||
|
||||
func (x *NatIPv4MultiRangeCompat) marshal(fam TableFamily, rev uint32) ([]byte, error) {
|
||||
ab := alignedbuff.New()
|
||||
if len(*x) != 1 {
|
||||
return nil, errors.New("MasqueradeIp must contain exactly one NatIPv4Range")
|
||||
}
|
||||
ab.PutUint(uint(len(*x)))
|
||||
for _, nat := range *x {
|
||||
if err := nat.marshalAB(fam, rev, &ab); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return ab.Data(), nil
|
||||
}
|
||||
|
||||
func (x *NatIPv4MultiRangeCompat) unmarshal(fam TableFamily, rev uint32, data []byte) error {
|
||||
ab := alignedbuff.NewWithData(data)
|
||||
l, err := ab.Uint()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nats := make(NatIPv4MultiRangeCompat, l)
|
||||
for l > 0 {
|
||||
l--
|
||||
if err := nats[l].unmarshalAB(fam, rev, &ab); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*x = nats
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NatIPv4Range) marshalAB(fam TableFamily, rev uint32, ab *alignedbuff.AlignedBuff) error {
|
||||
ab.PutUint(x.Flags)
|
||||
ab.PutBytesAligned32(x.MinIP.To4(), 4)
|
||||
ab.PutBytesAligned32(x.MaxIP.To4(), 4)
|
||||
ab.PutUint16BE(x.MinPort)
|
||||
ab.PutUint16BE(x.MaxPort)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NatIPv4Range) unmarshalAB(fam TableFamily, rev uint32, ab *alignedbuff.AlignedBuff) error {
|
||||
var err error
|
||||
if x.Flags, err = ab.Uint(); err != nil {
|
||||
return err
|
||||
}
|
||||
var ip []byte
|
||||
if ip, err = ab.BytesAligned32(4); err != nil {
|
||||
return err
|
||||
}
|
||||
x.MinIP = net.IP(ip)
|
||||
if ip, err = ab.BytesAligned32(4); err != nil {
|
||||
return err
|
||||
}
|
||||
x.MaxIP = net.IP(ip)
|
||||
if x.MinPort, err = ab.Uint16BE(); err != nil {
|
||||
return err
|
||||
}
|
||||
if x.MaxPort, err = ab.Uint16BE(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
17
vendor/github.com/google/nftables/xt/unknown.go
generated
vendored
Normal file
17
vendor/github.com/google/nftables/xt/unknown.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
package xt
|
||||
|
||||
// Unknown represents the bytes Info payload for unknown Info types where no
|
||||
// dedicated match/target info type has (yet) been defined.
|
||||
type Unknown []byte
|
||||
|
||||
func (x *Unknown) marshal(fam TableFamily, rev uint32) ([]byte, error) {
|
||||
// In case of unknown payload we assume its creator knows what she/he does
|
||||
// and thus we don't do any alignment padding. Just take the payload "as
|
||||
// is".
|
||||
return *x, nil
|
||||
}
|
||||
|
||||
func (x *Unknown) unmarshal(fam TableFamily, rev uint32, data []byte) error {
|
||||
*x = data
|
||||
return nil
|
||||
}
|
||||
64
vendor/github.com/google/nftables/xt/util.go
generated
vendored
Normal file
64
vendor/github.com/google/nftables/xt/util.go
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
package xt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/google/nftables/alignedbuff"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func bool32(ab *alignedbuff.AlignedBuff) (bool, error) {
|
||||
v, err := ab.Uint32()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if v != 0 {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func putBool32(ab *alignedbuff.AlignedBuff, b bool) {
|
||||
if b {
|
||||
ab.PutUint32(1)
|
||||
return
|
||||
}
|
||||
ab.PutUint32(0)
|
||||
}
|
||||
|
||||
func iPv46(ab *alignedbuff.AlignedBuff, fam TableFamily) (net.IP, error) {
|
||||
ip, err := ab.BytesAligned32(16)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch fam {
|
||||
case unix.NFPROTO_IPV4:
|
||||
return net.IP(ip[:4]), nil
|
||||
case unix.NFPROTO_IPV6:
|
||||
return net.IP(ip), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unmarshal IP: unsupported table family %d", fam)
|
||||
}
|
||||
}
|
||||
|
||||
func iPv46Mask(ab *alignedbuff.AlignedBuff, fam TableFamily) (net.IPMask, error) {
|
||||
v, err := iPv46(ab, fam)
|
||||
return net.IPMask(v), err
|
||||
}
|
||||
|
||||
func putIPv46(ab *alignedbuff.AlignedBuff, fam TableFamily, ip net.IP) error {
|
||||
switch fam {
|
||||
case unix.NFPROTO_IPV4:
|
||||
ab.PutBytesAligned32(ip.To4(), 16)
|
||||
case unix.NFPROTO_IPV6:
|
||||
ab.PutBytesAligned32(ip.To16(), 16)
|
||||
default:
|
||||
return fmt.Errorf("marshal IP: unsupported table family %d", fam)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func putIPv46Mask(ab *alignedbuff.AlignedBuff, fam TableFamily, mask net.IPMask) error {
|
||||
return putIPv46(ab, fam, net.IP(mask))
|
||||
}
|
||||
48
vendor/github.com/google/nftables/xt/xt.go
generated
vendored
Normal file
48
vendor/github.com/google/nftables/xt/xt.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Package xt implements dedicated types for (some) of the "Info" payload in Match
|
||||
and Target expressions that bridge between the nftables and xtables worlds.
|
||||
|
||||
Bridging between the more unified world of nftables and the slightly
|
||||
heterogenous world of xtables comes with some caveats. Unmarshalling the
|
||||
extension/translation information in Match and Target expressions requires
|
||||
information about the table family the information belongs to, as well as type
|
||||
and type revision information. In consequence, unmarshalling the Match and
|
||||
Target Info field payloads often (but not necessarily always) require the table
|
||||
family and revision information, so it gets passed to the type-specific
|
||||
unmarshallers.
|
||||
|
||||
To complicate things more, even marshalling requires knowledge about the
|
||||
enclosing table family. The NatRange/NatRange2 types are an example, where it is
|
||||
necessary to differentiate between IPv4 and IPv6 address marshalling. Due to
|
||||
Go's net.IP habit to normally store IPv4 addresses as IPv4-compatible IPv6
|
||||
addresses (see also RFC 4291, section 2.5.5.1) marshalling must be handled
|
||||
differently in the context of an IPv6 table compared to an IPv4 table. In an
|
||||
IPv4 table, an IPv4-compatible IPv6 address must be marshalled as a 32bit
|
||||
address, whereas in an IPv6 table the IPv4 address must be marshalled as an
|
||||
128bit IPv4-compatible IPv6 address. Not relying on heuristics here we avoid
|
||||
behavior unexpected and most probably unknown to our API users. The net.IP habit
|
||||
of storing IPv4 addresses in two different storage formats is already a source
|
||||
for trouble, especially when comparing net.IPs from different Go module sources.
|
||||
We won't add to this confusion. (...or maybe we can, because of it?)
|
||||
|
||||
An important property of all types of Info extension/translation payloads is
|
||||
that their marshalling and unmarshalling doesn't follow netlink's TLV
|
||||
(tag-length-value) architecture. Instead, Info payloads a basically plain binary
|
||||
blobs of their respective type-specific data structures, so host
|
||||
platform/architecture alignment and data type sizes apply. The alignedbuff
|
||||
package implements the different required data types alignments.
|
||||
|
||||
Please note that Info payloads are always padded at their end to the next uint64
|
||||
alignment. Kernel code is checking for the padded payload size and will reject
|
||||
payloads not correctly padded at their ends.
|
||||
|
||||
Most of the time, we find explifcitly sized (unsigned integer) data types.
|
||||
However, there are notable exceptions where "unsigned int" is used: on 64bit
|
||||
platforms this mostly translates into 32bit(!). This differs from Go mapping
|
||||
uint to uint64 instead. This package currently clamps its mapping of C's
|
||||
"unsigned int" to Go's uint32 for marshalling and unmarshalling. If in the
|
||||
future 128bit platforms with a differently sized C unsigned int should come into
|
||||
production, then the alignedbuff package will need to be adapted accordingly, as
|
||||
it abstracts away this data type handling.
|
||||
*/
|
||||
package xt
|
||||
Reference in New Issue
Block a user