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 }