mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Merge pull request #1558 from kevinGC:iptables-write-input-drop
PiperOrigin-RevId: 290793754
This commit is contained in:
@@ -18,7 +18,6 @@ go_library(
|
||||
"//pkg/sentry/kernel",
|
||||
"//pkg/sentry/usermem",
|
||||
"//pkg/syserr",
|
||||
"//pkg/tcpip",
|
||||
"//pkg/tcpip/iptables",
|
||||
"//pkg/tcpip/stack",
|
||||
],
|
||||
|
||||
@@ -25,7 +25,6 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel"
|
||||
"gvisor.dev/gvisor/pkg/sentry/usermem"
|
||||
"gvisor.dev/gvisor/pkg/syserr"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/iptables"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
)
|
||||
@@ -45,7 +44,7 @@ type metadata struct {
|
||||
}
|
||||
|
||||
// GetInfo returns information about iptables.
|
||||
func GetInfo(t *kernel.Task, ep tcpip.Endpoint, outPtr usermem.Addr) (linux.IPTGetinfo, *syserr.Error) {
|
||||
func GetInfo(t *kernel.Task, stack *stack.Stack, outPtr usermem.Addr) (linux.IPTGetinfo, *syserr.Error) {
|
||||
// Read in the struct and table name.
|
||||
var info linux.IPTGetinfo
|
||||
if _, err := t.CopyIn(outPtr, &info); err != nil {
|
||||
@@ -53,7 +52,7 @@ func GetInfo(t *kernel.Task, ep tcpip.Endpoint, outPtr usermem.Addr) (linux.IPTG
|
||||
}
|
||||
|
||||
// Find the appropriate table.
|
||||
table, err := findTable(ep, info.Name)
|
||||
table, err := findTable(stack, info.Name)
|
||||
if err != nil {
|
||||
return linux.IPTGetinfo{}, err
|
||||
}
|
||||
@@ -76,7 +75,7 @@ func GetInfo(t *kernel.Task, ep tcpip.Endpoint, outPtr usermem.Addr) (linux.IPTG
|
||||
}
|
||||
|
||||
// GetEntries returns netstack's iptables rules encoded for the iptables tool.
|
||||
func GetEntries(t *kernel.Task, ep tcpip.Endpoint, outPtr usermem.Addr, outLen int) (linux.KernelIPTGetEntries, *syserr.Error) {
|
||||
func GetEntries(t *kernel.Task, stack *stack.Stack, outPtr usermem.Addr, outLen int) (linux.KernelIPTGetEntries, *syserr.Error) {
|
||||
// Read in the struct and table name.
|
||||
var userEntries linux.IPTGetEntries
|
||||
if _, err := t.CopyIn(outPtr, &userEntries); err != nil {
|
||||
@@ -84,7 +83,7 @@ func GetEntries(t *kernel.Task, ep tcpip.Endpoint, outPtr usermem.Addr, outLen i
|
||||
}
|
||||
|
||||
// Find the appropriate table.
|
||||
table, err := findTable(ep, userEntries.Name)
|
||||
table, err := findTable(stack, userEntries.Name)
|
||||
if err != nil {
|
||||
return linux.KernelIPTGetEntries{}, err
|
||||
}
|
||||
@@ -103,11 +102,8 @@ func GetEntries(t *kernel.Task, ep tcpip.Endpoint, outPtr usermem.Addr, outLen i
|
||||
return entries, nil
|
||||
}
|
||||
|
||||
func findTable(ep tcpip.Endpoint, tablename linux.TableName) (iptables.Table, *syserr.Error) {
|
||||
ipt, err := ep.IPTables()
|
||||
if err != nil {
|
||||
return iptables.Table{}, syserr.FromError(err)
|
||||
}
|
||||
func findTable(stack *stack.Stack, tablename linux.TableName) (iptables.Table, *syserr.Error) {
|
||||
ipt := stack.IPTables()
|
||||
table, ok := ipt.Tables[tablename.String()]
|
||||
if !ok {
|
||||
return iptables.Table{}, syserr.ErrInvalidArgument
|
||||
@@ -348,7 +344,7 @@ func SetEntries(stack *stack.Stack, optVal []byte) *syserr.Error {
|
||||
// Go through the list of supported hooks for this table and, for each
|
||||
// one, set the rule it corresponds to.
|
||||
for hook, _ := range replace.HookEntry {
|
||||
if table.ValidHooks()&uint32(hook) != 0 {
|
||||
if table.ValidHooks()&(1<<hook) != 0 {
|
||||
hk := hookFromLinux(hook)
|
||||
for ruleIdx, offset := range offsets {
|
||||
if offset == replace.HookEntry[hook] {
|
||||
@@ -369,6 +365,23 @@ func SetEntries(stack *stack.Stack, optVal []byte) *syserr.Error {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(gvisor.dev/issue/170): Support other chains.
|
||||
// Since we only support modifying the INPUT chain right now, make sure
|
||||
// all other chains point to ACCEPT rules.
|
||||
for hook, ruleIdx := range table.BuiltinChains {
|
||||
if hook != iptables.Input {
|
||||
if _, ok := table.Rules[ruleIdx].Target.(iptables.UnconditionalAcceptTarget); !ok {
|
||||
log.Warningf("Hook %d is unsupported.", hook)
|
||||
return syserr.ErrInvalidArgument
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(gvisor.dev/issue/170): Check the following conditions:
|
||||
// - There are no loops.
|
||||
// - There are no chains without an unconditional final rule.
|
||||
// - There are no chains without an unconditional underflow rule.
|
||||
|
||||
ipt := stack.IPTables()
|
||||
table.SetMetadata(metadata{
|
||||
HookEntry: replace.HookEntry,
|
||||
@@ -411,10 +424,7 @@ func parseTarget(optVal []byte) (iptables.Target, uint32, *syserr.Error) {
|
||||
case iptables.Accept:
|
||||
return iptables.UnconditionalAcceptTarget{}, linux.SizeOfXTStandardTarget, nil
|
||||
case iptables.Drop:
|
||||
// TODO(gvisor.dev/issue/170): Return an
|
||||
// iptables.UnconditionalDropTarget to support DROP.
|
||||
log.Infof("netfilter DROP is not supported yet.")
|
||||
return nil, 0, syserr.ErrInvalidArgument
|
||||
return iptables.UnconditionalDropTarget{}, linux.SizeOfXTStandardTarget, nil
|
||||
default:
|
||||
panic(fmt.Sprintf("Unknown verdict: %v", verdict))
|
||||
}
|
||||
|
||||
@@ -868,7 +868,11 @@ func (s *SocketOperations) GetSockOpt(t *kernel.Task, level, name int, outPtr us
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
info, err := netfilter.GetInfo(t, s.Endpoint, outPtr)
|
||||
stack := inet.StackFromContext(t)
|
||||
if stack == nil {
|
||||
return nil, syserr.ErrNoDevice
|
||||
}
|
||||
info, err := netfilter.GetInfo(t, stack.(*Stack).Stack, outPtr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -879,7 +883,11 @@ func (s *SocketOperations) GetSockOpt(t *kernel.Task, level, name int, outPtr us
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
entries, err := netfilter.GetEntries(t, s.Endpoint, outPtr, outLen)
|
||||
stack := inet.StackFromContext(t)
|
||||
if stack == nil {
|
||||
return nil, syserr.ErrNoDevice
|
||||
}
|
||||
entries, err := netfilter.GetEntries(t, stack.(*Stack).Stack, outPtr, outLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/sync",
|
||||
"//pkg/tcpip/buffer",
|
||||
"//pkg/tcpip/iptables",
|
||||
"//pkg/waiter",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -13,6 +13,6 @@ go_library(
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/log",
|
||||
"//pkg/tcpip/buffer",
|
||||
"//pkg/tcpip",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
// tool.
|
||||
package iptables
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
)
|
||||
|
||||
// Table names.
|
||||
const (
|
||||
TablenameNat = "nat"
|
||||
@@ -127,3 +133,72 @@ func EmptyFilterTable() Table {
|
||||
UserChains: map[string]int{},
|
||||
}
|
||||
}
|
||||
|
||||
// Check runs pkt through the rules for hook. It returns true when the packet
|
||||
// should continue traversing the network stack and false when it should be
|
||||
// dropped.
|
||||
func (it *IPTables) Check(hook Hook, pkt tcpip.PacketBuffer) bool {
|
||||
// TODO(gvisor.dev/issue/170): A lot of this is uncomplicated because
|
||||
// we're missing features. Jumps, the call stack, etc. aren't checked
|
||||
// for yet because we're yet to support them.
|
||||
|
||||
// Go through each table containing the hook.
|
||||
for _, tablename := range it.Priorities[hook] {
|
||||
switch verdict := it.checkTable(hook, pkt, tablename); verdict {
|
||||
// If the table returns Accept, move on to the next table.
|
||||
case Accept:
|
||||
continue
|
||||
// The Drop verdict is final.
|
||||
case Drop:
|
||||
return false
|
||||
case Stolen, Queue, Repeat, None, Jump, Return, Continue:
|
||||
panic(fmt.Sprintf("Unimplemented verdict %v.", verdict))
|
||||
default:
|
||||
panic(fmt.Sprintf("Unknown verdict %v.", verdict))
|
||||
}
|
||||
}
|
||||
|
||||
// Every table returned Accept.
|
||||
return true
|
||||
}
|
||||
|
||||
func (it *IPTables) checkTable(hook Hook, pkt tcpip.PacketBuffer, tablename string) Verdict {
|
||||
// Start from ruleIdx and walk the list of rules until a rule gives us
|
||||
// a verdict.
|
||||
table := it.Tables[tablename]
|
||||
for ruleIdx := table.BuiltinChains[hook]; ruleIdx < len(table.Rules); ruleIdx++ {
|
||||
switch verdict := it.checkRule(hook, pkt, table, ruleIdx); verdict {
|
||||
// In either of these cases, this table is done with the packet.
|
||||
case Accept, Drop:
|
||||
return verdict
|
||||
// Continue traversing the rules of the table.
|
||||
case Continue:
|
||||
continue
|
||||
case Stolen, Queue, Repeat, None, Jump, Return:
|
||||
panic(fmt.Sprintf("Unimplemented verdict %v.", verdict))
|
||||
default:
|
||||
panic(fmt.Sprintf("Unknown verdict %v.", verdict))
|
||||
}
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Traversed past the entire list of iptables rules in table %q.", tablename))
|
||||
}
|
||||
|
||||
func (it *IPTables) checkRule(hook Hook, pkt tcpip.PacketBuffer, table Table, ruleIdx int) Verdict {
|
||||
rule := table.Rules[ruleIdx]
|
||||
// Go through each rule matcher. If they all match, run
|
||||
// the rule target.
|
||||
for _, matcher := range rule.Matchers {
|
||||
matches, hotdrop := matcher.Match(hook, pkt, "")
|
||||
if hotdrop {
|
||||
return Drop
|
||||
}
|
||||
if !matches {
|
||||
return Continue
|
||||
}
|
||||
}
|
||||
|
||||
// All the matchers matched, so run the target.
|
||||
verdict, _ := rule.Target.Action(pkt)
|
||||
return verdict
|
||||
}
|
||||
|
||||
@@ -18,14 +18,14 @@ package iptables
|
||||
|
||||
import (
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/buffer"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
)
|
||||
|
||||
// UnconditionalAcceptTarget accepts all packets.
|
||||
type UnconditionalAcceptTarget struct{}
|
||||
|
||||
// Action implements Target.Action.
|
||||
func (UnconditionalAcceptTarget) Action(packet buffer.VectorisedView) (Verdict, string) {
|
||||
func (UnconditionalAcceptTarget) Action(packet tcpip.PacketBuffer) (Verdict, string) {
|
||||
return Accept, ""
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ func (UnconditionalAcceptTarget) Action(packet buffer.VectorisedView) (Verdict,
|
||||
type UnconditionalDropTarget struct{}
|
||||
|
||||
// Action implements Target.Action.
|
||||
func (UnconditionalDropTarget) Action(packet buffer.VectorisedView) (Verdict, string) {
|
||||
func (UnconditionalDropTarget) Action(packet tcpip.PacketBuffer) (Verdict, string) {
|
||||
return Drop, ""
|
||||
}
|
||||
|
||||
@@ -42,8 +42,7 @@ func (UnconditionalDropTarget) Action(packet buffer.VectorisedView) (Verdict, st
|
||||
type ErrorTarget struct{}
|
||||
|
||||
// Action implements Target.Action.
|
||||
func (ErrorTarget) Action(packet buffer.VectorisedView) (Verdict, string) {
|
||||
func (ErrorTarget) Action(packet tcpip.PacketBuffer) (Verdict, string) {
|
||||
log.Warningf("ErrorTarget triggered.")
|
||||
return Drop, ""
|
||||
|
||||
}
|
||||
|
||||
@@ -14,9 +14,7 @@
|
||||
|
||||
package iptables
|
||||
|
||||
import (
|
||||
"gvisor.dev/gvisor/pkg/tcpip/buffer"
|
||||
)
|
||||
import "gvisor.dev/gvisor/pkg/tcpip"
|
||||
|
||||
// A Hook specifies one of the hooks built into the network stack.
|
||||
//
|
||||
@@ -165,7 +163,7 @@ type Matcher interface {
|
||||
// Match returns whether the packet matches and whether the packet
|
||||
// should be "hotdropped", i.e. dropped immediately. This is usually
|
||||
// used for suspicious packets.
|
||||
Match(hook Hook, packet buffer.VectorisedView, interfaceName string) (matches bool, hotdrop bool)
|
||||
Match(hook Hook, packet tcpip.PacketBuffer, interfaceName string) (matches bool, hotdrop bool)
|
||||
}
|
||||
|
||||
// A Target is the interface for taking an action for a packet.
|
||||
@@ -173,5 +171,5 @@ type Target interface {
|
||||
// Action takes an action on the packet and returns a verdict on how
|
||||
// traversal should (or should not) continue. If the return value is
|
||||
// Jump, it also returns the name of the chain to jump to.
|
||||
Action(packet buffer.VectorisedView) (Verdict, string)
|
||||
Action(packet tcpip.PacketBuffer) (Verdict, string)
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ func (*protocol) ParseAddresses(v buffer.View) (src, dst tcpip.Address) {
|
||||
return tcpip.Address(h.ProtocolAddressSender()), ProtocolAddress
|
||||
}
|
||||
|
||||
func (p *protocol) NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, sender stack.LinkEndpoint) (stack.NetworkEndpoint, *tcpip.Error) {
|
||||
func (p *protocol) NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, sender stack.LinkEndpoint, st *stack.Stack) (stack.NetworkEndpoint, *tcpip.Error) {
|
||||
if addrWithPrefix.Address != ProtocolAddress {
|
||||
return nil, tcpip.ErrBadLocalAddress
|
||||
}
|
||||
|
||||
@@ -212,10 +212,17 @@ func buildIPv6Route(local, remote tcpip.Address) (stack.Route, *tcpip.Error) {
|
||||
return s.FindRoute(1, local, remote, ipv6.ProtocolNumber, false /* multicastLoop */)
|
||||
}
|
||||
|
||||
func buildDummyStack() *stack.Stack {
|
||||
return stack.New(stack.Options{
|
||||
NetworkProtocols: []stack.NetworkProtocol{ipv6.NewProtocol()},
|
||||
TransportProtocols: []stack.TransportProtocol{udp.NewProtocol(), tcp.NewProtocol()},
|
||||
})
|
||||
}
|
||||
|
||||
func TestIPv4Send(t *testing.T) {
|
||||
o := testObject{t: t, v4: true}
|
||||
proto := ipv4.NewProtocol()
|
||||
ep, err := proto.NewEndpoint(1, tcpip.AddressWithPrefix{localIpv4Addr, localIpv4PrefixLen}, nil, nil, &o)
|
||||
ep, err := proto.NewEndpoint(1, tcpip.AddressWithPrefix{localIpv4Addr, localIpv4PrefixLen}, nil, nil, &o, buildDummyStack())
|
||||
if err != nil {
|
||||
t.Fatalf("NewEndpoint failed: %v", err)
|
||||
}
|
||||
@@ -250,7 +257,7 @@ func TestIPv4Send(t *testing.T) {
|
||||
func TestIPv4Receive(t *testing.T) {
|
||||
o := testObject{t: t, v4: true}
|
||||
proto := ipv4.NewProtocol()
|
||||
ep, err := proto.NewEndpoint(1, tcpip.AddressWithPrefix{localIpv4Addr, localIpv4PrefixLen}, nil, &o, nil)
|
||||
ep, err := proto.NewEndpoint(1, tcpip.AddressWithPrefix{localIpv4Addr, localIpv4PrefixLen}, nil, &o, nil, buildDummyStack())
|
||||
if err != nil {
|
||||
t.Fatalf("NewEndpoint failed: %v", err)
|
||||
}
|
||||
@@ -318,7 +325,7 @@ func TestIPv4ReceiveControl(t *testing.T) {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
o := testObject{t: t}
|
||||
proto := ipv4.NewProtocol()
|
||||
ep, err := proto.NewEndpoint(1, tcpip.AddressWithPrefix{localIpv4Addr, localIpv4PrefixLen}, nil, &o, nil)
|
||||
ep, err := proto.NewEndpoint(1, tcpip.AddressWithPrefix{localIpv4Addr, localIpv4PrefixLen}, nil, &o, nil, buildDummyStack())
|
||||
if err != nil {
|
||||
t.Fatalf("NewEndpoint failed: %v", err)
|
||||
}
|
||||
@@ -385,7 +392,7 @@ func TestIPv4ReceiveControl(t *testing.T) {
|
||||
func TestIPv4FragmentationReceive(t *testing.T) {
|
||||
o := testObject{t: t, v4: true}
|
||||
proto := ipv4.NewProtocol()
|
||||
ep, err := proto.NewEndpoint(1, tcpip.AddressWithPrefix{localIpv4Addr, localIpv4PrefixLen}, nil, &o, nil)
|
||||
ep, err := proto.NewEndpoint(1, tcpip.AddressWithPrefix{localIpv4Addr, localIpv4PrefixLen}, nil, &o, nil, buildDummyStack())
|
||||
if err != nil {
|
||||
t.Fatalf("NewEndpoint failed: %v", err)
|
||||
}
|
||||
@@ -456,7 +463,7 @@ func TestIPv4FragmentationReceive(t *testing.T) {
|
||||
func TestIPv6Send(t *testing.T) {
|
||||
o := testObject{t: t}
|
||||
proto := ipv6.NewProtocol()
|
||||
ep, err := proto.NewEndpoint(1, tcpip.AddressWithPrefix{localIpv6Addr, localIpv6PrefixLen}, nil, nil, &o)
|
||||
ep, err := proto.NewEndpoint(1, tcpip.AddressWithPrefix{localIpv6Addr, localIpv6PrefixLen}, nil, nil, &o, buildDummyStack())
|
||||
if err != nil {
|
||||
t.Fatalf("NewEndpoint failed: %v", err)
|
||||
}
|
||||
@@ -491,7 +498,7 @@ func TestIPv6Send(t *testing.T) {
|
||||
func TestIPv6Receive(t *testing.T) {
|
||||
o := testObject{t: t}
|
||||
proto := ipv6.NewProtocol()
|
||||
ep, err := proto.NewEndpoint(1, tcpip.AddressWithPrefix{localIpv6Addr, localIpv6PrefixLen}, nil, &o, nil)
|
||||
ep, err := proto.NewEndpoint(1, tcpip.AddressWithPrefix{localIpv6Addr, localIpv6PrefixLen}, nil, &o, nil, buildDummyStack())
|
||||
if err != nil {
|
||||
t.Fatalf("NewEndpoint failed: %v", err)
|
||||
}
|
||||
@@ -568,7 +575,7 @@ func TestIPv6ReceiveControl(t *testing.T) {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
o := testObject{t: t}
|
||||
proto := ipv6.NewProtocol()
|
||||
ep, err := proto.NewEndpoint(1, tcpip.AddressWithPrefix{localIpv6Addr, localIpv6PrefixLen}, nil, &o, nil)
|
||||
ep, err := proto.NewEndpoint(1, tcpip.AddressWithPrefix{localIpv6Addr, localIpv6PrefixLen}, nil, &o, nil, buildDummyStack())
|
||||
if err != nil {
|
||||
t.Fatalf("NewEndpoint failed: %v", err)
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ go_library(
|
||||
"//pkg/tcpip",
|
||||
"//pkg/tcpip/buffer",
|
||||
"//pkg/tcpip/header",
|
||||
"//pkg/tcpip/iptables",
|
||||
"//pkg/tcpip/network/fragmentation",
|
||||
"//pkg/tcpip/network/hash",
|
||||
"//pkg/tcpip/stack",
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/buffer"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/header"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/iptables"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/network/fragmentation"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/network/hash"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
@@ -54,10 +55,11 @@ type endpoint struct {
|
||||
dispatcher stack.TransportDispatcher
|
||||
fragmentation *fragmentation.Fragmentation
|
||||
protocol *protocol
|
||||
stack *stack.Stack
|
||||
}
|
||||
|
||||
// NewEndpoint creates a new ipv4 endpoint.
|
||||
func (p *protocol) NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, linkEP stack.LinkEndpoint) (stack.NetworkEndpoint, *tcpip.Error) {
|
||||
func (p *protocol) NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, linkEP stack.LinkEndpoint, st *stack.Stack) (stack.NetworkEndpoint, *tcpip.Error) {
|
||||
e := &endpoint{
|
||||
nicID: nicID,
|
||||
id: stack.NetworkEndpointID{LocalAddress: addrWithPrefix.Address},
|
||||
@@ -66,6 +68,7 @@ func (p *protocol) NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWi
|
||||
dispatcher: dispatcher,
|
||||
fragmentation: fragmentation.NewFragmentation(fragmentation.HighFragThreshold, fragmentation.LowFragThreshold, fragmentation.DefaultReassembleTimeout),
|
||||
protocol: p,
|
||||
stack: st,
|
||||
}
|
||||
|
||||
return e, nil
|
||||
@@ -350,6 +353,13 @@ func (e *endpoint) HandlePacket(r *stack.Route, pkt tcpip.PacketBuffer) {
|
||||
}
|
||||
pkt.NetworkHeader = headerView[:h.HeaderLength()]
|
||||
|
||||
// iptables filtering.
|
||||
ipt := e.stack.IPTables()
|
||||
if ok := ipt.Check(iptables.Input, pkt); !ok {
|
||||
// iptables is telling us to drop the packet.
|
||||
return
|
||||
}
|
||||
|
||||
hlen := int(h.HeaderLength())
|
||||
tlen := int(h.TotalLength())
|
||||
pkt.Data.TrimFront(hlen)
|
||||
|
||||
@@ -109,7 +109,7 @@ func TestICMPCounts(t *testing.T) {
|
||||
if netProto == nil {
|
||||
t.Fatalf("cannot find protocol instance for network protocol %d", ProtocolNumber)
|
||||
}
|
||||
ep, err := netProto.NewEndpoint(0, tcpip.AddressWithPrefix{lladdr1, netProto.DefaultPrefixLen()}, &stubLinkAddressCache{}, &stubDispatcher{}, nil)
|
||||
ep, err := netProto.NewEndpoint(0, tcpip.AddressWithPrefix{lladdr1, netProto.DefaultPrefixLen()}, &stubLinkAddressCache{}, &stubDispatcher{}, nil, s)
|
||||
if err != nil {
|
||||
t.Fatalf("NewEndpoint(_) = _, %s, want = _, nil", err)
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ func (*protocol) ParseAddresses(v buffer.View) (src, dst tcpip.Address) {
|
||||
}
|
||||
|
||||
// NewEndpoint creates a new ipv6 endpoint.
|
||||
func (p *protocol) NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, linkEP stack.LinkEndpoint) (stack.NetworkEndpoint, *tcpip.Error) {
|
||||
func (p *protocol) NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, linkEP stack.LinkEndpoint, st *stack.Stack) (stack.NetworkEndpoint, *tcpip.Error) {
|
||||
return &endpoint{
|
||||
nicID: nicID,
|
||||
id: stack.NetworkEndpointID{LocalAddress: addrWithPrefix.Address},
|
||||
|
||||
@@ -62,7 +62,7 @@ func setupStackAndEndpoint(t *testing.T, llladdr, rlladdr tcpip.Address) (*stack
|
||||
t.Fatalf("cannot find protocol instance for network protocol %d", ProtocolNumber)
|
||||
}
|
||||
|
||||
ep, err := netProto.NewEndpoint(0, tcpip.AddressWithPrefix{rlladdr, netProto.DefaultPrefixLen()}, &stubLinkAddressCache{}, &stubDispatcher{}, nil)
|
||||
ep, err := netProto.NewEndpoint(0, tcpip.AddressWithPrefix{rlladdr, netProto.DefaultPrefixLen()}, &stubLinkAddressCache{}, &stubDispatcher{}, nil, s)
|
||||
if err != nil {
|
||||
t.Fatalf("NewEndpoint(_) = _, %s, want = _, nil", err)
|
||||
}
|
||||
|
||||
@@ -598,7 +598,7 @@ func (n *NIC) addAddressLocked(protocolAddress tcpip.ProtocolAddress, peb Primar
|
||||
}
|
||||
|
||||
// Create the new network endpoint.
|
||||
ep, err := netProto.NewEndpoint(n.id, protocolAddress.AddressWithPrefix, n.stack, n, n.linkEP)
|
||||
ep, err := netProto.NewEndpoint(n.id, protocolAddress.AddressWithPrefix, n.stack, n, n.linkEP, n.stack)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -282,7 +282,7 @@ type NetworkProtocol interface {
|
||||
ParseAddresses(v buffer.View) (src, dst tcpip.Address)
|
||||
|
||||
// NewEndpoint creates a new endpoint of this protocol.
|
||||
NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache LinkAddressCache, dispatcher TransportDispatcher, sender LinkEndpoint) (NetworkEndpoint, *tcpip.Error)
|
||||
NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache LinkAddressCache, dispatcher TransportDispatcher, sender LinkEndpoint, st *Stack) (NetworkEndpoint, *tcpip.Error)
|
||||
|
||||
// SetOption allows enabling/disabling protocol specific features.
|
||||
// SetOption returns an error if the option is not supported or the
|
||||
|
||||
@@ -423,7 +423,11 @@ type Stack struct {
|
||||
// handleLocal allows non-loopback interfaces to loop packets.
|
||||
handleLocal bool
|
||||
|
||||
// tables are the iptables packet filtering and manipulation rules.
|
||||
// tablesMu protects iptables.
|
||||
tablesMu sync.RWMutex
|
||||
|
||||
// tables are the iptables packet filtering and manipulation rules. The are
|
||||
// protected by tablesMu.`
|
||||
tables iptables.IPTables
|
||||
|
||||
// resumableEndpoints is a list of endpoints that need to be resumed if the
|
||||
@@ -1594,12 +1598,17 @@ func (s *Stack) LeaveGroup(protocol tcpip.NetworkProtocolNumber, nicID tcpip.NIC
|
||||
|
||||
// IPTables returns the stack's iptables.
|
||||
func (s *Stack) IPTables() iptables.IPTables {
|
||||
return s.tables
|
||||
s.tablesMu.RLock()
|
||||
t := s.tables
|
||||
s.tablesMu.RUnlock()
|
||||
return t
|
||||
}
|
||||
|
||||
// SetIPTables sets the stack's iptables.
|
||||
func (s *Stack) SetIPTables(ipt iptables.IPTables) {
|
||||
s.tablesMu.Lock()
|
||||
s.tables = ipt
|
||||
s.tablesMu.Unlock()
|
||||
}
|
||||
|
||||
// ICMPLimit returns the maximum number of ICMP messages that can be sent
|
||||
|
||||
@@ -201,7 +201,7 @@ func (*fakeNetworkProtocol) ParseAddresses(v buffer.View) (src, dst tcpip.Addres
|
||||
return tcpip.Address(v[1:2]), tcpip.Address(v[0:1])
|
||||
}
|
||||
|
||||
func (f *fakeNetworkProtocol) NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, ep stack.LinkEndpoint) (stack.NetworkEndpoint, *tcpip.Error) {
|
||||
func (f *fakeNetworkProtocol) NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, ep stack.LinkEndpoint, _ *stack.Stack) (stack.NetworkEndpoint, *tcpip.Error) {
|
||||
return &fakeNetworkEndpoint{
|
||||
nicID: nicID,
|
||||
id: stack.NetworkEndpointID{LocalAddress: addrWithPrefix.Address},
|
||||
|
||||
@@ -40,7 +40,6 @@ import (
|
||||
|
||||
"gvisor.dev/gvisor/pkg/sync"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/buffer"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/iptables"
|
||||
"gvisor.dev/gvisor/pkg/waiter"
|
||||
)
|
||||
|
||||
@@ -454,9 +453,6 @@ type Endpoint interface {
|
||||
// NOTE: This method is a no-op for sockets other than TCP.
|
||||
ModerateRecvBuf(copied int)
|
||||
|
||||
// IPTables returns the iptables for this endpoint's stack.
|
||||
IPTables() (iptables.IPTables, error)
|
||||
|
||||
// Info returns a copy to the transport endpoint info.
|
||||
Info() EndpointInfo
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user