status-go/vendor/github.com/libp2p/go-sockaddr/sockaddr_bsd.go

145 lines
3.6 KiB
Go

// +build darwin dragonfly freebsd netbsd openbsd
package sockaddr
import (
"syscall"
"unsafe"
"golang.org/x/sys/unix"
)
func sockaddrToAny(sa unix.Sockaddr) (*unix.RawSockaddrAny, Socklen, error) {
if sa == nil {
return nil, 0, syscall.EINVAL
}
switch sa := sa.(type) {
case *unix.SockaddrInet4:
if sa.Port < 0 || sa.Port > 0xFFFF {
return nil, 0, syscall.EINVAL
}
var raw unix.RawSockaddrInet4
raw.Len = unix.SizeofSockaddrInet4
raw.Family = unix.AF_INET
p := (*[2]byte)(unsafe.Pointer(&raw.Port))
p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port)
for i := 0; i < len(sa.Addr); i++ {
raw.Addr[i] = sa.Addr[i]
}
return (*unix.RawSockaddrAny)(unsafe.Pointer(&raw)), Socklen(raw.Len), nil
case *unix.SockaddrInet6:
if sa.Port < 0 || sa.Port > 0xFFFF {
return nil, 0, syscall.EINVAL
}
var raw unix.RawSockaddrInet6
raw.Len = unix.SizeofSockaddrInet6
raw.Family = unix.AF_INET6
p := (*[2]byte)(unsafe.Pointer(&raw.Port))
p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port)
raw.Scope_id = sa.ZoneId
for i := 0; i < len(sa.Addr); i++ {
raw.Addr[i] = sa.Addr[i]
}
return (*unix.RawSockaddrAny)(unsafe.Pointer(&raw)), Socklen(raw.Len), nil
case *unix.SockaddrUnix:
name := sa.Name
n := len(name)
var raw unix.RawSockaddrUnix
if n >= len(raw.Path) || n == 0 {
return nil, 0, syscall.EINVAL
}
raw.Len = byte(3 + n) // 2 for Family, Len; 1 for NUL
raw.Family = unix.AF_UNIX
for i := 0; i < n; i++ {
raw.Path[i] = int8(name[i])
}
return (*unix.RawSockaddrAny)(unsafe.Pointer(&raw)), Socklen(raw.Len), nil
case *unix.SockaddrDatalink:
if sa.Index == 0 {
return nil, 0, syscall.EINVAL
}
var raw unix.RawSockaddrDatalink
raw.Len = sa.Len
raw.Family = unix.AF_LINK
raw.Index = sa.Index
raw.Type = sa.Type
raw.Nlen = sa.Nlen
raw.Alen = sa.Alen
raw.Slen = sa.Slen
for i := 0; i < len(raw.Data); i++ {
raw.Data[i] = sa.Data[i]
}
return (*unix.RawSockaddrAny)(unsafe.Pointer(&raw)), unix.SizeofSockaddrDatalink, nil
}
return nil, 0, syscall.EAFNOSUPPORT
}
func anyToSockaddr(rsa *unix.RawSockaddrAny) (unix.Sockaddr, error) {
if rsa == nil {
return nil, syscall.EINVAL
}
switch rsa.Addr.Family {
case unix.AF_LINK:
pp := (*unix.RawSockaddrDatalink)(unsafe.Pointer(rsa))
sa := new(unix.SockaddrDatalink)
sa.Len = pp.Len
sa.Family = pp.Family
sa.Index = pp.Index
sa.Type = pp.Type
sa.Nlen = pp.Nlen
sa.Alen = pp.Alen
sa.Slen = pp.Slen
for i := 0; i < len(sa.Data); i++ {
sa.Data[i] = pp.Data[i]
}
return sa, nil
case unix.AF_UNIX:
pp := (*unix.RawSockaddrUnix)(unsafe.Pointer(rsa))
if pp.Len < 3 || pp.Len > unix.SizeofSockaddrUnix {
return nil, syscall.EINVAL
}
sa := new(unix.SockaddrUnix)
n := int(pp.Len) - 3 // subtract leading Family, Len, terminating NUL
for i := 0; i < n; i++ {
if pp.Path[i] == 0 {
// found early NUL; assume Len is overestimating
n = i
break
}
}
bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
sa.Name = string(bytes)
return sa, nil
case unix.AF_INET:
pp := (*unix.RawSockaddrInet4)(unsafe.Pointer(rsa))
sa := new(unix.SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
return sa, nil
case unix.AF_INET6:
pp := (*unix.RawSockaddrInet6)(unsafe.Pointer(rsa))
sa := new(unix.SockaddrInet6)
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
sa.ZoneId = pp.Scope_id
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
return sa, nil
}
return nil, syscall.EAFNOSUPPORT
}