Commit dcbb8239 authored by Mikio Hara's avatar Mikio Hara

unix: drop small networking libraries

Those libraries, routing message parsers, netlink message parsers,
berkeley packat filter are linux packet filter, are subsets and just for
the net package of standard library. It would be better keeping,
extending them at the net sub repository instead of here.

Updates golang/go#10150.

Change-Id: I1ca437bea2e2be7f7f8f6496d4db291629f49136
Reviewed-on: https://go-review.googlesource.com/7581Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
Reviewed-by: 's avatarRob Pike <r@golang.org>
parent 0fcda138
// Copyright 2011 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.
// +build darwin dragonfly freebsd netbsd openbsd
// Berkeley packet filter for BSD variants
package unix
import (
"syscall"
"unsafe"
)
func BpfStmt(code, k int) *BpfInsn {
return &BpfInsn{Code: uint16(code), K: uint32(k)}
}
func BpfJump(code, k, jt, jf int) *BpfInsn {
return &BpfInsn{Code: uint16(code), Jt: uint8(jt), Jf: uint8(jf), K: uint32(k)}
}
func BpfBuflen(fd int) (int, error) {
var l int
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGBLEN, uintptr(unsafe.Pointer(&l)))
if err != 0 {
return 0, syscall.Errno(err)
}
return l, nil
}
func SetBpfBuflen(fd, l int) (int, error) {
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSBLEN, uintptr(unsafe.Pointer(&l)))
if err != 0 {
return 0, syscall.Errno(err)
}
return l, nil
}
func BpfDatalink(fd int) (int, error) {
var t int
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGDLT, uintptr(unsafe.Pointer(&t)))
if err != 0 {
return 0, syscall.Errno(err)
}
return t, nil
}
func SetBpfDatalink(fd, t int) (int, error) {
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSDLT, uintptr(unsafe.Pointer(&t)))
if err != 0 {
return 0, syscall.Errno(err)
}
return t, nil
}
func SetBpfPromisc(fd, m int) error {
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCPROMISC, uintptr(unsafe.Pointer(&m)))
if err != 0 {
return syscall.Errno(err)
}
return nil
}
func FlushBpf(fd int) error {
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCFLUSH, 0)
if err != 0 {
return syscall.Errno(err)
}
return nil
}
type ivalue struct {
name [IFNAMSIZ]byte
value int16
}
func BpfInterface(fd int, name string) (string, error) {
var iv ivalue
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGETIF, uintptr(unsafe.Pointer(&iv)))
if err != 0 {
return "", syscall.Errno(err)
}
return name, nil
}
func SetBpfInterface(fd int, name string) error {
var iv ivalue
copy(iv.name[:], []byte(name))
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSETIF, uintptr(unsafe.Pointer(&iv)))
if err != 0 {
return syscall.Errno(err)
}
return nil
}
func BpfTimeout(fd int) (*Timeval, error) {
var tv Timeval
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGRTIMEOUT, uintptr(unsafe.Pointer(&tv)))
if err != 0 {
return nil, syscall.Errno(err)
}
return &tv, nil
}
func SetBpfTimeout(fd int, tv *Timeval) error {
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSRTIMEOUT, uintptr(unsafe.Pointer(tv)))
if err != 0 {
return syscall.Errno(err)
}
return nil
}
func BpfStats(fd int) (*BpfStat, error) {
var s BpfStat
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGSTATS, uintptr(unsafe.Pointer(&s)))
if err != 0 {
return nil, syscall.Errno(err)
}
return &s, nil
}
func SetBpfImmediate(fd, m int) error {
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCIMMEDIATE, uintptr(unsafe.Pointer(&m)))
if err != 0 {
return syscall.Errno(err)
}
return nil
}
func SetBpf(fd int, i []BpfInsn) error {
var p BpfProgram
p.Len = uint32(len(i))
p.Insns = (*BpfInsn)(unsafe.Pointer(&i[0]))
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSETF, uintptr(unsafe.Pointer(&p)))
if err != 0 {
return syscall.Errno(err)
}
return nil
}
func CheckBpfVersion(fd int) error {
var v BpfVersion
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCVERSION, uintptr(unsafe.Pointer(&v)))
if err != 0 {
return syscall.Errno(err)
}
if v.Major != BPF_MAJOR_VERSION || v.Minor != BPF_MINOR_VERSION {
return EINVAL
}
return nil
}
func BpfHeadercmpl(fd int) (int, error) {
var f int
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGHDRCMPLT, uintptr(unsafe.Pointer(&f)))
if err != 0 {
return 0, syscall.Errno(err)
}
return f, nil
}
func SetBpfHeadercmpl(fd, f int) error {
_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSHDRCMPLT, uintptr(unsafe.Pointer(&f)))
if err != 0 {
return syscall.Errno(err)
}
return nil
}
// Copyright 2011 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.
// Linux socket filter
package unix
import (
"syscall"
"unsafe"
)
func LsfStmt(code, k int) *SockFilter {
return &SockFilter{Code: uint16(code), K: uint32(k)}
}
func LsfJump(code, k, jt, jf int) *SockFilter {
return &SockFilter{Code: uint16(code), Jt: uint8(jt), Jf: uint8(jf), K: uint32(k)}
}
func LsfSocket(ifindex, proto int) (int, error) {
var lsall SockaddrLinklayer
s, e := Socket(AF_PACKET, SOCK_RAW, proto)
if e != nil {
return 0, e
}
p := (*[2]byte)(unsafe.Pointer(&lsall.Protocol))
p[0] = byte(proto >> 8)
p[1] = byte(proto)
lsall.Ifindex = ifindex
e = Bind(s, &lsall)
if e != nil {
Close(s)
return 0, e
}
return s, nil
}
type iflags struct {
name [IFNAMSIZ]byte
flags uint16
}
func SetLsfPromisc(name string, m bool) error {
s, e := Socket(AF_INET, SOCK_DGRAM, 0)
if e != nil {
return e
}
defer Close(s)
var ifl iflags
copy(ifl.name[:], []byte(name))
_, _, ep := Syscall(SYS_IOCTL, uintptr(s), SIOCGIFFLAGS, uintptr(unsafe.Pointer(&ifl)))
if ep != 0 {
return syscall.Errno(ep)
}
if m {
ifl.flags |= uint16(IFF_PROMISC)
} else {
ifl.flags &= ^uint16(IFF_PROMISC)
}
_, _, ep = Syscall(SYS_IOCTL, uintptr(s), SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifl)))
if ep != 0 {
return syscall.Errno(ep)
}
return nil
}
func AttachLsf(fd int, i []SockFilter) error {
var p SockFprog
p.Len = uint16(len(i))
p.Filter = (*SockFilter)(unsafe.Pointer(&i[0]))
return setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, unsafe.Pointer(&p), unsafe.Sizeof(p))
}
func DetachLsf(fd int) error {
var dummy int
return setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, unsafe.Pointer(&dummy), unsafe.Sizeof(dummy))
}
// Copyright 2011 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.
// Netlink sockets and messages
package unix
import "unsafe"
// Round the length of a netlink message up to align it properly.
func nlmAlignOf(msglen int) int {
return (msglen + NLMSG_ALIGNTO - 1) & ^(NLMSG_ALIGNTO - 1)
}
// Round the length of a netlink route attribute up to align it
// properly.
func rtaAlignOf(attrlen int) int {
return (attrlen + RTA_ALIGNTO - 1) & ^(RTA_ALIGNTO - 1)
}
// NetlinkRouteRequest represents a request message to receive routing
// and link states from the kernel.
type NetlinkRouteRequest struct {
Header NlMsghdr
Data RtGenmsg
}
func (rr *NetlinkRouteRequest) toWireFormat() []byte {
b := make([]byte, rr.Header.Len)
*(*uint32)(unsafe.Pointer(&b[0:4][0])) = rr.Header.Len
*(*uint16)(unsafe.Pointer(&b[4:6][0])) = rr.Header.Type
*(*uint16)(unsafe.Pointer(&b[6:8][0])) = rr.Header.Flags
*(*uint32)(unsafe.Pointer(&b[8:12][0])) = rr.Header.Seq
*(*uint32)(unsafe.Pointer(&b[12:16][0])) = rr.Header.Pid
b[16] = byte(rr.Data.Family)
return b
}
func newNetlinkRouteRequest(proto, seq, family int) []byte {
rr := &NetlinkRouteRequest{}
rr.Header.Len = uint32(NLMSG_HDRLEN + SizeofRtGenmsg)
rr.Header.Type = uint16(proto)
rr.Header.Flags = NLM_F_DUMP | NLM_F_REQUEST
rr.Header.Seq = uint32(seq)
rr.Data.Family = uint8(family)
return rr.toWireFormat()
}
// NetlinkRIB returns routing information base, as known as RIB, which
// consists of network facility information, states and parameters.
func NetlinkRIB(proto, family int) ([]byte, error) {
s, err := Socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)
if err != nil {
return nil, err
}
defer Close(s)
lsa := &SockaddrNetlink{Family: AF_NETLINK}
if err := Bind(s, lsa); err != nil {
return nil, err
}
wb := newNetlinkRouteRequest(proto, 1, family)
if err := Sendto(s, wb, 0, lsa); err != nil {
return nil, err
}
var tab []byte
rbNew := make([]byte, Getpagesize())
done:
for {
rb := rbNew
nr, _, err := Recvfrom(s, rb, 0)
if err != nil {
return nil, err
}
if nr < NLMSG_HDRLEN {
return nil, EINVAL
}
rb = rb[:nr]
tab = append(tab, rb...)
msgs, err := ParseNetlinkMessage(rb)
if err != nil {
return nil, err
}
for _, m := range msgs {
lsa, err := Getsockname(s)
if err != nil {
return nil, err
}
switch v := lsa.(type) {
case *SockaddrNetlink:
if m.Header.Seq != 1 || m.Header.Pid != v.Pid {
return nil, EINVAL
}
default:
return nil, EINVAL
}
if m.Header.Type == NLMSG_DONE {
break done
}
if m.Header.Type == NLMSG_ERROR {
return nil, EINVAL
}
}
}
return tab, nil
}
// NetlinkMessage represents a netlink message.
type NetlinkMessage struct {
Header NlMsghdr
Data []byte
}
// ParseNetlinkMessage parses b as an array of netlink messages and
// returns the slice containing the NetlinkMessage structures.
func ParseNetlinkMessage(b []byte) ([]NetlinkMessage, error) {
var msgs []NetlinkMessage
for len(b) >= NLMSG_HDRLEN {
h, dbuf, dlen, err := netlinkMessageHeaderAndData(b)
if err != nil {
return nil, err
}
m := NetlinkMessage{Header: *h, Data: dbuf[:int(h.Len)-NLMSG_HDRLEN]}
msgs = append(msgs, m)
b = b[dlen:]
}
return msgs, nil
}
func netlinkMessageHeaderAndData(b []byte) (*NlMsghdr, []byte, int, error) {
h := (*NlMsghdr)(unsafe.Pointer(&b[0]))
if int(h.Len) < NLMSG_HDRLEN || int(h.Len) > len(b) {
return nil, nil, 0, EINVAL
}
return h, b[NLMSG_HDRLEN:], nlmAlignOf(int(h.Len)), nil
}
// NetlinkRouteAttr represents a netlink route attribute.
type NetlinkRouteAttr struct {
Attr RtAttr
Value []byte
}
// ParseNetlinkRouteAttr parses m's payload as an array of netlink
// route attributes and returns the slice containing the
// NetlinkRouteAttr structures.
func ParseNetlinkRouteAttr(m *NetlinkMessage) ([]NetlinkRouteAttr, error) {
var b []byte
switch m.Header.Type {
case RTM_NEWLINK, RTM_DELLINK:
b = m.Data[SizeofIfInfomsg:]
case RTM_NEWADDR, RTM_DELADDR:
b = m.Data[SizeofIfAddrmsg:]
case RTM_NEWROUTE, RTM_DELROUTE:
b = m.Data[SizeofRtMsg:]
default:
return nil, EINVAL
}
var attrs []NetlinkRouteAttr
for len(b) >= SizeofRtAttr {
a, vbuf, alen, err := netlinkRouteAttrAndValue(b)
if err != nil {
return nil, err
}
ra := NetlinkRouteAttr{Attr: *a, Value: vbuf[:int(a.Len)-SizeofRtAttr]}
attrs = append(attrs, ra)
b = b[alen:]
}
return attrs, nil
}
func netlinkRouteAttrAndValue(b []byte) (*RtAttr, []byte, int, error) {
a := (*RtAttr)(unsafe.Pointer(&b[0]))
if int(a.Len) < SizeofRtAttr || int(a.Len) > len(b) {
return nil, nil, 0, EINVAL
}
return a, b[SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil
}
// Copyright 2011 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.
// +build darwin dragonfly freebsd netbsd openbsd
// Routing sockets and messages
package unix
import "unsafe"
// Round the length of a raw sockaddr up to align it properly.
func rsaAlignOf(salen int) int {
salign := sizeofPtr
// NOTE: It seems like 64-bit Darwin kernel still requires
// 32-bit aligned access to BSD subsystem. Also NetBSD 6
// kernel and beyond require 64-bit aligned access to routing
// facilities.
if darwin64Bit {
salign = 4
} else if netbsd32Bit {
salign = 8
}
if salen == 0 {
return salign
}
return (salen + salign - 1) & ^(salign - 1)
}
// RouteRIB returns routing information base, as known as RIB,
// which consists of network facility information, states and
// parameters.
func RouteRIB(facility, param int) ([]byte, error) {
mib := []_C_int{CTL_NET, AF_ROUTE, 0, 0, _C_int(facility), _C_int(param)}
// Find size.
n := uintptr(0)
if err := sysctl(mib, nil, &n, nil, 0); err != nil {
return nil, err
}
if n == 0 {
return nil, nil
}
tab := make([]byte, n)
if err := sysctl(mib, &tab[0], &n, nil, 0); err != nil {
return nil, err
}
return tab[:n], nil
}
// RoutingMessage represents a routing message.
type RoutingMessage interface {
sockaddr() []Sockaddr
}
const anyMessageLen = int(unsafe.Sizeof(anyMessage{}))
type anyMessage struct {
Msglen uint16
Version uint8
Type uint8
}
// RouteMessage represents a routing message containing routing
// entries.
type RouteMessage struct {
Header RtMsghdr
Data []byte
}
const rtaRtMask = RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_GENMASK
func (m *RouteMessage) sockaddr() []Sockaddr {
var (
af int
sas [4]Sockaddr
)
b := m.Data[:]
for i := uint(0); i < RTAX_MAX; i++ {
if m.Header.Addrs&rtaRtMask&(1<<i) == 0 {
continue
}
rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
switch i {
case RTAX_DST, RTAX_GATEWAY:
sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
if err != nil {
return nil
}
if i == RTAX_DST {
af = int(rsa.Family)
}
sas[i] = sa
case RTAX_NETMASK, RTAX_GENMASK:
switch af {
case AF_INET:
rsa4 := (*RawSockaddrInet4)(unsafe.Pointer(&b[0]))
sa := new(SockaddrInet4)
for j := 0; rsa4.Len > 0 && j < int(rsa4.Len)-int(unsafe.Offsetof(rsa4.Addr)); j++ {
sa.Addr[j] = rsa4.Addr[j]
}
sas[i] = sa
case AF_INET6:
rsa6 := (*RawSockaddrInet6)(unsafe.Pointer(&b[0]))
sa := new(SockaddrInet6)
for j := 0; rsa6.Len > 0 && j < int(rsa6.Len)-int(unsafe.Offsetof(rsa6.Addr)); j++ {
sa.Addr[j] = rsa6.Addr[j]
}
sas[i] = sa
}
}
b = b[rsaAlignOf(int(rsa.Len)):]
}
return sas[:]
}
// InterfaceMessage represents a routing message containing
// network interface entries.
type InterfaceMessage struct {
Header IfMsghdr
Data []byte
}
func (m *InterfaceMessage) sockaddr() (sas []Sockaddr) {
if m.Header.Addrs&RTA_IFP == 0 {
return nil
}
sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(&m.Data[0])))
if err != nil {
return nil
}
return append(sas, sa)
}
// InterfaceAddrMessage represents a routing message containing
// network interface address entries.
type InterfaceAddrMessage struct {
Header IfaMsghdr
Data []byte
}
const rtaIfaMask = RTA_IFA | RTA_NETMASK | RTA_BRD
func (m *InterfaceAddrMessage) sockaddr() (sas []Sockaddr) {
if m.Header.Addrs&rtaIfaMask == 0 {
return nil
}
b := m.Data[:]
// We still see AF_UNSPEC in socket addresses on some
// platforms. To identify each address family correctly, we
// will use the address family of RTAX_NETMASK as a preferred
// one on the 32-bit NetBSD kernel, also use the length of
// RTAX_NETMASK socket address on the FreeBSD kernel.
preferredFamily := uint8(AF_UNSPEC)
for i := uint(0); i < RTAX_MAX; i++ {
if m.Header.Addrs&rtaIfaMask&(1<<i) == 0 {
continue
}
rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
switch i {
case RTAX_IFA:
if rsa.Family == AF_UNSPEC {
rsa.Family = preferredFamily
}
sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
if err != nil {
return nil
}
sas = append(sas, sa)
case RTAX_NETMASK:
switch rsa.Family {
case AF_UNSPEC:
switch rsa.Len {
case SizeofSockaddrInet4:
rsa.Family = AF_INET
case SizeofSockaddrInet6:
rsa.Family = AF_INET6
default:
rsa.Family = AF_INET // an old fashion, AF_UNSPEC means AF_INET
}
case AF_INET, AF_INET6:
preferredFamily = rsa.Family
default:
return nil
}
sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
if err != nil {
return nil
}
sas = append(sas, sa)
case RTAX_BRD:
// nothing to do
}
b = b[rsaAlignOf(int(rsa.Len)):]
}
return sas
}
// ParseRoutingMessage parses b as routing messages and returns the
// slice containing the RoutingMessage interfaces.
func ParseRoutingMessage(b []byte) (msgs []RoutingMessage, err error) {
msgCount := 0
for len(b) >= anyMessageLen {
msgCount++
any := (*anyMessage)(unsafe.Pointer(&b[0]))
if any.Version != RTM_VERSION {
b = b[any.Msglen:]
continue
}
msgs = append(msgs, any.toRoutingMessage(b))
b = b[any.Msglen:]
}
// We failed to parse any of the messages - version mismatch?
if msgCount > 0 && len(msgs) == 0 {
return nil, EINVAL
}
return msgs, nil
}
// ParseRoutingMessage parses msg's payload as raw sockaddrs and
// returns the slice containing the Sockaddr interfaces.
func ParseRoutingSockaddr(msg RoutingMessage) (sas []Sockaddr, err error) {
return append(sas, msg.sockaddr()...), nil
}
// Copyright 2011 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.
// Routing sockets and messages for Darwin
package unix
import "unsafe"
func (any *anyMessage) toRoutingMessage(b []byte) RoutingMessage {
switch any.Type {
case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
p := (*RouteMessage)(unsafe.Pointer(any))
return &RouteMessage{Header: p.Header, Data: b[SizeofRtMsghdr:any.Msglen]}
case RTM_IFINFO:
p := (*InterfaceMessage)(unsafe.Pointer(any))
return &InterfaceMessage{Header: p.Header, Data: b[SizeofIfMsghdr:any.Msglen]}
case RTM_NEWADDR, RTM_DELADDR:
p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
return &InterfaceAddrMessage{Header: p.Header, Data: b[SizeofIfaMsghdr:any.Msglen]}
case RTM_NEWMADDR2, RTM_DELMADDR:
p := (*InterfaceMulticastAddrMessage)(unsafe.Pointer(any))
return &InterfaceMulticastAddrMessage{Header: p.Header, Data: b[SizeofIfmaMsghdr2:any.Msglen]}
}
return nil
}
// InterfaceMulticastAddrMessage represents a routing message
// containing network interface address entries.
type InterfaceMulticastAddrMessage struct {
Header IfmaMsghdr2
Data []byte
}
const rtaIfmaMask = RTA_GATEWAY | RTA_IFP | RTA_IFA
func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) {
if m.Header.Addrs&rtaIfmaMask == 0 {
return nil
}
b := m.Data[:]
for i := uint(0); i < RTAX_MAX; i++ {
if m.Header.Addrs&rtaIfmaMask&(1<<i) == 0 {
continue
}
rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
switch i {
case RTAX_IFA:
sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
if e != nil {
return nil
}
sas = append(sas, sa)
case RTAX_GATEWAY, RTAX_IFP:
// nothing to do
}
b = b[rsaAlignOf(int(rsa.Len)):]
}
return sas
}
// Copyright 2011 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.
// Routing sockets and messages for Dragonfly
package unix
import "unsafe"
func (any *anyMessage) toRoutingMessage(b []byte) RoutingMessage {
switch any.Type {
case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
p := (*RouteMessage)(unsafe.Pointer(any))
return &RouteMessage{Header: p.Header, Data: b[SizeofRtMsghdr:any.Msglen]}
case RTM_IFINFO:
p := (*InterfaceMessage)(unsafe.Pointer(any))
return &InterfaceMessage{Header: p.Header, Data: b[SizeofIfMsghdr:any.Msglen]}
case RTM_IFANNOUNCE:
p := (*InterfaceAnnounceMessage)(unsafe.Pointer(any))
return &InterfaceAnnounceMessage{Header: p.Header}
case RTM_NEWADDR, RTM_DELADDR:
p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
return &InterfaceAddrMessage{Header: p.Header, Data: b[SizeofIfaMsghdr:any.Msglen]}
case RTM_NEWMADDR, RTM_DELMADDR:
p := (*InterfaceMulticastAddrMessage)(unsafe.Pointer(any))
return &InterfaceMulticastAddrMessage{Header: p.Header, Data: b[SizeofIfmaMsghdr:any.Msglen]}
}
return nil
}
// InterfaceAnnounceMessage represents a routing message containing
// network interface arrival and departure information.
type InterfaceAnnounceMessage struct {
Header IfAnnounceMsghdr
}
func (m *InterfaceAnnounceMessage) sockaddr() (sas []Sockaddr) { return nil }
// InterfaceMulticastAddrMessage represents a routing message
// containing network interface address entries.
type InterfaceMulticastAddrMessage struct {
Header IfmaMsghdr
Data []byte
}
const rtaIfmaMask = RTA_GATEWAY | RTA_IFP | RTA_IFA
func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) {
if m.Header.Addrs&rtaIfmaMask == 0 {
return nil
}
b := m.Data[:]
for i := uint(0); i < RTAX_MAX; i++ {
if m.Header.Addrs&rtaIfmaMask&(1<<i) == 0 {
continue
}
rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
switch i {
case RTAX_IFA:
sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
if e != nil {
return nil
}
sas = append(sas, sa)
case RTAX_GATEWAY, RTAX_IFP:
// nothing to do
}
b = b[rsaAlignOf(int(rsa.Len)):]
}
return sas
}
// Copyright 2011 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.
// Routing sockets and messages for FreeBSD
package unix
import "unsafe"
// See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
var freebsdVersion uint32
func init() {
freebsdVersion, _ = SysctlUint32("kern.osreldate")
}
func (any *anyMessage) toRoutingMessage(b []byte) RoutingMessage {
switch any.Type {
case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
p := (*RouteMessage)(unsafe.Pointer(any))
return &RouteMessage{Header: p.Header, Data: b[SizeofRtMsghdr:any.Msglen]}
case RTM_IFINFO:
return any.parseInterfaceMessage(b)
case RTM_IFANNOUNCE:
p := (*InterfaceAnnounceMessage)(unsafe.Pointer(any))
return &InterfaceAnnounceMessage{Header: p.Header}
case RTM_NEWADDR, RTM_DELADDR:
p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
return &InterfaceAddrMessage{Header: p.Header, Data: b[SizeofIfaMsghdr:any.Msglen]}
case RTM_NEWMADDR, RTM_DELMADDR:
p := (*InterfaceMulticastAddrMessage)(unsafe.Pointer(any))
return &InterfaceMulticastAddrMessage{Header: p.Header, Data: b[SizeofIfmaMsghdr:any.Msglen]}
}
return nil
}
// InterfaceAnnounceMessage represents a routing message containing
// network interface arrival and departure information.
type InterfaceAnnounceMessage struct {
Header IfAnnounceMsghdr
}
func (m *InterfaceAnnounceMessage) sockaddr() (sas []Sockaddr) { return nil }
// InterfaceMulticastAddrMessage represents a routing message
// containing network interface address entries.
type InterfaceMulticastAddrMessage struct {
Header IfmaMsghdr
Data []byte
}
const rtaIfmaMask = RTA_GATEWAY | RTA_IFP | RTA_IFA
func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) {
if m.Header.Addrs&rtaIfmaMask == 0 {
return nil
}
b := m.Data[:]
for i := uint(0); i < RTAX_MAX; i++ {
if m.Header.Addrs&rtaIfmaMask&(1<<i) == 0 {
continue
}
rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
switch i {
case RTAX_IFA:
sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
if e != nil {
return nil
}
sas = append(sas, sa)
case RTAX_GATEWAY, RTAX_IFP:
// nothing to do
}
b = b[rsaAlignOf(int(rsa.Len)):]
}
return sas
}
// Copyright 2014 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.
// +build freebsd,386 freebsd,arm
package unix
import "unsafe"
func (any *anyMessage) parseInterfaceMessage(b []byte) *InterfaceMessage {
p := (*InterfaceMessage)(unsafe.Pointer(any))
// FreeBSD 10 and beyond have a restructured mbuf
// packet header view.
// See http://svnweb.freebsd.org/base?view=revision&revision=254804.
if freebsdVersion >= 1000000 {
m := (*ifMsghdr)(unsafe.Pointer(any))
p.Header.Data.Hwassist = uint32(m.Data.Hwassist)
p.Header.Data.Epoch = m.Data.Epoch
p.Header.Data.Lastchange = m.Data.Lastchange
return &InterfaceMessage{Header: p.Header, Data: b[sizeofIfMsghdr:any.Msglen]}
}
return &InterfaceMessage{Header: p.Header, Data: b[SizeofIfMsghdr:any.Msglen]}
}
// Copyright 2014 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.
// +build freebsd,amd64
package unix
import "unsafe"
func (any *anyMessage) parseInterfaceMessage(b []byte) *InterfaceMessage {
p := (*InterfaceMessage)(unsafe.Pointer(any))
return &InterfaceMessage{Header: p.Header, Data: b[SizeofIfMsghdr:any.Msglen]}
}
// Copyright 2011 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.
// Routing sockets and messages for NetBSD
package unix
import "unsafe"
func (any *anyMessage) toRoutingMessage(b []byte) RoutingMessage {
switch any.Type {
case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
p := (*RouteMessage)(unsafe.Pointer(any))
return &RouteMessage{Header: p.Header, Data: b[SizeofRtMsghdr:any.Msglen]}
case RTM_IFINFO:
p := (*InterfaceMessage)(unsafe.Pointer(any))
return &InterfaceMessage{Header: p.Header, Data: b[SizeofIfMsghdr:any.Msglen]}
case RTM_IFANNOUNCE:
p := (*InterfaceAnnounceMessage)(unsafe.Pointer(any))
return &InterfaceAnnounceMessage{Header: p.Header}
case RTM_NEWADDR, RTM_DELADDR:
p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
return &InterfaceAddrMessage{Header: p.Header, Data: b[SizeofIfaMsghdr:any.Msglen]}
}
return nil
}
// InterfaceAnnounceMessage represents a routing message containing
// network interface arrival and departure information.
type InterfaceAnnounceMessage struct {
Header IfAnnounceMsghdr
}
func (m *InterfaceAnnounceMessage) sockaddr() (sas []Sockaddr) { return nil }
// Copyright 2011 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.
// Routing sockets and messages for OpenBSD
package unix
import "unsafe"
func (any *anyMessage) toRoutingMessage(b []byte) RoutingMessage {
switch any.Type {
case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
p := (*RouteMessage)(unsafe.Pointer(any))
return &RouteMessage{Header: p.Header, Data: b[SizeofRtMsghdr:any.Msglen]}
case RTM_IFINFO:
p := (*InterfaceMessage)(unsafe.Pointer(any))
return &InterfaceMessage{Header: p.Header, Data: b[SizeofIfMsghdr:any.Msglen]}
case RTM_IFANNOUNCE:
p := (*InterfaceAnnounceMessage)(unsafe.Pointer(any))
return &InterfaceAnnounceMessage{Header: p.Header}
case RTM_NEWADDR, RTM_DELADDR:
p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
return &InterfaceAddrMessage{Header: p.Header, Data: b[SizeofIfaMsghdr:any.Msglen]}
}
return nil
}
// InterfaceAnnounceMessage represents a routing message containing
// network interface arrival and departure information.
type InterfaceAnnounceMessage struct {
Header IfAnnounceMsghdr
}
func (m *InterfaceAnnounceMessage) sockaddr() (sas []Sockaddr) { return nil }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment