GrabBag/VrUtils/Src/VrNetUtils.cpp

800 lines
20 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "VrNetUtils.h"
#include "VrLog.h"
#ifdef _WIN32
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <WS2tcpip.h>
#include <winsock2.h>
#include <ws2def.h>
#include <ws2ipdef.h>
#include <IPHlpApi.h>
#include <functional>
#include <sstream>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "IPHlpApi.lib")
#pragma comment(lib, "Advapi32.lib")
#else
#include <net/if.h>
#include <net/if_arp.h>
#include <asm/types.h>
#include <linux/route.h>
#include <linux/if.h>
#include <linux/rtnetlink.h>
#include <ifaddrs.h>
#include <sys/types.h>
#include <ifaddrs.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
//#include <net/route.h>
#include <linux/netlink.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif
#include <sstream>
#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;
// <20><>ӡ sin->sin_addr.s_addr <20>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD>
//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<std::mutex> 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<49><50>ַ
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;
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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;
}
//<2F><><EFBFBD><EFBFBD>
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); // Ĭ<><C4AC>·<EFBFBD><C2B7>
((struct sockaddr_in *)&rt.rt_genmask)->sin_addr.s_addr = htonl(0); // <20><><EFBFBD><EFBFBD>Ϊ 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);//<2F><>ʽ<EFBFBD><CABD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
if (ERROR_SUCCESS != RegOpenKeyExA(hSubKey, szDataBuf, 0, KEY_READ, &hLocalKey))
{
break;
}
//<2F><><EFBFBD><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ֵ
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();
}
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>
bool CVrNetUtils::QueryAllNetworkInfo(std::list<SVrCardInfo>& 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);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E3B2A5>ַ
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<49>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
/// @param szIPv4[in] IP<49><50>ַ
/// @return IP<49><50><EFBFBD><EFBFBD><EFBFBD>򷵻<EFBFBD>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 = "\\."; //<2F>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
#ifdef _WIN32
char* p = strtok_s((char *)tmp, delim, &buf); //<2F><>һ<EFBFBD>ε<EFBFBD><CEB5><EFBFBD>strtok
#else
char* p = strtok((char *)tmp, delim); //<2F><>һ<EFBFBD>ε<EFBFBD><CEB5><EFBFBD>strtok
#endif
int index = 0;
while (p != NULL)
{ //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>ΪNULLʱ<4C><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD>
index++;
#ifdef _WIN32
p = strtok_s(NULL, delim, &buf); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>strtok<6F><6B><EFBFBD>ֽ<EFBFBD>ʣ<EFBFBD>µ<EFBFBD><C2B5>ַ<EFBFBD><D6B7><EFBFBD>
#else
p = strtok(NULL, delim); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>strtok<6F><6B><EFBFBD>ֽ<EFBFBD>ʣ<EFBFBD>µ<EFBFBD><C2B5>ַ<EFBFBD><D6B7><EFBFBD>
#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
/// <20><>ȡIP<49><50>ַ
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
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool CVrNetUtils::GetIPv4NetMask(char ip[IPV4_CHAR_LENGTH], const char *devName)
{
return _GetAddr(ip, SIOCGIFNETMASK, devName);
}
/// <20><>ȡ<EFBFBD><EFBFBD><E3B2A5>ַ
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
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
bool CVrNetUtils::GetLocalMAC(char byMac[MAC_CHAR_LENGTH], const char *devName)
{
return _GetAddr((char*)byMac, SIOCGIFHWADDR, devName);
}
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool CVrNetUtils::SetGateWay(const char ip[IPV4_CHAR_LENGTH], const char *devName)
{
#ifndef _WIN32
std::lock_guard<std::mutex> 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;
}
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>
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;
}
/// <20><>IP<49>ַ<EFBFBD><D6B7><EFBFBD>תΪ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;
}
/// <20><>IP<49><50>ByteתΪ<D7AA>ַ<EFBFBD><D6B7><EFBFBD>
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
}
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E3B2A5>ַ
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]);
}