1 // Copyright (c) 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "quiche/quic/platform/api/quic_socket_address.h"
6
7 #include <cstring>
8 #include <limits>
9 #include <string>
10
11 #include "absl/strings/str_cat.h"
12 #include "quiche/quic/platform/api/quic_bug_tracker.h"
13 #include "quiche/quic/platform/api/quic_ip_address.h"
14 #include "quiche/quic/platform/api/quic_ip_address_family.h"
15
16 namespace quic {
17
18 namespace {
19
HashIP(const QuicIpAddress & ip)20 uint32_t HashIP(const QuicIpAddress& ip) {
21 if (ip.IsIPv4()) {
22 return ip.GetIPv4().s_addr;
23 }
24 if (ip.IsIPv6()) {
25 auto v6addr = ip.GetIPv6();
26 const uint32_t* v6_as_ints =
27 reinterpret_cast<const uint32_t*>(&v6addr.s6_addr);
28 return v6_as_ints[0] ^ v6_as_ints[1] ^ v6_as_ints[2] ^ v6_as_ints[3];
29 }
30 return 0;
31 }
32
33 } // namespace
34
QuicSocketAddress(QuicIpAddress address,uint16_t port)35 QuicSocketAddress::QuicSocketAddress(QuicIpAddress address, uint16_t port)
36 : host_(address), port_(port) {}
37
QuicSocketAddress(const struct sockaddr_storage & saddr)38 QuicSocketAddress::QuicSocketAddress(const struct sockaddr_storage& saddr) {
39 switch (saddr.ss_family) {
40 case AF_INET: {
41 const sockaddr_in* v4 = reinterpret_cast<const sockaddr_in*>(&saddr);
42 host_ = QuicIpAddress(v4->sin_addr);
43 port_ = ntohs(v4->sin_port);
44 break;
45 }
46 case AF_INET6: {
47 const sockaddr_in6* v6 = reinterpret_cast<const sockaddr_in6*>(&saddr);
48 host_ = QuicIpAddress(v6->sin6_addr);
49 port_ = ntohs(v6->sin6_port);
50 break;
51 }
52 default:
53 QUIC_BUG(quic_bug_10075_1)
54 << "Unknown address family passed: " << saddr.ss_family;
55 break;
56 }
57 }
58
QuicSocketAddress(const sockaddr * saddr,socklen_t len)59 QuicSocketAddress::QuicSocketAddress(const sockaddr* saddr, socklen_t len) {
60 sockaddr_storage storage;
61 static_assert(std::numeric_limits<socklen_t>::max() >= sizeof(storage),
62 "Cannot cast sizeof(storage) to socklen_t as it does not fit");
63 if (len < static_cast<socklen_t>(sizeof(sockaddr)) ||
64 (saddr->sa_family == AF_INET &&
65 len < static_cast<socklen_t>(sizeof(sockaddr_in))) ||
66 (saddr->sa_family == AF_INET6 &&
67 len < static_cast<socklen_t>(sizeof(sockaddr_in6))) ||
68 len > static_cast<socklen_t>(sizeof(storage))) {
69 QUIC_BUG(quic_bug_10075_2) << "Socket address of invalid length provided";
70 return;
71 }
72 memcpy(&storage, saddr, len);
73 *this = QuicSocketAddress(storage);
74 }
75
operator ==(const QuicSocketAddress & lhs,const QuicSocketAddress & rhs)76 bool operator==(const QuicSocketAddress& lhs, const QuicSocketAddress& rhs) {
77 return lhs.host_ == rhs.host_ && lhs.port_ == rhs.port_;
78 }
79
operator !=(const QuicSocketAddress & lhs,const QuicSocketAddress & rhs)80 bool operator!=(const QuicSocketAddress& lhs, const QuicSocketAddress& rhs) {
81 return !(lhs == rhs);
82 }
83
IsInitialized() const84 bool QuicSocketAddress::IsInitialized() const { return host_.IsInitialized(); }
85
ToString() const86 std::string QuicSocketAddress::ToString() const {
87 switch (host_.address_family()) {
88 case IpAddressFamily::IP_V4:
89 return absl::StrCat(host_.ToString(), ":", port_);
90 case IpAddressFamily::IP_V6:
91 return absl::StrCat("[", host_.ToString(), "]:", port_);
92 default:
93 return "";
94 }
95 }
96
FromSocket(int fd)97 int QuicSocketAddress::FromSocket(int fd) {
98 sockaddr_storage addr;
99 socklen_t addr_len = sizeof(addr);
100 int result = getsockname(fd, reinterpret_cast<sockaddr*>(&addr), &addr_len);
101
102 bool success = result == 0 && addr_len > 0 &&
103 static_cast<size_t>(addr_len) <= sizeof(addr);
104 if (success) {
105 *this = QuicSocketAddress(addr);
106 return 0;
107 }
108 return -1;
109 }
110
Normalized() const111 QuicSocketAddress QuicSocketAddress::Normalized() const {
112 return QuicSocketAddress(host_.Normalized(), port_);
113 }
114
host() const115 QuicIpAddress QuicSocketAddress::host() const { return host_; }
116
port() const117 uint16_t QuicSocketAddress::port() const { return port_; }
118
generic_address() const119 sockaddr_storage QuicSocketAddress::generic_address() const {
120 union {
121 sockaddr_storage storage;
122 sockaddr_in v4;
123 sockaddr_in6 v6;
124 } result;
125 memset(&result.storage, 0, sizeof(result.storage));
126
127 switch (host_.address_family()) {
128 case IpAddressFamily::IP_V4:
129 result.v4.sin_family = AF_INET;
130 result.v4.sin_addr = host_.GetIPv4();
131 result.v4.sin_port = htons(port_);
132 break;
133 case IpAddressFamily::IP_V6:
134 result.v6.sin6_family = AF_INET6;
135 result.v6.sin6_addr = host_.GetIPv6();
136 result.v6.sin6_port = htons(port_);
137 break;
138 default:
139 result.storage.ss_family = AF_UNSPEC;
140 break;
141 }
142 return result.storage;
143 }
144
Hash() const145 uint32_t QuicSocketAddress::Hash() const {
146 uint32_t value = 0;
147 value ^= HashIP(host_);
148 value ^= port_ | (port_ << 16);
149 return value;
150 }
151
152 } // namespace quic
153