package syscall
import (
)
var (
freebsdConfArch string
minRoutingSockaddrLen = rsaAlignOf(0)
)
func ( int) int {
:= sizeofPtr
if darwin64Bit {
= 4
} else if netbsd32Bit {
= 8
} else if runtime.GOOS == "freebsd" {
if freebsdConfArch == "amd64" {
= 8
}
}
if == 0 {
return
}
return ( + - 1) & ^( - 1)
}
func ( []byte) (*SockaddrDatalink, error) {
if len() < 8 {
return nil, EINVAL
}
, , := parseLinkLayerAddr([4:])
if != nil {
return nil,
}
:= (*RawSockaddrDatalink)(unsafe.Pointer(&[0]))
.Len = .Len
.Family = .Family
.Index = .Index
return , nil
}
func ( []byte) (*SockaddrDatalink, int, error) {
type struct {
byte
byte
byte
byte
}
:= (*)(unsafe.Pointer(&[0]))
:= 4 + int(.) + int(.) + int(.)
if len() < {
return nil, 0, EINVAL
}
= [4:]
:= &SockaddrDatalink{Type: ., Nlen: ., Alen: ., Slen: .}
for := 0; len(.Data) > && < -4; ++ {
.Data[] = int8([])
}
return , rsaAlignOf(), nil
}
func ( []byte, byte) (Sockaddr, error) {
switch {
case AF_INET:
if len() < SizeofSockaddrInet4 {
return nil, EINVAL
}
:= (*RawSockaddrAny)(unsafe.Pointer(&[0]))
return anyToSockaddr()
case AF_INET6:
if len() < SizeofSockaddrInet6 {
return nil, EINVAL
}
:= (*RawSockaddrAny)(unsafe.Pointer(&[0]))
return anyToSockaddr()
default:
return nil, EINVAL
}
}
const (
offsetofInet4 = int(unsafe.Offsetof(RawSockaddrInet4{}.Addr))
offsetofInet6 = int(unsafe.Offsetof(RawSockaddrInet6{}.Addr))
)
func ( []byte, byte) (Sockaddr, error) {
:= int(rsaAlignOf(int([0])))
if len() < {
return nil, EINVAL
}
switch {
case [0] == SizeofSockaddrInet6:
:= &SockaddrInet6{}
copy(.Addr[:], [offsetofInet6:])
return , nil
case == AF_INET6:
:= &SockaddrInet6{}
if -1 < offsetofInet6 {
copy(.Addr[:], [1:])
} else {
copy(.Addr[:], [-offsetofInet6:])
}
return , nil
case [0] == SizeofSockaddrInet4:
:= &SockaddrInet4{}
copy(.Addr[:], [offsetofInet4:])
return , nil
default:
:= &SockaddrInet4{}
if -1 < offsetofInet4 {
copy(.Addr[:], [1:])
} else {
copy(.Addr[:], [-offsetofInet4:])
}
return , nil
}
}
func (, int) ([]byte, error) {
:= []_C_int{CTL_NET, AF_ROUTE, 0, 0, _C_int(), _C_int()}
:= uintptr(0)
if := sysctl(, nil, &, nil, 0); != nil {
return nil,
}
if == 0 {
return nil, nil
}
:= make([]byte, )
if := sysctl(, &[0], &, nil, 0); != nil {
return nil,
}
return [:], nil
}
type RoutingMessage interface {
sockaddr() ([]Sockaddr, error)
}
const anyMessageLen = int(unsafe.Sizeof(anyMessage{}))
type anyMessage struct {
Msglen uint16
Version uint8
Type uint8
}
type RouteMessage struct {
Header RtMsghdr
Data []byte
}
func ( *RouteMessage) () ([]Sockaddr, error) {
var [RTAX_MAX]Sockaddr
:= .Data[:]
:= uint8(AF_UNSPEC)
for := uint(0); < RTAX_MAX && len() >= minRoutingSockaddrLen; ++ {
if .Header.Addrs&(1<<) == 0 {
continue
}
:= (*RawSockaddr)(unsafe.Pointer(&[0]))
switch .Family {
case AF_LINK:
, := parseSockaddrLink()
if != nil {
return nil,
}
[] =
= [rsaAlignOf(int(.Len)):]
case AF_INET, AF_INET6:
, := parseSockaddrInet(, .Family)
if != nil {
return nil,
}
[] =
= [rsaAlignOf(int(.Len)):]
= .Family
default:
, := parseNetworkLayerAddr(, )
if != nil {
return nil,
}
[] =
= [rsaAlignOf(int([0])):]
}
}
return [:], nil
}
type InterfaceMessage struct {
Header IfMsghdr
Data []byte
}
func ( *InterfaceMessage) () ([]Sockaddr, error) {
var [RTAX_MAX]Sockaddr
if .Header.Addrs&RTA_IFP == 0 {
return nil, nil
}
, := parseSockaddrLink(.Data[:])
if != nil {
return nil,
}
[RTAX_IFP] =
return [:], nil
}
type InterfaceAddrMessage struct {
Header IfaMsghdr
Data []byte
}
func ( *InterfaceAddrMessage) () ([]Sockaddr, error) {
var [RTAX_MAX]Sockaddr
:= .Data[:]
:= uint8(AF_UNSPEC)
for := uint(0); < RTAX_MAX && len() >= minRoutingSockaddrLen; ++ {
if .Header.Addrs&(1<<) == 0 {
continue
}
:= (*RawSockaddr)(unsafe.Pointer(&[0]))
switch .Family {
case AF_LINK:
, := parseSockaddrLink()
if != nil {
return nil,
}
[] =
= [rsaAlignOf(int(.Len)):]
case AF_INET, AF_INET6:
, := parseSockaddrInet(, .Family)
if != nil {
return nil,
}
[] =
= [rsaAlignOf(int(.Len)):]
= .Family
default:
, := parseNetworkLayerAddr(, )
if != nil {
return nil,
}
[] =
= [rsaAlignOf(int([0])):]
}
}
return [:], nil
}
func ( []byte) ( []RoutingMessage, error) {
, := 0, 0
for len() >= anyMessageLen {
++
:= (*anyMessage)(unsafe.Pointer(&[0]))
if .Version != RTM_VERSION {
= [.Msglen:]
continue
}
if := .toRoutingMessage(); == nil {
++
} else {
= append(, )
}
= [.Msglen:]
}
if != len()+ {
return nil, EINVAL
}
return , nil
}
func ( RoutingMessage) ([]Sockaddr, error) {
, := .sockaddr()
if != nil {
return nil,
}
return , nil
}