blob: f2a7aa8ac2b731e3c8b8de5f4a6eb38e7596c461 [file] [log] [blame]
Deepak Kodihallic4966192018-08-23 02:19:58 -05001#include "server-conf.hpp"
Patrick Venturef18bf832018-10-26 18:14:00 -07002
Deepak Kodihallic4966192018-08-23 02:19:58 -05003#include "utils.hpp"
Deepak Kodihalli4db81462018-08-27 06:01:46 -05004#include "xyz/openbmc_project/Common/error.hpp"
Patrick Venturef18bf832018-10-26 18:14:00 -07005
Deepak Kodihalli4db81462018-08-27 06:01:46 -05006#include <phosphor-logging/elog.hpp>
Patrick Williams2544b412022-10-04 08:41:06 -05007
8#include <fstream>
Deepak Kodihalli4db81462018-08-27 06:01:46 -05009#if __has_include("../../usr/include/phosphor-logging/elog-errors.hpp")
10#include "../../usr/include/phosphor-logging/elog-errors.hpp"
11#else
12#include <phosphor-logging/elog-errors.hpp>
13#endif
Deepak Kodihalli4db81462018-08-27 06:01:46 -050014#include <arpa/inet.h>
Patrick Venturef18bf832018-10-26 18:14:00 -070015#include <netdb.h>
Deepak Kodihallic4966192018-08-23 02:19:58 -050016
Lei YUa1c43382021-04-15 20:26:25 +080017#include <optional>
Patrick Venture30047bf2018-11-01 18:52:15 -070018#include <string>
19
Deepak Kodihallic4966192018-08-23 02:19:58 -050020namespace phosphor
21{
22namespace rsyslog_config
23{
24
25namespace utils = phosphor::rsyslog_utils;
Deepak Kodihalli4db81462018-08-27 06:01:46 -050026using namespace phosphor::logging;
Willy Tu6ddbf692023-09-05 10:54:16 -070027using namespace sdbusplus::error::xyz::openbmc_project::common;
Deepak Kodihallic4966192018-08-23 02:19:58 -050028
Lei YUa1c43382021-04-15 20:26:25 +080029namespace internal
30{
31
32bool isIPv6Address(const std::string& addr)
33{
34 struct in6_addr result;
35 return inet_pton(AF_INET6, addr.c_str(), &result) == 1;
36}
37
Ivan Mikhaylov22e86952023-06-09 17:54:03 +030038std::optional<
39 std::tuple<std::string, uint32_t, NetworkClient::TransportProtocol>>
40 parseConfig(std::istream& ss)
Lei YUa1c43382021-04-15 20:26:25 +080041{
42 std::string line;
43 std::getline(ss, line);
44
Lei YUa1c43382021-04-15 20:26:25 +080045 std::string serverAddress;
46 std::string serverPort;
Ivan Mikhaylov22e86952023-06-09 17:54:03 +030047 NetworkClient::TransportProtocol serverTransportProtocol =
48 NetworkClient::TransportProtocol::TCP;
Lei YUa1c43382021-04-15 20:26:25 +080049
50 // Ignore if line is commented
51 if (!line.empty() && '#' != line.at(0))
52 {
Ivan Mikhaylov22e86952023-06-09 17:54:03 +030053 //"*.* @@<address>:<port>" or
54 //"*.* @@[<ipv6-address>:<port>"
55 auto start = line.find('@');
56 if (start == std::string::npos)
57 return {};
58
59 // Skip "*.* @@" or "*.* @"
60 if (line.at(start + 1) == '@')
61 {
62 serverTransportProtocol = NetworkClient::TransportProtocol::TCP;
63 start += 2;
64 }
65 else
66 {
67 serverTransportProtocol = NetworkClient::TransportProtocol::UDP;
68 start++;
69 }
70
Lei YUa1c43382021-04-15 20:26:25 +080071 // Check if there is "[]", and make IPv6 address from it
72 auto posColonLeft = line.find('[');
73 auto posColonRight = line.find(']');
74 if (posColonLeft != std::string::npos ||
75 posColonRight != std::string::npos)
76 {
77 // It contains [ or ], so it should be an IPv6 address
78 if (posColonLeft == std::string::npos ||
79 posColonRight == std::string::npos)
80 {
81 // There either '[' or ']', invalid config
82 return {};
83 }
84 if (line.size() < posColonRight + 2 ||
85 line.at(posColonRight + 1) != ':')
86 {
87 // There is no ':', or no more content after ':', invalid config
88 return {};
89 }
Patrick Williams075c7922024-08-16 15:19:49 -040090 serverAddress =
91 line.substr(posColonLeft + 1, posColonRight - posColonLeft - 1);
Lei YUa1c43382021-04-15 20:26:25 +080092 serverPort = line.substr(posColonRight + 2);
93 }
94 else
95 {
96 auto pos = line.find(':');
97 if (pos == std::string::npos)
98 {
99 // There is no ':', invalid config
100 return {};
101 }
102 serverAddress = line.substr(start, pos - start);
103 serverPort = line.substr(pos + 1);
104 }
105 }
106 if (serverAddress.empty() || serverPort.empty())
107 {
108 return {};
109 }
110 try
111 {
Ivan Mikhaylov22e86952023-06-09 17:54:03 +0300112 return std::make_tuple(std::move(serverAddress), std::stoul(serverPort),
113 serverTransportProtocol);
Lei YUa1c43382021-04-15 20:26:25 +0800114 }
115 catch (const std::exception& ex)
116 {
117 log<level::ERR>("Invalid config", entry("ERR=%s", ex.what()));
118 return {};
119 }
120}
121
122} // namespace internal
123
Deepak Kodihallic4966192018-08-23 02:19:58 -0500124std::string Server::address(std::string value)
125{
Willy Tu6ddbf692023-09-05 10:54:16 -0700126 using Argument = xyz::openbmc_project::common::InvalidArgument;
Patrick Venturef18bf832018-10-26 18:14:00 -0700127 std::string result{};
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500128
129 try
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500130 {
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500131 auto serverAddress = address();
132 if (serverAddress == value)
133 {
134 return serverAddress;
135 }
136
137 if (!value.empty() && !addressValid(value))
138 {
139 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Address"),
140 Argument::ARGUMENT_VALUE(value.c_str()));
141 }
142
Ivan Mikhaylov22e86952023-06-09 17:54:03 +0300143 writeConfig(value, port(), transportProtocol(), configFilePath.c_str());
Patrick Williams511a4752021-08-28 15:23:26 -0500144 result = NetworkClient::address(value);
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500145 }
146 catch (const InvalidArgument& e)
147 {
148 throw;
149 }
150 catch (const InternalFailure& e)
151 {
152 throw;
153 }
154 catch (const std::exception& e)
155 {
156 log<level::ERR>(e.what());
157 elog<InternalFailure>();
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500158 }
159
Deepak Kodihallic4966192018-08-23 02:19:58 -0500160 return result;
161}
162
163uint16_t Server::port(uint16_t value)
164{
Patrick Venturef18bf832018-10-26 18:14:00 -0700165 uint16_t result{};
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500166
167 try
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500168 {
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500169 auto serverPort = port();
170 if (serverPort == value)
171 {
172 return serverPort;
173 }
174
Ivan Mikhaylov22e86952023-06-09 17:54:03 +0300175 writeConfig(address(), value, transportProtocol(),
176 configFilePath.c_str());
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500177 result = NetworkClient::port(value);
178 }
179 catch (const InternalFailure& e)
180 {
181 throw;
182 }
183 catch (const std::exception& e)
184 {
185 log<level::ERR>(e.what());
186 elog<InternalFailure>();
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500187 }
188
Deepak Kodihallic4966192018-08-23 02:19:58 -0500189 return result;
190}
191
Ivan Mikhaylov22e86952023-06-09 17:54:03 +0300192NetworkClient::TransportProtocol
193 Server::transportProtocol(NetworkClient::TransportProtocol value)
194{
195 TransportProtocol result{};
196
197 try
198 {
199 auto serverTransportProtocol = transportProtocol();
200 if (serverTransportProtocol == value)
201 {
202 return serverTransportProtocol;
203 }
204
205 writeConfig(address(), port(), value, configFilePath.c_str());
206 result = NetworkClient::transportProtocol(value);
207 }
208 catch (const InternalFailure& e)
209 {
210 throw;
211 }
212 catch (const std::exception& e)
213 {
214 log<level::ERR>(e.what());
215 elog<InternalFailure>();
216 }
217
218 return result;
219}
220
221void Server::writeConfig(
222 const std::string& serverAddress, uint16_t serverPort,
223 NetworkClient::TransportProtocol serverTransportProtocol,
224 const char* filePath)
Deepak Kodihallic4966192018-08-23 02:19:58 -0500225{
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500226 std::fstream stream(filePath, std::fstream::out);
227
Deepak Kodihallic4966192018-08-23 02:19:58 -0500228 if (serverPort && !serverAddress.empty())
229 {
Ivan Mikhaylov22e86952023-06-09 17:54:03 +0300230 std::string type =
231 (serverTransportProtocol == NetworkClient::TransportProtocol::UDP)
232 ? "@"
233 : "@@";
234 // write '*.* @@<remote-host>:<port>' or '*.* @<remote-host>:<port>'
Lei YUa1c43382021-04-15 20:26:25 +0800235 if (internal::isIPv6Address(serverAddress))
236 {
Ivan Mikhaylov22e86952023-06-09 17:54:03 +0300237 stream << "*.* " << type << "[" << serverAddress
238 << "]:" << serverPort;
Lei YUa1c43382021-04-15 20:26:25 +0800239 }
240 else
241 {
Ivan Mikhaylov22e86952023-06-09 17:54:03 +0300242 stream << "*.* " << type << serverAddress << ":" << serverPort;
Lei YUa1c43382021-04-15 20:26:25 +0800243 }
Deepak Kodihallic4966192018-08-23 02:19:58 -0500244 }
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500245 else // this is a disable request
246 {
Paul Fertser445665a2022-03-17 14:45:42 +0000247 // dummy action to avoid error 2103 on startup
248 stream << "*.* /dev/null";
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500249 }
250
Paul Fertser445665a2022-03-17 14:45:42 +0000251 stream << std::endl;
252
Deepak Kodihalli2ce7b2c2018-08-31 04:22:55 -0500253 restart();
Deepak Kodihallic4966192018-08-23 02:19:58 -0500254}
255
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500256bool Server::addressValid(const std::string& address)
257{
258 addrinfo hints{};
259 addrinfo* res = nullptr;
260 hints.ai_family = AF_UNSPEC;
261 hints.ai_socktype = SOCK_STREAM;
262 hints.ai_flags |= AI_CANONNAME;
263
264 auto result = getaddrinfo(address.c_str(), nullptr, &hints, &res);
265 if (result)
266 {
Patrick Venturef18bf832018-10-26 18:14:00 -0700267 log<level::ERR>("bad address", entry("ADDRESS=%s", address.c_str()),
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500268 entry("ERRNO=%d", result));
269 return false;
270 }
Patrick Williamsa40c2162021-04-22 09:11:10 -0500271
272 freeaddrinfo(res);
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500273 return true;
274}
275
Deepak Kodihalli9fab2792018-08-28 07:47:11 -0500276void Server::restore(const char* filePath)
277{
278 std::fstream stream(filePath, std::fstream::in);
Deepak Kodihalli9fab2792018-08-28 07:47:11 -0500279
Lei YUa1c43382021-04-15 20:26:25 +0800280 auto ret = internal::parseConfig(stream);
281 if (ret)
Deepak Kodihalli9fab2792018-08-28 07:47:11 -0500282 {
Ivan Mikhaylov22e86952023-06-09 17:54:03 +0300283 NetworkClient::address(std::get<0>(*ret));
284 NetworkClient::port(std::get<1>(*ret));
285 NetworkClient::transportProtocol(std::get<2>(*ret));
Deepak Kodihalli9fab2792018-08-28 07:47:11 -0500286 }
287}
288
Deepak Kodihalli2ce7b2c2018-08-31 04:22:55 -0500289void Server::restart()
290{
291 utils::restart();
292}
293
Deepak Kodihallic4966192018-08-23 02:19:58 -0500294} // namespace rsyslog_config
295} // namespace phosphor