static bool get_all_netinfs(std::vector < NetInf > &nis) { static bool first = true; static std::vector < NetInf > _nis; #ifdef WIN32 if (first) { first = false; nis.clear(); ULONG len = 16 * 1024; IP_ADAPTER_ADDRESSES *adapter = (IP_ADAPTER_ADDRESSES *) malloc(len); // 仅仅 ipv4 DWORD rc = GetAdaptersAddresses(AF_INET, 0, 0, adapter, &len); if (rc == ERROR_BUFFER_OVERFLOW) { adapter = (IP_ADAPTER_ADDRESSES *) realloc(adapter, len); rc = GetAdaptersAddresses(AF_INET, 0, 0, adapter, &len); } if (rc == 0) { IP_ADAPTER_ADDRESSES *p = adapter; while (p) { if ((p->IfType == IF_TYPE_ETHERNET_CSMACD || p->IfType == IF_TYPE_IEEE80211) && (p->OperStatus == IfOperStatusUp)) { // 仅仅考虑 ethernet 或者 wifi,并且活动的. // 不包括虚拟机的 mac. std::string mac = conv_mac(p->PhysicalAddress, p->PhysicalAddressLength); if (!is_vm_mac(mac.c_str())) { NetInf ni; ni.macaddr = mac; // FIXME: 到底用哪个 :( .... 这里真混乱 .... //ni.name = p->AdapterName; //ni.name = (char*)bstr_t(p->FriendlyName); ni.name = (char *)bstr_t(p-> Description); IP_ADAPTER_UNICAST_ADDRESS *ip = p->FirstUnicastAddress; while (ip) { assert(ip->Address. lpSockaddr-> sa_family == AF_INET); sockaddr_in *addr = (sockaddr_in *) ip-> Address.lpSockaddr; ni.ips. push_back(inet_ntoa (addr-> sin_addr)); ip = ip->Next; } nis.push_back(ni); } } p = p->Next; } free(adapter); } _nis = nis; } else { nis = _nis; } #endif // win32 #ifdef __APPLE__ struct ifaddrs *ifap, *ifa; std::map < std::string, Tmp > name_macs; std::map < std::string, Tmp >::iterator itf; if (getifaddrs(&ifap) == 0 && ifap) { for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_flags & IFF_LOOPBACK) continue; if (!(ifa->ifa_flags & IFF_RUNNING)) continue; if (strstr(ifa->ifa_name, "bridge")) // 去除桥接网卡 . continue; if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_LINK) { /* Link layer interface */ struct sockaddr_dl *dl = (struct sockaddr_dl *)ifa->ifa_addr; unsigned char *p = (unsigned char *)LLADDR(dl); std::string mac = conv_mac(p, dl->sdl_alen); if (!is_vm_mac(mac.c_str())) { itf = name_macs.find(ifa->ifa_name); if (itf == name_macs.end()) { Tmp tmp; tmp.mac = mac; name_macs[ifa->ifa_name] = tmp; } else { itf->second.mac = mac; } } } if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET) { // IPV4 struct sockaddr_in *sin = (struct sockaddr_in *)ifa->ifa_addr; std::string ip = inet_ntoa(sin->sin_addr); itf = name_macs.find(ifa->ifa_name); if (itf == name_macs.end()) { Tmp tmp; tmp.ipv4 = ip; name_macs[ifa->ifa_name] = tmp; } else { itf->second.ipv4 = ip; } } } for (itf = name_macs.begin(); itf != name_macs.end(); ++itf) { Tmp & tmp = itf->second; if (!tmp.mac.empty() && !tmp.ipv4.empty()) { NetInf ni; ni.macaddr = tmp.mac; ni.ips.push_back(tmp.ipv4); nis.push_back(ni); } } freeifaddrs(ifap); } #endif // apple #ifdef linux if (!first) { nis = _nis; return true; } char buf[8096]; struct ifconf ifc; int fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd == -1) return false; ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if (ioctl(fd, SIOCGIFCONF, &ifc) == -1) return false; int n = ifc.ifc_len / sizeof(ifreq); for (int i = 0; i < n; i++) { ifreq *req = (ifreq *) & buf[i * sizeof(ifreq)]; const char *name = req->ifr_name; if (!strcmp(name, "lo")) continue; ioctl(fd, SIOCGIFFLAGS, (char *)req); if (!(req->ifr_flags & IFF_UP)) continue; ioctl(fd, SIOCGIFHWADDR, (char *)req); std::string mac = conv_mac((uint8_t *) req->ifr_hwaddr.sa_data, 6); ioctl(fd, SIOCGIFADDR, (char *)req); sockaddr_in *sin = (sockaddr_in *) & req->ifr_addr; if (sin->sin_family != AF_INET) continue; NetInf ni; ni.name = name; ni.macaddr = mac; ni.ips.push_back(inet_ntoa(sin->sin_addr)); nis.push_back(ni); } close(fd); _nis = nis; #endif return true; }
/** 获取可用网卡配置,仅仅选择启动的 ipv4的,非虚拟机的,ethernet */ bool get_all_netinfs(std::vector<NetInf> &nis) { nis.clear(); #ifdef WIN32 ULONG len = 16*1024; IP_ADAPTER_ADDRESSES *adapter = (IP_ADAPTER_ADDRESSES*)malloc(len); // 仅仅 ipv4 DWORD rc = GetAdaptersAddresses(AF_INET, 0, 0, adapter, &len); if (rc == ERROR_BUFFER_OVERFLOW) { adapter = (IP_ADAPTER_ADDRESSES*)realloc(adapter, len); rc = GetAdaptersAddresses(AF_INET, 0, 0, adapter, &len); } if (rc == 0) { IP_ADAPTER_ADDRESSES *p = adapter; while (p) { if ((p->IfType == IF_TYPE_ETHERNET_CSMACD || p->IfType == IF_TYPE_IEEE80211) && (p->OperStatus == IfOperStatusUp)) { // 仅仅考虑 ethernet 或者 wifi,并且活动的 // 不包括虚拟机的 mac std::string mac = conv_mac(p->PhysicalAddress, p->PhysicalAddressLength); if (!is_vm_mac(mac.c_str())) { NetInf ni; ni.macaddr = mac; IP_ADAPTER_UNICAST_ADDRESS *ip = p->FirstUnicastAddress; while (ip) { assert(ip->Address.lpSockaddr->sa_family == AF_INET); sockaddr_in *addr = (sockaddr_in*)ip->Address.lpSockaddr; ni.ips.push_back(inet_ntoa(addr->sin_addr)); ip = ip->Next; } nis.push_back(ni); } } p = p->Next; } free(adapter); } #else char buffer[8192]; struct ifconf ifc; struct ifreq ifr; int fd = socket(AF_INET, SOCK_DGRAM, 0); if(fd == -1) return false; ifc.ifc_len = sizeof(buffer); ifc.ifc_buf = buffer; if(ioctl(fd, SIOCGIFCONF, &ifc) == -1) return false; int count = ifc.ifc_len / sizeof(ifreq); struct ifreq *req = ifc.ifc_req; struct ifreq *end = req + count; for (; req != end; ++req) { strcpy(ifr.ifr_name, req->ifr_name); ioctl(fd, SIOCGIFFLAGS, &ifr); if (ifr.ifr_flags & IFF_LOOPBACK) continue; // lo sockaddr_in sin; sin.sin_addr = ((sockaddr_in&)req->ifr_addr).sin_addr; ioctl(fd, SIOCGIFHWADDR, &ifr); unsigned char mac_addr[6]; memcpy(mac_addr, ifr.ifr_hwaddr.sa_data, 6); NetInf ni; ni.ips.push_back(inet_ntoa(sin.sin_addr)); ni.macaddr = conv_mac(mac_addr, 6); nis.push_back(ni); } close(fd); #endif return true; }