package route
import
type Addr interface {
Family() int
}
type LinkAddr struct {
Index int
Name string
Addr []byte
}
func ( *LinkAddr) () int { return sysAF_LINK }
func ( *LinkAddr) () (int, int) {
:= 8 + len(.Name) + len(.Addr)
return , roundup()
}
func ( *LinkAddr) ( []byte) (int, error) {
, := .lenAndSpace()
if len() < {
return 0, errShortBuffer
}
, := len(.Name), len(.Addr)
if > 255 || > 255 {
return 0, errInvalidAddr
}
[0] = byte()
[1] = sysAF_LINK
if .Index > 0 {
nativeEndian.PutUint16([2:4], uint16(.Index))
}
:= [8:]
if > 0 {
[5] = byte()
copy([:], .Name)
= [:]
}
if > 0 {
[6] = byte()
copy([:], .Addr)
= [:]
}
return , nil
}
func ( []byte) (Addr, error) {
if len() < 8 {
return nil, errInvalidAddr
}
, , := parseKernelLinkAddr(sysAF_LINK, [4:])
if != nil {
return nil,
}
.(*LinkAddr).Index = int(nativeEndian.Uint16([2:4]))
return , nil
}
func ( int, []byte) (int, Addr, error) {
, , := int([1]), int([2]), int([3])
if == 0xff {
= 0
}
if == 0xff {
= 0
}
if == 0xff {
= 0
}
:= 4 + + +
if len() < {
return 0, nil, errInvalidAddr
}
:= [4:]
var string
var []byte
if > 0 {
= string([:])
= [:]
}
if > 0 {
= [:]
= [:]
}
return , &LinkAddr{Name: , Addr: }, nil
}
type Inet4Addr struct {
IP [4]byte
}
func ( *Inet4Addr) () int { return sysAF_INET }
func ( *Inet4Addr) () (int, int) {
return sizeofSockaddrInet, roundup(sizeofSockaddrInet)
}
func ( *Inet4Addr) ( []byte) (int, error) {
, := .lenAndSpace()
if len() < {
return 0, errShortBuffer
}
[0] = byte()
[1] = sysAF_INET
copy([4:8], .IP[:])
return , nil
}
type Inet6Addr struct {
IP [16]byte
ZoneID int
}
func ( *Inet6Addr) () int { return sysAF_INET6 }
func ( *Inet6Addr) () (int, int) {
return sizeofSockaddrInet6, roundup(sizeofSockaddrInet6)
}
func ( *Inet6Addr) ( []byte) (int, error) {
, := .lenAndSpace()
if len() < {
return 0, errShortBuffer
}
[0] = byte()
[1] = sysAF_INET6
copy([8:24], .IP[:])
if .ZoneID > 0 {
nativeEndian.PutUint32([24:28], uint32(.ZoneID))
}
return , nil
}
func ( int, []byte) (Addr, error) {
switch {
case sysAF_INET:
if len() < sizeofSockaddrInet {
return nil, errInvalidAddr
}
:= &Inet4Addr{}
copy(.IP[:], [4:8])
return , nil
case sysAF_INET6:
if len() < sizeofSockaddrInet6 {
return nil, errInvalidAddr
}
:= &Inet6Addr{ZoneID: int(nativeEndian.Uint32([24:28]))}
copy(.IP[:], [8:24])
if .IP[0] == 0xfe && .IP[1]&0xc0 == 0x80 || .IP[0] == 0xff && (.IP[1]&0x0f == 0x01 || .IP[1]&0x0f == 0x02) {
:= int(bigEndian.Uint16(.IP[2:4]))
if != 0 {
.ZoneID =
.IP[2], .IP[3] = 0, 0
}
}
return , nil
default:
return nil, errInvalidAddr
}
}
func ( int, []byte) (int, Addr, error) {
:= int([0])
if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
if == 0 || len() > roundup() {
= roundup()
}
} else {
= roundup()
}
if len() < {
return 0, nil, errInvalidAddr
}
const (
= 4
= 8
)
switch {
case [0] == sizeofSockaddrInet6:
:= &Inet6Addr{}
copy(.IP[:], [:+16])
return int([0]), , nil
case == sysAF_INET6:
:= &Inet6Addr{}
if -1 < {
copy(.IP[:], [1:])
} else {
copy(.IP[:], [-:])
}
return int([0]), , nil
case [0] == sizeofSockaddrInet:
:= &Inet4Addr{}
copy(.IP[:], [:+4])
return int([0]), , nil
default:
:= &Inet4Addr{}
if -1 < {
copy(.IP[:], [1:])
} else {
copy(.IP[:], [-:])
}
return int([0]), , nil
}
}
type DefaultAddr struct {
af int
Raw []byte
}
func ( *DefaultAddr) () int { return .af }
func ( *DefaultAddr) () (int, int) {
:= len(.Raw)
return , roundup()
}
func ( *DefaultAddr) ( []byte) (int, error) {
, := .lenAndSpace()
if len() < {
return 0, errShortBuffer
}
if > 255 {
return 0, errInvalidAddr
}
[1] = byte()
copy([:], .Raw)
return , nil
}
func ( []byte) (Addr, error) {
if len() < 2 || len() < int([0]) {
return nil, errInvalidAddr
}
:= &DefaultAddr{af: int([1]), Raw: [:[0]]}
return , nil
}
func ( []Addr) int {
var int
for , := range {
switch a := .(type) {
case *LinkAddr:
, := .lenAndSpace()
+=
case *Inet4Addr:
, := .lenAndSpace()
+=
case *Inet6Addr:
, := .lenAndSpace()
+=
case *DefaultAddr:
, := .lenAndSpace()
+=
}
}
return
}
func ( []byte, []Addr) (uint, error) {
var uint
for , := range {
switch a := .(type) {
case *LinkAddr:
, := .marshal()
if != nil {
return 0,
}
= [:]
|= 1 << uint()
case *Inet4Addr:
, := .marshal()
if != nil {
return 0,
}
= [:]
|= 1 << uint()
case *Inet6Addr:
, := .marshal()
if != nil {
return 0,
}
= [:]
|= 1 << uint()
case *DefaultAddr:
, := .marshal()
if != nil {
return 0,
}
= [:]
|= 1 << uint()
}
}
return , nil
}
func ( uint, func(int, []byte) (int, Addr, error), []byte) ([]Addr, error) {
var [sysRTAX_MAX]Addr
:= int(sysAF_UNSPEC)
for := uint(0); < sysRTAX_MAX && len() >= roundup(0); ++ {
if &(1<<) == 0 {
continue
}
if <= sysRTAX_BRD {
switch [1] {
case sysAF_LINK:
, := parseLinkAddr()
if != nil {
return nil,
}
[] =
:= roundup(int([0]))
if len() < {
return nil, errMessageTooShort
}
= [:]
case sysAF_INET, sysAF_INET6:
= int([1])
, := parseInetAddr(, )
if != nil {
return nil,
}
[] =
:= roundup(int([0]))
if len() < {
return nil, errMessageTooShort
}
= [:]
default:
, , := (, )
if != nil {
return nil,
}
[] =
:= roundup()
if len() < {
= [:]
} else {
= [:]
}
}
} else {
, := parseDefaultAddr()
if != nil {
return nil,
}
[] =
:= roundup(int([0]))
if len() < {
return nil, errMessageTooShort
}
= [:]
}
}
return [:], nil
}