1 // Copyright 2015 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // +build darwin dragonfly freebsd netbsd openbsd
18 func TestRouteRIB(t *testing.T) {
19 for _, facility := range []int{syscall.NET_RT_DUMP, syscall.NET_RT_IFLIST} {
20 for _, param := range []int{syscall.AF_UNSPEC, syscall.AF_INET, syscall.AF_INET6} {
23 // The VM allocator wrapper functions can
24 // return ENOMEM easily.
25 for i := 0; i < 3; i++ {
26 b, err = syscall.RouteRIB(facility, param)
28 time.Sleep(5 * time.Millisecond)
34 t.Error(facility, param, err)
37 msgs, err := syscall.ParseRoutingMessage(b)
39 t.Error(facility, param, err)
42 var ipv4loopback, ipv6loopback bool
43 for _, m := range msgs {
44 flags, err := parseRoutingMessageHeader(m)
49 sas, err := parseRoutingSockaddrs(m)
54 if flags&(syscall.RTA_DST|syscall.RTA_IFA) != 0 {
55 sa := sas[syscall.RTAX_DST]
57 sa = sas[syscall.RTAX_IFA]
59 switch sa := sa.(type) {
60 case *syscall.SockaddrInet4:
61 if net.IP(sa.Addr[:]).IsLoopback() {
64 case *syscall.SockaddrInet6:
65 if net.IP(sa.Addr[:]).IsLoopback() {
70 t.Log(facility, param, flags, sockaddrs(sas))
72 if param == syscall.AF_UNSPEC && len(msgs) > 0 && !ipv4loopback && !ipv6loopback {
73 t.Errorf("no loopback facility found: ipv4/ipv6=%v/%v, %v", ipv4loopback, ipv6loopback, len(msgs))
80 func TestRouteMonitor(t *testing.T) {
81 if testing.Short() || os.Getuid() != 0 {
82 t.Skip("must be root")
85 s, err := syscall.Socket(syscall.AF_ROUTE, syscall.SOCK_RAW, syscall.AF_UNSPEC)
89 defer syscall.Close(s)
91 tmo := time.After(30 * time.Second)
93 b := make([]byte, os.Getpagesize())
95 n, err := syscall.Read(s, b)
99 msgs, err := syscall.ParseRoutingMessage(b[:n])
104 for _, m := range msgs {
105 flags, err := parseRoutingMessageHeader(m)
110 sas, err := parseRoutingSockaddrs(m)
115 t.Log(flags, sockaddrs(sas))
124 func (f addrFamily) String() string {
126 case syscall.AF_UNSPEC:
128 case syscall.AF_LINK:
130 case syscall.AF_INET:
132 case syscall.AF_INET6:
135 return fmt.Sprintf("unknown %d", f)
139 type addrFlags uint32
141 var addrFlagNames = [...]string{
150 "mpls1,tag,src", // sockaddr_mpls=dragonfly,netbsd, sockaddr_in/in6=openbsd
151 "mpls2,srcmask", // sockaddr_mpls=dragonfly, sockaddr_in/in6=openbsd
152 "mpls3,label", // sockaddr_mpls=dragonfly, sockaddr_rtlabel=openbsd
155 func (f addrFlags) String() string {
157 for i, name := range addrFlagNames {
158 if f&(1<<uint(i)) != 0 {
171 type sockaddrs []syscall.Sockaddr
173 func (sas sockaddrs) String() string {
175 for _, sa := range sas {
182 switch sa := sa.(type) {
183 case *syscall.SockaddrDatalink:
184 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)
185 case *syscall.SockaddrInet4:
186 s += fmt.Sprintf("%v", net.IP(sa.Addr[:]).To4())
187 case *syscall.SockaddrInet6:
188 s += fmt.Sprintf("%v", net.IP(sa.Addr[:]).To16())
197 func (sas sockaddrs) match(flags addrFlags) error {
199 family := syscall.AF_UNSPEC
204 switch sas[i].(type) {
205 case *syscall.SockaddrInet4:
206 if family == syscall.AF_UNSPEC {
207 family = syscall.AF_INET
209 if family != syscall.AF_INET {
210 return fmt.Errorf("got %v; want %v", sockaddrs(sas), family)
212 case *syscall.SockaddrInet6:
213 if family == syscall.AF_UNSPEC {
214 family = syscall.AF_INET6
216 if family != syscall.AF_INET6 {
217 return fmt.Errorf("got %v; want %v", sockaddrs(sas), family)
222 return fmt.Errorf("got %v; want %v", f, flags)