func parseAllowedIP(aip *wgh.WGAIPIO) net.IPNet {
	switch aip.Af {
	case unix.AF_INET:
		return net.IPNet{
			IP:   net.IP(aip.Addr[:net.IPv4len]),
			Mask: net.CIDRMask(int(aip.Cidr), 32),
		}
	case unix.AF_INET6:
		return net.IPNet{
			IP:   net.IP(aip.Addr[:]),
			Mask: net.CIDRMask(int(aip.Cidr), 128),
		}
	default:
		panicf("wgopenbsd: invalid address family for allowed IP: %+v", aip)
		return net.IPNet{}
	}
}
parseAllowedIP unpacks a net.IPNet from a WGAIP structure.
package wgopenbsd
import (
	"bytes"
	"encoding/binary"
	"fmt"
	"net"
	"os"
	"runtime"
	"time"
	"unsafe"
	"golang.org/x/sys/unix"
	"golang.zx2c4.com/wireguard/wgctrl/internal/wginternal"
	"golang.zx2c4.com/wireguard/wgctrl/internal/wgopenbsd/internal/wgh"
	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
)
var (
	ifGroupWG = [16]byte{0: 'w', 1: 'g'}
)
var _ wginternal.Client = &Client{}
type Client struct {
	close           func() error
	ioctlIfgroupreq func(ifg *wgh.Ifgroupreq) error
	ioctlWGDataIO   func(data *wgh.WGDataIO) error
}
func New() (*Client, bool, error) {
	fd, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, 0)
	if err != nil {
		return nil, false, err
	}
	return &Client{
		close:           func() error { return unix.Close(fd) },
		ioctlIfgroupreq: ioctlIfgroupreq(fd),
		ioctlWGDataIO:   ioctlWGDataIO(fd),
	}, true, nil
}
func (c *Client) Close() error {
	return c.close()
}
func (c *Client) Devices() ([]*wgtypes.Device, error) {
	ifg := wgh.Ifgroupreq{
		Name: ifGroupWG,
	}
	if err := c.ioctlIfgroupreq(&ifg); err != nil {
		return nil, err
	}
	ifgrs := make([]wgh.Ifgreq, ifg.Len/wgh.SizeofIfgreq)
	ifg.Groups = &ifgrs[0]
	if err := c.ioctlIfgroupreq(&ifg); err != nil {
		return nil, err
	}
	runtime.KeepAlive(&ifg)
	devices := make([]*wgtypes.Device, 0, len(ifgrs))
	for _, ifgr := range ifgrs {
		d, err := c.Device(string(bytes.TrimRight(ifgr.Ifgrqu[:], "\x00")))
		if err != nil {
			return nil, err
		}
		devices = append(devices, d)
	}
	return devices, nil
}
func (c *Client) Device(name string) (*wgtypes.Device, error) {
	dname, err := deviceName(name)
	if err != nil {
		return nil, err
	}
	data := wgh.WGDataIO{Name: dname}
	var mem []byte
	for {
		if err := c.ioctlWGDataIO(&data); err != nil {
			switch err.(*os.SyscallError).Err {
			case unix.ENXIO, unix.ENOTTY:
				return nil, os.ErrNotExist
			default:
				return nil, err
			}
		}
		if len(mem) >= int(data.Size) {
			break
		}
		if data.Size < wgh.SizeofWGInterfaceIO {
			return nil, fmt.Errorf("wgopenbsd: kernel returned unexpected number of bytes for WGInterfaceIO: %d", data.Size)
		}
		mem = make([]byte, data.Size)
		data.Interface = (*wgh.WGInterfaceIO)(unsafe.Pointer(&mem[0]))
	}
	return parseDevice(name, data.Interface)
}
func parseDevice(name string, ifio *wgh.WGInterfaceIO) (*wgtypes.Device, error) {
	d := &wgtypes.Device{
		Name: name,
		Type: wgtypes.OpenBSDKernel,
	}
	if ifio.Flags&wgh.WG_INTERFACE_HAS_PRIVATE != 0 {
		d.PrivateKey = wgtypes.Key(ifio.Private)
	}
	if ifio.Flags&wgh.WG_INTERFACE_HAS_PUBLIC != 0 {
		d.PublicKey = wgtypes.Key(ifio.Public)
	}
	if ifio.Flags&wgh.WG_INTERFACE_HAS_PORT != 0 {
		d.ListenPort = int(ifio.Port)
	}
	if ifio.Flags&wgh.WG_INTERFACE_HAS_RTABLE != 0 {
		d.FirewallMark = int(ifio.Rtable)
	}
	d.Peers = make([]wgtypes.Peer, 0, ifio.Peers_count)
	if ifio.Peers_count == 0 {
		return d, nil
	}
	peer := (*wgh.WGPeerIO)(unsafe.Pointer(
		uintptr(unsafe.Pointer(ifio)) + wgh.SizeofWGInterfaceIO,
	))
	for i := 0; i < int(ifio.Peers_count); i++ {
		p := parsePeer(peer)
		p.AllowedIPs = make([]net.IPNet, 0, peer.Aips_count)
		for j := uintptr(0); j < uintptr(peer.Aips_count); j++ {
			aip := (*wgh.WGAIPIO)(unsafe.Pointer(
				uintptr(unsafe.Pointer(peer)) + wgh.SizeofWGPeerIO + j*wgh.SizeofWGAIPIO,
			))
			p.AllowedIPs = append(p.AllowedIPs, parseAllowedIP(aip))
		}
		d.Peers = append(d.Peers, p)
		peer = (*wgh.WGPeerIO)(unsafe.Pointer(
			uintptr(unsafe.Pointer(peer)) + wgh.SizeofWGPeerIO +
				uintptr(peer.Aips_count)*wgh.SizeofWGAIPIO,
		))
	}
	return d, nil
}
func (c *Client) ConfigureDevice(name string, cfg wgtypes.Config) error {
	if _, err := c.Device(name); err != nil {
		return err
	}
	return wginternal.ErrReadOnly
}
func deviceName(name string) ([16]byte, error) {
	var out [unix.IFNAMSIZ]byte
	if len(name) > unix.IFNAMSIZ {
		return out, fmt.Errorf("wgopenbsd: interface name %q too long", name)
	}
	copy(out[:], name)
	return out, nil
}
func parsePeer(pio *wgh.WGPeerIO) wgtypes.Peer {
	p := wgtypes.Peer{
		ReceiveBytes:    int64(pio.Rxbytes),
		TransmitBytes:   int64(pio.Txbytes),
		ProtocolVersion: int(pio.Protocol_version),
	}
	if pio.Last_handshake.Sec > 0 && pio.Last_handshake.Nsec > 0 {
		p.LastHandshakeTime = time.Unix(
			pio.Last_handshake.Sec,
			int64(pio.Last_handshake.Nsec),
		)
	}
	if pio.Flags&wgh.WG_PEER_HAS_PUBLIC != 0 {
		p.PublicKey = wgtypes.Key(pio.Public)
	}
	if pio.Flags&wgh.WG_PEER_HAS_PSK != 0 {
		p.PresharedKey = wgtypes.Key(pio.Psk)
	}
	if pio.Flags&wgh.WG_PEER_HAS_PKA != 0 {
		p.PersistentKeepaliveInterval = time.Duration(pio.Pka) * time.Second
	}
	if pio.Flags&wgh.WG_PEER_HAS_ENDPOINT != 0 {
		p.Endpoint = parseEndpoint(pio.Endpoint)
	}
	return p
}