How can I get the default gateway IP using QT ?
-
I found the following code somewhere, it works for me
@int getDefaultGatewayCC(char *gatewayip, socklen_t size)
{
int found_gatewayip = 0;struct nlmsghdr *nlMsg; struct route_info *rtInfo; char msgBuf[BUFSIZE]; // pretty large buffer int sock, msgSeq = 0; int len; /* Create Socket */ if((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) { perror("Socket Creation: "); return(-1); } /* Initialize the buffer */ memset(msgBuf, 0, BUFSIZE); /* 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)); // Length of message. 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. /* Send the request */ if(send(sock, nlMsg, nlMsg->nlmsg_len, 0) < 0) { fprintf(stderr, "Write To Socket Failed...\n"); return -1; } /* Read the response */ if((len = readNlSock(sock, msgBuf, msgSeq, getpid())) < 0) { fprintf(stderr, "Read From Socket Failed...\n"); return -1; } /* Parse and print the response */ rtInfo = (struct route_info *)malloc(sizeof(struct route_info)); for(;NLMSG_OK(nlMsg,len);nlMsg = NLMSG_NEXT(nlMsg,len)) { memset(rtInfo, 0, sizeof(struct route_info)); parseRoutes(nlMsg, rtInfo); // Check if default gateway if (strstr((char *)inet_ntoa(rtInfo->dstAddr), "0.0.0.0") && !strstr((char *)inet_ntoa(rtInfo->gateWay), "0.0.0.0")) { // copy it over inet_ntop(AF_INET, &rtInfo->gateWay, gatewayip, size); found_gatewayip = 1; break; } } free(rtInfo); close(sock); return found_gatewayip;
}@
-
What libraries did you use?
Do you have Win32 example also ? -
For a Win32 API implementation see MSDN and the "GetAdaptersInfo":http://msdn.microsoft.com/en-us/library/Aa365917 function.
-
Another one platform-dependent solution for Windows using WinAPI:
@ char strHost[50];
WSADATA wsaData;
SOCKADDR_IN SockAddr;memset(strHost, 0 , 50); if(WSAStartup(0x0101, &wsaData) != 0) return m_myIP; gethostname(strHost, 50); hostent* HostInfo = gethostbyname(strHost); memcpy(&(SockAddr.sin_addr),HostInfo->h_addr,HostInfo->h_length); char* pIP = inet_ntoa(SockAddr.sin_addr);@
Now pIP holds your default IP address.
-
Tested on Windows 7, Debian 7 and Android:
#ifdef Q_OS_WIN #include <wbemidl.h> #include <comdef.h> #include <windows.h> #pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "Wbemuuid.lib") #else #define BUFSIZE 8192 #include <arpa/inet.h> #include <net/if.h> #include <sys/socket.h> #include <linux/rtnetlink.h> #include <unistd.h> struct route_info { in_addr dstAddr; in_addr srcAddr; in_addr gateWay; char ifName[IF_NAMESIZE]; }; int readNlSock(int sockFd, char *bufPtr, unsigned int seqNum, int pId) { struct nlmsghdr *nlHdr; int readLen = 0, msgLen = 0; do { if ((readLen = recv(sockFd, bufPtr, BUFSIZE - msgLen, 0)) < 0) { perror("SOCK READ: "); return -1; } nlHdr = (struct nlmsghdr *)bufPtr; if ((NLMSG_OK(nlHdr, readLen) == 0) || (nlHdr->nlmsg_type == NLMSG_ERROR)) { perror("Error in received packet"); return -1; } if (nlHdr->nlmsg_type == NLMSG_DONE) break; bufPtr += readLen; msgLen += readLen; if ((nlHdr->nlmsg_flags & NLM_F_MULTI) == 0) break; } while ((nlHdr->nlmsg_seq != seqNum) || (nlHdr->nlmsg_pid != (unsigned)pId)); return msgLen; } void parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo) { struct rtmsg *rtMsg = (struct rtmsg *)NLMSG_DATA(nlHdr); if ((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN)) return; struct rtattr *rtAttr = (struct rtattr *)RTM_RTA(rtMsg); int rtLen = RTM_PAYLOAD(nlHdr); for (; RTA_OK(rtAttr, rtLen); rtAttr = RTA_NEXT(rtAttr, rtLen)) { switch (rtAttr->rta_type) { case RTA_OIF: if_indextoname(*(int *)RTA_DATA(rtAttr), rtInfo->ifName); break; case RTA_GATEWAY: rtInfo->gateWay = *(in_addr *)RTA_DATA(rtAttr); break; case RTA_PREFSRC: rtInfo->srcAddr = *(in_addr *)RTA_DATA(rtAttr); break; case RTA_DST: rtInfo->dstAddr = *(in_addr *)RTA_DATA(rtAttr); break; } } } #endif class NetworkHelper { public: static QString DefaultGateway() { QString ret; #ifdef Q_OS_WIN CoInitialize(NULL); if (CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0) != S_OK) return ret; IWbemLocator *pLoc = NULL; if (CoCreateInstance(CLSID_WbemAdministrativeLocator, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, IID_IUnknown, (void **)&pLoc) != S_OK) return ret; IWbemServices *pSvc = NULL; if (pLoc->ConnectServer(L"root\\cimv2", NULL, NULL, NULL, 0, NULL, NULL, &pSvc) != S_OK) return ret; IEnumWbemClassObject *pEnumerator = NULL; HRESULT hr = pSvc->ExecQuery(L"WQL", L"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = 'TRUE'", WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator); if (FAILED(hr)) { pSvc->Release(); pLoc->Release(); CoUninitialize(); return ret; } IWbemClassObject *pclsObj = NULL; while (pEnumerator && ret.isEmpty()) { _variant_t vaDefaultIPGateway; ULONG uReturn; hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if (!uReturn) break; hr = pclsObj->Get(L"DefaultIPGateway", 0, &vaDefaultIPGateway, NULL, NULL); if (hr == WBEM_S_NO_ERROR && vaDefaultIPGateway.vt != VT_NULL) { LONG lLow = 0; LONG lUp = 0; ::SafeArrayGetLBound(vaDefaultIPGateway.parray, 1, &lLow); ::SafeArrayGetUBound(vaDefaultIPGateway.parray, 1, &lUp); for (LONG i = lLow; i <= lUp; i++) { BSTR bsDefaultIPGateway; if (::SafeArrayGetElement(vaDefaultIPGateway.parray, &i, &bsDefaultIPGateway) == S_OK) { ret = QString::fromUtf16(reinterpret_cast<const ushort *>(bsDefaultIPGateway)); ::SysFreeString(bsDefaultIPGateway); break; } } } VariantClear(&vaDefaultIPGateway); } if (pclsObj) pclsObj->Release(); if (pEnumerator) pEnumerator->Release(); if (pSvc) pSvc->Release(); if (pLoc) pLoc->Release(); CoUninitialize(); #else int sock, msgSeq = 0; if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) { perror("Socket Creation: "); return ret; } char msgBuf[BUFSIZE]; memset(msgBuf, 0, BUFSIZE); struct nlmsghdr *nlMsg = (struct nlmsghdr *)msgBuf; nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); nlMsg->nlmsg_type = RTM_GETROUTE; nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; nlMsg->nlmsg_seq = msgSeq++; nlMsg->nlmsg_pid = getpid(); if (send(sock, nlMsg, nlMsg->nlmsg_len, 0) < 0) return ret; int len; if ((len = readNlSock(sock, msgBuf, msgSeq, getpid())) < 0) return ret; struct route_info *rtInfo = (struct route_info *)malloc(sizeof(struct route_info)); for (; NLMSG_OK(nlMsg, len); nlMsg = NLMSG_NEXT(nlMsg, len)) { memset(rtInfo, 0, sizeof(struct route_info)); parseRoutes(nlMsg, rtInfo); if (strstr((char *)inet_ntoa(rtInfo->dstAddr), "0.0.0.0") && !strstr((char *)inet_ntoa(rtInfo->gateWay), "0.0.0.0")) { char buf[64]; inet_ntop(AF_INET, &rtInfo->gateWay, buf, sizeof(buf)); ret = QString(buf); break; } } free(rtInfo); close(sock); #endif return ret; } };
Usage:
QString addr = NetworkHelper::DefaultGateway();
-
Hi and welcome to devnet,
Thanks for sharing your code. You should consider making it a wiki entry. Forum posts will get buried time passing by.
-
@Mechan
on windows 8 doesn't work
for comipling replace:
#include <wbemidl.h>to
Wbemcli.h
CLSID_WbemAdministrativeLocator to CLSID_WbemLocator
if (pLoc->ConnectServer(L"root\cimv2", NULL, NULL, NULL, 0, NULL, NULL, &pSvc) != S_OK)to
if (pLoc->ConnectServer(BSTR (L"root\cimv2"), NULL, NULL, NULL, 0, NULL, NULL, &pSvc) != S_OK)
HRESULT hr = pSvc->ExecQuery(L"WQL", L"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = 'TRUE'", WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
to
HRESULT hr = pSvc->ExecQuery(BSTR (L"WQL"),BSTR ( L"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = 'TRUE'"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
after launching:
CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0) never OKif delete this check then uReturn is bad
-
@Adrian_Eddy said in How can I get the default gateway IP using QT ?:
Tested on Windows 7, Debian 7 and Android:
Does this work on OSX and Ubuntu?
-
@Taytoo
Since that post is from 2014 and he last posted in 2016, he probably will not be answering you.... -
@Taytoo
well it used to work on Debian so high chance it will work
on Ubuntu too but time moved on and changes might be needed.
I have no idea about macOs but my guess would be no.
also the last post using
CoInitializeSecurity seems very windows focused.