Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qnetworkinterface_win.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#define WIN32_LEAN_AND_MEAN 1
6
7#include "qnetworkinterface.h"
9
10#ifndef QT_NO_NETWORKINTERFACE
11
12#include <qhostinfo.h>
13#include <qhash.h>
14#include <qurl.h>
15
16// Since we need to include winsock2.h, we need to define WIN32_LEAN_AND_MEAN
17// (above) so windows.h won't include winsock.h.
18// In addition, we need to include winsock2.h before iphlpapi.h and we need
19// to include ws2ipdef.h to work around an MinGW-w64 bug
20// (http://sourceforge.net/p/mingw-w64/mailman/message/32935366/)
21#include <winsock2.h>
22#include <ws2ipdef.h>
23#include <wincrypt.h>
24#include <iphlpapi.h>
25#include <ws2tcpip.h>
26
27#include <qt_windows.h>
28
29// In case these aren't defined
30#define IF_TYPE_IEEE80216_WMAN 237
31#define IF_TYPE_IEEE802154 259
32
34
36{
38 if (!sa)
39 return address;
40
41 if (sa->sa_family == AF_INET) {
42 address.setAddress(htonl(reinterpret_cast<const sockaddr_in *>(sa)->sin_addr.s_addr));
43 } else if (sa->sa_family == AF_INET6) {
44 auto sai6 = reinterpret_cast<const sockaddr_in6 *>(sa);
45 address.setAddress(sai6->sin6_addr.s6_addr);
46 if (sai6->sin6_scope_id)
47 address.setScopeId(QNetworkInterfaceManager::interfaceNameFromIndex(sai6->sin6_scope_id));
48 } else {
49 qWarning("Got unknown socket family %d", sa->sa_family);
50 }
51 return address;
52
53}
54
56{
57 NET_IFINDEX id;
58 NET_LUID luid;
59 if (ConvertInterfaceNameToLuidW(reinterpret_cast<const wchar_t *>(name.constData()), &luid) == NO_ERROR
60 && ConvertInterfaceLuidToIndex(&luid, &id) == NO_ERROR)
61 return uint(id);
62 return 0;
63}
64
66{
67 NET_LUID luid;
68 if (ConvertInterfaceIndexToLuid(index, &luid) == NO_ERROR) {
69 WCHAR buf[IF_MAX_STRING_SIZE + 1];
70 if (ConvertInterfaceLuidToNameW(&luid, buf, sizeof(buf)/sizeof(buf[0])) == NO_ERROR)
72 }
73 return QString::number(index);
74}
75
76static QList<QNetworkInterfacePrivate *> interfaceListing()
77{
78 QList<QNetworkInterfacePrivate *> interfaces;
79 IP_ADAPTER_ADDRESSES staticBuf[2]; // 2 is arbitrary
80 PIP_ADAPTER_ADDRESSES pAdapter = staticBuf;
81 ULONG bufSize = sizeof staticBuf;
82
83 ULONG flags = GAA_FLAG_INCLUDE_PREFIX |
84 GAA_FLAG_SKIP_DNS_SERVER |
85 GAA_FLAG_SKIP_MULTICAST;
86 ULONG retval = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAdapter, &bufSize);
87 if (retval == ERROR_BUFFER_OVERFLOW) {
88 // need more memory
89 pAdapter = reinterpret_cast<IP_ADAPTER_ADDRESSES *>(malloc(bufSize));
90 if (!pAdapter)
91 return interfaces;
92 // try again
93 if (GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAdapter, &bufSize) != ERROR_SUCCESS) {
94 free(pAdapter);
95 return interfaces;
96 }
97 } else if (retval != ERROR_SUCCESS) {
98 // error
99 return interfaces;
100 }
101
102 // iterate over the list and add the entries to our listing
103 for (PIP_ADAPTER_ADDRESSES ptr = pAdapter; ptr; ptr = ptr->Next) {
104 // the structure grows over time, so let's make sure the fields
105 // introduced in Windows Vista are present (Luid is the furthest
106 // field we access from IP_ADAPTER_ADDRESSES_LH)
107 Q_ASSERT(ptr->Length >= offsetof(IP_ADAPTER_ADDRESSES, Luid));
108 Q_ASSERT(ptr->Length >= offsetof(IP_ADAPTER_ADDRESSES, Ipv6IfIndex));
109
111 interfaces << iface;
112
113 iface->index = 0;
114 if (ptr->Ipv6IfIndex != 0)
115 iface->index = ptr->Ipv6IfIndex;
116 else if (ptr->IfIndex != 0)
117 iface->index = ptr->IfIndex;
118
119 iface->mtu = qMin<qint64>(ptr->Mtu, INT_MAX);
120 iface->flags = QNetworkInterface::CanBroadcast;
121 if (ptr->OperStatus == IfOperStatusUp)
123 if ((ptr->Flags & IP_ADAPTER_NO_MULTICAST) == 0)
124 iface->flags |= QNetworkInterface::CanMulticast;
125 if (ptr->IfType == IF_TYPE_PPP)
126 iface->flags |= QNetworkInterface::IsPointToPoint;
127
128 switch (ptr->IfType) {
129 case IF_TYPE_ETHERNET_CSMACD:
130 iface->type = QNetworkInterface::Ethernet;
131 break;
132
133 case IF_TYPE_FDDI:
134 iface->type = QNetworkInterface::Fddi;
135 break;
136
137 case IF_TYPE_PPP:
138 iface->type = QNetworkInterface::Ppp;
139 break;
140
141 case IF_TYPE_SLIP:
142 iface->type = QNetworkInterface::Slip;
143 break;
144
145 case IF_TYPE_SOFTWARE_LOOPBACK:
146 iface->type = QNetworkInterface::Loopback;
147 iface->flags |= QNetworkInterface::IsLoopBack;
148 break;
149
150 case IF_TYPE_IEEE80211:
151 iface->type = QNetworkInterface::Ieee80211;
152 break;
153
154 case IF_TYPE_IEEE1394:
155 iface->type = QNetworkInterface::Ieee1394;
156 break;
157
159 iface->type = QNetworkInterface::Ieee80216;
160 break;
161
163 iface->type = QNetworkInterface::Ieee802154;
164 break;
165 }
166
167 // use ConvertInterfaceLuidToNameW because that returns a friendlier name, though not
168 // as "friendly" as FriendlyName below
169 WCHAR buf[IF_MAX_STRING_SIZE + 1];
170 if (ConvertInterfaceLuidToNameW(&ptr->Luid, buf, sizeof(buf)/sizeof(buf[0])) == NO_ERROR)
171 iface->name = QString::fromWCharArray(buf);
172 if (iface->name.isEmpty())
173 iface->name = QString::fromLocal8Bit(ptr->AdapterName);
174
175 iface->friendlyName = QString::fromWCharArray(ptr->FriendlyName);
176 if (ptr->PhysicalAddressLength)
177 iface->hardwareAddress = iface->makeHwAddress(ptr->PhysicalAddressLength,
178 ptr->PhysicalAddress);
179
180 // parse the IP (unicast) addresses
181 for (PIP_ADAPTER_UNICAST_ADDRESS addr = ptr->FirstUnicastAddress; addr; addr = addr->Next) {
182 Q_ASSERT(addr->Length >= offsetof(IP_ADAPTER_UNICAST_ADDRESS, OnLinkPrefixLength));
183
184 // skip addresses in invalid state
185 if (addr->DadState == IpDadStateInvalid)
186 continue;
187
189 entry.setIp(addressFromSockaddr(addr->Address.lpSockaddr));
190 entry.setPrefixLength(addr->OnLinkPrefixLength);
191
192 auto toDeadline = [](ULONG lifetime) -> QDeadlineTimer {
193 if (lifetime == 0xffffffffUL)
195 return QDeadlineTimer(lifetime * 1000);
196 };
197 entry.setAddressLifetime(toDeadline(addr->ValidLifetime), toDeadline(addr->PreferredLifetime));
198 entry.setDnsEligibility(addr->Flags & IP_ADAPTER_ADDRESS_DNS_ELIGIBLE ?
201
202 iface->addressEntries << entry;
203 }
204 }
205
206 if (pAdapter != staticBuf)
207 free(pAdapter);
208
209 return interfaces;
210}
211
212QList<QNetworkInterfacePrivate *> QNetworkInterfaceManager::scan()
213{
214 return interfaceListing();
215}
216
218{
219 FIXED_INFO info, *pinfo;
220 ULONG bufSize = sizeof info;
221 pinfo = &info;
222 if (GetNetworkParams(pinfo, &bufSize) == ERROR_BUFFER_OVERFLOW) {
223 pinfo = reinterpret_cast<FIXED_INFO *>(malloc(bufSize));
224 if (!pinfo)
225 return QString();
226 // try again
227 if (GetNetworkParams(pinfo, &bufSize) != ERROR_SUCCESS) {
228 free(pinfo);
229 return QString(); // error
230 }
231 }
232
233 QString domainName = QUrl::fromAce(pinfo->DomainName);
234
235 if (pinfo != &info)
236 free(pinfo);
237
238 return domainName;
239}
240
242
243#endif // QT_NO_NETWORKINTERFACE
\inmodule QtCore
static constexpr ForeverConstant Forever
The QHostAddress class provides an IP address.
void setAddress(quint32 ip4Addr)
Set the IPv4 address specified by ip4Addr.
static QString localDomainName()
Returns the DNS domain of this machine.
The QNetworkAddressEntry class stores one IP address supported by a network interface,...
void setIp(const QHostAddress &newIp)
Sets the IP address the QNetworkAddressEntry object contains to newIp.
static uint interfaceIndexFromName(const QString &name)
static QString interfaceNameFromIndex(uint index)
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5949
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
Definition qstring.h:1309
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:8084
static QString fromAce(const QByteArray &domain, AceProcessingOptions options={})
Definition qurl.cpp:3041
Combined button and popup list for selecting options.
#define qWarning
Definition qlogging.h:166
static ControlElement< T > * ptr(QWidget *widget)
#define AF_INET6
static QList< QNetworkInterfacePrivate * > interfaceListing()
#define IF_TYPE_IEEE802154
static QList< QNetworkInterfacePrivate * > interfaceListing()
static QT_BEGIN_NAMESPACE QHostAddress addressFromSockaddr(sockaddr *sa)
#define IF_TYPE_IEEE80216_WMAN
GLuint index
[2]
GLenum GLuint id
[7]
GLenum GLuint GLenum GLsizei const GLchar * buf
GLbitfield flags
GLuint name
GLsizei bufSize
GLuint entry
GLenum const void * addr
GLuint GLuint64EXT address
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
unsigned int uint
Definition qtypes.h:34
QHostInfo info
[0]