Qt 6.x
The Qt SDK
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
77{
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.
static QString localDomainName()
Returns the DNS domain of this machine.
Definition qlist.h:74
The QNetworkAddressEntry class stores one IP address supported by a network interface,...
static uint interfaceIndexFromName(const QString &name)
static QString interfaceNameFromIndex(uint index)
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5788
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
Definition qstring.h:1164
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:7822
static QString fromAce(const QByteArray &domain, AceProcessingOptions options={})
Definition qurl.cpp:3038
Combined button and popup list for selecting options.
#define qWarning
Definition qlogging.h:162
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:29
QFileInfo info(fileName)
[8]