File indexing completed on 2024-04-14 03:57:42

0001 /*
0002     SPDX-FileCopyrightText: 2008, 2011 Will Stephenson <wstephenson@kde.org>
0003     SPDX-FileCopyrightText: 2013 Daniel Nicoletti <dantti12@gmail.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0006 */
0007 
0008 #include "ipconfig.h"
0009 
0010 #include "manager.h"
0011 #include "manager_p.h"
0012 
0013 #include <arpa/inet.h>
0014 
0015 #include "dbus/ip4configinterface.h"
0016 #include "dbus/ip6configinterface.h"
0017 
0018 namespace NetworkManager
0019 {
0020 class NetworkManager::IpConfig::Private
0021 {
0022 public:
0023     Private(const QList<IpAddress> &theAddresses, const QList<QHostAddress> &theNameservers, const QStringList &theDomains, const QList<IpRoute> &theRoutes)
0024         : addresses(theAddresses)
0025         , nameservers(theNameservers)
0026         , domains(theDomains)
0027         , routes(theRoutes)
0028     {
0029     }
0030     Private()
0031     {
0032     }
0033     IpAddresses addresses;
0034     QString gateway;
0035     QStringList searches;
0036     QList<QHostAddress> nameservers;
0037     QStringList domains;
0038     IpRoutes routes;
0039     QStringList dnsOptions;
0040 };
0041 
0042 }
0043 
0044 NetworkManager::IpConfig::IpConfig(const IpAddresses &addresses, const QList<QHostAddress> &nameservers, const QStringList &domains, const IpRoutes &routes)
0045     : d(new Private(addresses, nameservers, domains, routes))
0046 {
0047 }
0048 
0049 NetworkManager::IpConfig::IpConfig()
0050     : d(new Private())
0051 {
0052 }
0053 
0054 NetworkManager::IpConfig::IpConfig(const IpConfig &other)
0055     : d(new Private)
0056 {
0057     *this = other;
0058 }
0059 
0060 void NetworkManager::IpConfig::setIPv4Path(const QString &path)
0061 {
0062     OrgFreedesktopNetworkManagerIP4ConfigInterface iface(NetworkManagerPrivate::DBUS_SERVICE,
0063                                                          path,
0064 #ifdef NMQT_STATIC
0065                                                          QDBusConnection::sessionBus());
0066 #else
0067                                                          QDBusConnection::systemBus());
0068 #endif
0069     // TODO - watch propertiesChanged signal
0070 
0071     QList<NetworkManager::IpAddress> addressObjects;
0072     QList<NetworkManager::IpRoute> routeObjects;
0073     if (NetworkManager::checkVersion(1, 0, 0)) {
0074         const NMVariantMapList addresses = iface.addressData();
0075         for (const QVariantMap &addressList : addresses) {
0076             if (addressList.contains(QLatin1String("address")) //
0077                 && addressList.contains(QLatin1String("prefix"))) {
0078                 NetworkManager::IpAddress address;
0079                 address.setIp(QHostAddress(addressList.value(QLatin1String("address")).toString()));
0080                 address.setPrefixLength(addressList.value(QLatin1String("prefix")).toUInt());
0081                 if (addressList.contains(QLatin1String("gateway"))) {
0082                     address.setGateway(QHostAddress(addressList.value(QLatin1String("gateway")).toString()));
0083                 }
0084                 addressObjects << address;
0085             }
0086         }
0087 
0088         const NMVariantMapList routes = iface.routeData();
0089         for (const QVariantMap &routeList : routes) {
0090             if (routeList.contains(QLatin1String("address")) && routeList.contains(QLatin1String("prefix"))) {
0091                 NetworkManager::IpRoute route;
0092                 route.setIp(QHostAddress(routeList.value(QLatin1String("address")).toString()));
0093                 route.setPrefixLength(routeList.value(QLatin1String("prefix")).toUInt());
0094                 if (routeList.contains(QLatin1String("next-hop"))) {
0095                     route.setNextHop(QHostAddress(routeList.value(QLatin1String("next-hop")).toString()));
0096                 }
0097 
0098                 if (routeList.contains(QLatin1String("metric"))) {
0099                     route.setMetric(routeList.value(QLatin1String("metric")).toUInt());
0100                 }
0101                 routeObjects << route;
0102             }
0103         }
0104     } else {
0105         // convert ipaddresses into object
0106         const UIntListList addresses = iface.addresses();
0107         for (const UIntList &addressList : addresses) {
0108             if (addressList.count() == 3) {
0109                 NetworkManager::IpAddress address;
0110                 address.setIp(QHostAddress(ntohl(addressList[0])));
0111                 address.setPrefixLength(addressList[1]);
0112                 address.setGateway(QHostAddress(ntohl(addressList[2])));
0113                 addressObjects << address;
0114             }
0115         }
0116         // convert routes into objects
0117         const UIntListList routes = iface.routes();
0118         for (const UIntList &routeList : routes) {
0119             if (routeList.count() == 4) {
0120                 NetworkManager::IpRoute route;
0121                 route.setIp(QHostAddress(ntohl(routeList[0])));
0122                 route.setPrefixLength(routeList[1]);
0123                 route.setNextHop(QHostAddress(ntohl(routeList[2])));
0124                 route.setMetric(ntohl(routeList[3]));
0125                 routeObjects << route;
0126             }
0127         }
0128     }
0129     // nameservers' IP addresses are always in network byte order
0130     QList<QHostAddress> nameservers;
0131     const QList<uint> ifaceNameservers = iface.nameservers();
0132     for (uint nameserver : ifaceNameservers) {
0133         nameservers << QHostAddress(ntohl(nameserver));
0134     }
0135 
0136     d->addresses = addressObjects;
0137     d->routes = routeObjects;
0138     d->nameservers = nameservers;
0139     d->gateway = iface.gateway();
0140     d->searches = iface.searches();
0141     d->domains = iface.domains();
0142     if (NetworkManager::checkVersion(1, 2, 0)) {
0143         d->dnsOptions = iface.dnsOptions();
0144     }
0145 }
0146 
0147 void NetworkManager::IpConfig::setIPv6Path(const QString &path)
0148 {
0149     // ask the daemon for the details
0150     OrgFreedesktopNetworkManagerIP6ConfigInterface iface(NetworkManagerPrivate::DBUS_SERVICE,
0151                                                          path,
0152 #ifdef NMQT_STATIC
0153                                                          QDBusConnection::sessionBus());
0154 #else
0155                                                          QDBusConnection::systemBus());
0156 #endif
0157     // TODO - watch propertiesChanged signal
0158 
0159     QList<NetworkManager::IpAddress> addressObjects;
0160     QList<NetworkManager::IpRoute> routeObjects;
0161     if (NetworkManager::checkVersion(1, 0, 0)) {
0162         const NMVariantMapList addresses = iface.addressData();
0163         for (const QVariantMap &addressList : addresses) {
0164             if (addressList.contains(QLatin1String("address")) //
0165                 && addressList.contains(QLatin1String("prefix"))) {
0166                 NetworkManager::IpAddress address;
0167                 address.setIp(QHostAddress(addressList.value(QLatin1String("address")).toString()));
0168                 address.setPrefixLength(addressList.value(QLatin1String("prefix")).toUInt());
0169                 if (addressList.contains(QLatin1String("gateway"))) {
0170                     address.setGateway(QHostAddress(addressList.value(QLatin1String("gateway")).toString()));
0171                 }
0172                 addressObjects << address;
0173             }
0174         }
0175 
0176         const NMVariantMapList routes = iface.routeData();
0177         for (const QVariantMap &routeList : routes) {
0178             if (routeList.contains(QLatin1String("address")) && routeList.contains(QLatin1String("prefix"))) {
0179                 NetworkManager::IpRoute route;
0180                 route.setIp(QHostAddress(routeList.value(QLatin1String("address")).toString()));
0181                 route.setPrefixLength(routeList.value(QLatin1String("prefix")).toUInt());
0182                 if (routeList.contains(QLatin1String("next-hop"))) {
0183                     route.setNextHop(QHostAddress(routeList.value(QLatin1String("next-hop")).toString()));
0184                 }
0185 
0186                 if (routeList.contains(QLatin1String("metric"))) {
0187                     route.setMetric(routeList.value(QLatin1String("metric")).toUInt());
0188                 }
0189                 routeObjects << route;
0190             }
0191         }
0192     } else {
0193         const IpV6DBusAddressList addresses = iface.addresses();
0194         for (const IpV6DBusAddress &address : addresses) {
0195             Q_IPV6ADDR addr;
0196             Q_IPV6ADDR gateway;
0197             for (int i = 0; i < 16; i++) {
0198                 addr[i] = address.address[i];
0199             }
0200             for (int i = 0; i < 16; i++) {
0201                 gateway[i] = address.gateway[i];
0202             }
0203             NetworkManager::IpAddress addressEntry;
0204             addressEntry.setIp(QHostAddress(addr));
0205             addressEntry.setPrefixLength(address.prefix);
0206             addressEntry.setGateway(QHostAddress(gateway));
0207             addressObjects << addressEntry;
0208         }
0209 
0210         const IpV6DBusRouteList routes = iface.routes();
0211         for (const IpV6DBusRoute &route : routes) {
0212             Q_IPV6ADDR dest;
0213             Q_IPV6ADDR nexthop;
0214             for (int i = 0; i < 16; i++) {
0215                 dest[i] = route.destination[i];
0216             }
0217             for (int i = 0; i < 16; i++) {
0218                 nexthop[i] = route.nexthop[i];
0219             }
0220             NetworkManager::IpRoute routeEntry;
0221             routeEntry.setIp(QHostAddress(dest));
0222             routeEntry.setPrefixLength(route.prefix);
0223             routeEntry.setNextHop(QHostAddress(nexthop));
0224             routeEntry.setMetric(route.metric);
0225             routeObjects << routeEntry;
0226         }
0227     }
0228 
0229     QList<QHostAddress> nameservers;
0230     const QList<QByteArray> ifaceNservers = iface.nameservers();
0231     for (const QByteArray &nameserver : ifaceNservers) {
0232         Q_IPV6ADDR address;
0233         for (int i = 0; i < 16; i++) {
0234             address[i] = static_cast<quint8>(nameserver[i]);
0235         }
0236         nameservers << QHostAddress(address);
0237     }
0238 
0239     d->addresses = addressObjects;
0240     d->routes = routeObjects;
0241     d->nameservers = nameservers;
0242     d->gateway = iface.gateway();
0243     d->searches = iface.searches();
0244     d->domains = iface.domains();
0245     if (NetworkManager::checkVersion(1, 2, 0)) {
0246         d->dnsOptions = iface.dnsOptions();
0247     }
0248 }
0249 
0250 NetworkManager::IpConfig::~IpConfig()
0251 {
0252     delete d;
0253 }
0254 
0255 NetworkManager::IpAddresses NetworkManager::IpConfig::addresses() const
0256 {
0257     return d->addresses;
0258 }
0259 
0260 QString NetworkManager::IpConfig::gateway() const
0261 {
0262     return d->gateway;
0263 }
0264 
0265 QList<QHostAddress> NetworkManager::IpConfig::nameservers() const
0266 {
0267     return d->nameservers;
0268 }
0269 
0270 QStringList NetworkManager::IpConfig::domains() const
0271 {
0272     return d->domains;
0273 }
0274 
0275 QList<NetworkManager::IpRoute> NetworkManager::IpConfig::routes() const
0276 {
0277     return d->routes;
0278 }
0279 
0280 QStringList NetworkManager::IpConfig::searches() const
0281 {
0282     return d->searches;
0283 }
0284 
0285 QStringList NetworkManager::IpConfig::dnsOptions() const
0286 {
0287     return d->dnsOptions;
0288 }
0289 
0290 NetworkManager::IpConfig &NetworkManager::IpConfig::operator=(const IpConfig &other)
0291 {
0292     if (this == &other) {
0293         return *this;
0294     }
0295 
0296     *d = *other.d;
0297     return *this;
0298 }
0299 
0300 bool NetworkManager::IpConfig::isValid() const
0301 {
0302     return !d->addresses.isEmpty();
0303 }