// 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.

//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris

package socket

import (
	
	

	
)

//go:linkname syscall_getsockopt syscall.getsockopt
func syscall_getsockopt(, ,  int,  unsafe.Pointer,  *uint32) error

//go:linkname syscall_setsockopt syscall.setsockopt
func syscall_setsockopt(, ,  int,  unsafe.Pointer,  uintptr) error

func getsockopt( uintptr, ,  int,  []byte) (int, error) {
	 := uint32(len())
	 := syscall_getsockopt(int(), , , unsafe.Pointer(&[0]), &)
	return int(), 
}

func setsockopt( uintptr, ,  int,  []byte) error {
	return syscall_setsockopt(int(), , , unsafe.Pointer(&[0]), uintptr(len()))
}

func recvmsg( uintptr,  [][]byte,  []byte,  int,  string) (,  int,  int,  net.Addr,  error) {
	var  unix.Sockaddr
	, , , ,  = unix.RecvmsgBuffers(int(), , , )
	if  != nil {
		 = sockaddrToAddr(, )
	}
	return
}

func sendmsg( uintptr,  [][]byte,  []byte,  net.Addr,  int) (int, error) {
	var  unix.Sockaddr
	if  != nil {
		 = addrToSockaddr()
	}
	return unix.SendmsgBuffers(int(), , , , )
}

// addrToSockaddr converts a net.Addr to a unix.Sockaddr.
func addrToSockaddr( net.Addr) unix.Sockaddr {
	var (
		   net.IP
		 int
		 string
	)
	switch a := .(type) {
	case *net.TCPAddr:
		 = .IP
		 = .Port
		 = .Zone
	case *net.UDPAddr:
		 = .IP
		 = .Port
		 = .Zone
	case *net.IPAddr:
		 = .IP
		 = .Zone
	default:
		return nil
	}

	if  := .To4();  != nil {
		 := unix.SockaddrInet4{Port: }
		copy(.Addr[:], )
		return &
	}

	if  := .To16();  != nil && .To4() == nil {
		 := unix.SockaddrInet6{Port: }
		copy(.Addr[:], )
		if  != "" {
			.ZoneId = uint32(zoneCache.index())
		}
		return &
	}

	return nil
}

// sockaddrToAddr converts a unix.Sockaddr to a net.Addr.
func sockaddrToAddr( unix.Sockaddr,  string) net.Addr {
	var (
		   net.IP
		 int
		 string
	)
	switch sa := .(type) {
	case *unix.SockaddrInet4:
		 = make(net.IP, net.IPv4len)
		copy(, .Addr[:])
		 = .Port
	case *unix.SockaddrInet6:
		 = make(net.IP, net.IPv6len)
		copy(, .Addr[:])
		 = .Port
		if .ZoneId > 0 {
			 = zoneCache.name(int(.ZoneId))
		}
	default:
		return nil
	}

	switch  {
	case "tcp", "tcp4", "tcp6":
		return &net.TCPAddr{IP: , Port: , Zone: }
	case "udp", "udp4", "udp6":
		return &net.UDPAddr{IP: , Port: , Zone: }
	default:
		return &net.IPAddr{IP: , Zone: }
	}
}