blob: 1a6f1b7a64bd56a31672896ef7a380ad221a76f2 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
Sunitha Harish29a82b02021-02-18 15:54:16 +05303#pragma once
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08004#include "dbus_singleton.hpp"
5#include "logging.hpp"
6
Ed Tanousd7857202025-01-28 15:32:26 -08007#include <sys/socket.h>
8
9#include <boost/asio/io_context.hpp>
Sunitha Harish29a82b02021-02-18 15:54:16 +053010#include <boost/asio/ip/address.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080011#include <boost/asio/ip/address_v4.hpp>
12#include <boost/asio/ip/address_v6.hpp>
Carson Labrado7e8890c2022-11-23 23:58:01 +000013#include <boost/asio/ip/tcp.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080014#include <boost/system/errc.hpp>
Sunitha Harish29a82b02021-02-18 15:54:16 +053015
16#include <charconv>
Ed Tanousd7857202025-01-28 15:32:26 -080017#include <cstdint>
18#include <string>
19#include <string_view>
20#include <system_error>
21#include <tuple>
22#include <vector>
Sunitha Harish29a82b02021-02-18 15:54:16 +053023
Sunitha Harish29a82b02021-02-18 15:54:16 +053024namespace async_resolve
25{
26
Ed Tanouse1452be2021-10-04 17:03:52 -070027inline bool endpointFromResolveTuple(const std::vector<uint8_t>& ipAddress,
28 boost::asio::ip::tcp::endpoint& endpoint)
29{
30 if (ipAddress.size() == 4) // ipv4 address
31 {
Ed Tanous62598e32023-07-17 17:06:25 -070032 BMCWEB_LOG_DEBUG("ipv4 address");
Ed Tanouse1452be2021-10-04 17:03:52 -070033 boost::asio::ip::address_v4 ipv4Addr(
34 {ipAddress[0], ipAddress[1], ipAddress[2], ipAddress[3]});
35 endpoint.address(ipv4Addr);
36 }
37 else if (ipAddress.size() == 16) // ipv6 address
38 {
Ed Tanous62598e32023-07-17 17:06:25 -070039 BMCWEB_LOG_DEBUG("ipv6 address");
Ed Tanouse1452be2021-10-04 17:03:52 -070040 boost::asio::ip::address_v6 ipv6Addr(
41 {ipAddress[0], ipAddress[1], ipAddress[2], ipAddress[3],
42 ipAddress[4], ipAddress[5], ipAddress[6], ipAddress[7],
43 ipAddress[8], ipAddress[9], ipAddress[10], ipAddress[11],
44 ipAddress[12], ipAddress[13], ipAddress[14], ipAddress[15]});
45 endpoint.address(ipv6Addr);
46 }
47 else
48 {
Ed Tanous62598e32023-07-17 17:06:25 -070049 BMCWEB_LOG_ERROR("Resolve failed to fetch the IP address");
Ed Tanouse1452be2021-10-04 17:03:52 -070050 return false;
51 }
52 return true;
53}
54
Sunitha Harish29a82b02021-02-18 15:54:16 +053055class Resolver
56{
57 public:
Ed Tanousf8ca6d72022-06-28 12:12:03 -070058 // unused io param used to keep interface identical to
59 // boost::asio::tcp:::resolver
60 explicit Resolver(boost::asio::io_context& /*io*/) {}
Sunitha Harish29a82b02021-02-18 15:54:16 +053061
62 ~Resolver() = default;
63
Ed Tanousecd6a3a2022-01-07 09:18:40 -080064 Resolver(const Resolver&) = delete;
65 Resolver(Resolver&&) = delete;
66 Resolver& operator=(const Resolver&) = delete;
67 Resolver& operator=(Resolver&&) = delete;
68
Ed Tanousf8ca6d72022-06-28 12:12:03 -070069 using results_type = std::vector<boost::asio::ip::tcp::endpoint>;
70
Sunitha Harish29a82b02021-02-18 15:54:16 +053071 template <typename ResolveHandler>
Ed Tanousf8ca6d72022-06-28 12:12:03 -070072 // This function is kept using snake case so that it is interoperable with
73 // boost::asio::ip::tcp::resolver
74 // NOLINTNEXTLINE(readability-identifier-naming)
Ed Tanousa716aa72023-08-01 11:35:53 -070075 void async_resolve(std::string_view host, std::string_view port,
Ed Tanousf8ca6d72022-06-28 12:12:03 -070076 ResolveHandler&& handler)
Sunitha Harish29a82b02021-02-18 15:54:16 +053077 {
Ed Tanous62598e32023-07-17 17:06:25 -070078 BMCWEB_LOG_DEBUG("Trying to resolve: {}:{}", host, port);
Ed Tanousf8ca6d72022-06-28 12:12:03 -070079
80 uint16_t portNum = 0;
81
82 auto it = std::from_chars(&*port.begin(), &*port.end(), portNum);
83 if (it.ec != std::errc())
84 {
Ed Tanous62598e32023-07-17 17:06:25 -070085 BMCWEB_LOG_ERROR("Failed to get the Port");
Ed Tanousf8ca6d72022-06-28 12:12:03 -070086 handler(std::make_error_code(std::errc::invalid_argument),
87 results_type{});
88
89 return;
90 }
91
Sunitha Harish29a82b02021-02-18 15:54:16 +053092 uint64_t flag = 0;
93 crow::connections::systemBus->async_method_call(
Ed Tanousa716aa72023-08-01 11:35:53 -070094 [host{std::string(host)}, portNum,
Ed Tanous8cb2c022024-03-27 16:31:46 -070095 handler = std::forward<ResolveHandler>(handler)](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -080096 const boost::system::error_code& ec,
Sunitha Harish29a82b02021-02-18 15:54:16 +053097 const std::vector<
98 std::tuple<int32_t, int32_t, std::vector<uint8_t>>>& resp,
99 const std::string& hostName, const uint64_t flagNum) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400100 results_type endpointList;
101 if (ec)
Ed Tanouse1452be2021-10-04 17:03:52 -0700102 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400103 BMCWEB_LOG_ERROR("Resolve failed: {}", ec.message());
104 handler(ec, endpointList);
105 return;
Ed Tanouse1452be2021-10-04 17:03:52 -0700106 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400107 BMCWEB_LOG_DEBUG("ResolveHostname returned: {}:{}", hostName,
108 flagNum);
109 // Extract the IP address from the response
110 for (const std::tuple<int32_t, int32_t, std::vector<uint8_t>>&
111 resolveList : resp)
112 {
113 boost::asio::ip::tcp::endpoint endpoint;
114 endpoint.port(portNum);
115 if (!endpointFromResolveTuple(std::get<2>(resolveList),
116 endpoint))
117 {
118 boost::system::error_code ecErr = make_error_code(
119 boost::system::errc::address_not_available);
120 handler(ecErr, endpointList);
121 }
122 BMCWEB_LOG_DEBUG("resolved endpoint is : {}",
123 endpoint.address().to_string());
124 endpointList.push_back(endpoint);
125 }
126 // All the resolved data is filled in the endpointList
127 handler(ec, endpointList);
128 },
Sunitha Harish29a82b02021-02-18 15:54:16 +0530129 "org.freedesktop.resolve1", "/org/freedesktop/resolve1",
130 "org.freedesktop.resolve1.Manager", "ResolveHostname", 0, host,
131 AF_UNSPEC, flag);
132 }
133};
134
135} // namespace async_resolve