mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
ip6tables: ABI structs and constants
Part of #3549. PiperOrigin-RevId: 326329028
This commit is contained in:
committed by
gVisor bot
parent
252329c1f3
commit
d50f2e2c76
@@ -41,6 +41,7 @@ go_library(
|
||||
"mm.go",
|
||||
"netdevice.go",
|
||||
"netfilter.go",
|
||||
"netfilter_ipv6.go",
|
||||
"netlink.go",
|
||||
"netlink_route.go",
|
||||
"poll.go",
|
||||
|
||||
@@ -412,7 +412,7 @@ func (ke *KernelIPTGetEntries) SizeBytes() int {
|
||||
func (ke *KernelIPTGetEntries) MarshalBytes(dst []byte) {
|
||||
ke.IPTGetEntries.MarshalBytes(dst)
|
||||
marshalledUntil := ke.IPTGetEntries.SizeBytes()
|
||||
for i := 0; i < len(ke.Entrytable); i++ {
|
||||
for i := range ke.Entrytable {
|
||||
ke.Entrytable[i].MarshalBytes(dst[marshalledUntil:])
|
||||
marshalledUntil += ke.Entrytable[i].SizeBytes()
|
||||
}
|
||||
@@ -422,7 +422,7 @@ func (ke *KernelIPTGetEntries) MarshalBytes(dst []byte) {
|
||||
func (ke *KernelIPTGetEntries) UnmarshalBytes(src []byte) {
|
||||
ke.IPTGetEntries.UnmarshalBytes(src)
|
||||
unmarshalledUntil := ke.IPTGetEntries.SizeBytes()
|
||||
for i := 0; i < len(ke.Entrytable); i++ {
|
||||
for i := range ke.Entrytable {
|
||||
ke.Entrytable[i].UnmarshalBytes(src[unmarshalledUntil:])
|
||||
unmarshalledUntil += ke.Entrytable[i].SizeBytes()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,310 @@
|
||||
// Copyright 2020 The gVisor Authors.
|
||||
//
|
||||
// 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 linux
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
"gvisor.dev/gvisor/tools/go_marshal/marshal"
|
||||
"gvisor.dev/gvisor/tools/go_marshal/primitive"
|
||||
)
|
||||
|
||||
// This file contains structures required to support IPv6 netfilter and
|
||||
// ip6tables. Some constants and structs are equal to their IPv4 analogues, and
|
||||
// are only distinguished by context (e.g. whether used on an IPv4 of IPv6
|
||||
// socket).
|
||||
|
||||
// Socket options for SOL_SOCLET. These correspond to values in
|
||||
// include/uapi/linux/netfilter_ipv6/ip6_tables.h.
|
||||
const (
|
||||
IP6T_BASE_CTL = 64
|
||||
IP6T_SO_SET_REPLACE = IPT_BASE_CTL
|
||||
IP6T_SO_SET_ADD_COUNTERS = IPT_BASE_CTL + 1
|
||||
IP6T_SO_SET_MAX = IPT_SO_SET_ADD_COUNTERS
|
||||
|
||||
IP6T_SO_GET_INFO = IPT_BASE_CTL
|
||||
IP6T_SO_GET_ENTRIES = IPT_BASE_CTL + 1
|
||||
IP6T_SO_GET_REVISION_MATCH = IPT_BASE_CTL + 4
|
||||
IP6T_SO_GET_REVISION_TARGET = IPT_BASE_CTL + 5
|
||||
IP6T_SO_GET_MAX = IP6T_SO_GET_REVISION_TARGET
|
||||
)
|
||||
|
||||
// IP6T_ORIGINAL_DST is the ip6tables SOL_IPV6 socket option. Corresponds to
|
||||
// the value in include/uapi/linux/netfilter_ipv6/ip6_tables.h.
|
||||
// TODO(gvisor.dev/issue/3549): Support IPv6 original destination.
|
||||
const IP6T_ORIGINAL_DST = 80
|
||||
|
||||
// IP6TReplace is the argument for the IP6T_SO_SET_REPLACE sockopt. It
|
||||
// corresponds to struct ip6t_replace in
|
||||
// include/uapi/linux/netfilter_ipv6/ip6_tables.h.
|
||||
//
|
||||
// +marshal
|
||||
type IP6TReplace struct {
|
||||
Name TableName
|
||||
ValidHooks uint32
|
||||
NumEntries uint32
|
||||
Size uint32
|
||||
HookEntry [NF_INET_NUMHOOKS]uint32
|
||||
Underflow [NF_INET_NUMHOOKS]uint32
|
||||
NumCounters uint32
|
||||
Counters uint64 // This is really a *XTCounters.
|
||||
// Entries is omitted here because it would cause IP6TReplace to be an
|
||||
// extra byte longer (see http://www.catb.org/esr/structure-packing/).
|
||||
// Entries [0]IP6TEntry
|
||||
}
|
||||
|
||||
// SizeOfIP6TReplace is the size of an IP6TReplace.
|
||||
const SizeOfIP6TReplace = 96
|
||||
|
||||
// KernelIP6TGetEntries is identical to IP6TGetEntries, but includes the
|
||||
// Entrytable field. This has been manually made marshal.Marshallable since it
|
||||
// is dynamically sized.
|
||||
type KernelIP6TGetEntries struct {
|
||||
IPTGetEntries
|
||||
Entrytable []KernelIP6TEntry
|
||||
}
|
||||
|
||||
// SizeBytes implements marshal.Marshallable.SizeBytes.
|
||||
func (ke *KernelIP6TGetEntries) SizeBytes() int {
|
||||
res := ke.IPTGetEntries.SizeBytes()
|
||||
for _, entry := range ke.Entrytable {
|
||||
res += entry.SizeBytes()
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// MarshalBytes implements marshal.Marshallable.MarshalBytes.
|
||||
func (ke *KernelIP6TGetEntries) MarshalBytes(dst []byte) {
|
||||
ke.IPTGetEntries.MarshalBytes(dst)
|
||||
marshalledUntil := ke.IPTGetEntries.SizeBytes()
|
||||
for i := range ke.Entrytable {
|
||||
ke.Entrytable[i].MarshalBytes(dst[marshalledUntil:])
|
||||
marshalledUntil += ke.Entrytable[i].SizeBytes()
|
||||
}
|
||||
}
|
||||
|
||||
// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
|
||||
func (ke *KernelIP6TGetEntries) UnmarshalBytes(src []byte) {
|
||||
ke.IPTGetEntries.UnmarshalBytes(src)
|
||||
unmarshalledUntil := ke.IPTGetEntries.SizeBytes()
|
||||
for i := range ke.Entrytable {
|
||||
ke.Entrytable[i].UnmarshalBytes(src[unmarshalledUntil:])
|
||||
unmarshalledUntil += ke.Entrytable[i].SizeBytes()
|
||||
}
|
||||
}
|
||||
|
||||
// Packed implements marshal.Marshallable.Packed.
|
||||
func (ke *KernelIP6TGetEntries) Packed() bool {
|
||||
// KernelIP6TGetEntries isn't packed because the ke.Entrytable contains
|
||||
// an indirection to the actual data we want to marshal (the slice data
|
||||
// pointer), and the memory for KernelIP6TGetEntries contains the slice
|
||||
// header which we don't want to marshal.
|
||||
return false
|
||||
}
|
||||
|
||||
// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
|
||||
func (ke *KernelIP6TGetEntries) MarshalUnsafe(dst []byte) {
|
||||
// Fall back to safe Marshal because the type in not packed.
|
||||
ke.MarshalBytes(dst)
|
||||
}
|
||||
|
||||
// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
|
||||
func (ke *KernelIP6TGetEntries) UnmarshalUnsafe(src []byte) {
|
||||
// Fall back to safe Unmarshal because the type in not packed.
|
||||
ke.UnmarshalBytes(src)
|
||||
}
|
||||
|
||||
// CopyIn implements marshal.Marshallable.CopyIn.
|
||||
func (ke *KernelIP6TGetEntries) CopyIn(task marshal.Task, addr usermem.Addr) (int, error) {
|
||||
buf := task.CopyScratchBuffer(ke.SizeBytes()) // escapes: okay.
|
||||
length, err := task.CopyInBytes(addr, buf) // escapes: okay.
|
||||
// Unmarshal unconditionally. If we had a short copy-in, this results
|
||||
// in a partially unmarshalled struct.
|
||||
ke.UnmarshalBytes(buf) // escapes: fallback.
|
||||
return length, err
|
||||
}
|
||||
|
||||
// CopyOut implements marshal.Marshallable.CopyOut.
|
||||
func (ke *KernelIP6TGetEntries) CopyOut(task marshal.Task, addr usermem.Addr) (int, error) {
|
||||
// Type KernelIP6TGetEntries doesn't have a packed layout in memory,
|
||||
// fall back to MarshalBytes.
|
||||
return task.CopyOutBytes(addr, ke.marshalAll(task))
|
||||
}
|
||||
|
||||
// CopyOutN implements marshal.Marshallable.CopyOutN.
|
||||
func (ke *KernelIP6TGetEntries) CopyOutN(task marshal.Task, addr usermem.Addr, limit int) (int, error) {
|
||||
// Type KernelIP6TGetEntries doesn't have a packed layout in memory, fall
|
||||
// back to MarshalBytes.
|
||||
return task.CopyOutBytes(addr, ke.marshalAll(task)[:limit])
|
||||
}
|
||||
|
||||
func (ke *KernelIP6TGetEntries) marshalAll(task marshal.Task) []byte {
|
||||
buf := task.CopyScratchBuffer(ke.SizeBytes())
|
||||
ke.MarshalBytes(buf)
|
||||
return buf
|
||||
}
|
||||
|
||||
// WriteTo implements io.WriterTo.WriteTo.
|
||||
func (ke *KernelIP6TGetEntries) WriteTo(w io.Writer) (int64, error) {
|
||||
buf := make([]byte, ke.SizeBytes())
|
||||
ke.MarshalBytes(buf)
|
||||
length, err := w.Write(buf)
|
||||
return int64(length), err
|
||||
}
|
||||
|
||||
var _ marshal.Marshallable = (*KernelIP6TGetEntries)(nil)
|
||||
|
||||
// IP6TEntry is an iptables rule. It corresponds to struct ip6t_entry in
|
||||
// include/uapi/linux/netfilter_ipv6/ip6_tables.h.
|
||||
//
|
||||
// +marshal
|
||||
type IP6TEntry struct {
|
||||
// IPv6 is used to filter packets based on the IPv6 header.
|
||||
IPv6 IP6TIP
|
||||
|
||||
// NFCache relates to kernel-internal caching and isn't used by
|
||||
// userspace.
|
||||
NFCache uint32
|
||||
|
||||
// TargetOffset is the byte offset from the beginning of this IPTEntry
|
||||
// to the start of the entry's target.
|
||||
TargetOffset uint16
|
||||
|
||||
// NextOffset is the byte offset from the beginning of this IPTEntry to
|
||||
// the start of the next entry. It is thus also the size of the entry.
|
||||
NextOffset uint16
|
||||
|
||||
// Comeback is a return pointer. It is not used by userspace.
|
||||
Comeback uint32
|
||||
|
||||
_ [4]byte
|
||||
|
||||
// Counters holds the packet and byte counts for this rule.
|
||||
Counters XTCounters
|
||||
|
||||
// Elems holds the data for all this rule's matches followed by the
|
||||
// target. It is variable length -- users have to iterate over any
|
||||
// matches and use TargetOffset and NextOffset to make sense of the
|
||||
// data.
|
||||
//
|
||||
// Elems is omitted here because it would cause IPTEntry to be an extra
|
||||
// byte larger (see http://www.catb.org/esr/structure-packing/).
|
||||
//
|
||||
// Elems [0]byte
|
||||
}
|
||||
|
||||
// SizeOfIP6TEntry is the size of an IP6TEntry.
|
||||
const SizeOfIP6TEntry = 168
|
||||
|
||||
// KernelIP6TEntry is identical to IP6TEntry, but includes the Elems field.
|
||||
// KernelIP6TEntry itself is not Marshallable but it implements some methods of
|
||||
// marshal.Marshallable that help in other implementations of Marshallable.
|
||||
type KernelIP6TEntry struct {
|
||||
Entry IP6TEntry
|
||||
|
||||
// Elems holds the data for all this rule's matches followed by the
|
||||
// target. It is variable length -- users have to iterate over any
|
||||
// matches and use TargetOffset and NextOffset to make sense of the
|
||||
// data.
|
||||
Elems primitive.ByteSlice
|
||||
}
|
||||
|
||||
// SizeBytes implements marshal.Marshallable.SizeBytes.
|
||||
func (ke *KernelIP6TEntry) SizeBytes() int {
|
||||
return ke.Entry.SizeBytes() + ke.Elems.SizeBytes()
|
||||
}
|
||||
|
||||
// MarshalBytes implements marshal.Marshallable.MarshalBytes.
|
||||
func (ke *KernelIP6TEntry) MarshalBytes(dst []byte) {
|
||||
ke.Entry.MarshalBytes(dst)
|
||||
ke.Elems.MarshalBytes(dst[ke.Entry.SizeBytes():])
|
||||
}
|
||||
|
||||
// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
|
||||
func (ke *KernelIP6TEntry) UnmarshalBytes(src []byte) {
|
||||
ke.Entry.UnmarshalBytes(src)
|
||||
ke.Elems.UnmarshalBytes(src[ke.Entry.SizeBytes():])
|
||||
}
|
||||
|
||||
// IP6TIP contains information for matching a packet's IP header.
|
||||
// It corresponds to struct ip6t_ip6 in
|
||||
// include/uapi/linux/netfilter_ipv6/ip6_tables.h.
|
||||
//
|
||||
// +marshal
|
||||
type IP6TIP struct {
|
||||
// Src is the source IP address.
|
||||
Src Inet6Addr
|
||||
|
||||
// Dst is the destination IP address.
|
||||
Dst Inet6Addr
|
||||
|
||||
// SrcMask is the source IP mask.
|
||||
SrcMask Inet6Addr
|
||||
|
||||
// DstMask is the destination IP mask.
|
||||
DstMask Inet6Addr
|
||||
|
||||
// InputInterface is the input network interface.
|
||||
InputInterface [IFNAMSIZ]byte
|
||||
|
||||
// OutputInterface is the output network interface.
|
||||
OutputInterface [IFNAMSIZ]byte
|
||||
|
||||
// InputInterfaceMask is the input interface mask.
|
||||
InputInterfaceMask [IFNAMSIZ]byte
|
||||
|
||||
// OuputInterfaceMask is the output interface mask.
|
||||
OutputInterfaceMask [IFNAMSIZ]byte
|
||||
|
||||
// Protocol is the transport protocol.
|
||||
Protocol uint16
|
||||
|
||||
// TOS matches TOS flags when Flags indicates filtering by TOS.
|
||||
TOS uint8
|
||||
|
||||
// Flags define matching behavior for the IP header.
|
||||
Flags uint8
|
||||
|
||||
// InverseFlags invert the meaning of fields in struct IPTIP. See the
|
||||
// IP6T_INV_* flags.
|
||||
InverseFlags uint8
|
||||
|
||||
// Linux defines in6_addr (Inet6Addr for us) as the union of a
|
||||
// 16-element byte array and a 4-element 32-bit integer array, so the
|
||||
// whole struct is 4-byte aligned.
|
||||
_ [3]byte
|
||||
}
|
||||
|
||||
const SizeOfIP6TIP = 136
|
||||
|
||||
// Flags in IP6TIP.InverseFlags. Corresponding constants are in
|
||||
// include/uapi/linux/netfilter_ipv6/ip6_tables.h.
|
||||
const (
|
||||
// Invert the meaning of InputInterface.
|
||||
IP6T_INV_VIA_IN = 0x01
|
||||
// Invert the meaning of OutputInterface.
|
||||
IP6T_INV_VIA_OUT = 0x02
|
||||
// Invert the meaning of TOS.
|
||||
IP6T_INV_TOS = 0x04
|
||||
// Invert the meaning of Src.
|
||||
IP6T_INV_SRCIP = 0x08
|
||||
// Invert the meaning of Dst.
|
||||
IP6T_INV_DSTIP = 0x10
|
||||
// Invert the meaning of the IPT_F_FRAG flag.
|
||||
IP6T_INV_FRAG = 0x20
|
||||
// Enable all flags.
|
||||
IP6T_INV_MASK = 0x7F
|
||||
)
|
||||
@@ -36,6 +36,9 @@ func TestSizes(t *testing.T) {
|
||||
{XTEntryTarget{}, SizeOfXTEntryTarget},
|
||||
{XTErrorTarget{}, SizeOfXTErrorTarget},
|
||||
{XTStandardTarget{}, SizeOfXTStandardTarget},
|
||||
{IP6TReplace{}, SizeOfIP6TReplace},
|
||||
{IP6TEntry{}, SizeOfIP6TEntry},
|
||||
{IP6TIP{}, SizeOfIP6TIP},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
||||
@@ -259,6 +259,11 @@ type InetMulticastRequestWithNIC struct {
|
||||
InterfaceIndex int32
|
||||
}
|
||||
|
||||
// Inet6Addr is struct in6_addr, from uapi/linux/in6.h.
|
||||
//
|
||||
// +marshal
|
||||
type Inet6Addr [16]byte
|
||||
|
||||
// SockAddrInet6 is struct sockaddr_in6, from uapi/linux/in6.h.
|
||||
type SockAddrInet6 struct {
|
||||
Family uint16
|
||||
|
||||
Reference in New Issue
Block a user