Example #1
0
// We currently only set up information for interfaces with IPv4
// addresses associated with them.
//
// Solaris's getifaddrs() (currently) only returns results for
// interfaces that have been configured with IP addresses.
// Inactive interfaces are thus silently omitted, unlike on eg
// Linux.
//
// TODO: I should figure out some scheme of first trying the
// net.Interfaces() stuff, so that when Go 1.x finally gets
// support for it on Solaris we'll automatically start to
// use it.
func setupNetinfo() error {
	var ifap *C.struct_ifaddrs

	rc, err := C.getifaddrs(&ifap)
	if rc != 0 || err != nil {
		C.freeifaddrs(ifap)
		return err
	}
	ifaces := make(set)

	// Note that the ifap list has one entry *per IP*; if a single
	// interface has multiple IPs associated with it, via eg
	// aliases, the interface will show up multiple times as we
	// traverse the list. This is unlike net.Interfaces().
	for fi := ifap; fi != nil; fi = fi.ifa_next {
		// sorry, I only deal with IPv4 right now.
		if fi.ifa_addr.sa_family != C.AF_INET {
			continue
		}
		iname := C.GoString(fi.ifa_name)
		ifaces.add(iname)

		if (fi.ifa_flags & C.IFF_LOOPBACK) > 0 {
			netinfo.loopbacks.add(iname)
		}
		if (fi.ifa_flags & C.IFF_POINTOPOINT) > 0 {
			netinfo.pointtopoint.add(iname)
		}

		// Get the IPv4 address associated with this entry.
		// We set it up as a string.
		//
		// Reverse engineering what the sin_addr field is
		// called by CGo was a pain in the ass. Thank goodness
		// for %#v is all I can say; CGo apparently takes the
		// leading _ off what is really '_S_un' for its own
		// reasons.
		//
		// Because this is a union, CGo sets it up as a
		// uint8 buffer. This is very convenient for us because
		// we want to interpret it that way anyways so we can
		// just Sprintf() the bytes into a string.
		t := (*C.struct_sockaddr_in)(unsafe.Pointer(fi.ifa_addr)).sin_addr.S_un
		ipstr := fmt.Sprintf("%d.%d.%d.%d", t[0], t[1], t[2], t[3])

		netinfo.ipmap.add(ipstr, iname)
	}
	C.freeifaddrs(ifap)

	netinfo.ifaces = ifaces.members()
	return nil
}
func getNetDevStats() (map[string]map[string]string, error) {
	netDev := map[string]map[string]string{}

	var ifap, ifa *C.struct_ifaddrs
	if C.getifaddrs(&ifap) == -1 {
		return nil, errors.New("getifaddrs() failed")
	}
	defer C.freeifaddrs(ifap)

	for ifa = ifap; ifa != nil; ifa = ifa.ifa_next {
		if ifa.ifa_addr.sa_family == C.AF_LINK {
			devStats := map[string]string{}
			data := (*C.struct_if_data)(ifa.ifa_data)

			devStats["receive_packets"] = strconv.Itoa(int(data.ifi_ipackets))
			devStats["transmit_packets"] = strconv.Itoa(int(data.ifi_opackets))
			devStats["receive_errs"] = strconv.Itoa(int(data.ifi_ierrors))
			devStats["transmit_errs"] = strconv.Itoa(int(data.ifi_oerrors))
			devStats["receive_bytes"] = strconv.Itoa(int(data.ifi_ibytes))
			devStats["transmit_bytes"] = strconv.Itoa(int(data.ifi_obytes))
			devStats["receive_multicast"] = strconv.Itoa(int(data.ifi_imcasts))
			devStats["transmit_multicast"] = strconv.Itoa(int(data.ifi_omcasts))
			devStats["receive_drop"] = strconv.Itoa(int(data.ifi_iqdrops))
			devStats["transmit_drop"] = strconv.Itoa(int(data.ifi_oqdrops))
			netDev[C.GoString(ifa.ifa_name)] = devStats
		}
	}

	return netDev, nil
}
func getNetDevStats(ignore *regexp.Regexp) (map[string]map[string]string, error) {
	netDev := map[string]map[string]string{}

	var ifap, ifa *C.struct_ifaddrs
	if C.getifaddrs(&ifap) == -1 {
		return nil, errors.New("getifaddrs() failed")
	}
	defer C.freeifaddrs(ifap)

	for ifa = ifap; ifa != nil; ifa = ifa.ifa_next {
		if ifa.ifa_addr.sa_family == C.AF_LINK {
			dev := C.GoString(ifa.ifa_name)
			if ignore.MatchString(dev) {
				log.Debugf("Ignoring device: %s", dev)
				continue
			}

			devStats := map[string]string{}
			data := (*C.struct_if_data)(ifa.ifa_data)
			devStats["receive_packets"] = strconv.FormatUint(uint64(data.ifi_ipackets), 10)
			devStats["transmit_packets"] = strconv.FormatUint(uint64(data.ifi_opackets), 10)
			devStats["receive_errs"] = strconv.FormatUint(uint64(data.ifi_ierrors), 10)
			devStats["transmit_errs"] = strconv.FormatUint(uint64(data.ifi_oerrors), 10)
			devStats["receive_bytes"] = strconv.FormatUint(uint64(data.ifi_ibytes), 10)
			devStats["transmit_bytes"] = strconv.FormatUint(uint64(data.ifi_obytes), 10)
			devStats["receive_multicast"] = strconv.FormatUint(uint64(data.ifi_imcasts), 10)
			devStats["transmit_multicast"] = strconv.FormatUint(uint64(data.ifi_omcasts), 10)
			netDev[dev] = devStats
		}
	}

	return netDev, nil
}
func NewInterfaces() ([]InterfaceTotal, string) {
	var ifaces *C.struct_ifaddrs
	if getrc, _ := C.getifaddrs(&ifaces); getrc != 0 {
		return []InterfaceTotal{}, ""
	}
	defer C.freeifaddrs(ifaces)

	ifs := []InterfaceTotal{}
	IP := ""

	for fi := ifaces; fi != nil; fi = fi.ifa_next {
		if fi.ifa_addr == nil {
			continue
		}

		ifa_name := C.GoString(fi.ifa_name)
		if IP == "" &&
			fi.ifa_addr.sa_family == C.AF_INET &&
			ifa_name != "lo" &&
			!rx_lo.Match([]byte(ifa_name)) &&
			realInterfaceName(ifa_name) {

			sa_in := (*C.struct_sockaddr_in)(unsafe.Pointer(fi.ifa_addr))
			if C.inet_ntop(
				C.int(fi.ifa_addr.sa_family), // C.AF_INET,
				unsafe.Pointer(&sa_in.sin_addr),
				&C.ADDR[0],
				C.socklen_t(unsafe.Sizeof(C.ADDR))) != nil {

				IP = C.GoString((*C.char)(unsafe.Pointer(&C.ADDR)))
			}
		}

		if fi.ifa_addr.sa_family != C.AF_LINK {
			continue
		}

		data := fi.ifa_data
		if C.Ibytes(data) == 0 &&
			C.Obytes(data) == 0 {
			continue
		}
		ifs = append(ifs, InterfaceTotal{
			Name: ifa_name,
			In:   uint(C.Ibytes(data)),
			Out:  uint(C.Obytes(data)),
		})
	}
	return ifs, IP
}
Example #5
0
// Getifaddrs returns a list of IfData. Unlike with getifaddrs(3) the
// IfData has merged link level and interface address data.
func Getifaddrs() ([]IfData, error) {
	var ifaces *C.struct_ifaddrs
	if rc, err := C.getifaddrs(&ifaces); rc != 0 {
		return []IfData{}, err
	}
	defer C.freeifaddrs(ifaces)

	ips := make(map[string]string)
	ifs := []IfData{}

	for fi := ifaces; fi != nil; fi = fi.ifa_next {
		if fi.ifa_addr == nil {
			continue
		}

		ifaName := C.GoString(fi.ifa_name)
		if ip, ok := ntop(fi); ok {
			ips[ifaName] = ip
			continue // fi.ifa_addr.sa_family == C.AF_INET
		}

		if fi.ifa_addr.sa_family != C.AF_LINK {
			continue
		}

		data := fi.ifa_data
		it := IfData{
			Name:       ifaName,
			InBytes:    uint(C.Ibytes(data)),
			OutBytes:   uint(C.Obytes(data)),
			InPackets:  uint(C.Ipackets(data)),
			OutPackets: uint(C.Opackets(data)),
			InErrors:   uint(C.Ierrors(data)),
			OutErrors:  uint(C.Oerrors(data)),
		}
		if ip, ok := ips[ifaName]; ok {
			it.IP = ip
		}
		ifs = append(ifs, it)
	}
	for i, ifdata := range ifs {
		if ifdata.IP != "" {
			continue
		}
		if ip, ok := ips[ifdata.Name]; ok {
			ifs[i].IP = ip
		}
	}
	return ifs, nil
}
func NewInterfaces(CH chan InterfacesInfo) {
	var ifaces *C.struct_ifaddrs
	if getrc, _ := C.getifaddrs(&ifaces); getrc != 0 {
		CH <- InterfacesInfo{}
		return
	}
	defer C.freeifaddrs(ifaces)

	ifs := []InterfaceInfo{}
	IP := ""

	for fi := ifaces; fi != nil; fi = fi.ifa_next {
		if fi.ifa_addr == nil {
			continue
		}

		ifa_name := C.GoString(fi.ifa_name)
		if IP == "" &&
			fi.ifa_addr.sa_family == C.AF_INET &&
			!rx_lo.Match([]byte(ifa_name)) &&
			realInterfaceName(ifa_name) {

			sa_in := (*C.struct_sockaddr_in)(unsafe.Pointer(fi.ifa_addr))
			if C.inet_ntop(
				C.int(fi.ifa_addr.sa_family), // C.AF_INET,
				unsafe.Pointer(&sa_in.sin_addr),
				&C.ADDR[0],
				C.socklen_t(unsafe.Sizeof(C.ADDR))) != nil {

				IP = C.GoString((*C.char)(unsafe.Pointer(&C.ADDR)))
			}
		}

		if fi.ifa_addr.sa_family != C.AF_LINK {
			continue
		}

		data := fi.ifa_data
		it := InterfaceInfo{
			Name:       ifa_name,
			InBytes:    uint(C.Ibytes(data)),
			OutBytes:   uint(C.Obytes(data)),
			InPackets:  uint(C.Ipackets(data)),
			OutPackets: uint(C.Opackets(data)),
			InErrors:   uint(C.Ierrors(data)),
			OutErrors:  uint(C.Oerrors(data)),
		}
		if it.InBytes == 0 &&
			it.OutBytes == 0 &&
			it.InPackets == 0 &&
			it.OutPackets == 0 &&
			it.InErrors == 0 &&
			it.OutErrors == 0 {
			continue
		}
		ifs = append(ifs, it)
	}
	CH <- InterfacesInfo{
		List: ifs,
		IP:   IP,
	}
}