summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--pkg/sentry/socket/epsocket/epsocket.go57
-rw-r--r--pkg/tcpip/link/channel/channel.go5
-rw-r--r--pkg/tcpip/link/fdbased/endpoint.go13
-rw-r--r--pkg/tcpip/link/loopback/loopback.go5
-rw-r--r--pkg/tcpip/link/sharedmem/sharedmem.go7
-rw-r--r--pkg/tcpip/link/sniffer/sniffer.go5
-rw-r--r--pkg/tcpip/link/waitable/waitable.go5
-rw-r--r--pkg/tcpip/link/waitable/waitable_test.go5
-rw-r--r--pkg/tcpip/network/ip_test.go5
-rw-r--r--pkg/tcpip/stack/registration.go4
-rw-r--r--pkg/tcpip/stack/stack.go33
11 files changed, 138 insertions, 6 deletions
diff --git a/pkg/sentry/socket/epsocket/epsocket.go b/pkg/sentry/socket/epsocket/epsocket.go
index 2495ba459..9ff9af0bc 100644
--- a/pkg/sentry/socket/epsocket/epsocket.go
+++ b/pkg/sentry/socket/epsocket/epsocket.go
@@ -48,12 +48,15 @@ import (
"gvisor.googlesource.com/gvisor/pkg/syserror"
"gvisor.googlesource.com/gvisor/pkg/tcpip"
"gvisor.googlesource.com/gvisor/pkg/tcpip/buffer"
+ nstack "gvisor.googlesource.com/gvisor/pkg/tcpip/stack"
"gvisor.googlesource.com/gvisor/pkg/tcpip/transport/unix"
"gvisor.googlesource.com/gvisor/pkg/waiter"
)
const sizeOfInt32 int = 4
+var errStackType = syserr.New("expected but did not receive an epsocket.Stack", linux.EINVAL)
+
// ntohs converts a 16-bit number from network byte order to host byte order. It
// assumes that the host is little endian.
func ntohs(v uint16) uint16 {
@@ -1177,9 +1180,11 @@ func interfaceIoctl(ctx context.Context, io usermem.IO, arg int, ifr *linux.IFRe
usermem.ByteOrder.PutUint16(ifr.Data[:2], uint16(n))
case syscall.SIOCGIFFLAGS:
- // TODO: Implement. For now, return only that the
- // device is up so that ifconfig prints it.
- usermem.ByteOrder.PutUint16(ifr.Data[:2], linux.IFF_UP)
+ f, err := interfaceStatusFlags(stack, iface.Name)
+ if err != nil {
+ return err
+ }
+ usermem.ByteOrder.PutUint16(ifr.Data[:2], f)
case syscall.SIOCGIFADDR:
// Copy the IPv4 address out.
@@ -1288,3 +1293,49 @@ func ifconfIoctl(ctx context.Context, io usermem.IO, ifc *linux.IFConf) error {
}
return nil
}
+
+// interfaceStatusFlags returns status flags for an interface in the stack.
+// Flag values and meanings are described in greater detail in netdevice(7) in
+// the SIOCGIFFLAGS section.
+func interfaceStatusFlags(stack inet.Stack, name string) (uint16, *syserr.Error) {
+ // epsocket should only ever be passed an epsocket.Stack.
+ epstack, ok := stack.(*Stack)
+ if !ok {
+ return 0, errStackType
+ }
+
+ // Find the NIC corresponding to this interface.
+ var (
+ nicid tcpip.NICID
+ info nstack.NICInfo
+ found bool
+ )
+ ns := epstack.Stack
+ for nicid, info = range ns.NICInfo() {
+ if info.Name == name {
+ found = true
+ break
+ }
+ }
+ if !found {
+ return 0, syserr.ErrNoDevice
+ }
+
+ // Set flags based on NIC state.
+ nicFlags, err := ns.NICFlags(nicid)
+ if err != nil {
+ return 0, syserr.TranslateNetstackError(err)
+ }
+
+ var retFlags uint16
+ if nicFlags.Up {
+ retFlags |= linux.IFF_UP
+ }
+ if nicFlags.Running {
+ retFlags |= linux.IFF_RUNNING
+ }
+ if nicFlags.Promiscuous {
+ retFlags |= linux.IFF_PROMISC
+ }
+ return retFlags, nil
+}
diff --git a/pkg/tcpip/link/channel/channel.go b/pkg/tcpip/link/channel/channel.go
index cebc34553..3f5440cc1 100644
--- a/pkg/tcpip/link/channel/channel.go
+++ b/pkg/tcpip/link/channel/channel.go
@@ -67,6 +67,11 @@ func (e *Endpoint) Attach(dispatcher stack.NetworkDispatcher) {
e.dispatcher = dispatcher
}
+// IsAttached implements stack.LinkEndpoint.IsAttached.
+func (e *Endpoint) IsAttached() bool {
+ return e.dispatcher != nil
+}
+
// MTU implements stack.LinkEndpoint.MTU. It returns the value initialized
// during construction.
func (e *Endpoint) MTU() uint32 {
diff --git a/pkg/tcpip/link/fdbased/endpoint.go b/pkg/tcpip/link/fdbased/endpoint.go
index da74cd644..668514454 100644
--- a/pkg/tcpip/link/fdbased/endpoint.go
+++ b/pkg/tcpip/link/fdbased/endpoint.go
@@ -45,9 +45,10 @@ type endpoint struct {
// its end of the communication pipe.
closed func(*tcpip.Error)
- vv *buffer.VectorisedView
- iovecs []syscall.Iovec
- views []buffer.View
+ vv *buffer.VectorisedView
+ iovecs []syscall.Iovec
+ views []buffer.View
+ attached bool
}
// Options specify the details about the fd-based endpoint to be created.
@@ -96,9 +97,15 @@ func New(opts *Options) tcpip.LinkEndpointID {
// Attach launches the goroutine that reads packets from the file descriptor and
// dispatches them via the provided dispatcher.
func (e *endpoint) Attach(dispatcher stack.NetworkDispatcher) {
+ e.attached = true
go e.dispatchLoop(dispatcher) // S/R-FIXME
}
+// IsAttached implements stack.LinkEndpoint.IsAttached.
+func (e *endpoint) IsAttached() bool {
+ return e.attached
+}
+
// MTU implements stack.LinkEndpoint.MTU. It returns the value initialized
// during construction.
func (e *endpoint) MTU() uint32 {
diff --git a/pkg/tcpip/link/loopback/loopback.go b/pkg/tcpip/link/loopback/loopback.go
index 1a9cd09d7..f38847949 100644
--- a/pkg/tcpip/link/loopback/loopback.go
+++ b/pkg/tcpip/link/loopback/loopback.go
@@ -32,6 +32,11 @@ func (e *endpoint) Attach(dispatcher stack.NetworkDispatcher) {
e.dispatcher = dispatcher
}
+// IsAttached implements stack.LinkEndpoint.IsAttached.
+func (e *endpoint) IsAttached() bool {
+ return e.dispatcher != nil
+}
+
// MTU implements stack.LinkEndpoint.MTU. It returns a constant that matches the
// linux loopback interface.
func (*endpoint) MTU() uint32 {
diff --git a/pkg/tcpip/link/sharedmem/sharedmem.go b/pkg/tcpip/link/sharedmem/sharedmem.go
index 2c0f1b294..5369ebc68 100644
--- a/pkg/tcpip/link/sharedmem/sharedmem.go
+++ b/pkg/tcpip/link/sharedmem/sharedmem.go
@@ -137,6 +137,13 @@ func (e *endpoint) Attach(dispatcher stack.NetworkDispatcher) {
e.mu.Unlock()
}
+// IsAttached implements stack.LinkEndpoint.IsAttached.
+func (e *endpoint) IsAttached() bool {
+ e.mu.Lock()
+ defer e.mu.Unlock()
+ return e.workerStarted
+}
+
// MTU implements stack.LinkEndpoint.MTU. It returns the value initialized
// during construction.
func (e *endpoint) MTU() uint32 {
diff --git a/pkg/tcpip/link/sniffer/sniffer.go b/pkg/tcpip/link/sniffer/sniffer.go
index 72d9a0f1c..3a40081c0 100644
--- a/pkg/tcpip/link/sniffer/sniffer.go
+++ b/pkg/tcpip/link/sniffer/sniffer.go
@@ -143,6 +143,11 @@ func (e *endpoint) Attach(dispatcher stack.NetworkDispatcher) {
e.lower.Attach(e)
}
+// IsAttached implements stack.LinkEndpoint.IsAttached.
+func (e *endpoint) IsAttached() bool {
+ return e.dispatcher != nil
+}
+
// MTU implements stack.LinkEndpoint.MTU. It just forwards the request to the
// lower endpoint.
func (e *endpoint) MTU() uint32 {
diff --git a/pkg/tcpip/link/waitable/waitable.go b/pkg/tcpip/link/waitable/waitable.go
index 2c6e73f22..91aed7a12 100644
--- a/pkg/tcpip/link/waitable/waitable.go
+++ b/pkg/tcpip/link/waitable/waitable.go
@@ -58,6 +58,11 @@ func (e *Endpoint) Attach(dispatcher stack.NetworkDispatcher) {
e.lower.Attach(e)
}
+// IsAttached implements stack.LinkEndpoint.IsAttached.
+func (e *Endpoint) IsAttached() bool {
+ return e.dispatcher != nil
+}
+
// MTU implements stack.LinkEndpoint.MTU. It just forwards the request to the
// lower endpoint.
func (e *Endpoint) MTU() uint32 {
diff --git a/pkg/tcpip/link/waitable/waitable_test.go b/pkg/tcpip/link/waitable/waitable_test.go
index cb433dc19..188049322 100644
--- a/pkg/tcpip/link/waitable/waitable_test.go
+++ b/pkg/tcpip/link/waitable/waitable_test.go
@@ -34,6 +34,11 @@ func (e *countedEndpoint) Attach(dispatcher stack.NetworkDispatcher) {
e.dispatcher = dispatcher
}
+// IsAttached implements stack.LinkEndpoint.IsAttached.
+func (e *countedEndpoint) IsAttached() bool {
+ return e.dispatcher != nil
+}
+
func (e *countedEndpoint) MTU() uint32 {
return e.mtu
}
diff --git a/pkg/tcpip/network/ip_test.go b/pkg/tcpip/network/ip_test.go
index 797501858..c5f8714da 100644
--- a/pkg/tcpip/network/ip_test.go
+++ b/pkg/tcpip/network/ip_test.go
@@ -90,6 +90,11 @@ func (t *testObject) DeliverTransportControlPacket(local, remote tcpip.Address,
// Attach is only implemented to satisfy the LinkEndpoint interface.
func (*testObject) Attach(stack.NetworkDispatcher) {}
+// IsAttached implements stack.LinkEndpoint.IsAttached.
+func (*testObject) IsAttached() bool {
+ return true
+}
+
// MTU implements stack.LinkEndpoint.MTU. It just returns a constant that
// matches the linux loopback MTU.
func (*testObject) MTU() uint32 {
diff --git a/pkg/tcpip/stack/registration.go b/pkg/tcpip/stack/registration.go
index e7e6381ac..15b2418ad 100644
--- a/pkg/tcpip/stack/registration.go
+++ b/pkg/tcpip/stack/registration.go
@@ -224,6 +224,10 @@ type LinkEndpoint interface {
// Attach attaches the data link layer endpoint to the network-layer
// dispatcher of the stack.
Attach(dispatcher NetworkDispatcher)
+
+ // IsAttached returns whether a NetworkDispatcher is attached to the
+ // endpoint.
+ IsAttached() bool
}
// A LinkAddressResolver is an extension to a NetworkProtocol that
diff --git a/pkg/tcpip/stack/stack.go b/pkg/tcpip/stack/stack.go
index f0fbd8aad..3976f585c 100644
--- a/pkg/tcpip/stack/stack.go
+++ b/pkg/tcpip/stack/stack.go
@@ -541,6 +541,39 @@ func (s *Stack) NICInfo() map[tcpip.NICID]NICInfo {
return nics
}
+// NICStateFlags holds information about the state of an NIC.
+type NICStateFlags struct {
+ // Up indicates whether the interface is running.
+ Up bool
+
+ // Running indicates whether resources are allocated.
+ Running bool
+
+ // Promiscuous indicates whether the interface is in promiscuous mode.
+ Promiscuous bool
+}
+
+// NICFlags returns flags about the state of the NIC. It returns an error if
+// the NIC corresponding to id cannot be found.
+func (s *Stack) NICFlags(id tcpip.NICID) (NICStateFlags, *tcpip.Error) {
+ s.mu.RLock()
+ defer s.mu.RUnlock()
+
+ nic := s.nics[id]
+ if nic == nil {
+ return NICStateFlags{}, tcpip.ErrUnknownNICID
+ }
+
+ ret := NICStateFlags{
+ // Netstack interfaces are always up.
+ Up: true,
+
+ Running: nic.linkEP.IsAttached(),
+ Promiscuous: nic.promiscuous,
+ }
+ return ret, nil
+}
+
// AddAddress adds a new network-layer address to the specified NIC.
func (s *Stack) AddAddress(id tcpip.NICID, protocol tcpip.NetworkProtocolNumber, addr tcpip.Address) *tcpip.Error {
s.mu.RLock()