Path: blob/main/contrib/llvm-project/lldb/source/Host/common/SocketAddress.cpp
39606 views
//===-- SocketAddress.cpp -------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Note: This file is used on Darwin by debugserver, so it needs to remain as9// self contained as possible, and devoid of references to LLVM unless10// there is compelling reason.11//12//===----------------------------------------------------------------------===//1314#if defined(_MSC_VER)15#define _WINSOCK_DEPRECATED_NO_WARNINGS16#endif1718#include "lldb/Host/SocketAddress.h"19#include <cstddef>20#include <cstdio>2122#if !defined(_WIN32)23#include <arpa/inet.h>24#endif2526#include <cassert>27#include <cstring>2829#include "lldb/Host/PosixApi.h"3031// WindowsXP needs an inet_ntop implementation32#ifdef _WIN323334#ifndef INET6_ADDRSTRLEN // might not be defined in older Windows SDKs35#define INET6_ADDRSTRLEN 4636#endif3738// TODO: implement shortened form "::" for runs of zeros39const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) {40if (size == 0) {41return nullptr;42}4344switch (af) {45case AF_INET: {46{47const char *formatted = inet_ntoa(*static_cast<const in_addr *>(src));48if (formatted && strlen(formatted) < static_cast<size_t>(size)) {49return ::strcpy(dst, formatted);50}51}52return nullptr;53case AF_INET6: {54char tmp[INET6_ADDRSTRLEN] = {0};55const uint16_t *src16 = static_cast<const uint16_t *>(src);56int full_size = ::snprintf(57tmp, sizeof(tmp), "%x:%x:%x:%x:%x:%x:%x:%x", ntohs(src16[0]),58ntohs(src16[1]), ntohs(src16[2]), ntohs(src16[3]), ntohs(src16[4]),59ntohs(src16[5]), ntohs(src16[6]), ntohs(src16[7]));60if (full_size < static_cast<int>(size)) {61return ::strcpy(dst, tmp);62}63return nullptr;64}65}66}67return nullptr;68}69#endif7071using namespace lldb_private;7273// SocketAddress constructor74SocketAddress::SocketAddress() { Clear(); }7576SocketAddress::SocketAddress(const struct sockaddr &s) { m_socket_addr.sa = s; }7778SocketAddress::SocketAddress(const struct sockaddr_in &s) {79m_socket_addr.sa_ipv4 = s;80}8182SocketAddress::SocketAddress(const struct sockaddr_in6 &s) {83m_socket_addr.sa_ipv6 = s;84}8586SocketAddress::SocketAddress(const struct sockaddr_storage &s) {87m_socket_addr.sa_storage = s;88}8990SocketAddress::SocketAddress(const struct addrinfo *addr_info) {91*this = addr_info;92}9394// Destructor95SocketAddress::~SocketAddress() = default;9697void SocketAddress::Clear() {98memset(&m_socket_addr, 0, sizeof(m_socket_addr));99}100101bool SocketAddress::IsValid() const { return GetLength() != 0; }102103static socklen_t GetFamilyLength(sa_family_t family) {104switch (family) {105case AF_INET:106return sizeof(struct sockaddr_in);107case AF_INET6:108return sizeof(struct sockaddr_in6);109}110assert(0 && "Unsupported address family");111return 0;112}113114socklen_t SocketAddress::GetLength() const {115#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || \116defined(__OpenBSD__)117return m_socket_addr.sa.sa_len;118#else119return GetFamilyLength(GetFamily());120#endif121}122123socklen_t SocketAddress::GetMaxLength() { return sizeof(sockaddr_t); }124125sa_family_t SocketAddress::GetFamily() const {126return m_socket_addr.sa.sa_family;127}128129void SocketAddress::SetFamily(sa_family_t family) {130m_socket_addr.sa.sa_family = family;131#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || \132defined(__OpenBSD__)133m_socket_addr.sa.sa_len = GetFamilyLength(family);134#endif135}136137std::string SocketAddress::GetIPAddress() const {138char str[INET6_ADDRSTRLEN] = {0};139switch (GetFamily()) {140case AF_INET:141if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv4.sin_addr, str,142sizeof(str)))143return str;144break;145case AF_INET6:146if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv6.sin6_addr, str,147sizeof(str)))148return str;149break;150}151return "";152}153154uint16_t SocketAddress::GetPort() const {155switch (GetFamily()) {156case AF_INET:157return ntohs(m_socket_addr.sa_ipv4.sin_port);158case AF_INET6:159return ntohs(m_socket_addr.sa_ipv6.sin6_port);160}161return 0;162}163164bool SocketAddress::SetPort(uint16_t port) {165switch (GetFamily()) {166case AF_INET:167m_socket_addr.sa_ipv4.sin_port = htons(port);168return true;169170case AF_INET6:171m_socket_addr.sa_ipv6.sin6_port = htons(port);172return true;173}174return false;175}176177// SocketAddress assignment operator178const SocketAddress &SocketAddress::179operator=(const struct addrinfo *addr_info) {180Clear();181if (addr_info && addr_info->ai_addr && addr_info->ai_addrlen > 0 &&182size_t(addr_info->ai_addrlen) <= sizeof m_socket_addr) {183::memcpy(&m_socket_addr, addr_info->ai_addr, addr_info->ai_addrlen);184}185return *this;186}187188const SocketAddress &SocketAddress::operator=(const struct sockaddr &s) {189m_socket_addr.sa = s;190return *this;191}192193const SocketAddress &SocketAddress::operator=(const struct sockaddr_in &s) {194m_socket_addr.sa_ipv4 = s;195return *this;196}197198const SocketAddress &SocketAddress::operator=(const struct sockaddr_in6 &s) {199m_socket_addr.sa_ipv6 = s;200return *this;201}202203const SocketAddress &SocketAddress::204operator=(const struct sockaddr_storage &s) {205m_socket_addr.sa_storage = s;206return *this;207}208209bool SocketAddress::getaddrinfo(const char *host, const char *service,210int ai_family, int ai_socktype, int ai_protocol,211int ai_flags) {212Clear();213214auto addresses = GetAddressInfo(host, service, ai_family, ai_socktype,215ai_protocol, ai_flags);216if (!addresses.empty())217*this = addresses[0];218return IsValid();219}220221std::vector<SocketAddress>222SocketAddress::GetAddressInfo(const char *hostname, const char *servname,223int ai_family, int ai_socktype, int ai_protocol,224int ai_flags) {225std::vector<SocketAddress> addr_list;226227struct addrinfo hints;228memset(&hints, 0, sizeof(hints));229hints.ai_family = ai_family;230hints.ai_socktype = ai_socktype;231hints.ai_protocol = ai_protocol;232hints.ai_flags = ai_flags;233234struct addrinfo *service_info_list = nullptr;235int err = ::getaddrinfo(hostname, servname, &hints, &service_info_list);236if (err == 0 && service_info_list) {237for (struct addrinfo *service_ptr = service_info_list;238service_ptr != nullptr; service_ptr = service_ptr->ai_next) {239addr_list.emplace_back(SocketAddress(service_ptr));240}241}242243if (service_info_list)244::freeaddrinfo(service_info_list);245return addr_list;246}247248bool SocketAddress::SetToLocalhost(sa_family_t family, uint16_t port) {249switch (family) {250case AF_INET:251SetFamily(AF_INET);252if (SetPort(port)) {253m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);254return true;255}256break;257258case AF_INET6:259SetFamily(AF_INET6);260if (SetPort(port)) {261m_socket_addr.sa_ipv6.sin6_addr = in6addr_loopback;262return true;263}264break;265}266Clear();267return false;268}269270bool SocketAddress::SetToAnyAddress(sa_family_t family, uint16_t port) {271switch (family) {272case AF_INET:273SetFamily(AF_INET);274if (SetPort(port)) {275m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);276return true;277}278break;279280case AF_INET6:281SetFamily(AF_INET6);282if (SetPort(port)) {283m_socket_addr.sa_ipv6.sin6_addr = in6addr_any;284return true;285}286break;287}288Clear();289return false;290}291292bool SocketAddress::IsAnyAddr() const {293return (GetFamily() == AF_INET)294? m_socket_addr.sa_ipv4.sin_addr.s_addr == htonl(INADDR_ANY)295: 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, &in6addr_any, 16);296}297298bool SocketAddress::IsLocalhost() const {299return (GetFamily() == AF_INET)300? m_socket_addr.sa_ipv4.sin_addr.s_addr == htonl(INADDR_LOOPBACK)301: 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, &in6addr_loopback,30216);303}304305bool SocketAddress::operator==(const SocketAddress &rhs) const {306if (GetFamily() != rhs.GetFamily())307return false;308if (GetLength() != rhs.GetLength())309return false;310switch (GetFamily()) {311case AF_INET:312return m_socket_addr.sa_ipv4.sin_addr.s_addr ==313rhs.m_socket_addr.sa_ipv4.sin_addr.s_addr;314case AF_INET6:315return 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr,316&rhs.m_socket_addr.sa_ipv6.sin6_addr, 16);317}318return false;319}320321bool SocketAddress::operator!=(const SocketAddress &rhs) const {322return !(*this == rhs);323}324325326