f8d9fa9e80
This upgrades all of libgo other than the runtime package to the Go 1.4 release. In Go 1.4 much of the runtime was rewritten into Go. Merging that code will take more time and will not change the API, so I'm putting it off for now. There are a few runtime changes anyhow, to accomodate other packages that rely on minor modifications to the runtime support. The compiler changes slightly to add a one-bit flag to each type descriptor kind that is stored directly in an interface, which for gccgo is currently only pointer types. Another one-bit flag (gcprog) is reserved because it is used by the gc compiler, but gccgo does not currently use it. There is another error check in the compiler since I ran across it during testing. gotools/: * Makefile.am (go_cmd_go_files): Sort entries. Add generate.go. * Makefile.in: Rebuild. From-SVN: r219627
179 lines
4.7 KiB
Go
179 lines
4.7 KiB
Go
// 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 syscall
|
|
|
|
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
|
|
}
|