1 /*  -*- C++ -*-
2  *  Copyright (C) 2003 Thiago Macieira <thiago@kde.org>
3  *
4  *
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:
12  *
13  *  The above copyright notice and this permission notice shall be included
14  *  in all copies or substantial portions of the Software.
15  *
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.
23  */
24 
25 #include "k3socketaddress.h"
26 
27 #include <config-network.h>
28 #include <config-kdelibs4support.h>
29 
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <sys/un.h>
33 #include <arpa/inet.h>
34 #include <netinet/in.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 
39 #include <QFile>
40 #include <QObject>
41 
42 #include "klocalizedstring.h"
43 
44 #ifndef Q_CC_MSVC
45 #include "netsupp.h"
46 #endif
47 
48 using namespace KNetwork;
49 
50 #if 0
51 class KIpAddress_localhostV4 : public KIpAddress
52 {
53 public:
54     KIpAddress_localhostV4()
55     {
56         *m_data = htonl(0x7f000001);
57         m_version = 4;
58     }
59 };
60 
61 class KIpAddress_localhostV6 : public KIpAddress
62 {
63 public:
64     KIpAddress_localhostV6()
65         : KIpAddress(0L, 6)
66     {
67         m_data[3] = htonl(1);
68     }
69 };
70 #endif
71 
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 };
74 
75 const KIpAddress KIpAddress::localhostV4(&localhostV4_data, 4);
76 const KIpAddress KIpAddress::localhostV6(&localhostV6_data, 6);
77 const KIpAddress KIpAddress::anyhostV4(nullptr, 4);
78 const KIpAddress KIpAddress::anyhostV6(nullptr, 6);
79 
80 // helper function to test if an IPv6 v4-mapped address is equal to its IPv4 counterpart
check_v4mapped(const quint32 * v6addr,quint32 v4addr)81 static bool check_v4mapped(const quint32 *v6addr, quint32 v4addr)
82 {
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
86     }
87 
88     return v6addr[3] == v4addr;
89 }
90 
91 // copy operator
operator =(const KIpAddress & other)92 KIpAddress &KIpAddress::operator =(const KIpAddress &other)
93 {
94     m_version = other.m_version;
95     if (m_version == 4 || m_version == 6) {
96         memcpy(m_data, other.m_data, sizeof(m_data));
97     }
98     return *this;
99 }
100 
101 // comparison
compare(const KIpAddress & other,bool checkMapped) const102 bool KIpAddress::compare(const KIpAddress &other, bool checkMapped) const
103 {
104     if (m_version == other.m_version)
105         switch (m_version) {
106         case 0:
107             // both objects are empty
108             return true;
109 
110         case 4:
111             // IPv4 address
112             return *m_data == *other.m_data;
113 
114         case 6:
115             // IPv6 address
116             // they are 128-bit long, that is, 16 bytes
117             return memcmp(m_data, other.m_data, 16) == 0;
118         }
119 
120     if (checkMapped) {
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)) {
123             return true;
124         }
125 
126         if (other.m_version == 6 && m_version == 4 && check_v4mapped(other.m_data, *m_data)) {
127             return true;
128         }
129     }
130 
131     return false;
132 }
133 
134 // sets the address to the given address
setAddress(const QString & address)135 bool KIpAddress::setAddress(const QString &address)
136 {
137     m_version = 0;
138 
139     // try to guess the address version
140     if (address.indexOf(QLatin1Char(':')) != -1) {
141 #ifdef AF_INET6
142         // guessing IPv6
143 
144         quint32 buf[4];
145         if (inet_pton(AF_INET6, address.toLatin1(), buf)) {
146             memcpy(m_data, buf, sizeof(m_data));
147             m_version = 6;
148             return true;
149         }
150 #endif
151 
152         return false;
153     } else {
154         quint32 buf;
155         if (inet_pton(AF_INET, address.toLatin1(), &buf)) {
156             *m_data = buf;
157             m_version = 4;
158             return true;
159         }
160 
161         return false;
162     }
163 
164     return false;         // can never happen!
165 }
166 
setAddress(const char * address)167 bool KIpAddress::setAddress(const char *address)
168 {
169     return setAddress(QLatin1String(address));
170 }
171 
172 // set from binary data
setAddress(const void * raw,int version)173 bool KIpAddress::setAddress(const void *raw, int version)
174 {
175     // this always succeeds
176     // except if version is invalid
177     if (version != 4 && version != 6) {
178         return false;
179     }
180 
181     m_version = version;
182     if (raw != nullptr) {
183         memcpy(m_data, raw, version == 4 ? 4 : 16);
184     } else {
185         memset(m_data, 0, 16);
186     }
187 
188     return true;
189 }
190 
191 // presentation form
toString() const192 QString KIpAddress::toString() const
193 {
194     char buf[sizeof "1111:2222:3333:4444:5555:6666:255.255.255.255" + 2];
195     buf[0] = '\0';
196     switch (m_version) {
197     case 4:
198         inet_ntop(AF_INET, (void *)m_data, buf, sizeof(buf) - 1);
199         return QLatin1String(buf);
200 
201     case 6:
202 #ifdef AF_INET6
203         inet_ntop(AF_INET6, (void *)m_data, buf, sizeof(buf) - 1);
204 #endif
205         return QLatin1String(buf);
206     }
207 
208     return QString();
209 }
210 
211 /*
212  * An IPv6 socket address
213  * This is taken from RFC 2553.
214  */
215 struct our_sockaddr_in6 {
216 # if HAVE_STRUCT_SOCKADDR_SA_LEN
217     quint8        sin6_len;
218     quint8        sin6_family;
219 # else  //!HAVE_STRUCT_SOCKADDR_SA_LEN
220     quint16       sin6_family;
221 # endif
222     quint16           sin6_port;  /* RFC says in_port_t */
223     quint32       sin6_flowinfo;
224     quint8        sin6_addr[16]; // 24 bytes up to here
225     quint32       sin6_scope_id; // 28 bytes total
226 };
227 
228 // useful definitions
229 #define MIN_SOCKADDR_LEN    sizeof(quint16)
230 #define SOCKADDR_IN_LEN     sizeof(sockaddr_in)
231 #define MIN_SOCKADDR_IN6_LEN    ((quintptr) &(((our_sockaddr_in6*)0)->sin6_scope_id))
232 #define SOCKADDR_IN6_LEN    sizeof(our_sockaddr_in6)
233 #define MIN_SOCKADDR_UN_LEN (sizeof(quint16) + sizeof(char))
234 
235 class KNetwork::KSocketAddressData
236 {
237 public:
238     /*
239      * Note: maybe this should be virtual
240      * But since the data is shared via the d pointer, it doesn't really matter
241      * what one class sees, so will the other
242      */
243     class QMixSocketAddressRef : public KInetSocketAddress, public KUnixSocketAddress
244     {
245     public:
QMixSocketAddressRef(KSocketAddressData * d)246         QMixSocketAddressRef(KSocketAddressData *d)
247             : KInetSocketAddress(d), KUnixSocketAddress(d)
248         {
249         }
250     };
251     QMixSocketAddressRef ref;
252 
253     union {
254         struct sockaddr         *generic;
255         struct sockaddr_in      *in;
256         struct our_sockaddr_in6 *in6;
257         struct sockaddr_un      *un;
258     } addr;
259     quint16 curlen, reallen;
260 
KSocketAddressData()261     KSocketAddressData()
262         : ref(this)
263     {
264         addr.generic = nullptr;
265         curlen = 0;
266         invalidate();
267     }
268 
~KSocketAddressData()269     ~KSocketAddressData()
270     {
271         if (addr.generic != nullptr) {
272             free(addr.generic);
273         }
274     }
275 
invalid() const276     inline bool invalid() const
277     {
278         return reallen == 0;
279     }
280 
invalidate()281     inline void invalidate()
282     {
283         reallen = 0;
284     }
285 
286     void dup(const sockaddr *sa, quint16 len, bool clear = true);
287 
makeipv4()288     void makeipv4()
289     {
290         short oldport = 0;
291         if (!invalid())
292             switch (addr.generic->sa_family) {
293             case AF_INET:
294                 return;       // nothing to do here
295 #ifdef AF_INET6
296             case AF_INET6:
297                 oldport = addr.in6->sin6_port;
298                 break;
299 #endif
300             }
301 
302         // create new space
303         dup(nullptr, SOCKADDR_IN_LEN);
304 
305         addr.in->sin_family = AF_INET;
306 #if HAVE_STRUCT_SOCKADDR_SA_LEN
307         addr.in->sin_len = SOCKADDR_IN_LEN;
308 #endif
309         addr.in->sin_port = oldport;
310     }
311 
makeipv6()312     void makeipv6()
313     {
314         short oldport = 0;
315         if (!invalid())
316             switch (addr.generic->sa_family) {
317             case AF_INET:
318                 oldport = addr.in->sin_port;
319                 break;
320 
321 #ifdef AF_INET6
322             case AF_INET6:
323                 return;       // nothing to do here
324 #endif
325             }
326 
327         // make room
328         dup(nullptr, SOCKADDR_IN6_LEN);
329 #ifdef AF_INET6
330         addr.in6->sin6_family = AF_INET6;
331 #endif
332 #if HAVE_STRUCT_SOCKADDR_SA_LEN
333         addr.in6->sin6_len = SOCKADDR_IN6_LEN;
334 #endif
335         addr.in6->sin6_port = oldport;
336         // sin6_scope_id and sin6_flowid are zero
337     }
338 
339 };
340 
341 // create duplicates of
dup(const sockaddr * sa,quint16 len,bool clear)342 void KSocketAddressData::dup(const sockaddr *sa, quint16 len, bool clear)
343 {
344     if (len < MIN_SOCKADDR_LEN) {
345         // certainly invalid
346         invalidate();
347         return;
348     }
349 
350     if (sa && ((sa->sa_family == AF_INET && len < SOCKADDR_IN_LEN) ||
351 #ifdef AF_INET6
352                (sa->sa_family == AF_INET6 && len < MIN_SOCKADDR_IN6_LEN) ||
353 #endif
354                (sa->sa_family == AF_UNIX && len < MIN_SOCKADDR_UN_LEN))) {
355         // also invalid
356         invalidate();
357         return;
358     }
359 
360     // good
361     reallen = len;
362     if (len > curlen) {
363         if (len < 32) {
364             curlen = 32;    // big enough for sockaddr_in and sockaddr_in6
365         } else {
366             curlen = len;
367         }
368         addr.generic = (sockaddr *)realloc(addr.generic, curlen);
369     }
370 
371     if (sa != nullptr) {
372         memcpy(addr.generic, sa, len); // copy
373 
374         // now, normalise the data
375         if (addr.generic->sa_family == AF_INET) {
376             reallen = SOCKADDR_IN_LEN;    // no need to be larger
377         }
378 #ifdef AF_INET6
379         else if (addr.generic->sa_family == AF_INET6) {
380             // set the extra field (sin6_scope_id)
381 
382             // the buffer is never smaller than 32 bytes, so this is always
383             // allowed
384             if (reallen < SOCKADDR_IN6_LEN) {
385                 addr.in6->sin6_scope_id = 0;
386             }
387 
388             reallen = SOCKADDR_IN6_LEN;
389         }
390 #endif
391         else if (addr.generic->sa_family == AF_UNIX) {
392             reallen = MIN_SOCKADDR_UN_LEN + strlen(addr.un->sun_path);
393         }
394     } else if (clear) {
395         memset(addr.generic, 0, len);
396         addr.generic->sa_family = AF_UNSPEC;
397     }
398 }
399 
400 // default constructor
KSocketAddress()401 KSocketAddress::KSocketAddress()
402     : d(new KSocketAddressData)
403 {
404 }
405 
406 // constructor from binary data
KSocketAddress(const sockaddr * sa,quint16 len)407 KSocketAddress::KSocketAddress(const sockaddr *sa, quint16 len)
408     : d(new KSocketAddressData)
409 {
410     setAddress(sa, len);
411 }
412 
KSocketAddress(const KSocketAddress & other)413 KSocketAddress::KSocketAddress(const KSocketAddress &other)
414     : d(new(KSocketAddressData))
415 {
416     *this = other;
417 }
418 
KSocketAddress(KSocketAddressData * d2)419 KSocketAddress::KSocketAddress(KSocketAddressData *d2)
420     : d(d2)
421 {
422 }
423 
~KSocketAddress()424 KSocketAddress::~KSocketAddress()
425 {
426     // prevent double-deletion, since we're already being deleted
427     if (d) {
428         d->ref.KInetSocketAddress::d = nullptr;
429         d->ref.KUnixSocketAddress::d = nullptr;
430         delete d;
431     }
432 }
433 
operator =(const KSocketAddress & other)434 KSocketAddress &KSocketAddress::operator =(const KSocketAddress &other)
435 {
436     if (other.d && !other.d->invalid()) {
437         d->dup(other.d->addr.generic, other.d->reallen);
438     } else {
439         d->invalidate();
440     }
441     return *this;
442 }
443 
address() const444 const sockaddr *KSocketAddress::address() const
445 {
446     if (d->invalid()) {
447         return nullptr;
448     }
449     return d->addr.generic;
450 }
451 
address()452 sockaddr *KSocketAddress::address()
453 {
454     if (d->invalid()) {
455         return nullptr;
456     }
457     return d->addr.generic;
458 }
459 
setAddress(const sockaddr * sa,quint16 len)460 KSocketAddress &KSocketAddress::setAddress(const sockaddr *sa, quint16 len)
461 {
462     if (sa != nullptr && len >= MIN_SOCKADDR_LEN) {
463         d->dup(sa, len);
464     } else {
465         d->invalidate();
466     }
467 
468     return *this;
469 }
470 
length() const471 quint16 KSocketAddress::length() const
472 {
473     if (d->invalid()) {
474         return 0;
475     }
476     return d->reallen;
477 }
478 
setLength(quint16 len)479 KSocketAddress &KSocketAddress::setLength(quint16 len)
480 {
481     d->dup((sockaddr *)nullptr, len, false);
482 
483     return *this;
484 }
485 
family() const486 int KSocketAddress::family() const
487 {
488     if (d->invalid()) {
489         return AF_UNSPEC;
490     }
491     return d->addr.generic->sa_family;
492 }
493 
setFamily(int family)494 KSocketAddress &KSocketAddress::setFamily(int family)
495 {
496     if (d->invalid()) {
497         d->dup((sockaddr *)nullptr, MIN_SOCKADDR_LEN);
498     }
499     d->addr.generic->sa_family = family;
500 
501     return *this;
502 }
503 
operator ==(const KSocketAddress & other) const504 bool KSocketAddress::operator ==(const KSocketAddress &other) const
505 {
506     // if this is invalid, it's only equal if the other one is invalid as well
507     if (d->invalid()) {
508         return other.d->invalid();
509     }
510 
511     // check the family to make sure we don't do unnecessary comparison
512     if (d->addr.generic->sa_family != other.d->addr.generic->sa_family) {
513         return false;    // not the same family, not equal
514     }
515 
516     // same family then
517     // check the ones we know already
518     switch (d->addr.generic->sa_family) {
519     case AF_INET:
520         Q_ASSERT(d->reallen == SOCKADDR_IN_LEN);
521         Q_ASSERT(other.d->reallen == SOCKADDR_IN_LEN);
522         return memcmp(d->addr.in, other.d->addr.in, SOCKADDR_IN_LEN) == 0;
523 
524 #ifdef AF_INET6
525     case AF_INET6:
526         Q_ASSERT(d->reallen >= MIN_SOCKADDR_IN6_LEN);
527         Q_ASSERT(other.d->reallen >= MIN_SOCKADDR_IN6_LEN);
528 
529 # if !HAVE_STRUCT_SOCKADDR_IN6 || defined(HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID)
530         // check for the case where sin6_scope_id isn't present
531         if (d->reallen != other.d->reallen) {
532             if (memcmp(d->addr.in6, other.d->addr.in6, MIN_SOCKADDR_IN6_LEN) != 0) {
533                 return false;    // not equal
534             }
535             if (d->reallen > other.d->reallen) {
536                 return d->addr.in6->sin6_scope_id == 0;
537             } else {
538                 return other.d->addr.in6->sin6_scope_id == 0;
539             }
540         }
541 # endif
542 
543         return memcmp(d->addr.in6, other.d->addr.in6, d->reallen) == 0;
544 #endif
545 
546     case AF_UNIX:
547         Q_ASSERT(d->reallen >= MIN_SOCKADDR_UN_LEN);
548         Q_ASSERT(other.d->reallen >= MIN_SOCKADDR_UN_LEN);
549 
550         // do a string comparison here
551         return strcmp(d->addr.un->sun_path, other.d->addr.un->sun_path) == 0;
552 
553     default:
554         // something else we don't know about
555         // they are equal if and only if they are exactly equal
556         if (d->reallen == other.d->reallen) {
557             return memcmp(d->addr.generic, other.d->addr.generic, d->reallen) == 0;
558         }
559     }
560 
561     return false;     // not equal in any other case
562 }
563 
nodeName() const564 QString KSocketAddress::nodeName() const
565 {
566     if (d->invalid()) {
567         return QString();
568     }
569 
570     switch (d->addr.generic->sa_family) {
571     case AF_INET:
572 #ifdef AF_INET6
573     case AF_INET6:
574 
575         QString scopeid(QLatin1Char('%'));
576         if (d->addr.generic->sa_family == AF_INET6 && d->addr.in6->sin6_scope_id) {
577             scopeid += QString::number(d->addr.in6->sin6_scope_id);
578         } else {
579             scopeid.truncate(0);
580         }
581         return d->ref.ipAddress().toString() + scopeid;
582 #else
583         return d->ref.ipAddress().toString();
584 #endif
585     }
586 
587     // any other case, including AF_UNIX
588     return QString();
589 }
590 
serviceName() const591 QString KSocketAddress::serviceName() const
592 {
593     if (d->invalid()) {
594         return QString();
595     }
596 
597     switch (d->addr.generic->sa_family) {
598     case AF_INET:
599 #ifdef AF_INET6
600     case AF_INET6:
601 #endif
602         return QString::number(d->ref.port());
603 
604     case AF_UNIX:
605         return d->ref.pathname();
606     }
607 
608     return QString();
609 }
610 
toString() const611 QString KSocketAddress::toString() const
612 {
613     if (d->invalid()) {
614         return QString();
615     }
616 
617     QString fmt;
618 
619     if (d->addr.generic->sa_family == AF_INET) {
620         fmt = QLatin1String("%1:%2");
621     }
622 #ifdef AF_INET6
623     else if (d->addr.generic->sa_family == AF_INET6) {
624         fmt = QLatin1String("[%1]:%2");
625     }
626 #endif
627     else if (d->addr.generic->sa_family == AF_UNIX) {
628         return QString(QLatin1String("unix:%1")).arg(serviceName());
629     } else
630         return i18nc("1: the unknown socket address family number",
631                      "Unknown family %1", d->addr.generic->sa_family);
632 
633     return fmt.arg(nodeName()).arg(serviceName());
634 }
635 
asInet()636 KInetSocketAddress &KSocketAddress::asInet()
637 {
638     return d->ref;
639 }
640 
asInet() const641 KInetSocketAddress KSocketAddress::asInet() const
642 {
643     return d->ref;
644 }
645 
asUnix()646 KUnixSocketAddress &KSocketAddress::asUnix()
647 {
648     return d->ref;
649 }
650 
asUnix() const651 KUnixSocketAddress KSocketAddress::asUnix() const
652 {
653     return d->ref;
654 }
655 
ianaFamily(int af)656 int KSocketAddress::ianaFamily(int af)
657 {
658     switch (af) {
659     case AF_INET:
660         return 1;
661 
662 #ifdef AF_INET6
663     case AF_INET6:
664         return 2;
665 #endif
666 
667     default:
668         return 0;
669     }
670 }
671 
fromIanaFamily(int iana)672 int KSocketAddress::fromIanaFamily(int iana)
673 {
674     switch (iana) {
675     case 1:
676         return AF_INET;
677 
678 #ifdef AF_INET6
679     case 2:
680         return AF_INET6;
681 #endif
682 
683     default:
684         return AF_UNSPEC;
685     }
686 }
687 
688 // default constructor
KInetSocketAddress()689 KInetSocketAddress::KInetSocketAddress()
690 {
691 }
692 
693 // binary data constructor
KInetSocketAddress(const sockaddr * sa,quint16 len)694 KInetSocketAddress::KInetSocketAddress(const sockaddr *sa, quint16 len)
695     : KSocketAddress(sa, len)
696 {
697     if (!d->invalid()) {
698         update();
699     }
700 }
701 
702 // create from IP and port
KInetSocketAddress(const KIpAddress & host,quint16 port)703 KInetSocketAddress::KInetSocketAddress(const KIpAddress &host, quint16 port)
704 {
705     setHost(host);
706     setPort(port);
707 }
708 
709 // copy constructor
KInetSocketAddress(const KInetSocketAddress & other)710 KInetSocketAddress::KInetSocketAddress(const KInetSocketAddress &other)
711     : KSocketAddress(other)
712 {
713 }
714 
715 // special copy constructor
KInetSocketAddress(const KSocketAddress & other)716 KInetSocketAddress::KInetSocketAddress(const KSocketAddress &other)
717     : KSocketAddress(other)
718 {
719     if (!d->invalid()) {
720         update();
721     }
722 }
723 
724 // special constructor
KInetSocketAddress(KSocketAddressData * d)725 KInetSocketAddress::KInetSocketAddress(KSocketAddressData *d)
726     : KSocketAddress(d)
727 {
728 }
729 
730 // destructor
~KInetSocketAddress()731 KInetSocketAddress::~KInetSocketAddress()
732 {
733     /* nothing to do */
734 }
735 
736 // copy operator
operator =(const KInetSocketAddress & other)737 KInetSocketAddress &KInetSocketAddress::operator =(const KInetSocketAddress &other)
738 {
739     KSocketAddress::operator =(other);
740     return *this;
741 }
742 
743 // IP version
ipVersion() const744 int KInetSocketAddress::ipVersion() const
745 {
746     if (d->invalid()) {
747         return 0;
748     }
749 
750     switch (d->addr.generic->sa_family) {
751     case AF_INET:
752         return 4;
753 
754 #ifdef AF_INET6
755     case AF_INET6:
756         return 6;
757 #endif
758     }
759 
760     return 0;         // for all other cases
761 }
762 
ipAddress() const763 KIpAddress KInetSocketAddress::ipAddress() const
764 {
765     if (d->invalid()) {
766         return KIpAddress();    // return an empty address as well
767     }
768 
769     switch (d->addr.generic->sa_family) {
770     case AF_INET:
771         return KIpAddress(&d->addr.in->sin_addr, 4);
772 #ifdef AF_INET6
773     case AF_INET6:
774         return KIpAddress(&d->addr.in6->sin6_addr, 6);
775 #endif
776     }
777 
778     return KIpAddress();      // empty in all other cases
779 }
780 
setHost(const KIpAddress & ip)781 KInetSocketAddress &KInetSocketAddress::setHost(const KIpAddress &ip)
782 {
783     switch (ip.version()) {
784     case 4:
785         makeIPv4();
786         memcpy(&d->addr.in->sin_addr, ip.addr(), sizeof(d->addr.in->sin_addr));
787         break;
788 
789     case 6:
790         makeIPv6();
791         memcpy(&d->addr.in6->sin6_addr, ip.addr(), sizeof(d->addr.in6->sin6_addr));
792         break;
793 
794     default:
795         // empty
796         d->invalidate();
797     }
798 
799     return *this;
800 }
801 
802 // returns the port
port() const803 quint16 KInetSocketAddress::port() const
804 {
805     if (d->invalid()) {
806         return 0;
807     }
808 
809     switch (d->addr.generic->sa_family) {
810     case AF_INET:
811         return ntohs(d->addr.in->sin_port);
812 
813 #ifdef AF_INET6
814     case AF_INET6:
815         return ntohs(d->addr.in6->sin6_port);
816 #endif
817     }
818 
819     return 0;
820 }
821 
setPort(quint16 port)822 KInetSocketAddress &KInetSocketAddress::setPort(quint16 port)
823 {
824     if (d->invalid()) {
825         makeIPv4();
826     }
827 
828     switch (d->addr.generic->sa_family) {
829     case AF_INET:
830         d->addr.in->sin_port = htons(port);
831         break;
832 
833 #ifdef AF_INET6
834     case AF_INET6:
835         d->addr.in6->sin6_port = htons(port);
836         break;
837 #endif
838 
839     default:
840         d->invalidate();      // setting the port on something else
841     }
842 
843     return *this;
844 }
845 
makeIPv4()846 KInetSocketAddress &KInetSocketAddress::makeIPv4()
847 {
848     d->makeipv4();
849     return *this;
850 }
851 
makeIPv6()852 KInetSocketAddress &KInetSocketAddress::makeIPv6()
853 {
854     d->makeipv6();
855     return *this;
856 }
857 
flowinfo() const858 quint32 KInetSocketAddress::flowinfo() const
859 {
860 #ifndef AF_INET6
861     return 0;
862 #else
863 
864     if (!d->invalid() && d->addr.in6->sin6_family == AF_INET6) {
865         return d->addr.in6->sin6_flowinfo;
866     }
867     return 0;
868 #endif
869 }
870 
setFlowinfo(quint32 flowinfo)871 KInetSocketAddress &KInetSocketAddress::setFlowinfo(quint32 flowinfo)
872 {
873     makeIPv6();           // must set here
874     d->addr.in6->sin6_flowinfo = flowinfo;
875     return *this;
876 }
877 
scopeId() const878 int KInetSocketAddress::scopeId() const
879 {
880 #ifndef AF_INET6
881     return 0;
882 #else
883 
884     if (!d->invalid() && d->addr.in6->sin6_family == AF_INET6) {
885         return d->addr.in6->sin6_scope_id;
886     }
887     return 0;
888 #endif
889 }
890 
setScopeId(int scopeid)891 KInetSocketAddress &KInetSocketAddress::setScopeId(int scopeid)
892 {
893     makeIPv6();           // must set here
894     d->addr.in6->sin6_scope_id = scopeid;
895     return *this;
896 }
897 
update()898 void KInetSocketAddress::update()
899 {
900     if (d->addr.generic->sa_family == AF_INET) {
901         return;
902     }
903 #ifdef AF_INET6
904     else if (d->addr.generic->sa_family == AF_INET6) {
905         return;
906     }
907 #endif
908     else {
909         d->invalidate();
910     }
911 }
912 
KUnixSocketAddress()913 KUnixSocketAddress::KUnixSocketAddress()
914 {
915 }
916 
KUnixSocketAddress(const sockaddr * sa,quint16 len)917 KUnixSocketAddress::KUnixSocketAddress(const sockaddr *sa, quint16 len)
918     : KSocketAddress(sa, len)
919 {
920     if (!d->invalid() && d->addr.un->sun_family != AF_UNIX) {
921         d->invalidate();
922     }
923 }
924 
KUnixSocketAddress(const KUnixSocketAddress & other)925 KUnixSocketAddress::KUnixSocketAddress(const KUnixSocketAddress &other)
926     : KSocketAddress(other)
927 {
928 }
929 
KUnixSocketAddress(const QString & pathname)930 KUnixSocketAddress::KUnixSocketAddress(const QString &pathname)
931 {
932     setPathname(pathname);
933 }
934 
KUnixSocketAddress(KSocketAddressData * d)935 KUnixSocketAddress::KUnixSocketAddress(KSocketAddressData *d)
936     : KSocketAddress(d)
937 {
938 }
939 
~KUnixSocketAddress()940 KUnixSocketAddress::~KUnixSocketAddress()
941 {
942 }
943 
operator =(const KUnixSocketAddress & other)944 KUnixSocketAddress &KUnixSocketAddress::operator =(const KUnixSocketAddress &other)
945 {
946     KSocketAddress::operator =(other);
947     return *this;
948 }
949 
pathname() const950 QString KUnixSocketAddress::pathname() const
951 {
952     if (!d->invalid() && d->addr.un->sun_family == AF_UNIX) {
953         return QFile::decodeName(d->addr.un->sun_path);
954     }
955     return QString();
956 }
957 
setPathname(const QString & path)958 KUnixSocketAddress &KUnixSocketAddress::setPathname(const QString &path)
959 {
960     d->dup(nullptr, MIN_SOCKADDR_UN_LEN + path.length());
961     d->addr.un->sun_family = AF_UNIX;
962     strcpy(d->addr.un->sun_path, QFile::encodeName(path));
963 
964 #if HAVE_STRUCT_SOCKADDR_SA_LEN
965     d->addr.un->sun_len = d->reallen;
966 #endif
967 
968     return *this;
969 }
970