152 lines
4.4 KiB
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
|
|
}
|