OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [syscall/] [route_bsd.go] - Rev 762

Go to most recent revision | Compare with Previous | Blame | View Log

// 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 freebsd netbsd openbsd

// Routing sockets and messages

package syscall

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.
        if darwinAMD64 {
                salign = 4
        }
        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
        )

        buf := m.Data[:]
        for i := uint(0); i < RTAX_MAX; i++ {
                if m.Header.Addrs&rtaRtMask&(1<<i) == 0 {
                        continue
                }
                rsa := (*RawSockaddr)(unsafe.Pointer(&buf[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(&buf[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(&buf[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
                        }
                }
                buf = buf[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
        }

        buf := m.Data[:]
        for i := uint(0); i < RTAX_MAX; i++ {
                if m.Header.Addrs&rtaIfaMask&(1<<i) == 0 {
                        continue
                }
                rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
                switch i {
                case RTAX_IFA:
                        sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
                        if err != nil {
                                return nil
                        }
                        sas = append(sas, sa)
                case RTAX_NETMASK:
                        if rsa.Family == AF_UNSPEC {
                                rsa.Family = AF_INET // an old fasion, AF_UNSPEC means AF_INET
                        }
                        sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
                        if err != nil {
                                return nil
                        }
                        sas = append(sas, sa)
                case RTAX_BRD:
                        // nothing to do
                }
                buf = buf[rsaAlignOf(int(rsa.Len)):]
        }

        return sas
}

// ParseRoutingMessage parses buf as routing messages and returns
// the slice containing the RoutingMessage interfaces.
func ParseRoutingMessage(buf []byte) (msgs []RoutingMessage, err error) {
        for len(buf) >= anyMessageLen {
                any := (*anyMessage)(unsafe.Pointer(&buf[0]))
                if any.Version != RTM_VERSION {
                        return nil, EINVAL
                }
                msgs = append(msgs, any.toRoutingMessage(buf))
                buf = buf[any.Msglen:]
        }
        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
}

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.