YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/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.20M
InetAddress::InetAddress() {
32
2.20M
}
33
34
InetAddress::InetAddress(const boost::asio::ip::address& address)
35
604k
    : boost_addr_(address) {
36
604k
}
37
38
135k
InetAddress::InetAddress(const InetAddress& other) {
39
135k
  boost_addr_ = other.boost_addr_;
40
135k
}
41
42
1
std::string InetAddress::ToString() const {
43
1
  std::string strval;
44
1
  CHECK_OK(ToString(&strval));
45
1
  return strval;
46
1
}
47
48
11
CHECKED_STATUS InetAddress::ToString(std::string *strval) const {
49
11
  boost::system::error_code ec;
50
11
  *strval = boost_addr_.to_string(ec);
51
11
  if (ec.value()) {
52
0
    return STATUS(IllegalState, "InetAddress object cannot be converted to string: $0",
53
0
                  ec.message());
54
0
  }
55
11
  return Status::OK();
56
11
}
57
58
2.76M
CHECKED_STATUS InetAddress::ToBytes(std::string* bytes) const {
59
2.76M
  try {
60
2.76M
    if (boost_addr_.is_v4()) {
61
2.76M
      auto v4bytes = boost_addr_.to_v4().to_bytes();
62
2.76M
      bytes->assign(reinterpret_cast<char *>(v4bytes.data()), v4bytes.size());
63
687
    } else if (boost_addr_.is_v6()) {
64
687
      auto v6bytes = boost_addr_.to_v6().to_bytes();
65
687
      bytes->assign(reinterpret_cast<char *>(v6bytes.data()), v6bytes.size());
66
18.4E
    } else {
67
18.4E
      return STATUS(Uninitialized, "InetAddress doesn't hold a valid IPv4 or IPv6 address");
68
18.4E
    }
69
0
  } catch (std::exception& e) {
70
0
    return STATUS(Corruption, "Couldn't serialize InetAddress to raw bytes!");
71
0
  }
72
2.76M
  return Status::OK();
73
2.76M
}
74
75
2.13M
CHECKED_STATUS InetAddress::FromSlice(const Slice& slice, size_t size_hint) {
76
18.4E
  size_t expected_size = (size_hint == 0) ? slice.size() : size_hint;
77
2.13M
  if (expected_size > slice.size()) {
78
0
    return STATUS_SUBSTITUTE(InvalidArgument, "Size of slice: $0 is smaller than provided "
79
0
        "size_hint: $1", slice.size(), expected_size);
80
0
  }
81
2.13M
  if (expected_size == kInetAddressV4Size) {
82
2.12M
    address_v4::bytes_type v4bytes;
83
2.12M
    DCHECK_EQ(expected_size, v4bytes.size());
84
2.12M
    memcpy(v4bytes.data(), slice.data(), v4bytes.size());
85
2.12M
    address_v4 v4address(v4bytes);
86
2.12M
    boost_addr_ = v4address;
87
911
  } else if (expected_size == kInetAddressV6Size) {
88
911
    address_v6::bytes_type v6bytes;
89
911
    DCHECK_EQ(expected_size, v6bytes.size());
90
911
    memcpy(v6bytes.data(), slice.data(), v6bytes.size());
91
911
    address_v6 v6address(v6bytes);
92
911
    boost_addr_ = v6address;
93
18.4E
  } else {
94
18.4E
    return STATUS_SUBSTITUTE(InvalidArgument, "Size of slice is invalid: $0", expected_size);
95
18.4E
  }
96
2.13M
  return Status::OK();
97
2.13M
}
98
99
2.13M
CHECKED_STATUS InetAddress::FromBytes(const std::string& bytes) {
100
2.13M
  Slice slice (bytes.data(), bytes.size());
101
2.13M
  return FromSlice(slice);
102
2.13M
}
103
104
356
bool IsIPv6NonLinkLocal(const IpAddress& address) {
105
356
  if (!address.is_v6() || address.is_unspecified()) {
106
5
    return false;
107
5
  }
108
351
  boost::asio::ip::address_v6 v6_address = address.to_v6();
109
351
  return !v6_address.is_link_local();
110
351
}
111
112
364
bool IsIPv6External(const IpAddress& address) {
113
364
  return address.is_v6() && !address.is_unspecified() &&
114
350
         !address.is_loopback() && IsIPv6NonLinkLocal(address);
115
364
}
116
117
typedef std::function<bool(const IpAddress&)> FilterType;
118
119
90.2k
const std::map<string, FilterType>* GetFilters() {
120
67.7k
  static const auto ipv4_filter = [](const IpAddress& a) { return a.is_v4(); };
121
18
  static const auto ipv6_filter = [](const IpAddress& a) { return a.is_v6(); };
122
113k
  static const auto ipv4_external_filter = [](const IpAddress& a) {
123
113k
    return !a.is_unspecified() && a.is_v4() && !a.is_loopback();
124
113k
  };
125
364
  static const auto ipv6_external_filter = [](const IpAddress& a) {
126
364
    return IsIPv6External(a);
127
364
  };
128
347
  static const auto ipv6_non_link_local_filter = [](const IpAddress& a) {
129
347
    return IsIPv6NonLinkLocal(a);
130
347
  };
131
0
  static const auto all_filter = [](const IpAddress& a) { return true; };
132
133
90.2k
  static const std::map<string, FilterType> kFilters(
134
90.2k
      { { "ipv4_all",
135
90.2k
          ipv4_filter }, // any IPv4 address including 0.0.0.0 and loopback
136
90.2k
        { "ipv6_all",
137
90.2k
          ipv6_filter }, // any IPv6 address including ::, loopback etc
138
90.2k
        { "ipv4_external", ipv4_external_filter }, // Non-loopback IPv4
139
90.2k
        { "ipv6_external",
140
90.2k
          ipv6_external_filter }, // Non-loopback non-link-local IPv6
141
90.2k
        { "ipv6_non_link_local",
142
90.2k
          ipv6_non_link_local_filter }, // Non-link-local, loopback is ok
143
90.2k
        { "all", all_filter } });
144
145
90.2k
  return &kFilters;
146
90.2k
}
147
148
// Filter_spec has to be some subset of the following filters
149
// ipv4_all,ipv4_external,ipv6_all,ipv6_external,ipv6_non_link_local
150
// For ex: "ipv4_external,ipv4_all,ipv6_external,ipv6_non_link_local"
151
// This would result in a vector that has
152
// [ IPV4 external addresses, Remaining IPv4 addresses, IPv6 external addresses,
153
// Non-external IPv6 non_link_local addresses ]
154
// with [ link_local IPv6 addresses ] removed from the original list
155
90.2k
void FilterAddresses(const string& filter_spec, vector<IpAddress>* addresses) {
156
90.2k
  if (filter_spec.empty()) {
157
0
    return;
158
0
  }
159
160
90.2k
  const std::map<string, FilterType>* kFilters = GetFilters();
161
90.2k
  DCHECK(kFilters);
162
90.2k
  vector<string> filter_names = strings::Split(filter_spec, ",");
163
164
90.2k
  vector<const FilterType*> filters;
165
90.2k
  filters.reserve(filter_names.size());
166
451k
  for (const auto &filter_name : filter_names) {
167
15
    VLOG(4) << "filtering by " << filter_name;
168
451k
    auto filter_it = kFilters->find(filter_name);
169
451k
    if (filter_it != kFilters->end()) {
170
451k
      filters.push_back(&filter_it->second);
171
18.4E
    } else {
172
18.4E
      LOG(ERROR) << "Unknown filter spec " << filter_name << " in filter spec "
173
18.4E
                 << filter_spec;
174
18.4E
    }
175
451k
  }
176
177
90.2k
  vector<vector<IpAddress> > matches(filters.size());
178
113k
  for (const auto& address : *addresses) {
179
181k
    for (size_t i = 0; i < filters.size(); ++i) {
180
181k
      DCHECK(filters[i]);
181
181k
      if ((*filters[i])(address)) {
182
18.4E
        VLOG(3) << address.to_string() << " matches filter " << filter_names[i];
183
113k
        matches[i].push_back(address);
184
113k
        break;
185
68.5k
      } else {
186
30
        VLOG(4) << address.to_string() << " does not match filter "
187
30
                << filter_names[i];
188
68.5k
      }
189
181k
    }
190
113k
  }
191
90.2k
  vector<IpAddress> results;
192
450k
  for (const auto& match : matches) {
193
450k
    results.insert(results.end(), match.begin(), match.end());
194
450k
  }
195
90.2k
  addresses->swap(results);
196
90.2k
}
197
198
872
bool InetAddress::operator<(const InetAddress& other) const {
199
872
  string this_bytes, other_bytes;
200
872
  Status s = ToBytes(&this_bytes);
201
872
  Status t = other.ToBytes(&other_bytes);
202
872
  DCHECK(s.ok() && t.ok());
203
872
  return this_bytes < other_bytes;
204
872
}
205
206
0
bool InetAddress::isV4() const {
207
0
  DCHECK(!boost_addr_.is_unspecified());
208
0
  return boost_addr_.is_v4();
209
0
}
210
211
0
bool InetAddress::isV6() const {
212
0
  DCHECK(!boost_addr_.is_unspecified());
213
0
  return boost_addr_.is_v6();
214
0
}
215
216
} // namespace yb