Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 : #include "base/address_util.h"
6 :
7 : #include <endian.h>
8 : #include <boost/algorithm/string.hpp>
9 : #include <boost/asio/io_service.hpp>
10 : #include <boost/asio/ip/tcp.hpp>
11 : #include <boost/asio/ip/host_name.hpp>
12 : #include <boost/foreach.hpp>
13 :
14 : /* Returns true if the given IPv4 address is member of the IPv4 subnet
15 : * indicated by IPv4 address and prefix length. Otherwise returns false.
16 : * We convert both the input IPv4 addresses to their subnet addresses and
17 : * then compare with each other to conclude whether the IPv4 address is
18 : * member of the subnet or not.
19 : */
20 16932 : bool IsIp4SubnetMember(
21 : const Ip4Address &ip, const Ip4Address &prefix_ip, uint16_t plen) {
22 16932 : Ip4Address prefix = Address::GetIp4SubnetAddress(prefix_ip, plen);
23 16932 : return ((prefix.to_ulong() | ~(0xFFFFFFFF << (32 - plen))) ==
24 16932 : (ip.to_ulong() | ~(0xFFFFFFFF << (32 - plen))));
25 : }
26 :
27 : /* Returns true if the given IPv6 address is member of the IPv6 subnet
28 : * indicated by IPv6 address and prefix length. Otherwise returns false.
29 : */
30 15191 : bool IsIp6SubnetMember(
31 : const Ip6Address &ip, const Ip6Address &subnet, uint8_t plen) {
32 15191 : Ip6Address mask = Address::GetIp6SubnetAddress(subnet, plen);
33 15191 : Ip6Address ip1 = Address::GetIp6SubnetAddress(ip, plen);
34 30382 : return (ip1 == mask);
35 : }
36 :
37 : /*
38 : * Returns the canonical hostname (FQDN)
39 : */
40 :
41 61 : std::string ResolveCanonicalName()
42 : {
43 61 : boost::asio::io_context io_service;
44 61 : boost::system::error_code error;
45 61 : boost::asio::ip::tcp::resolver resolver (io_service);
46 122 : boost::asio::ip::tcp::resolver::query query(boost::asio::ip::host_name(),
47 183 : "", boost::asio::ip::resolver_query_base::canonical_name);
48 : boost::asio::ip::tcp::resolver::iterator iter =
49 122 : resolver.resolve (query,error), end;
50 61 : if (error) {
51 0 : return boost::asio::ip::host_name();
52 : }
53 61 : while (iter != end) {
54 61 : if (iter->host_name() != "") {
55 61 : return iter->host_name();
56 : }
57 0 : iter++;
58 : }
59 0 : return boost::asio::ip::host_name();
60 61 : }
61 :
62 : /*
63 : * Returns the canonical hostname (FQDN) by IPv4 address
64 : */
65 27098 : std::string ResolveCanonicalName(const std::string& ipv4)
66 : {
67 27098 : if (boost::starts_with(ipv4, "127."))
68 27098 : return "localhost";
69 0 : boost::asio::ip::tcp::endpoint endpoint;
70 0 : boost::asio::io_context io_service;
71 : boost::asio::ip::address_v4 ip =
72 0 : boost::asio::ip::address_v4::from_string(ipv4);
73 0 : endpoint.address(ip);
74 0 : boost::asio::ip::tcp::resolver resolver(io_service);
75 : boost::asio::ip::tcp::resolver::iterator iter =
76 0 : resolver.resolve (endpoint), end;
77 0 : while (iter != end){
78 0 : if(iter->host_name() != ""){
79 0 : return iter->host_name();
80 : }
81 0 : iter++;
82 : }
83 0 : return boost::asio::ip::host_name();
84 0 : }
85 :
86 : /* This variant passes all tests
87 : * To be covered by more tests later
88 : * Returns the canonical hostname (FQDN) by IPv6 address
89 : */
90 3 : std::string ResolveCanonicalNameIPv6(const std::string& ipv6)
91 : {
92 3 : std::string loc_ip = ipv6;
93 3 : if (boost::starts_with(loc_ip, "::1"))
94 3 : return "localhost";
95 0 : unsigned int perc_pos = loc_ip.find("%");
96 : if (perc_pos != std::string::npos) {
97 0 : loc_ip = loc_ip.substr(0,perc_pos);
98 : }
99 0 : return loc_ip;
100 : // Next code is incompatible with schema_transformer:
101 : // boost::asio::ip::tcp::endpoint endpoint;
102 : // boost::asio::io_context io_service;
103 : // boost::asio::ip::address_v6 ip =
104 : // boost::asio::ip::address_v6::from_string(loc_ip);
105 : // endpoint.address(ip);
106 : // boost::asio::ip::tcp::resolver resolver(io_service);
107 : // boost::asio::ip::tcp::resolver::iterator iter =
108 : // resolver.resolve (endpoint), end;
109 : // while (iter != end){
110 : // if(iter->host_name() != ""){
111 : // return iter->host_name();
112 : // }
113 : // iter++;
114 : // }
115 : // return boost::asio::ip::host_name();
116 3 : }
117 :
118 : /*
119 : * Returns boost::asio::ip::address if given string is either valid
120 : * IPv4, IPv6 or a resolvable FQDN
121 : */
122 :
123 15941 : IpAddress AddressFromString(
124 : const std::string &ip_address_str,
125 : boost::system::error_code *ec) {
126 : IpAddress addr =
127 15941 : boost::asio::ip::address::from_string(ip_address_str, *ec);
128 15941 : boost::system::error_code error_code = *ec;
129 15941 : if (error_code.value() != 0) {
130 319 : boost::asio::io_context io_service;
131 319 : std::string ip_string = GetHostIp(&io_service, ip_address_str);
132 319 : addr = boost::asio::ip::address::from_string(ip_string, *ec);
133 319 : }
134 31882 : return addr;
135 : }
136 :
137 23 : Ip4Address GetIp4SubnetBroadcastAddress(
138 : const Ip4Address &ip_prefix, uint16_t plen) {
139 23 : Ip4Address subnet(ip_prefix.to_ulong() | ~(0xFFFFFFFF << (32 - plen)));
140 23 : return subnet;
141 : }
142 :
143 : // Validate IPv4/IPv6 address string.
144 11 : bool ValidateIPAddressString(std::string ip_address_str,
145 : std::string *error_msg) {
146 11 : boost::system::error_code error;
147 11 : AddressFromString(ip_address_str, &error);
148 11 : if (error.value() != 0) {
149 2 : std::ostringstream out;
150 2 : out << "Invalid IP address: " << ip_address_str << std::endl;
151 2 : *error_msg = out.str();
152 2 : return false;
153 2 : }
154 9 : return true;
155 : }
156 :
157 330 : IpAddress PrefixToIpNetmask(uint32_t prefix_len) {
158 : uint32_t mask;
159 :
160 330 : if (prefix_len == 0) {
161 12 : mask = 0;
162 : } else {
163 318 : mask = (~((1 << (32 - prefix_len)) - 1));
164 : }
165 330 : return IpAddress(Ip4Address(mask));
166 : }
167 :
168 0 : uint32_t NetmaskToPrefix(uint32_t netmask) {
169 0 : uint32_t count = 0;
170 :
171 0 : while (netmask) {
172 0 : count++;
173 0 : netmask = (netmask - 1) & netmask;
174 : }
175 0 : return count;
176 : }
177 :
178 39 : IpAddress PrefixToIp6Netmask(uint32_t plen) {
179 39 : if (plen == 0) {
180 38 : return IpAddress(Ip6Address());
181 : }
182 :
183 1 : if (plen == 128) {
184 1 : boost::system::error_code ec;
185 : Ip6Address all_fs = Ip6Address::from_string
186 1 : ("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", ec);
187 1 : return IpAddress(all_fs);
188 : }
189 :
190 : Ip6Address::bytes_type bytes;
191 :
192 0 : int index = (int) (plen / 8);
193 0 : int remain_mask = plen % 8;
194 :
195 0 : for (int i = 0; i < index; i++) {
196 0 : bytes.at(i) = 0xff;
197 : }
198 :
199 0 : switch (remain_mask) {
200 0 : case 0:
201 0 : bytes.at(index++) = 0;
202 0 : break;
203 0 : case 1:
204 0 : bytes.at(index++) = 0x80;
205 0 : break;
206 0 : case 2:
207 0 : bytes.at(index++) = 0xc0;
208 0 : break;
209 0 : case 3:
210 0 : bytes.at(index++) = 0xe0;
211 0 : break;
212 0 : case 4:
213 0 : bytes.at(index++) = 0xf0;
214 0 : break;
215 0 : case 5:
216 0 : bytes.at(index++) = 0xf8;
217 0 : break;
218 0 : case 6:
219 0 : bytes.at(index++) = 0xfc;
220 0 : break;
221 0 : case 7:
222 0 : bytes.at(index++) = 0xfe;
223 0 : break;
224 : }
225 :
226 0 : for (int i = index; i < 16; ++i) {
227 0 : bytes.at(i) = 0;
228 : }
229 :
230 0 : return IpAddress(Ip6Address(bytes));
231 : }
232 :
233 : // Validate a list of <ip-address>:<port> endpoints.
234 13 : bool ValidateServerEndpoints(std::vector<std::string> list,
235 : std::string *error_msg) {
236 13 : std::ostringstream out;
237 :
238 47 : BOOST_FOREACH(std::string endpoint, list) {
239 19 : std::vector<std::string> tokens;
240 19 : boost::split(tokens, endpoint, boost::is_any_of(":"));
241 19 : if (tokens.size() != 2) {
242 1 : out << "Invalid endpoint " << endpoint << std::endl;
243 1 : *error_msg = out.str();
244 1 : return false;
245 : }
246 :
247 18 : boost::system::error_code error;
248 18 : AddressFromString(tokens[0], &error);
249 :
250 18 : if (error) {
251 1 : out << "Invalid IP address: " << tokens[0] << std::endl;
252 1 : *error_msg = out.str();
253 1 : return false;
254 : }
255 :
256 17 : unsigned long port = strtoul(tokens[1].c_str(), NULL, 0);
257 17 : if (errno || port > 0xffFF) {
258 0 : out << "Invalid port : " << tokens[1];
259 0 : if (errno) {
260 0 : out << " " << strerror(errno) << std::endl;
261 : }
262 0 : *error_msg = out.str();
263 0 : return false;
264 : }
265 38 : }
266 :
267 11 : return true;
268 13 : }
269 :
270 : // Return IP address string for a host if it is resolvable, empty string
271 : // otherwise.
272 463 : std::string GetHostIp(boost::asio::io_context *io_service,
273 : const std::string &hostname) {
274 463 : boost::asio::ip::tcp::resolver::iterator iter, end;
275 463 : boost::system::error_code error;
276 463 : boost::asio::ip::tcp::resolver resolver(*io_service);
277 926 : boost::asio::ip::tcp::resolver::query query(hostname, "");
278 :
279 463 : std::string result;
280 :
281 463 : iter = resolver.resolve(query, error);
282 463 : if (error) {
283 22 : return result;
284 : }
285 :
286 882 : for (; iter != end; ++iter) {
287 882 : const boost::asio::ip::address &addr = iter->endpoint().address();
288 882 : if (addr.is_v6()) {
289 441 : boost::asio::ip::address_v6 addr6 = addr.to_v6();
290 441 : if (addr6.is_link_local()) {
291 119 : continue;
292 : }
293 : }
294 763 : result = addr.to_string();
295 763 : if (addr.is_v4()) {
296 441 : return result;
297 : }
298 : }
299 0 : return result;
300 463 : }
301 :
302 : //
303 : // Get VN name from routing instance
304 : //
305 336 : std::string GetVNFromRoutingInstance(const std::string &vn) {
306 336 : std::vector<std::string> tokens;
307 336 : boost::split(tokens, vn, boost::is_any_of(":"), boost::token_compress_on);
308 336 : if (tokens.size() < 3) return "";
309 0 : return tokens[0] + ":" + tokens[1] + ":" + tokens[2];
310 336 : }
311 :
312 7736 : void IpToU64(const IpAddress &sip, const IpAddress &dip,
313 : uint64_t *sip_u, uint64_t *sip_l,
314 : uint64_t *dip_u, uint64_t *dip_l) {
315 7736 : if (sip.is_v4()) {
316 7582 : *sip_l = htonl(sip.to_v4().to_ulong());
317 7582 : *sip_u = 0;
318 : } else {
319 : uint64_t data[2];
320 153 : Ip6AddressToU64Array(sip.to_v6(), data, 2);
321 153 : *sip_u = data[0];
322 153 : *sip_l = data[1];
323 : }
324 :
325 7735 : if (dip.is_v4()) {
326 7582 : *dip_l = htonl(dip.to_v4().to_ulong());
327 7582 : *dip_u = 0;
328 : } else {
329 : uint64_t data[2];
330 153 : Ip6AddressToU64Array(dip.to_v6(), data, 2);
331 153 : *dip_u = data[0];
332 153 : *dip_l = data[1];
333 : }
334 7735 : }
335 :
336 140 : void U64ToIpv6(uint64_t upper, uint64_t lower, IpAddress *ip) {
337 : boost::asio::ip::address_v6::bytes_type bytes;
338 140 : const unsigned char *ptr = (const unsigned char *)&lower;
339 1260 : for (unsigned int i = 0; i < sizeof(uint64_t); i++) {
340 1120 : bytes[i] = ptr[i];
341 : }
342 140 : ptr = (const unsigned char *)&upper;
343 1260 : for (unsigned int i = 0; i < sizeof(uint64_t); i++) {
344 1120 : bytes[8 + i] = ptr[i];
345 : }
346 140 : *ip = Ip6Address(bytes);
347 140 : }
348 :
349 3494 : void U64ToIp(uint64_t sip_u, uint64_t sip_l, uint64_t dip_u, uint64_t dip_l,
350 : int family, IpAddress *sip, IpAddress *dip) {
351 3494 : if (family == Address::INET) {
352 3424 : *sip = Ip4Address(ntohl(sip_l & 0xFFFFFFFF));
353 3424 : *dip = Ip4Address(ntohl(dip_l & 0xFFFFFFFF));
354 : } else {
355 70 : U64ToIpv6(sip_u, sip_l, sip);
356 70 : U64ToIpv6(dip_u, dip_l, dip);
357 : }
358 3494 : }
359 :
360 37910 : void Ip6AddressToU64Array(const Ip6Address &addr, uint64_t *arr, int size) {
361 : unsigned char b[16];
362 : uint64_t ip;
363 : unsigned int i, j, k;
364 :
365 37910 : if (size != 2)
366 0 : return;
367 :
368 37910 : memcpy(b, addr.to_bytes().data(), sizeof(b));
369 :
370 189550 : for (i = 0, j = 0, k = 0; i < 4; i++, j = j+4) {
371 151640 : ip = 0;
372 :
373 151640 : ip = ((((uint32_t)b[j]) << 24) & 0xFF000000) |
374 151640 : ((((uint32_t)b[j+1]) << 16) & 0x00FF0000) |
375 151640 : ((((uint32_t)b[j+2]) << 8) & 0x0000FF00) |
376 151640 : (((uint32_t)b[j+3]) & 0x000000FF);
377 :
378 151640 : if (i >= 2)
379 75820 : k = 1;
380 :
381 151640 : if (i%2) {
382 75820 : arr[k] = arr[k] | (ip & 0x00000000FFFFFFFFU);
383 : } else {
384 75820 : arr[k] = (ip << 32) & 0xFFFFFFFF00000000U;
385 : }
386 : }
387 :
388 :
389 37910 : arr[0] = htobe64(arr[0]);
390 37910 : arr[1] = htobe64(arr[1]);
391 : }
392 :
393 0 : std::string VectorIpv6ToString(const std::vector<signed char> &ipv6) {
394 :
395 0 : if (ipv6.size() != 16) {
396 0 : return "0000:0000:0000:0000";
397 : }
398 0 : std::ostringstream strm;
399 0 : int count = 1;
400 0 : for(std::vector<signed char>::const_iterator it = ipv6.begin();
401 0 : it != ipv6.end(); ++it) {
402 0 : strm << std::hex << (int)((uint8_t) *it);
403 0 : if((count % 4) ==0)
404 0 : strm << ":";
405 0 : count++;
406 : }
407 0 : return strm.str();
408 0 : }
|