github.com/d4l3k/go@v0.0.0-20151015000803-65fc379daeda/src/syscall/route_bsd_test.go (about) 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. 4 5 // +build darwin dragonfly freebsd netbsd openbsd 6 7 package syscall_test 8 9 import ( 10 "fmt" 11 "net" 12 "os" 13 "syscall" 14 "testing" 15 "time" 16 ) 17 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} { 21 var err error 22 var b []byte 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) 27 if err != nil { 28 time.Sleep(5 * time.Millisecond) 29 continue 30 } 31 break 32 } 33 if err != nil { 34 t.Error(facility, param, err) 35 continue 36 } 37 msgs, err := syscall.ParseRoutingMessage(b) 38 if err != nil { 39 t.Error(facility, param, err) 40 continue 41 } 42 var ipv4loopback, ipv6loopback bool 43 for _, m := range msgs { 44 flags, err := parseRoutingMessageHeader(m) 45 if err != nil { 46 t.Error(err) 47 continue 48 } 49 sas, err := parseRoutingSockaddrs(m) 50 if err != nil { 51 t.Error(err) 52 continue 53 } 54 if flags&(syscall.RTA_DST|syscall.RTA_IFA) != 0 { 55 sa := sas[syscall.RTAX_DST] 56 if sa == nil { 57 sa = sas[syscall.RTAX_IFA] 58 } 59 switch sa := sa.(type) { 60 case *syscall.SockaddrInet4: 61 if net.IP(sa.Addr[:]).IsLoopback() { 62 ipv4loopback = true 63 } 64 case *syscall.SockaddrInet6: 65 if net.IP(sa.Addr[:]).IsLoopback() { 66 ipv6loopback = true 67 } 68 } 69 } 70 t.Log(facility, param, flags, sockaddrs(sas)) 71 } 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)) 74 continue 75 } 76 } 77 } 78 } 79 80 func TestRouteMonitor(t *testing.T) { 81 if testing.Short() || os.Getuid() != 0 { 82 t.Skip("must be root") 83 } 84 85 s, err := syscall.Socket(syscall.AF_ROUTE, syscall.SOCK_RAW, syscall.AF_UNSPEC) 86 if err != nil { 87 t.Fatal(err) 88 } 89 defer syscall.Close(s) 90 91 tmo := time.After(30 * time.Second) 92 go func() { 93 b := make([]byte, os.Getpagesize()) 94 for { 95 n, err := syscall.Read(s, b) 96 if err != nil { 97 return 98 } 99 msgs, err := syscall.ParseRoutingMessage(b[:n]) 100 if err != nil { 101 t.Error(err) 102 return 103 } 104 for _, m := range msgs { 105 flags, err := parseRoutingMessageHeader(m) 106 if err != nil { 107 t.Error(err) 108 continue 109 } 110 sas, err := parseRoutingSockaddrs(m) 111 if err != nil { 112 t.Error(err) 113 continue 114 } 115 t.Log(flags, sockaddrs(sas)) 116 } 117 } 118 }() 119 <-tmo 120 } 121 122 var parseInterfaceMessageTests = []*syscall.InterfaceMessage{ 123 // with link-layer address 124 { 125 Header: syscall.IfMsghdr{Version: syscall.RTM_VERSION, Addrs: syscall.RTA_IFP}, 126 Data: []uint8{ 127 0x11, 0x12, 0x2, 0x0, 0x6, 0x3, 0x6, 0x0, 128 0x77, 0x6d, 0x31, 0x01, 0x23, 0x45, 0xab, 0xcd, 129 0xef, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 130 }, 131 }, 132 // without link-layer address 133 { 134 Header: syscall.IfMsghdr{Version: syscall.RTM_VERSION, Addrs: syscall.RTA_IFP}, 135 Data: []uint8{ 136 0xe, 0x12, 0x4, 0x0, 0xf5, 0x6, 0x0, 0x0, 137 0x70, 0x66, 0x6c, 0x6f, 0x67, 0x30, 0x0, 0x0, 138 }, 139 }, 140 // no data 141 { 142 Header: syscall.IfMsghdr{Version: syscall.RTM_VERSION, Addrs: syscall.RTA_IFP}, 143 Data: []uint8{ 144 0x8, 0xa, 0xb, 0xc, 0xd, 0x0, 0x0, 0x0, 145 }, 146 }, 147 } 148 149 func TestParseInterfaceMessage(t *testing.T) { 150 for i, tt := range parseInterfaceMessageTests { 151 if _, err := syscall.ParseRoutingSockaddr(tt); err != nil { 152 t.Errorf("#%d: %v", i, err) 153 } 154 } 155 } 156 157 type addrFamily byte 158 159 func (f addrFamily) String() string { 160 switch f { 161 case syscall.AF_UNSPEC: 162 return "unspec" 163 case syscall.AF_LINK: 164 return "link" 165 case syscall.AF_INET: 166 return "inet4" 167 case syscall.AF_INET6: 168 return "inet6" 169 default: 170 return fmt.Sprintf("unknown %d", f) 171 } 172 } 173 174 type addrFlags uint32 175 176 var addrFlagNames = [...]string{ 177 "dst", 178 "gateway", 179 "netmask", 180 "genmask", 181 "ifp", 182 "ifa", 183 "author", 184 "brd", 185 "mpls1,tag,src", // sockaddr_mpls=dragonfly,netbsd, sockaddr_in/in6=openbsd 186 "mpls2,srcmask", // sockaddr_mpls=dragonfly, sockaddr_in/in6=openbsd 187 "mpls3,label", // sockaddr_mpls=dragonfly, sockaddr_rtlabel=openbsd 188 } 189 190 func (f addrFlags) String() string { 191 var s string 192 for i, name := range addrFlagNames { 193 if f&(1<<uint(i)) != 0 { 194 if s != "" { 195 s += "|" 196 } 197 s += name 198 } 199 } 200 if s == "" { 201 return "<nil>" 202 } 203 return s 204 } 205 206 type sockaddrs []syscall.Sockaddr 207 208 func (sas sockaddrs) String() string { 209 var s string 210 for _, sa := range sas { 211 if sa == nil { 212 continue 213 } 214 if len(s) > 0 { 215 s += " " 216 } 217 switch sa := sa.(type) { 218 case *syscall.SockaddrDatalink: 219 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) 220 case *syscall.SockaddrInet4: 221 s += fmt.Sprintf("%v", net.IP(sa.Addr[:]).To4()) 222 case *syscall.SockaddrInet6: 223 s += fmt.Sprintf("%v", net.IP(sa.Addr[:]).To16()) 224 } 225 } 226 if s == "" { 227 return "<nil>" 228 } 229 return s 230 } 231 232 func (sas sockaddrs) match(flags addrFlags) error { 233 var f addrFlags 234 family := syscall.AF_UNSPEC 235 for i := range sas { 236 if sas[i] != nil { 237 f |= 1 << uint(i) 238 } 239 switch sas[i].(type) { 240 case *syscall.SockaddrInet4: 241 if family == syscall.AF_UNSPEC { 242 family = syscall.AF_INET 243 } 244 if family != syscall.AF_INET { 245 return fmt.Errorf("got %v; want %v", sockaddrs(sas), family) 246 } 247 case *syscall.SockaddrInet6: 248 if family == syscall.AF_UNSPEC { 249 family = syscall.AF_INET6 250 } 251 if family != syscall.AF_INET6 { 252 return fmt.Errorf("got %v; want %v", sockaddrs(sas), family) 253 } 254 } 255 } 256 if f != flags { 257 return fmt.Errorf("got %v; want %v", f, flags) 258 } 259 return nil 260 }