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