// 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 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 } } } }