#include "VrNetUtils.h" #include "VrLog.h" #ifdef _WIN32 #define _WINSOCK_DEPRECATED_NO_WARNINGS #include #include #include #include #include #include #include #pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "IPHlpApi.lib") #pragma comment(lib, "Advapi32.lib") #else #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include #include #include #endif #include #ifdef _WIN32 enum { SIOCSIFADDR = 1, SIOCGIFADDR, SIOCSIFNETMASK, SIOCGIFNETMASK, SIOCGIFHWADDR, }; #endif #define PJ_MAX_HOSTNAME (128) #define RUN_SUCCESS 0 #define RUN_FAIL -1 std::mutex csDevice; std::ostream& operator<<(std::ostream& os, const SVrCardInfo& sAction) { os << "cardInfo"; os << " index:" << sAction.nAdapterIndex << " name:" << sAction.szNetCardName; char ip[IPV4_CHAR_LENGTH]; CVrNetUtils::IPByte2String(sAction.byLocalIP, ip); os << " ip:" << ip; // os << "mac:" << sAction.byMacAddress[0] << ":" << sAction.byMacAddress[1] << sAction.byMacAddress[3] << ":" // << sAction.byMacAddress[4] << ":" << sAction.byMacAddress[4] << sAction.byMacAddress[5]; CVrNetUtils::IPByte2String(sAction.bySubMask, ip); os << " mask:" << ip; CVrNetUtils::IPByte2String(sAction.byGetWay, ip); os << " getway:" << ip; CVrNetUtils::IPByte2String(sAction.byBroadCastIP, ip); os << " broadIp:" << ip; return os; } static bool _GetAddr(char *addr, int flag, const char *devName) { #ifdef _WIN32 char ip[IPV4_CHAR_LENGTH] = "192.168.1.173"; memcpy(addr, ip, IPV4_CHAR_LENGTH); return false; #else int sockfd = 0; struct sockaddr_in *sin; struct ifreq ifr; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { LOG_ERRO("socket error! [%d]\n", sockfd); return false; } memset(&ifr, 0, sizeof(ifr)); sprintf(ifr.ifr_name, "%s", devName); LOG_DEBUG("dev %s \n", ifr.ifr_name); if (ioctl(sockfd, flag, &ifr) < 0) { LOG_ERRO("ioctl error! [%d]\n", sockfd); close(sockfd); return false; } close(sockfd); if (SIOCGIFHWADDR == flag) { memcpy((void *)addr, (const void *)&ifr.ifr_ifru.ifru_hwaddr.sa_data, 6); sprintf((char *)addr, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); } else { sin = (struct sockaddr_in *)&ifr.ifr_addr; // 打印 sin->sin_addr.s_addr 以便调试 //sprintf((char *)addr, "%s", inet_ntoa(sin->sin_addr)); unsigned long ipInfo = sin->sin_addr.s_addr; sprintf((char*)addr, "%ld.%ld.%ld.%ld", ipInfo & 0xFF, (ipInfo >> 8) & 0xFF, (ipInfo >> 16) & 0xFF, (ipInfo >> 24) & 0xFF); } return true; #endif // _WIN32 } static bool _SetAddr(const char ip[IPV4_CHAR_LENGTH], int flag, const char* devName) { #ifndef _WIN32 std::lock_guard oLock(csDevice); struct ifreq ifr; struct sockaddr_in sin; int sockfd; if (!CVrNetUtils::IsValidIP(ip)) { LOG_WARNING("Set %d %s invalied ", flag, ip); return false; } sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd <= 0) { LOG_ERRO("Could not get socket %s fd = %d [%d - %s]\n", devName, sockfd, errno, strerror(errno)); return false; } snprintf(ifr.ifr_name, (sizeof(ifr.ifr_name) - 1), "%s", devName); /* Read interface flags */ if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { LOG_ERRO("%s ifdown: shutdown ", ifr.ifr_name); close(sockfd); return false; } memset(&sin, 0, sizeof(struct sockaddr)); sin.sin_family = AF_INET; inet_aton((const char*)ip, (in_addr*)(&sin.sin_addr.s_addr)); memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr)); if (ioctl(sockfd, flag, &ifr) < 0) { LOG_ERRO("Cannot set IP address. "); perror(ifr.ifr_name); close(sockfd); return false; } close(sockfd); #endif return true; } bool CVrNetUtils::SetAddrMaskGateWay(const char *ifname, const char *Ipaddr, const char *mask, const char *gateway) { #ifndef _WIN32 int fd; int rc; struct ifreq ifr; struct sockaddr_in *sin; struct rtentry rt; fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("socket error"); return false; } memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, ifname); sin = (struct sockaddr_in*)&ifr.ifr_addr; sin->sin_family = AF_INET; //IP地址 if (inet_aton(Ipaddr, &(sin->sin_addr)) < 0) { LOG_ERRO("inet_aton error"); return false; } if (ioctl(fd, SIOCSIFADDR, &ifr) < 0) { LOG_ERRO("ioctl SIOCSIFADDR error"); return false; } //子网掩码 if (inet_aton(mask, &(sin->sin_addr)) < 0) { LOG_ERRO("inet_pton error"); return false; } if (ioctl(fd, SIOCSIFNETMASK, &ifr) < 0) { LOG_ERRO("ioctl"); return false; } //网关 memset(&rt, 0, sizeof(struct rtentry)); memset(sin, 0, sizeof(struct sockaddr_in)); sin->sin_family = AF_INET; sin->sin_port = 0; if (inet_aton(gateway, &sin->sin_addr) < 0) { LOG_WARNING("inet_aton error\n"); } #if 0 memcpy(&rt.rt_gateway, sin, sizeof(struct sockaddr_in)); ((struct sockaddr_in *)&rt.rt_dst)->sin_family = AF_INET; ((struct sockaddr_in *)&rt.rt_genmask)->sin_family = AF_INET; ((struct sockaddr_in *)&rt.rt_dst)->sin_addr.s_addr = htonl(INADDR_ANY); // 默认路由 ((struct sockaddr_in *)&rt.rt_genmask)->sin_addr.s_addr = htonl(0); // 掩码为 0.0.0.0 rt.rt_flags = RTF_GATEWAY; if (ioctl(fd, SIOCADDRT, &rt) < 0) { LOG_ERRO("ioctl(SIOCADDRT) error in set_default_route\n"); close(fd); return false; } #endif close(fd); #endif // !_WIN32 return true; } // @brief // Is Virtual Net Card static bool _IsVirtualNetDevice(char* lpszAdapterName) { bool bRet = false; #ifdef _WIN32 HKEY hSubKey = NULL; HKEY hLocalKey = NULL; do { if (nullptr == lpszAdapterName || 0 == strlen(lpszAdapterName)) { break; } char szKeyName[260] = "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"; if (ERROR_SUCCESS != RegOpenKeyExA(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_READ, &hSubKey)) { break; } char szDataBuf[260] = { 0 }; sprintf_s(szDataBuf, "%s\\Connection", lpszAdapterName);//格式化字符串 if (ERROR_SUCCESS != RegOpenKeyExA(hSubKey, szDataBuf, 0, KEY_READ, &hLocalKey)) { break; } //请求注册表中的值 DWORD dwType = REG_SZ; char szData[250]; DWORD dwSize = 250; if (ERROR_SUCCESS != RegQueryValueExA(hLocalKey, "PnPInstanceId", 0, &dwType, (BYTE*)(szData), &dwSize)) { break; } bRet = (nullptr == strstr(szData, "PCI") && nullptr == strstr(szData, "USB")); } while (false); if (nullptr != hSubKey) { RegCloseKey(hSubKey); } if (nullptr != hLocalKey) { RegCloseKey(hLocalKey); } #else #endif return bRet; } std::string _GetCardBroadIP(const std::string localIP, const std::string locakMask) { unsigned int arrLocalIP[4]; unsigned int arrlocakMask[4]; unsigned int arrlocalBroadcast[4]; #ifndef _WIN32 sscanf(localIP.c_str(), "%u.%u.%u.%u", &arrLocalIP[0], &arrLocalIP[1], &arrLocalIP[2], &arrLocalIP[3]); sscanf(locakMask.c_str(), "%u.%u.%u.%u", &arrlocakMask[0], &arrlocakMask[1], &arrlocakMask[2], &arrlocakMask[3]); #else sscanf_s(localIP.c_str(), "%u.%u.%u.%u", &arrLocalIP[0], &arrLocalIP[1], &arrLocalIP[2], &arrLocalIP[3]); sscanf_s(locakMask.c_str(), "%u.%u.%u.%u", &arrlocakMask[0], &arrlocakMask[1], &arrlocakMask[2], &arrlocakMask[3]); #endif // !_WIN32 arrlocalBroadcast[0] = (arrlocakMask[0] & arrLocalIP[0] & 0xFF) | (~arrlocakMask[0] & 0xFF); arrlocalBroadcast[1] = (arrlocakMask[1] & arrLocalIP[1] & 0xFF) | (~arrlocakMask[1] & 0xFF); arrlocalBroadcast[2] = (arrlocakMask[2] & arrLocalIP[2] & 0xFF) | (~arrlocakMask[2] & 0xFF); arrlocalBroadcast[3] = (arrlocakMask[3] & arrLocalIP[3] & 0xFF) | (~arrlocakMask[3] & 0xFF); std::stringstream ss; ss << arrlocalBroadcast[0] << "."; ss << arrlocalBroadcast[1] << "."; ss << arrlocalBroadcast[2] << "."; ss << arrlocalBroadcast[3]; return ss.str(); } /// 获取所有设备 bool CVrNetUtils::QueryAllNetworkInfo(std::list& lstNetCardInfo) { #ifdef _WIN32 unsigned long lSize = 0; GetAdaptersInfo(nullptr, &lSize); if (lSize > 0) { PIP_ADAPTER_INFO pAdapterInfo = (PIP_ADAPTER_INFO)new unsigned char[lSize]; GetAdaptersInfo(pAdapterInfo, &lSize); PIP_ADAPTER_INFO pCurAdapter = pAdapterInfo; while (nullptr != pCurAdapter) { IP_ADDR_STRING* pCurAddress = &pCurAdapter->IpAddressList; IP_ADDR_STRING* pCurGetWay = &pCurAdapter->GatewayList; while (nullptr != pCurAddress) { // Filter? // is Virtual Card if (pCurAdapter->AdapterName == nullptr || _IsVirtualNetDevice(pCurAdapter->AdapterName)) { pCurAddress = pCurAddress->Next; continue; } // if (0 == strcmp("0.0.0.0", pCurAddress->IpAddress.String)) { pCurAddress = pCurAddress->Next; continue; } // No Support UnEqu Length 6 MAC Address if (pCurAdapter->AddressLength != 6) { pCurAddress = pCurAddress->Next; continue; } // Add To list //lstNetCardInfo.push_back(pCurAddress->IpAddress.String); //SVrCardInfo config; //config.ip = pCurAddress->IpAddress.String; //config.mask = pCurAddress->IpMask.String; //config.borad = _GetCardBroadIP(pCurAddress->IpAddress.String, pCurAddress->IpMask.String); // SVrCardInfo sNetCardInfo; sNetCardInfo.nAdapterIndex = pCurAdapter->Index; if (pCurGetWay && 0 != strlen(pCurGetWay->IpAddress.String)) { IPString2Byte(pCurGetWay->IpAddress.String, sNetCardInfo.byGetWay); } IPString2Byte(pCurAddress->IpAddress.String, sNetCardInfo.byLocalIP); IPString2Byte(pCurAddress->IpMask.String, sNetCardInfo.bySubMask); #ifdef _WIN32 strcpy_s(sNetCardInfo.szNetCardName, pCurAdapter->Description); #else strcpy(sNetCardInfo.szNetCardName, pCurAdapter->Description); #endif // _WIN32 memcpy(sNetCardInfo.byMacAddress, pCurAdapter->Address, pCurAdapter->AddressLength); // 计算广播地址 CalcBroadCastIP(sNetCardInfo.byLocalIP, sNetCardInfo.bySubMask, sNetCardInfo.byBroadCastIP); lstNetCardInfo.push_back(sNetCardInfo); pCurAddress = pCurAddress->Next; if (pCurGetWay) { pCurGetWay = pCurGetWay->Next; } } pCurAdapter = pCurAdapter->Next; } delete pAdapterInfo; } #else int fd; int interfaceNum = 0; struct ifreq buf[16]; struct ifconf ifc; struct ifreq ifrcopy; char ip[32] = { 0 }; char broadAddr[32] = { 0 }; char subnetMask[32] = { 0 }; if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { close(fd); return -1; } ifc.ifc_len = sizeof(buf); ifc.ifc_buf = (caddr_t)buf; if (!ioctl(fd, SIOCGIFCONF, (char *)&ifc)) { interfaceNum = ifc.ifc_len / sizeof(struct ifreq); while (interfaceNum-- > 0) { SVrCardInfo sNetCardInfo; strcpy(sNetCardInfo.szNetCardName, buf[interfaceNum].ifr_name); //ignore the interface that not up or not runing ifrcopy = buf[interfaceNum]; if (ioctl(fd, SIOCGIFFLAGS, &ifrcopy)) { close(fd); return false; } // index sNetCardInfo.nAdapterIndex = if_nametoindex(sNetCardInfo.szNetCardName); //get the mac of this interface if (!ioctl(fd, SIOCGIFHWADDR, (char *)(&buf[interfaceNum]))) { memcpy(sNetCardInfo.byMacAddress, buf[interfaceNum].ifr_hwaddr.sa_data, 6); } else { close(fd); return false; } //get the IP of this interface if (!ioctl(fd, SIOCGIFADDR, (char *)&buf[interfaceNum])) { snprintf(ip, sizeof(ip), "%s", (char *)inet_ntoa(((struct sockaddr_in *)&(buf[interfaceNum].ifr_addr))->sin_addr)); CVrNetUtils::IPString2Byte(ip, sNetCardInfo.byLocalIP); } else { close(fd); return false; } //get the subnet mask of this interface if (!ioctl(fd, SIOCGIFNETMASK, &buf[interfaceNum])) { snprintf(subnetMask, sizeof(subnetMask), "%s", (char *)inet_ntoa(((struct sockaddr_in *)&(buf[interfaceNum].ifr_netmask))->sin_addr)); CVrNetUtils::IPString2Byte(subnetMask, sNetCardInfo.bySubMask); } else { close(fd); return false; } lstNetCardInfo.push_back(sNetCardInfo); } } else { close(fd); return false; } close(fd); #endif return lstNetCardInfo.size() > 0; } /// @brief /// IP是否可用 /// @param szIPv4[in] IP地址 /// @return IP可用则返回true bool CVrNetUtils::IsValidIP(const char szIPv4[IPV4_CHAR_LENGTH]) { char tmp[IPV4_CHAR_LENGTH]; memcpy(tmp, szIPv4, IPV4_CHAR_LENGTH); char *buf; const char * delim = "\\."; //分隔符字符串 #ifdef _WIN32 char* p = strtok_s((char *)tmp, delim, &buf); //第一次调用strtok #else char* p = strtok((char *)tmp, delim); //第一次调用strtok #endif int index = 0; while (p != NULL) { //当返回值不为NULL时,继续循环 index++; #ifdef _WIN32 p = strtok_s(NULL, delim, &buf); //继续调用strtok,分解剩下的字符串 #else p = strtok(NULL, delim); //继续调用strtok,分解剩下的字符串 #endif // _WIN32 } if (index == 4) { return true; } return false; } bool CVrNetUtils::SetIPv4Address(const char ip[IPV4_CHAR_LENGTH], const char *devName) { return _SetAddr(ip, SIOCSIFADDR, devName); } /// @brief /// 获取IP地址 bool CVrNetUtils::GetIPv4Address(char ip[IPV4_CHAR_LENGTH], const char *devName) { return _GetAddr(ip, SIOCGIFADDR, devName) && IsValidIP(ip); } bool CVrNetUtils::SetIPv4NetMask(const char ip[IPV4_CHAR_LENGTH], const char *devName) { return _SetAddr(ip, SIOCSIFNETMASK, devName); } /// @brief /// 获取子网掩码 bool CVrNetUtils::GetIPv4NetMask(char ip[IPV4_CHAR_LENGTH], const char *devName) { return _GetAddr(ip, SIOCGIFNETMASK, devName); } /// 获取广播地址 bool CVrNetUtils::GetIPv4BroadIP(char ip[IPV4_CHAR_LENGTH], const char *devName) { char devip[IPV4_CHAR_LENGTH]; char devmask[IPV4_CHAR_LENGTH]; unsigned char deviparr[4]; unsigned char devmaskarr[4]; unsigned char devbroadarr[4]; bool bRet = GetIPv4Address(devip, devName); if (bRet) { bRet = GetIPv4NetMask(devmask, devName); } if (bRet) { IPString2Byte(devip, deviparr); IPString2Byte(devmask, devmaskarr); CalcBroadCastIP(deviparr, devmaskarr, devbroadarr); IPByte2String(devbroadarr, ip); } return bRet; } /// @brief /// 获取网卡地址 bool CVrNetUtils::GetLocalMAC(char byMac[MAC_CHAR_LENGTH], const char *devName) { return _GetAddr((char*)byMac, SIOCGIFHWADDR, devName); } /// 设置网关 bool CVrNetUtils::SetGateWay(const char ip[IPV4_CHAR_LENGTH], const char *devName) { #ifndef _WIN32 std::lock_guard oLock(csDevice); int sockFd; struct sockaddr_in sockaddr; struct rtentry rt; if (!IsValidIP(ip)) { LOG_WARNING("gateway invalid!\n"); return false; } sockFd = socket(AF_INET, SOCK_DGRAM, 0); if (sockFd < 0) { LOG_WARNING("Socket create error.\n"); return false; } memset(&rt, 0, sizeof(struct rtentry)); memset(&sockaddr, 0, sizeof(struct sockaddr_in)); sockaddr.sin_family = AF_INET; sockaddr.sin_port = 0; if (inet_aton((const char*)ip, &sockaddr.sin_addr) < 0) { perror("inet_aton error\n"); close(sockFd); return false; } memcpy(&rt.rt_gateway, &sockaddr, sizeof(struct sockaddr_in)); ((struct sockaddr_in *)&rt.rt_dst)->sin_family = AF_INET; ((struct sockaddr_in *)&rt.rt_genmask)->sin_family = AF_INET; rt.rt_flags = RTF_GATEWAY; if (ioctl(sockFd, SIOCADDRT, &rt) < 0) { perror("ioctl(SIOCADDRT) error in set_default_route\n"); close(sockFd); return true; } close(sockFd); #endif return true; } /// 获取网关 bool CVrNetUtils::GetGateWay(char ip[IPV4_CHAR_LENGTH], const char *devName) { #ifndef _WIN32 int received_bytes = 0, msg_len = 0, route_attribute_len = 0; int sock = -1, msgseq = 0; struct nlmsghdr *nlh, *nlmsg; struct rtmsg *route_entry; // This struct contain route attributes (route type) struct rtattr *route_attribute; int BUFFER_SIZE = 4096; char msgbuf[BUFFER_SIZE], buffer[BUFFER_SIZE]; char *ptr = buffer; struct timeval tv; if ((sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) { perror("socket failed"); return false; } memset(msgbuf, 0, sizeof(msgbuf)); memset(ip, 0, IPV4_CHAR_LENGTH); memset(buffer, 0, sizeof(buffer)); /* point the header and the msg structure pointers into the buffer */ nlmsg = (struct nlmsghdr *)msgbuf; /* Fill in the nlmsg header*/ nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); nlmsg->nlmsg_type = RTM_GETROUTE; // Get the routes from kernel routing table . nlmsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; // The message is a request for dump. nlmsg->nlmsg_seq = msgseq++; // Sequence of the message packet. nlmsg->nlmsg_pid = getpid(); // PID of process sending the request. /* 1 Sec Timeout to avoid stall */ tv.tv_sec = 1; setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval)); /* send msg */ if (send(sock, nlmsg, nlmsg->nlmsg_len, 0) < 0) { perror("send failed"); return false; } /* receive response */ do { received_bytes = recv(sock, ptr, sizeof(buffer) - msg_len, 0); if (received_bytes < 0) { perror("Error in recv"); return false; } nlh = (struct nlmsghdr *) ptr; /* Check if the header is valid */ if ((NLMSG_OK(nlmsg, received_bytes) == 0) || (nlmsg->nlmsg_type == NLMSG_ERROR)) { perror("Error in received packet"); return false; } /* If we received all data break */ if (nlh->nlmsg_type == NLMSG_DONE) break; else { ptr += received_bytes; msg_len += received_bytes; } /* Break if its not a multi part message */ if ((nlmsg->nlmsg_flags & NLM_F_MULTI) == 0) break; } while ((nlmsg->nlmsg_seq != msgseq) || (nlmsg->nlmsg_pid != getpid())); /* parse response */ for (; NLMSG_OK(nlh, received_bytes); nlh = NLMSG_NEXT(nlh, received_bytes)) { /* Get the route data */ route_entry = (struct rtmsg *) NLMSG_DATA(nlh); /* We are just interested in main routing table */ if (route_entry->rtm_table != RT_TABLE_MAIN) continue; route_attribute = (struct rtattr *) RTM_RTA(route_entry); route_attribute_len = RTM_PAYLOAD(nlh); /* Loop through all attributes */ for (; RTA_OK(route_attribute, route_attribute_len); route_attribute = RTA_NEXT(route_attribute, route_attribute_len)) { switch (route_attribute->rta_type) { case RTA_GATEWAY: inet_ntop(AF_INET, RTA_DATA(route_attribute), ip, IPV4_CHAR_LENGTH); break; default: break; } } } close(sock); return IsValidIP(ip); #endif // !_WIN32 return true; } /// 将IP字符串转为Byte bool CVrNetUtils::IPString2Byte(const char* szIP, unsigned char byIP[4]) { if (nullptr == szIP) return false; unsigned char byTmpIP[4] = { 0 }; int nNum = 0; const char* pchValue = szIP; while ('\0' != *pchValue) { if (*pchValue == '.') { nNum++; if (nNum >= 4) return false; pchValue++; continue; } if (*pchValue < '0' || *pchValue > '9') return false; byTmpIP[nNum] = byTmpIP[nNum] * 10 + (*pchValue - '0'); pchValue++; } memcpy(byIP, byTmpIP, 4); return true; } /// 将IP的Byte转为字符串 void CVrNetUtils::IPByte2String(const unsigned char byIP[4], char szIP[IPV4_CHAR_LENGTH]) { memset(szIP, 0, IPV4_CHAR_LENGTH); #ifdef _MSC_VER sprintf_s(szIP, IPV4_CHAR_LENGTH, "%d.%d.%d.%d", byIP[0], byIP[1], byIP[2], byIP[3]); #else sprintf(szIP, "%d.%d.%d.%d", byIP[0], byIP[1], byIP[2], byIP[3]); #endif } /// 计算广播地址 void CVrNetUtils::CalcBroadCastIP(unsigned char byIP[4], unsigned char byMask[4], unsigned char byBroadCast[4]) { byBroadCast[0] = (byMask[0] & byIP[0]) | (~byMask[0]); byBroadCast[1] = (byMask[1] & byIP[1]) | (~byMask[1]); byBroadCast[2] = (byMask[2] & byIP[2]) | (~byMask[2]); byBroadCast[3] = (byMask[3] & byIP[3]) | (~byMask[3]); }