Commit 6d668195 authored by Mikio Hara's avatar Mikio Hara

syscall: deprecate routing message APIs for BSD variants

Also removes unnecessary test cases for avoiding unexpected failures on
newer operating systems.

Updates #14724.

Change-Id: I2291585d951fb70383da68293a6ac1ff3524c7f7
Reviewed-on: https://go-review.googlesource.com/22452
Run-TryBot: Mikio Hara <mikioh.mikioh@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 6cc6ef82
......@@ -176,6 +176,8 @@ func parseNetworkLayerAddr(b []byte, family byte) (Sockaddr, error) {
// 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.
......@@ -194,6 +196,8 @@ func RouteRIB(facility, param int) ([]byte, error) {
}
// RoutingMessage represents a routing message.
//
// Deprecated: Use golang.org/x/net/route instead.
type RoutingMessage interface {
sockaddr() ([]Sockaddr, error)
}
......@@ -208,6 +212,8 @@ type anyMessage struct {
// RouteMessage represents a routing message containing routing
// entries.
//
// Deprecated: Use golang.org/x/net/route instead.
type RouteMessage struct {
Header RtMsghdr
Data []byte
......@@ -252,6 +258,8 @@ func (m *RouteMessage) sockaddr() ([]Sockaddr, error) {
// InterfaceMessage represents a routing message containing
// network interface entries.
//
// Deprecated: Use golang.org/x/net/route instead.
type InterfaceMessage struct {
Header IfMsghdr
Data []byte
......@@ -272,6 +280,8 @@ func (m *InterfaceMessage) sockaddr() ([]Sockaddr, error) {
// 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
......@@ -316,6 +326,8 @@ func (m *InterfaceAddrMessage) sockaddr() ([]Sockaddr, error) {
// 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 {
......@@ -341,6 +353,8 @@ func ParseRoutingMessage(b []byte) (msgs []RoutingMessage, err error) {
// 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 {
......
// Copyright 2015 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
package syscall_test
import (
"fmt"
"net"
"os"
"syscall"
"testing"
"time"
)
func TestRouteRIB(t *testing.T) {
for _, facility := range []int{syscall.NET_RT_DUMP, syscall.NET_RT_IFLIST} {
for _, param := range []int{syscall.AF_UNSPEC, syscall.AF_INET, syscall.AF_INET6} {
var err error
var b []byte
// The VM allocator wrapper functions can
// return ENOMEM easily.
for i := 0; i < 3; i++ {
b, err = syscall.RouteRIB(facility, param)
if err != nil {
time.Sleep(5 * time.Millisecond)
continue
}
break
}
if err != nil {
t.Error(facility, param, err)
continue
}
msgs, err := syscall.ParseRoutingMessage(b)
if err != nil {
t.Error(facility, param, err)
continue
}
var ipv4loopback, ipv6loopback bool
for _, m := range msgs {
flags, err := parseRoutingMessageHeader(m)
if err != nil {
t.Error(err)
continue
}
sas, err := parseRoutingSockaddrs(m)
if err != nil {
t.Error(err)
continue
}
if flags&(syscall.RTA_DST|syscall.RTA_IFA) != 0 {
sa := sas[syscall.RTAX_DST]
if sa == nil {
sa = sas[syscall.RTAX_IFA]
}
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
if net.IP(sa.Addr[:]).IsLoopback() {
ipv4loopback = true
}
case *syscall.SockaddrInet6:
if net.IP(sa.Addr[:]).IsLoopback() {
ipv6loopback = true
}
}
}
t.Log(facility, param, flags, sockaddrs(sas))
}
if param == syscall.AF_UNSPEC && len(msgs) > 0 && !ipv4loopback && !ipv6loopback {
t.Errorf("no loopback facility found: ipv4/ipv6=%v/%v, %v", ipv4loopback, ipv6loopback, len(msgs))
continue
}
}
}
}
func TestRouteMonitor(t *testing.T) {
if testing.Short() || os.Getuid() != 0 {
t.Skip("must be root")
}
s, err := syscall.Socket(syscall.AF_ROUTE, syscall.SOCK_RAW, syscall.AF_UNSPEC)
if err != nil {
t.Fatal(err)
}
defer syscall.Close(s)
tmo := time.After(30 * time.Second)
go func() {
b := make([]byte, os.Getpagesize())
for {
n, err := syscall.Read(s, b)
if err != nil {
return
}
msgs, err := syscall.ParseRoutingMessage(b[:n])
if err != nil {
t.Error(err)
return
}
for _, m := range msgs {
flags, err := parseRoutingMessageHeader(m)
if err != nil {
t.Error(err)
continue
}
sas, err := parseRoutingSockaddrs(m)
if err != nil {
t.Error(err)
continue
}
t.Log(flags, sockaddrs(sas))
}
}
}()
<-tmo
}
var parseInterfaceMessageTests = []*syscall.InterfaceMessage{
// with link-layer address
{
Header: syscall.IfMsghdr{Version: syscall.RTM_VERSION, Addrs: syscall.RTA_IFP},
Data: []uint8{
0x11, 0x12, 0x2, 0x0, 0x6, 0x3, 0x6, 0x0,
0x77, 0x6d, 0x31, 0x01, 0x23, 0x45, 0xab, 0xcd,
0xef, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
},
},
// without link-layer address
{
Header: syscall.IfMsghdr{Version: syscall.RTM_VERSION, Addrs: syscall.RTA_IFP},
Data: []uint8{
0xe, 0x12, 0x4, 0x0, 0xf5, 0x6, 0x0, 0x0,
0x70, 0x66, 0x6c, 0x6f, 0x67, 0x30, 0x0, 0x0,
},
},
// no data
{
Header: syscall.IfMsghdr{Version: syscall.RTM_VERSION, Addrs: syscall.RTA_IFP},
Data: []uint8{
0x8, 0xa, 0xb, 0xc, 0xd, 0x0, 0x0, 0x0,
},
},
}
func TestParseInterfaceMessage(t *testing.T) {
for i, tt := range parseInterfaceMessageTests {
if _, err := syscall.ParseRoutingSockaddr(tt); err != nil {
t.Errorf("#%d: %v", i, err)
}
}
}
type addrFamily byte
func (f addrFamily) String() string {
switch f {
case syscall.AF_UNSPEC:
return "unspec"
case syscall.AF_LINK:
return "link"
case syscall.AF_INET:
return "inet4"
case syscall.AF_INET6:
return "inet6"
default:
return fmt.Sprintf("unknown %d", f)
}
}
type addrFlags uint32
var addrFlagNames = [...]string{
"dst",
"gateway",
"netmask",
"genmask",
"ifp",
"ifa",
"author",
"brd",
"mpls1,tag,src", // sockaddr_mpls=dragonfly,netbsd, sockaddr_in/in6=openbsd
"mpls2,srcmask", // sockaddr_mpls=dragonfly, sockaddr_in/in6=openbsd
"mpls3,label", // sockaddr_mpls=dragonfly, sockaddr_rtlabel=openbsd
}
func (f addrFlags) String() string {
var s string
for i, name := range addrFlagNames {
if f&(1<<uint(i)) != 0 {
if s != "" {
s += "|"
}
s += name
}
}
if s == "" {
return "<nil>"
}
return s
}
type sockaddrs []syscall.Sockaddr
func (sas sockaddrs) String() string {
var s string
for _, sa := range sas {
if sa == nil {
continue
}
if len(s) > 0 {
s += " "
}
switch sa := sa.(type) {
case *syscall.SockaddrDatalink:
s += fmt.Sprintf("[%v/%v/%v t/n/a/s=%v/%v/%v/%v]", sa.Len, addrFamily(sa.Family), sa.Index, sa.Type, sa.Nlen, sa.Alen, sa.Slen)
case *syscall.SockaddrInet4:
s += fmt.Sprintf("%v", net.IP(sa.Addr[:]).To4())
case *syscall.SockaddrInet6:
s += fmt.Sprintf("%v", net.IP(sa.Addr[:]).To16())
}
}
if s == "" {
return "<nil>"
}
return s
}
func (sas sockaddrs) match(flags addrFlags) error {
var f addrFlags
family := syscall.AF_UNSPEC
for i := range sas {
if sas[i] != nil {
f |= 1 << uint(i)
}
switch sas[i].(type) {
case *syscall.SockaddrInet4:
if family == syscall.AF_UNSPEC {
family = syscall.AF_INET
}
if family != syscall.AF_INET {
return fmt.Errorf("got %v; want %v", sockaddrs(sas), family)
}
case *syscall.SockaddrInet6:
if family == syscall.AF_UNSPEC {
family = syscall.AF_INET6
}
if family != syscall.AF_INET6 {
return fmt.Errorf("got %v; want %v", sockaddrs(sas), family)
}
}
}
if f != flags {
return fmt.Errorf("got %v; want %v", f, flags)
}
return nil
}
......@@ -26,6 +26,8 @@ func (any *anyMessage) toRoutingMessage(b []byte) RoutingMessage {
// InterfaceMulticastAddrMessage represents a routing message
// containing network interface address entries.
//
// Deprecated: Use golang.org/x/net/route instead.
type InterfaceMulticastAddrMessage struct {
Header IfmaMsghdr2
Data []byte
......
......@@ -31,6 +31,8 @@ func (any *anyMessage) toRoutingMessage(b []byte) RoutingMessage {
// InterfaceAnnounceMessage represents a routing message containing
// network interface arrival and departure information.
//
// Deprecated: Use golang.org/x/net/route instead.
type InterfaceAnnounceMessage struct {
Header IfAnnounceMsghdr
}
......@@ -39,6 +41,8 @@ func (m *InterfaceAnnounceMessage) sockaddr() ([]Sockaddr, error) { return nil,
// InterfaceMulticastAddrMessage represents a routing message
// containing network interface address entries.
//
// Deprecated: Use golang.org/x/net/route instead.
type InterfaceMulticastAddrMessage struct {
Header IfmaMsghdr
Data []byte
......
......@@ -53,6 +53,8 @@ func (any *anyMessage) toRoutingMessage(b []byte) RoutingMessage {
// InterfaceAnnounceMessage represents a routing message containing
// network interface arrival and departure information.
//
// Deprecated: Use golang.org/x/net/route instead.
type InterfaceAnnounceMessage struct {
Header IfAnnounceMsghdr
}
......@@ -61,6 +63,8 @@ func (m *InterfaceAnnounceMessage) sockaddr() ([]Sockaddr, error) { return nil,
// InterfaceMulticastAddrMessage represents a routing message
// containing network interface address entries.
//
// Deprecated: Use golang.org/x/net/route instead.
type InterfaceMulticastAddrMessage struct {
Header IfmaMsghdr
Data []byte
......
// Copyright 2015 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
package syscall_test
import (
"fmt"
"syscall"
)
func parseRoutingMessageHeader(m syscall.RoutingMessage) (addrFlags, error) {
switch m := m.(type) {
case *syscall.RouteMessage:
errno := syscall.Errno(uintptr(m.Header.Errno))
if errno != 0 {
return 0, fmt.Errorf("%T: %v, %#v", m, errno, m.Header)
}
return addrFlags(m.Header.Addrs), nil
case *syscall.InterfaceMessage:
return addrFlags(m.Header.Addrs), nil
case *syscall.InterfaceAddrMessage:
return addrFlags(m.Header.Addrs), nil
case *syscall.InterfaceMulticastAddrMessage:
return addrFlags(m.Header.Addrs), nil
default:
panic(fmt.Sprintf("unknown routing message type: %T", m))
}
}
func parseRoutingSockaddrs(m syscall.RoutingMessage) ([]syscall.Sockaddr, error) {
switch m := m.(type) {
case *syscall.RouteMessage:
sas, err := syscall.ParseRoutingSockaddr(m)
if err != nil {
return nil, fmt.Errorf("%T: %v, %#v", m, err, m.Data)
}
if err = sockaddrs(sas).match(addrFlags(m.Header.Addrs)); err != nil {
return nil, err
}
return sas, nil
case *syscall.InterfaceMessage:
sas, err := syscall.ParseRoutingSockaddr(m)
if err != nil {
return nil, fmt.Errorf("%T: %v, %#v", m, err, m.Data)
}
if err = sockaddrs(sas).match(addrFlags(m.Header.Addrs)); err != nil {
return nil, err
}
return sas, nil
case *syscall.InterfaceAddrMessage:
sas, err := syscall.ParseRoutingSockaddr(m)
if err != nil {
return nil, fmt.Errorf("%T: %v, %#v", m, err, m.Data)
}
if err = sockaddrs(sas).match(addrFlags(m.Header.Addrs)); err != nil {
return nil, err
}
return sas, nil
case *syscall.InterfaceMulticastAddrMessage:
sas, err := syscall.ParseRoutingSockaddr(m)
if err != nil {
return nil, fmt.Errorf("%T: %v, %#v", m, err, m.Data)
}
if err = sockaddrs(sas).match(addrFlags(m.Header.Addrs)); err != nil {
return nil, err
}
return sas, nil
default:
panic(fmt.Sprintf("unknown routing message type: %T", m))
}
}
......@@ -28,6 +28,8 @@ func (any *anyMessage) toRoutingMessage(b []byte) RoutingMessage {
// InterfaceAnnounceMessage represents a routing message containing
// network interface arrival and departure information.
//
// Deprecated: Use golang.org/x/net/route instead.
type InterfaceAnnounceMessage struct {
Header IfAnnounceMsghdr
}
......
// Copyright 2015 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 netbsd openbsd
package syscall_test
import (
"fmt"
"syscall"
)
func parseRoutingMessageHeader(m syscall.RoutingMessage) (addrFlags, error) {
switch m := m.(type) {
case *syscall.RouteMessage:
errno := syscall.Errno(uintptr(m.Header.Errno))
if errno != 0 {
return 0, fmt.Errorf("%T: %v, %#v", m, errno, m.Header)
}
return addrFlags(m.Header.Addrs), nil
case *syscall.InterfaceMessage:
return addrFlags(m.Header.Addrs), nil
case *syscall.InterfaceAddrMessage:
return addrFlags(m.Header.Addrs), nil
default:
panic(fmt.Sprintf("unknown routing message type: %T", m))
}
}
func parseRoutingSockaddrs(m syscall.RoutingMessage) ([]syscall.Sockaddr, error) {
switch m := m.(type) {
case *syscall.RouteMessage:
sas, err := syscall.ParseRoutingSockaddr(m)
if err != nil {
return nil, fmt.Errorf("%T: %v, %#v", m, err, m.Data)
}
if err = sockaddrs(sas).match(addrFlags(m.Header.Addrs)); err != nil {
return nil, err
}
return sas, nil
case *syscall.InterfaceMessage:
sas, err := syscall.ParseRoutingSockaddr(m)
if err != nil {
return nil, fmt.Errorf("%T: %v, %#v", m, err, m.Data)
}
if err = sockaddrs(sas).match(addrFlags(m.Header.Addrs)); err != nil {
return nil, err
}
return sas, nil
case *syscall.InterfaceAddrMessage:
sas, err := syscall.ParseRoutingSockaddr(m)
if err != nil {
return nil, fmt.Errorf("%T: %v, %#v", m, err, m.Data)
}
if err = sockaddrs(sas).match(addrFlags(m.Header.Addrs)); err != nil {
return nil, err
}
return sas, nil
default:
panic(fmt.Sprintf("unknown routing message type: %T", m))
}
}
......@@ -28,6 +28,8 @@ func (any *anyMessage) toRoutingMessage(b []byte) RoutingMessage {
// InterfaceAnnounceMessage represents a routing message containing
// network interface arrival and departure information.
//
// Deprecated: Use golang.org/x/net/route instead.
type InterfaceAnnounceMessage struct {
Header IfAnnounceMsghdr
}
......
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