YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/util/net/inetaddress.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) YugaByte, Inc.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
4
// in compliance with the License.  You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software distributed under the License
9
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10
// or implied.  See the License for the specific language governing permissions and limitations
11
// under the License.
12
//
13
#include "yb/util/net/inetaddress.h"
14
15
#include <memory>
16
#include <string>
17
#include <vector>
18
19
#include "yb/gutil/strings/split.h"
20
#include "yb/util/net/net_fwd.h"
21
#include "yb/util/status.h"
22
#include "yb/util/status_fwd.h"
23
24
using boost::asio::ip::address;
25
using boost::asio::ip::address_v4;
26
using boost::asio::ip::address_v6;
27
using boost::asio::ip::tcp;
28
29
namespace yb {
30
31
2.26M
InetAddress::InetAddress() {
32
2.26M
}
33
34
InetAddress::InetAddress(const boost::asio::ip::address& address)
35
661k
    : boost_addr_(address) {
36
661k
}
37
38
178k
InetAddress::InetAddress(const InetAddress& other) {
39
178k
  boost_addr_ = other.boost_addr_;
40
178k
}
41
42
23
std::string InetAddress::ToString() const {
43
23
  std::string strval;
44
23
  CHECK_OK(ToString(&strval));
45
23
  return strval;
46
23
}
47
48
33
CHECKED_STATUS InetAddress::ToString(std::string *strval) const {
49
33
  boost::system::error_code ec;
50
33
  *strval = boost_addr_.to_string(ec);
51
33
  if (ec.value()) {
52
0
    return STATUS(IllegalState, "InetAddress object cannot be converted to string: $0",
53
0
                  ec.message());
54
0
  }
55
33
  return Status::OK();
56
33
}
57
58
1.35M
std::string InetAddress::ToBytes() const {
59
1.35M
  std::string result;
60
1.35M
  AppendToBytes(&result);
61
1.35M
  return result;
62
1.35M
}
63
64
2.88M
void InetAddress::AppendToBytes(std::string* bytes) const {
65
2.88M
  if (boost_addr_.is_v4()) {
66
2.88M
    auto v4bytes = boost_addr_.to_v4().to_bytes();
67
2.88M
    bytes->append(reinterpret_cast<char *>(v4bytes.data()), v4bytes.size());
68
2.88M
  } else {
69
1.24k
    auto v6bytes = boost_addr_.to_v6().to_bytes();
70
1.24k
    bytes->append(reinterpret_cast<char *>(v6bytes.data()), v6bytes.size());
71
1.24k
  }
72
2.88M
}
73
74
2.19M
CHECKED_STATUS InetAddress::FromSlice(const Slice& slice, size_t size_hint) {
75
18.4E
  size_t expected_size = 
(size_hint == 0)2.19M
?
slice.size()2.19M
: size_hint;
76
2.19M
  if (expected_size > slice.size()) {
77
0
    return STATUS_SUBSTITUTE(InvalidArgument, "Size of slice: $0 is smaller than provided "
78
0
        "size_hint: $1", slice.size(), expected_size);
79
0
  }
80
2.19M
  if (expected_size == kInetAddressV4Size) {
81
2.19M
    address_v4::bytes_type v4bytes;
82
2.19M
    DCHECK_EQ(expected_size, v4bytes.size());
83
2.19M
    memcpy(v4bytes.data(), slice.data(), v4bytes.size());
84
2.19M
    address_v4 v4address(v4bytes);
85
2.19M
    boost_addr_ = v4address;
86
2.19M
  } else 
if (908
expected_size == kInetAddressV6Size908
) {
87
866
    address_v6::bytes_type v6bytes;
88
866
    DCHECK_EQ(expected_size, v6bytes.size());
89
866
    memcpy(v6bytes.data(), slice.data(), v6bytes.size());
90
866
    address_v6 v6address(v6bytes);
91
866
    boost_addr_ = v6address;
92
866
  } else {
93
42
    return STATUS_SUBSTITUTE(InvalidArgument, "Size of slice is invalid: $0", expected_size);
94
42
  }
95
2.19M
  return Status::OK();
96
2.19M
}
97
98
2.19M
CHECKED_STATUS InetAddress::FromBytes(const std::string& bytes) {
99
2.19M
  Slice slice (bytes.data(), bytes.size());
100
2.19M
  return FromSlice(slice);
101
2.19M
}
102
103
693
bool IsIPv6NonLinkLocal(const IpAddress& address) {
104
693
  if (!address.is_v6() || 
address.is_unspecified()689
) {
105
5
    return false;
106
5
  }
107
688
  boost::asio::ip::address_v6 v6_address = address.to_v6();
108
688
  return !v6_address.is_link_local();
109
693
}
110
111
701
bool IsIPv6External(const IpAddress& address) {
112
701
  return address.is_v6() && 
!address.is_unspecified()690
&&
113
701
         
!address.is_loopback()687
&&
IsIPv6NonLinkLocal(address)9
;
114
701
}
115
116
typedef std::function<bool(const IpAddress&)> FilterType;
117
118
131k
const std::map<string, FilterType>* GetFilters() {
119
131k
  static const auto ipv4_filter = [](const IpAddress& a) 
{ return a.is_v4(); }102k
;
120
131k
  static const auto ipv6_filter = [](const IpAddress& a) 
{ return a.is_v6(); }18
;
121
162k
  static const auto ipv4_external_filter = [](const IpAddress& a) {
122
162k
    return !a.is_unspecified() && 
a.is_v4()162k
&&
!a.is_loopback()162k
;
123
162k
  };
124
131k
  static const auto ipv6_external_filter = [](const IpAddress& a) {
125
701
    return IsIPv6External(a);
126
701
  };
127
131k
  static const auto ipv6_non_link_local_filter = [](const IpAddress& a) {
128
684
    return IsIPv6NonLinkLocal(a);
129
684
  };
130
131k
  static const auto all_filter = [](const IpAddress& a) 
{ return true; }0
;
131
132
131k
  static const std::map<string, FilterType> kFilters(
133
131k
      { { "ipv4_all",
134
131k
          ipv4_filter }, // any IPv4 address including 0.0.0.0 and loopback
135
131k
        { "ipv6_all",
136
131k
          ipv6_filter }, // any IPv6 address including ::, loopback etc
137
131k
        { "ipv4_external", ipv4_external_filter }, // Non-loopback IPv4
138
131k
        { "ipv6_external",
139
131k
          ipv6_external_filter }, // Non-loopback non-link-local IPv6
140
131k
        { "ipv6_non_link_local",
141
131k
          ipv6_non_link_local_filter }, // Non-link-local, loopback is ok
142
131k
        { "all", all_filter } });
143
144
131k
  return &kFilters;
145
131k
}
146
147
// Filter_spec has to be some subset of the following filters
148
// ipv4_all,ipv4_external,ipv6_all,ipv6_external,ipv6_non_link_local
149
// For ex: "ipv4_external,ipv4_all,ipv6_external,ipv6_non_link_local"
150
// This would result in a vector that has
151
// [ IPV4 external addresses, Remaining IPv4 addresses, IPv6 external addresses,
152
// Non-external IPv6 non_link_local addresses ]
153
// with [ link_local IPv6 addresses ] removed from the original list
154
131k
void FilterAddresses(const string& filter_spec, vector<IpAddress>* addresses) {
155
131k
  if (filter_spec.empty()) {
156
0
    return;
157
0
  }
158
159
131k
  const std::map<string, FilterType>* kFilters = GetFilters();
160
131k
  DCHECK(kFilters);
161
131k
  vector<string> filter_names = strings::Split(filter_spec, ",");
162
163
131k
  vector<const FilterType*> filters;
164
131k
  filters.reserve(filter_names.size());
165
659k
  for (const auto &filter_name : filter_names) {
166
18.4E
    VLOG(4) << "filtering by " << filter_name;
167
659k
    auto filter_it = kFilters->find(filter_name);
168
659k
    if (
filter_it != kFilters->end()659k
) {
169
659k
      filters.push_back(&filter_it->second);
170
18.4E
    } else {
171
18.4E
      LOG(ERROR) << "Unknown filter spec " << filter_name << " in filter spec "
172
18.4E
                 << filter_spec;
173
18.4E
    }
174
659k
  }
175
176
131k
  vector<vector<IpAddress> > matches(filters.size());
177
162k
  for (const auto& address : *addresses) {
178
266k
    for (size_t i = 0; i < filters.size(); 
++i103k
) {
179
266k
      DCHECK(filters[i]);
180
266k
      if ((*filters[i])(address)) {
181
162k
        VLOG
(3) << address.to_string() << " matches filter " << filter_names[i]0
;
182
162k
        matches[i].push_back(address);
183
162k
        break;
184
162k
      } else {
185
103k
        VLOG(4) << address.to_string() << " does not match filter "
186
15
                << filter_names[i];
187
103k
      }
188
266k
    }
189
162k
  }
190
131k
  vector<IpAddress> results;
191
659k
  for (const auto& match : matches) {
192
659k
    results.insert(results.end(), match.begin(), match.end());
193
659k
  }
194
131k
  addresses->swap(results);
195
131k
}
196
197
1.36k
bool InetAddress::operator<(const InetAddress& other) const {
198
1.36k
  return ToBytes() < other.ToBytes();
199
1.36k
}
200
201
0
bool InetAddress::isV4() const {
202
0
  DCHECK(!boost_addr_.is_unspecified());
203
0
  return boost_addr_.is_v4();
204
0
}
205
206
0
bool InetAddress::isV6() const {
207
0
  DCHECK(!boost_addr_.is_unspecified());
208
0
  return boost_addr_.is_v6();
209
0
}
210
211
} // namespace yb