Commit 7a4fde3f authored by Ben Laurie's avatar Ben Laurie Committed by Ian Lance Taylor

unix: add some FreeBSD Capsicum support.

Change-Id: Ibb1426ebd18d27ee9f144af0fd8c94b08c06f7d7
Reviewed-on: https://go-review.googlesource.com/47290Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent cd2c2764
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build freebsd
package unix
import (
errorspkg "errors"
"fmt"
)
// Go implementation of C mostly found in /usr/src/sys/kern/subr_capability.c
const (
// This is the version of CapRights this package understands. See C implementation for parallels.
capRightsGoVersion = CAP_RIGHTS_VERSION_00
capArSizeMin = CAP_RIGHTS_VERSION_00 + 2
capArSizeMax = capRightsGoVersion + 2
)
var (
bit2idx = []int{
-1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1,
4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
}
)
func capidxbit(right uint64) int {
return int((right >> 57) & 0x1f)
}
func rightToIndex(right uint64) (int, error) {
idx := capidxbit(right)
if idx < 0 || idx >= len(bit2idx) {
return -2, fmt.Errorf("index for right 0x%x out of range", right)
}
return bit2idx[idx], nil
}
func caprver(right uint64) int {
return int(right >> 62)
}
func capver(rights *CapRights) int {
return caprver(rights.Rights[0])
}
func caparsize(rights *CapRights) int {
return capver(rights) + 2
}
// CapRightsSet sets the permissions in setrights in rights.
func CapRightsSet(rights *CapRights, setrights []uint64) error {
// This is essentially a copy of cap_rights_vset()
if capver(rights) != CAP_RIGHTS_VERSION_00 {
return fmt.Errorf("bad rights version %d", capver(rights))
}
n := caparsize(rights)
if n < capArSizeMin || n > capArSizeMax {
return errorspkg.New("bad rights size")
}
for _, right := range setrights {
if caprver(right) != CAP_RIGHTS_VERSION_00 {
return errorspkg.New("bad right version")
}
i, err := rightToIndex(right)
if err != nil {
return err
}
if i >= n {
return errorspkg.New("index overflow")
}
if capidxbit(rights.Rights[i]) != capidxbit(right) {
return errorspkg.New("index mismatch")
}
rights.Rights[i] |= right
if capidxbit(rights.Rights[i]) != capidxbit(right) {
return errorspkg.New("index mismatch (after assign)")
}
}
return nil
}
// CapRightsClear clears the permissions in clearrights from rights.
func CapRightsClear(rights *CapRights, clearrights []uint64) error {
// This is essentially a copy of cap_rights_vclear()
if capver(rights) != CAP_RIGHTS_VERSION_00 {
return fmt.Errorf("bad rights version %d", capver(rights))
}
n := caparsize(rights)
if n < capArSizeMin || n > capArSizeMax {
return errorspkg.New("bad rights size")
}
for _, right := range clearrights {
if caprver(right) != CAP_RIGHTS_VERSION_00 {
return errorspkg.New("bad right version")
}
i, err := rightToIndex(right)
if err != nil {
return err
}
if i >= n {
return errorspkg.New("index overflow")
}
if capidxbit(rights.Rights[i]) != capidxbit(right) {
return errorspkg.New("index mismatch")
}
rights.Rights[i] &= ^(right & 0x01FFFFFFFFFFFFFF)
if capidxbit(rights.Rights[i]) != capidxbit(right) {
return errorspkg.New("index mismatch (after assign)")
}
}
return nil
}
// CapRightsIsSet checks whether all the permissions in setrights are present in rights.
func CapRightsIsSet(rights *CapRights, setrights []uint64) (bool, error) {
// This is essentially a copy of cap_rights_is_vset()
if capver(rights) != CAP_RIGHTS_VERSION_00 {
return false, fmt.Errorf("bad rights version %d", capver(rights))
}
n := caparsize(rights)
if n < capArSizeMin || n > capArSizeMax {
return false, errorspkg.New("bad rights size")
}
for _, right := range setrights {
if caprver(right) != CAP_RIGHTS_VERSION_00 {
return false, errorspkg.New("bad right version")
}
i, err := rightToIndex(right)
if err != nil {
return false, err
}
if i >= n {
return false, errorspkg.New("index overflow")
}
if capidxbit(rights.Rights[i]) != capidxbit(right) {
return false, errorspkg.New("index mismatch")
}
if (rights.Rights[i] & right) != right {
return false, nil
}
}
return true, nil
}
func capright(idx uint64, bit uint64) uint64 {
return ((1 << (57 + idx)) | bit)
}
// CapRightsInit returns a pointer to an initialised CapRights structure filled with rights.
// See man cap_rights_init(3) and rights(4).
func CapRightsInit(rights []uint64) (*CapRights, error) {
var r CapRights
r.Rights[0] = (capRightsGoVersion << 62) | capright(0, 0)
r.Rights[1] = capright(1, 0)
err := CapRightsSet(&r, rights)
if err != nil {
return nil, err
}
return &r, nil
}
// CapRightsLimit reduces the operations permitted on fd to at most those contained in rights.
// The capability rights on fd can never be increased by CapRightsLimit.
// See man cap_rights_limit(2) and rights(4).
func CapRightsLimit(fd uintptr, rights *CapRights) error {
return capRightsLimit(int(fd), rights)
}
// CapRightsGet returns a CapRights structure containing the operations permitted on fd.
// See man cap_rights_get(3) and rights(4).
func CapRightsGet(fd uintptr) (*CapRights, error) {
r, err := CapRightsInit(nil)
if err != nil {
return nil, err
}
err = capRightsGet(capRightsGoVersion, int(fd), r)
if err != nil {
return nil, err
}
return r, nil
}
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package unix
import (
"os"
"syscall"
)
// FIXME: unexported function from os
// syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
func syscallMode(i os.FileMode) (o uint32) {
o |= uint32(i.Perm())
if i&os.ModeSetuid != 0 {
o |= syscall.S_ISUID
}
if i&os.ModeSetgid != 0 {
o |= syscall.S_ISGID
}
if i&os.ModeSticky != 0 {
o |= syscall.S_ISVTX
}
// No mapping for Go's ModeTemporary (plan9 only).
return
}
...@@ -75,6 +75,7 @@ includes_DragonFly=' ...@@ -75,6 +75,7 @@ includes_DragonFly='
' '
includes_FreeBSD=' includes_FreeBSD='
#include <sys/capability.h>
#include <sys/param.h> #include <sys/param.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/event.h> #include <sys/event.h>
...@@ -401,6 +402,7 @@ ccflags="$@" ...@@ -401,6 +402,7 @@ ccflags="$@"
$2 ~ /^(BPF|DLT)_/ || $2 ~ /^(BPF|DLT)_/ ||
$2 ~ /^CLOCK_/ || $2 ~ /^CLOCK_/ ||
$2 ~ /^CAN_/ || $2 ~ /^CAN_/ ||
$2 ~ /^CAP_/ ||
$2 ~ /^ALG_/ || $2 ~ /^ALG_/ ||
$2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE|IOC_(GET|SET)_ENCRYPTION)/ || $2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE|IOC_(GET|SET)_ENCRYPTION)/ ||
$2 ~ /^GRND_/ || $2 ~ /^GRND_/ ||
......
...@@ -40,21 +40,8 @@ while(<>){ ...@@ -40,21 +40,8 @@ while(<>){
if($name eq 'SYS_SYS_EXIT'){ if($name eq 'SYS_SYS_EXIT'){
$name = 'SYS_EXIT'; $name = 'SYS_EXIT';
} }
if($name =~ /^SYS_CAP_+/ || $name =~ /^SYS___CAP_+/){
next
}
print " $name = $num; // $proto\n"; print " $name = $num; // $proto\n";
# We keep Capsicum syscall numbers for FreeBSD
# 9-STABLE here because we are not sure whether they
# are mature and stable.
if($num == 513){
print " SYS_CAP_NEW = 514 // { int cap_new(int fd, uint64_t rights); }\n";
print " SYS_CAP_GETRIGHTS = 515 // { int cap_getrights(int fd, \\\n";
print " SYS_CAP_ENTER = 516 // { int cap_enter(void); }\n";
print " SYS_CAP_GETMODE = 517 // { int cap_getmode(u_int *modep); }\n";
}
} }
} }
......
...@@ -357,6 +357,9 @@ func Llistxattr(link string, dest []byte) (sz int, err error) { ...@@ -357,6 +357,9 @@ func Llistxattr(link string, dest []byte) (sz int, err error) {
*/ */
//sys Access(path string, mode uint32) (err error) //sys Access(path string, mode uint32) (err error)
//sys Adjtime(delta *Timeval, olddelta *Timeval) (err error) //sys Adjtime(delta *Timeval, olddelta *Timeval) (err error)
//sys CapEnter() (err error)
//sys capRightsGet(version int, fd int, rightsp *CapRights) (err error) = SYS___CAP_RIGHTS_GET
//sys capRightsLimit(fd int, rightsp *CapRights) (err error)
//sys Chdir(path string) (err error) //sys Chdir(path string) (err error)
//sys Chflags(path string, flags int) (err error) //sys Chflags(path string, flags int) (err error)
//sys Chmod(path string, mode uint32) (err error) //sys Chmod(path string, mode uint32) (err error)
...@@ -421,6 +424,7 @@ func Llistxattr(link string, dest []byte) (sz int, err error) { ...@@ -421,6 +424,7 @@ func Llistxattr(link string, dest []byte) (sz int, err error) {
//sys Munlockall() (err error) //sys Munlockall() (err error)
//sys Nanosleep(time *Timespec, leftover *Timespec) (err error) //sys Nanosleep(time *Timespec, leftover *Timespec) (err error)
//sys Open(path string, mode int, perm uint32) (fd int, err error) //sys Open(path string, mode int, perm uint32) (fd int, err error)
//sys Openat(fdat int, path string, mode int, perm uint32) (fd int, err error)
//sys Pathconf(path string, name int) (val int, err error) //sys Pathconf(path string, name int) (val int, err error)
//sys Pread(fd int, p []byte, offset int64) (n int, err error) //sys Pread(fd int, p []byte, offset int64) (n int, err error)
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) //sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
......
...@@ -7,6 +7,13 @@ ...@@ -7,6 +7,13 @@
package unix_test package unix_test
import ( import (
"flag"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"testing" "testing"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
...@@ -18,3 +25,266 @@ func TestSysctlUint64(t *testing.T) { ...@@ -18,3 +25,266 @@ func TestSysctlUint64(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
} }
// FIXME: Infrastructure for launching tests in subprocesses stolen from openbsd_test.go - refactor?
// testCmd generates a proper command that, when executed, runs the test
// corresponding to the given key.
type testProc struct {
fn func() // should always exit instead of returning
arg func(t *testing.T) string // generate argument for test
cleanup func(arg string) error // for instance, delete coredumps from testing pledge
success bool // whether zero-exit means success or failure
}
var (
testProcs = map[string]testProc{}
procName = ""
procArg = ""
)
const (
optName = "sys-unix-internal-procname"
optArg = "sys-unix-internal-arg"
)
func init() {
flag.StringVar(&procName, optName, "", "internal use only")
flag.StringVar(&procArg, optArg, "", "internal use only")
}
func testCmd(procName string, procArg string) (*exec.Cmd, error) {
exe, err := filepath.Abs(os.Args[0])
if err != nil {
return nil, err
}
cmd := exec.Command(exe, "-"+optName+"="+procName, "-"+optArg+"="+procArg)
cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
return cmd, nil
}
// ExitsCorrectly is a comprehensive, one-line-of-use wrapper for testing
// a testProc with a key.
func ExitsCorrectly(t *testing.T, procName string) {
s := testProcs[procName]
arg := "-"
if s.arg != nil {
arg = s.arg(t)
}
c, err := testCmd(procName, arg)
defer func(arg string) {
if err := s.cleanup(arg); err != nil {
t.Fatalf("Failed to run cleanup for %s %s %#v", procName, err, err)
}
}(arg)
if err != nil {
t.Fatalf("Failed to construct command for %s", procName)
}
if (c.Run() == nil) != s.success {
result := "succeed"
if !s.success {
result = "fail"
}
t.Fatalf("Process did not %s when it was supposed to", result)
}
}
func TestMain(m *testing.M) {
flag.Parse()
if procName != "" {
t := testProcs[procName]
t.fn()
os.Stderr.WriteString("test function did not exit\n")
if t.success {
os.Exit(1)
} else {
os.Exit(0)
}
}
os.Exit(m.Run())
}
// end of infrastructure
const testfile = "gocapmodetest"
const testfile2 = testfile + "2"
func CapEnterTest() {
_, err := os.OpenFile(path.Join(procArg, testfile), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
panic(fmt.Sprintf("OpenFile: %s", err))
}
err = unix.CapEnter()
if err != nil {
panic(fmt.Sprintf("CapEnter: %s", err))
}
_, err = os.OpenFile(path.Join(procArg, testfile2), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err == nil {
panic("OpenFile works!")
}
if err.(*os.PathError).Err != unix.ECAPMODE {
panic(fmt.Sprintf("OpenFile failed wrong: %s %#v", err, err))
}
os.Exit(0)
}
func makeTempDir(t *testing.T) string {
d, err := ioutil.TempDir("", "go_openat_test")
if err != nil {
t.Fatalf("TempDir failed: %s", err)
}
return d
}
func removeTempDir(arg string) error {
err := os.RemoveAll(arg)
if err != nil && err.(*os.PathError).Err == unix.ENOENT {
return nil
}
return err
}
func init() {
testProcs["cap_enter"] = testProc{
CapEnterTest,
makeTempDir,
removeTempDir,
true,
}
}
func TestCapEnter(t *testing.T) {
ExitsCorrectly(t, "cap_enter")
}
func OpenatTest() {
f, err := os.Open(procArg)
if err != nil {
panic(err)
}
err = unix.CapEnter()
if err != nil {
panic(fmt.Sprintf("CapEnter: %s", err))
}
fxx, err := unix.Openat(int(f.Fd()), "xx", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
panic(err)
}
unix.Close(fxx)
// The right to open BASE/xx is not ambient
_, err = os.OpenFile(procArg+"/xx", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err == nil {
panic("OpenFile succeeded")
}
if err.(*os.PathError).Err != unix.ECAPMODE {
panic(fmt.Sprintf("OpenFile failed wrong: %s %#v", err, err))
}
// Can't make a new directory either
err = os.Mkdir(procArg+"2", 0777)
if err == nil {
panic("MKdir succeeded")
}
if err.(*os.PathError).Err != unix.ECAPMODE {
panic(fmt.Sprintf("Mkdir failed wrong: %s %#v", err, err))
}
// Remove all caps except read and lookup.
r, err := unix.CapRightsInit([]uint64{unix.CAP_READ, unix.CAP_LOOKUP})
if err != nil {
panic(fmt.Sprintf("CapRightsInit failed: %s %#v", err, err))
}
err = unix.CapRightsLimit(f.Fd(), r)
if err != nil {
panic(fmt.Sprintf("CapRightsLimit failed: %s %#v", err, err))
}
// Check we can get the rights back again
r, err = unix.CapRightsGet(f.Fd())
if err != nil {
panic(fmt.Sprintf("CapRightsGet failed: %s %#v", err, err))
}
b, err := unix.CapRightsIsSet(r, []uint64{unix.CAP_READ, unix.CAP_LOOKUP})
if err != nil {
panic(fmt.Sprintf("CapRightsIsSet failed: %s %#v", err, err))
}
if !b {
panic(fmt.Sprintf("Unexpected rights"))
}
b, err = unix.CapRightsIsSet(r, []uint64{unix.CAP_READ, unix.CAP_LOOKUP, unix.CAP_WRITE})
if err != nil {
panic(fmt.Sprintf("CapRightsIsSet failed: %s %#v", err, err))
}
if b {
panic(fmt.Sprintf("Unexpected rights (2)"))
}
// Can no longer create a file
_, err = unix.Openat(int(f.Fd()), "xx2", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err == nil {
panic("Openat succeeded")
}
if err != unix.ENOTCAPABLE {
panic(fmt.Sprintf("OpenFileAt failed wrong: %s %#v", err, err))
}
// But can read an existing one
_, err = unix.Openat(int(f.Fd()), "xx", os.O_RDONLY, 0666)
if err != nil {
panic(fmt.Sprintf("Openat failed: %s %#v", err, err))
}
os.Exit(0)
}
func init() {
testProcs["openat"] = testProc{
OpenatTest,
makeTempDir,
removeTempDir,
true,
}
}
func TestOpenat(t *testing.T) {
ExitsCorrectly(t, "openat")
}
func TestCapRightsSetAndClear(t *testing.T) {
r, err := unix.CapRightsInit([]uint64{unix.CAP_READ, unix.CAP_WRITE, unix.CAP_PDWAIT})
if err != nil {
t.Fatalf("CapRightsInit failed: %s", err)
}
err = unix.CapRightsSet(r, []uint64{unix.CAP_EVENT, unix.CAP_LISTEN})
if err != nil {
t.Fatalf("CapRightsSet failed: %s", err)
}
b, err := unix.CapRightsIsSet(r, []uint64{unix.CAP_READ, unix.CAP_WRITE, unix.CAP_PDWAIT, unix.CAP_EVENT, unix.CAP_LISTEN})
if err != nil {
t.Fatalf("CapRightsIsSet failed: %s", err)
}
if !b {
t.Fatalf("Wrong rights set")
}
err = unix.CapRightsClear(r, []uint64{unix.CAP_READ, unix.CAP_PDWAIT})
if err != nil {
t.Fatalf("CapRightsClear failed: %s", err)
}
b, err = unix.CapRightsIsSet(r, []uint64{unix.CAP_WRITE, unix.CAP_EVENT, unix.CAP_LISTEN})
if err != nil {
t.Fatalf("CapRightsIsSet failed: %s", err)
}
if !b {
t.Fatalf("Wrong rights set")
}
}
...@@ -21,6 +21,7 @@ package unix ...@@ -21,6 +21,7 @@ package unix
#include <termios.h> #include <termios.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <sys/capability.h>
#include <sys/event.h> #include <sys/event.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/mount.h> #include <sys/mount.h>
...@@ -130,7 +131,10 @@ struct if_data8 { ...@@ -130,7 +131,10 @@ struct if_data8 {
u_long ifi_iqdrops; u_long ifi_iqdrops;
u_long ifi_noproto; u_long ifi_noproto;
u_long ifi_hwassist; u_long ifi_hwassist;
// FIXME: these are now unions, so maybe need to change definitions?
#undef ifi_epoch
time_t ifi_epoch; time_t ifi_epoch;
#undef ifi_lastchange
struct timeval ifi_lastchange; struct timeval ifi_lastchange;
}; };
...@@ -351,3 +355,7 @@ type BpfZbufHeader C.struct_bpf_zbuf_header ...@@ -351,3 +355,7 @@ type BpfZbufHeader C.struct_bpf_zbuf_header
// Terminal handling // Terminal handling
type Termios C.struct_termios type Termios C.struct_termios
// Capabilities
type CapRights C.struct_cap_rights
This source diff could not be displayed because it is too large. You can view the blob instead.
// mksyscall.pl -tags freebsd,amd64 syscall_bsd.go syscall_freebsd.go syscall_freebsd_amd64.go // mksyscall.pl -tags freebsd,amd64 syscall_bsd.go syscall_freebsd.go syscall_freebsd_amd64.go
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT // Code generated by the command above; see README.md. DO NOT EDIT.
// +build freebsd,amd64 // +build freebsd,amd64
...@@ -303,6 +303,36 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { ...@@ -303,6 +303,36 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func CapEnter() (err error) {
_, _, e1 := Syscall(SYS_CAP_ENTER, 0, 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func capRightsGet(version int, fd int, rightsp *CapRights) (err error) {
_, _, e1 := Syscall(SYS___CAP_RIGHTS_GET, uintptr(version), uintptr(fd), uintptr(unsafe.Pointer(rightsp)))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func capRightsLimit(fd int, rightsp *CapRights) (err error) {
_, _, e1 := Syscall(SYS_CAP_RIGHTS_LIMIT, uintptr(fd), uintptr(unsafe.Pointer(rightsp)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Chdir(path string) (err error) { func Chdir(path string) (err error) {
var _p0 *byte var _p0 *byte
_p0, err = BytePtrFromString(path) _p0, err = BytePtrFromString(path)
...@@ -1113,6 +1143,22 @@ func Open(path string, mode int, perm uint32) (fd int, err error) { ...@@ -1113,6 +1143,22 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Openat(fdat int, path string, mode int, perm uint32) (fd int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(fdat), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0)
fd = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Pathconf(path string, name int) (val int, err error) { func Pathconf(path string, name int) (val int, err error) {
var _p0 *byte var _p0 *byte
_p0, err = BytePtrFromString(path) _p0, err = BytePtrFromString(path)
......
This diff is collapsed.
// cgo -godefs types_freebsd.go | go run mkpost.go
// Code generated by the command above; see README.md. DO NOT EDIT.
// +build amd64,freebsd // +build amd64,freebsd
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_freebsd.go
package unix package unix
...@@ -85,7 +86,7 @@ type Stat_t struct { ...@@ -85,7 +86,7 @@ type Stat_t struct {
Ctimespec Timespec Ctimespec Timespec
Size int64 Size int64
Blocks int64 Blocks int64
Blksize uint32 Blksize int32
Flags uint32 Flags uint32
Gen uint32 Gen uint32
Lspare int32 Lspare int32
...@@ -324,31 +325,31 @@ type IfMsghdr struct { ...@@ -324,31 +325,31 @@ type IfMsghdr struct {
} }
type ifData struct { type ifData struct {
Type uint8 Type uint8
Physical uint8 Physical uint8
Addrlen uint8 Addrlen uint8
Hdrlen uint8 Hdrlen uint8
Link_state uint8 Link_state uint8
Vhid uint8 Vhid uint8
Baudrate_pf uint8 Datalen uint16
Datalen uint8 Mtu uint32
Mtu uint64 Metric uint32
Metric uint64 Baudrate uint64
Baudrate uint64 Ipackets uint64
Ipackets uint64 Ierrors uint64
Ierrors uint64 Opackets uint64
Opackets uint64 Oerrors uint64
Oerrors uint64 Collisions uint64
Collisions uint64 Ibytes uint64
Ibytes uint64 Obytes uint64
Obytes uint64 Imcasts uint64
Imcasts uint64 Omcasts uint64
Omcasts uint64 Iqdrops uint64
Iqdrops uint64 Oqdrops uint64
Noproto uint64 Noproto uint64
Hwassist uint64 Hwassist uint64
Epoch int64 X__ifi_epoch [8]byte
Lastchange Timeval X__ifi_lastchange [16]byte
} }
type IfData struct { type IfData struct {
...@@ -503,3 +504,7 @@ type Termios struct { ...@@ -503,3 +504,7 @@ type Termios struct {
Ispeed uint32 Ispeed uint32
Ospeed uint32 Ospeed uint32
} }
type CapRights struct {
Rights [2]uint64
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment