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