/* * Represents an Inet interface * Copyright (C) 2002 Tim Jansen * * $Id$ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include "kinetinterface.h" #include "getifaddrs.h" #include #include class KInetInterfacePrivate { public: QString name; int flags; KInetSocketAddress *address; KInetSocketAddress *netmask; KInetSocketAddress *broadcast; KInetSocketAddress *destination; KInetInterfacePrivate() : flags(0), address(0), netmask(0), broadcast(0), destination(0) { } KInetInterfacePrivate(const QString _name, int _flags, KInetSocketAddress *_address, KInetSocketAddress *_netmask, KInetSocketAddress *_broadcast, KInetSocketAddress *_destination) : name(_name), flags(_flags), address(_address), netmask(_netmask), broadcast(_broadcast), destination(_destination) { } ~KInetInterfacePrivate() { if (address) delete address; if (netmask) delete netmask; if (broadcast) delete broadcast; if (destination) delete destination; } KInetInterfacePrivate& operator =(const KInetInterfacePrivate& i) { name = i.name; flags = i.flags; if (i.address) address = new KInetSocketAddress(*i.address); else address = 0; if (i.netmask) netmask = new KInetSocketAddress(*i.netmask); else netmask = 0; if (i.broadcast) broadcast = new KInetSocketAddress(*i.broadcast); else broadcast = 0; if (i.destination) destination = new KInetSocketAddress(*i.destination); else destination = 0; return *this; } }; KInetInterface::KInetInterface() : d(0) { } KInetInterface::KInetInterface(const QString &_name, int _flags, KInetSocketAddress *_address, KInetSocketAddress *_netmask, KInetSocketAddress *_broadcast, KInetSocketAddress *_destination) { d = new KInetInterfacePrivate(_name, _flags, _address, _netmask, _broadcast, _destination); } KInetInterface::KInetInterface(const KInetInterface &i) : d(0) { if (!i.d) return; d = new KInetInterfacePrivate(); *d = *i.d; } KInetInterface::~KInetInterface() { if (d) delete d; } KInetInterface& KInetInterface::operator =(const KInetInterface& i) { if (this == &i) return *this; if (d) delete d; d = 0; if (!i.d) return *this; d = new KInetInterfacePrivate(); *d = *i.d; return *this; } bool KInetInterface::isValid() const { return d == 0; } QString KInetInterface::displayName() const { return d->name; } QString KInetInterface::name() const { return d->name; } int KInetInterface::flags() const { return d->flags; } KInetSocketAddress *KInetInterface::address() const { return d->address; } KInetSocketAddress *KInetInterface::netmask() const { return d->netmask; } KInetSocketAddress *KInetInterface::broadcastAddress() const { return d->broadcast; } KInetSocketAddress *KInetInterface::destinationAddress() const { return d->destination; } KInetSocketAddress *KInetInterface::getPublicInetAddress() { QValueVector v = getAllInterfaces(true); // TODO: first step: take the default route interface // try to find point-2-point interface, because it may be // a dial-up connection. Take it. QValueVector::const_iterator it = v.begin(); while (it != v.end()) { if (((*it).flags() & (PointToPoint | Up | Running)) && (!((*it).flags() & Loopback)) && (*it).address() && ((*it).address()->family() == AF_INET)) return new KInetSocketAddress(*(*it).address()); it++; } // otherwise, just take the first non-loopback interface it = v.begin(); while (it != v.end()) { if (((*it).flags() & (Up | Running)) && (!((*it).flags() & Loopback)) && (*it).address() && ((*it).address()->family() == AF_INET)) return new KInetSocketAddress(*(*it).address()); it++; } // ok, giving up, try to take loopback it = v.begin(); while (it != v.end()) { if (((*it).flags() & (Up | Running)) && (*it).address()) return new KInetSocketAddress(*(*it).address()); it++; } // not even loopback.. return 0; } namespace { KInetSocketAddress *createAddress(struct sockaddr *a) { if (!a) return 0; else if (a->sa_family == AF_INET) return new KInetSocketAddress((struct sockaddr_in*) a, sizeof(struct sockaddr_in)); #ifdef AF_INET6 else if (a->sa_family == AF_INET6) return new KInetSocketAddress((struct sockaddr_in6*) a, sizeof(struct sockaddr_in6)); #endif else return 0; } int convertFlags(int flags) { int r = 0; if (flags & IFF_UP) r |= KInetInterface::Up; if (flags & IFF_BROADCAST) r |= KInetInterface::Broadcast; if (flags & IFF_LOOPBACK) r |= KInetInterface::Loopback; if (flags & IFF_POINTOPOINT) r |= KInetInterface::PointToPoint; if (flags & IFF_RUNNING) r |= KInetInterface::Running; if (flags & IFF_MULTICAST) r |= KInetInterface::Multicast; return r; } } QValueVector KInetInterface::getAllInterfaces(bool includeLoopback) { struct kde_ifaddrs *ads; struct kde_ifaddrs *a; QValueVector r; if (kde_getifaddrs(&ads)) return r; a = ads; while (a) { if ((a->ifa_flags & IFF_LOOPBACK) && !includeLoopback) { a = a->ifa_next; continue; } r.push_back(KInetInterface(QString::fromUtf8(a->ifa_name), convertFlags(a->ifa_flags), createAddress(a->ifa_addr), createAddress(a->ifa_netmask), (a->ifa_flags & IFF_BROADCAST) ? createAddress(a->ifa_broadaddr) : 0, (a->ifa_flags & IFF_POINTOPOINT) ? createAddress(a->ifa_dstaddr) : 0)); a = a->ifa_next; } kde_freeifaddrs(ads); return r; }