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 <tobias.klauser@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com>
Trust: Ian Lance Taylor <iant@golang.org>
diff --git a/unix/syscall_illumos.go b/unix/syscall_illumos.go
index c5c5880..8c53576 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 @@
 	}
 	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 0000000..45c89d0
--- /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 a4860c7..770f8aa 100644
--- a/unix/types_illumos.go
+++ b/unix/types_illumos.go
@@ -42,6 +42,6 @@
 
 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 1137a5a..236f37e 100644
--- a/unix/ztypes_illumos_amd64.go
+++ b/unix/ztypes_illumos_amd64.go
@@ -25,14 +25,14 @@
 	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