File indexing completed on 2025-01-05 04:37:19

0001 /*
0002     SPDX-FileCopyrightText: 2005 Joris Guisson <joris.guisson@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "address.h"
0008 #include <sys/socket.h>
0009 #include <util/log.h>
0010 
0011 using namespace bt;
0012 
0013 namespace net
0014 {
0015 Address::Address()
0016     : port_number(0)
0017 {
0018 }
0019 
0020 Address::Address(quint32 ip4Addr, Uint16 port)
0021     : QHostAddress(ip4Addr)
0022     , port_number(port)
0023 {
0024 }
0025 
0026 Address::Address(quint8 *ip6Addr, Uint16 port)
0027     : QHostAddress(ip6Addr)
0028     , port_number(port)
0029 {
0030 }
0031 
0032 Address::Address(const Q_IPV6ADDR &ip6Addr, Uint16 port)
0033     : QHostAddress(ip6Addr)
0034     , port_number(port)
0035 {
0036 }
0037 
0038 Address::Address(const struct sockaddr_storage *ss)
0039     : port_number(0)
0040 {
0041     if (ss->ss_family == AF_INET) {
0042         setAddress((const struct sockaddr *)ss);
0043         port_number = ntohs(((const struct sockaddr_in *)ss)->sin_port);
0044     } else if (ss->ss_family == AF_INET6) {
0045         setAddress((const struct sockaddr *)ss);
0046         port_number = ntohs(((const struct sockaddr_in6 *)ss)->sin6_port);
0047         if (isIPv4Mapped()) {
0048             Q_IPV6ADDR ipv6 = toIPv6Address();
0049             quint32 ip = ipv6[12] << 24 | ipv6[13] << 16 | ipv6[14] << 8 | ipv6[15];
0050             setAddress(ip);
0051         }
0052     } else
0053         Out(SYS_GEN | LOG_DEBUG) << "Unknown address family" << endl;
0054 }
0055 
0056 Address::Address(const QString &host, Uint16 port)
0057     : QHostAddress(host)
0058     , port_number(port)
0059 {
0060 }
0061 
0062 Address::Address(const Address &addr)
0063     : QHostAddress(addr)
0064     , port_number(addr.port_number)
0065 {
0066 }
0067 
0068 Address::Address(const QHostAddress &addr, Uint16 port)
0069     : QHostAddress(addr)
0070     , port_number(port)
0071 {
0072 }
0073 
0074 Address::~Address()
0075 {
0076 }
0077 
0078 void Address::toSocketAddress(sockaddr_storage *ss, int &length) const
0079 {
0080     if (protocol() == QAbstractSocket::IPv4Protocol) {
0081         struct sockaddr_in *addr = (struct sockaddr_in *)ss;
0082         memset(addr, 0, sizeof(struct sockaddr_in));
0083         addr->sin_family = AF_INET;
0084         addr->sin_port = htons(port_number);
0085         addr->sin_addr.s_addr = htonl(toIPv4Address());
0086         length = sizeof(struct sockaddr_in);
0087     } else {
0088         struct sockaddr_in6 *addr = (struct sockaddr_in6 *)ss;
0089         memset(addr, 0, sizeof(struct sockaddr_in6));
0090         addr->sin6_family = AF_INET6;
0091         addr->sin6_port = htons(port_number);
0092         memcpy(&addr->sin6_addr, toIPv6Address().c, 16);
0093         length = sizeof(struct sockaddr_in6);
0094     }
0095 }
0096 
0097 bool Address::operator==(const net::Address &other) const
0098 {
0099     return QHostAddress::operator==(other) && port_number == other.port();
0100 }
0101 
0102 bool Address::operator<(const net::Address &other) const
0103 {
0104     if (ipVersion() != other.ipVersion()) {
0105         return ipVersion() < other.ipVersion();
0106     } else if (other.ipVersion() == 4) {
0107         return toIPv4Address() == other.toIPv4Address() ? port_number < other.port_number : toIPv4Address() < other.toIPv4Address();
0108     } else { // IPv6
0109         if (QHostAddress::operator==(other))
0110             return port_number < other.port_number;
0111         else {
0112             Q_IPV6ADDR a = toIPv6Address();
0113             Q_IPV6ADDR b = other.toIPv6Address();
0114             for (int i = 0; i < 16; i++) {
0115                 if (a[i] < b[i])
0116                     return true;
0117                 else if (a[i] > b[i])
0118                     return false;
0119             }
0120             return false;
0121         }
0122     }
0123 }
0124 
0125 Address &Address::operator=(const net::Address &other)
0126 {
0127     QHostAddress::operator=(other);
0128     port_number = other.port();
0129     return *this;
0130 }
0131 
0132 Address &Address::operator=(const struct sockaddr_storage &ss)
0133 {
0134     if (ss.ss_family == AF_INET) {
0135         setAddress((const struct sockaddr *)&ss);
0136         port_number = ntohs(((const struct sockaddr_in *)&ss)->sin_port);
0137     } else if (ss.ss_family == AF_INET6) {
0138         setAddress((const struct sockaddr *)&ss);
0139         port_number = ntohs(((const struct sockaddr_in6 *)&ss)->sin6_port);
0140         if (isIPv4Mapped()) {
0141             Q_IPV6ADDR ipv6 = toIPv6Address();
0142             quint32 ip = ipv6[12] << 24 | ipv6[13] << 16 | ipv6[14] << 8 | ipv6[15];
0143             setAddress(ip);
0144         }
0145     }
0146 
0147     return *this;
0148 }
0149 
0150 bool Address::isIPv4Mapped() const
0151 {
0152     Q_IPV6ADDR addr = toIPv6Address();
0153     for (int i = 0; i < 10; i++)
0154         if (addr[i] != 0)
0155             return false;
0156 
0157     return addr[10] == 0xff && addr[11] == 0xff;
0158 }
0159 
0160 Address Address::convertIPv4Mapped() const
0161 {
0162     if (isIPv4Mapped()) {
0163         Q_IPV6ADDR ipv6 = toIPv6Address();
0164         quint32 ip = ipv6[12] << 24 | ipv6[13] << 16 | ipv6[14] << 8 | ipv6[15];
0165         return net::Address(ip, port());
0166     }
0167 
0168     return net::Address(*this);
0169 }
0170 }