// If the ifindex is zero, interfaceMulticastAddrTable returns // addresses for all network interfaces. Otherwise it returns // addresses for a specific interface. func interfaceMulticastAddrTable(ifindex int) ([]Addr, os.Error) { var ( tab []byte e int msgs []syscall.RoutingMessage ifmat []Addr ) tab, e = syscall.RouteRIB(syscall.NET_RT_IFLIST2, ifindex) if e != 0 { return nil, os.NewSyscallError("route rib", e) } msgs, e = syscall.ParseRoutingMessage(tab) if e != 0 { return nil, os.NewSyscallError("route message", e) } for _, m := range msgs { switch v := m.(type) { case *syscall.InterfaceMulticastAddrMessage: if ifindex == 0 || ifindex == int(v.Header.Index) { ifma, err := newMulticastAddr(v) if err != nil { return nil, err } ifmat = append(ifmat, ifma...) } } } return ifmat, nil }
// interfaceMulticastAddrTable returns addresses for a specific // interface. func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) { tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST2, ifi.Index) if err != nil { return nil, os.NewSyscallError("route rib", err) } msgs, err := syscall.ParseRoutingMessage(tab) if err != nil { return nil, os.NewSyscallError("route message", err) } var ifmat []Addr for _, m := range msgs { switch m := m.(type) { case *syscall.InterfaceMulticastAddrMessage: if ifi.Index == int(m.Header.Index) { ifma, err := newMulticastAddr(ifi, m) if err != nil { return nil, err } if ifma != nil { ifmat = append(ifmat, ifma) } } } } return ifmat, nil }
// If the ifindex is zero, interfaceTable returns mappings of all // network interfaces. Otheriwse it returns a mapping of a specific // interface. func interfaceTable(ifindex int) ([]Interface, error) { var ift []Interface tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex) if err != nil { return nil, os.NewSyscallError("route rib", err) } msgs, err := syscall.ParseRoutingMessage(tab) if err != nil { return nil, os.NewSyscallError("route message", err) } for _, m := range msgs { switch v := m.(type) { case *syscall.InterfaceMessage: if ifindex == 0 || ifindex == int(v.Header.Index) { ifi, err := newLink(v) if err != nil { return nil, err } ift = append(ift, ifi...) } } } return ift, nil }
// If the ifindex is zero, interfaceAddrTable returns addresses // for all network interfaces. Otherwise it returns addresses // for a specific interface. func interfaceAddrTable(ifindex int) ([]Addr, error) { tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex) if err != nil { return nil, os.NewSyscallError("route rib", err) } msgs, err := syscall.ParseRoutingMessage(tab) if err != nil { return nil, os.NewSyscallError("route message", err) } var ifat []Addr for _, m := range msgs { switch v := m.(type) { case *syscall.InterfaceAddrMessage: if ifindex == 0 || ifindex == int(v.Header.Index) { ifa, err := newAddr(v) if err != nil { return nil, err } if ifa != nil { ifat = append(ifat, ifa) } } } } return ifat, nil }
// If the ifindex is zero, interfaceTable returns mappings of all // network interfaces. Otherwise it returns a mapping of a specific // interface. func interfaceTable(ifindex int) ([]Interface, error) { tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex) if err != nil { return nil, os.NewSyscallError("route rib", err) } msgs, err := syscall.ParseRoutingMessage(tab) if err != nil { return nil, os.NewSyscallError("route message", err) } return parseInterfaceTable(ifindex, msgs) }
// If the ifi is nil, interfaceAddrTable returns addresses for all // network interfaces. Otherwise it returns addresses for a specific // interface. func interfaceAddrTable(ifi *Interface) ([]Addr, error) { index := 0 if ifi != nil { index = ifi.Index } tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST, index) if err != nil { return nil, os.NewSyscallError("route rib", err) } msgs, err := syscall.ParseRoutingMessage(tab) if err != nil { return nil, os.NewSyscallError("route message", err) } var ift []Interface if index == 0 { ift, err = parseInterfaceTable(index, msgs) if err != nil { return nil, err } } var ifat []Addr for _, m := range msgs { switch m := m.(type) { case *syscall.InterfaceAddrMessage: if index == 0 || index == int(m.Header.Index) { if index == 0 { var err error ifi, err = interfaceByIndex(ift, int(m.Header.Index)) if err != nil { return nil, err } } ifa, err := newAddr(ifi, m) if err != nil { return nil, err } if ifa != nil { ifat = append(ifat, ifa) } } } } return ifat, nil }
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 }
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 TestSocketConn(t *testing.T) { var freebsd32o64 bool if runtime.GOOS == "freebsd" && runtime.GOARCH == "386" { archs, _ := syscall.Sysctl("kern.supported_archs") for _, s := range strings.Split(archs, " ") { if strings.TrimSpace(s) == "amd64" { freebsd32o64 = true break } } } s, err := syscall.Socket(syscall.AF_ROUTE, syscall.SOCK_RAW, syscall.AF_UNSPEC) if err != nil { t.Fatal(err) } f := os.NewFile(uintptr(s), "route") c, err := SocketConn(f, &routeAddr{}) f.Close() if err != nil { t.Fatal(err) } defer c.Close() const N = 3 var wg sync.WaitGroup wg.Add(2 * N) for i := 0; i < N; i++ { go func(i int) { defer wg.Done() l := syscall.SizeofRtMsghdr + syscall.SizeofSockaddrInet4 if freebsd32o64 { l += syscall.SizeofRtMetrics // see syscall/route_freebsd_32bit.go } b := make([]byte, l) h := (*syscall.RtMsghdr)(unsafe.Pointer(&b[0])) h.Msglen = uint16(len(b)) h.Version = syscall.RTM_VERSION h.Type = syscall.RTM_GET h.Addrs = syscall.RTA_DST h.Pid = int32(os.Getpid()) h.Seq = int32(i) p := (*syscall.RawSockaddrInet4)(unsafe.Pointer(&b[syscall.SizeofRtMsghdr])) p.Len = syscall.SizeofSockaddrInet4 p.Family = syscall.AF_INET p.Addr = [4]byte{127, 0, 0, 1} if _, err := c.Write(b); err != nil { t.Error(err) return } }(i + 1) } for i := 0; i < N; i++ { go func() { defer wg.Done() b := make([]byte, os.Getpagesize()) n, err := c.Read(b) if err != nil { t.Error(err) return } if _, err := syscall.ParseRoutingMessage(b[:n]); err != nil { t.Error(err) return } }() } wg.Wait() }