blob: 71d2497e264da2dc31cdff0bef61012958de6c4f [file] [log] [blame]
Sunitha Harish29a82b02021-02-18 15:54:16 +05301#pragma once
Ed Tanousf8ca6d72022-06-28 12:12:03 -07002#ifdef BMCWEB_DBUS_DNS_RESOLVER
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08003#include "dbus_singleton.hpp"
4#include "logging.hpp"
5
Sunitha Harish29a82b02021-02-18 15:54:16 +05306#include <boost/asio/ip/address.hpp>
7#include <boost/asio/ip/basic_endpoint.hpp>
Carson Labrado7e8890c2022-11-23 23:58:01 +00008#include <boost/asio/ip/tcp.hpp>
Sunitha Harish29a82b02021-02-18 15:54:16 +05309#include <sdbusplus/message.hpp>
10
11#include <charconv>
12#include <iostream>
13#include <memory>
14
Sunitha Harish29a82b02021-02-18 15:54:16 +053015namespace async_resolve
16{
17
Ed Tanouse1452be2021-10-04 17:03:52 -070018inline bool endpointFromResolveTuple(const std::vector<uint8_t>& ipAddress,
19 boost::asio::ip::tcp::endpoint& endpoint)
20{
21 if (ipAddress.size() == 4) // ipv4 address
22 {
Ed Tanous62598e32023-07-17 17:06:25 -070023 BMCWEB_LOG_DEBUG("ipv4 address");
Ed Tanouse1452be2021-10-04 17:03:52 -070024 boost::asio::ip::address_v4 ipv4Addr(
25 {ipAddress[0], ipAddress[1], ipAddress[2], ipAddress[3]});
26 endpoint.address(ipv4Addr);
27 }
28 else if (ipAddress.size() == 16) // ipv6 address
29 {
Ed Tanous62598e32023-07-17 17:06:25 -070030 BMCWEB_LOG_DEBUG("ipv6 address");
Ed Tanouse1452be2021-10-04 17:03:52 -070031 boost::asio::ip::address_v6 ipv6Addr(
32 {ipAddress[0], ipAddress[1], ipAddress[2], ipAddress[3],
33 ipAddress[4], ipAddress[5], ipAddress[6], ipAddress[7],
34 ipAddress[8], ipAddress[9], ipAddress[10], ipAddress[11],
35 ipAddress[12], ipAddress[13], ipAddress[14], ipAddress[15]});
36 endpoint.address(ipv6Addr);
37 }
38 else
39 {
Ed Tanous62598e32023-07-17 17:06:25 -070040 BMCWEB_LOG_ERROR("Resolve failed to fetch the IP address");
Ed Tanouse1452be2021-10-04 17:03:52 -070041 return false;
42 }
43 return true;
44}
45
Sunitha Harish29a82b02021-02-18 15:54:16 +053046class Resolver
47{
48 public:
Ed Tanousf8ca6d72022-06-28 12:12:03 -070049 // unused io param used to keep interface identical to
50 // boost::asio::tcp:::resolver
51 explicit Resolver(boost::asio::io_context& /*io*/) {}
Sunitha Harish29a82b02021-02-18 15:54:16 +053052
53 ~Resolver() = default;
54
Ed Tanousecd6a3a2022-01-07 09:18:40 -080055 Resolver(const Resolver&) = delete;
56 Resolver(Resolver&&) = delete;
57 Resolver& operator=(const Resolver&) = delete;
58 Resolver& operator=(Resolver&&) = delete;
59
Ed Tanousf8ca6d72022-06-28 12:12:03 -070060 using results_type = std::vector<boost::asio::ip::tcp::endpoint>;
61
Sunitha Harish29a82b02021-02-18 15:54:16 +053062 template <typename ResolveHandler>
Ed Tanousf8ca6d72022-06-28 12:12:03 -070063 // This function is kept using snake case so that it is interoperable with
64 // boost::asio::ip::tcp::resolver
65 // NOLINTNEXTLINE(readability-identifier-naming)
Ed Tanousa716aa72023-08-01 11:35:53 -070066 void async_resolve(std::string_view host, std::string_view port,
Ed Tanousf8ca6d72022-06-28 12:12:03 -070067 ResolveHandler&& handler)
Sunitha Harish29a82b02021-02-18 15:54:16 +053068 {
Ed Tanous62598e32023-07-17 17:06:25 -070069 BMCWEB_LOG_DEBUG("Trying to resolve: {}:{}", host, port);
Ed Tanousf8ca6d72022-06-28 12:12:03 -070070
71 uint16_t portNum = 0;
72
73 auto it = std::from_chars(&*port.begin(), &*port.end(), portNum);
74 if (it.ec != std::errc())
75 {
Ed Tanous62598e32023-07-17 17:06:25 -070076 BMCWEB_LOG_ERROR("Failed to get the Port");
Ed Tanousf8ca6d72022-06-28 12:12:03 -070077 handler(std::make_error_code(std::errc::invalid_argument),
78 results_type{});
79
80 return;
81 }
82
Sunitha Harish29a82b02021-02-18 15:54:16 +053083 uint64_t flag = 0;
84 crow::connections::systemBus->async_method_call(
Ed Tanousa716aa72023-08-01 11:35:53 -070085 [host{std::string(host)}, portNum,
86 handler{std::forward<ResolveHandler>(handler)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -080087 const boost::system::error_code& ec,
Sunitha Harish29a82b02021-02-18 15:54:16 +053088 const std::vector<
89 std::tuple<int32_t, int32_t, std::vector<uint8_t>>>& resp,
90 const std::string& hostName, const uint64_t flagNum) {
Ed Tanousf8ca6d72022-06-28 12:12:03 -070091 results_type endpointList;
Ed Tanous002d39b2022-05-31 08:59:27 -070092 if (ec)
93 {
Ed Tanous62598e32023-07-17 17:06:25 -070094 BMCWEB_LOG_ERROR("Resolve failed: {}", ec.message());
Ed Tanous002d39b2022-05-31 08:59:27 -070095 handler(ec, endpointList);
96 return;
97 }
Ed Tanous62598e32023-07-17 17:06:25 -070098 BMCWEB_LOG_DEBUG("ResolveHostname returned: {}:{}", hostName,
99 flagNum);
Ed Tanous002d39b2022-05-31 08:59:27 -0700100 // Extract the IP address from the response
Ed Tanousf8ca6d72022-06-28 12:12:03 -0700101 for (const std::tuple<int32_t, int32_t, std::vector<uint8_t>>&
102 resolveList : resp)
Ed Tanous002d39b2022-05-31 08:59:27 -0700103 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700104 boost::asio::ip::tcp::endpoint endpoint;
Ed Tanousf8ca6d72022-06-28 12:12:03 -0700105 endpoint.port(portNum);
Ed Tanouse1452be2021-10-04 17:03:52 -0700106 if (!endpointFromResolveTuple(std::get<2>(resolveList),
107 endpoint))
108 {
109 boost::system::error_code ecErr = make_error_code(
110 boost::system::errc::address_not_available);
111 handler(ecErr, endpointList);
112 }
Ed Tanous62598e32023-07-17 17:06:25 -0700113 BMCWEB_LOG_DEBUG("resolved endpoint is : {}",
114 endpoint.address().to_string());
Ed Tanous002d39b2022-05-31 08:59:27 -0700115 endpointList.push_back(endpoint);
116 }
117 // All the resolved data is filled in the endpointList
118 handler(ec, endpointList);
Sunitha Harish29a82b02021-02-18 15:54:16 +0530119 },
120 "org.freedesktop.resolve1", "/org/freedesktop/resolve1",
121 "org.freedesktop.resolve1.Manager", "ResolveHostname", 0, host,
122 AF_UNSPEC, flag);
123 }
124};
125
126} // namespace async_resolve
Ed Tanousf8ca6d72022-06-28 12:12:03 -0700127#endif