2 * Copyright (C) 2003 Thiago Macieira <thiago@kde.org>
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 #include "k3socketaddress.h"
28 #include <config-network.h>
30 #include <sys/types.h>
31 #include <sys/socket.h>
33 #include <arpa/inet.h>
34 #include <netinet/in.h>
48 using namespace KNetwork
;
51 class KIpAddress_localhostV4
: public KIpAddress
54 KIpAddress_localhostV4()
56 *m_data
= htonl(0x7f000001);
61 class KIpAddress_localhostV6
: public KIpAddress
64 KIpAddress_localhostV6()
72 static const char localhostV4_data
[] = { 127, 0, 0, 1 };
73 static const char localhostV6_data
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,1 };
75 const KIpAddress
KIpAddress::localhostV4(&localhostV4_data
, 4);
76 const KIpAddress
KIpAddress::localhostV6(&localhostV6_data
, 6);
77 const KIpAddress
KIpAddress::anyhostV4(0L, 4);
78 const KIpAddress
KIpAddress::anyhostV6(0L, 6);
80 // helper function to test if an IPv6 v4-mapped address is equal to its IPv4 counterpart
81 static bool check_v4mapped(const quint32
* v6addr
, quint32 v4addr
)
83 // check that the v6 is a v4-mapped address
84 if (!(v6addr
[0] == 0 && v6addr
[1] == 0 && v6addr
[2] == htonl(0x0000ffff)))
85 return false; // not a v4-mapped address
87 return v6addr
[3] == v4addr
;
91 KIpAddress
& KIpAddress::operator =(const KIpAddress
& other
)
93 m_version
= other
.m_version
;
94 if (m_version
== 4 || m_version
== 6)
95 memcpy(m_data
, other
.m_data
, sizeof(m_data
));
100 bool KIpAddress::compare(const KIpAddress
& other
, bool checkMapped
) const
102 if (m_version
== other
.m_version
)
106 // both objects are empty
111 return *m_data
== *other
.m_data
;
115 // they are 128-bit long, that is, 16 bytes
116 return memcmp(m_data
, other
.m_data
, 16) == 0;
121 // check the possibility of a v4-mapped address being compared to an IPv4 one
122 if (m_version
== 6 && other
.m_version
== 4 && check_v4mapped(m_data
, *other
.m_data
))
125 if (other
.m_version
== 6 && m_version
== 4 && check_v4mapped(other
.m_data
, *m_data
))
132 // sets the address to the given address
133 bool KIpAddress::setAddress(const QString
& address
)
137 // try to guess the address version
138 if (address
.indexOf(':') != -1)
144 if (inet_pton(AF_INET6
, address
.toLatin1(), buf
))
146 memcpy(m_data
, buf
, sizeof(m_data
));
157 if (inet_pton(AF_INET
, address
.toLatin1(), &buf
))
167 return false; // can never happen!
170 bool KIpAddress::setAddress(const char* address
)
172 return setAddress(QLatin1String(address
));
175 // set from binary data
176 bool KIpAddress::setAddress(const void* raw
, int version
)
178 // this always succeeds
179 // except if version is invalid
180 if (version
!= 4 && version
!= 6)
185 memcpy(m_data
, raw
, version
== 4 ? 4 : 16);
187 memset(m_data
, 0, 16);
193 QString
KIpAddress::toString() const
195 char buf
[sizeof "1111:2222:3333:4444:5555:6666:255.255.255.255" + 2];
200 inet_ntop(AF_INET
, (void*)m_data
, buf
, sizeof(buf
) - 1);
201 return QLatin1String(buf
);
205 inet_ntop(AF_INET6
, (void*)m_data
, buf
, sizeof(buf
) - 1);
207 return QLatin1String(buf
);
214 * An IPv6 socket address
215 * This is taken from RFC 2553.
217 struct our_sockaddr_in6
219 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
222 # else //!HAVE_STRUCT_SOCKADDR_SA_LEN
225 quint16 sin6_port
; /* RFC says in_port_t */
226 quint32 sin6_flowinfo
;
227 quint8 sin6_addr
[16]; // 24 bytes up to here
228 quint32 sin6_scope_id
; // 28 bytes total
231 // useful definitions
232 #define MIN_SOCKADDR_LEN sizeof(quint16)
233 #define SOCKADDR_IN_LEN sizeof(sockaddr_in)
234 #define MIN_SOCKADDR_IN6_LEN ((unsigned long) &(((our_sockaddr_in6*)0)->sin6_scope_id))
235 #define SOCKADDR_IN6_LEN sizeof(our_sockaddr_in6)
236 #define MIN_SOCKADDR_UN_LEN (sizeof(quint16) + sizeof(char))
239 class KNetwork::KSocketAddressData
243 * Note: maybe this should be virtual
244 * But since the data is shared via the d pointer, it doesn't really matter
245 * what one class sees, so will the other
247 class QMixSocketAddressRef
: public KInetSocketAddress
, public KUnixSocketAddress
250 QMixSocketAddressRef(KSocketAddressData
* d
)
251 : KInetSocketAddress(d
), KUnixSocketAddress(d
)
255 QMixSocketAddressRef ref
;
259 struct sockaddr
*generic
;
260 struct sockaddr_in
*in
;
261 struct our_sockaddr_in6
*in6
;
262 struct sockaddr_un
*un
;
264 quint16 curlen
, reallen
;
274 ~KSocketAddressData()
276 if (addr
.generic
!= 0L)
280 inline bool invalid() const
281 { return reallen
== 0; }
283 inline void invalidate()
286 void dup(const sockaddr
* sa
, quint16 len
, bool clear
= true);
292 switch (addr
.generic
->sa_family
)
295 return; // nothing to do here
298 oldport
= addr
.in6
->sin6_port
;
304 dup(0L, SOCKADDR_IN_LEN
);
306 addr
.in
->sin_family
= AF_INET
;
307 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
308 addr
.in
->sin_len
= SOCKADDR_IN_LEN
;
310 addr
.in
->sin_port
= oldport
;
317 switch (addr
.generic
->sa_family
)
320 oldport
= addr
.in
->sin_port
;
325 return; // nothing to do here
330 dup(0L, SOCKADDR_IN6_LEN
);
332 addr
.in6
->sin6_family
= AF_INET6
;
334 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
335 addr
.in6
->sin6_len
= SOCKADDR_IN6_LEN
;
337 addr
.in6
->sin6_port
= oldport
;
338 // sin6_scope_id and sin6_flowid are zero
343 // create duplicates of
344 void KSocketAddressData::dup(const sockaddr
* sa
, quint16 len
, bool clear
)
346 if (len
< MIN_SOCKADDR_LEN
)
353 if (sa
&& ((sa
->sa_family
== AF_INET
&& len
< SOCKADDR_IN_LEN
) ||
355 (sa
->sa_family
== AF_INET6
&& len
< MIN_SOCKADDR_IN6_LEN
) ||
357 (sa
->sa_family
== AF_UNIX
&& len
< MIN_SOCKADDR_UN_LEN
)))
369 curlen
= 32; // big enough for sockaddr_in and sockaddr_in6
372 addr
.generic
= (sockaddr
*)realloc(addr
.generic
, curlen
);
377 memcpy(addr
.generic
, sa
, len
); // copy
379 // now, normalise the data
380 if (addr
.generic
->sa_family
== AF_INET
)
381 reallen
= SOCKADDR_IN_LEN
; // no need to be larger
383 else if (addr
.generic
->sa_family
== AF_INET6
)
385 // set the extra field (sin6_scope_id)
387 // the buffer is never smaller than 32 bytes, so this is always
389 if (reallen
< SOCKADDR_IN6_LEN
)
390 addr
.in6
->sin6_scope_id
= 0;
392 reallen
= SOCKADDR_IN6_LEN
;
395 else if (addr
.generic
->sa_family
== AF_UNIX
)
396 reallen
= MIN_SOCKADDR_UN_LEN
+ strlen(addr
.un
->sun_path
);
400 memset(addr
.generic
, 0, len
);
401 addr
.generic
->sa_family
= AF_UNSPEC
;
405 // default constructor
406 KSocketAddress::KSocketAddress()
407 : d(new KSocketAddressData
)
411 // constructor from binary data
412 KSocketAddress::KSocketAddress(const sockaddr
*sa
, quint16 len
)
413 : d(new KSocketAddressData
)
418 KSocketAddress::KSocketAddress(const KSocketAddress
& other
)
419 : d(new(KSocketAddressData
))
424 KSocketAddress::KSocketAddress(KSocketAddressData
*d2
)
429 KSocketAddress::~KSocketAddress()
431 // prevent double-deletion, since we're already being deleted
434 d
->ref
.KInetSocketAddress::d
= 0L;
435 d
->ref
.KUnixSocketAddress::d
= 0L;
440 KSocketAddress
& KSocketAddress::operator =(const KSocketAddress
& other
)
442 if (other
.d
&& !other
.d
->invalid())
443 d
->dup(other
.d
->addr
.generic
, other
.d
->reallen
);
449 const sockaddr
* KSocketAddress::address() const
453 return d
->addr
.generic
;
456 sockaddr
* KSocketAddress::address()
460 return d
->addr
.generic
;
463 KSocketAddress
& KSocketAddress::setAddress(const sockaddr
* sa
, quint16 len
)
465 if (sa
!= 0L && len
>= MIN_SOCKADDR_LEN
)
473 quint16
KSocketAddress::length() const
480 KSocketAddress
& KSocketAddress::setLength(quint16 len
)
482 d
->dup((sockaddr
*)0L, len
, false);
487 int KSocketAddress::family() const
491 return d
->addr
.generic
->sa_family
;
494 KSocketAddress
& KSocketAddress::setFamily(int family
)
497 d
->dup((sockaddr
*)0L, MIN_SOCKADDR_LEN
);
498 d
->addr
.generic
->sa_family
= family
;
503 bool KSocketAddress::operator ==(const KSocketAddress
& other
) const
505 // if this is invalid, it's only equal if the other one is invalid as well
507 return other
.d
->invalid();
509 // check the family to make sure we don't do unnecessary comparison
510 if (d
->addr
.generic
->sa_family
!= other
.d
->addr
.generic
->sa_family
)
511 return false; // not the same family, not equal
514 // check the ones we know already
515 switch (d
->addr
.generic
->sa_family
)
518 Q_ASSERT(d
->reallen
== SOCKADDR_IN_LEN
);
519 Q_ASSERT(other
.d
->reallen
== SOCKADDR_IN_LEN
);
520 return memcmp(d
->addr
.in
, other
.d
->addr
.in
, SOCKADDR_IN_LEN
) == 0;
524 Q_ASSERT(d
->reallen
>= MIN_SOCKADDR_IN6_LEN
);
525 Q_ASSERT(other
.d
->reallen
>= MIN_SOCKADDR_IN6_LEN
);
527 # if !defined(HAVE_STRUCT_SOCKADDR_IN6) || defined(HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID)
528 // check for the case where sin6_scope_id isn't present
529 if (d
->reallen
!= other
.d
->reallen
)
531 if (memcmp(d
->addr
.in6
, other
.d
->addr
.in6
, MIN_SOCKADDR_IN6_LEN
) != 0)
532 return false; // not equal
533 if (d
->reallen
> other
.d
->reallen
)
534 return d
->addr
.in6
->sin6_scope_id
== 0;
536 return other
.d
->addr
.in6
->sin6_scope_id
== 0;
540 return memcmp(d
->addr
.in6
, other
.d
->addr
.in6
, d
->reallen
) == 0;
544 Q_ASSERT(d
->reallen
>= MIN_SOCKADDR_UN_LEN
);
545 Q_ASSERT(other
.d
->reallen
>= MIN_SOCKADDR_UN_LEN
);
547 // do a string comparison here
548 return strcmp(d
->addr
.un
->sun_path
, other
.d
->addr
.un
->sun_path
) == 0;
551 // something else we don't know about
552 // they are equal if and only if they are exactly equal
553 if (d
->reallen
== other
.d
->reallen
)
554 return memcmp(d
->addr
.generic
, other
.d
->addr
.generic
, d
->reallen
) == 0;
557 return false; // not equal in any other case
560 QString
KSocketAddress::nodeName() const
565 switch (d
->addr
.generic
->sa_family
)
571 QString
scopeid("%");
572 if (d
->addr
.generic
->sa_family
== AF_INET6
&& d
->addr
.in6
->sin6_scope_id
)
573 scopeid
+= QString::number(d
->addr
.in6
->sin6_scope_id
);
576 return d
->ref
.ipAddress().toString() + scopeid
;
578 return d
->ref
.ipAddress().toString();
582 // any other case, including AF_UNIX
586 QString
KSocketAddress::serviceName() const
591 switch (d
->addr
.generic
->sa_family
)
597 return QString::number(d
->ref
.port());
600 return d
->ref
.pathname();
606 QString
KSocketAddress::toString() const
613 if (d
->addr
.generic
->sa_family
== AF_INET
)
614 fmt
= QLatin1String("%1:%2");
616 else if (d
->addr
.generic
->sa_family
== AF_INET6
)
617 fmt
= QLatin1String("[%1]:%2");
619 else if (d
->addr
.generic
->sa_family
== AF_UNIX
)
620 return QString(QLatin1String("unix:%1")).arg(serviceName());
622 return i18nc("1: the unknown socket address family number",
623 "Unknown family %1", d
->addr
.generic
->sa_family
);
625 return fmt
.arg(nodeName()).arg(serviceName());
628 KInetSocketAddress
& KSocketAddress::asInet()
633 KInetSocketAddress
KSocketAddress::asInet() const
638 KUnixSocketAddress
& KSocketAddress::asUnix()
643 KUnixSocketAddress
KSocketAddress::asUnix() const
648 int KSocketAddress::ianaFamily(int af
)
665 int KSocketAddress::fromIanaFamily(int iana
)
682 // default constructor
683 KInetSocketAddress::KInetSocketAddress()
687 // binary data constructor
688 KInetSocketAddress::KInetSocketAddress(const sockaddr
* sa
, quint16 len
)
689 : KSocketAddress(sa
, len
)
695 // create from IP and port
696 KInetSocketAddress::KInetSocketAddress(const KIpAddress
& host
, quint16 port
)
703 KInetSocketAddress::KInetSocketAddress(const KInetSocketAddress
& other
)
704 : KSocketAddress(other
)
708 // special copy constructor
709 KInetSocketAddress::KInetSocketAddress(const KSocketAddress
& other
)
710 : KSocketAddress(other
)
716 // special constructor
717 KInetSocketAddress::KInetSocketAddress(KSocketAddressData
*d
)
723 KInetSocketAddress::~KInetSocketAddress()
729 KInetSocketAddress
& KInetSocketAddress::operator =(const KInetSocketAddress
& other
)
731 KSocketAddress::operator =(other
);
736 int KInetSocketAddress::ipVersion() const
741 switch (d
->addr
.generic
->sa_family
)
752 return 0; // for all other cases
755 KIpAddress
KInetSocketAddress::ipAddress() const
758 return KIpAddress(); // return an empty address as well
760 switch (d
->addr
.generic
->sa_family
)
763 return KIpAddress(&d
->addr
.in
->sin_addr
, 4);
766 return KIpAddress(&d
->addr
.in6
->sin6_addr
, 6);
770 return KIpAddress(); // empty in all other cases
773 KInetSocketAddress
& KInetSocketAddress::setHost(const KIpAddress
& ip
)
775 switch (ip
.version())
779 memcpy(&d
->addr
.in
->sin_addr
, ip
.addr(), sizeof(d
->addr
.in
->sin_addr
));
784 memcpy(&d
->addr
.in6
->sin6_addr
, ip
.addr(), sizeof(d
->addr
.in6
->sin6_addr
));
796 quint16
KInetSocketAddress::port() const
801 switch (d
->addr
.generic
->sa_family
)
804 return ntohs(d
->addr
.in
->sin_port
);
808 return ntohs(d
->addr
.in6
->sin6_port
);
815 KInetSocketAddress
& KInetSocketAddress::setPort(quint16 port
)
820 switch (d
->addr
.generic
->sa_family
)
823 d
->addr
.in
->sin_port
= htons(port
);
828 d
->addr
.in6
->sin6_port
= htons(port
);
833 d
->invalidate(); // setting the port on something else
839 KInetSocketAddress
& KInetSocketAddress::makeIPv4()
845 KInetSocketAddress
& KInetSocketAddress::makeIPv6()
851 quint32
KInetSocketAddress::flowinfo() const
857 if (!d
->invalid() && d
->addr
.in6
->sin6_family
== AF_INET6
)
858 return d
->addr
.in6
->sin6_flowinfo
;
863 KInetSocketAddress
& KInetSocketAddress::setFlowinfo(quint32 flowinfo
)
865 makeIPv6(); // must set here
866 d
->addr
.in6
->sin6_flowinfo
= flowinfo
;
870 int KInetSocketAddress::scopeId() const
876 if (!d
->invalid() && d
->addr
.in6
->sin6_family
== AF_INET6
)
877 return d
->addr
.in6
->sin6_scope_id
;
882 KInetSocketAddress
& KInetSocketAddress::setScopeId(int scopeid
)
884 makeIPv6(); // must set here
885 d
->addr
.in6
->sin6_scope_id
= scopeid
;
889 void KInetSocketAddress::update()
891 if (d
->addr
.generic
->sa_family
== AF_INET
)
894 else if (d
->addr
.generic
->sa_family
== AF_INET6
)
901 KUnixSocketAddress::KUnixSocketAddress()
905 KUnixSocketAddress::KUnixSocketAddress(const sockaddr
* sa
, quint16 len
)
906 : KSocketAddress(sa
, len
)
908 if (!d
->invalid() && d
->addr
.un
->sun_family
!= AF_UNIX
)
912 KUnixSocketAddress::KUnixSocketAddress(const KUnixSocketAddress
& other
)
913 : KSocketAddress(other
)
917 KUnixSocketAddress::KUnixSocketAddress(const QString
& pathname
)
919 setPathname(pathname
);
922 KUnixSocketAddress::KUnixSocketAddress(KSocketAddressData
* d
)
927 KUnixSocketAddress::~KUnixSocketAddress()
931 KUnixSocketAddress
& KUnixSocketAddress::operator =(const KUnixSocketAddress
& other
)
933 KSocketAddress::operator =(other
);
937 QString
KUnixSocketAddress::pathname() const
939 if (!d
->invalid() && d
->addr
.un
->sun_family
== AF_UNIX
)
940 return QFile::decodeName(d
->addr
.un
->sun_path
);
944 KUnixSocketAddress
& KUnixSocketAddress::setPathname(const QString
& path
)
946 d
->dup(0L, MIN_SOCKADDR_UN_LEN
+ path
.length());
947 d
->addr
.un
->sun_family
= AF_UNIX
;
948 strcpy(d
->addr
.un
->sun_path
, QFile::encodeName(path
));
950 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
951 d
->addr
.un
->sun_len
= d
->reallen
;