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