示例#1
0
// 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
}
示例#2
0
// 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
}
示例#3
0
// 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
}
示例#4
0
// 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
}
示例#5
0
// 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)
}
示例#6
0
// 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
}
示例#7
0
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
}
示例#8
0
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
			}
		}
	}
}
示例#9
0
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()
}