gvisor/pkg/sentry/fs/proc/net.go

152 lines
4.4 KiB
Go

// Copyright 2018 Google Inc.
//
// 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 proc
import (
"fmt"
"gvisor.googlesource.com/gvisor/pkg/abi/linux"
"gvisor.googlesource.com/gvisor/pkg/sentry/context"
"gvisor.googlesource.com/gvisor/pkg/sentry/fs"
"gvisor.googlesource.com/gvisor/pkg/sentry/fs/proc/seqfile"
"gvisor.googlesource.com/gvisor/pkg/sentry/fs/ramfs"
"gvisor.googlesource.com/gvisor/pkg/sentry/inet"
)
// newNet creates a new proc net entry.
func (p *proc) newNetDir(ctx context.Context, msrc *fs.MountSource) *fs.Inode {
d := &ramfs.Dir{}
d.InitDir(ctx, nil, fs.RootOwner, fs.FilePermsFromMode(0555))
if s := p.k.NetworkStack(); s != nil && s.SupportsIPv6() {
d.AddChild(ctx, "dev", seqfile.NewSeqFileInode(ctx, &netDev{s: s}, msrc))
d.AddChild(ctx, "if_inet6", seqfile.NewSeqFileInode(ctx, &ifinet6{s: s}, msrc))
}
return newFile(d, msrc, fs.SpecialDirectory, nil)
}
// ifinet6 implements seqfile.SeqSource for /proc/net/if_inet6.
type ifinet6 struct {
s inet.Stack `state:"nosave"` // S/R-FIXME
}
func (n *ifinet6) contents() []string {
var lines []string
nics := n.s.Interfaces()
for id, naddrs := range n.s.InterfaceAddrs() {
nic, ok := nics[id]
if !ok {
// NIC was added after NICNames was called. We'll just
// ignore it.
continue
}
for _, a := range naddrs {
// IPv6 only.
if a.Family != linux.AF_INET6 {
continue
}
// Fields:
// IPv6 address displayed in 32 hexadecimal chars without colons
// Netlink device number (interface index) in hexadecimal (use nic id)
// Prefix length in hexadecimal
// Scope value (use 0)
// Interface flags
// Device name
lines = append(lines, fmt.Sprintf("%032x %02x %02x %02x %02x %8s\n", a.Addr, id, a.PrefixLen, 0, a.Flags, nic.Name))
}
}
return lines
}
// NeedsUpdate implements seqfile.SeqSource.NeedsUpdate.
func (*ifinet6) NeedsUpdate(generation int64) bool {
return true
}
// ReadSeqFileData implements seqfile.SeqSource.ReadSeqFileData.
func (n *ifinet6) ReadSeqFileData(h seqfile.SeqHandle) ([]seqfile.SeqData, int64) {
if h != nil {
return nil, 0
}
var data []seqfile.SeqData
for _, l := range n.contents() {
data = append(data, seqfile.SeqData{Buf: []byte(l), Handle: (*ifinet6)(nil)})
}
return data, 0
}
// netDev implements seqfile.SeqSource for /proc/net/dev.
type netDev struct {
s inet.Stack `state:"nosave"` // S/R-FIXME
}
// NeedsUpdate implements seqfile.SeqSource.NeedsUpdate.
func (n *netDev) NeedsUpdate(generation int64) bool {
return true
}
// ReadSeqFileData implements seqfile.SeqSource.ReadSeqFileData. See Linux's
// net/core/net-procfs.c:dev_seq_show.
func (n *netDev) ReadSeqFileData(h seqfile.SeqHandle) ([]seqfile.SeqData, int64) {
if h != nil {
return nil, 0
}
interfaces := n.s.Interfaces()
contents := make([]string, 2, 2+len(interfaces))
// Add the table header. From net/core/net-procfs.c:dev_seq_show.
contents[0] = "Inter-| Receive | Transmit\n"
contents[1] = " face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed\n"
for _, i := range interfaces {
// TODO: Collect stats from each inet.Stack
// implementation (hostinet, epsocket, and rpcinet).
// Implements the same format as
// net/core/net-procfs.c:dev_seq_printf_stats.
l := fmt.Sprintf("%6s: %7d %7d %4d %4d %4d %5d %10d %9d %8d %7d %4d %4d %4d %5d %7d %10d\n",
i.Name,
// Received
0, // bytes
0, // packets
0, // errors
0, // dropped
0, // fifo
0, // frame
0, // compressed
0, // multicast
// Transmitted
0, // bytes
0, // packets
0, // errors
0, // dropped
0, // fifo
0, // frame
0, // compressed
0) // multicast
contents = append(contents, l)
}
var data []seqfile.SeqData
for _, l := range contents {
data = append(data, seqfile.SeqData{Buf: []byte(l), Handle: (*ifinet6)(nil)})
}
return data, 0
}