From c94f62235c83adae0d1b95637d3970228d00a36f Mon Sep 17 00:00:00 2001 From: Nahum Shalman Date: Tue, 16 Mar 2021 16:49:22 +0000 Subject: [PATCH] unix: add more illumos ioctl wrappers Expose Strioctl and Lifreq structs Add helpers for working with them Add additional wrapper functions This work is in support of wireGuard/wireguard-go#39 Change-Id: I7a4d919f986ec977e2cd393eaf237d8c43bbc1cb Reviewed-on: https://go-review.googlesource.com/c/sys/+/302831 Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Tobias Klauser Trust: Ian Lance Taylor --- unix/syscall_illumos.go | 51 +++++++++++++++++++++++++++++++++++- unix/syscall_illumos_test.go | 26 ++++++++++++++++++ unix/types_illumos.go | 4 +-- unix/ztypes_illumos_amd64.go | 4 +-- 4 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 unix/syscall_illumos_test.go diff --git a/unix/syscall_illumos.go b/unix/syscall_illumos.go index c5c58806..8c535768 100644 --- a/unix/syscall_illumos.go +++ b/unix/syscall_illumos.go @@ -1,4 +1,4 @@ -// Copyright 2009 The Go Authors. All rights reserved. +// Copyright 2021 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. @@ -10,6 +10,8 @@ package unix import ( + "fmt" + "runtime" "unsafe" ) @@ -127,3 +129,50 @@ func Getmsg(fd int, cl []byte, data []byte) (retCl []byte, retData []byte, flags } return retCl, retData, flags, nil } + +func IoctlSetIntRetInt(fd int, req uint, arg int) (int, error) { + return ioctlRet(fd, req, uintptr(arg)) +} + +func IoctlSetString(fd int, req uint, val string) error { + bs := make([]byte, len(val)+1) + copy(bs[:len(bs)-1], val) + err := ioctl(fd, req, uintptr(unsafe.Pointer(&bs[0]))) + runtime.KeepAlive(&bs[0]) + return err +} + +// Lifreq Helpers + +func (l *Lifreq) SetName(name string) error { + if len(name) >= len(l.Name) { + return fmt.Errorf("name cannot be more than %d characters", len(l.Name)-1) + } + for i := range name { + l.Name[i] = int8(name[i]) + } + return nil +} + +func (l *Lifreq) SetLifruInt(d int) { + *(*int)(unsafe.Pointer(&l.Lifru[0])) = d +} + +func (l *Lifreq) GetLifruInt() int { + return *(*int)(unsafe.Pointer(&l.Lifru[0])) +} + +func IoctlLifreq(fd int, req uint, l *Lifreq) error { + return ioctl(fd, req, uintptr(unsafe.Pointer(l))) +} + +// Strioctl Helpers + +func (s *Strioctl) SetInt(i int) { + s.Len = int32(unsafe.Sizeof(i)) + s.Dp = (*int8)(unsafe.Pointer(&i)) +} + +func IoctlSetStrioctlRetInt(fd int, req uint, s *Strioctl) (int, error) { + return ioctlRet(fd, req, uintptr(unsafe.Pointer(s))) +} diff --git a/unix/syscall_illumos_test.go b/unix/syscall_illumos_test.go new file mode 100644 index 00000000..45c89d03 --- /dev/null +++ b/unix/syscall_illumos_test.go @@ -0,0 +1,26 @@ +// Copyright 2021 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. + +//go:build illumos +// +build illumos + +package unix_test + +import ( + "testing" + + "golang.org/x/sys/unix" +) + +func TestLifreqSetName(t *testing.T) { + var l unix.Lifreq + err := l.SetName("12345678901234356789012345678901234567890") + if err == nil { + t.Fatal(`Lifreq.SetName should reject names that are too long`) + } + err = l.SetName("tun0") + if err != nil { + t.Errorf(`Lifreq.SetName("tun0") failed: %v`, err) + } +} diff --git a/unix/types_illumos.go b/unix/types_illumos.go index a4860c77..770f8aa3 100644 --- a/unix/types_illumos.go +++ b/unix/types_illumos.go @@ -42,6 +42,6 @@ const ( type strbuf C.struct_strbuf -type strioctl C.struct_strioctl +type Strioctl C.struct_strioctl -type lifreq C.struct_lifreq +type Lifreq C.struct_lifreq diff --git a/unix/ztypes_illumos_amd64.go b/unix/ztypes_illumos_amd64.go index 1137a5a1..236f37ef 100644 --- a/unix/ztypes_illumos_amd64.go +++ b/unix/ztypes_illumos_amd64.go @@ -25,14 +25,14 @@ type strbuf struct { Buf *int8 } -type strioctl struct { +type Strioctl struct { Cmd int32 Timout int32 Len int32 Dp *int8 } -type lifreq struct { +type Lifreq struct { Name [32]int8 Lifru1 [4]byte Type uint32