123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364 |
- // 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.
- //go:build darwin || dragonfly || freebsd || netbsd || openbsd
- package syscall
- import (
- "runtime"
- "unsafe"
- )
- var (
- freebsdConfArch string // "machine $arch" line in kern.conftxt on freebsd
- minRoutingSockaddrLen = rsaAlignOf(0)
- )
- // Round the length of a raw sockaddr up to align it properly.
- func rsaAlignOf(salen int) int {
- salign := int(sizeofPtr)
- if darwin64Bit {
- // Darwin kernels require 32-bit aligned access to
- // routing facilities.
- salign = 4
- } else if netbsd32Bit {
- // NetBSD 6 and beyond kernels require 64-bit aligned
- // access to routing facilities.
- salign = 8
- } else if runtime.GOOS == "freebsd" {
- // In the case of kern.supported_archs="amd64 i386",
- // we need to know the underlying kernel's
- // architecture because the alignment for routing
- // facilities are set at the build time of the kernel.
- if freebsdConfArch == "amd64" {
- salign = 8
- }
- }
- if salen == 0 {
- return salign
- }
- return (salen + salign - 1) & ^(salign - 1)
- }
- // parseSockaddrLink parses b as a datalink socket address.
- func parseSockaddrLink(b []byte) (*SockaddrDatalink, error) {
- if len(b) < 8 {
- return nil, EINVAL
- }
- sa, _, err := parseLinkLayerAddr(b[4:])
- if err != nil {
- return nil, err
- }
- rsa := (*RawSockaddrDatalink)(unsafe.Pointer(&b[0]))
- sa.Len = rsa.Len
- sa.Family = rsa.Family
- sa.Index = rsa.Index
- return sa, nil
- }
- // parseLinkLayerAddr parses b as a datalink socket address in
- // conventional BSD kernel form.
- func parseLinkLayerAddr(b []byte) (*SockaddrDatalink, int, error) {
- // The encoding looks like the following:
- // +----------------------------+
- // | Type (1 octet) |
- // +----------------------------+
- // | Name length (1 octet) |
- // +----------------------------+
- // | Address length (1 octet) |
- // +----------------------------+
- // | Selector length (1 octet) |
- // +----------------------------+
- // | Data (variable) |
- // +----------------------------+
- type linkLayerAddr struct {
- Type byte
- Nlen byte
- Alen byte
- Slen byte
- }
- lla := (*linkLayerAddr)(unsafe.Pointer(&b[0]))
- l := 4 + int(lla.Nlen) + int(lla.Alen) + int(lla.Slen)
- if len(b) < l {
- return nil, 0, EINVAL
- }
- b = b[4:]
- sa := &SockaddrDatalink{Type: lla.Type, Nlen: lla.Nlen, Alen: lla.Alen, Slen: lla.Slen}
- for i := 0; len(sa.Data) > i && i < l-4; i++ {
- sa.Data[i] = int8(b[i])
- }
- return sa, rsaAlignOf(l), nil
- }
- // parseSockaddrInet parses b as an internet socket address.
- func parseSockaddrInet(b []byte, family byte) (Sockaddr, error) {
- switch family {
- case AF_INET:
- if len(b) < SizeofSockaddrInet4 {
- return nil, EINVAL
- }
- rsa := (*RawSockaddrAny)(unsafe.Pointer(&b[0]))
- return anyToSockaddr(rsa)
- case AF_INET6:
- if len(b) < SizeofSockaddrInet6 {
- return nil, EINVAL
- }
- rsa := (*RawSockaddrAny)(unsafe.Pointer(&b[0]))
- return anyToSockaddr(rsa)
- default:
- return nil, EINVAL
- }
- }
- const (
- offsetofInet4 = int(unsafe.Offsetof(RawSockaddrInet4{}.Addr))
- offsetofInet6 = int(unsafe.Offsetof(RawSockaddrInet6{}.Addr))
- )
- // parseNetworkLayerAddr parses b as an internet socket address in
- // conventional BSD kernel form.
- func parseNetworkLayerAddr(b []byte, family byte) (Sockaddr, error) {
- // The encoding looks similar to the NLRI encoding.
- // +----------------------------+
- // | Length (1 octet) |
- // +----------------------------+
- // | Address prefix (variable) |
- // +----------------------------+
- //
- // The differences between the kernel form and the NLRI
- // encoding are:
- //
- // - The length field of the kernel form indicates the prefix
- // length in bytes, not in bits
- //
- // - In the kernel form, zero value of the length field
- // doesn't mean 0.0.0.0/0 or ::/0
- //
- // - The kernel form appends leading bytes to the prefix field
- // to make the <length, prefix> tuple to be conformed with
- // the routing message boundary
- l := int(rsaAlignOf(int(b[0])))
- if len(b) < l {
- return nil, EINVAL
- }
- // Don't reorder case expressions.
- // The case expressions for IPv6 must come first.
- switch {
- case b[0] == SizeofSockaddrInet6:
- sa := &SockaddrInet6{}
- copy(sa.Addr[:], b[offsetofInet6:])
- return sa, nil
- case family == AF_INET6:
- sa := &SockaddrInet6{}
- if l-1 < offsetofInet6 {
- copy(sa.Addr[:], b[1:l])
- } else {
- copy(sa.Addr[:], b[l-offsetofInet6:l])
- }
- return sa, nil
- case b[0] == SizeofSockaddrInet4:
- sa := &SockaddrInet4{}
- copy(sa.Addr[:], b[offsetofInet4:])
- return sa, nil
- default: // an old fashion, AF_UNSPEC or unknown means AF_INET
- sa := &SockaddrInet4{}
- if l-1 < offsetofInet4 {
- copy(sa.Addr[:], b[1:l])
- } else {
- copy(sa.Addr[:], b[l-offsetofInet4:l])
- }
- return sa, nil
- }
- }
- // RouteRIB returns routing information base, as known as RIB,
- // which consists of network facility information, states and
- // parameters.
- //
- // Deprecated: Use golang.org/x/net/route instead.
- 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.
- //
- // Deprecated: Use golang.org/x/net/route instead.
- type RoutingMessage interface {
- sockaddr() ([]Sockaddr, error)
- }
- const anyMessageLen = int(unsafe.Sizeof(anyMessage{}))
- type anyMessage struct {
- Msglen uint16
- Version uint8
- Type uint8
- }
- // RouteMessage represents a routing message containing routing
- // entries.
- //
- // Deprecated: Use golang.org/x/net/route instead.
- type RouteMessage struct {
- Header RtMsghdr
- Data []byte
- }
- func (m *RouteMessage) sockaddr() ([]Sockaddr, error) {
- var sas [RTAX_MAX]Sockaddr
- b := m.Data[:]
- family := uint8(AF_UNSPEC)
- for i := uint(0); i < RTAX_MAX && len(b) >= minRoutingSockaddrLen; i++ {
- if m.Header.Addrs&(1<<i) == 0 {
- continue
- }
- rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
- switch rsa.Family {
- case AF_LINK:
- sa, err := parseSockaddrLink(b)
- if err != nil {
- return nil, err
- }
- sas[i] = sa
- b = b[rsaAlignOf(int(rsa.Len)):]
- case AF_INET, AF_INET6:
- sa, err := parseSockaddrInet(b, rsa.Family)
- if err != nil {
- return nil, err
- }
- sas[i] = sa
- b = b[rsaAlignOf(int(rsa.Len)):]
- family = rsa.Family
- default:
- sa, err := parseNetworkLayerAddr(b, family)
- if err != nil {
- return nil, err
- }
- sas[i] = sa
- b = b[rsaAlignOf(int(b[0])):]
- }
- }
- return sas[:], nil
- }
- // InterfaceMessage represents a routing message containing
- // network interface entries.
- //
- // Deprecated: Use golang.org/x/net/route instead.
- type InterfaceMessage struct {
- Header IfMsghdr
- Data []byte
- }
- func (m *InterfaceMessage) sockaddr() ([]Sockaddr, error) {
- var sas [RTAX_MAX]Sockaddr
- if m.Header.Addrs&RTA_IFP == 0 {
- return nil, nil
- }
- sa, err := parseSockaddrLink(m.Data[:])
- if err != nil {
- return nil, err
- }
- sas[RTAX_IFP] = sa
- return sas[:], nil
- }
- // InterfaceAddrMessage represents a routing message containing
- // network interface address entries.
- //
- // Deprecated: Use golang.org/x/net/route instead.
- type InterfaceAddrMessage struct {
- Header IfaMsghdr
- Data []byte
- }
- func (m *InterfaceAddrMessage) sockaddr() ([]Sockaddr, error) {
- var sas [RTAX_MAX]Sockaddr
- b := m.Data[:]
- family := uint8(AF_UNSPEC)
- for i := uint(0); i < RTAX_MAX && len(b) >= minRoutingSockaddrLen; i++ {
- if m.Header.Addrs&(1<<i) == 0 {
- continue
- }
- rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
- switch rsa.Family {
- case AF_LINK:
- sa, err := parseSockaddrLink(b)
- if err != nil {
- return nil, err
- }
- sas[i] = sa
- b = b[rsaAlignOf(int(rsa.Len)):]
- case AF_INET, AF_INET6:
- sa, err := parseSockaddrInet(b, rsa.Family)
- if err != nil {
- return nil, err
- }
- sas[i] = sa
- b = b[rsaAlignOf(int(rsa.Len)):]
- family = rsa.Family
- default:
- sa, err := parseNetworkLayerAddr(b, family)
- if err != nil {
- return nil, err
- }
- sas[i] = sa
- b = b[rsaAlignOf(int(b[0])):]
- }
- }
- return sas[:], nil
- }
- // ParseRoutingMessage parses b as routing messages and returns the
- // slice containing the RoutingMessage interfaces.
- //
- // Deprecated: Use golang.org/x/net/route instead.
- func ParseRoutingMessage(b []byte) (msgs []RoutingMessage, err error) {
- nmsgs, nskips := 0, 0
- for len(b) >= anyMessageLen {
- nmsgs++
- any := (*anyMessage)(unsafe.Pointer(&b[0]))
- if any.Version != RTM_VERSION {
- b = b[any.Msglen:]
- continue
- }
- if m := any.toRoutingMessage(b); m == nil {
- nskips++
- } else {
- msgs = append(msgs, m)
- }
- b = b[any.Msglen:]
- }
- // We failed to parse any of the messages - version mismatch?
- if nmsgs != len(msgs)+nskips {
- return nil, EINVAL
- }
- return msgs, nil
- }
- // ParseRoutingSockaddr parses msg's payload as raw sockaddrs and
- // returns the slice containing the Sockaddr interfaces.
- //
- // Deprecated: Use golang.org/x/net/route instead.
- func ParseRoutingSockaddr(msg RoutingMessage) ([]Sockaddr, error) {
- sas, err := msg.sockaddr()
- if err != nil {
- return nil, err
- }
- return sas, nil
- }
|