diff --git a/TODO b/TODO index 412238a..424dfc6 100644 --- a/TODO +++ b/TODO @@ -8,6 +8,8 @@ For 3.2: of a LAN) - enhance RFB with SASL authentication (Kerberos) - encrypted connections (using SASL and/or SSL/TLS) +- with kerberos/ssl: display name of remote user in connection dialog, + kpassivepopup and systray (if name is available) - try to solve the non-atomic KConfig changes problem - mention that invitations are one-time on personal invitation dialog diff --git a/configure.in.in b/configure.in.in index a2353a1..5e0353d 100644 --- a/configure.in.in +++ b/configure.in.in @@ -2,3 +2,19 @@ KDE_CHECK_HEADER(X11/extensions/XTest.h, [], AC_MSG_ERROR([XTest extension header not found / no xlib headers])) +#check for getifaddrs(3) (as in glibc >= 2.3 and newer bsds) +AC_MSG_CHECKING(for getifaddrs support) +AC_TRY_LINK( [ + #include + #include + ],[ + getifaddrs(0); + ],[ + AC_DEFINE(HAVE_GETIFADDRS,1,[Define if getifaddrs is available]) + COMPILE_GETIFADDRS="getifaddrs.cpp" + AC_MSG_RESULT(yes) + ],[ + AC_MSG_RESULT(no) + COMPILE_GETIFADDRS="" +]) +AC_SUBST(COMPILE_GETIFADDRS) diff --git a/kinetd/kinetd.cpp b/kinetd/kinetd.cpp index 264069c..967305a 100644 --- a/kinetd/kinetd.cpp +++ b/kinetd/kinetd.cpp @@ -18,7 +18,7 @@ #include "kinetd.h" #include "kinetd.moc" -#include "kinetaddr.h" +#include "kinetinterface.h" #include "kuser.h" #include "uuid.h" #include @@ -210,10 +210,10 @@ int PortListener::port() { QStringList PortListener::processServiceTemplate(const QString &a) { QStringList l; - QValueVector v = KInetAddress::getAllAddresses(); - QValueVector::Iterator it = v.begin(); + QValueVector v = KInetInterface::getAllInterfaces(false); + QValueVector::Iterator it = v.begin(); while (it != v.end()) { - QString hostName = (*(it++)).nodeName(); + QString hostName = (*(it++)).address()->nodeName(); KUser u; QString x = a; // replace does not work in const QString. Why?? l.append(x.replace(QRegExp("%h"), KServiceRegistry::encodeAttributeValue(hostName)) diff --git a/krfb/configuration.cc b/krfb/configuration.cc index 62e777e..321bedd 100644 --- a/krfb/configuration.cc +++ b/krfb/configuration.cc @@ -16,13 +16,14 @@ ***************************************************************************/ #include "configuration.h" -#include "kinetaddr.h" +#include "kinetinterface.h" #include #include #include #include #include +#include #include #include @@ -232,8 +233,14 @@ void Configuration::refreshTimeout() { QString Configuration::hostname() const { - KInetAddress a = KInetAddress::getPublicInetAddress(); - QString hostName = a.nodeName(); + KInetSocketAddress *a = KInetInterface::getPublicInetAddress(); + QString hostName; + if (a) { + hostName = a->nodeName(); + delete a; + } + else + hostName = "localhost"; return hostName; } diff --git a/srvloc/Makefile.am b/srvloc/Makefile.am index 4977897..1db43db 100644 --- a/srvloc/Makefile.am +++ b/srvloc/Makefile.am @@ -3,11 +3,14 @@ METASOURCES = AUTO # Code noinst_LTLIBRARIES = libsrvloc.la -libsrvloc_la_SOURCES = kinetaddr.cpp kinetaddr_ipfinder.cpp \ - kserviceregistry.cpp kuser.cpp uuid.cpp +libsrvloc_la_SOURCES = kserviceregistry.cpp kuser.cpp uuid.cpp \ + kinetinterface.cpp kinetinterfacewatcher.cpp \ + getifaddrs.cpp + libsrvloc_la_LIBADD = $(LIB_QT) $(LIB_KDECORE) $(LIB_SLP) libsrvloc_la_LDFLAGS = $(all_libraries) -no-undefined -noinst_HEADERS = kinetaddr.h kserviceregistry.h kuser.h uuid.h +noinst_HEADERS = kserviceregistry.h kuser.h uuid.h \ + getifaddrs.h kinetinterface.h kinetinterfacewatcher.h # set the include path for X, qt and KDE INCLUDES= $(all_includes) diff --git a/srvloc/getifaddrs.cpp b/srvloc/getifaddrs.cpp new file mode 100644 index 0000000..c8ac955 --- /dev/null +++ b/srvloc/getifaddrs.cpp @@ -0,0 +1,255 @@ +/* getifaddrs -- get names and addresses of all network interfaces + Copyright (C) 1999,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/** + * 02-12-26, tim@tjansen.de: put in kde_ namespace, C++ fixes, + * included ifreq.h + * removed glibc dependencies + */ + +#ifndef HAVE_GETIFADDRS + +#include "getifaddrs.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef SIOCGIFCONF + +#define old_siocgifconf 0 + +static inline void +__ifreq (struct ifreq **ifreqs, int *num_ifs, int sockfd) +{ + int fd = sockfd; + struct ifconf ifc; + int rq_len; + int nifs; +# define RQ_IFS 4 + + if (fd < 0) + fd = socket (AF_INET, SOCK_DGRAM, 0); + if (fd < 0) + { + *num_ifs = 0; + *ifreqs = NULL; + return; + } + + ifc.ifc_buf = NULL; + + /* We may be able to get the needed buffer size directly, rather than + guessing. */ + if (! old_siocgifconf) + { + ifc.ifc_buf = NULL; + ifc.ifc_len = 0; + if (ioctl (fd, SIOCGIFCONF, &ifc) < 0 || ifc.ifc_len == 0) + { + rq_len = RQ_IFS * sizeof (struct ifreq); + } + else + rq_len = ifc.ifc_len; + } + else + rq_len = RQ_IFS * sizeof (struct ifreq); + + /* Read all the interfaces out of the kernel. */ + while (1) + { + ifc.ifc_len = rq_len; + ifc.ifc_buf = (char*) realloc (ifc.ifc_buf, ifc.ifc_len); + if (ifc.ifc_buf == NULL || ioctl (fd, SIOCGIFCONF, &ifc) < 0) + { + if (ifc.ifc_buf) + free (ifc.ifc_buf); + + if (fd != sockfd) + close (fd); + + *num_ifs = 0; + *ifreqs = NULL; + return; + } + + if (!old_siocgifconf || ifc.ifc_len < rq_len) + break; + + rq_len *= 2; + } + + nifs = ifc.ifc_len / sizeof (struct ifreq); + + if (fd != sockfd) + close (fd); + + *num_ifs = nifs; + *ifreqs = (ifreq*)realloc (ifc.ifc_buf, nifs * sizeof (struct ifreq)); +} + +static inline struct ifreq * +__if_nextreq (struct ifreq *ifr) +{ + return ifr + 1; +} + +static inline void +__if_freereq (struct ifreq *ifreqs, int num_ifs) +{ + free (ifreqs); +} + +/* Create a linked list of `struct kde_ifaddrs' structures, one for each + network interface on the host machine. If successful, store the + list in *IFAP and return 0. On errors, return -1 and set `errno'. */ +int +kde_getifaddrs (struct kde_ifaddrs **ifap) +{ + /* This implementation handles only IPv4 interfaces. + The various ioctls below will only work on an AF_INET socket. + Some different mechanism entirely must be used for IPv6. */ + int fd = socket (AF_INET, SOCK_DGRAM, 0); + struct ifreq *ifreqs; + int nifs; + + if (fd < 0) + return -1; + + __ifreq (&ifreqs, &nifs, fd); + if (ifreqs == NULL) /* XXX doesn't distinguish error vs none */ + { + close (fd); + return -1; + } + + /* Now we have the list of interfaces and each one's address. + Put it into the expected format and fill in the remaining details. */ + if (nifs == 0) + *ifap = NULL; + else + { + struct Storage + { + struct kde_ifaddrs ia; + struct sockaddr addr, netmask, broadaddr; + char name[IF_NAMESIZE]; + } *storage; + struct ifreq *ifr; + int i; + + storage = (Storage*) malloc (nifs * sizeof storage[0]); + if (storage == NULL) + { + close (fd); + __if_freereq (ifreqs, nifs); + return -1; + } + + i = 0; + ifr = ifreqs; + do + { + /* Fill in all pointers to the storage we've already allocated. */ + storage[i].ia.ifa_next = &storage[i + 1].ia; + storage[i].ia.ifa_addr = &storage[i].addr; + storage[i].ia.ifa_netmask = &storage[i].netmask; + storage[i].ia.ifa_broadaddr = &storage[i].broadaddr; /* & dstaddr */ + + /* Now copy the information we already have from SIOCGIFCONF. */ + storage[i].ia.ifa_name = strncpy (storage[i].name, ifr->ifr_name, + sizeof storage[i].name); + storage[i].addr = ifr->ifr_addr; + + /* The SIOCGIFCONF call filled in only the name and address. + Now we must also ask for the other information we need. */ + + if (ioctl (fd, SIOCGIFFLAGS, ifr) < 0) + break; + storage[i].ia.ifa_flags = ifr->ifr_flags; + + ifr->ifr_addr = storage[i].addr; + + if (ioctl (fd, SIOCGIFNETMASK, ifr) < 0) + break; + storage[i].netmask = ifr->ifr_netmask; + + if (ifr->ifr_flags & IFF_BROADCAST) + { + ifr->ifr_addr = storage[i].addr; + if (ioctl (fd, SIOCGIFBRDADDR, ifr) < 0) + break; + storage[i].broadaddr = ifr->ifr_broadaddr; + } + else if (ifr->ifr_flags & IFF_POINTOPOINT) + { + ifr->ifr_addr = storage[i].addr; + if (ioctl (fd, SIOCGIFDSTADDR, ifr) < 0) + break; + storage[i].broadaddr = ifr->ifr_dstaddr; + } + else + /* Just 'cause. */ + memset (&storage[i].broadaddr, 0, sizeof storage[i].broadaddr); + + storage[i].ia.ifa_data = NULL; /* Nothing here for now. */ + + ifr = __if_nextreq (ifr); + } while (++i < nifs); + if (i < nifs) /* Broke out early on error. */ + { + close (fd); + free (storage); + __if_freereq (ifreqs, nifs); + return -1; + } + + storage[i - 1].ia.ifa_next = NULL; + + *ifap = &storage[0].ia; + + close (fd); + __if_freereq (ifreqs, nifs); + } + + return 0; +} + +void +kde_freeifaddrs (struct kde_ifaddrs *ifa) +{ + free (ifa); +} + +#else +int kde_getifaddrs(struct kde_ifaddrs **) { + return 1; +} +void kde_freeifaddrs(struct kde_ifaddrs *) { +} +struct { } kde_ifaddrs; + +#endif + +#endif diff --git a/srvloc/getifaddrs.h b/srvloc/getifaddrs.h new file mode 100644 index 0000000..f0de618 --- /dev/null +++ b/srvloc/getifaddrs.h @@ -0,0 +1,90 @@ +/* ifaddrs.h -- declarations for getting network interface addresses + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/** + * 02-12-26, tim@tjansen.de: added kde_ prefix, fallback-code, + * removed glibs dependencies + */ + + #include + +#ifdef HAVE_GETIFADDRS + #include + #include + +#define kde_getifaddrs(a) getifaddrs(a) +#define kde_freeifaddrs(a) freeifaddrs(a) +#define kde_ifaddrs ifaddrs + +#else + +#ifndef _GETIFADDRS_H +#define _GETIFADDRS_H + + +#include + +/* The `getifaddrs' function generates a linked list of these structures. + Each element of the list describes one network interface. */ +struct kde_ifaddrs +{ + struct kde_ifaddrs *ifa_next; /* Pointer to the next structure. */ + + char *ifa_name; /* Name of this network interface. */ + unsigned int ifa_flags; /* Flags as from SIOCGIFFLAGS ioctl. */ + + struct sockaddr *ifa_addr; /* Network address of this interface. */ + struct sockaddr *ifa_netmask; /* Netmask of this interface. */ + union + { + /* At most one of the following two is valid. If the IFF_BROADCAST + bit is set in `ifa_flags', then `ifa_broadaddr' is valid. If the + IFF_POINTOPOINT bit is set, then `ifa_dstaddr' is valid. + It is never the case that both these bits are set at once. */ + struct sockaddr *ifu_broadaddr; /* Broadcast address of this interface. */ + struct sockaddr *ifu_dstaddr; /* Point-to-point destination address. */ + } ifa_ifu; + /* These very same macros are defined by for `struct ifaddr'. + So if they are defined already, the existing definitions will be fine. */ +# ifndef ifa_broadaddr +# define ifa_broadaddr ifa_ifu.ifu_broadaddr +# endif +# ifndef ifa_dstaddr +# define ifa_dstaddr ifa_ifu.ifu_dstaddr +# endif + + void *ifa_data; /* Address-specific data (may be unused). */ +}; + + +/* Create a linked list of `struct kde_ifaddrs' structures, one for each + network interface on the host machine. If successful, store the + list in *IFAP and return 0. On errors, return -1 and set `errno'. + + The storage returned in *IFAP is allocated dynamically and can + only be properly freed by passing it to `freeifaddrs'. */ +extern int kde_getifaddrs (struct kde_ifaddrs **__ifap); + +/* Reclaim the storage allocated by a previous `getifaddrs' call. */ +extern void kde_freeifaddrs (struct kde_ifaddrs *__ifa); + +#endif + +#endif + diff --git a/srvloc/kinetaddr.cpp b/srvloc/kinetaddr.cpp deleted file mode 100644 index 3e8376f..0000000 --- a/srvloc/kinetaddr.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Represents an IP address. - * Copyright (C) 2002 Tim Jansen - * based on code from KInetSocketAddress: - * Copyright (C) 2000,2001 Thiago Macieira - * - * $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 "kinetaddr.h" -#include - -#include -#include - -#include -#include -#include - -#if defined(__osf__) && defined(AF_INET6) -#undef AF_INET6 -#endif - -#define V6_CAN_CONVERT_TO_V4(addr) (KDE_IN6_IS_ADDR_V4MAPPED(addr) || KDE_IN6_IS_ADDR_V4COMPAT(addr)) - -// This is how it is -// 46 == strlen("1234:5678:9abc:def0:1234:5678:255.255.255.255") -#ifndef INET6_ADDRSTRLEN -#define INET6_ADDRSTRLEN 46 -#endif - -class KInetAddressPrivate -{ -public: - int sockfamily; - struct in_addr in; -#ifdef AF_INET6 - struct in6_addr in6; -#endif - - KInetAddressPrivate() : sockfamily(AF_UNSPEC) - { - memset((void*)&in, 0, sizeof(in)); -#ifdef AF_INET6 - memset((void*)&in6, 0, sizeof(in6)); -#endif - } - -}; - -/** - * Functions defined in kinetaddr_ipfinder.cpp: - */ -QMap kinetaddr_getAllInterfaces(bool includeLoopback); - - - - -KInetAddress::KInetAddress() : - d(new KInetAddressPrivate) -{ -} - -KInetAddress::KInetAddress(const KInetAddress &other) : - d(new KInetAddressPrivate) -{ - d->sockfamily = other.d->sockfamily; - memcpy(&d->in, &other.d->in, sizeof(d->in)); -#ifdef AF_INET6 - memcpy(&d->in6, &other.d->in6, sizeof(d->in6)); -#endif -} - -KInetAddress::KInetAddress(const struct in_addr& in) : - d(new KInetAddressPrivate) -{ - d->sockfamily = AF_INET; - memcpy(&d->in, &in, sizeof(in)); -} - -KInetAddress::KInetAddress(const struct in6_addr& in6) : - d(new KInetAddressPrivate) -{ -#ifdef AF_INET6 - d->sockfamily = AF_INET6; - memcpy(&d->in6, &in6, sizeof(in6)); -#else - d->sockfamily = AF_UNSPEC; -#endif -} - -KInetAddress::KInetAddress(const QString &host) : - d(new KInetAddressPrivate) -{ - struct hostent *h = gethostbyname(host.latin1()); - if ((!h) || (!h->h_addr_list) || (!h->h_addr_list[0])) { - d->sockfamily = AF_UNSPEC; - return; - } - d->sockfamily = h->h_addrtype; -#ifdef AF_INET6 - if (h->h_addrtype == AF_INET6) - memcpy(&d->in6, h->h_addr_list[0], h->h_length); - else - memcpy(&d->in, h->h_addr_list[0], h->h_length); -#else - memcpy(&d->in, h->h_addr_list[0], h->h_length); -#endif - - -} - -KInetAddress& KInetAddress::operator =(const KInetAddress& a) { - d->sockfamily = a.d->sockfamily; - memcpy(&d->in, &a.d->in, sizeof(d->in)); -#ifdef AF_INET6 - memcpy(&d->in6, &a.d->in6, sizeof(d->in6)); -#endif - return *this; -} - -KInetAddress::~KInetAddress() -{ - delete d; -} - -const struct in_addr *KInetAddress::addressV4() const { - if (d->sockfamily != AF_INET) - return 0; - return &d->in; -} - -#ifdef AF_INET6 -const struct in6_addr *KInetAddress::addressV6() const { - if (d->sockfamily != AF_INET6) - return 0; - return &d->in6; -} -#endif - -QString KInetAddress::nodeName() const -{ - char buf[INET6_ADDRSTRLEN+1]; // INET6_ADDRSTRLEN > INET_ADDRSTRLEN - -#ifdef __osf__ - if (d->sockfamily == AF_INET) { - char *p = inet_ntoa(d->in); - strncpy(buf, p, sizeof(buf)); - } -#else - if (d->sockfamily == AF_INET) - inet_ntop(d->sockfamily, (void*)&d->in, buf, sizeof(buf)); -#endif -#ifdef AF_INET6 - else if (d->sockfamily == AF_INET6) - inet_ntop(d->sockfamily, (void*)&d->in6, buf, sizeof(buf)); -#endif - else { - kdWarning() << "KInetAddress::nodeName() called on uninitialized class\n"; - return QString::null; - } - - return QString::fromLatin1(buf); // FIXME! What's the encoding? -} - -bool KInetAddress::areEqual(const KInetAddress &a1, const KInetAddress &a2) -{ - if (a1.d->sockfamily != a2.d->sockfamily) - return false; - - if (a1.d->sockfamily == AF_INET) { - return (memcmp(&a1.d->in.s_addr, &a2.d->in.s_addr, - sizeof(a1.d->in.s_addr)) == 0); - } -#ifdef AF_INET6 - if (a1.d->sockfamily == AF_INET6) { - return (memcmp(&a1.d->in6.s6_addr, &a2.d->in6.s6_addr, - sizeof(a1.d->in6.s6_addr)) == 0); - } -#endif - return true; -} - -KInetAddress KInetAddress::getPublicInetAddress() { - KInetAddress kia("localhost"); - QMap list = getAllInterfaces(false); - QMap::iterator it = list.begin(); - while (it != list.end()) { - QString ifc = it.key(); - kia = it.data(); - if (ifc.startsWith("ppp")) - return kia; - if (ifc.startsWith("ippp")) - return kia; - it++; - } - return kia; -} - -QValueVector KInetAddress::getAllAddresses(bool includeLoopback) { - QValueVector list; - QMap map = getAllInterfaces(includeLoopback); - QMap::iterator it = map.begin(); - while (it != map.end()) { - list.push_back(it.data()); - it++; - } - return list; -} - -QMap KInetAddress::getAllInterfaces(bool includeLoopback) { - QMap map; - QMap l = kinetaddr_getAllInterfaces(includeLoopback); - QMap::iterator it = l.begin(); - while (it != l.end()) { - map[it.key()] = KInetAddress(it.data()); - it++; - } - return map; -} - diff --git a/srvloc/kinetaddr.h b/srvloc/kinetaddr.h deleted file mode 100644 index 703d6e4..0000000 --- a/srvloc/kinetaddr.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Represents an IP address. - * Copyright (C) 2002 Tim Jansen - * based on code from KInetSocketAddress: - * Copyright (C) 2000,2001 Thiago Macieira - * - * $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. - */ -#ifndef KINETADDR_H -#define KINETADDR_H - -#include -#include - -#include - -#if defined(__FreeBSD__) -#include -#endif - -#include -#include -#include -#include -#include - - -class KInetAddressPrivate; - - -/** - * An Inet (IPv4 or IPv6) address. - * - * This class represents an internet (IPv4 or IPv6) address. The difference - * between @ref KInetAddress and @ref KInetSocketAddress is that the socket - * address consists of the address and the port, KInetAddress represents - * only the address itself. - * - * @author Tim Jansen - * @short Represents an Internet Address - * @since 3.2 - */ -class KInetAddress { -public: - /** - * Default constructor. Creates an uninitialized KInetAddress. - */ - KInetAddress(); - - /** - * Copy constructor - * @param a the KInetAddress to copy - */ - KInetAddress(const KInetAddress &a); - - /** - * Creates an IPv4 socket from in_addr - * @param in a in_addr structure to copy from - * @param len the socket address length - */ - KInetAddress(const struct in_addr& in); - - /** - * Creates an IPv6 socket from in6_addr - * @param in6 a in_addr6 structure to copy from - * @param len the socket address length - */ - KInetAddress(const struct in6_addr& in6); - - /** - * Creates a socket from text representation. Be careful with names - * as they may require a name server lookup which can block for a - * long time. - * - * @param addr a text representation of the address - */ - KInetAddress(const QString& addr); - - /** - * Destructor - */ - virtual ~KInetAddress(); - - /** - * Assignment, makes a deep copy of @p a. - * @param a the KInetAddress to copy - * @return this KInetAddress - */ - KInetAddress& operator =(const KInetAddress& a); - - /** - * Returns a text representation of the host address. - * @return a text representation of the host address, or - * QString::null if created using the default - * constructor - */ - virtual QString nodeName() const; - - /** - * Checks whether this KInetAddress equals the @p other. - * @param other the other KInetAddress to compare - * @return true if both addresses equal - * @see areEqual() - */ - bool isEqual(const KInetAddress* other) const - { return areEqual(*this, *other); } - - /** - * Checks whether this KInetAddress equals the @p other. - * @param other the other KInetAddress to compare - * @return true if both addresses equal - * @see areEqual() - */ - bool operator==(const KInetAddress& other) const - { return areEqual(*this, other); } - - /** - * Checks whether the given KInetAddresses are equal. - * @param a1 the first KInetAddress to compare - * @param a2 the second KInetAddress to compare - * @return true if both addresses equal - * @see isEqual() - */ - static bool areEqual(const KInetAddress &a1, const KInetAddress &a2); - - /** - * Returns the in_addr structure. - * @return the in_addr structure, or 0 if this is not a v4 address. - * The pointer is valid as long as the KInetAddress object lives. - * @see addressV6 - */ - const struct in_addr* addressV4() const; - - /** - * Returns the in6_addr structure. - * @return the in_addr structure, or 0 if this is not a v6 address. - * The pointer is valid as long as the KInetAddress object lives. - * @see addressV4 - */ - const struct in6_addr* addressV6() const; - - operator const struct in_addr*() const - { return addressV4(); } - - operator const struct in6_addr*() const - { return addressV6(); } - - /** - * Tries to guess the public internet address of this computer. - * This is not always successful, especially when the computer - * is behind a firewall or NAT gateway. In the worst case, it - * returns localhost. - * @return a KInetAddress object that contains the best match - */ - static KInetAddress getPublicInetAddress(); - - /** - * Returns all active IP addresses that can be used to reach this - * system. - * @param includeLoopback if true, include the loopback interface's - * name - * @return the list of IP addresses - */ - static QValueVector getAllAddresses(bool includeLoopback = false); - - /** - * Returns all active interfaces as name/IP address pairs. - * @param includeLoopback if true, include the loopback interface's - * name - * @return the map of interfaces. The QString contains the name (like 'eth0' - * or 'ppp1'), KInetAddress the address - */ - static QMap getAllInterfaces(bool includeLoopback = false); - - -private: - KInetAddressPrivate* d; -}; - -#endif diff --git a/srvloc/kinetinterface.cpp b/srvloc/kinetinterface.cpp new file mode 100644 index 0000000..50d4092 --- /dev/null +++ b/srvloc/kinetinterface.cpp @@ -0,0 +1,253 @@ +/* + * 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; + address = new KInetSocketAddress(*i.address); + netmask = new KInetSocketAddress(*i.netmask); + broadcast = new KInetSocketAddress(*i.broadcast); + destination = new KInetSocketAddress(*i.destination); + 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::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()) + 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()) + 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->sa_family == AF_INET) + return new KInetSocketAddress((struct sockaddr_in*) a, + sizeof(struct sockaddr_in)); + else if (a->sa_family == AF_INET6) + return new KInetSocketAddress((struct sockaddr_in6*) a, + sizeof(struct sockaddr_in6)); + 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), + createAddress(a->ifa_broadaddr), + createAddress(a->ifa_dstaddr))); + a = a->ifa_next; + } + + kde_freeifaddrs(ads); + return r; +} + diff --git a/srvloc/kinetinterface.h b/srvloc/kinetinterface.h new file mode 100644 index 0000000..87ad350 --- /dev/null +++ b/srvloc/kinetinterface.h @@ -0,0 +1,175 @@ +/* + * 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. + */ +#ifndef KINETINTERFACE_H +#define KINETINTERFACE_H + +#include +#include +#include + + +class KInetInterfacePrivate; +class KInetSocketAddress; + +/** + * An Internet (IPv4 or IPv6) network interface. + * + * Represents a snapshot of the network interface's state. It is + * not possible to modify the interface using this class, only + * to read it. Note that the interfaces can change it any time + * (for example when the internet connection goes up or down), + * so when you use it in a server you may want to use it together + * with a @ref KInetInterfaceWatcher. + * Use @ref getAllInterfaces() to get all interfaces of a system. + * + * @author Tim Jansen + * @short Represents an IPv4 or IPv6 Network Interface + * @see KInetInterfaceWatcher + * @since 3.2 + */ +class KInetInterface { +private: + KInetInterface(const QString &name, + int flags, + KInetSocketAddress *address, + KInetSocketAddress *netmask, + KInetSocketAddress *broadcast, + KInetSocketAddress *destination); + +public: + /** + * Default constructor. Creates an uninitialized KInetInterface. + * @see isValid() + */ + KInetInterface(); + + /** + * Copy constructor. Makes a deep copy. + * @param i the KInetInterface to copy + */ + KInetInterface(const KInetInterface &i); + + /** + * Destructor + */ + virtual ~KInetInterface(); + + /** + * Assignment, makes a deep copy of @p i. + * @param i the KInetInterface to copy + * @return this KInetInterface + */ + KInetInterface& operator =(const KInetInterface& i); + + /** + * Checks whether the object is valid. Only interfaces that + * have been created using the default constructor are invalid. + * @return true if valid, false if invalid + */ + bool isValid() const; + + /** + * Returns the name of the interface, e.g. 'eth0'. + * @return the name of the interface + */ + QString name() const; + + /** + * Flags describing the interface. These flags + * can be ORed. + */ + enum Flags { + Up = 1, ///< Interface is up. + Broadcast = 2, ///< Broadcast address (@ref broadcastAddress()) is valid.. + Loopback = 8, ///< Interface is a loopback interface. + PointToPoint = 16, ///< Interface is a point-to-point interface. + Running = 128, ///< Interface is running. + Multicast = 65536 ///< Interface is multicast-capable. + }; + + /** + * A set of ORed flags describing the interface. See + * @ref Flags for description of the flags. + * @return the ORed @ref Flags of the interface + */ + int flags() const; + + /** + * Returns the address of the interface. + * The returned object is valid as long as this object + * exists. + * @return the address of this interface + */ + KInetSocketAddress *address() const; + + /** + * Returns the netmask of the interface. + * The returned object is valid as long as this object + * exists. + * @return the netmask of this interface + */ + KInetSocketAddress *netmask() const; + + /** + * Returns the broadcast address of the interface. + * The returned object is valid as long as this object + * exists. + * @return the broadcast address of this interface. Can be 0 if + * the interface is a peer-to-peer interface (like PPP) + */ + KInetSocketAddress *broadcastAddress() const; + + /** + * Returns the destination / peer address of the interface. + * It is used for peer-to-peer interfaces like PPP. + * The returned object is valid as long as this object + * exists. + * @return the destination address of this interface. Can be 0 + * if the interface is not a peer-to-peer interface + */ + KInetSocketAddress *destinationAddress() const; + + /** + * Tries to guess the public internet address of this computer. + * This is not always successful, especially when the computer + * is behind a firewall or NAT gateway. In the worst case, it + * returns localhost. + * @return a KInetAddress object that contains the best match. + * The caller takes ownership of the object and is + * responsible for freeing it + */ + static KInetSocketAddress *getPublicInetAddress(); + + /** + * Returns all active interfaces of the system. + * + * @param includeLoopback if true, include the loopback interface's + * name + * @return the list of IP addresses + */ + static QValueVector getAllInterfaces(bool includeLoopback = false); + +private: + KInetInterfacePrivate* d; +}; + +#endif diff --git a/srvloc/kinetinterfacewatcher.cpp b/srvloc/kinetinterfacewatcher.cpp new file mode 100644 index 0000000..1841f8f --- /dev/null +++ b/srvloc/kinetinterfacewatcher.cpp @@ -0,0 +1,59 @@ +/* + * Watches Inet interfaces + * 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 "kinetinterfacewatcher.h" + + +class KInetInterfaceWatcherPrivate { +public: + QString interface; + int minInterval; // not used yet, but my be when a daemon watches + + + KInetInterfaceWatcherPrivate(const QString &iface, + int minIntv) : + interface(iface), + minInterval(minIntv) { + } +}; + +/* + * or all network interfaces. + * @param interface the name of the interface to watch (e.g.'eth0') + * or QString::null to watch all interfaces + * @param minInterval the minimum interval between two checks in + * seconds. Be careful not to check too often, to + * avoid unneccessary wasting of CPU time + */ +KInetInterfaceWatcher::KInetInterfaceWatcher(const QString &interface, + int minInterval) { + d = new KInetInterfaceWatcherPrivate(interface, minInterval); +} + +QString KInetInterfaceWatcher::interface() const { + return d->interface; +} + +KInetInterfaceWatcher::~KInetInterfaceWatcher() { + delete d; +} + diff --git a/srvloc/kinetinterfacewatcher.h b/srvloc/kinetinterfacewatcher.h new file mode 100644 index 0000000..ed4da87 --- /dev/null +++ b/srvloc/kinetinterfacewatcher.h @@ -0,0 +1,89 @@ +/* + * Watches Inet interfaces + * 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. + */ +#ifndef KINETINTERFACEWATCHER_H +#define KINETINTERFACEWATCHER_H + +#include +#include +#include +#include +#include + + +class KInetInterfaceWatcherPrivate; + + +/** + * KInetInterfaceWatcher can watch the state of one or all + * of the system's network interfaces. + * The watcher will emit the signal @ref changed() when an + * interface changed or a interface has been added or removed. + * + * @author Tim Jansen + * @short Watches the state of the network interfaces + * @see KInetInterface + * @since 3.2 + */ +class KInetInterfaceWatcher : public QObject { + Q_OBJECT +public: + /** + * Creates a new KInetInterfaceWatcher. It watches either one + * or all network interfaces. + * @param interface the name of the interface to watch (e.g.'eth0') + * or QString::null to watch all interfaces + * @param minInterval the minimum interval between two checks in + * seconds. Be careful not to check too often, to + * avoid unneccessary wasting of CPU time + */ + KInetInterfaceWatcher(const QString &interface = QString::null, + int minInterval = 60); + + /** + * Returns the name of the interface that is being watched. + * @return the name of the interface, or QString::null if all + * interfaces are watched + */ + QString interface() const; + + /** + * Destructor + */ + virtual ~KInetInterfaceWatcher(); + +signals: + /** + * Emitted when one or more watched interfaces have changed. The + * @p interfaceName is the name of the interface being watched, not + * the interface that has changed (because more than one interface + * may have changed). + * @param interfaceName the name of the interface that is watched, + * by the emitter, or QString::null if all + * interfaces are being watched + */ + void changed(QString interfaceName); + +private: + KInetInterfaceWatcherPrivate* d; +}; + +#endif