mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Merge pull request #3651 from ianlewis:ip-forwarding
PiperOrigin-RevId: 332760843
This commit is contained in:
@@ -50,6 +50,7 @@ go_library(
|
||||
"//pkg/sync",
|
||||
"//pkg/syserror",
|
||||
"//pkg/tcpip/header",
|
||||
"//pkg/tcpip/network/ipv4",
|
||||
"//pkg/usermem",
|
||||
"//pkg/waiter",
|
||||
],
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs/ramfs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/inet"
|
||||
"gvisor.dev/gvisor/pkg/sync"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
"gvisor.dev/gvisor/pkg/waiter"
|
||||
)
|
||||
@@ -54,7 +55,7 @@ type tcpMemInode struct {
|
||||
|
||||
// size stores the tcp buffer size during save, and sets the buffer
|
||||
// size in netstack in restore. We must save/restore this here, since
|
||||
// netstack itself is stateless.
|
||||
// a netstack instance is created on restore.
|
||||
size inet.TCPBufferSize
|
||||
|
||||
// mu protects against concurrent reads/writes to files based on this
|
||||
@@ -258,6 +259,9 @@ func (f *tcpSackFile) Write(ctx context.Context, _ *fs.File, src usermem.IOSeque
|
||||
if src.NumBytes() == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// Only consider size of one memory page for input for performance reasons.
|
||||
// We are only reading if it's zero or not anyway.
|
||||
src = src.TakeFirst(usermem.PageSize - 1)
|
||||
|
||||
var v int32
|
||||
@@ -383,11 +387,125 @@ func (p *proc) newSysNetCore(ctx context.Context, msrc *fs.MountSource, s inet.S
|
||||
return newProcInode(ctx, d, msrc, fs.SpecialDirectory, nil)
|
||||
}
|
||||
|
||||
// ipForwarding implements fs.InodeOperations.
|
||||
//
|
||||
// ipForwarding is used to enable/disable packet forwarding of netstack.
|
||||
//
|
||||
// +stateify savable
|
||||
type ipForwarding struct {
|
||||
fsutil.SimpleFileInode
|
||||
|
||||
stack inet.Stack `state:"wait"`
|
||||
|
||||
// enabled stores the IPv4 forwarding state on save.
|
||||
// We must save/restore this here, since a netstack instance
|
||||
// is created on restore.
|
||||
enabled *bool
|
||||
}
|
||||
|
||||
func newIPForwardingInode(ctx context.Context, msrc *fs.MountSource, s inet.Stack) *fs.Inode {
|
||||
ipf := &ipForwarding{
|
||||
SimpleFileInode: *fsutil.NewSimpleFileInode(ctx, fs.RootOwner, fs.FilePermsFromMode(0444), linux.PROC_SUPER_MAGIC),
|
||||
stack: s,
|
||||
}
|
||||
sattr := fs.StableAttr{
|
||||
DeviceID: device.ProcDevice.DeviceID(),
|
||||
InodeID: device.ProcDevice.NextIno(),
|
||||
BlockSize: usermem.PageSize,
|
||||
Type: fs.SpecialFile,
|
||||
}
|
||||
return fs.NewInode(ctx, ipf, msrc, sattr)
|
||||
}
|
||||
|
||||
// Truncate implements fs.InodeOperations.Truncate. Truncate is called when
|
||||
// O_TRUNC is specified for any kind of existing Dirent but is not called via
|
||||
// (f)truncate for proc files.
|
||||
func (*ipForwarding) Truncate(context.Context, *fs.Inode, int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type ipForwardingFile struct {
|
||||
fsutil.FileGenericSeek `state:"nosave"`
|
||||
fsutil.FileNoIoctl `state:"nosave"`
|
||||
fsutil.FileNoMMap `state:"nosave"`
|
||||
fsutil.FileNoSplice `state:"nosave"`
|
||||
fsutil.FileNoopFlush `state:"nosave"`
|
||||
fsutil.FileNoopFsync `state:"nosave"`
|
||||
fsutil.FileNoopRelease `state:"nosave"`
|
||||
fsutil.FileNotDirReaddir `state:"nosave"`
|
||||
fsutil.FileUseInodeUnstableAttr `state:"nosave"`
|
||||
waiter.AlwaysReady `state:"nosave"`
|
||||
|
||||
ipf *ipForwarding
|
||||
|
||||
stack inet.Stack `state:"wait"`
|
||||
}
|
||||
|
||||
// GetFile implements fs.InodeOperations.GetFile.
|
||||
func (ipf *ipForwarding) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
|
||||
flags.Pread = true
|
||||
flags.Pwrite = true
|
||||
return fs.NewFile(ctx, dirent, flags, &ipForwardingFile{
|
||||
stack: ipf.stack,
|
||||
ipf: ipf,
|
||||
}), nil
|
||||
}
|
||||
|
||||
// Read implements fs.FileOperations.Read.
|
||||
func (f *ipForwardingFile) Read(ctx context.Context, _ *fs.File, dst usermem.IOSequence, offset int64) (int64, error) {
|
||||
if offset != 0 {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
if f.ipf.enabled == nil {
|
||||
enabled := f.stack.Forwarding(ipv4.ProtocolNumber)
|
||||
f.ipf.enabled = &enabled
|
||||
}
|
||||
|
||||
val := "0\n"
|
||||
if *f.ipf.enabled {
|
||||
// Technically, this is not quite compatible with Linux. Linux
|
||||
// stores these as an integer, so if you write "2" into
|
||||
// ip_forward, you should get 2 back.
|
||||
val = "1\n"
|
||||
}
|
||||
n, err := dst.CopyOut(ctx, []byte(val))
|
||||
return int64(n), err
|
||||
}
|
||||
|
||||
// Write implements fs.FileOperations.Write.
|
||||
//
|
||||
// Offset is ignored, multiple writes are not supported.
|
||||
func (f *ipForwardingFile) Write(ctx context.Context, _ *fs.File, src usermem.IOSequence, offset int64) (int64, error) {
|
||||
if src.NumBytes() == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// Only consider size of one memory page for input for performance reasons.
|
||||
// We are only reading if it's zero or not anyway.
|
||||
src = src.TakeFirst(usermem.PageSize - 1)
|
||||
|
||||
var v int32
|
||||
n, err := usermem.CopyInt32StringInVec(ctx, src.IO, src.Addrs, &v, src.Opts)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
if f.ipf.enabled == nil {
|
||||
f.ipf.enabled = new(bool)
|
||||
}
|
||||
*f.ipf.enabled = v != 0
|
||||
return n, f.stack.SetForwarding(ipv4.ProtocolNumber, *f.ipf.enabled)
|
||||
}
|
||||
|
||||
func (p *proc) newSysNetIPv4Dir(ctx context.Context, msrc *fs.MountSource, s inet.Stack) *fs.Inode {
|
||||
contents := map[string]*fs.Inode{
|
||||
// Add tcp_sack.
|
||||
"tcp_sack": newTCPSackInode(ctx, msrc, s),
|
||||
|
||||
// Add ip_forward.
|
||||
"ip_forward": newIPForwardingInode(ctx, msrc, s),
|
||||
|
||||
// The following files are simple stubs until they are
|
||||
// implemented in netstack, most of these files are
|
||||
// configuration related. We use the value closest to the
|
||||
|
||||
@@ -14,7 +14,11 @@
|
||||
|
||||
package proc
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
|
||||
)
|
||||
|
||||
// beforeSave is invoked by stateify.
|
||||
func (t *tcpMemInode) beforeSave() {
|
||||
@@ -40,3 +44,12 @@ func (s *tcpSack) afterLoad() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// afterLoad is invoked by stateify.
|
||||
func (ipf *ipForwarding) afterLoad() {
|
||||
if ipf.enabled != nil {
|
||||
if err := ipf.stack.SetForwarding(ipv4.ProtocolNumber, *ipf.enabled); err != nil {
|
||||
panic(fmt.Sprintf("failed to set IPv4 forwarding [%v]: %v", *ipf.enabled, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,3 +123,76 @@ func TestConfigureRecvBufferSize(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestIPForwarding tests the implementation of
|
||||
// /proc/sys/net/ipv4/ip_forwarding
|
||||
func TestIPForwarding(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
s := inet.NewTestStack()
|
||||
|
||||
var cases = []struct {
|
||||
comment string
|
||||
initial bool
|
||||
str string
|
||||
final bool
|
||||
}{
|
||||
{
|
||||
comment: `Forwarding is disabled; write 1 and enable forwarding`,
|
||||
initial: false,
|
||||
str: "1",
|
||||
final: true,
|
||||
},
|
||||
{
|
||||
comment: `Forwarding is disabled; write 0 and disable forwarding`,
|
||||
initial: false,
|
||||
str: "0",
|
||||
final: false,
|
||||
},
|
||||
{
|
||||
comment: `Forwarding is enabled; write 1 and enable forwarding`,
|
||||
initial: true,
|
||||
str: "1",
|
||||
final: true,
|
||||
},
|
||||
{
|
||||
comment: `Forwarding is enabled; write 0 and disable forwarding`,
|
||||
initial: true,
|
||||
str: "0",
|
||||
final: false,
|
||||
},
|
||||
{
|
||||
comment: `Forwarding is disabled; write 2404 and enable forwarding`,
|
||||
initial: false,
|
||||
str: "2404",
|
||||
final: true,
|
||||
},
|
||||
{
|
||||
comment: `Forwarding is enabled; write 2404 and enable forwarding`,
|
||||
initial: true,
|
||||
str: "2404",
|
||||
final: true,
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.comment, func(t *testing.T) {
|
||||
s.IPForwarding = c.initial
|
||||
ipf := &ipForwarding{stack: s}
|
||||
file := &ipForwardingFile{
|
||||
stack: s,
|
||||
ipf: ipf,
|
||||
}
|
||||
|
||||
// Write the values.
|
||||
src := usermem.BytesIOSequence([]byte(c.str))
|
||||
if n, err := file.Write(ctx, nil, src, 0); n != int64(len(c.str)) || err != nil {
|
||||
t.Errorf("file.Write(ctx, nil, %q, 0) = (%d, %v); want (%d, nil)", c.str, n, err, len(c.str))
|
||||
}
|
||||
|
||||
// Read the values from the stack and check them.
|
||||
if got, want := s.IPForwarding, c.final; got != want {
|
||||
t.Errorf("s.IPForwarding incorrect; got: %v, want: %v", got, want)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +100,7 @@ go_library(
|
||||
"//pkg/sync",
|
||||
"//pkg/syserror",
|
||||
"//pkg/tcpip/header",
|
||||
"//pkg/tcpip/network/ipv4",
|
||||
"//pkg/usermem",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/sentry/vfs"
|
||||
"gvisor.dev/gvisor/pkg/sync"
|
||||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
)
|
||||
|
||||
@@ -67,6 +68,7 @@ func (fs *filesystem) newSysNetDir(root *auth.Credentials, k *kernel.Kernel) *ke
|
||||
"tcp_rmem": fs.newDentry(root, fs.NextIno(), 0644, &tcpMemData{stack: stack, dir: tcpRMem}),
|
||||
"tcp_sack": fs.newDentry(root, fs.NextIno(), 0644, &tcpSackData{stack: stack}),
|
||||
"tcp_wmem": fs.newDentry(root, fs.NextIno(), 0644, &tcpMemData{stack: stack, dir: tcpWMem}),
|
||||
"ip_forward": fs.newDentry(root, fs.NextIno(), 0444, &ipForwarding{stack: stack}),
|
||||
|
||||
// The following files are simple stubs until they are implemented in
|
||||
// netstack, most of these files are configuration related. We use the
|
||||
@@ -354,3 +356,63 @@ func (d *tcpMemData) writeSizeLocked(size inet.TCPBufferSize) error {
|
||||
panic(fmt.Sprintf("unknown tcpMemFile type: %v", d.dir))
|
||||
}
|
||||
}
|
||||
|
||||
// ipForwarding implements vfs.WritableDynamicBytesSource for
|
||||
// /proc/sys/net/ipv4/ip_forwarding.
|
||||
//
|
||||
// +stateify savable
|
||||
type ipForwarding struct {
|
||||
kernfs.DynamicBytesFile
|
||||
|
||||
stack inet.Stack `state:"wait"`
|
||||
enabled *bool
|
||||
}
|
||||
|
||||
var _ vfs.WritableDynamicBytesSource = (*ipForwarding)(nil)
|
||||
|
||||
// Generate implements vfs.DynamicBytesSource.Generate.
|
||||
func (ipf *ipForwarding) Generate(ctx context.Context, buf *bytes.Buffer) error {
|
||||
if ipf.enabled == nil {
|
||||
enabled := ipf.stack.Forwarding(ipv4.ProtocolNumber)
|
||||
ipf.enabled = &enabled
|
||||
}
|
||||
|
||||
val := "0\n"
|
||||
if *ipf.enabled {
|
||||
// Technically, this is not quite compatible with Linux. Linux stores these
|
||||
// as an integer, so if you write "2" into tcp_sack, you should get 2 back.
|
||||
// Tough luck.
|
||||
val = "1\n"
|
||||
}
|
||||
buf.WriteString(val)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write implements vfs.WritableDynamicBytesSource.Write.
|
||||
func (ipf *ipForwarding) Write(ctx context.Context, src usermem.IOSequence, offset int64) (int64, error) {
|
||||
if offset != 0 {
|
||||
// No need to handle partial writes thus far.
|
||||
return 0, syserror.EINVAL
|
||||
}
|
||||
if src.NumBytes() == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// Limit input size so as not to impact performance if input size is large.
|
||||
src = src.TakeFirst(usermem.PageSize - 1)
|
||||
|
||||
var v int32
|
||||
n, err := usermem.CopyInt32StringInVec(ctx, src.IO, src.Addrs, &v, src.Opts)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if ipf.enabled == nil {
|
||||
ipf.enabled = new(bool)
|
||||
}
|
||||
*ipf.enabled = v != 0
|
||||
if err := ipf.stack.SetForwarding(ipv4.ProtocolNumber, *ipf.enabled); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
@@ -20,8 +20,10 @@ import (
|
||||
"testing"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/sentry/contexttest"
|
||||
"gvisor.dev/gvisor/pkg/sentry/inet"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
)
|
||||
|
||||
func newIPv6TestStack() *inet.TestStack {
|
||||
@@ -76,3 +78,72 @@ func TestIfinet6(t *testing.T) {
|
||||
t.Errorf("Got n.contents() = %v, want = %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestIPForwarding tests the implementation of
|
||||
// /proc/sys/net/ipv4/ip_forwarding
|
||||
func TestConfigureIPForwarding(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
s := inet.NewTestStack()
|
||||
|
||||
var cases = []struct {
|
||||
comment string
|
||||
initial bool
|
||||
str string
|
||||
final bool
|
||||
}{
|
||||
{
|
||||
comment: `Forwarding is disabled; write 1 and enable forwarding`,
|
||||
initial: false,
|
||||
str: "1",
|
||||
final: true,
|
||||
},
|
||||
{
|
||||
comment: `Forwarding is disabled; write 0 and disable forwarding`,
|
||||
initial: false,
|
||||
str: "0",
|
||||
final: false,
|
||||
},
|
||||
{
|
||||
comment: `Forwarding is enabled; write 1 and enable forwarding`,
|
||||
initial: true,
|
||||
str: "1",
|
||||
final: true,
|
||||
},
|
||||
{
|
||||
comment: `Forwarding is enabled; write 0 and disable forwarding`,
|
||||
initial: true,
|
||||
str: "0",
|
||||
final: false,
|
||||
},
|
||||
{
|
||||
comment: `Forwarding is disabled; write 2404 and enable forwarding`,
|
||||
initial: false,
|
||||
str: "2404",
|
||||
final: true,
|
||||
},
|
||||
{
|
||||
comment: `Forwarding is enabled; write 2404 and enable forwarding`,
|
||||
initial: true,
|
||||
str: "2404",
|
||||
final: true,
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.comment, func(t *testing.T) {
|
||||
s.IPForwarding = c.initial
|
||||
|
||||
file := &ipForwarding{stack: s, enabled: &c.initial}
|
||||
|
||||
// Write the values.
|
||||
src := usermem.BytesIOSequence([]byte(c.str))
|
||||
if n, err := file.Write(ctx, src, 0); n != int64(len(c.str)) || err != nil {
|
||||
t.Errorf("file.Write(ctx, nil, %q, 0) = (%d, %v); want (%d, nil)", c.str, n, err, len(c.str))
|
||||
}
|
||||
|
||||
// Read the values from the stack and check them.
|
||||
if got, want := s.IPForwarding, c.final; got != want {
|
||||
t.Errorf("s.IPForwarding incorrect; got: %v, want: %v", got, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ go_library(
|
||||
],
|
||||
deps = [
|
||||
"//pkg/context",
|
||||
"//pkg/tcpip",
|
||||
"//pkg/tcpip/stack",
|
||||
],
|
||||
)
|
||||
|
||||
+10
-1
@@ -15,7 +15,10 @@
|
||||
// Package inet defines semantics for IP stacks.
|
||||
package inet
|
||||
|
||||
import "gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
import (
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
)
|
||||
|
||||
// Stack represents a TCP/IP stack.
|
||||
type Stack interface {
|
||||
@@ -80,6 +83,12 @@ type Stack interface {
|
||||
// RestoreCleanupEndpoints adds endpoints to cleanup tracking. This is useful
|
||||
// for restoring a stack after a save.
|
||||
RestoreCleanupEndpoints([]stack.TransportEndpoint)
|
||||
|
||||
// Forwarding returns if packet forwarding between NICs is enabled.
|
||||
Forwarding(protocol tcpip.NetworkProtocolNumber) bool
|
||||
|
||||
// SetForwarding enables or disables packet forwarding between NICs.
|
||||
SetForwarding(protocol tcpip.NetworkProtocolNumber, enable bool) error
|
||||
}
|
||||
|
||||
// Interface contains information about a network interface.
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
|
||||
package inet
|
||||
|
||||
import "gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
import (
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
)
|
||||
|
||||
// TestStack is a dummy implementation of Stack for tests.
|
||||
type TestStack struct {
|
||||
@@ -26,6 +29,7 @@ type TestStack struct {
|
||||
TCPSendBufSize TCPBufferSize
|
||||
TCPSACKFlag bool
|
||||
Recovery TCPLossRecovery
|
||||
IPForwarding bool
|
||||
}
|
||||
|
||||
// NewTestStack returns a TestStack with no network interfaces. The value of
|
||||
@@ -128,3 +132,14 @@ func (s *TestStack) CleanupEndpoints() []stack.TransportEndpoint {
|
||||
|
||||
// RestoreCleanupEndpoints implements inet.Stack.RestoreCleanupEndpoints.
|
||||
func (s *TestStack) RestoreCleanupEndpoints([]stack.TransportEndpoint) {}
|
||||
|
||||
// Forwarding implements inet.Stack.Forwarding.
|
||||
func (s *TestStack) Forwarding(protocol tcpip.NetworkProtocolNumber) bool {
|
||||
return s.IPForwarding
|
||||
}
|
||||
|
||||
// SetForwarding implements inet.Stack.SetForwarding.
|
||||
func (s *TestStack) SetForwarding(protocol tcpip.NetworkProtocolNumber, enable bool) error {
|
||||
s.IPForwarding = enable
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -39,6 +39,9 @@ go_library(
|
||||
"//pkg/sentry/vfs",
|
||||
"//pkg/syserr",
|
||||
"//pkg/syserror",
|
||||
"//pkg/tcpip",
|
||||
"//pkg/tcpip/network/ipv4",
|
||||
"//pkg/tcpip/network/ipv6",
|
||||
"//pkg/tcpip/stack",
|
||||
"//pkg/usermem",
|
||||
"//pkg/waiter",
|
||||
|
||||
@@ -30,6 +30,9 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/sentry/inet"
|
||||
"gvisor.dev/gvisor/pkg/syserr"
|
||||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
)
|
||||
@@ -59,6 +62,8 @@ type Stack struct {
|
||||
tcpSACKEnabled bool
|
||||
netDevFile *os.File
|
||||
netSNMPFile *os.File
|
||||
ipv4Forwarding bool
|
||||
ipv6Forwarding bool
|
||||
}
|
||||
|
||||
// NewStack returns an empty Stack containing no configuration.
|
||||
@@ -118,6 +123,13 @@ func (s *Stack) Configure() error {
|
||||
s.netSNMPFile = f
|
||||
}
|
||||
|
||||
s.ipv6Forwarding = false
|
||||
if ipForwarding, err := ioutil.ReadFile("/proc/sys/net/ipv6/conf/all/forwarding"); err == nil {
|
||||
s.ipv6Forwarding = strings.TrimSpace(string(ipForwarding)) != "0"
|
||||
} else {
|
||||
log.Warningf("Failed to read if ipv6 forwarding is enabled, setting to false")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -468,3 +480,21 @@ func (s *Stack) CleanupEndpoints() []stack.TransportEndpoint { return nil }
|
||||
|
||||
// RestoreCleanupEndpoints implements inet.Stack.RestoreCleanupEndpoints.
|
||||
func (s *Stack) RestoreCleanupEndpoints([]stack.TransportEndpoint) {}
|
||||
|
||||
// Forwarding implements inet.Stack.Forwarding.
|
||||
func (s *Stack) Forwarding(protocol tcpip.NetworkProtocolNumber) bool {
|
||||
switch protocol {
|
||||
case ipv4.ProtocolNumber:
|
||||
return s.ipv4Forwarding
|
||||
case ipv6.ProtocolNumber:
|
||||
return s.ipv6Forwarding
|
||||
default:
|
||||
log.Warningf("Forwarding(%v) failed: unsupported protocol", protocol)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// SetForwarding implements inet.Stack.SetForwarding.
|
||||
func (s *Stack) SetForwarding(protocol tcpip.NetworkProtocolNumber, enable bool) error {
|
||||
return syserror.EACCES
|
||||
}
|
||||
|
||||
@@ -412,3 +412,24 @@ func (s *Stack) CleanupEndpoints() []stack.TransportEndpoint {
|
||||
func (s *Stack) RestoreCleanupEndpoints(es []stack.TransportEndpoint) {
|
||||
s.Stack.RestoreCleanupEndpoints(es)
|
||||
}
|
||||
|
||||
// Forwarding implements inet.Stack.Forwarding.
|
||||
func (s *Stack) Forwarding(protocol tcpip.NetworkProtocolNumber) bool {
|
||||
switch protocol {
|
||||
case ipv4.ProtocolNumber, ipv6.ProtocolNumber:
|
||||
return s.Stack.Forwarding(protocol)
|
||||
default:
|
||||
panic(fmt.Sprintf("Forwarding(%v) failed: unsupported protocol", protocol))
|
||||
}
|
||||
}
|
||||
|
||||
// SetForwarding implements inet.Stack.SetForwarding.
|
||||
func (s *Stack) SetForwarding(protocol tcpip.NetworkProtocolNumber, enable bool) error {
|
||||
switch protocol {
|
||||
case ipv4.ProtocolNumber, ipv6.ProtocolNumber:
|
||||
s.Stack.SetForwarding(protocol, enable)
|
||||
default:
|
||||
panic(fmt.Sprintf("SetForwarding(%v) failed: unsupported protocol", protocol))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ go_library(
|
||||
go_test(
|
||||
name = "buffer_test",
|
||||
size = "small",
|
||||
srcs = ["view_test.go"],
|
||||
srcs = [
|
||||
"view_test.go",
|
||||
],
|
||||
library = ":buffer",
|
||||
)
|
||||
|
||||
@@ -477,7 +477,7 @@ func (e *endpoint) handleICMP(r *stack.Route, pkt *stack.PacketBuffer, hasFragme
|
||||
stack := r.Stack()
|
||||
|
||||
// Is the networking stack operating as a router?
|
||||
if !stack.Forwarding() {
|
||||
if !stack.Forwarding(ProtocolNumber) {
|
||||
// ... No, silently drop the packet.
|
||||
received.RouterOnlyPacketsDroppedByHost.Increment()
|
||||
return
|
||||
|
||||
@@ -728,7 +728,7 @@ func TestICMPChecksumValidationSimple(t *testing.T) {
|
||||
})
|
||||
if isRouter {
|
||||
// Enabling forwarding makes the stack act as a router.
|
||||
s.SetForwarding(true)
|
||||
s.SetForwarding(ProtocolNumber, true)
|
||||
}
|
||||
if err := s.CreateNIC(nicID, e); err != nil {
|
||||
t.Fatalf("CreateNIC(_, _) = %s", err)
|
||||
|
||||
@@ -958,7 +958,7 @@ func TestNDPValidation(t *testing.T) {
|
||||
|
||||
if isRouter {
|
||||
// Enabling forwarding makes the stack act as a router.
|
||||
s.SetForwarding(true)
|
||||
s.SetForwarding(ProtocolNumber, true)
|
||||
}
|
||||
|
||||
stats := s.Stats().ICMP.V6PacketsReceived
|
||||
|
||||
@@ -316,7 +316,7 @@ func fwdTestNetFactory(t *testing.T, proto *fwdTestNetworkProtocol, useNeighborC
|
||||
}
|
||||
|
||||
// Enable forwarding.
|
||||
s.SetForwarding(true)
|
||||
s.SetForwarding(proto.Number(), true)
|
||||
|
||||
// NIC 1 has the link address "a", and added the network address 1.
|
||||
ep1 = &fwdTestLinkEndpoint{
|
||||
|
||||
@@ -817,7 +817,7 @@ func (ndp *ndpState) handleRA(ip tcpip.Address, ra header.NDPRouterAdvert) {
|
||||
// per-interface basis; it is a stack-wide configuration, so we check
|
||||
// stack's forwarding flag to determine if the NIC is a routing
|
||||
// interface.
|
||||
if !ndp.configs.HandleRAs || ndp.nic.stack.forwarding {
|
||||
if !ndp.configs.HandleRAs || ndp.nic.stack.Forwarding(header.IPv6ProtocolNumber) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -1120,7 +1120,7 @@ func TestNoRouterDiscovery(t *testing.T) {
|
||||
},
|
||||
NDPDisp: &ndpDisp,
|
||||
})
|
||||
s.SetForwarding(forwarding)
|
||||
s.SetForwarding(ipv6.ProtocolNumber, forwarding)
|
||||
|
||||
if err := s.CreateNIC(1, e); err != nil {
|
||||
t.Fatalf("CreateNIC(1) = %s", err)
|
||||
@@ -1365,7 +1365,7 @@ func TestNoPrefixDiscovery(t *testing.T) {
|
||||
},
|
||||
NDPDisp: &ndpDisp,
|
||||
})
|
||||
s.SetForwarding(forwarding)
|
||||
s.SetForwarding(ipv6.ProtocolNumber, forwarding)
|
||||
|
||||
if err := s.CreateNIC(1, e); err != nil {
|
||||
t.Fatalf("CreateNIC(1) = %s", err)
|
||||
@@ -1723,7 +1723,7 @@ func TestNoAutoGenAddr(t *testing.T) {
|
||||
},
|
||||
NDPDisp: &ndpDisp,
|
||||
})
|
||||
s.SetForwarding(forwarding)
|
||||
s.SetForwarding(ipv6.ProtocolNumber, forwarding)
|
||||
|
||||
if err := s.CreateNIC(1, e); err != nil {
|
||||
t.Fatalf("CreateNIC(1) = %s", err)
|
||||
@@ -4640,7 +4640,7 @@ func TestCleanupNDPState(t *testing.T) {
|
||||
name: "Enable forwarding",
|
||||
cleanupFn: func(t *testing.T, s *stack.Stack) {
|
||||
t.Helper()
|
||||
s.SetForwarding(true)
|
||||
s.SetForwarding(ipv6.ProtocolNumber, true)
|
||||
},
|
||||
keepAutoGenLinkLocal: true,
|
||||
maxAutoGenAddrEvents: 4,
|
||||
@@ -5286,11 +5286,11 @@ func TestStopStartSolicitingRouters(t *testing.T) {
|
||||
name: "Enable and disable forwarding",
|
||||
startFn: func(t *testing.T, s *stack.Stack) {
|
||||
t.Helper()
|
||||
s.SetForwarding(false)
|
||||
s.SetForwarding(ipv6.ProtocolNumber, false)
|
||||
},
|
||||
stopFn: func(t *testing.T, s *stack.Stack, _ bool) {
|
||||
t.Helper()
|
||||
s.SetForwarding(true)
|
||||
s.SetForwarding(ipv6.ProtocolNumber, true)
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user