File indexing completed on 2024-03-24 04:03:02
0001 /* 0002 SPDX-FileCopyrightText: 2009 Will Stephenson <wstephenson@kde.org> 0003 SPDX-FileCopyrightText: 2012-2013 Jan Grulich <jgrulich@redhat.com> 0004 0005 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0006 */ 0007 0008 #include <QRegularExpression> 0009 0010 #include "time.h" 0011 #include "utils.h" 0012 0013 QHostAddress NetworkManager::ipv6AddressAsHostAddress(const QByteArray &address) 0014 { 0015 // Q_ASSERT(address.size() == 16); 0016 Q_IPV6ADDR tmp; 0017 for (int i = 0; i < 16; ++i) { 0018 tmp[i] = address[i]; 0019 } 0020 QHostAddress hostaddress(tmp); 0021 Q_ASSERT(hostaddress.protocol() == QAbstractSocket::IPv6Protocol); 0022 0023 return hostaddress; 0024 } 0025 0026 QByteArray NetworkManager::ipv6AddressFromHostAddress(const QHostAddress &address) 0027 { 0028 // Q_ASSERT(address.protocol() == QAbstractSocket::IPv6Protocol); 0029 Q_IPV6ADDR tmp = address.toIPv6Address(); 0030 QByteArray assembledAddress; 0031 assembledAddress.reserve(16); 0032 for (int i = 0; i < 16; ++i) { 0033 assembledAddress.push_back(tmp[i]); 0034 } 0035 0036 return assembledAddress; 0037 } 0038 0039 QString NetworkManager::macAddressAsString(const QByteArray &ba) 0040 { 0041 QStringList mac; 0042 0043 for (int i = 0; i < ba.size(); ++i) { 0044 mac << QString("%1").arg((quint8)ba[i], 2, 16, QLatin1Char('0')).toUpper(); 0045 } 0046 0047 return mac.join(":"); 0048 } 0049 0050 QByteArray NetworkManager::macAddressFromString(const QString &s) 0051 { 0052 const QStringList macStringList = s.split(':'); 0053 // Q_ASSERT(macStringList.size() == 6); 0054 QByteArray ba; 0055 if (!s.isEmpty()) { 0056 ba.resize(6); 0057 int i = 0; 0058 0059 for (const QString &macPart : macStringList) { 0060 ba[i++] = macPart.toUInt(nullptr, 16); 0061 } 0062 } 0063 return ba; 0064 } 0065 0066 bool NetworkManager::macAddressIsValid(const QString &macAddress) 0067 { 0068 QRegularExpression macAddressCheck(QStringLiteral("([a-fA-F0-9][a-fA-F0-9]:){5}[0-9a-fA-F][0-9a-fA-F]")); 0069 0070 return macAddressCheck.match(macAddress).hasMatch(); 0071 } 0072 0073 bool NetworkManager::macAddressIsValid(const QByteArray &macAddress) 0074 { 0075 return macAddressIsValid(macAddressAsString(macAddress)); 0076 } 0077 0078 int NetworkManager::findChannel(int freq) 0079 { 0080 int channel; 0081 if (freq < 2500) { 0082 channel = 0; 0083 int i = 0; 0084 QList<QPair<int, int>> bFreqs = getBFreqs(); 0085 while (i < bFreqs.size()) { 0086 if (bFreqs.at(i).second <= freq) { 0087 channel = bFreqs.at(i).first; 0088 } else { 0089 break; 0090 } 0091 i++; 0092 } 0093 return channel; 0094 } 0095 channel = 0; 0096 int i = 0; 0097 QList<QPair<int, int>> aFreqs = getAFreqs(); 0098 while (i < aFreqs.size()) { 0099 if (aFreqs.at(i).second <= freq) { 0100 channel = aFreqs.at(i).first; 0101 if (aFreqs.at(i).second == freq) { 0102 break; 0103 } 0104 } else { 0105 break; 0106 } 0107 i++; 0108 } 0109 0110 return channel; 0111 } 0112 0113 NetworkManager::WirelessSetting::FrequencyBand NetworkManager::findFrequencyBand(int freq) 0114 { 0115 if (freq < 2500) { 0116 return WirelessSetting::Bg; 0117 } 0118 0119 return WirelessSetting::A; 0120 } 0121 0122 bool NetworkManager::deviceSupportsApCiphers(NetworkManager::WirelessDevice::Capabilities interfaceCaps, 0123 NetworkManager::AccessPoint::WpaFlags apCiphers, 0124 WirelessSecurityType type) 0125 { 0126 bool havePair = false; 0127 bool haveGroup = true; 0128 0129 if (type == NetworkManager::StaticWep) { 0130 havePair = true; 0131 } else { 0132 if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Wep40) && apCiphers.testFlag(NetworkManager::AccessPoint::PairWep40)) { 0133 havePair = true; 0134 } 0135 if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Wep104) && apCiphers.testFlag(NetworkManager::AccessPoint::PairWep104)) { 0136 havePair = true; 0137 } 0138 if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Tkip) && apCiphers.testFlag(NetworkManager::AccessPoint::PairTkip)) { 0139 havePair = true; 0140 } 0141 if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Ccmp) && apCiphers.testFlag(NetworkManager::AccessPoint::PairCcmp)) { 0142 havePair = true; 0143 } 0144 } 0145 0146 if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Wep40) && apCiphers.testFlag(NetworkManager::AccessPoint::GroupWep40)) { 0147 haveGroup = true; 0148 } 0149 if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Wep104) && apCiphers.testFlag(NetworkManager::AccessPoint::GroupWep104)) { 0150 haveGroup = true; 0151 } 0152 if (type != StaticWep) { 0153 if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Tkip) && apCiphers.testFlag(NetworkManager::AccessPoint::GroupTkip)) { 0154 haveGroup = true; 0155 } 0156 if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Ccmp) && apCiphers.testFlag(NetworkManager::AccessPoint::GroupCcmp)) { 0157 haveGroup = true; 0158 } 0159 } 0160 0161 return (havePair && haveGroup); 0162 } 0163 0164 // Keep this in sync with NetworkManager/libnm-core/nm-utils.c:nm_utils_security_valid() 0165 bool NetworkManager::securityIsValid(WirelessSecurityType type, 0166 NetworkManager::WirelessDevice::Capabilities interfaceCaps, 0167 bool haveAp, 0168 bool adhoc, 0169 NetworkManager::AccessPoint::Capabilities apCaps, 0170 NetworkManager::AccessPoint::WpaFlags apWpa, 0171 NetworkManager::AccessPoint::WpaFlags apRsn) 0172 { 0173 bool good = true; 0174 0175 // kDebug() << "type(" << type << ") interfaceCaps(" << interfaceCaps << ") haveAp(" << haveAp << ") adhoc(" << adhoc << ") apCaps(" << apCaps << ") apWpa(" 0176 // << apWpa << " apRsn(" << apRsn << ")"; 0177 0178 if (!haveAp) { 0179 if (type == NoneSecurity) { 0180 return true; 0181 } 0182 if ((type == StaticWep) // 0183 || ((type == DynamicWep) && !adhoc) // 0184 || ((type == Leap) && !adhoc)) { 0185 if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Wep40) || interfaceCaps.testFlag(NetworkManager::WirelessDevice::Wep104)) { 0186 return true; 0187 } else { 0188 return false; 0189 } 0190 } 0191 0192 // apCaps.testFlag(Privacy) == true for StaticWep, Leap and DynamicWep 0193 // see libs/internals/wirelessinterfaceconnectionhelpers.cpp 0194 0195 // TODO: this is not in nm-utils.c 0196 // if (type == Knm::WirelessSecurity::WpaPsk 0197 // || ((type == Knm::WirelessSecurity::WpaEap) && !adhoc)) { 0198 // if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Wpa) && 0199 // !apCaps.testFlag(NetworkManager::AccessPoint::Privacy)) { 0200 // return true; 0201 // } 0202 // } 0203 // if (type == Knm::WirelessSecurity::Wpa2Psk 0204 // || ((type == Knm::WirelessSecurity::Wpa2Eap) && !adhoc)) { 0205 // if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Rsn) && 0206 // !apCaps.testFlag(NetworkManager::AccessPoint::Privacy)) { 0207 // return true; 0208 // } 0209 // } 0210 } 0211 0212 switch (type) { 0213 case NoneSecurity: 0214 Q_ASSERT(haveAp); 0215 if (apCaps.testFlag(NetworkManager::AccessPoint::Privacy)) { 0216 return false; 0217 } 0218 if (apWpa || apRsn) { 0219 return false; 0220 } 0221 break; 0222 case Leap: /* require PRIVACY bit for LEAP? */ 0223 if (adhoc) { 0224 return false; 0225 } 0226 /* Fall through */ 0227 case StaticWep: 0228 Q_ASSERT(haveAp); 0229 if (!apCaps.testFlag(NetworkManager::AccessPoint::Privacy)) { 0230 return false; 0231 } 0232 if (apWpa || apRsn) { 0233 if (!deviceSupportsApCiphers(interfaceCaps, apWpa, StaticWep)) { 0234 if (!deviceSupportsApCiphers(interfaceCaps, apRsn, StaticWep)) { 0235 return false; 0236 } 0237 } 0238 } 0239 break; 0240 case DynamicWep: 0241 if (adhoc) { 0242 return false; 0243 } 0244 Q_ASSERT(haveAp); 0245 if (apRsn || !(apCaps.testFlag(NetworkManager::AccessPoint::Privacy))) { 0246 return false; 0247 } 0248 /* Some APs broadcast minimal WPA-enabled beacons that must be handled */ 0249 if (apWpa) { 0250 if (!apWpa.testFlag(NetworkManager::AccessPoint::KeyMgmt8021x)) { 0251 return false; 0252 } 0253 if (!deviceSupportsApCiphers(interfaceCaps, apWpa, DynamicWep)) { 0254 return false; 0255 } 0256 } 0257 break; 0258 case WpaPsk: 0259 if (adhoc) { 0260 return false; 0261 } 0262 0263 if (!interfaceCaps.testFlag(NetworkManager::WirelessDevice::Wpa)) { 0264 return false; 0265 } 0266 if (haveAp) { 0267 if (apWpa.testFlag(NetworkManager::AccessPoint::KeyMgmtPsk)) { 0268 if (apWpa.testFlag(NetworkManager::AccessPoint::PairTkip) // 0269 && interfaceCaps.testFlag(NetworkManager::WirelessDevice::Tkip)) { 0270 return true; 0271 } 0272 if (apWpa.testFlag(NetworkManager::AccessPoint::PairCcmp) // 0273 && interfaceCaps.testFlag(NetworkManager::WirelessDevice::Ccmp)) { 0274 return true; 0275 } 0276 } 0277 return false; 0278 } 0279 break; 0280 case Wpa2Psk: 0281 if (!interfaceCaps.testFlag(NetworkManager::WirelessDevice::Rsn)) { 0282 return false; 0283 } 0284 if (haveAp) { 0285 if (adhoc) { 0286 if (!interfaceCaps.testFlag(NetworkManager::WirelessDevice::IBSSRsn)) { 0287 return false; 0288 } 0289 if (apRsn.testFlag(NetworkManager::AccessPoint::PairCcmp) // 0290 && interfaceCaps.testFlag(NetworkManager::WirelessDevice::Ccmp)) { 0291 return true; 0292 } 0293 } else { 0294 if (apRsn.testFlag(NetworkManager::AccessPoint::KeyMgmtPsk)) { 0295 if (apRsn.testFlag(NetworkManager::AccessPoint::PairTkip) // 0296 && interfaceCaps.testFlag(NetworkManager::WirelessDevice::Tkip)) { 0297 return true; 0298 } 0299 if (apRsn.testFlag(NetworkManager::AccessPoint::PairCcmp) // 0300 && interfaceCaps.testFlag(NetworkManager::WirelessDevice::Ccmp)) { 0301 return true; 0302 } 0303 } 0304 } 0305 return false; 0306 } 0307 break; 0308 case WpaEap: 0309 if (adhoc) { 0310 return false; 0311 } 0312 if (!interfaceCaps.testFlag(NetworkManager::WirelessDevice::Wpa)) { 0313 return false; 0314 } 0315 if (haveAp) { 0316 if (!apWpa.testFlag(NetworkManager::AccessPoint::KeyMgmt8021x)) { 0317 return false; 0318 } 0319 /* Ensure at least one WPA cipher is supported */ 0320 if (!deviceSupportsApCiphers(interfaceCaps, apWpa, WpaEap)) { 0321 return false; 0322 } 0323 } 0324 break; 0325 case Wpa2Eap: 0326 if (adhoc) { 0327 return false; 0328 } 0329 if (!interfaceCaps.testFlag(NetworkManager::WirelessDevice::Rsn)) { 0330 return false; 0331 } 0332 if (haveAp) { 0333 if (!apRsn.testFlag(NetworkManager::AccessPoint::KeyMgmt8021x)) { 0334 return false; 0335 } 0336 /* Ensure at least one WPA cipher is supported */ 0337 if (!deviceSupportsApCiphers(interfaceCaps, apRsn, Wpa2Eap)) { 0338 return false; 0339 } 0340 } 0341 break; 0342 case SAE: 0343 if (!interfaceCaps.testFlag(NetworkManager::WirelessDevice::Rsn)) { 0344 return false; 0345 } 0346 if (haveAp) { 0347 if (adhoc) { 0348 if (!interfaceCaps.testFlag(NetworkManager::WirelessDevice::IBSSRsn)) { 0349 return false; 0350 } 0351 if (apRsn.testFlag(NetworkManager::AccessPoint::PairCcmp) // 0352 && interfaceCaps.testFlag(NetworkManager::WirelessDevice::Ccmp)) { 0353 return true; 0354 } 0355 } else { 0356 if (apRsn.testFlag(NetworkManager::AccessPoint::KeyMgmtSAE)) { 0357 if (apRsn.testFlag(NetworkManager::AccessPoint::PairTkip) // 0358 && interfaceCaps.testFlag(NetworkManager::WirelessDevice::Tkip)) { 0359 return true; 0360 } 0361 if (apRsn.testFlag(NetworkManager::AccessPoint::PairCcmp) // 0362 && interfaceCaps.testFlag(NetworkManager::WirelessDevice::Ccmp)) { 0363 return true; 0364 } 0365 } 0366 } 0367 return false; 0368 } 0369 break; 0370 case Wpa3SuiteB192: 0371 if (adhoc) { 0372 return false; 0373 } 0374 if (!interfaceCaps.testFlag(NetworkManager::WirelessDevice::Rsn)) { 0375 return false; 0376 } 0377 if (haveAp && !apRsn.testFlag(NetworkManager::AccessPoint::KeyMgmtEapSuiteB192)) { 0378 return false; 0379 } 0380 break; 0381 default: 0382 good = false; 0383 break; 0384 } 0385 0386 return good; 0387 } 0388 0389 NetworkManager::WirelessSecurityType NetworkManager::findBestWirelessSecurity(NetworkManager::WirelessDevice::Capabilities interfaceCaps, 0390 bool haveAp, 0391 bool adHoc, 0392 NetworkManager::AccessPoint::Capabilities apCaps, 0393 NetworkManager::AccessPoint::WpaFlags apWpa, 0394 NetworkManager::AccessPoint::WpaFlags apRsn) 0395 { 0396 // The ordering of this list is a pragmatic combination of security level and popularity. 0397 // Therefore static WEP is before LEAP and Dynamic WEP because there is no way to detect 0398 // if an AP is capable of Dynamic WEP and showing Dynamic WEP first would confuse 0399 // Static WEP users. 0400 const QList<NetworkManager::WirelessSecurityType> types = {NetworkManager::Wpa3SuiteB192, 0401 NetworkManager::SAE, 0402 NetworkManager::Wpa2Eap, 0403 NetworkManager::Wpa2Psk, 0404 NetworkManager::WpaEap, 0405 NetworkManager::WpaPsk, 0406 NetworkManager::StaticWep, 0407 NetworkManager::DynamicWep, 0408 NetworkManager::Leap, 0409 NetworkManager::NoneSecurity}; 0410 0411 for (NetworkManager::WirelessSecurityType type : types) { 0412 if (NetworkManager::securityIsValid(type, interfaceCaps, haveAp, adHoc, apCaps, apWpa, apRsn)) { 0413 return type; 0414 } 0415 } 0416 return NetworkManager::UnknownSecurity; 0417 } 0418 0419 bool NetworkManager::wepKeyIsValid(const QString &key, NetworkManager::WirelessSecuritySetting::WepKeyType type) 0420 { 0421 if (key.isEmpty()) { 0422 return false; 0423 } 0424 0425 const int keylen = key.length(); 0426 0427 if (type != WirelessSecuritySetting::NotSpecified) { 0428 if (type == WirelessSecuritySetting::Hex) { 0429 if (keylen == 10 || keylen == 26) { 0430 /* Hex key */ 0431 for (int i = 0; i < keylen; ++i) { 0432 if (!(key.at(i).isDigit() || (key.at(i) >= 'A' && key.at(i) <= 'F') || (key.at(i) >= 'a' && key.at(i) <= 'f'))) { 0433 return false; 0434 } 0435 } 0436 return true; 0437 } else if (keylen == 5 || keylen == 13) { 0438 /* ASCII KEY */ 0439 for (int i = 0; i < keylen; ++i) { 0440 if (!key.at(i).isPrint()) { 0441 return false; 0442 } 0443 } 0444 return true; 0445 } 0446 0447 return false; 0448 } else if (type == WirelessSecuritySetting::Passphrase) { 0449 if (!keylen || keylen > 64) { 0450 return false; 0451 } 0452 0453 return true; 0454 } 0455 } 0456 0457 return false; 0458 } 0459 0460 bool NetworkManager::wpaPskIsValid(const QString &psk) 0461 { 0462 if (psk.isEmpty()) { 0463 return false; 0464 } 0465 0466 const int psklen = psk.length(); 0467 0468 if (psklen < 8 || psklen > 64) { 0469 return false; 0470 } 0471 0472 if (psklen == 64) { 0473 /* Hex PSK */ 0474 for (int i = 0; i < psklen; ++i) { 0475 if (!psk.at(i).isLetterOrNumber()) { 0476 return false; 0477 } 0478 } 0479 } 0480 0481 return true; 0482 } 0483 0484 NetworkManager::WirelessSecurityType NetworkManager::securityTypeFromConnectionSetting(const NetworkManager::ConnectionSettings::Ptr &settings) 0485 { 0486 NetworkManager::WirelessSecuritySetting::Ptr wifiSecuritySetting = settings->setting(Setting::WirelessSecurity).dynamicCast<WirelessSecuritySetting>(); 0487 if (wifiSecuritySetting->keyMgmt() == WirelessSecuritySetting::Wep) { 0488 return StaticWep; 0489 } else if (wifiSecuritySetting->keyMgmt() == WirelessSecuritySetting::Ieee8021x) { 0490 if (wifiSecuritySetting->authAlg() == WirelessSecuritySetting::Leap) { 0491 return Leap; 0492 } else { 0493 return DynamicWep; 0494 } 0495 } else if (wifiSecuritySetting->keyMgmt() == WirelessSecuritySetting::WpaPsk) { 0496 if (wifiSecuritySetting->proto().contains(WirelessSecuritySetting::Wpa) && !wifiSecuritySetting->proto().contains(WirelessSecuritySetting::Rsn)) { 0497 return WpaPsk; 0498 } 0499 return Wpa2Psk; 0500 } else if (wifiSecuritySetting->keyMgmt() == WirelessSecuritySetting::WpaEap) { 0501 if (wifiSecuritySetting->proto().contains(WirelessSecuritySetting::Wpa) && !wifiSecuritySetting->proto().contains(WirelessSecuritySetting::Rsn)) { 0502 return WpaEap; 0503 } 0504 return Wpa2Eap; 0505 } else if (wifiSecuritySetting->keyMgmt() == WirelessSecuritySetting::SAE) { 0506 return SAE; 0507 } else if (wifiSecuritySetting->keyMgmt() == WirelessSecuritySetting::WpaEapSuiteB192) { 0508 return Wpa3SuiteB192; 0509 } 0510 0511 return NoneSecurity; 0512 } 0513 0514 QList<QPair<int, int>> NetworkManager::getBFreqs() 0515 { 0516 QList<QPair<int, int>> freqs; 0517 0518 freqs.append(QPair<int, int>(1, 2412)); 0519 freqs.append(QPair<int, int>(2, 2417)); 0520 freqs.append(QPair<int, int>(3, 2422)); 0521 freqs.append(QPair<int, int>(4, 2427)); 0522 freqs.append(QPair<int, int>(5, 2432)); 0523 freqs.append(QPair<int, int>(6, 2437)); 0524 freqs.append(QPair<int, int>(7, 2442)); 0525 freqs.append(QPair<int, int>(8, 2447)); 0526 freqs.append(QPair<int, int>(9, 2452)); 0527 freqs.append(QPair<int, int>(10, 2457)); 0528 freqs.append(QPair<int, int>(11, 2462)); 0529 freqs.append(QPair<int, int>(12, 2467)); 0530 freqs.append(QPair<int, int>(13, 2472)); 0531 freqs.append(QPair<int, int>(14, 2484)); 0532 0533 return freqs; 0534 } 0535 0536 QList<QPair<int, int>> NetworkManager::getAFreqs() 0537 { 0538 QList<QPair<int, int>> freqs; 0539 0540 freqs.append(QPair<int, int>(7, 5035)); 0541 freqs.append(QPair<int, int>(8, 5040)); 0542 freqs.append(QPair<int, int>(9, 5045)); 0543 freqs.append(QPair<int, int>(11, 5055)); 0544 freqs.append(QPair<int, int>(12, 5060)); 0545 freqs.append(QPair<int, int>(16, 5080)); 0546 freqs.append(QPair<int, int>(34, 5170)); 0547 freqs.append(QPair<int, int>(36, 5180)); 0548 freqs.append(QPair<int, int>(38, 5190)); 0549 freqs.append(QPair<int, int>(40, 5200)); 0550 freqs.append(QPair<int, int>(42, 5210)); 0551 freqs.append(QPair<int, int>(44, 5220)); 0552 freqs.append(QPair<int, int>(46, 5230)); 0553 freqs.append(QPair<int, int>(48, 5240)); 0554 freqs.append(QPair<int, int>(52, 5260)); 0555 freqs.append(QPair<int, int>(56, 5280)); 0556 freqs.append(QPair<int, int>(60, 5300)); 0557 freqs.append(QPair<int, int>(64, 5320)); 0558 freqs.append(QPair<int, int>(100, 5500)); 0559 freqs.append(QPair<int, int>(104, 5520)); 0560 freqs.append(QPair<int, int>(108, 5540)); 0561 freqs.append(QPair<int, int>(112, 5560)); 0562 freqs.append(QPair<int, int>(116, 5580)); 0563 freqs.append(QPair<int, int>(120, 5600)); 0564 freqs.append(QPair<int, int>(124, 5620)); 0565 freqs.append(QPair<int, int>(128, 5640)); 0566 freqs.append(QPair<int, int>(132, 5660)); 0567 freqs.append(QPair<int, int>(136, 5680)); 0568 freqs.append(QPair<int, int>(140, 5700)); 0569 freqs.append(QPair<int, int>(149, 5745)); 0570 freqs.append(QPair<int, int>(153, 5765)); 0571 freqs.append(QPair<int, int>(157, 5785)); 0572 freqs.append(QPair<int, int>(161, 5805)); 0573 freqs.append(QPair<int, int>(165, 5825)); 0574 freqs.append(QPair<int, int>(183, 4915)); 0575 freqs.append(QPair<int, int>(184, 4920)); 0576 freqs.append(QPair<int, int>(185, 4925)); 0577 freqs.append(QPair<int, int>(187, 4935)); 0578 freqs.append(QPair<int, int>(188, 4940)); 0579 freqs.append(QPair<int, int>(189, 4945)); 0580 freqs.append(QPair<int, int>(192, 4960)); 0581 freqs.append(QPair<int, int>(196, 4980)); 0582 0583 return freqs; 0584 } 0585 0586 QDateTime NetworkManager::clockBootTimeToDateTime(qlonglong clockBootime) 0587 { 0588 clockid_t clk_id = CLOCK_BOOTTIME; 0589 struct timespec tp; 0590 int r; 0591 0592 // now is used as a point of reference 0593 // with the timespec that contains the number of msec since boot 0594 QDateTime now = QDateTime::currentDateTime(); 0595 r = clock_gettime(clk_id, &tp); 0596 if (r == -1 && errno == EINVAL) { 0597 clk_id = CLOCK_MONOTONIC; 0598 r = clock_gettime(clk_id, &tp); 0599 } 0600 0601 // convert to msecs 0602 long now_msecs = tp.tv_sec * 1000 + tp.tv_nsec / 1000000; 0603 0604 // diff the msecs and construct a QDateTime based on the offset 0605 QDateTime res; 0606 if (clockBootime > now_msecs) { 0607 qlonglong offset = clockBootime - now_msecs; 0608 res = QDateTime::fromMSecsSinceEpoch(now.toMSecsSinceEpoch() + offset); 0609 } else { 0610 qlonglong offset = now_msecs - clockBootime; 0611 res = QDateTime::fromMSecsSinceEpoch(now.toMSecsSinceEpoch() - offset); 0612 } 0613 0614 return res; 0615 }