1 // Copyright 2005-2019 The Mumble Developers. All rights reserved.
2 // Use of this source code is governed by a BSD-style license
3 // that can be found in the LICENSE file at the root of the
4 // Mumble source tree or at <https://www.mumble.info/LICENSE>.
5 
6 #ifdef MUMBLE
7 	#include "mumble_pch.hpp"
8 #else
9 	#include "murmur_pch.h"
10 #endif
11 
12 #include "HostAddress.h"
13 
14 #include "ByteSwap.h"
15 
HostAddress()16 HostAddress::HostAddress() {
17 	addr[0] = addr[1] = 0ULL;
18 }
19 
HostAddress(const Q_IPV6ADDR & address)20 HostAddress::HostAddress(const Q_IPV6ADDR &address) {
21 	memcpy(qip6.c, address.c, 16);
22 }
23 
HostAddress(const std::string & address)24 HostAddress::HostAddress(const std::string &address) {
25 	if (address.length() != 16)
26 		addr[0] = addr[1] = 0ULL;
27 	else
28 		for (int i=0;i<16;++i)
29 			qip6[i] = address[i];
30 }
31 
HostAddress(const QByteArray & address)32 HostAddress::HostAddress(const QByteArray &address) {
33 	if (address.length() != 16)
34 		addr[0] = addr[1] = 0ULL;
35 	else
36 		for (int i=0;i<16;++i)
37 			qip6[i] = address[i];
38 }
39 
HostAddress(const QHostAddress & address)40 HostAddress::HostAddress(const QHostAddress &address) {
41 	if (address.protocol() == QAbstractSocket::IPv6Protocol) {
42 		const Q_IPV6ADDR &a = address.toIPv6Address();
43 		memcpy(qip6.c, a.c, 16);
44 	} else {
45 		addr[0] = 0ULL;
46 		shorts[4] = 0;
47 		shorts[5] = 0xffff;
48 		hash[3] = htonl(address.toIPv4Address());
49 	}
50 }
51 
HostAddress(const sockaddr_storage & address)52 HostAddress::HostAddress(const sockaddr_storage &address) {
53 	if (address.ss_family == AF_INET) {
54 		const struct sockaddr_in *in = reinterpret_cast<const struct sockaddr_in *>(&address);
55 		addr[0] = 0ULL;
56 		shorts[4] = 0;
57 		shorts[5] = 0xffff;
58 		hash[3] = in->sin_addr.s_addr;
59 	} else if (address.ss_family == AF_INET6) {
60 		const struct sockaddr_in6 *in6 = reinterpret_cast<const struct sockaddr_in6 *>(&address);
61 		memcpy(qip6.c, in6->sin6_addr.s6_addr, 16);
62 	} else {
63 		addr[0] = addr[1] = 0ULL;
64 	}
65 }
66 
operator <(const HostAddress & other) const67 bool HostAddress::operator < (const HostAddress &other) const {
68 	return memcmp(qip6.c, other.qip6.c, 16) < 0;
69 }
70 
operator ==(const HostAddress & other) const71 bool HostAddress::operator == (const HostAddress &other) const {
72 	return ((addr[0] == other.addr[0]) && (addr[1] == other.addr[1]));
73 }
74 
match(const HostAddress & netmask,int bits) const75 bool HostAddress::match(const HostAddress &netmask, int bits) const {
76 	quint64 mask[2];
77 
78 	if (bits == 128) {
79 		mask[0] = mask[1] = 0xffffffffffffffffULL;
80 	} else if (bits > 64) {
81 		mask[0] = 0xffffffffffffffffULL;
82 		mask[1] = SWAP64(~((1ULL << (128-bits)) - 1));
83 	} else {
84 		mask[0] = SWAP64(~((1ULL << (64-bits)) - 1));
85 		mask[1] = 0ULL;
86 	}
87 	return ((addr[0] & mask[0]) == (netmask.addr[0] & mask[0])) && ((addr[1] & mask[1]) == (netmask.addr[1] & mask[1]));
88 }
89 
toStdString() const90 std::string HostAddress::toStdString() const {
91 	return std::string(reinterpret_cast<const char *>(qip6.c), 16);
92 }
93 
isV6() const94 bool HostAddress::isV6() const {
95 	return (addr[0] != 0ULL) || (shorts[4] != 0) || (shorts[5] != 0xffff);
96 }
97 
isValid() const98 bool HostAddress::isValid() const {
99 	return (addr[0] != 0ULL) || (addr[1] != 0ULL);
100 }
101 
toAddress() const102 QHostAddress HostAddress::toAddress() const {
103 	if (isV6())
104 		return QHostAddress(qip6);
105 	else {
106 		return QHostAddress(ntohl(hash[3]));
107 	}
108 }
109 
toByteArray() const110 QByteArray HostAddress::toByteArray() const {
111 	return QByteArray(reinterpret_cast<const char *>(qip6.c), 16);
112 }
113 
toSockaddr(sockaddr_storage * dst) const114 void HostAddress::toSockaddr(sockaddr_storage *dst) const {
115 	memset(dst, 0, sizeof(*dst));
116 	if (isV6()) {
117 		struct sockaddr_in6 *in6 = reinterpret_cast<struct sockaddr_in6 *>(dst);
118 		dst->ss_family = AF_INET6;
119 		memcpy(in6->sin6_addr.s6_addr, qip6.c, 16);
120 	} else {
121 		struct sockaddr_in *in = reinterpret_cast<struct sockaddr_in *>(dst);
122 		dst->ss_family = AF_INET;
123 		in->sin_addr.s_addr = hash[3];
124 	}
125 }
126 
qHash(const HostAddress & ha)127 quint32 qHash(const HostAddress &ha) {
128 	return (ha.hash[0] ^ ha.hash[1] ^ ha.hash[2] ^ ha.hash[3]);
129 }
130 
toString() const131 QString HostAddress::toString() const {
132 	if (isV6()) {
133 		if (isValid()) {
134 			QString qs;
135 			qs.sprintf("[%x:%x:%x:%x:%x:%x:%x:%x]", ntohs(shorts[0]), ntohs(shorts[1]), ntohs(shorts[2]), ntohs(shorts[3]), ntohs(shorts[4]), ntohs(shorts[5]), ntohs(shorts[6]), ntohs(shorts[7]));
136 			return qs.replace(QRegExp(QLatin1String("(:0)+")),QLatin1String(":"));
137 		} else {
138 			return QLatin1String("[::]");
139 		}
140 	} else {
141 		return QHostAddress(ntohl(hash[3])).toString();
142 	}
143 }
144