blob: 7aa4cba45fcbedb1086482a0bfdcee821be05c81 [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;
27using namespace sdbusplus::xyz::openbmc_project::Common::Error;
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
38std::optional<std::pair<std::string, uint32_t>> parseConfig(std::istream& ss)
39{
40 std::string line;
41 std::getline(ss, line);
42
43 //"*.* @@<address>:<port>" or
44 //"*.* @@[<ipv6-address>:<port>"
45 constexpr auto start = 6; // Skip "*.* @@"
46 std::string serverAddress;
47 std::string serverPort;
48
49 // Ignore if line is commented
50 if (!line.empty() && '#' != line.at(0))
51 {
52 // Check if there is "[]", and make IPv6 address from it
53 auto posColonLeft = line.find('[');
54 auto posColonRight = line.find(']');
55 if (posColonLeft != std::string::npos ||
56 posColonRight != std::string::npos)
57 {
58 // It contains [ or ], so it should be an IPv6 address
59 if (posColonLeft == std::string::npos ||
60 posColonRight == std::string::npos)
61 {
62 // There either '[' or ']', invalid config
63 return {};
64 }
65 if (line.size() < posColonRight + 2 ||
66 line.at(posColonRight + 1) != ':')
67 {
68 // There is no ':', or no more content after ':', invalid config
69 return {};
70 }
Patrick Williams2544b412022-10-04 08:41:06 -050071 serverAddress = line.substr(posColonLeft + 1,
72 posColonRight - posColonLeft - 1);
Lei YUa1c43382021-04-15 20:26:25 +080073 serverPort = line.substr(posColonRight + 2);
74 }
75 else
76 {
77 auto pos = line.find(':');
78 if (pos == std::string::npos)
79 {
80 // There is no ':', invalid config
81 return {};
82 }
83 serverAddress = line.substr(start, pos - start);
84 serverPort = line.substr(pos + 1);
85 }
86 }
87 if (serverAddress.empty() || serverPort.empty())
88 {
89 return {};
90 }
91 try
92 {
93 uint32_t port = std::stoul(serverPort);
94 return std::make_pair(std::move(serverAddress), port);
95 }
96 catch (const std::exception& ex)
97 {
98 log<level::ERR>("Invalid config", entry("ERR=%s", ex.what()));
99 return {};
100 }
101}
102
103} // namespace internal
104
Deepak Kodihallic4966192018-08-23 02:19:58 -0500105std::string Server::address(std::string value)
106{
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500107 using Argument = xyz::openbmc_project::Common::InvalidArgument;
Patrick Venturef18bf832018-10-26 18:14:00 -0700108 std::string result{};
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500109
110 try
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500111 {
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500112 auto serverAddress = address();
113 if (serverAddress == value)
114 {
115 return serverAddress;
116 }
117
118 if (!value.empty() && !addressValid(value))
119 {
120 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Address"),
121 Argument::ARGUMENT_VALUE(value.c_str()));
122 }
123
124 writeConfig(value, port(), configFilePath.c_str());
Patrick Williams511a4752021-08-28 15:23:26 -0500125 result = NetworkClient::address(value);
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500126 }
127 catch (const InvalidArgument& e)
128 {
129 throw;
130 }
131 catch (const InternalFailure& e)
132 {
133 throw;
134 }
135 catch (const std::exception& e)
136 {
137 log<level::ERR>(e.what());
138 elog<InternalFailure>();
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500139 }
140
Deepak Kodihallic4966192018-08-23 02:19:58 -0500141 return result;
142}
143
144uint16_t Server::port(uint16_t value)
145{
Patrick Venturef18bf832018-10-26 18:14:00 -0700146 uint16_t result{};
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500147
148 try
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500149 {
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500150 auto serverPort = port();
151 if (serverPort == value)
152 {
153 return serverPort;
154 }
155
156 writeConfig(address(), value, configFilePath.c_str());
157 result = NetworkClient::port(value);
158 }
159 catch (const InternalFailure& e)
160 {
161 throw;
162 }
163 catch (const std::exception& e)
164 {
165 log<level::ERR>(e.what());
166 elog<InternalFailure>();
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500167 }
168
Deepak Kodihallic4966192018-08-23 02:19:58 -0500169 return result;
170}
171
Patrick Venturef18bf832018-10-26 18:14:00 -0700172void Server::writeConfig(const std::string& serverAddress, uint16_t serverPort,
173 const char* filePath)
Deepak Kodihallic4966192018-08-23 02:19:58 -0500174{
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500175 std::fstream stream(filePath, std::fstream::out);
176
Deepak Kodihallic4966192018-08-23 02:19:58 -0500177 if (serverPort && !serverAddress.empty())
178 {
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500179 // write '*.* @@<remote-host>:<port>'
Lei YUa1c43382021-04-15 20:26:25 +0800180 if (internal::isIPv6Address(serverAddress))
181 {
182 stream << "*.* @@[" << serverAddress << "]:" << serverPort;
183 }
184 else
185 {
186 stream << "*.* @@" << serverAddress << ":" << serverPort;
187 }
Deepak Kodihallic4966192018-08-23 02:19:58 -0500188 }
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500189 else // this is a disable request
190 {
Paul Fertser445665a2022-03-17 14:45:42 +0000191 // dummy action to avoid error 2103 on startup
192 stream << "*.* /dev/null";
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500193 }
194
Paul Fertser445665a2022-03-17 14:45:42 +0000195 stream << std::endl;
196
Deepak Kodihalli2ce7b2c2018-08-31 04:22:55 -0500197 restart();
Deepak Kodihallic4966192018-08-23 02:19:58 -0500198}
199
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500200bool Server::addressValid(const std::string& address)
201{
202 addrinfo hints{};
203 addrinfo* res = nullptr;
204 hints.ai_family = AF_UNSPEC;
205 hints.ai_socktype = SOCK_STREAM;
206 hints.ai_flags |= AI_CANONNAME;
207
208 auto result = getaddrinfo(address.c_str(), nullptr, &hints, &res);
209 if (result)
210 {
Patrick Venturef18bf832018-10-26 18:14:00 -0700211 log<level::ERR>("bad address", entry("ADDRESS=%s", address.c_str()),
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500212 entry("ERRNO=%d", result));
213 return false;
214 }
Patrick Williamsa40c2162021-04-22 09:11:10 -0500215
216 freeaddrinfo(res);
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500217 return true;
218}
219
Deepak Kodihalli9fab2792018-08-28 07:47:11 -0500220void Server::restore(const char* filePath)
221{
222 std::fstream stream(filePath, std::fstream::in);
Deepak Kodihalli9fab2792018-08-28 07:47:11 -0500223
Lei YUa1c43382021-04-15 20:26:25 +0800224 auto ret = internal::parseConfig(stream);
225 if (ret)
Deepak Kodihalli9fab2792018-08-28 07:47:11 -0500226 {
Lei YUa1c43382021-04-15 20:26:25 +0800227 NetworkClient::address(ret->first);
228 NetworkClient::port(ret->second);
Deepak Kodihalli9fab2792018-08-28 07:47:11 -0500229 }
230}
231
Deepak Kodihalli2ce7b2c2018-08-31 04:22:55 -0500232void Server::restart()
233{
234 utils::restart();
235}
236
Deepak Kodihallic4966192018-08-23 02:19:58 -0500237} // namespace rsyslog_config
238} // namespace phosphor