-
Notifications
You must be signed in to change notification settings - Fork 0
/
DnsTlsServer.cpp
139 lines (119 loc) · 4.81 KB
/
DnsTlsServer.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "DnsTlsServer.h"
#include <algorithm>
#include <android-base/format.h>
#include <netdutils/InternetAddresses.h>
namespace {
// Returns a tuple of references to the elements of a.
auto make_tie(const sockaddr_in& a) {
return std::tie(a.sin_port, a.sin_addr.s_addr);
}
// Returns a tuple of references to the elements of a.
auto make_tie(const sockaddr_in6& a) {
// Skip flowinfo, which is not relevant.
return std::tie(
a.sin6_port,
a.sin6_addr,
a.sin6_scope_id
);
}
} // namespace
// These binary operators make sockaddr_storage comparable. They need to be
// in the global namespace so that the std::tuple < and == operators can see them.
static bool operator <(const in6_addr& x, const in6_addr& y) {
return std::lexicographical_compare(
std::begin(x.s6_addr), std::end(x.s6_addr),
std::begin(y.s6_addr), std::end(y.s6_addr));
}
static bool operator ==(const in6_addr& x, const in6_addr& y) {
return std::equal(
std::begin(x.s6_addr), std::end(x.s6_addr),
std::begin(y.s6_addr), std::end(y.s6_addr));
}
static bool operator <(const sockaddr_storage& x, const sockaddr_storage& y) {
if (x.ss_family != y.ss_family) {
return x.ss_family < y.ss_family;
}
// Same address family.
if (x.ss_family == AF_INET) {
const sockaddr_in& x_sin = reinterpret_cast<const sockaddr_in&>(x);
const sockaddr_in& y_sin = reinterpret_cast<const sockaddr_in&>(y);
return make_tie(x_sin) < make_tie(y_sin);
} else if (x.ss_family == AF_INET6) {
const sockaddr_in6& x_sin6 = reinterpret_cast<const sockaddr_in6&>(x);
const sockaddr_in6& y_sin6 = reinterpret_cast<const sockaddr_in6&>(y);
return make_tie(x_sin6) < make_tie(y_sin6);
}
return false; // Unknown address type. This is an error.
}
static bool operator ==(const sockaddr_storage& x, const sockaddr_storage& y) {
if (x.ss_family != y.ss_family) {
return false;
}
// Same address family.
if (x.ss_family == AF_INET) {
const sockaddr_in& x_sin = reinterpret_cast<const sockaddr_in&>(x);
const sockaddr_in& y_sin = reinterpret_cast<const sockaddr_in&>(y);
return make_tie(x_sin) == make_tie(y_sin);
} else if (x.ss_family == AF_INET6) {
const sockaddr_in6& x_sin6 = reinterpret_cast<const sockaddr_in6&>(x);
const sockaddr_in6& y_sin6 = reinterpret_cast<const sockaddr_in6&>(y);
return make_tie(x_sin6) == make_tie(y_sin6);
}
return false; // Unknown address type. This is an error.
}
namespace android {
namespace net {
// This comparison ignores ports and certificates.
bool AddressComparator::operator() (const DnsTlsServer& x, const DnsTlsServer& y) const {
if (x.ss.ss_family != y.ss.ss_family) {
return x.ss.ss_family < y.ss.ss_family;
}
// Same address family.
if (x.ss.ss_family == AF_INET) {
const sockaddr_in& x_sin = reinterpret_cast<const sockaddr_in&>(x.ss);
const sockaddr_in& y_sin = reinterpret_cast<const sockaddr_in&>(y.ss);
return x_sin.sin_addr.s_addr < y_sin.sin_addr.s_addr;
} else if (x.ss.ss_family == AF_INET6) {
const sockaddr_in6& x_sin6 = reinterpret_cast<const sockaddr_in6&>(x.ss);
const sockaddr_in6& y_sin6 = reinterpret_cast<const sockaddr_in6&>(y.ss);
return std::tie(x_sin6.sin6_addr, x_sin6.sin6_scope_id) <
std::tie(y_sin6.sin6_addr, y_sin6.sin6_scope_id);
}
return false; // Unknown address type. This is an error.
}
// Returns a tuple of references to the elements of s.
auto make_tie(const DnsTlsServer& s) {
return std::tie(s.ss, s.name, s.protocol);
}
bool DnsTlsServer::operator <(const DnsTlsServer& other) const {
return make_tie(*this) < make_tie(other);
}
bool DnsTlsServer::operator ==(const DnsTlsServer& other) const {
return make_tie(*this) == make_tie(other);
}
bool DnsTlsServer::wasExplicitlyConfigured() const {
return !name.empty();
}
std::string DnsTlsServer::toIpString() const {
return netdutils::IPSockAddr::toIPSockAddr(ss).ip().toString();
}
std::string DnsTlsServer::toString() const {
return fmt::format("{{{}/{}}}", toIpString(), name);
}
} // namespace net
} // namespace android